From fcf5135446c50e1d91784d2f7f004988b6b8c65d Mon Sep 17 00:00:00 2001 From: samgalam <65561329+samgalam@users.noreply.github.com> Date: Thu, 2 Jul 2020 17:38:30 -0400 Subject: [PATCH] Fix some python3 bugs in mbmap (#98) * Fix some python3 bugs in mbmap * Add tests for to_xml --- .gitignore | 3 + sunspec/core/modbus/mbmap.py | 19 +-- .../test/devices/mbmap_test_device_1_d.xml | 109 ++++++++++++++++++ .../devices/mbmap_test_device_1_processed.xml | 1 + sunspec/core/test/test_modbus_mbmap.py | 30 +++++ 5 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 sunspec/core/test/devices/mbmap_test_device_1_d.xml create mode 100644 sunspec/core/test/devices/mbmap_test_device_1_processed.xml diff --git a/.gitignore b/.gitignore index 6704a40..ade1819 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,9 @@ build/ doc/_build/ doc/sphinx/ +# Jetbrains IDE junk +.idea/ + # Mac OS X Junk .DS_Store *.AppleDouble diff --git a/sunspec/core/modbus/mbmap.py b/sunspec/core/modbus/mbmap.py index af3ab2e..0a010d3 100644 --- a/sunspec/core/modbus/mbmap.py +++ b/sunspec/core/modbus/mbmap.py @@ -273,11 +273,11 @@ def from_xml(self, filename=None, pathlist=None, element=None): else: data += c # fill remainder of string with nulls - regs_len = rlen * 2 - if regs_len > text_len: + padding_needed = 2 * int(rlen - text_len / 4) + if padding_needed > 0: if data is None: - data = '' - data += struct.pack(str(regs_len - text_len) + 's', '') + data = b'' + data += struct.pack(str(padding_needed) + 's', b'') else: raise ModbusMapError('Unknown type at offset %d' % (offset)) @@ -318,8 +318,13 @@ def to_xml(self, parent=None, no_data=False): if no_data is False: s = '' - for d in regs.data: - s += '%02x' % ord(d) + if sys.version_info > (3,): + # Iterating over python 3 bytes gives integers + for d in regs.data: + s += '%02x' % d + else: + for d in regs.data: + s += '%02x' % ord(d) e.text = s return element @@ -341,7 +346,7 @@ def regs_add(self, addr=None, offset=None, count=1, access=MBMAP_REGS_ACCESS_RW) if offset < last_regs_next: raise ModbusMapError('Register offsets must be in ascending order with no overlap %d %d' % (offset, last_regs_next)) - data = struct.pack(str(count * 2) + 's', '') + data = struct.pack(str(count * 2) + 's', b'') if last_regs is None or offset > last_regs_next: mmr = ModbusMapRegs(offset, count, data, access) diff --git a/sunspec/core/test/devices/mbmap_test_device_1_d.xml b/sunspec/core/test/devices/mbmap_test_device_1_d.xml new file mode 100644 index 0000000..dd6678c --- /dev/null +++ b/sunspec/core/test/devices/mbmap_test_device_1_d.xml @@ -0,0 +1,109 @@ + + + SunS + 1 + 66 + SunSpecTest + TestDevice-1 + opt_a_b_c + 1.2.3 + sn-123456789 + 1 + 0 + + + 63001 + 188 + fff6 000a 0000 0001 0001 ffff 0002 fffe 0003 8000 0004 0005 fff4 0006 0007 ffff + 0008 0000 0009 ffff 000a ffff 0000 000b 0000 000c 0000 000d 0000 000e 0000 000f + 80000000 + 00000010 + 00000011 + 00000012 + 00000013 + 00000014 + ffffffff + 00000015 + 00000000 + 00000016 + ffffffff + 00000017 + ffffffff + 01020304 + 00000000 + 0000000000000018 + 8000000000000000 + 0000000000000019 + 0000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 41d0 + 7fc00000 + 3132333435363738000000000000000000000000000000000000000000000000 + + + + + 0000000000000000000000000000000000000000000000000000000000000000 + + + + 2 + 3 + 4 + -32768 + + + -2 + 30 + 31 + -32768 + 32 + 33 + 34 + 0xffff + 35 + -2147483648 + 36 + 0xffffffff + -3 + 0x8000 + + + -4 + 40 + 41 + -32768 + 42 + 43 + 44 + 0xffff + 45 + -2147483648 + 46 + 0xffffffff + -5 + 0x8000 + + + 2 + 50 + 51 + -32768 + 52 + 53 + 54 + 0xffff + 55 + -2147483648 + 56 + 0xffffffff + 3 + 0xffff + + 0xffff + 0 + + diff --git a/sunspec/core/test/devices/mbmap_test_device_1_processed.xml b/sunspec/core/test/devices/mbmap_test_device_1_processed.xml new file mode 100644 index 0000000..93f24fc --- /dev/null +++ b/sunspec/core/test/devices/mbmap_test_device_1_processed.xml @@ -0,0 +1 @@ +53756e530001004253756e5370656354657374000000000000000000000000000000000000000000546573744465766963652d3100000000000000000000000000000000000000006f70745f615f625f6300000000000000312e322e330000000000000000000000736e2d313233343536373839000000000000000000000000000000000000000000010000f61900bcfff6000a000000010001ffff0002fffe0003800000040005fff400060007ffff000800000009ffff000affff0000000b0000000c0000000d0000000e0000000f800000000000001000000011000000120000001300000014ffffffff000000150000000000000016ffffffff00000017ffffffff01020304000000000000000000000018800000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000000000000000000000041d000007fc00000313233343536373800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000300048000fffe001e001f8000002000210022ffff000000238000000000000024fffffffffffd8000fffc002800298000002a002b002cffff0000002d800000000000002efffffffffffb80000002003200338000003400350036ffff000000378000000000000038ffffffff0003ffffffff0000 \ No newline at end of file diff --git a/sunspec/core/test/test_modbus_mbmap.py b/sunspec/core/test/test_modbus_mbmap.py index 1dae45c..f20c9e3 100644 --- a/sunspec/core/test/test_modbus_mbmap.py +++ b/sunspec/core/test/test_modbus_mbmap.py @@ -64,6 +64,12 @@ def test_modbus_mbmap_from_xml_file(self): if not_equal: raise Exception(not_equal) + m5 = mbmap.ModbusMap() + m5.from_xml('mbmap_test_device_1_d.xml', self.pathlist) + not_equal = m1.not_equal(m5) + if not_equal: + raise Exception(not_equal) + def test_modbus_mbmap_from_xml_element(self): filename = os.path.join(self.pathlist.path[1], @@ -95,6 +101,30 @@ def test_modbus_mbmap_from_xml_element(self): if not_equal: raise Exception(not_equal) + def test_modbus_mbmap_regs_add(self): + m1 = mbmap.ModbusMap(base_addr=999, func='holding', mapid=12345) + m1.regs_add(offset=40072, count=1) + + def test_modbus_mbmap_to_xml(self): + filename = os.path.join(self.pathlist.path[1], 'mbmap_test_device_1.xml') + + f = open(filename, 'r') + map_data = f.read() + f.close() + root = ET.fromstring(map_data) + + expected_output_filename = os.path.join(self.pathlist.path[1], 'mbmap_test_device_1_processed.xml') + f = open(expected_output_filename, 'r') + expected_output = f.read() + f.close() + expected_root = ET.fromstring(expected_output) + + # Convert from xml to ModbusMap and back to xml to verify to_xml() is working properly + m1 = mbmap.ModbusMap() + m1.from_xml(element=root) + + assert m1.to_xml().find('regs').text == expected_root.find('regs').text + if __name__ == "__main__":