Skip to content

Commit 1564f00

Browse files
committed
Merge branch 'dev' into 3.0.0
2 parents 88ff6b0 + 93fc0fb commit 1564f00

File tree

6 files changed

+63
-10
lines changed

6 files changed

+63
-10
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ PyModbus - A Python Modbus Stack
2020
Summary
2121
------------------------------------------------------------
2222

23-
Pymodbus is a full Modbus protocol implementation using twisted/torndo/asyncio for its
23+
Pymodbus is a full Modbus protocol implementation using twisted/tornado/asyncio for its
2424
asynchronous communications core. It can also be used without any third
2525
party dependencies (aside from pyserial) if a more lightweight project is
2626
needed. Furthermore, it should work fine under any python version > 2.7

pymodbus/client/sync.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,11 @@ def _recv(self, size):
291291
time_ = time.time()
292292
end = time_ + timeout
293293
while recv_size > 0:
294-
ready = select.select([self.socket], [], [], end - time_)
294+
try:
295+
ready = select.select([self.socket], [], [], end - time_)
296+
except ValueError:
297+
return self._handle_abrupt_socket_close(
298+
size, data, time.time() - time_)
295299
if ready[0]:
296300
recv_data = self.socket.recv(recv_size)
297301
if recv_data == b'':

pymodbus/other_message.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,16 @@ def execute(self, context=None):
369369
reportSlaveIdData = getattr(context, 'reportSlaveIdData', None)
370370
if not reportSlaveIdData:
371371
information = DeviceInformationFactory.get(_MCB)
372-
identifier = "-".join(information.values()).encode()
372+
373+
# Support identity values as bytes data and regular str data
374+
id_data = []
375+
for v in information.values():
376+
if isinstance(v, bytes):
377+
id_data.append(v)
378+
else:
379+
id_data.append(v.encode())
380+
381+
identifier = b"-".join(id_data)
373382
identifier = identifier or b'Pymodbus'
374383
reportSlaveIdData = identifier
375384
return ReportSlaveIdResponse(reportSlaveIdData)

pymodbus/repl/client/mclient.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def mask_write_register(self, address=0x0000,
270270
:param unit: The slave unit this request is targeting
271271
:return:
272272
"""
273-
resp = super(ExtendedRequestSupport, self).read_input_registers(
273+
resp = super(ExtendedRequestSupport, self).mask_write_register(
274274
address=address, and_mask=and_mask, or_mask=or_mask, **kwargs)
275275
if not resp.isError():
276276
return {

pymodbus/server/sync.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ def __init__(self, context, framer=None, identity=None, **kwargs):
536536
self.socket = None
537537
if self._connect():
538538
self.is_running = True
539-
self._build_handler()
539+
self._build_handler(kwargs.get('handler',
540+
CustomSingleRequestHandler))
540541

541542
def _connect(self):
542543
""" Connect to the serial server
@@ -555,19 +556,19 @@ def _connect(self):
555556
_logger.error(msg)
556557
return self.socket is not None
557558

558-
def _build_handler(self):
559+
def _build_handler(self, handler):
559560
""" A helper method to create and monkeypatch
560561
a serial handler.
562+
:param handler: a custom handler, uses ModbusSingleRequestHandler if set to None
561563
562564
:returns: A patched handler
563565
"""
564-
565566
request = self.socket
566567
request.send = request.write
567568
request.recv = request.read
568-
self.handler = CustomSingleRequestHandler(request,
569-
(self.device, self.device),
570-
self)
569+
self.handler = handler(request,
570+
(self.device, self.device),
571+
self)
571572

572573
def serve_forever(self):
573574
""" Callback for connecting a new client thread

test/test_other_messages.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,45 @@ def testGetCommEventLogWithEvents(self):
8787
self.assertEqual(response.event_count, 0x12)
8888
self.assertEqual(response.events, [0x12,0x34,0x56])
8989

90+
def testReportSlaveIdRequest(self):
91+
with mock.patch("pymodbus.other_message.DeviceInformationFactory") as dif:
92+
# First test regular identity strings
93+
identity = {
94+
0x00: 'VN', # VendorName
95+
0x01: 'PC', # ProductCode
96+
0x02: 'REV', # MajorMinorRevision
97+
0x03: 'VU', # VendorUrl
98+
0x04: 'PN', # ProductName
99+
0x05: 'MN', # ModelName
100+
0x06: 'UAN', # UserApplicationName
101+
0x07: 'RA', # reserved
102+
0x08: 'RB', # reserved
103+
}
104+
dif.get.return_value = identity
105+
expected_identity = "-".join(identity.values()).encode()
106+
107+
request = ReportSlaveIdRequest()
108+
response = request.execute()
109+
self.assertEqual(response.identifier, expected_identity)
110+
111+
# Change to byte strings and test again (final result should be the same)
112+
identity = {
113+
0x00: b'VN', # VendorName
114+
0x01: b'PC', # ProductCode
115+
0x02: b'REV', # MajorMinorRevision
116+
0x03: b'VU', # VendorUrl
117+
0x04: b'PN', # ProductName
118+
0x05: b'MN', # ModelName
119+
0x06: b'UAN', # UserApplicationName
120+
0x07: b'RA', # reserved
121+
0x08: b'RB', # reserved
122+
}
123+
dif.get.return_value = identity
124+
125+
request = ReportSlaveIdRequest()
126+
response = request.execute()
127+
self.assertEqual(response.identifier, expected_identity)
128+
90129
def testReportSlaveId(self):
91130
with mock.patch("pymodbus.other_message.DeviceInformationFactory") as dif:
92131
dif.get.return_value = dict()

0 commit comments

Comments
 (0)