[WIP] PoC for CLI event handling (not compatible with textual)
This commit is contained in:
parent
754afed50b
commit
f9505c2cde
|
@ -1,24 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import click
|
||||
|
||||
from ..tools.ble import scanner, monitor
|
||||
from ..tools import context
|
||||
from ..tools.ble import monitor, scanner
|
||||
|
||||
|
||||
@click.command(name="scan")
|
||||
def scanner_cmd():
|
||||
def scanner_cmd() -> None:
|
||||
scanner.run()
|
||||
|
||||
|
||||
@click.command(name="monitor")
|
||||
def monitor_cmd():
|
||||
def monitor_cmd() -> None:
|
||||
monitor.run()
|
||||
|
||||
|
||||
@click.group()
|
||||
def main():
|
||||
@click.command(name="tui")
|
||||
def tui_cmd() -> None:
|
||||
pass
|
||||
|
||||
|
||||
@click.group()
|
||||
def main() -> None:
|
||||
context.set_environment(context.BlattedEnvironment.CLI)
|
||||
|
||||
|
||||
main.add_command(scanner_cmd)
|
||||
main.add_command(monitor_cmd)
|
||||
main.add_command(tui_cmd)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
from .event import DeviceDiscovered
|
||||
|
||||
__all__ = ["DeviceDiscovered"]
|
|
@ -0,0 +1,16 @@
|
|||
from textual.message import Message
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
|
||||
|
||||
class DeviceDiscovered(Message):
|
||||
def __init__(self, device: BLEDevice, adverisement_data: AdvertisementData) -> None:
|
||||
self.device = device
|
||||
self.adverisement_data = adverisement_data
|
||||
super().__init__()
|
||||
|
||||
def has_services(self) -> bool:
|
||||
return len(self.advertising_data.service_uuids) > 0
|
||||
|
||||
def repr(self) -> str:
|
||||
return f"{self.device.address} - {self.device.name}"
|
|
@ -15,7 +15,7 @@ class DiscoveredDevices:
|
|||
devices: list[DiscoveredDevice] = field(default_factory=list)
|
||||
|
||||
def add(self, device: DiscoveredDevice):
|
||||
if not device in self.devices:
|
||||
if device not in self.devices:
|
||||
self.devices.append(device)
|
||||
|
||||
def count(self):
|
||||
|
|
|
@ -7,7 +7,7 @@ from icecream import ic
|
|||
|
||||
|
||||
async def monitor_services(filter: list[str] = []):
|
||||
await asyncio.sleep(.1)
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
|
||||
def run(uuid_filter: list[str] = []):
|
||||
|
|
|
@ -1,31 +1,55 @@
|
|||
import asyncio
|
||||
from typing import Dict, Any
|
||||
|
||||
import bleak.exc
|
||||
from bleak import BleakScanner
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
from pydispatch import Dispatcher
|
||||
|
||||
from .models import DiscoveredDevice
|
||||
from ...events.event import DeviceDiscovered
|
||||
from ...tools import context
|
||||
|
||||
|
||||
def discover_callback(device: BLEDevice, advertising_data: AdvertisementData):
|
||||
if len(advertising_data.service_uuids) > 0:
|
||||
discovered = DiscoveredDevice(device, advertising_data)
|
||||
print(
|
||||
f"[{advertising_data.rssi:-4d}] {device.address} - {device.name} [{discovered}]"
|
||||
)
|
||||
class Scanner(Dispatcher):
|
||||
_events_ = ["device_discovered"]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.environment = context.get_environment()
|
||||
self.devices: Dict[str, Any] = {}
|
||||
self.bind(device_discovered=self.on_device_discovered)
|
||||
|
||||
async def discover_devices():
|
||||
stop_event = asyncio.Event()
|
||||
def discover_callback(
|
||||
self, device: BLEDevice, advertising_data: AdvertisementData
|
||||
) -> None:
|
||||
if len(advertising_data.service_uuids) > 0:
|
||||
#discovered = DiscoveredDevice(device, advertising_data)
|
||||
discovered = DeviceDiscovered(device, advertising_data)
|
||||
if context.get_environment() == context.BlattedEnvironment.CLI:
|
||||
self.emit("device_discovered", data=discovered)
|
||||
elif context.get_environment() == context.BlattedEnvironment.TUI:
|
||||
pass # TODO Implement
|
||||
|
||||
async with BleakScanner(discover_callback):
|
||||
await stop_event.wait()
|
||||
def on_device_discovered(self, data: DeviceDiscovered) -> None:
|
||||
if data.device.address not in self.devices:
|
||||
print(f"new device discovered: {data.device}")
|
||||
self.devices[data.device.address] = {"data": data, "seen": 1}
|
||||
else:
|
||||
self.devices[data.device.address]["seen"] += 1
|
||||
print(
|
||||
f"device seen {self.devices[data.device.address]['seen']} times: {data.device}"
|
||||
)
|
||||
|
||||
async def run(self) -> None:
|
||||
stop_event = asyncio.Event()
|
||||
|
||||
async with BleakScanner(self.discover_callback):
|
||||
await stop_event.wait()
|
||||
|
||||
|
||||
def run():
|
||||
print("scanner called")
|
||||
try:
|
||||
asyncio.run(discover_devices())
|
||||
asyncio.run(Scanner().run())
|
||||
except bleak.exc.BleakDBusError as exc:
|
||||
print(f"ERROR: {exc}")
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
from contextvars import ContextVar
|
||||
from enum import Enum
|
||||
|
||||
|
||||
blatted_environment_var: ContextVar = ContextVar("blatted_environment")
|
||||
|
||||
|
||||
class BlattedEnvironment(Enum):
|
||||
CLI = "console line interface"
|
||||
TUI = "terminal user interface"
|
||||
|
||||
|
||||
def set_environment(mode: BlattedEnvironment) -> None:
|
||||
blatted_environment_var.set(mode)
|
||||
|
||||
|
||||
def get_environment() -> BlattedEnvironment:
|
||||
return blatted_environment_var.get()
|
|
@ -238,6 +238,47 @@ files = [
|
|||
[package.extras]
|
||||
license = ["ukkonen"]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "6.6.0"
|
||||
description = "Read metadata from Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
|
||||
{file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
zipp = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
perf = ["ipython"]
|
||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "linkify-it-py"
|
||||
version = "2.0.2"
|
||||
description = "Links recognition library with FULL unicode support."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "linkify-it-py-2.0.2.tar.gz", hash = "sha256:19f3060727842c254c808e99d465c80c49d2c7306788140987a1a7a29b0d6ad2"},
|
||||
{file = "linkify_it_py-2.0.2-py3-none-any.whl", hash = "sha256:a3a24428f6c96f27370d7fe61d2ac0be09017be5190d68d8658233171f1b6541"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
uc-micro-py = "*"
|
||||
|
||||
[package.extras]
|
||||
benchmark = ["pytest", "pytest-benchmark"]
|
||||
dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"]
|
||||
doc = ["myst-parser", "sphinx", "sphinx-book-theme"]
|
||||
test = ["coverage", "pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "2.2.0"
|
||||
|
@ -251,6 +292,8 @@ files = [
|
|||
]
|
||||
|
||||
[package.dependencies]
|
||||
linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""}
|
||||
mdit-py-plugins = {version = "*", optional = true, markers = "extra == \"plugins\""}
|
||||
mdurl = ">=0.1,<1.0"
|
||||
|
||||
[package.extras]
|
||||
|
@ -263,6 +306,26 @@ profiling = ["gprof2dot"]
|
|||
rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
||||
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||
|
||||
[[package]]
|
||||
name = "mdit-py-plugins"
|
||||
version = "0.3.5"
|
||||
description = "Collection of plugins for markdown-it-py"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"},
|
||||
{file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
markdown-it-py = ">=1.0.0,<3.0.0"
|
||||
|
||||
[package.extras]
|
||||
code-style = ["pre-commit"]
|
||||
rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"]
|
||||
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.2"
|
||||
|
@ -415,6 +478,18 @@ files = [
|
|||
[package.dependencies]
|
||||
pyobjc-core = ">=9.1.1"
|
||||
|
||||
[[package]]
|
||||
name = "python-dispatch"
|
||||
version = "0.2.1"
|
||||
description = "Lightweight Event Handling"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "python-dispatch-0.2.1.tar.gz", hash = "sha256:ca166addfdedd11fef80a004b930503b30c5c2a6f23cec0395986fd7cc8a5f1c"},
|
||||
{file = "python_dispatch-0.2.1-py3-none-any.whl", hash = "sha256:43fb413a87404b212281bfc5733ef23d4b4ed3b7452faddb3c82517ea58634f1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0"
|
||||
|
@ -513,6 +588,54 @@ files = [
|
|||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textual"
|
||||
version = "0.25.0"
|
||||
description = "Modern Text User Interface framework"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
files = [
|
||||
{file = "textual-0.25.0-py3-none-any.whl", hash = "sha256:8258499a09793696e13a1d1e1391810916828015a91770abd7ce3d9ab64cfd9e"},
|
||||
{file = "textual-0.25.0.tar.gz", hash = "sha256:5e2d6320026dd8ff86e0d023fc4988071e80ec2e34de913bd63263a8301d664b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
importlib-metadata = ">=4.11.3"
|
||||
markdown-it-py = {version = ">=2.1.0,<3.0.0", extras = ["linkify", "plugins"]}
|
||||
rich = ">=13.3.3"
|
||||
typing-extensions = ">=4.4.0,<5.0.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["aiohttp (>=3.8.1)", "click (>=8.1.2)", "msgpack (>=1.0.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.5.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
|
||||
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uc-micro-py"
|
||||
version = "1.0.2"
|
||||
description = "Micro subset of unicode data files for linkify-it-py projects."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "uc-micro-py-1.0.2.tar.gz", hash = "sha256:30ae2ac9c49f39ac6dce743bd187fcd2b574b16ca095fa74cd9396795c954c54"},
|
||||
{file = "uc_micro_py-1.0.2-py3-none-any.whl", hash = "sha256:8c9110c309db9d9e87302e2f4ad2c3152770930d88ab385cd544e7a7e75f3de0"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["coverage", "pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.23.0"
|
||||
|
@ -534,7 +657,23 @@ platformdirs = ">=3.2,<4"
|
|||
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
|
||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.15.0"
|
||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
|
||||
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "1a257f20c24d028b39114e970d7e3156f4cac3daeae8e443f1381b168c7eeca5"
|
||||
content-hash = "a8b87d0f21a27962db7d2999e0e30657c5ee0705abe98325a0a65466421d1349"
|
||||
|
|
|
@ -10,6 +10,8 @@ python = "^3.10"
|
|||
bleak = "^0.20.2"
|
||||
click = "^8.1.3"
|
||||
rich = "^13.3.5"
|
||||
textual = "^0.25.0"
|
||||
python-dispatch = "^0.2.1"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
blatted = "blatted.cli:main"
|
||||
|
|
Loading…
Reference in New Issue