From 50f406570c5631e5a36681e5bbca0393cb2c76ca Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 20 Sep 2018 11:58:04 +0200 Subject: [PATCH] =?UTF-8?q?IOs=20des=20Core=20als=20einzelne=20Werte=20beh?= =?UTF-8?q?andeln=20Topic=20base/get/ioname=20sendet=20den=20angegebenen?= =?UTF-8?q?=20IO=20sofort=20per=20MQTT=20base/got/ioname=20Topic=20base/ge?= =?UTF-8?q?t=20sendet=20Zyklische=20Daten=20sofort=20Funktion=20SaveXMLRPC?= =?UTF-8?q?Server.isAlive=20in=20SaveXMLRPCServer.is=5Falive()=20umbenannt?= =?UTF-8?q?=20MqttServer=20l=C3=A4d=20RevPiModIO=20sofort=20neu=20bei=20re?= =?UTF-8?q?load=5Frevpimodio=20sendinterval=3D0=20deaktiviert=20zyklische?= =?UTF-8?q?=20=C3=9Cbertragung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/mqttserver.html | 7 ++- doc/xrpcserver.html | 8 +-- eric-revpipyload.api | 4 +- revpipyload/mqttserver.py | 125 ++++++++++++++++++++++++++++++------- revpipyload/revpipyload.py | 4 +- revpipyload/xrpcserver.py | 2 +- setup.py | 2 +- stdeb.cfg | 2 +- 8 files changed, 117 insertions(+), 37 deletions(-) diff --git a/doc/mqttserver.html b/doc/mqttserver.html index 37e2e71..43edbd9 100644 --- a/doc/mqttserver.html +++ b/doc/mqttserver.html @@ -101,7 +101,7 @@ Init MqttServer class. Basis-Topic fuer Datenaustausch
sendinterval
-Prozessabbild alle n Sekunden senden +Prozessabbild alle n Sekunden senden / 0 = aus
broker_address
Adresse des MQTT-Servers @@ -130,7 +130,7 @@ Per MQTT auch Outputs schreiben

MqttServer._evt_io

-_evt_io(name, value) +_evt_io(name, value, requested=False)

Sendet Daten aus Events.

@@ -140,6 +140,9 @@ IO-Name
value
IO-Value +
requested
+
+Wenn True, wird 'got' Topic verwendet

diff --git a/doc/xrpcserver.html b/doc/xrpcserver.html index 4364aa4..dd943a0 100644 --- a/doc/xrpcserver.html +++ b/doc/xrpcserver.html @@ -104,7 +104,7 @@ Methods

_dispatch Prueft ACL Level fuer angeforderte Methode. -isAlive +is_alive Prueft ob der XML RPC Server laeuft. register_function @@ -152,10 +152,10 @@ Argumente fuer Methode
Dispatched data
- +

-SaveXMLRPCServer.isAlive

-isAlive() +SaveXMLRPCServer.is_alive +is_alive()

Prueft ob der XML RPC Server laeuft.

diff --git a/eric-revpipyload.api b/eric-revpipyload.api index e05d512..a4952f1 100644 --- a/eric-revpipyload.api +++ b/eric-revpipyload.api @@ -18,7 +18,7 @@ logsystem.PipeLogwriter?1(logfilename) logsystem.__author__?9 logsystem.__copyright__?9 logsystem.__license__?9 -mqttserver.MqttServer._evt_io?5(name, value) +mqttserver.MqttServer._evt_io?5(name, value, requested=False) mqttserver.MqttServer._loadrevpimodio?5() mqttserver.MqttServer._on_connect?5(client, userdata, flags, rc) mqttserver.MqttServer._on_disconnect?5(client, userdata, rc) @@ -149,7 +149,7 @@ revpipyload.shared.ipaclmanager.__version__?9 revpipyload.shared.ipaclmanager.refullmatch?4(regex, string) xrpcserver.SaveXMLRPCRequestHandler.parse_request?4() xrpcserver.SaveXMLRPCServer._dispatch?5(method, params) -xrpcserver.SaveXMLRPCServer.isAlive?4() +xrpcserver.SaveXMLRPCServer.is_alive?4() xrpcserver.SaveXMLRPCServer.register_function?4(acl_level, function, name=None) xrpcserver.SaveXMLRPCServer.start?4() xrpcserver.SaveXMLRPCServer.stop?4() diff --git a/revpipyload/mqttserver.py b/revpipyload/mqttserver.py index 3ce3978..979d1d0 100644 --- a/revpipyload/mqttserver.py +++ b/revpipyload/mqttserver.py @@ -22,7 +22,7 @@ class MqttServer(Thread): """Init MqttServer class. @param basetopic Basis-Topic fuer Datenaustausch - @param sendinterval Prozessabbild alle n Sekunden senden + @param sendinterval Prozessabbild alle n Sekunden senden / 0 = aus @param broker_address Adresse des MQTT-Servers @param port Portnummer des MQTT-Servers @param tls_set TLS fuer Verbindung zum MQTT-Server verwenden @@ -35,9 +35,9 @@ class MqttServer(Thread): """ if not isinstance(basetopic, str): raise ValueError("parameter topic must be ") - if not (isinstance(sendinterval, int) and sendinterval > 0): + if not (isinstance(sendinterval, int) and sendinterval >= 0): raise ValueError( - "parameter sendinterval must be and > 0" + "parameter sendinterval must be and >= 0" ) if not (isinstance(broker_address, str) and broker_address != ""): raise ValueError( @@ -80,9 +80,12 @@ class MqttServer(Thread): # Topics konfigurieren self._mqtt_evt_io = join(basetopic, "event/{0}") + self._mqtt_got_io = join(basetopic, "got/{0}") self._mqtt_io = join(basetopic, "io/{0}") + self._mqtt_ioget = join(basetopic, "get/#") self._mqtt_ioset = join(basetopic, "set/#") self._mqtt_pictory = join(basetopic, "pictory") + self._mqtt_senddata = join(basetopic, "get") self._mqtt_sendpictory = join(basetopic, "needpictory") self._mq = Client(client_id) @@ -96,13 +99,22 @@ class MqttServer(Thread): self._mq.on_connect = self._on_connect self._mq.on_message = self._on_message - def _evt_io(self, name, value): + def _evt_io(self, name, value, requested=False): """Sendet Daten aus Events. + @param name IO-Name - @param value IO-Value""" + @param value IO-Value + @param requested Wenn True, wird 'got' Topic verwendet + + """ + if requested: + topic = self._mqtt_got_io.format(name) + else: + topic = self._mqtt_evt_io.format(name) + if isinstance(value, bytes): value = int.from_bytes(value, "little") - self._mq.publish(self._mqtt_evt_io.format(name), int(value)) + self._mq.publish(topic, int(value)) def _loadrevpimodio(self): """Instantiiert das RevPiModIO Modul. @@ -147,6 +159,26 @@ class MqttServer(Thread): io.reg_event(self._evt_io) self._exported_ios.append(io) + # RevPiLED Ausgang zerlegen und exportieren + if self._rpi.core._ioled.export: + lst_coreio = [ + self._rpi.core.a1green, self._rpi.core.a1red, + self._rpi.core.a2green, self._rpi.core.a2red, + ] + + # Connect-IOs anhängen + if type(self._rpi.core) == revpimodio2.device.Connect: + lst_coreio += [ + self._rpi.core.a3green, self._rpi.core.a3red, + self._rpi.core.wd, + self._rpi.core.x2in, self._rpi.core.x2out, + ] + + # Events registrieren + for io in lst_coreio: + io.reg_event(self._evt_io) + self._exported_ios.append(io) + proginit.logger.debug("created revpimodio2 object") def _on_connect(self, client, userdata, flags, rc): @@ -158,6 +190,8 @@ class MqttServer(Thread): ) else: # Subscribe piCtory Anforderung + client.subscribe(self._mqtt_ioget) + client.subscribe(self._mqtt_senddata) client.subscribe(self._mqtt_sendpictory) if self._write_outputs: client.subscribe(self._mqtt_ioset) @@ -176,12 +210,33 @@ class MqttServer(Thread): # piCtory Konfiguration senden self._send_pictory_conf() + elif msg.topic == self._mqtt_senddata: + # Alle zyklischen Daten senden + self._evt_data.set() + else: lst_topic = msg.topic.split("/") + if len(lst_topic) < 2: + proginit.logger.info( + "wrong topic format - need ./get/ioname or ./set/ioname" + ) + return + + # Aktion und IO auswerten + ioget = lst_topic[-2].lower() == "get" + ioset = lst_topic[-2].lower() == "set" ioname = lst_topic[-1] + coreio = ioname.find(".") != -1 try: - io = self._rpi_write.io[ioname] + # IO holen + if coreio: + coreio = ioname.split(".")[-1] + io = getattr(self._rpi_write.core, coreio) + if not isinstance(io, revpimodio2.io.IOBase): + raise RuntimeError() + else: + io = self._rpi_write.io[ioname] io_needbytes = type(io.value) == bytes except Exception: proginit.logger.error( @@ -189,17 +244,28 @@ class MqttServer(Thread): ) return - # Check Output exists and is an Output - if io.type != revpimodio2.OUT: - proginit.logger.error( - "can not write to inputs with MQTT" - ) - elif not io.export: + # Aktion verarbeiten + if not io.export: proginit.logger.error( "io '{0}' is not marked as export in piCtory for MQTT use" "".format(ioname) ) - else: + + elif ioget: + # Daten je nach IO Type aus Prozessabbild laden + if io.type == revpimodio2.OUT: + io._parentdevice.syncoutputs() + else: + io._parentdevice.readprocimg() + + # Publish Wert von IO + self._evt_io(io.name, io.value, requested=True) + + elif ioset and io.type != revpimodio2.OUT: + proginit.logger.error( + "can not write to inputs with MQTT" + ) + elif ioset: # Convert MQTT Payload to valid Output-Value value = msg.payload.decode("utf8") @@ -241,6 +307,12 @@ class MqttServer(Thread): else: io._parentdevice.writeprocimg() + else: + # Aktion nicht erkennbar + proginit.logger.warning( + "can not see get/set in topic '{0}'".format(msg.topic) + ) + def _send_pictory_conf(self): """Sendet piCtory Konfiguration per MQTT.""" try: @@ -260,6 +332,7 @@ class MqttServer(Thread): def reload_revpimodio(self): """Fuehrt im naechsten Zyklus zum Reload.""" self._reloadmodio = True + self._evt_data.set() def run(self): """Startet die Uebertragung per MQTT.""" @@ -280,6 +353,7 @@ class MqttServer(Thread): self._rpi.mainloop(blocking=False) # mainloop + send_cycledata = self._sendinterval > 0 while not self.__exit: self._evt_data.clear() @@ -291,18 +365,21 @@ class MqttServer(Thread): if self._send_events: self._rpi.mainloop(blocking=False) - # Werte laden, wenn nicht autorefresh - if not self._send_events: - self._rpi.readprocimg() + if send_cycledata: + # Werte laden, wenn nicht autorefresh + if not self._send_events: + self._rpi.readprocimg() - # Exportierte IOs übertragen - for io in self._exported_ios: - value = io.value - if isinstance(value, bytes): - value = int.from_bytes(value, "little") - self._mq.publish(self._mqtt_io.format(io.name), int(value)) + # Exportierte IOs übertragen + for io in self._exported_ios: + value = io.value + if isinstance(value, bytes): + value = int.from_bytes(value, "little") + self._mq.publish(self._mqtt_io.format(io.name), int(value)) - self._evt_data.wait(self._sendinterval) + self._evt_data.wait( + 10 if not send_cycledata else self._sendinterval + ) # MQTT trennen self._mq.loop_stop() diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py index 58fdd5c..6b0c6d0 100755 --- a/revpipyload/revpipyload.py +++ b/revpipyload/revpipyload.py @@ -387,7 +387,7 @@ class RevPiPyLoad(): self.xml_ps = None proginit.logger.warning( "can not load revpimodio2 module. maybe its not installed " - "or an old version (required at least 2.2.3). if you " + "or an old version (required at least 2.2.4). if you " "like to use the process monitor feature, update/install " "revpimodio2: 'apt-get install python3-revpimodio2'" ) @@ -453,7 +453,7 @@ class RevPiPyLoad(): except Exception: proginit.logger.warning( "can not load revpimodio2 module. maybe its not installed " - "or an old version (required at least 2.2.3). if you " + "or an old version (required at least 2.2.4). if you " "like to use the mqtt feature, update/install " "revpimodio2: 'apt-get install python3-revpimodio2'" ) diff --git a/revpipyload/xrpcserver.py b/revpipyload/xrpcserver.py index d318d68..bde8fde 100644 --- a/revpipyload/xrpcserver.py +++ b/revpipyload/xrpcserver.py @@ -62,7 +62,7 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): return super()._dispatch(method, params) - def isAlive(self): + def is_alive(self): """Prueft ob der XML RPC Server laeuft. @return True, wenn Server noch laeuft""" return False if self.fut is None else self.fut.running() diff --git a/setup.py b/setup.py index f7ad38a..5f8b64a 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ setup( scripts=["data/revpipyload"], - install_requires=["revpimodio2 >= 2.2.3"], + install_requires=["revpimodio2 >= 2.2.4"], python_requires=">=3.2", data_files=[ diff --git a/stdeb.cfg b/stdeb.cfg index 582c987..012449f 100644 --- a/stdeb.cfg +++ b/stdeb.cfg @@ -1,5 +1,5 @@ [DEFAULT] Debian-Version: 1 -Depends3: python3-revpimodio2 (>= 2.2.3) +Depends3: python3-revpimodio2 (>= 2.2.4) Package: revpipyload Suite: stable