Skip to content

Commit f415459

Browse files
committed
ble.lwp3: add virtual port commands
1 parent 4ae4a78 commit f415459

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

pybricksdev/ble/lwp3/bytecodes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,3 +995,8 @@ class DataFormat(IntEnum):
995995

996996
DATAF = 0x03
997997
"""32-bit floating point, little-endian."""
998+
999+
1000+
class VirtualPortSetupCommand(IntEnum):
1001+
DISCONNECT = 0x00
1002+
CONNECT = 0x01

pybricksdev/ble/lwp3/messages.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
PortID,
4646
PortInfoFormatSetupCommand,
4747
Version,
48+
VirtualPortSetupCommand,
4849
)
4950

5051

@@ -1314,6 +1315,56 @@ def __repr__(self) -> str:
13141315
return f"{self.__class__.__name__}({repr(self.port)}, {repr(self.combo)}, {repr(self.multi_update)}, {repr(self.modes_and_datasets)})"
13151316

13161317

1318+
###############################################################################
1319+
# Virtual port messages
1320+
###############################################################################
1321+
1322+
1323+
class AbstractVirtualPortSetupMessage(AbstractMessage):
1324+
@abc.abstractmethod
1325+
def __init__(self, length: int, command: VirtualPortSetupCommand) -> None:
1326+
super().__init__(length, MessageKind.VIRTUAL_PORT_SETUP)
1327+
1328+
self._data[3] = command
1329+
1330+
@property
1331+
def command(self) -> VirtualPortSetupCommand:
1332+
return VirtualPortSetupCommand(self._data[3])
1333+
1334+
1335+
class VirtualPortSetupDisconnectMessage(AbstractVirtualPortSetupMessage):
1336+
def __init__(self, port: PortID) -> None:
1337+
super().__init__(5, VirtualPortSetupCommand.DISCONNECT)
1338+
1339+
self._data[4] = port
1340+
1341+
@property
1342+
def port(self) -> PortID:
1343+
return PortID(self._data[4])
1344+
1345+
def __repr__(self) -> str:
1346+
return f"{self.__class__.__name__}({repr(self.port)})"
1347+
1348+
1349+
class VirtualPortSetupConnectMessage(AbstractVirtualPortSetupMessage):
1350+
def __init__(self, port_a: PortID, port_b: PortID) -> None:
1351+
super().__init__(6, VirtualPortSetupCommand.CONNECT)
1352+
1353+
self._data[4] = port_a
1354+
self._data[5] = port_b
1355+
1356+
@property
1357+
def port_a(self) -> PortID:
1358+
return PortID(self._data[4])
1359+
1360+
@property
1361+
def port_b(self) -> PortID:
1362+
return PortID(self._data[5])
1363+
1364+
def __repr__(self) -> str:
1365+
return f"{self.__class__.__name__}({repr(self.port_a)}, {repr(self.port_b)})"
1366+
1367+
13171368
###############################################################################
13181369
# Message parsing
13191370
###############################################################################
@@ -1399,6 +1450,11 @@ class _Lookup(NamedTuple):
13991450
ModeInfoKind.FORMAT: PortModeInfoFormatMessage,
14001451
}
14011452

1453+
_VIRTUAL_PORT_SETUP_CLASS_MAP = {
1454+
VirtualPortSetupCommand.DISCONNECT: VirtualPortSetupDisconnectMessage,
1455+
VirtualPortSetupCommand.CONNECT: VirtualPortSetupConnectMessage,
1456+
}
1457+
14021458
# base type descriminator for messages
14031459
_MESSAGE_CLASS_MAP = {
14041460
MessageKind.HUB_PROPERTY: _Lookup(4, _HUB_PROPERTY_OP_CLASS_MAP),
@@ -1420,6 +1476,7 @@ class _Lookup(NamedTuple):
14201476
MessageKind.PORT_VALUE_COMBO: PortValueComboMessage,
14211477
MessageKind.PORT_INPUT_FMT: PortInputFormatMessage,
14221478
MessageKind.PORT_INPUT_FMT_COMBO: PortInputFormatComboMessage,
1479+
MessageKind.VIRTUAL_PORT_SETUP: _Lookup(3, _VIRTUAL_PORT_SETUP_CLASS_MAP),
14231480
}
14241481

14251482

tests/ble/test_lwp3_messages.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
PortID,
2828
PortInfoFormatSetupCommand,
2929
Version,
30+
VirtualPortSetupCommand,
3031
)
3132
from pybricksdev.ble.lwp3.messages import (
3233
AbstractHubAlertMessage,
@@ -36,6 +37,7 @@
3637
AbstractMessage,
3738
AbstractPortInfoMessage,
3839
AbstractPortModeInfoMessage,
40+
AbstractVirtualPortSetupMessage,
3941
ErrorMessage,
4042
FirmwareUpdateMessage,
4143
HubActionMessage,
@@ -88,6 +90,8 @@
8890
PortModeInfoSymbolMessage,
8991
PortValueComboMessage,
9092
PortValueMessage,
93+
VirtualPortSetupConnectMessage,
94+
VirtualPortSetupDisconnectMessage,
9195
parse_message,
9296
)
9397

@@ -1292,3 +1296,48 @@ def test_parse_message(self):
12921296
assert msg.combo == 2
12931297
assert msg.multi_update is True
12941298
assert msg.modes_and_datasets == [0, 1]
1299+
1300+
1301+
class TestVirtualPortMessages:
1302+
class TestVirtualPortSetupMessages:
1303+
def test_is_abstract(self):
1304+
assert inspect.isabstract(AbstractVirtualPortSetupMessage)
1305+
1306+
class TestVirtualPortSetupDisconnectMessage:
1307+
def test_constructor(self):
1308+
msg = VirtualPortSetupDisconnectMessage(PortID(3))
1309+
assert msg.length == 5
1310+
assert msg.kind is MessageKind.VIRTUAL_PORT_SETUP
1311+
assert msg.command is VirtualPortSetupCommand.DISCONNECT
1312+
assert msg.port is PortID(3)
1313+
assert repr(msg) == "VirtualPortSetupDisconnectMessage(<PortID.3: 3>)"
1314+
1315+
def test_parse_message(self):
1316+
msg = parse_message(b"\x05\x00\x61\x00\x03")
1317+
assert isinstance(msg, VirtualPortSetupDisconnectMessage)
1318+
assert msg.length == 5
1319+
assert msg.kind is MessageKind.VIRTUAL_PORT_SETUP
1320+
assert msg.command is VirtualPortSetupCommand.DISCONNECT
1321+
assert msg.port is PortID(3)
1322+
1323+
class TestVirtualPortSetupConnectMessage:
1324+
def test_constructor(self):
1325+
msg = VirtualPortSetupConnectMessage(PortID(1), PortID(2))
1326+
assert msg.length == 6
1327+
assert msg.kind is MessageKind.VIRTUAL_PORT_SETUP
1328+
assert msg.command is VirtualPortSetupCommand.CONNECT
1329+
assert msg.port_a is PortID(1)
1330+
assert msg.port_b is PortID(2)
1331+
assert (
1332+
repr(msg)
1333+
== "VirtualPortSetupConnectMessage(<PortID.1: 1>, <PortID.2: 2>)"
1334+
)
1335+
1336+
def test_parse_message(self):
1337+
msg = parse_message(b"\x06\x00\x61\x01\x01\x02")
1338+
assert isinstance(msg, VirtualPortSetupConnectMessage)
1339+
assert msg.length == 6
1340+
assert msg.kind is MessageKind.VIRTUAL_PORT_SETUP
1341+
assert msg.command is VirtualPortSetupCommand.CONNECT
1342+
assert msg.port_a is PortID(1)
1343+
assert msg.port_b is PortID(2)

0 commit comments

Comments
 (0)