Exemplo n.º 1
0
 def test_query_hello(self):
     connection = create_autospec(Connection)
     connection.read.return_value = b'\x51\x00\x00\xa0\x00\x00\x9d\x4b\x01\x00\xd8\x19'
     protocol = Protocol(connection)
     self.assertEqual(b'\x01\0', protocol.query(Range(0xa000, 1)))
     connection.write.assert_called_once_with(
         b'\x51\x00\x00\xa0\x00\x00\x9d\x4b')
Exemplo n.º 2
0
 def test_read_retry(self):
     connection = create_autospec(Connection)
     connection.read.side_effect = [
         b'\x51',
         b'\x00\x00',
         b'\xa0',
         b'\x00',
         b'\x00',
         b'\x9d\x4b\x01\x00',
         b'\xd8',
         b'\x19',
     ]
     protocol = Protocol(connection)
     self.assertEqual(b'\x01\0', protocol.query(Range(0xa000, 1)))
     connection.read.assert_has_calls([
         call(12),
         call(11),
         call(9),
         call(8),
         call(7),
         call(6),
         call(2),
         call(1),
     ])
     connection.write.assert_called_once_with(
         b'\x51\x00\x00\xa0\x00\x00\x9d\x4b')
Exemplo n.º 3
0
 def test_query_invalid_crc_response(self):
     response = b'12345678901234567890123456'
     connection = create_autospec(Connection)
     connection.read.return_value = response
     protocol = Protocol(connection)
     with self.assertRaises(ValidationException) as context:
         protocol.query(Range(0xa000, 8))
     self.assertEqual('Incorrect CRC (0x958a)', context.exception.args[0])
Exemplo n.º 4
0
def _reduce(ranges: list) -> list:
    if len(ranges) <= 1:
        return ranges
    r1 = ranges[0]
    r2 = ranges[1]
    words = r2.address - r1.address + r2.words
    if words > MAX_WORDS:
        return [r1] + _reduce(ranges[1:])
    return _reduce([Range(r1.address, words)] + ranges[2:])
Exemplo n.º 5
0
 def test_query_hash(self):
     sent = b'Q\x07\x00\x00\x1f\x00\xcfb'
     read = b"Q\x07\x00\x00\x1f\x00\xcfbz\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b\xa0@"
     connection = create_autospec(Connection)
     connection.read.return_value = read
     protocol = Protocol(connection)
     self.assertEqual(
         b'z\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b',
         protocol.query(Range(0x1f0000, 8)))
     connection.write.assert_called_once_with(sent)
Exemplo n.º 6
0
 def test_sorted(self):
     datas = [
         Data(Range(0x1234, 1), b'zz'),
         Data(Range(0x9999, 2), b'aaaa'),
         Data(Range(0x0000, 1), b'mm'),
         Data(Range(0x4567, 1), b'aa'),
     ]
     self.maxDiff = None
     self.assertEqual([
         Data(Range(0x0000, 1), b'mm'),
         Data(Range(0x1234, 1), b'zz'),
         Data(Range(0x4567, 1), b'aa'),
         Data(Range(0x9999, 2), b'aaaa'),
     ], sorted(datas))
Exemplo n.º 7
0
class DataTest(TestCase):
    def test_bytes_raises_before_set(self):
        data = Data(Mock())
        with self.assertRaises(NotFoundException) as context:
            data.bytes
        self.assertEqual('Unable to read bytes before property is set',
                         context.exception.args[0])

    def test_bytes_raises_during_init(self):
        with self.assertRaises(ValidationException) as context:
            Data(Range(0x0000, 1), b'1234')
        self.assertEqual('Unable to store 4 bytes to range requiring 2',
                         context.exception.args[0])

    @data_provider(lambda: (
        (Range(0xcafe, 1), b'ab'),
        (Range(0xfeed, 5), b'1234567890'),
    ))
    def test_bytes_getter(self, range: Range, bytes: bytes):
        data = Data(range, bytes)
        self.assertEqual(bytes, data.bytes)

    @data_provider(lambda: (
        (Range(0xcafe, 1), b'ab'),
        (Range(0xfeed, 5), b'1234567890'),
    ))
    def test_bytes_setter(self, range: Range, bytes: bytes):
        data = Data(range)
        data.bytes = bytes
        self.assertEqual(bytes, data.bytes)

    @data_provider(lambda: (
        (Range(0xcafe, 2), b'ab',
         'Unable to store 2 bytes to range requiring 4'),
        (Range(0xfeed, 1), b'1234567890',
         'Unable to store 10 bytes to range requiring 2'),
    ))
    def test_bytes_raises_setter(self, range, bytes, expected):
        data = Data(range)
        with self.assertRaises(ValidationException) as context:
            data.bytes = bytes
        self.assertEqual(expected, context.exception.args[0])

    def test_sorted(self):
        datas = [
            Data(Range(0x1234, 1), b'zz'),
            Data(Range(0x9999, 2), b'aaaa'),
            Data(Range(0x0000, 1), b'mm'),
            Data(Range(0x4567, 1), b'aa'),
        ]
        self.maxDiff = None
        self.assertEqual([
            Data(Range(0x0000, 1), b'mm'),
            Data(Range(0x1234, 1), b'zz'),
            Data(Range(0x4567, 1), b'aa'),
            Data(Range(0x9999, 2), b'aaaa'),
        ], sorted(datas))
Exemplo n.º 8
0
 def test_query_short_response(self):
     connection = create_autospec(Connection)
     connection.read.side_effect = [
         b'123456',
         b'',
         b'',
         b'',
         b'',
         b'',
         b'',
         b'',
         b'',
         b'',
         b'',
     ]
     protocol = Protocol(connection)
     with self.assertRaises(BufferError) as context:
         protocol.query(Range(0xa000, 9))
     self.assertEqual('Expected 28 bytes, but only able to read 6',
                      context.exception.args[0])
Exemplo n.º 9
0
    def test_update(self):
        protocol = create_autospec(Protocol)
        protocol.query.side_effect = [
            b'\x12\x34\x00\x00\x00\x00\x00\x00\x56\x78'
        ]
        muster = Muster(protocol)
        vars = [
            variable.create('CommonScaleForAcVolts'),
            variable.create('CommonScaleForTemperature'),
        ]

        muster.update(vars)

        self.assertEqual(2, len(vars))
        self.assertEqual('CommonScaleForAcVolts', vars[0].get_name())
        self.assertEqual('CommonScaleForTemperature', vars[1].get_name())
        self.assertEqual(b'\x12\x34', vars[0].bytes)
        self.assertEqual(b'\x56\x78', vars[1].bytes)
        self.assertEqual(1, len(protocol.query.call_args_list))
        self.assertEqual(call(Range(41000, 5)),
                         protocol.query.call_args_list[0])
Exemplo n.º 10
0
def run(args):
    protocol = Protocol(connection.create())
    protocol.login()

    # Before 0xa001 we don't get anything back
    start = 0xa001
    # How much to get at a time
    fetch_words = 0x100
    line_words = 0x10
    # When to stop
    end = 0xa301
    print(
        '          1   2   3   4   5   6   7   8   9   a   b   c   d   e   f   0'
    )
    for address in range(start, end, fetch_words):
        memory = protocol.query(Range(address, fetch_words))
        for offset in range(0, fetch_words, line_words):
            start_bytes = offset * 2
            end_bytes = (offset + line_words) * 2
            sub_memory = memory[start_bytes:end_bytes]
            hex_memory = binascii.hexlify(sub_memory)
            hex_address = binascii.hexlify(struct.pack(">H", address + offset))
            print(b''.join([b'0x', hex_address, b' ',
                            hex_memory]).decode('utf-8'))
Exemplo n.º 11
0
 def range(self):
     return Range(self.__address, TYPES[self.get_type()][WORDS])
Exemplo n.º 12
0
class ExtractTest(TestCase):
    @data_provider(lambda: (
        (
            Range(0x0001, 2),
            [
                Data(Range(0x0000, 10), b'1234567890abcdefghij'),
            ],
            Data(Range(0x0001, 2), b'3456'),
        ),
        (
            Range(0x0001, 2),
            [
                Data(Range(0x0001, 4), b'12345678'),
            ],
            Data(Range(0x0001, 2), b'1234'),
        ),
        (Range(0x1234, 4), [
            Data(Range(0x0000, 10), b'aaaaaaaaaaaaaaaaaaaa'),
            Data(Range(0x1230, 10), b'mmmmmmmm78901234mmmm'),
            Data(Range(0x9999, 10), b'zzzzzzzzzzzzzzzzzzzz'),
        ], Data(Range(0x1234, 4), b'78901234')),
    ))
    def test_extract(self, range, datas, expected):
        self.assertEqual(expected, extract(range, datas))

    @data_provider(lambda: (
        (Range(0x0000, 10),
         [Data(Range(0x00010, 10), b'1234567890abcdefghij')]),
        (Range(0x0010, 12),
         [Data(Range(0x00010, 10), b'1234567890abcdefghij')]),
        (Range(0x0011, 5), [Data(Range(0x00010, 5), b'1234567890')]),
        (Range(0xcafe, 1), [Data(Range(0x00010, 5), b'1234567890')]),
    ))
    def test_extract_out_of_range(self, range, datas):
        with self.assertRaises(NotFoundException) as context:
            extract(range, datas)
        self.assertEqual('%s was not found' % range, context.exception.args[0])
Exemplo n.º 13
0
class RangeTest(TestCase):
    @data_provider(lambda: (
        (Range(0x0000, 3), Range(0x0000, 3), True),
        (Range(0x0000, 3), Range(0x0000, 4), False),
        (Range(0xa033, 1), Range(0xa033, 1), True),
        (Range(0xa033, 1), Range(0xa034, 1), False),
        (Range(0xa033, 1), [Range(0xa033, 1)], False),
    ))
    def test___eq__(self, r1, r2, expected):
        self.assertEqual(expected, r1 == r2)

    @data_provider(lambda: (
        (Range(0x0000, 3), 'Range(0x0000, 3)'),
        (Range(0x1234, 99), 'Range(0x1234, 99)'),
        (Range(0xcafe, 1), 'Range(0xcafe, 1)'),
    ))
    def test___repr__(self, range, expected):
        self.assertEqual(expected, repr(range))

    @data_provider(lambda: (
        ([
            Range(0x0000, 2),
            Range(0x0004, 3),
        ], [
            Range(0x0000, 2),
            Range(0x0004, 3),
        ]),
        ([
            Range(0x0009, 1),
            Range(0x0004, 3),
            Range(0x0000, 2),
            Range(0x0007, 1),
        ], [
            Range(0x0000, 2),
            Range(0x0004, 3),
            Range(0x0007, 1),
            Range(0x0009, 1),
        ]),
    ))
    def test_sorted(self, ranges, expected):
        self.assertEqual(expected, sorted(ranges))
Exemplo n.º 14
0
class VariableTest(TestCase):
    @data_provider(lambda: (
        # (arg, name, address)
        ('CommonScaleForDcVolts', 'CommonScaleForDcVolts', 0xa02a),
        ('Shunt1Power', 'Shunt1Power', 0xa088),
        ('BatteryVolts', 'BatteryVolts', 0xa05c),
        ('BattSocPercent', 'BattSocPercent', 0xa081),
        (0xa02a, 'CommonScaleForDcVolts', 0xa02a),
        (0xa088, 'Shunt1Power', 0xa088),
        (0xa05c, 'BatteryVolts', 0xa05c),
        (0xa081, 'BattSocPercent', 0xa081),
        (0xcafe, 'Unknown', 0xcafe),
        (0xfeed, 'Unknown', 0xfeed),
    ))
    def test_create(self, arg, name, address):
        var = variable.create(arg)
        self.assertIsInstance(var, Variable)
        self.assertEqual(address, var.range.address)
        self.assertEqual(name, var.get_name())

    @data_provider(lambda: (
        ('CommonScaleForDcVolts', Range(41002, 1)),
        ('BattOutkWhPreviousAcc', Range(41356, 2)),
        ('DCBatteryPower', Range(41007, 2)),
        (0xcafe, Range(0xcafe, 1)),
        (0xfeed, Range(0xfeed, 1)),
    ))
    def test_range(self, arg, range):
        self.assertEqual(range, variable.create(arg).range)

    @data_provider(lambda: (
        # (arg, type)
        ('CommonScaleForDcVolts', 'ushort'),
        ('BattOutkWhPreviousAcc', 'uint'),
        ('DCBatteryPower', 'int'),
        (0xcafe, 'ushort'),
        (0xfeed, 'ushort'),
    ))
    def test_get_type(self, arg, type):
        self.assertEqual(type, variable.create(arg).get_type())

    @data_provider(lambda: (
        ('CommonScaleForDcVolts', b'\x1a\x04', 1050),
        ('BatteryVolts', b'\x41\x44', 55.989532470703125),
    ))
    def test_bytes(self, arg, bytes, value):
        var = variable.create(arg)
        var.bytes = bytes
        self.assertEqual(value, var.get_value(scales))
        self.assertEqual(bytes, var.bytes)

    @data_provider(lambda: (
        ('CommonScaleForDcVolts', b'\x1a\x04', 1050),
        ('CommonScaleForTemperature', b'\x12\x02', 530),
        ('Shunt1Power', b'\x46\xfe', -1699.5849609375),
        ('Shunt1Power', b'\x3f\xfe', -1726.50146484375),
        ('Shunt1Power', b'\x7a\xfe', -1499.6337890625),
        ('Shunt1Power', b'\xfd\xff', -11.53564453125),
        ('BatteryVolts', b'\x41\x44', 55.989532470703125),
        ('BatteryVolts', b'\x3a\x44', 55.96710205078125),
        ('BatteryTemperature', b'\x44\x05', 21.802978515625),
        ('LoadAcPower', b'\xff\x02\x00\x00', 341.1567687988281),
        ('LoadAcPower', b'\x1d\x03\x00\x00', 354.5005798339844),
        ('DCBatteryPower', b'\xd4\xff\xff\xff', -169.189453125),
        ('DCBatteryPower', b'\xf4\xff\xff\xff', -46.142578125),
        ('ACLoadkWhTotalAcc', b'\x19\xeb\x00\x00', 5139822.509765625),
        ('BattOutkWhPreviousAcc', b'\x29\x00\x00\x00', 3783.69140625),
        ('BattSocPercent', b'\xdb\x63', 99.85546875),
        ('Shunt1Name', b'\x01\x00', 'Solar'),
        ('Shunt2Name', b'\x00\x00', 'None'),
        ('Shunt1Name', b'\x3a\x00', 'Error'),
    ))
    def test_get_value(self, name, bytes, value):
        address = 0xcafe  # address doesn't matter for this test
        var = Variable(name, address, bytes)
        self.assertEqual(value, var.get_value(scales))

    def test_get_value_errors(self):
        var = variable.create(0xcafe)
        with self.assertRaises(Exception) as context:
            var.get_value([])
        self.assertEqual('Can not convert value for unknown variable type',
                         context.exception.args[0])
Exemplo n.º 15
0
class ReduceTest(TestCase):
    @data_provider(lambda: (
        ([
            Range(0x1234, 2),
        ], [
            Range(0x1234, 2),
        ]),
        ([
            Range(0x0010, 1),
            Range(0x0014, 2),
        ], [
            Range(0x0010, 6),
        ]),
        ([
            Range(0x0004, 2),
            Range(0x0000, 1),
        ], [
            Range(0x0000, 6),
        ]),
        ([
            Range(0x0001, 2),
            Range(0x0002, 2),
            Range(0x0003, 2),
        ], [
            Range(0x0001, 4),
        ]),
        # Split across MAX_WORDS (256)
        ([
            Range(0x0000, 2),
            Range(0x00ff, 1),
            Range(0x0103, 1),
            Range(0x0203, 1),
            Range(0x0301, 2),
        ], [
            Range(0x0000, 256),
            Range(0x0103, 1),
            Range(0x0203, 256),
        ]),
    ))
    def test_reduce(self, ranges, expected):
        self.assertEqual(expected, reduce(ranges))
Exemplo n.º 16
0
 def test_bytes_raises_during_init(self):
     with self.assertRaises(ValidationException) as context:
         Data(Range(0x0000, 1), b'1234')
     self.assertEqual('Unable to store 4 bytes to range requiring 2',
                      context.exception.args[0])