output working

This commit is contained in:
Wolfgang Hottgenroth 2021-08-23 17:45:59 +02:00
parent 17e5b6b012
commit 882571425b
Signed by: wn
GPG Key ID: 6C1E5E531E0D5D7F
4 changed files with 70 additions and 11 deletions

View File

@ -63,6 +63,7 @@ def modbusHandler(config, processImage):
coils = processImage.getCoils() coils = processImage.getCoils()
if coils: if coils:
logger.debug("write coils to device: {}".format(coils))
reg = client.write_coils(0, coils) reg = client.write_coils(0, coils)
if isinstance(reg, ModbusIOException): if isinstance(reg, ModbusIOException):
raise Exception(reg) raise Exception(reg)

45
src/MqttCoilSubscriber.py Normal file
View File

@ -0,0 +1,45 @@
import paho.mqtt.client as mqtt
import threading
from loguru import logger
from AbstractMqttHandler import AbstractMqttPublisher
from time import sleep
def mqttCoilSubscriberStart(config, processImage):
mqttCoilSubscriberThread = MqttCoilSubscriber(config, processImage)
mqttCoilSubscriberThread.start()
class MqttCoilSubscriber(AbstractMqttPublisher):
def __init__(self, config, processImage):
super().__init__(config, processImage)
def localLoop(self):
while True:
sleep(self.config["analogInputPublishPeriod"])
def onMessage(self, topic, payload):
logger.warning("mqtt message received: {} -> {}".format(topic, str(payload)))
coilNum = topic.split('/')[-1]
try:
coilNum = int(coilNum)
if (coilNum < 0) or (coilNum >= self.processImage.numCoils):
raise ValueError("coilNum too large or negative")
payload = payload.decode("ascii")
if payload.lower() in [ "on", "true", "1" ]:
state = True
elif payload.lower() in [ "off", "false", "0" ]:
state = False
else:
raise ValueError("Invalid payload")
with self.processImage:
self.processImage.setCoil(coilNum, state)
logger.debug("requested to set coil {} to {}".format(coilNum, state))
except ValueError as e:
logger.warning("invavlid topic ({}) or payload ({}) in message, error {}".format(topic, str(payload), e))
def onConnect(self):
logger.info("mqtt connected")
self.client.subscribe("{}/+".format(self.config["digitalOutputTopicPrefix"]))
logger.info("subscribed to coil topic")

View File

@ -1,5 +1,5 @@
from threading import Condition from threading import Condition
from loguru import logger
def zippingFilter(a, b): def zippingFilter(a, b):
return [ x for x in enumerate(zip(a, b)) if x[1][0] != x[1][1] ] return [ x for x in enumerate(zip(a, b)) if x[1][0] != x[1][1] ]
@ -12,12 +12,15 @@ class ProcessImage(Condition):
self.initialized = False self.initialized = False
def init(self, numCoils, numDiscreteInputs, numAnalogInputs): def init(self, numCoils, numDiscreteInputs, numAnalogInputs):
self.numCoils = numCoils
self.coils = [] self.coils = []
self.shadowCoils = [ None ] * numCoils self.shadowCoils = [ None ] * numCoils
self.numDiscreteInputs = numDiscreteInputs
self.discreteInputs = [] self.discreteInputs = []
self.shadowDiscreteInputs = [ None ] * numDiscreteInputs self.shadowDiscreteInputs = [ None ] * numDiscreteInputs
self.numAnalogInputs = numAnalogInputs
self.analogInputs = [] self.analogInputs = []
self.shadowAnalogInputs = [ None ] * (numAnalogInputs // 8) self.shadowAnalogInputs = [ None ] * (numAnalogInputs // 8)
@ -41,29 +44,35 @@ class ProcessImage(Condition):
if not self.initialized: if not self.initialized:
raise NotInitializedException raise NotInitializedException
changedDiscreteInputs = zippingFilter(self.discreteInputs, self.shadowDiscreteInputs) changedDiscreteInputs = zippingFilter(self.discreteInputs, self.shadowDiscreteInputs)
self.shadowDiscreteInputs = self.discreteInputs self.shadowDiscreteInputs = self.discreteInputs[:]
return changedDiscreteInputs return changedDiscreteInputs
def getDiscreteInputs(self): # def getDiscreteInputs(self):
if not self.initialized: # if not self.initialized:
raise NotInitializedException # raise NotInitializedException
return self.discreteInputs # return self.discreteInputs
def setCoils(self, coils): def setCoils(self, coils):
if not self.initialized: if not self.initialized:
raise NotInitializedException raise NotInitializedException
self.coils = coils self.coils = coils
def getChangedCoils(self): def setCoil(self, coilNum, value):
if not self.initialized: if not self.initialized:
raise NotInitializedException raise NotInitializedException
changedCoils = zippingFilter(self.coils, self.shadowCoils) self.coils[coilNum] = value
self.shadowCoils = self.coils
return changedCoils # def getChangedCoils(self):
# if not self.initialized:
# raise NotInitializedException
# changedCoils = zippingFilter(self.coils, self.shadowCoils)
# self.shadowCoils = self.coils
# return changedCoils
def getCoils(self): def getCoils(self):
if not self.initialized: if not self.initialized:
raise NotInitializedException raise NotInitializedException
self.shadowCoils = self.coils[:]
return self.coils return self.coils
def setAnalogsInputs(self, analogInputs): def setAnalogsInputs(self, analogInputs):
@ -75,7 +84,7 @@ class ProcessImage(Condition):
if not self.initialized: if not self.initialized:
raise NotInitializedException raise NotInitializedException
changedAnalogInputs = zippingFilter(self.analogInputs, self.shadowAnalogInputs) changedAnalogInputs = zippingFilter(self.analogInputs, self.shadowAnalogInputs)
self.shadowAnalogInputs = self.analogInputs self.shadowAnalogInputs = self.analogInputs[:]
return changedAnalogInputs return changedAnalogInputs
def getAnalogsInputs(self): def getAnalogsInputs(self):

View File

@ -2,6 +2,7 @@ from ProcessImage import ProcessImage
from ModbusHandler import modbusStart from ModbusHandler import modbusStart
from MqttEventPublisher import mqttEventPublisherStart from MqttEventPublisher import mqttEventPublisherStart
from MqttPeriodPublisher import mqttPeriodPublisherStart from MqttPeriodPublisher import mqttPeriodPublisherStart
from MqttCoilSubscriber import mqttCoilSubscriberStart
import threading import threading
from loguru import logger from loguru import logger
@ -35,5 +36,8 @@ logger.info("MQTT event publisher running")
mqttPeriodPublisherStart(config, processImage) mqttPeriodPublisherStart(config, processImage)
logger.info("MQTT period publisher running") logger.info("MQTT period publisher running")
mqttCoilSubscriberStart(config, processImage)
logger.info("MQTT coil subscriber running")
logger.info("DigitalTwin1 running") logger.info("DigitalTwin1 running")