diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index 2b54d3c7d2..69403d20ff 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -1029,6 +1029,10 @@ def process_system_topic(self, msg: mqtt.MQTTMessage): elif "io" in msg.topic: if "/config" in msg.topic: self._validate_value(msg, "json") + elif "/set/manual/analog_output" in msg.topic: + self._validate_value(msg, float) + elif "/set/manual/digital_output" in msg.topic: + self._validate_value(msg, bool) else: # hier kommen auch noch alte Topics ohne json-Format an. # log.error("Unbekanntes set-Topic: "+str(msg.topic)+", "+ diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index cb26297c36..fa58ead9f3 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -980,6 +980,12 @@ def process_system_topic(self, client: mqtt.Client, var: dict, msg: mqtt.MQTTMes "modules") config = dataclass_from_dict(dev.device_descriptor.configuration_factory, io_config) var["io"+index] = dev.create_io(config) + elif re.search("^.+/io/[0-9]+/set/manual/analog_output", msg.topic) is not None: + index = get_index(msg.topic) + self.set_json_payload(var["io"+index].set_manual["analog_output"], msg) + elif re.search("^.+/io/[0-9]+/set/manual/digital_output", msg.topic) is not None: + index = get_index(msg.topic) + self.set_json_payload(var["io"+index].set_manual["digital_output"], msg) else: if "module_update_completed" in msg.topic: self.event_module_update_completed.set() diff --git a/packages/modules/common/configurable_io.py b/packages/modules/common/configurable_io.py index 6e450bd9f0..fe1f2563f0 100644 --- a/packages/modules/common/configurable_io.py +++ b/packages/modules/common/configurable_io.py @@ -1,5 +1,7 @@ +import logging from typing import Dict, Optional, TypeVar, Generic, Callable, Union +from helpermodules.pub import Pub from modules.common import store from modules.common.abstract_io import AbstractIoDevice from modules.common.component_context import SingleComponentUpdateContext @@ -9,6 +11,7 @@ T_IO_CONFIG = TypeVar("T_IO_CONFIG") +log = logging.getLogger(__name__) class ConfigurableIo(Generic[T_IO_CONFIG], AbstractIoDevice): @@ -20,6 +23,7 @@ def __init__(self, self.fault_state = FaultState(ComponentInfo(self.config.id, self.config.name, ComponentType.IO.value)) self.store = store.get_io_value_store(self.config.id) + self.set_manual: Dict = {"analog_output": {}, "digital_output": {}} with SingleComponentUpdateContext(self.fault_state): self.component_reader = component_reader self.component_writer = component_writer @@ -28,12 +32,24 @@ def read(self): if hasattr(self, "component_reader"): # Wenn beim Initialisieren etwas schief gelaufen ist, ursprüngliche Fehlermeldung beibehalten with SingleComponentUpdateContext(self.fault_state): - self.store.set(self.component_reader()) + io_state = self.component_reader() + self.store.set(io_state) + + def update_manual_output(self, manual: Dict[str, bool], output: Dict[str, bool], string: str, topic_suffix: str): + if len(manual) > 0: + log.debug(f"Manuell gesetzte {string} Ausgänge: {manual}") + for manual_out_pin, manual_out_value in manual.items(): + output[manual_out_pin] = manual_out_value + # nur die in diesem Zyklus gesetzten manuellen Ausgänge setzen, für nächsten Zyklus zurücksetzen + Pub().pub(f"openWB/set/io/{self.config.id}/set/manual/{topic_suffix}/{manual_out_pin}", "") def write(self, analog_output, digital_output): if hasattr(self, "component_writer"): # Wenn beim Initialisieren etwas schief gelaufen ist, ursprüngliche Fehlermeldung beibehalten with SingleComponentUpdateContext(self.fault_state): + self.update_manual_output(self.set_manual["analog_output"], analog_output, "analoge", "analog_output") + self.update_manual_output(self.set_manual["digital_output"], + digital_output, "digitale", "digital_output") if ((analog_output and self.store.delegate.state.analog_output != analog_output) or (digital_output and self.store.delegate.state.digital_output != digital_output)): io_state = self.component_writer(analog_output, digital_output)