discrete input

This commit is contained in:
2019-07-08 16:07:26 +02:00
parent 1a1ba21c45
commit 3024cadb5d
3 changed files with 79 additions and 2 deletions

View File

@ -149,6 +149,42 @@ class CmdInterpreter(cmd.Cmd):
self.__println("<ScanRate> Scanrate in seconds (float)") self.__println("<ScanRate> Scanrate in seconds (float)")
self.__println("<ReadTopic> Topic to publish read data") self.__println("<ReadTopic> Topic to publish read data")
def do_add_di(self, arg):
try:
(label, unit, address, count, scanrate, readTopic) = self.splitterRe.split(arg)
self.__println("Label: {0}".format(label))
self.__println("Unit: {0}".format(unit))
self.__println("Address: {0}".format(address))
self.__println("Count: {0}".format(count))
self.__println("ScanRate: {0}".format(scanrate))
self.__println("ReadTopic: {0}".format(readTopic))
if readTopic == 'None':
readTopic = None
unit = parseIntArbitraryBase(unit)
address = parseIntArbitraryBase(address)
count = parseIntArbitraryBase(count)
scanrate = float(scanrate)
if scanrate == 0.0:
raise CmdInterpreterException('scanRate must not be zero')
r = RegisterDatapoint.DiscreteInputDatapoint(label, unit, address, count, datetime.timedelta(seconds=scanrate), readTopic)
self.registers.append(r)
except ValueError as e:
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
def help_add_di(self):
self.__println("Usage: add <Label> <Unit> <Address> <Count> <ScanRate>")
self.__println(" <ReadTopic>")
self.__println("Adds a discrete input")
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
self.__println("---------------------------------------------------------------------")
self.__println("<Label> Descriptive label")
self.__println("<Unit> Modbus address of the device")
self.__println("<Address> Register address within the device")
self.__println("<Count> Count of registers to be read in words")
self.__println("<ScanRate> Scanrate in seconds (float)")
self.__println("<ReadTopic> Topic to publish read data")
def do_list(self, arg): def do_list(self, arg):
for i, r in enumerate(self.registers): for i, r in enumerate(self.registers):
self.__println("#{0}: {1!s}".format(i, r)) self.__println("#{0}: {1!s}".format(i, r))

View File

@ -21,7 +21,12 @@ class AbstractModbusDatapoint(object):
self.priority = 0 self.priority = 0
def __str__(self): def __str__(self):
return "{0}, {1}: Unit: {2}, Address: {3}, Count: {4}".format(self.type, self.label, self.unit, self.address, self.count) return "{0}, {1}: Unit: {2}, Address: {3}, Count: {4}, Scanrate: {5}".format(self.type,
self.label,
self.unit,
self.address,
self.count,
self.scanRate)
def process(self, client): def process(self, client):
raise NotImplementedError raise NotImplementedError
@ -100,7 +105,7 @@ class InputRegisterDatapoint(AbstractModbusDatapoint):
unit=self.unit) unit=self.unit)
if type(result) in [ExceptionResponse, ModbusIOException]: if type(result) in [ExceptionResponse, ModbusIOException]:
raise DatapointException(result) raise DatapointException(result)
print("{0}: {1!s}".format(self.label, result.registers)) # print("{0}: {1!s}".format(self.label, result.registers))
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(result.registers))) pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(result.registers)))
if successFull: if successFull:
@ -114,6 +119,41 @@ class InputRegisterDatapoint(AbstractModbusDatapoint):
pass pass
class DiscreteInputDatapoint(AbstractModbusDatapoint):
def __init__(self, label, unit, address, count, scanRate, publishTopic):
super().__init__(label, unit, address, count, scanRate)
self.publishTopic = publishTopic
self.lastContact = None
self.type = 'discrete input'
def __str__(self):
return "[{0!s}, {1}".format(super().__str__(), self.publishTopic)
def process(self, client, pubQueue):
successFull = True
giveUp = False
# perform read operation
# print("Discrete input, perform read operation")
result = client.read_discrete_inputs(address=self.address,
count=self.count,
unit=self.unit)
if type(result) in [ExceptionResponse, ModbusIOException]:
raise DatapointException(result)
# print("{0}: {1!s}".format(self.label, result.bits))
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(result.bits)))
if successFull:
self.lastContact = datetime.datetime.now()
# publish value
else:
# retries handling
if giveUp:
# backoff and availability handling
# give negative feedback
pass
def checkRegisterList(registers): def checkRegisterList(registers):
for r in registers: for r in registers:
if not isinstance(r, AbstractModbusDatapoint): if not isinstance(r, AbstractModbusDatapoint):

View File

@ -6,6 +6,7 @@ import pickle
datapoints = [ datapoints = [
RegisterDatapoint.InputRegisterDatapoint('Temperature', 5, 0x0001, 1, datetime.timedelta(seconds=0.2), 'Pub/Temperature'), RegisterDatapoint.InputRegisterDatapoint('Temperature', 5, 0x0001, 1, datetime.timedelta(seconds=0.2), 'Pub/Temperature'),
RegisterDatapoint.InputRegisterDatapoint('Humidity', 5, 0x0002, 1, datetime.timedelta(seconds=0.2), 'Pub/Humidity'), RegisterDatapoint.InputRegisterDatapoint('Humidity', 5, 0x0002, 1, datetime.timedelta(seconds=0.2), 'Pub/Humidity'),
RegisterDatapoint.DiscreteInputDatapoint('Switches', 4, 0x0000, 1, datetime.timedelta(seconds=0.2), 'Pub/Switches'),
] ]