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__":