Skip to content

Commit d159a44

Browse files
chintaldhoomakethu
authored andcommitted
Fix device information selectors (#295)
* Fix device information selectors * Fixed behaviour of the MEI device information command as a server when an invalid object_id is provided by an external client.
1 parent 65e4a09 commit d159a44

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

pymodbus/device.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def __init__(self, info=None):
220220
'''
221221
if isinstance(info, dict):
222222
for key in info:
223-
if (0x06 >= key >= 0x00) or (0x80 > key > 0x08):
223+
if (0x06 >= key >= 0x00) or (0xFF >= key >= 0x80):
224224
self.__data[key] = info[key]
225225

226226
def __iter__(self):
@@ -287,10 +287,14 @@ class DeviceInformationFactory(Singleton):
287287
'''
288288

289289
__lookup = {
290-
DeviceInformation.Basic: lambda c,r,i: c.__gets(r, list(range(0x00, 0x03))),
291-
DeviceInformation.Regular: lambda c,r,i: c.__gets(r, list(range(0x00, 0x08))),
292-
DeviceInformation.Extended: lambda c,r,i: c.__gets(r, list(range(0x80, i))),
293-
DeviceInformation.Specific: lambda c,r,i: c.__get(r, i),
290+
DeviceInformation.Basic: lambda c, r, i: c.__gets(r, list(range(i, 0x03))),
291+
DeviceInformation.Regular: lambda c, r, i: c.__gets(r, list(range(i, 0x07))
292+
if c.__get(r, i)[i] else list(range(0, 0x07))),
293+
DeviceInformation.Extended: lambda c, r, i: c.__gets(r,
294+
[x for x in range(i, 0x100) if x not in range(0x07, 0x80)]
295+
if c.__get(r, i)[i] else
296+
[x for x in range(0, 0x100) if x not in range(0x07, 0x80)]),
297+
DeviceInformation.Specific: lambda c, r, i: c.__get(r, i),
294298
}
295299

296300
@classmethod
@@ -323,7 +327,7 @@ def __gets(cls, identity, object_ids):
323327
:param object_ids: The specific object ids to read
324328
:returns: The requested data (id, length, value)
325329
'''
326-
return dict((oid, identity[oid]) for oid in object_ids)
330+
return dict((oid, identity[oid]) for oid in object_ids if identity[oid])
327331

328332

329333
#---------------------------------------------------------------------------#

test/test_device.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ def setUp(self):
2727
0x06: 'unittest', # UserApplicationName
2828
0x07: 'x', # reserved
2929
0x08: 'x', # reserved
30-
0x10: 'private' # private data
30+
0x10: 'reserved', # reserved
31+
0x80: 'custom1', # device specific start
32+
0x82: 'custom2', # device specific
33+
0xFF: 'customlast', # device specific last
3134
}
3235
self.ident = ModbusDeviceIdentification(self.info)
3336
self.control = ModbusControlBlock()
@@ -71,6 +74,30 @@ def testDeviceInformationFactory(self):
7174
self.assertEqual(result[0x05], 'bashwork')
7275
self.assertEqual(result[0x06], 'unittest')
7376

77+
def testDeviceInformationFactoryLookup(self):
78+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Basic, 0x00)
79+
self.assertEqual(sorted(result.keys()), [0x00, 0x01, 0x02])
80+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Basic, 0x02)
81+
self.assertEqual(sorted(result.keys()), [0x02])
82+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Regular, 0x00)
83+
self.assertEqual(sorted(result.keys()), [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
84+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Regular, 0x01)
85+
self.assertEqual(sorted(result.keys()), [0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
86+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Regular, 0x05)
87+
self.assertEqual(sorted(result.keys()), [0x05, 0x06])
88+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x00)
89+
self.assertEqual(sorted(result.keys()), [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x80, 0x82, 0xFF])
90+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x02)
91+
self.assertEqual(sorted(result.keys()), [0x02, 0x03, 0x04, 0x05, 0x06, 0x80, 0x82, 0xFF])
92+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x06)
93+
self.assertEqual(sorted(result.keys()), [0x06, 0x80, 0x82, 0xFF])
94+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x80)
95+
self.assertEqual(sorted(result.keys()), [0x80, 0x82, 0xFF])
96+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x82)
97+
self.assertEqual(sorted(result.keys()), [0x82, 0xFF])
98+
result = DeviceInformationFactory.get(self.control, DeviceInformation.Extended, 0x81)
99+
self.assertEqual(sorted(result.keys()), [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x80, 0x82, 0xFF])
100+
74101
def testBasicCommands(self):
75102
''' Test device identification reading '''
76103
self.assertEqual(str(self.ident), "DeviceIdentity")
@@ -87,13 +114,13 @@ def testModbusDeviceIdentificationGet(self):
87114
self.assertEqual(self.ident[0x06], 'unittest')
88115
self.assertNotEqual(self.ident[0x07], 'x')
89116
self.assertNotEqual(self.ident[0x08], 'x')
90-
self.assertEqual(self.ident[0x10], 'private')
117+
self.assertNotEqual(self.ident[0x10], 'reserved')
91118
self.assertEqual(self.ident[0x54], '')
92119

93120
def testModbusDeviceIdentificationSummary(self):
94121
''' Test device identification summary creation '''
95122
summary = sorted(self.ident.summary().values())
96-
expected = sorted(list(self.info.values())[:-3]) # remove private
123+
expected = sorted(list(self.info.values())[:0x07]) # remove private
97124
self.assertEqual(summary, expected)
98125

99126
def testModbusDeviceIdentificationSet(self):

0 commit comments

Comments
 (0)