2019-06-19 21:52:15 +01:00
|
|
|
from pymodbus.client.sync import ModbusSerialClient
|
|
|
|
from pymodbus.pdu import ExceptionResponse
|
2019-06-19 22:47:06 +01:00
|
|
|
from pymodbus.exceptions import ModbusIOException
|
2019-06-19 21:52:15 +01:00
|
|
|
import RS485Ext
|
|
|
|
import struct
|
|
|
|
import time
|
|
|
|
|
|
|
|
def registersToIeeeFloat(i):
|
|
|
|
return struct.unpack('f', bytes(
|
|
|
|
[((x & 0xff00) >> 8) if y else (x & 0x00ff)
|
|
|
|
for x in i[::-1]
|
|
|
|
for y in [False, True]
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)[0]
|
|
|
|
|
|
|
|
def registersToIeeeFloatReverse(i):
|
|
|
|
return struct.unpack('f', bytes(
|
|
|
|
[((x & 0xff00) >> 8) if y else (x & 0x00ff)
|
|
|
|
for x in i
|
|
|
|
for y in [False, True]
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)[0]
|
|
|
|
|
2019-06-19 23:06:48 +02:00
|
|
|
def dataConverter(t, d):
|
|
|
|
if t == 'F':
|
|
|
|
return registersToIeeeFloat(d)
|
|
|
|
elif t == 'RF':
|
|
|
|
return registersToIeeeFloatReverse(d)
|
|
|
|
else:
|
|
|
|
raise Exception("Converter '{0}' is not supported".format(t))
|
|
|
|
|
|
|
|
|
2019-06-19 21:52:15 +01:00
|
|
|
class ModbusException(Exception):
|
|
|
|
def __init__(self, resp):
|
|
|
|
self.msg = str(result)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.msg
|
|
|
|
|
2019-06-19 23:06:48 +02:00
|
|
|
class ModbusRequestDefinition(object):
|
2019-07-07 02:35:40 +02:00
|
|
|
def __init__(self, kind, unit, address, count, converter, label):
|
|
|
|
self.kind = kind
|
2019-06-19 23:06:48 +02:00
|
|
|
self.unit = unit
|
|
|
|
self.address = address
|
|
|
|
self.count = count
|
|
|
|
self.converter = converter
|
|
|
|
self.label = label
|
|
|
|
|
|
|
|
reqs = [
|
2019-07-06 23:27:26 +01:00
|
|
|
# ModbusRequestDefinition(4, 0x2000, 2, 'F', '(ERR) Unavailable device'),
|
|
|
|
# ModbusRequestDefinition(1, 0x2000, 4, 'F', '(ERR) Wrong register size'),
|
|
|
|
# ModbusRequestDefinition(1, 0x2000, 2, 'F', 'Voltage'),
|
|
|
|
# ModbusRequestDefinition(1, 0x2020, 2, 'F', 'Frequency'),
|
|
|
|
# ModbusRequestDefinition(1, 0x2060, 2, 'F', 'Current'),
|
2019-07-08 09:28:33 +01:00
|
|
|
# ModbusRequestDefinition('H', 3, 0x0004, 2, 'RF', 'Resistance Channel 1'),
|
|
|
|
# ModbusRequestDefinition('H', 3, 0x000C, 2, 'RF', 'Temperature Channel 1'),
|
|
|
|
# ModbusRequestDefinition('H', 3, 0x0014, 2, 'RF', 'Resistance Channel 2'),
|
|
|
|
# ModbusRequestDefinition('H', 3, 0x001C, 2, 'RF', 'Temperature Channel 2'),
|
2019-07-07 02:35:40 +02:00
|
|
|
ModbusRequestDefinition('D', 4, 0x0000, 1, '', 'Discrete Input'),
|
2019-07-08 09:28:33 +01:00
|
|
|
ModbusRequestDefinition('I', 5, 0x0001, 1, '', 'Temperature'),
|
|
|
|
ModbusRequestDefinition('I', 5, 0x0002, 1, '', 'Humidity'),
|
2019-06-19 23:06:48 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2019-06-19 22:47:06 +01:00
|
|
|
def getSerial():
|
2019-07-08 09:28:33 +01:00
|
|
|
return RS485Ext.RS485Ext(port='/dev/ttyAMA0', baudrate=9600, stopbits=1,
|
2019-06-19 22:47:06 +01:00
|
|
|
timeout=1)
|
2019-06-19 21:52:15 +01:00
|
|
|
|
|
|
|
client = ModbusSerialClient(method='rtu')
|
2019-06-19 22:47:06 +01:00
|
|
|
client.socket = getSerial()
|
2019-06-19 21:52:15 +01:00
|
|
|
client.connect()
|
|
|
|
|
|
|
|
delay = 0.05
|
2019-07-08 09:28:33 +01:00
|
|
|
period = 0.5
|
2019-06-19 21:52:15 +01:00
|
|
|
|
|
|
|
while True:
|
2019-06-19 23:06:48 +02:00
|
|
|
for req in reqs:
|
|
|
|
try:
|
|
|
|
time.sleep(delay)
|
2019-07-07 02:35:40 +02:00
|
|
|
if req.kind == 'H':
|
|
|
|
# print("Trying to read: {0} {1} {2}".format(req.address, req.count, req.unit))
|
|
|
|
result = client.read_holding_registers(address=req.address,
|
|
|
|
count=req.count,
|
|
|
|
unit=req.unit)
|
|
|
|
if type(result) in [ExceptionResponse, ModbusIOException]:
|
|
|
|
raise ModbusException(result)
|
|
|
|
print("{0}: {1:.2f}".format(req.label,
|
|
|
|
dataConverter(req.converter,
|
|
|
|
result.registers)))
|
|
|
|
elif req.kind == 'D':
|
|
|
|
result = client.read_discrete_inputs(address=req.address,
|
|
|
|
count=req.count,
|
2019-06-19 22:47:06 +01:00
|
|
|
unit=req.unit)
|
2019-07-07 02:35:40 +02:00
|
|
|
if type(result) in [ExceptionResponse, ModbusIOException]:
|
|
|
|
raise ModbusException(result)
|
|
|
|
print("{0}: {1!s}".format(req.label, result.bits))
|
2019-07-08 09:28:33 +01:00
|
|
|
elif req.kind == 'I':
|
|
|
|
result = client.read_input_registers(address=req.address,
|
|
|
|
count=req.count,
|
|
|
|
unit=req.unit)
|
|
|
|
if type(result) in [ExceptionResponse, ModbusIOException]:
|
|
|
|
raise ModbusException(result)
|
|
|
|
print("{0}: {1}".format(req.label, result.registers))
|
2019-06-19 23:06:48 +02:00
|
|
|
except ModbusException as e:
|
2019-06-19 22:47:06 +01:00
|
|
|
print("ERROR when querying '{0}': {1!s}".format(req.label, e))
|
|
|
|
if client.socket is None:
|
|
|
|
print("renew socket")
|
|
|
|
client.socket = getSerial()
|
|
|
|
|
|
|
|
print("-------------")
|
2019-07-06 23:27:26 +01:00
|
|
|
time.sleep(period)
|
2019-06-19 22:47:06 +01:00
|
|
|
|
2019-06-19 21:52:15 +01:00
|
|
|
|
|
|
|
client.close()
|
|
|
|
|