From 6f06e7e58751ad0b4c7ef25c9bb2be1f0519801f Mon Sep 17 00:00:00 2001 From: Iori Mizutani Date: Thu, 8 Jun 2023 00:34:31 +0200 Subject: [PATCH] chore: add workflows and flake8 --- .github/workflows/build.yml | 47 ++++++++++++++++++++++++++++ .github/workflows/python-publish.yml | 37 ++++++++++------------ README.md | 17 ++++++++-- examples/driver.py | 4 ++- myo/__init__.py | 20 +++++++++--- myo/commands.py | 10 ++++-- myo/device.py | 20 ++++++------ pyproject.toml | 6 +++- 8 files changed, 119 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..97e5b1e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,47 @@ +name: Build +on: + release: + types: [published] +jobs: + build-wheel: + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + os: [macOS-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Lint + run: | + pip install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=examples,myo/handle.py + - name: Build + run: | + pip install hatch + python -m hatch build + - name: Upload wheel + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist + build-wheel-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build + run: | + pip install hatch + python -m hatch build + - name: Upload wheel + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index bdaab28..fde0131 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -7,33 +7,28 @@ # documentation. name: Upload Python Package - on: release: types: [published] - permissions: contents: read - jobs: deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.x" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/README.md b/README.md index b08661e..ad079c1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,19 @@ -# dl-myo +# dl-myo (Dongle-less Myo) -A replacement middleware to MyoConnect for Myo Armband without an official Myo dongle. +[![PyPI Version](https://badge.fury.io/py/dl-myo.svg)](https://badge.fury.io/py/dl-myo) +[![Build Status](https://github.com/iomz/dl-myo/workflows/Build/badge.svg)](https://github.com/iomz/dl-myo/actions?query=workflow%3ABuild) + +dl-myo is a replacement to MyoConnect for Myo Armband without an official Myo dongle. + +If you are fed up with the dongle and still need to use Myo anyway this is the right stuff to grab. + +This project is a reimplementation of [Dongleless-myo](https://github.com/iomz/Dongleless-myo) (originally created by [@mamo91] and enhanced by [@MyrikLD]) using [Bleak](https://github.com/hbldh/bleak) instead of [bluepy](https://github.com/IanHarvey/bluepy), and therefore supports asyncio on multiple platforms. + +## Platform Support + +| Linux | Raspberry Pi | macOS | Windows | +| :----------------: | :----------------: | :----------------: | :----------------: | +| :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | ## Install diff --git a/examples/driver.py b/examples/driver.py index 947397f..a0d7cb6 100644 --- a/examples/driver.py +++ b/examples/driver.py @@ -53,7 +53,9 @@ async def main(args: argparse.Namespace): await m.vibrate(client, VibrationType.MEDIUM) # enable emg and imu - await m.set_mode(client, EMGMode.SEND_EMG, IMUMode.SEND_ALL, ClassifierMode.DISABLED) + await m.set_mode( + client, EMGMode.SEND_EMG, IMUMode.SEND_ALL, ClassifierMode.DISABLED + ) logging.info("sleep 1") await asyncio.sleep(0.5) diff --git a/myo/__init__.py b/myo/__init__.py index f57d75e..b5e47c1 100644 --- a/myo/__init__.py +++ b/myo/__init__.py @@ -1,10 +1,20 @@ # -*- coding: utf-8 -*- """ -dl-myo: Dongleless Myo EMG/IMU with Bleak - -Author: Iori Mizutani (@iomz) - + Top-level package for dl-myo ~~~~~~~~~~~~~~~~~~~~ >>> import myo """ -from .device import * + +from __future__ import annotations + +__author__ = """Iori Mizutani""" +__email__ = "iori.mizutani@gmail.com" + +from pkgutil import extend_path + +__path__ = extend_path(__path__, __name__) + +from .commands import * # noqa: F401,F403 +from .device import * # noqa: F401,F403 +from .handle import * # noqa: F401,F403 +from .types import * # noqa: F401,F403 diff --git a/myo/commands.py b/myo/commands.py index f4d2447..875ac98 100644 --- a/myo/commands.py +++ b/myo/commands.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from .types import * +from .types import SleepMode, UnlockType, UserActionType # myohw_command_t @@ -86,7 +86,13 @@ def __init__(self, duration, strength): @property def payload(self) -> bytearray: - return bytearray((self.steps.duration >> 0xFF, self.steps.duration & 0xFF, self.steps.strength)) + return bytearray( + ( + self.steps.duration >> 0xFF, + self.steps.duration & 0xFF, + self.steps.strength, + ) + ) # -> myohw_command_set_sleep_mode_t diff --git a/myo/device.py b/myo/device.py index 502dd59..a653f6d 100644 --- a/myo/device.py +++ b/myo/device.py @@ -9,9 +9,9 @@ from bleak.backends.device import BLEDevice from bleak.backends.scanner import AdvertisementData -from .commands import * -from .handle import * -from .types import * +from .commands import Command, SetMode, Vibrate, DeepSleep, LED, Vibrate2, SetSleepMode, Unlock, UserAction +from .handle import Handle, UUID +from .types import FirmwareInfo, FirmwareVersion # from .quaternion import Quaternion @@ -46,8 +46,8 @@ def match_myo_mac(device: BLEDevice, _: AdvertisementData): if self.device is None: logger.error(f"could not find device with address {mac}") return self - except: - logger.error("the mac address may be invalid") + except Exception as e: + logger.error("the mac address may be invalid", e) return self # get the device name @@ -99,7 +99,7 @@ async def emg_service(self, client): """ await client.write_gatt_char(Handle.EMG_SERVICE.value, b"\x01\x00", True) # pyright: ignore - async def get_services(self, client: BleakClient, indent=2) -> str: + async def get_services(self, client: BleakClient, indent=2) -> str: # noqa: C901 """fetch available services as dict""" sd = {"services": {}} for service in client.services: # BleakGATTServiceCollection @@ -156,9 +156,9 @@ async def led(self, client: BleakClient, *args): if not isinstance(args, tuple) or len(args) != 2: raise Exception(f"Unknown payload for LEDs: {args}") - for l in args: - if any(not isinstance(v, int) for v in l): - raise Exception(f"Values must be int 0-255: {l}") + for lst in args: + if any(not isinstance(v, int) for v in lst): + raise Exception(f"Values must be int 0-255: {lst}") await self.command(client, LED(args[0], args[1])) @@ -197,4 +197,4 @@ async def vibrate2(self, client: BleakClient, duration, strength): """ Vibrate2 Command """ - await self.command(client, Vibrate2(duration, strength)) \ No newline at end of file + await self.command(client, Vibrate2(duration, strength)) diff --git a/pyproject.toml b/pyproject.toml index d6d333e..202c8fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,12 +8,16 @@ version = "0.1.0" authors = [ { name="Iori Mizutani", email="iori.mizutani@gmail.com" }, ] -Maintainers = [ +maintainers = [ { name="Iori Mizutani", email="iori.mizutani@gmail.com" }, ] description = "A replacement middleware to MyoConnect for Myo Armband" readme = "README.md" requires-python = ">=3.11" +dependencies = [ + "aenum", + "bleak", +] classifiers = [ "Framework :: AsyncIO", "Intended Audience :: Education",