def test_get_uint16(): f = SmlFrame(b'\x63\xff\x00') check(f.get_value(0), 65280, '63ff00') assert f.next_pos == 3 f = SmlFrame(b'\x63\x00\x03') check(f.get_value(0), 3, '630003') assert f.next_pos == 3 f = SmlFrame(b'\x00\x63\xff\x01') f.next_pos = 9999 check(f.get_value(1), 65281, '63ff01') assert f.next_pos == 4
def test_get_uint8(): f = SmlFrame(b'\x62\xff') check(f.get_value(0), 255, '62ff') assert f.next_pos == 2 f = SmlFrame(b'\x62\x03') check(f.get_value(0), 3, '6203') assert f.next_pos == 2 f = SmlFrame(b'\x00\x62\xff') f.next_pos = 9999 check(f.get_value(1), 255, '62ff') assert f.next_pos == 3
def test_get_int16(): f = SmlFrame(b'\x53\xff\x00') check(f.get_value(0), -256, '53ff00') assert f.next_pos == 3 f = SmlFrame(b'\x53\x00\x03') check(f.get_value(0), 3, '530003') assert f.next_pos == 3 f = SmlFrame(b'\x00\x53\xff\x01') f.next_pos = 9999 check(f.get_value(1), -255, '53ff01') assert f.next_pos == 4
def test_get_int8(): f = SmlFrame(b'\x52\xff') check(f.get_value(0), -1, '52ff') assert f.next_pos == 2 f = SmlFrame(b'\x52\x03') check(f.get_value(0), 3, '5203') assert f.next_pos == 2 f = SmlFrame(b'\x00\x52\x03') f.next_pos = 9999 check(f.get_value(1), 3, '5203') assert f.next_pos == 3
class SmlStreamReader: MAX_SIZE = 50 * 1024 def __init__(self, build_ctx: CTX_HINT = None): self.bytes: bytes = b'' self.build_ctx: CTX_HINT = build_ctx if build_ctx is not None else create_context( ) def add(self, _bytes: bytes): self.bytes += _bytes if len(self.bytes) > SmlStreamReader.MAX_SIZE: self.bytes = self.bytes[-1 * SmlStreamReader.MAX_SIZE:] def clear(self): self.bytes = b'' def get_frame(self) -> Optional[SmlFrame]: start = self.bytes.find(b'\x1B\x1B\x1B\x1B\x01\x01\x01\x01') if start == -1: return None # if we start reading in the mid of a message if start != 0: self.bytes = self.bytes[start:] start = 0 end = -1 while (end := self.bytes.find(b'\x1B\x1B\x1B\x1B\x1A', end + 1)) != -1: pre = self.bytes[end - 4:end] if pre != b'\x1B\x1B\x1B\x1B': break if end == -1: return None end += 8 if len(self.bytes) < end: return None # remove msg from buffer msg = self.bytes[start:end] self.bytes = self.bytes[end:] # Last three bytes are PADDING, CRC PART 1, CRC PART 2 padding = msg[-3] # check crc crc_msg = msg[-2] << 8 | msg[-1] crc_calc = get_crc(msg[:-2]) if crc_msg != crc_calc: raise CrcError(msg, crc_msg, crc_calc) frame = msg[8:-1 * (8 + padding)].replace( b'\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B', b'\x1B\x1B\x1B\x1B') return SmlFrame(frame, msg_ctx=msg, build_ctx=self.build_ctx)
def test_get_int32(): f = SmlFrame(b'\x55\x00\x00\x0a\x8c') check(f.get_value(0), 2700, '5500000a8c') assert f.next_pos == 5 f = SmlFrame(b'\x01\x01\x55\x00\x00\x0a\x8c') f.next_pos = 9999 check(f.get_value(2), 2700, '5500000a8c') assert f.next_pos == 7
def test_bool(): f = SmlFrame(b'\x42\x01') f.next_pos = 9999 check(f.get_value(0), True, '4201') assert f.next_pos == 2 f = SmlFrame(b'\x42\x00') check(f.get_value(0), False, '4200') assert f.next_pos == 2
def test_val_time(): # Frame where time is None f = SmlFrame(a2b_hex('77070100600100ff010101010b0a01484c5902000424a001')) val_list = f._parse_msg(f.get_value(0)) o = SmlListEntryBuilder().build(val_list, create_context()) assert o.val_time is None # Frame where secIndex == 1 and time == 0 # -> 7262016200 f = SmlFrame(a2b_hex('77070100600100ff017262016200620052000b0a01445a47000282c0b001')) val_list = f._parse_msg(f.get_value(0)) o = SmlListEntryBuilder().build(val_list, create_context()) assert o.val_time == 0
def test_eom(): f = SmlFrame(b'\x00') check(f.get_value(0), EndOfSmlMsg, '00') assert f.next_pos == 1 f = SmlFrame(b'\x00\x00') check(f.get_value(1), EndOfSmlMsg, '00') assert f.next_pos == 2
def test_sml_fields(): f = SmlFrame(a2b_hex('77078181c78203ff010101010449534b0177070100000009ff010101010b')) val_list = f._parse_msg(f.get_value(0)) o = SmlListEntryBuilder().build(val_list, create_context()) assert o.obis == '8181c78203ff' assert o.value == 'ISK' f = SmlFrame(a2b_hex('77070100010800ff650000018201621e52ff590000000001122334017707')) val_list = f._parse_msg(f.get_value(0)) o = SmlListEntryBuilder().build(val_list, create_context()) assert o.obis == '0100010800ff' assert o.status == 386 assert o.unit == 30 assert o.scaler == -1 assert o.value == 17965876 assert o.get_value() == 1796587.6
def test_none(): f = SmlFrame(b'\x01\x01\x01') assert f.get_value().value is None assert f.next_pos == 1 f.next_pos = 9999 assert f.get_value(1).value is None assert f.next_pos == 2 assert f.get_value().value is None assert f.next_pos == 3
def test_long_str(): f = SmlFrame(a2b_hex('8302010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102')) # noqa: E501 check( f.get_value(0), '010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102', '8302010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102') assert f.next_pos == 50 f = SmlFrame(a2b_hex('8302010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102FF')) # noqa: E501 check( f.get_value(0), '010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102', '8302010203040101010101010101010101010101010101010101010101010101010101010101010101010101010101010102') assert f.next_pos == 50 assert f.buffer[f.next_pos] == 0xFF
def test_str(): f = SmlFrame(b'\x07\x01\x00\x01\x08\x00\xFF') f.next_pos = 9999 check(f.get_value(0), '0100010800ff', '070100010800ff') assert f.next_pos == 7
def test_get_list(): f = SmlFrame(b'\x71\x01') f.next_pos = 9999 check(f._parse_msg(f.get_value(0)), [None], '7101') assert f.next_pos == 2 f = SmlFrame(b'\x72\x01\x00') f.next_pos = 9999 check(f._parse_msg(f.get_value(0)), [None, EndOfSmlMsg], '720100') assert f.next_pos == 3 f = SmlFrame(b'\x72\x52\xff\x62\x1e') check(f._parse_msg(f.get_value(0)), [-1, 30], '7252ff621e') assert f.next_pos == 5 f = SmlFrame(a2b_hex( '77070100010800ff' '6500000782' '01' '621e' '52ff' '59000000000dd359d6' '01' 'ff')) check(f._parse_msg(f.get_value(0)), ['0100010800ff', 1922, None, 30, -1, 231954902, None], '77070100010800ff650000078201621e52ff59000000000dd359d601') assert f.next_pos == 28