Skip to content

Commit

Permalink
Fix some python3 bugs in mbmap (sunspec#98)
Browse files Browse the repository at this point in the history
* Fix some python3 bugs in mbmap

* Add tests for to_xml
  • Loading branch information
samgalam authored Jul 2, 2020
1 parent ab80e90 commit fcf5135
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ build/
doc/_build/
doc/sphinx/

# Jetbrains IDE junk
.idea/

# Mac OS X Junk
.DS_Store
*.AppleDouble
Expand Down
19 changes: 12 additions & 7 deletions sunspec/core/modbus/mbmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
109 changes: 109 additions & 0 deletions sunspec/core/test/devices/mbmap_test_device_1_d.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<mbmap>
<!-- common model -->
<regs type="string" len="2">SunS</regs>
<regs type="u16">1</regs>
<regs type="u16">66</regs>
<regs type="string" len="16">SunSpecTest</regs>
<regs type="string" len="16">TestDevice-1</regs>
<regs type="string" len="8">opt_a_b_c</regs>
<regs type="string" len="8">1.2.3</regs>
<regs type="string" len="16">sn-123456789</regs>
<regs type="u16">1</regs>
<regs type="u16">0</regs>

<!-- model 63000 len = 188 -->
<regs offset="70" type="u16">63001</regs>
<regs offset="71" type="s16">188</regs>
<regs>fff6 000a 0000 0001 0001 ffff 0002 fffe 0003 8000 0004 0005 fff4 0006 0007 ffff</regs>
<regs>0008 0000 0009 ffff 000a ffff 0000 000b 0000 000c 0000 000d 0000 000e 0000 000f</regs>
<regs offset="104">80000000</regs> <!-- 0x8000, 0, # 0x80000000 <point id="int32_u" offset="32" type="int32" /> -->
<regs offset="106">00000010</regs> <!-- 0, 0x10, # 16 <point id="uint32_1" offset="34" type="uint32" sf="sunssf_5" /> -->
<regs offset="108">00000011</regs> <!-- 0, 0x11, # 17 <point id="uint32_2" offset="36" type="uint32" sf="sunssf_6" /> -->
<regs offset="110">00000012</regs> <!-- 0, 0x12, # 18 <point id="uint32_3" offset="38" type="uint32" sf="sunssf_7" /> -->
<regs offset="112">00000013</regs> <!-- 0, 0x13, # 19 <point id="uint32_4" offset="40" type="uint32" /> -->
<regs offset="114">00000014</regs> <!-- 0, 0x14, # 20 <point id="uint32_5" offset="42" type="uint32" /> -->
<regs offset="116">ffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="uint32_u" offset="44" type="uint32" /> -->
<regs offset="118">00000015</regs> <!-- 0, 0x15, # 21 <point id="acc32" offset="46" type="acc32" /> -->
<regs offset="120">00000000</regs> <!-- 0, 0, # 0 <point id="acc32_u" offset="48" type="acc32" /> -->
<regs offset="122">00000016</regs> <!-- 0, 0x16, # 22 <point id="enum32" offset="50" type="enum32" /> -->
<regs offset="124">ffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="enum32_u" offset="52" type="enum32" /> -->
<regs offset="126">00000017</regs> <!-- 0, 0x17, # 23 <point id="bitfield32" offset="54" type="bitfield32" /> -->
<regs offset="128">ffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="bitfield32_u" offset="56" type="bitfield32" /> -->
<regs offset="130">01020304</regs> <!-- 0x0102, 0x0304, # 0x01020304 <point id="ipaddr" offset="58" type="ipaddr" /> -->
<regs offset="132">00000000</regs> <!-- 0, 0, # 0 <point id="ipaddr_u" offset="60" type="ipaddr" /> -->
<regs offset="134">0000000000000018</regs> <!-- 0, 0, 0, 0x18, # 24 <point id="int64" offset="62" type="int64" /> -->
<regs offset="138">8000000000000000</regs> <!-- 0x8000, 0, 0, 0, # 0x8000000000000000 <point id="int64_u" offset="66" type="int64" /> -->
<regs offset="142" len="4">0000000000000019</regs> <!-- 0, 0, 0, 0x19, # 25 <point id="acc64" offset="70" type="acc64" /> -->
<regs offset="146" len="4">0000</regs> <!-- 0, 0, 0, 0, # 0 <point id="acc64_u" offset="74" type="int64" /> -->
<regs offset="150">0000000000000000</regs> <!-- 0, 0, 0, 0, # 0 <point id="ipv6addr" offset="78" type="ipv6addr" /> -->
<regs offset="154">0000000000000000</regs> <!-- 0, 0, 0, 0, -->
<regs offset="158">0000000000000000</regs> <!-- 0, 0, 0, 0, # 0 <point id="ipv6addr_u" offset="86" type="ipv6addr" /> -->
<regs offset="162">0000000000000000</regs> <!-- 0, 0, 0, 0, -->
<regs offset="166" len="2">41d0</regs> <!-- 0x41d0, 0, # 26 <point id="float32" offset="94" type="float32" /> -->
<regs offset="168">7fc00000</regs> <!-- 0x7fc0, 0, # NaN <point id="float32_u" offset="96" type="float32" /> -->
<regs offset="170">3132333435363738000000000000000000000000000000000000000000000000</regs> <!-- 0x3132, 0x3334, # 12345678 <point id="string" offset="98" type="string" len="16"/> -->
<!-- 0x3536, 0x3738, -->
<!-- 0, 0, 0, 0, -->
<!-- 0, 0, 0, 0, -->
<!-- 0, 0, 0, 0, -->
<regs offset="186">0000000000000000000000000000000000000000000000000000000000000000</regs> <!-- 0, 0, 0, 0, # 0 <point id="string_u" offset="114" type="string" len="16"/> -->
<!-- 0, 0, 0, 0, -->
<!-- 0, 0, 0, 0, -->
<!-- 0, 0, 0, 0, -->
<regs offset="202" type="s16">2</regs> <!-- 2, # 2 <point id="sunssf_5" offset="130" type="sunssf" /> -->
<regs offset="203" type="s16">3</regs> <!-- 3, # 3 <point id="sunssf_6" offset="131" type="sunssf" /> -->
<regs offset="204" type="s16">4</regs> <!-- 4, # 4 <point id="sunssf_7" offset="132" type="sunssf" /> -->
<regs offset="205" type="s16">-32768</regs> <!-- 0x8000, # 0x8000 <point id="pad_1" offset="133" type="pad" /> -->

<!-- # block type="repeating" len="18" -->
<regs offset="206" type="s16">-2</regs> <!-- 0xfffe, # -2 <point id="sunssf_8" offset="0" type="sunssf" /> -->
<regs offset="207" type="s16">30</regs> <!-- 0x1e, # 30 <point id="int16_11" offset="1" type="int16" sf="sunssf_8" /> -->
<regs offset="208" type="s16">31</regs> <!-- 0x1f, # 31 <point id="int16_12" offset="2" type="int16" sf="sunssf_9" /> -->
<regs offset="209" type="s16">-32768</regs> <!-- 0x8000, # 0x8000 <point id="int16_u" offset="3" type="int16" /> -->
<regs offset="210" type="u16">32</regs> <!-- 0x20, # 32 <point id="uint16_11" offset="4" type="uint16" sf="sunssf_8" /> -->
<regs offset="211" type="u16">33</regs> <!-- 0x21, # 33 <point id="uint16_12" offset="5" type="uint16" sf="sunssf_9" /> -->
<regs offset="212" type="u16">34</regs> <!-- 0x22, # 34 <point id="uint16_13" offset="6" type="uint16" /> -->
<regs offset="213" type="u16">0xffff</regs> <!-- 0xffff, # 0xffff <point id="uint16_u" offset="7" type="uint16" /> -->
<regs offset="214" type="s32">35</regs> <!-- 0, 0x23, # 35 <point id="int32" offset="8" type="int32" sf="sunssf_1" /> -->
<regs offset="216" type="s32">-2147483648</regs> <!-- 0x8000, 0, # 0x80000000 <point id="int32_u" offset="10" type="int32" /> -->
<regs offset="218" type="u32">36</regs> <!-- 0, 0x24, # 36 <point id="uint32" offset="12" type="uint32" sf="sunssf_9" /> -->
<regs offset="220" type="u32">0xffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="uint32_u" offset="14" type="uint32" /> -->
<regs offset="222" type="s16">-3</regs> <!-- 0xfffd, # -3 <point id="sunssf_9" offset="16" type="sunssf" /> -->
<regs offset="223" type="u16">0x8000</regs> <!-- 0x8000, # 0x8000 <point id="pad_2" offset="17" type="pad" /> -->

<!-- # block type="repeating" len="18" -->
<regs offset="224" type="s16">-4</regs> <!-- 0xfffc, # -4 <point id="sunssf_8" offset="0" type="sunssf" /> -->
<regs offset="225" type="s16">40</regs> <!-- 0x28, # 40 <point id="int16_11" offset="1" type="int16" sf="sunssf_8" /> -->
<regs offset="226" type="s16">41</regs> <!-- 0x29, # 41 <point id="int16_12" offset="2" type="int16" sf="sunssf_9" /> -->
<regs offset="227" type="s16">-32768</regs> <!-- 0x8000, # 0x8000 <point id="int16_u" offset="3" type="int16" /> -->
<regs offset="228" type="u16">42</regs> <!-- 0x2a, # 42 <point id="uint16_11" offset="4" type="uint16" sf="sunssf_8" /> -->
<regs offset="229" type="u16">43</regs> <!-- 0x2b, # 43 <point id="uint16_12" offset="5" type="uint16" sf="sunssf_9" /> -->
<regs offset="230" type="u16">44</regs> <!-- 0x2c, # 44 <point id="uint16_13" offset="6" type="uint16" /> -->
<regs offset="231" type="u16">0xffff</regs> <!-- 0xffff, # 0xffff <point id="uint16_u" offset="7" type="uint16" /> -->
<regs offset="232" type="s32">45</regs> <!-- 0, 0x2d, # 45 <point id="int32" offset="8" type="int32" sf="sunssf_1" /> -->
<regs offset="234" type="s32">-2147483648</regs> <!-- 0x8000, 0, # 0x80000000 <point id="int32_u" offset="10" type="int32" /> -->
<regs offset="236" type="u32">46</regs> <!-- 0, 0x2e, # 46 <point id="uint32" offset="12" type="uint32" sf="sunssf_9" /> -->
<regs offset="238" type="u32">0xffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="uint32_u" offset="14" type="uint32" /> -->
<regs offset="240" type="s16">-5</regs> <!-- 0xfffb, # -5 <point id="sunssf_9" offset="16" type="sunssf" /> -->
<regs offset="241" type="u16">0x8000</regs> <!-- 0x8000, # 0x8000 <point id="pad_2" offset="17" type="pad" /> -->

<!-- # block type="repeating" len="18" -->
<regs offset="242" type="s16">2</regs> <!-- 2, # 2 <point id="sunssf_8" offset="0" type="sunssf" /> -->
<regs offset="243" type="s16">50</regs> <!-- 0x32, # 50 <point id="int16_11" offset="1" type="int16" sf="sunssf_8" /> -->
<regs offset="244" type="s16">51</regs> <!-- 0x33, # 51 <point id="int16_12" offset="2" type="int16" sf="sunssf_9" /> -->
<regs offset="245" type="s16">-32768</regs> <!-- 0x8000, # 0x8000 <point id="int16_u" offset="3" type="int16" /> -->
<regs offset="246" type="u16">52</regs> <!-- 0x34, # 52 <point id="uint16_11" offset="4" type="uint16" sf="sunssf_8" /> -->
<regs offset="247" type="u16">53</regs> <!-- 0x35, # 53 <point id="uint16_12" offset="5" type="uint16" sf="sunssf_9" /> -->
<regs offset="248" type="u16">54</regs> <!-- 0x36, # 54 <point id="uint16_13" offset="6" type="uint16" /> -->
<regs offset="249" type="u16">0xffff</regs> <!-- 0xffff, # 0xffff <point id="uint16_u" offset="7" type="uint16" /> -->
<regs offset="250" type="s32">55</regs> <!-- 0, 0x37, # 55 <point id="int32" offset="8" type="int32" sf="sunssf_1" /> -->
<regs offset="252" type="s32">-2147483648</regs> <!-- 0x8000, 0, # 0x80000000 <point id="int32_u" offset="10" type="int32" /> -->
<regs offset="254" type="u32">56</regs> <!-- 0, 0x38, # 56 <point id="uint32" offset="12" type="uint32" sf="sunssf_9" /> -->
<regs offset="256" type="u32">0xffffffff</regs> <!-- 0xffff, 0xffff, # 0xffffffff <point id="uint32_u" offset="14" type="uint32" /> -->
<regs offset="258" type="s16">3</regs> <!-- 3, # 3 <point id="sunssf_9" offset="16" type="sunssf" /> -->
<regs offset="259" type="u16">0xffff</regs> <!-- 0x8000, # 0x8000 <point id="pad_2" offset="17" type="pad" /> -->

<regs offset="260" type="u16">0xffff</regs> <!-- 0xffff, 0x0000 -->
<regs offset="261" type="u16">0</regs>
</mbmap>

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mbmap addr="40000" func="holding"><regs len="262" offset="0">53756e530001004253756e5370656354657374000000000000000000000000000000000000000000546573744465766963652d3100000000000000000000000000000000000000006f70745f615f625f6300000000000000312e322e330000000000000000000000736e2d313233343536373839000000000000000000000000000000000000000000010000f61900bcfff6000a000000010001ffff0002fffe0003800000040005fff400060007ffff000800000009ffff000affff0000000b0000000c0000000d0000000e0000000f800000000000001000000011000000120000001300000014ffffffff000000150000000000000016ffffffff00000017ffffffff01020304000000000000000000000018800000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000000000000000000000041d000007fc00000313233343536373800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000300048000fffe001e001f8000002000210022ffff000000238000000000000024fffffffffffd8000fffc002800298000002a002b002cffff0000002d800000000000002efffffffffffb80000002003200338000003400350036ffff000000378000000000000038ffffffff0003ffffffff0000</regs></mbmap>
30 changes: 30 additions & 0 deletions sunspec/core/test/test_modbus_mbmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -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__":

Expand Down

0 comments on commit fcf5135

Please sign in to comment.