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,82 @@
|
||||
"""Packet fixtures and stream boundaries independent of physical Bluetooth."""
|
||||
|
||||
import unittest
|
||||
|
||||
from controller.protocol import Decoder, Encoder
|
||||
|
||||
|
||||
class ProtocolTests(unittest.TestCase):
|
||||
def test_captured_mx_t40_connection_reply(self):
|
||||
raw = bytes.fromhex("00 bb 01 1d 00 0b 02 10 01 34 30 04 01 02 04 05 01 b0")
|
||||
frames = Decoder().feed(raw)
|
||||
self.assertEqual(len(frames), 1)
|
||||
self.assertEqual(frames[0].sequence, 0x1D)
|
||||
self.assertEqual(frames[0].payload, bytes.fromhex("02 10 01 34 30 04 01 02 04 05 01"))
|
||||
|
||||
def test_captured_ble_source_and_eq_replies(self):
|
||||
# These two consecutive hardware replies demonstrate both checksum
|
||||
# variants: source excludes type, EQ includes it.
|
||||
decoder = Decoder()
|
||||
frames = decoder.feed(
|
||||
bytes.fromhex("00 bb 01 6d 00 02 31 01 a1 00 bb 01 6e 00 04 41 03 02 00 b9")
|
||||
)
|
||||
self.assertEqual([frame.payload for frame in frames], [b"\x31\x01", b"\x41\x03\x02\x00"])
|
||||
|
||||
def test_captured_lighting_checksum_quirk(self):
|
||||
for raw, mode in [
|
||||
("00 bb 01 91 00 03 51 03 03 e9", 3),
|
||||
("00 bb 01 ab 00 03 51 03 05 03", 5),
|
||||
("00 bb 01 b0 00 03 51 03 06 08", 6),
|
||||
("00 bb 01 b1 00 03 51 03 01 09", 1),
|
||||
]:
|
||||
with self.subTest(raw=raw):
|
||||
frame = Decoder().feed(bytes.fromhex(raw))[0]
|
||||
self.assertEqual(frame.payload, bytes((0x51, 3, mode)))
|
||||
self.assertTrue(frame.checksum_valid)
|
||||
|
||||
def test_unknown_checksum_is_flagged_in_compatibility_mode(self):
|
||||
raw = bytes.fromhex("00 bb 01 91 00 03 51 03 03 20")
|
||||
self.assertEqual(Decoder().feed(raw), [])
|
||||
frame = Decoder(strict_checksums=False).feed(raw)[0]
|
||||
self.assertFalse(frame.checksum_valid)
|
||||
|
||||
def test_captured_play_pause_event_checksums(self):
|
||||
for raw in ("00 bb 01 cd 00 02 70 11 40", "00 bb 01 ce 00 02 70 11 41"):
|
||||
with self.subTest(raw=raw):
|
||||
frame = Decoder().feed(bytes.fromhex(raw))[0]
|
||||
self.assertEqual(frame.payload, b"\x70\x11")
|
||||
self.assertTrue(frame.checksum_valid)
|
||||
|
||||
def test_app_connection_fixture(self):
|
||||
self.assertEqual(Encoder().encode(b"\x01"), bytes.fromhex("00 bb 01 01 00 01 01 04"))
|
||||
|
||||
def test_signed_java_sequence_rollover(self):
|
||||
encoder = Encoder()
|
||||
for _ in range(127):
|
||||
encoder.encode(b"\x01")
|
||||
self.assertEqual(encoder.sequence, 127)
|
||||
self.assertEqual(encoder.encode(b"\x01")[3], 1)
|
||||
|
||||
def test_every_split_and_multiple_frames(self):
|
||||
# Peer replies use a different checksum rule than Encoder's commands.
|
||||
first = bytes.fromhex("00 bb 01 01 00 04 41 03 00 02 4b")
|
||||
second = bytes.fromhex("00 bb 01 02 00 03 51 03 01 5a")
|
||||
for split in range(len(first) + 1):
|
||||
decoder = Decoder()
|
||||
frames = decoder.feed(first[:split]) + decoder.feed(first[split:] + second)
|
||||
self.assertEqual([f.payload for f in frames], [b"\x41\x03\x00\x02", b"\x51\x03\x01"])
|
||||
|
||||
def test_corruption_and_noise_recovery(self):
|
||||
bad = bytearray.fromhex("00 bb 01 01 00 01 01 03")
|
||||
bad[-1] ^= 1
|
||||
good = bytes.fromhex("00 bb 01 02 00 01 04 07")
|
||||
frames = Decoder().feed(b"noise" + bad + good)
|
||||
self.assertEqual([f.payload for f in frames], [b"\x04"])
|
||||
|
||||
def test_empty_ack(self):
|
||||
frame = Decoder().feed(bytes.fromhex("00 bb 00 02 00 00 02"))[0]
|
||||
self.assertEqual((frame.kind, frame.sequence, frame.payload), (0, 2, b""))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user