Open jbm950 opened 7 years ago
I'll try and take a look at this tomorrow but I'll mention that there is some general trouble with too many layers involved in constructing. We end up having to add pass through parameters to several layers to get at the serial object. I recently got a request for a couple more. This also plays into using the faux enumerations to select the type of connection. This is much less needed in Python since we can comfortably pass around classes and callables. I know this is vague but perhaps you have already noticed this. I should probably just implement the extra serial options as an example.
I was talking to Bob about this yesterday and we felt I was not familiar enough with modbus and there may not have been enough benefit for me to work on this.
I barely know modbus and I made a working twisted version... 1) it's often about programming as much as topic. 2) even more duplication that needs to be tamed. Let alone when someone wants a twisted tcp option. But, I would get py3 integrated first. Notice a theme in my priority? :]
How about extracting all the uncommon in functions and then implementing them in the child classes? This is really quick and dirty but gives an idea. Some functionality changed and may not be acceptable, but the original code needs to be tidied anyways, probably before attempting to extract a base class.
def _read(self, addr, count, op=FUNC_READ_HOLDING):
resp = ''
len_remaining = self.initial_read_length()
len_found = False
except_code = None
req = self.pack(op, addr, count)
self.trace('->', req)
self.flush_input()
try:
self.transport_write(req)
except Exception, e:
raise ModbusClientError('%s write error: %s' % (self.type_string, str(e)))
while len_remaining > 0:
c = self.transport_read(len_remaining)
len_read = len(c)
if len_read > 0:
resp += c
len_remaining -= len_read
if len_found is False and len(resp) >= self.initial_read_length():
len_remaining, len_found, except_code = self.len_remaining(resp, len_remaining, len_found, except_code)
else:
raise ModbusClientTimeout('Response timeout')
self.trace('<--', resp)
self.check_result(resp)
return self.data_from_response(resp)
def trace(direction, data)
if self.trace_func:
s = '%s:%s[addr=%s] %s' % (self.trace_identifier(), str(self.slave_id), addr, direction)
for c in data:
s += '%02X' % (ord(c))
self.trace_func(s)
There are similar _methods in the
ModbusClientRTU
andModbusClientDeviceTCP
classes and so I thought I would do a comparison of the _read method to see if there's interest in creating something along the lines of aModbusClientBase
class. Below is a pseudo code draft of how such a class might look.The ModbusClientRTU._read method can be found at here and the ModbusClientDeviceTCP._read method can be found here.
Pros:
Cons: