Add MX-T40 BLE desktop controller and protocol documentation
Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
This commit is contained in:
38 files changed
+2344
No files matched your search
@@ -0,0 +1,95 @@
|
||||
"""Replay the captured reply through asynchronous FFA1/FFA2 operations."""
|
||||
|
||||
import queue
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from controller.ble_link import NOTIFY, SERVICE, WRITE, BLELink
|
||||
|
||||
|
||||
class BLELinkTests(unittest.TestCase):
|
||||
def run_peer(self, write_error=False):
|
||||
operations = []
|
||||
closed = []
|
||||
write = types.SimpleNamespace(uuid=WRITE, properties=["write"])
|
||||
notify = types.SimpleNamespace(uuid=NOTIFY, properties=["notify"])
|
||||
service = types.SimpleNamespace(
|
||||
get_characteristic=lambda uuid: {WRITE: write, NOTIFY: notify}.get(uuid)
|
||||
)
|
||||
|
||||
class Events(queue.Queue):
|
||||
def put(self, event, *args, **kwargs):
|
||||
super().put(event, *args, **kwargs)
|
||||
if event[0] == "ready":
|
||||
link.stop()
|
||||
|
||||
events = Events()
|
||||
link = BLELink("12:34:56:78:9A:BC", events)
|
||||
|
||||
class Peer:
|
||||
services = types.SimpleNamespace(
|
||||
get_service=lambda uuid: service if uuid == SERVICE else None
|
||||
)
|
||||
is_connected = True
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
closed.append(True)
|
||||
|
||||
async def start_notify(self, characteristic, callback):
|
||||
operations.append(("subscribe", characteristic.uuid))
|
||||
self.callback = callback
|
||||
|
||||
async def write_gatt_char(self, characteristic, data, response):
|
||||
operations.append(("write", characteristic.uuid, data, response))
|
||||
if write_error:
|
||||
raise OSError("GATT write failed")
|
||||
if data[6:-1] == b"\x01":
|
||||
self.callback(notify, bytes.fromhex("00 bb 00 01 00 00 01"))
|
||||
reply = bytes.fromhex("00 bb 01 1d 00 0b 02 10 01 34 30 04 01 02 04 05 01 b0")
|
||||
self.callback(notify, reply[:8])
|
||||
self.callback(notify, reply[8:])
|
||||
elif data[6:-1] == b"\x04":
|
||||
self.callback(notify, bytes.fromhex("00 bb 00 02 00 00 02"))
|
||||
|
||||
scanner = types.SimpleNamespace(find_device_by_address=AsyncMock(return_value=object()))
|
||||
with patch.dict(
|
||||
sys.modules,
|
||||
{
|
||||
"bleak": types.SimpleNamespace(
|
||||
BleakScanner=scanner, BleakClient=lambda *a, **k: Peer()
|
||||
)
|
||||
},
|
||||
):
|
||||
link.run()
|
||||
return operations, list(events.queue), closed
|
||||
|
||||
def test_subscribe_before_handshake_and_reassemble_notifications(self):
|
||||
operations, events, closed = self.run_peer()
|
||||
self.assertEqual(operations[0], ("subscribe", NOTIFY))
|
||||
writes = operations[1:]
|
||||
self.assertEqual([op[1] for op in writes], [WRITE, WRITE])
|
||||
self.assertEqual(
|
||||
[op[2] for op in writes],
|
||||
[
|
||||
bytes.fromhex("00 bb 01 01 00 01 01 04"),
|
||||
bytes.fromhex("00 bb 01 02 00 01 04 08"),
|
||||
],
|
||||
)
|
||||
self.assertTrue(all(op[3] is True for op in writes))
|
||||
self.assertEqual(sum(kind == "ready" for kind, _ in events), 1)
|
||||
self.assertFalse(any(kind == "error" for kind, _ in events))
|
||||
self.assertEqual(closed, [True])
|
||||
|
||||
def test_write_error_disconnects_without_enabling_controls(self):
|
||||
_, events, closed = self.run_peer(write_error=True)
|
||||
self.assertFalse(any(kind == "ready" for kind, _ in events))
|
||||
self.assertTrue(
|
||||
any(kind == "error" and "GATT write failed" in value for kind, value in events)
|
||||
)
|
||||
self.assertEqual(events[-1], ("closed", None))
|
||||
self.assertEqual(closed, [True])
|
||||
Reference in new issue
Block a user