From 5fbefe51d63de9a64b6b598515df611be0f6b30c Mon Sep 17 00:00:00 2001 From: Josef Zweck <24647999+zweckj@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:51:58 +0100 Subject: [PATCH] add two part message parsing --- aioacaia/acaiascale.py | 24 +++++++++++++++++++++--- aioacaia/decode.py | 3 ++- aioacaia/exceptions.py | 10 ++++++++++ run.py | 18 ++++++++++++++++++ setup.py | 2 +- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/aioacaia/acaiascale.py b/aioacaia/acaiascale.py index 994b52b..62ebf49 100644 --- a/aioacaia/acaiascale.py +++ b/aioacaia/acaiascale.py @@ -15,11 +15,13 @@ from .const import ( DEFAULT_CHAR_ID, + HEADER1, + HEADER2, HEARTBEAT_INTERVAL, NOTIFY_CHAR_ID, OLD_STYLE_CHAR_ID, ) -from .exceptions import AcaiaDeviceNotFound, AcaiaError +from .exceptions import AcaiaDeviceNotFound, AcaiaError, AcaiaMessageTooShort from .const import UnitMass from .decode import Message, Settings, decode from .helpers import encode, encode_id, encode_notification_request, derive_model_name @@ -88,6 +90,8 @@ def __init__( self._queue: asyncio.Queue = asyncio.Queue() self._add_to_queue_lock = asyncio.Lock() + self._last_short_msg: bytearray | None = None + self._msg_types["auth"] = encode_id(is_pyxis_style=is_new_style_scale) if not is_new_style_scale: @@ -222,7 +226,7 @@ async def connect( address_or_ble_device=self.address_or_ble_device, disconnected_callback=self.device_disconnected_handler, ) - self._client.get_services() + try: await self._client.connect() except BleakError as ex: @@ -389,7 +393,21 @@ async def on_bluetooth_data_received( data: bytearray, ) -> None: """Receive data from scale.""" - msg = decode(data)[0] + + # For some scales the header is sent and then in next message the content + if ( + self._last_short_msg is not None + and self._last_short_msg[0] == HEADER1 + and self._last_short_msg[1] == HEADER2 + ): + data = self._last_short_msg + data + self._last_short_msg = None + + try: + msg = decode(data)[0] + except AcaiaMessageTooShort as ex: + self._last_short_msg = ex.bytes_recvd + return if isinstance(msg, Settings): self._device_state = AcaiaDeviceState( diff --git a/aioacaia/decode.py b/aioacaia/decode.py index 21d9d78..4eece52 100644 --- a/aioacaia/decode.py +++ b/aioacaia/decode.py @@ -5,6 +5,7 @@ from bleak import BleakGATTCharacteristic from .const import HEADER1, HEADER2 +from .exceptions import AcaiaMessageTooShort _LOGGER = logging.getLogger(__name__) @@ -161,7 +162,7 @@ def decode(byte_msg: bytearray): if msg_start < 0 or len(byte_msg) - msg_start < 6: _LOGGER.debug("Message too short %s", byte_msg) - return (None, byte_msg) + raise AcaiaMessageTooShort(byte_msg) msg_end = msg_start + byte_msg[msg_start + 3] + 5 diff --git a/aioacaia/exceptions.py b/aioacaia/exceptions.py index e344c41..d82e68b 100644 --- a/aioacaia/exceptions.py +++ b/aioacaia/exceptions.py @@ -17,3 +17,13 @@ class AcaiaError(BleakError): class AcaiaUnknownDevice(Exception): """Exception for unknown devices.""" + + +class AcaiaMessageTooShort(Exception): + """Exception for messages that are too short.""" + + def __init__( + self, bytes_recvd: bytearray, message: str = "Message too short" + ) -> None: + super().__init__(message) + self.bytes_recvd = bytes_recvd diff --git a/run.py b/run.py index 815f033..7bc6da0 100644 --- a/run.py +++ b/run.py @@ -2,9 +2,27 @@ from aioacaia import AcaiaScale from aioacaia.decode import notification_handler +from aioacaia.decode import decode, Message async def main(): + scale = AcaiaScale("aa:bb:cc:dd:ee:ff") + await scale.on_bluetooth_data_received(None, bytearray(b"\xef\xdd\x0c")) + res = await scale.on_bluetooth_data_received( + None, bytearray(b"\x0c\x05\xdf\x06\x00\x00\x01\x00\x07\x00\x00\x02\xf3\r") + ) + decode( + bytearray(b"\xef\xdd\x0c\x0c\x05\xdf\x06\x00\x00\x01\x00\x07\x00\x00\x02\xf3\r") + ) + # Message(5, bytearray(b"\xdf\x06\x00\x00\x01\x00\x07\x00\x00\x02\xf3\r")) + # Message(5, b"\xa1\x10\x00\x00\x01\x01\x07\x00\x00\x02\xb5\x18") + # Message(5, bytearray(b"]\x07\x00\x00\x01\x00\x07\x00\x00\x02q\x0e")) + # 0 = 12 + # 1 = 5 + Message(5, b"\x00\x00\x00\x00\x01\x00\x07\x00\x00\x02\x14\x07") + decode(bytearray(b"\x0c\x05\x00\x00\x00\x00\x01\x00\x07\x00\x00\x02\x14\x07")) + exit(0) + with open("mac.txt", "r") as f: mac = f.read().strip() diff --git a/setup.py b/setup.py index 0034be4..349124b 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="aioacaia", - version="0.1.4", + version="0.1.5b1", description="An async implementation of PyAcaia", long_description=readme, long_description_content_type="text/markdown",