Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
532b5b7211
|
|||
|
25f6a1f43f
|
|||
|
a5f9527f4d
|
|||
|
08c1faf606
|
|||
|
00afad4a3d
|
|||
|
086c240638
|
@@ -4,21 +4,21 @@ steps:
|
|||||||
settings:
|
settings:
|
||||||
repo: gitea.hottis.de/wn/digitaltwin1
|
repo: gitea.hottis.de/wn/digitaltwin1
|
||||||
registry:
|
registry:
|
||||||
from_secret: container_registry
|
from_secret: local_registry
|
||||||
tags: latest,${CI_COMMIT_SHA},${CI_COMMIT_TAG}
|
tags: latest,${CI_COMMIT_TAG}
|
||||||
username:
|
username:
|
||||||
from_secret: container_registry_username
|
from_secret: local_username
|
||||||
password:
|
password:
|
||||||
from_secret: container_registry_password
|
from_secret: local_password
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
when:
|
when:
|
||||||
- event: [push, tag]
|
- event: tag
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
image: portainer/kubectl-shell:latest
|
image: portainer/kubectl-shell:latest
|
||||||
secrets:
|
environment:
|
||||||
- source: kube_config
|
KUBE_CONFIG_CONTENT:
|
||||||
target: KUBE_CONFIG_CONTENT
|
from_secret: kube_config
|
||||||
commands:
|
commands:
|
||||||
- export IMAGE_TAG=$CI_COMMIT_TAG
|
- export IMAGE_TAG=$CI_COMMIT_TAG
|
||||||
- printf "$KUBE_CONFIG_CONTENT" > /tmp/kubeconfig
|
- printf "$KUBE_CONFIG_CONTENT" > /tmp/kubeconfig
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ ARG CONF_DIR="${APP_DIR}/config"
|
|||||||
RUN \
|
RUN \
|
||||||
apt update && \
|
apt update && \
|
||||||
pip3 install loguru && \
|
pip3 install loguru && \
|
||||||
pip3 install pymodbus && \
|
pip3 install pymodbus==3.6.3 && \
|
||||||
pip3 install paho-mqtt
|
pip3 install paho-mqtt
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ data:
|
|||||||
MQTT__BROKER: "emqx01-anonymous-cluster-internal.broker.svc.cluster.local"
|
MQTT__BROKER: "emqx01-anonymous-cluster-internal.broker.svc.cluster.local"
|
||||||
MQTT__DIGITALOUTPUTTOPICPREFIX: "dt1/coil"
|
MQTT__DIGITALOUTPUTTOPICPREFIX: "dt1/coil"
|
||||||
MQTT__DIGITALINPUTTOPICPREFIX: "dt1/di"
|
MQTT__DIGITALINPUTTOPICPREFIX: "dt1/di"
|
||||||
|
MQTT__COILINPUTTOPICPREFIX: "dt1/ci"
|
||||||
MQTT__ANALOGINPUTEVENTTOPICPREFIX: "dt1/ai/event"
|
MQTT__ANALOGINPUTEVENTTOPICPREFIX: "dt1/ai/event"
|
||||||
MQTT__ANALOGINPUTPERIODICTOPICPREFIX: "dt1/ai/periodic"
|
MQTT__ANALOGINPUTPERIODICTOPICPREFIX: "dt1/ai/periodic"
|
||||||
MQTT__ANALOGINPUTPUBLISHPERIOD: "60.0"
|
MQTT__ANALOGINPUTPUBLISHPERIOD: "60.0"
|
||||||
|
|||||||
@@ -39,17 +39,17 @@ class ModbusHandler(threading.Thread):
|
|||||||
|
|
||||||
self.processImage.init(digitalOutputBits, digitalInputBits, analogInputBits)
|
self.processImage.init(digitalOutputBits, digitalInputBits, analogInputBits)
|
||||||
|
|
||||||
reg = client.read_coils(0, digitalOutputBits)
|
|
||||||
if isinstance(reg, ModbusIOException):
|
|
||||||
raise Exception(reg)
|
|
||||||
with self.processImage:
|
|
||||||
self.processImage.setCoils(reg.bits)
|
|
||||||
|
|
||||||
while not self.killBill:
|
while not self.killBill:
|
||||||
try:
|
try:
|
||||||
if not client.is_socket_open():
|
if not client.is_socket_open():
|
||||||
client.connect()
|
client.connect()
|
||||||
|
|
||||||
|
reg = client.read_coils(0, digitalOutputBits)
|
||||||
|
if isinstance(reg, ModbusIOException):
|
||||||
|
raise Exception(reg)
|
||||||
|
readCoils = reg.bits
|
||||||
|
|
||||||
reg = client.read_input_registers(0, analogInputBits // 8)
|
reg = client.read_input_registers(0, analogInputBits // 8)
|
||||||
if isinstance(reg, ModbusIOException):
|
if isinstance(reg, ModbusIOException):
|
||||||
raise Exception(reg)
|
raise Exception(reg)
|
||||||
@@ -64,6 +64,7 @@ class ModbusHandler(threading.Thread):
|
|||||||
with self.processImage:
|
with self.processImage:
|
||||||
self.processImage.setAnalogsInputs(analogInputs)
|
self.processImage.setAnalogsInputs(analogInputs)
|
||||||
self.processImage.setDiscreteInputs(discreteInputs)
|
self.processImage.setDiscreteInputs(discreteInputs)
|
||||||
|
self.processImage.setCoils(readCoils)
|
||||||
if self.processImage.hasPendingInputChanges():
|
if self.processImage.hasPendingInputChanges():
|
||||||
self.processImage.notify()
|
self.processImage.notify()
|
||||||
if self.processImage.hasPendingOutputChanges():
|
if self.processImage.hasPendingOutputChanges():
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class MqttEventPublisher(AbstractMqttPublisher):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
discreteInputChangeset = self.processImage.getChangedDiscreteInputs()
|
discreteInputChangeset = self.processImage.getChangedDiscreteInputs()
|
||||||
|
coilInputChangeset = self.processImage.getChangedCoils()
|
||||||
if not self.disableAnalogInputEventPublishing:
|
if not self.disableAnalogInputEventPublishing:
|
||||||
analogInputChangeset = self.processImage.getChangedAnalogsInputs()
|
analogInputChangeset = self.processImage.getChangedAnalogsInputs()
|
||||||
|
|
||||||
@@ -34,6 +35,15 @@ class MqttEventPublisher(AbstractMqttPublisher):
|
|||||||
str(discreteInputChangeItem[1][0]),
|
str(discreteInputChangeItem[1][0]),
|
||||||
retain=True)
|
retain=True)
|
||||||
|
|
||||||
|
for coilInputChangeItem in coilInputChangeset:
|
||||||
|
logger.debug("Coil input {} changed from {} to {}"
|
||||||
|
.format(coilInputChangeItem[0],
|
||||||
|
coilInputChangeItem[1][1],
|
||||||
|
coilInputChangeItem[1][0]))
|
||||||
|
self.client.publish("{}/{}".format(self.config["coilInputTopicPrefix"], str(coilInputChangeItem[0])),
|
||||||
|
str(coilInputChangeItem[1][0]),
|
||||||
|
retain=True)
|
||||||
|
|
||||||
if not self.disableAnalogInputEventPublishing:
|
if not self.disableAnalogInputEventPublishing:
|
||||||
for analogInputChangeItem in analogInputChangeset:
|
for analogInputChangeItem in analogInputChangeset:
|
||||||
logger.debug("Analog input {} changed from {} to {}"
|
logger.debug("Analog input {} changed from {} to {}"
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ class ProcessImage(Condition):
|
|||||||
self.numCoils = numCoils
|
self.numCoils = numCoils
|
||||||
self.coils = []
|
self.coils = []
|
||||||
self.shadowCoils = [ None ] * numCoils
|
self.shadowCoils = [ None ] * numCoils
|
||||||
|
self.readCoils = [ None ] * numCoils
|
||||||
|
self.readShadowCoils = [ None ] * numCoils
|
||||||
|
|
||||||
self.numDiscreteInputs = numDiscreteInputs
|
self.numDiscreteInputs = numDiscreteInputs
|
||||||
self.discreteInputs = []
|
self.discreteInputs = []
|
||||||
@@ -31,7 +33,7 @@ class ProcessImage(Condition):
|
|||||||
return self.initialized
|
return self.initialized
|
||||||
|
|
||||||
def hasPendingInputChanges(self):
|
def hasPendingInputChanges(self):
|
||||||
return (self.discreteInputs != self.shadowDiscreteInputs) or (self.analogInputs != self.shadowAnalogInputs)
|
return (self.discreteInputs != self.shadowDiscreteInputs) or (self.analogInputs != self.shadowAnalogInputs) or (self.readCoils != self.readShadowCoils)
|
||||||
|
|
||||||
def hasPendingOutputChanges(self):
|
def hasPendingOutputChanges(self):
|
||||||
return self.shadowCoils != self.coils
|
return self.shadowCoils != self.coils
|
||||||
@@ -56,6 +58,8 @@ class ProcessImage(Condition):
|
|||||||
def setCoils(self, coils):
|
def setCoils(self, coils):
|
||||||
if not self.initialized:
|
if not self.initialized:
|
||||||
raise NotInitializedException
|
raise NotInitializedException
|
||||||
|
self.readCoils = coils
|
||||||
|
if self.coils == []:
|
||||||
self.coils = coils
|
self.coils = coils
|
||||||
|
|
||||||
def setCoil(self, coilNum, value):
|
def setCoil(self, coilNum, value):
|
||||||
@@ -64,12 +68,12 @@ class ProcessImage(Condition):
|
|||||||
self.coils[coilNum] = value
|
self.coils[coilNum] = value
|
||||||
self.coilEvent.set()
|
self.coilEvent.set()
|
||||||
|
|
||||||
# def getChangedCoils(self):
|
def getChangedCoils(self):
|
||||||
# if not self.initialized:
|
if not self.initialized:
|
||||||
# raise NotInitializedException
|
raise NotInitializedException
|
||||||
# changedCoils = zippingFilter(self.coils, self.shadowCoils)
|
changedCoils = zippingFilter(self.coils, self.readCoils)
|
||||||
# self.shadowCoils = self.coils
|
self.readShadowCoils = self.coils
|
||||||
# return changedCoils
|
return changedCoils
|
||||||
|
|
||||||
def getCoils(self):
|
def getCoils(self):
|
||||||
if not self.initialized:
|
if not self.initialized:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class Config:
|
|||||||
'mqtt': [ 'broker',
|
'mqtt': [ 'broker',
|
||||||
'digitalOutputTopicPrefix',
|
'digitalOutputTopicPrefix',
|
||||||
'digitalInputTopicPrefix',
|
'digitalInputTopicPrefix',
|
||||||
|
'coilInputTopicPrefix',
|
||||||
'analogInputEventTopicPrefix',
|
'analogInputEventTopicPrefix',
|
||||||
'analogInputPeriodicTopicPrefix',
|
'analogInputPeriodicTopicPrefix',
|
||||||
'analogInputPublishPeriod',
|
'analogInputPublishPeriod',
|
||||||
|
|||||||
Reference in New Issue
Block a user