Skip to content

Commit

Permalink
Fix unpack methods.
Browse files Browse the repository at this point in the history
Arbitrary size integers must be unpacked via 'int.from_bytes'.
  • Loading branch information
denpamusic committed Oct 17, 2023
1 parent 07c50d6 commit 04aede8
Show file tree
Hide file tree
Showing 9 changed files with 21 additions and 27 deletions.
2 changes: 1 addition & 1 deletion pyplumio/helpers/data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class UnsignedShort(DataType):
@property
def value(self) -> int:
"""A data value."""
return util.unpack_ushort(self._data)
return util.unpack_ushort(self._data)[0]

@property
def size(self) -> int:
Expand Down
13 changes: 8 additions & 5 deletions pyplumio/helpers/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from pyplumio.const import BYTE_UNDEFINED, STATE_OFF, STATE_ON
from pyplumio.frames import Request
from pyplumio.helpers.typing import ParameterTupleType, ParameterValueType
from pyplumio.util import unpack_ushort

if TYPE_CHECKING:
from pyplumio.devices import Device
Expand All @@ -27,11 +26,15 @@ def unpack_parameter(
if not check_parameter(data[offset : offset + size * 3]):
return None

value = unpack_ushort(data[offset : offset + size])
min_value = unpack_ushort(data[offset + size : offset + 2 * size])
max_value = unpack_ushort(data[offset + 2 * size : offset + 3 * size])
value = data[offset : offset + size]
min_value = data[offset + size : offset + 2 * size]
max_value = data[offset + 2 * size : offset + 3 * size]

return value, min_value, max_value
return (
int.from_bytes(value, byteorder="little"),
int.from_bytes(min_value, byteorder="little"),
int.from_bytes(max_value, byteorder="little"),
)


def check_parameter(data: bytearray) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions pyplumio/structures/data_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def _unpack_block(self, message: bytearray) -> tuple[int, DataType]:
param_type = message[self._offset]
param_id = util.unpack_ushort(
message[self._offset + 1 : self._offset + BLOCK_SIZE]
)
)[0]

try:
return param_id, DATA_TYPES[param_type]()
Expand All @@ -34,7 +34,7 @@ def decode(
self, message: bytearray, offset: int = 0, data: EventDataType | None = None
) -> tuple[EventDataType, int]:
"""Decode bytes and return message data and offset."""
blocks = util.unpack_ushort(message[offset : offset + 2])
blocks = util.unpack_ushort(message[offset : offset + 2])[0]
self._offset = offset + 2
if blocks == 0:
return ensure_device_data(data), self._offset
Expand Down
2 changes: 1 addition & 1 deletion pyplumio/structures/frame_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def _unpack_frame_versions(self, message: bytearray) -> tuple[FrameType | int, i

version = util.unpack_ushort(
message[self._offset + 1 : self._offset + FRAME_VERSION_SIZE]
)
)[0]

try:
return frame_type, version
Expand Down
2 changes: 1 addition & 1 deletion pyplumio/structures/lambda_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def decode(
if message[offset] == BYTE_UNDEFINED:
return ensure_device_data(data), offset + 1

level = util.unpack_ushort(message[offset + 2 : offset + LAMBDA_LEVEL_SIZE])
level = util.unpack_ushort(message[offset + 2 : offset + LAMBDA_LEVEL_SIZE])[0]
return (
ensure_device_data(
data,
Expand Down
2 changes: 1 addition & 1 deletion pyplumio/structures/output_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def decode(
self, message: bytearray, offset: int = 0, data: EventDataType | None = None
) -> tuple[EventDataType, int]:
"""Decode bytes and return message data and offset."""
output_flags = util.unpack_ushort(message[offset : offset + OUTPUT_FLAGS_SIZE])
output_flags = util.unpack_uint(message[offset : offset + OUTPUT_FLAGS_SIZE])[0]
return (
ensure_device_data(
data,
Expand Down
2 changes: 1 addition & 1 deletion pyplumio/structures/outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def decode(
self, message: bytearray, offset: int = 0, data: EventDataType | None = None
) -> tuple[EventDataType, int]:
"""Decode bytes and return message data and offset."""
outputs = util.unpack_ushort(message[offset : offset + OUTPUTS_SIZE])
outputs = util.unpack_uint(message[offset : offset + OUTPUTS_SIZE])[0]
return (
ensure_device_data(
data,
Expand Down
16 changes: 6 additions & 10 deletions pyplumio/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
unpack_float = struct.Struct("<f").unpack
unpack_char = struct.Struct("<b").unpack
unpack_short = struct.Struct("<h").unpack
unpack_ushort = struct.Struct("<H").unpack
unpack_int = struct.Struct("<i").unpack
unpack_uint = struct.Struct("<I").unpack
unpack_double = struct.Struct("<d").unpack
Expand All @@ -16,23 +17,18 @@
unpack_header = struct.Struct("<BH4B").unpack_from


def crc(data: bytes) -> int:
"""Return a checksum."""
return functools.reduce(lambda x, y: x ^ y, data)


def unpack_ushort(data: bytes) -> int:
"""Unpack a unsigned short number."""
return int.from_bytes(data, byteorder="little", signed=False)


def unpack_string(data: bytearray, offset: int = 0) -> str:
"""Unpack a string."""
strlen = data[offset]
offset += 1
return data[offset : offset + strlen + 1].decode()


def crc(data: bytes) -> int:
"""Return a checksum."""
return functools.reduce(lambda x, y: x ^ y, data)


def to_camelcase(text: str, overrides: dict[str, str] = None) -> str:
"""Convert snake_case to CamelCase."""
if overrides is None:
Expand Down
5 changes: 0 additions & 5 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ def test_crc() -> None:
assert util.crc(b"\x68\x0a\x00\x00\x56\x30\x05\x40") == 0x41


def test_unpack_ushort() -> None:
"""Test unpacking unsigned short."""
assert util.unpack_ushort(b"\x0a\x00") == 10


def test_to_camelcase() -> None:
"""Test string to camelcase converter."""
assert util.to_camelcase("make_love_not_war") == "MakeLoveNotWar"
Expand Down

0 comments on commit 04aede8

Please sign in to comment.