output working
This commit is contained in:
parent
17e5b6b012
commit
882571425b
@ -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
45
src/MqttCoilSubscriber.py
Normal 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")
|
@ -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):
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user