Alle IOs mit Export-Flag in piCtory werden per MQTT gesendet

Parameter für Event-Senden und Output-Schreiben in Konfig eingefügt
Processabbild wird nicht komplett per MQTT gesendet
piCtory Konfig kann angefordert werden
Ausgänge können gesetzt werden (wenn Export-Flag)
This commit is contained in:
2018-09-03 12:16:43 +02:00
parent 0e27aa1d57
commit c6fe2e93e5
11 changed files with 313 additions and 134 deletions

View File

@@ -26,7 +26,9 @@ bindip = *
[MQTT] [MQTT]
mqtt = 0 mqtt = 0
basetopic = revpi/data basetopic = revpi/data
sendinterval = 10 sendinterval = 30
send_on_event = 0
write_outputs = 0
host = host =
port = 1883 port = 1883
tls_set = 0 tls_set = 0

View File

@@ -13,7 +13,7 @@ Packages</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="index-revpipyload.shared.html">shared</a></td> <td><a style="color:#0000FF" href="index-revpipyload.shared.html">shared</a></td>
<td></td> <td>Shared modules.</td>
</tr> </tr>
</table> </table>

View File

@@ -12,7 +12,7 @@ Stellt die MQTT Uebertragung fuer IoT-Zwecke bereit.
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <table>
<tr><td>None</td></tr> <tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
@@ -53,8 +53,11 @@ Methods</h3>
<td><a style="color:#0000FF" href="#MqttServer.__init__">MqttServer</a></td> <td><a style="color:#0000FF" href="#MqttServer.__init__">MqttServer</a></td>
<td>Init MqttServer class.</td> <td>Init MqttServer class.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#MqttServer._get_procimglength">_get_procimglength</a></td> <td><a style="color:#0000FF" href="#MqttServer._evt_io">_evt_io</a></td>
<td>Ermittelt aus piCtory Konfiguration die laenge.</td> <td>Sendet Daten aus Events.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttServer._loadrevpimodio">_loadrevpimodio</a></td>
<td>Instantiiert das RevPiModIO Modul.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#MqttServer._on_connect">_on_connect</a></td> <td><a style="color:#0000FF" href="#MqttServer._on_connect">_on_connect</a></td>
<td>Verbindung zu MQTT Broker.</td> <td>Verbindung zu MQTT Broker.</td>
@@ -66,11 +69,14 @@ Methods</h3>
<td>Sendet piCtory Konfiguration.</td> <td>Sendet piCtory Konfiguration.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#MqttServer._send_pictory_conf">_send_pictory_conf</a></td> <td><a style="color:#0000FF" href="#MqttServer._send_pictory_conf">_send_pictory_conf</a></td>
<td>Sendet piCtory Konfiguration.</td> <td>Sendet piCtory Konfiguration per MQTT.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#MqttServer.newlogfile">newlogfile</a></td> <td><a style="color:#0000FF" href="#MqttServer.newlogfile">newlogfile</a></td>
<td>Konfiguriert die FileHandler auf neue Logdatei.</td> <td>Konfiguriert die FileHandler auf neue Logdatei.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#MqttServer.reload_revpimodio">reload_revpimodio</a></td>
<td>Fuehrt im naechsten Zyklus zum Reload.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttServer.run">run</a></td> <td><a style="color:#0000FF" href="#MqttServer.run">run</a></td>
<td>Startet die Uebertragung per MQTT.</td> <td>Startet die Uebertragung per MQTT.</td>
</tr><tr> </tr><tr>
@@ -86,7 +92,7 @@ Static Methods</h3>
<a NAME="MqttServer.__init__" ID="MqttServer.__init__"></a> <a NAME="MqttServer.__init__" ID="MqttServer.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer (Constructor)</h3> MqttServer (Constructor)</h3>
<b>MqttServer</b>(<i>basetopic, sendinterval, host, port=1883, tls_set=False, username="", password=None, client_id=""</i>) <b>MqttServer</b>(<i>basetopic, sendinterval, host, port=1883, tls_set=False, username="", password=None, client_id="", send_events=False, write_outputs=False</i>)
<p> <p>
Init MqttServer class. Init MqttServer class.
</p><dl> </p><dl>
@@ -102,9 +108,6 @@ Adresse <class 'str'> des MQTT-Servers
</dd><dt><i>port</i></dt> </dd><dt><i>port</i></dt>
<dd> <dd>
Portnummer <class 'int'> des MQTT-Servers Portnummer <class 'int'> des MQTT-Servers
</dd><dt><i>keepalive</i></dt>
<dd>
MQTT Ping bei leerlauf
</dd><dt><i>tls_set</i></dt> </dd><dt><i>tls_set</i></dt>
<dd> <dd>
TLS fuer Verbindung zum MQTT-Server verwenden TLS fuer Verbindung zum MQTT-Server verwenden
@@ -117,17 +120,37 @@ Optional Password fuer MQTT-Server
</dd><dt><i>client_id</i></dt> </dd><dt><i>client_id</i></dt>
<dd> <dd>
MQTT ClientID, wenn leer automatisch random erzeugung MQTT ClientID, wenn leer automatisch random erzeugung
</dd><dt><i>send_events</i></dt>
<dd>
Sendet Werte bei IO Wertaenderung
</dd><dt><i>write_outputs</i></dt>
<dd>
Per MQTT auch Outputs schreiben
</dd> </dd>
</dl><a NAME="MqttServer._get_procimglength" ID="MqttServer._get_procimglength"></a> </dl><a NAME="MqttServer._evt_io" ID="MqttServer._evt_io"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer._get_procimglength</h3> MqttServer._evt_io</h3>
<b>_get_procimglength</b>(<i></i>) <b>_evt_io</b>(<i>name, value</i>)
<p> <p>
Ermittelt aus piCtory Konfiguration die laenge. Sendet Daten aus Events.
</p><dl>
<dt><i>name</i></dt>
<dd>
IO-Name
</dd><dt><i>value</i></dt>
<dd>
IO-Value
</dd>
</dl><a NAME="MqttServer._loadrevpimodio" ID="MqttServer._loadrevpimodio"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer._loadrevpimodio</h3>
<b>_loadrevpimodio</b>(<i></i>)
<p>
Instantiiert das RevPiModIO Modul.
</p><dl> </p><dl>
<dt>Returns:</dt> <dt>Returns:</dt>
<dd> <dd>
Laenge des Prozessabbilds <class 'int'> None or Exception
</dd> </dd>
</dl><a NAME="MqttServer._on_connect" ID="MqttServer._on_connect"></a> </dl><a NAME="MqttServer._on_connect" ID="MqttServer._on_connect"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -152,13 +175,19 @@ Sendet piCtory Konfiguration.
MqttServer._send_pictory_conf</h3> MqttServer._send_pictory_conf</h3>
<b>_send_pictory_conf</b>(<i></i>) <b>_send_pictory_conf</b>(<i></i>)
<p> <p>
Sendet piCtory Konfiguration. Sendet piCtory Konfiguration per MQTT.
</p><a NAME="MqttServer.newlogfile" ID="MqttServer.newlogfile"></a> </p><a NAME="MqttServer.newlogfile" ID="MqttServer.newlogfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer.newlogfile</h3> MqttServer.newlogfile</h3>
<b>newlogfile</b>(<i></i>) <b>newlogfile</b>(<i></i>)
<p> <p>
Konfiguriert die FileHandler auf neue Logdatei. Konfiguriert die FileHandler auf neue Logdatei.
</p><a NAME="MqttServer.reload_revpimodio" ID="MqttServer.reload_revpimodio"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer.reload_revpimodio</h3>
<b>reload_revpimodio</b>(<i></i>)
<p>
Fuehrt im naechsten Zyklus zum Reload.
</p><a NAME="MqttServer.run" ID="MqttServer.run"></a> </p><a NAME="MqttServer.run" ID="MqttServer.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
MqttServer.run</h3> MqttServer.run</h3>

View File

@@ -137,7 +137,7 @@ Instantiiert das RevPiModIO Modul.
</p><dl> </p><dl>
<dt>Returns:</dt> <dt>Returns:</dt>
<dd> <dd>
True, wenn erfolgreich, sonst False None or Exception
</dd> </dd>
</dl><a NAME="ProcimgServer.setvalue" ID="ProcimgServer.setvalue"></a> </dl><a NAME="ProcimgServer.setvalue" ID="ProcimgServer.setvalue"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">

View File

@@ -9,6 +9,8 @@ revpipyload</h1>
<p> <p>
Revolution Pi Python PLC Loader. Revolution Pi Python PLC Loader.
</p><p> </p><p>
Webpage: https://revpimodio.org/revpipyplc/
</p><p>
Stellt das RevPiPyLoad Programm bereit. Dieses Programm lauft als Daemon auf Stellt das RevPiPyLoad Programm bereit. Dieses Programm lauft als Daemon auf
dem Revolution Pi. Es stellt Funktionen bereit, die es ermoeglichen ein Python dem Revolution Pi. Es stellt Funktionen bereit, die es ermoeglichen ein Python
Programm zu starten und fuehrt dessen Ausgaben in eine Logdatei. Die Logdaten Programm zu starten und fuehrt dessen Ausgaben in eine Logdatei. Die Logdaten
@@ -32,7 +34,7 @@ begrenzt werden!
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <table>
<tr><td>pyloadversion</td></tr> <tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr><tr><td>__version__</td></tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -1,3 +1,6 @@
helper.__author__?9
helper.__copyright__?9
helper.__license__?9
helper._setuprt?5(pid, evt_exit) helper._setuprt?5(pid, evt_exit)
helper._zeroprocimg?5() helper._zeroprocimg?5()
helper.refullmatch?4(regex, string) helper.refullmatch?4(regex, string)
@@ -12,15 +15,23 @@ logsystem.PipeLogwriter.newlogfile?4()
logsystem.PipeLogwriter.run?4() logsystem.PipeLogwriter.run?4()
logsystem.PipeLogwriter.stop?4() logsystem.PipeLogwriter.stop?4()
logsystem.PipeLogwriter?1(logfilename) logsystem.PipeLogwriter?1(logfilename)
mqttserver.MqttServer._get_procimglength?5() logsystem.__author__?9
logsystem.__copyright__?9
logsystem.__license__?9
mqttserver.MqttServer._evt_io?5(name, value)
mqttserver.MqttServer._loadrevpimodio?5()
mqttserver.MqttServer._on_connect?5(client, userdata, flags, rc) mqttserver.MqttServer._on_connect?5(client, userdata, flags, rc)
mqttserver.MqttServer._on_disconnect?5(client, userdata, rc) mqttserver.MqttServer._on_disconnect?5(client, userdata, rc)
mqttserver.MqttServer._on_message?5(client, userdata, msg) mqttserver.MqttServer._on_message?5(client, userdata, msg)
mqttserver.MqttServer._send_pictory_conf?5() mqttserver.MqttServer._send_pictory_conf?5()
mqttserver.MqttServer.newlogfile?4() mqttserver.MqttServer.newlogfile?4()
mqttserver.MqttServer.reload_revpimodio?4()
mqttserver.MqttServer.run?4() mqttserver.MqttServer.run?4()
mqttserver.MqttServer.stop?4() mqttserver.MqttServer.stop?4()
mqttserver.MqttServer?1(basetopic, sendinterval, host, port=1883, tls_set=False, username="", password=None, client_id="") mqttserver.MqttServer?1(basetopic, sendinterval, host, port=1883, tls_set=False, username="", password=None, client_id="", send_events=False, write_outputs=False)
mqttserver.__author__?9
mqttserver.__copyright__?9
mqttserver.__license__?9
picontrolserver.RevPiSlave.check_connectedacl?4() picontrolserver.RevPiSlave.check_connectedacl?4()
picontrolserver.RevPiSlave.newlogfile?4() picontrolserver.RevPiSlave.newlogfile?4()
picontrolserver.RevPiSlave.run?4() picontrolserver.RevPiSlave.run?4()
@@ -29,6 +40,9 @@ picontrolserver.RevPiSlave?1(ipacl, port=55234)
picontrolserver.RevPiSlaveDev.run?4() picontrolserver.RevPiSlaveDev.run?4()
picontrolserver.RevPiSlaveDev.stop?4() picontrolserver.RevPiSlaveDev.stop?4()
picontrolserver.RevPiSlaveDev?1(devcon, acl) picontrolserver.RevPiSlaveDev?1(devcon, acl)
picontrolserver.__author__?9
picontrolserver.__copyright__?9
picontrolserver.__license__?9
plcsystem.RevPiPlc.__get_autoreloaddelay?6() plcsystem.RevPiPlc.__get_autoreloaddelay?6()
plcsystem.RevPiPlc.__set_autoreloaddelay?6(value) plcsystem.RevPiPlc.__set_autoreloaddelay?6(value)
plcsystem.RevPiPlc._configureplw?5() plcsystem.RevPiPlc._configureplw?5()
@@ -39,14 +53,23 @@ plcsystem.RevPiPlc.newlogfile?4()
plcsystem.RevPiPlc.run?4() plcsystem.RevPiPlc.run?4()
plcsystem.RevPiPlc.stop?4() plcsystem.RevPiPlc.stop?4()
plcsystem.RevPiPlc?1(program, arguments, pversion) plcsystem.RevPiPlc?1(program, arguments, pversion)
plcsystem.__author__?9
plcsystem.__copyright__?9
plcsystem.__license__?9
procimgserver.ProcimgServer.devices?4() procimgserver.ProcimgServer.devices?4()
procimgserver.ProcimgServer.ios?4(type) procimgserver.ProcimgServer.ios?4(iotype)
procimgserver.ProcimgServer.loadrevpimodio?4() procimgserver.ProcimgServer.loadrevpimodio?4()
procimgserver.ProcimgServer.setvalue?4(device, io, value) procimgserver.ProcimgServer.setvalue?4(device, io, value)
procimgserver.ProcimgServer.start?4() procimgserver.ProcimgServer.start?4()
procimgserver.ProcimgServer.stop?4() procimgserver.ProcimgServer.stop?4()
procimgserver.ProcimgServer.values?4() procimgserver.ProcimgServer.values?4()
procimgserver.ProcimgServer?1(xmlserver) procimgserver.ProcimgServer?1(xmlserver)
procimgserver.__author__?9
procimgserver.__copyright__?9
procimgserver.__license__?9
proginit.__author__?9
proginit.__copyright__?9
proginit.__license__?9
proginit.cleanup?4() proginit.cleanup?4()
proginit.configure?4() proginit.configure?4()
proginit.forked?7 proginit.forked?7
@@ -98,7 +121,13 @@ revpipyload.RevPiPyLoad.xml_reload?4()
revpipyload.RevPiPyLoad.xml_setconfig?4(dc, loadnow=False) revpipyload.RevPiPyLoad.xml_setconfig?4(dc, loadnow=False)
revpipyload.RevPiPyLoad.xml_setpictoryrsc?4(filebytes, reset=False) revpipyload.RevPiPyLoad.xml_setpictoryrsc?4(filebytes, reset=False)
revpipyload.RevPiPyLoad?1() revpipyload.RevPiPyLoad?1()
revpipyload.pyloadversion?7 revpipyload.__author__?9
revpipyload.__copyright__?9
revpipyload.__license__?9
revpipyload.__version__?9
revpipyload.shared.__author__?9
revpipyload.shared.__copyright__?9
revpipyload.shared.__license__?9
revpipyload.shared.ipaclmanager.IpAclManager.__get_acl?6() revpipyload.shared.ipaclmanager.IpAclManager.__get_acl?6()
revpipyload.shared.ipaclmanager.IpAclManager.__get_filename?6() revpipyload.shared.ipaclmanager.IpAclManager.__get_filename?6()
revpipyload.shared.ipaclmanager.IpAclManager.__get_regex_acl?6() revpipyload.shared.ipaclmanager.IpAclManager.__get_regex_acl?6()
@@ -112,6 +141,10 @@ revpipyload.shared.ipaclmanager.IpAclManager.loadaclfile?4(filename)
revpipyload.shared.ipaclmanager.IpAclManager.regex_acl?7 revpipyload.shared.ipaclmanager.IpAclManager.regex_acl?7
revpipyload.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None) revpipyload.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None)
revpipyload.shared.ipaclmanager.IpAclManager?1(minlevel, maxlevel, acl=None) revpipyload.shared.ipaclmanager.IpAclManager?1(minlevel, maxlevel, acl=None)
revpipyload.shared.ipaclmanager.__author__?9
revpipyload.shared.ipaclmanager.__copyright__?9
revpipyload.shared.ipaclmanager.__license__?9
revpipyload.shared.ipaclmanager.__version__?9
revpipyload.shared.ipaclmanager.refullmatch?4(regex, string) revpipyload.shared.ipaclmanager.refullmatch?4(regex, string)
xrpcserver.SaveXMLRPCRequestHandler.parse_request?4() xrpcserver.SaveXMLRPCRequestHandler.parse_request?4()
xrpcserver.SaveXMLRPCServer._dispatch?5(method, params) xrpcserver.SaveXMLRPCServer._dispatch?5(method, params)
@@ -120,3 +153,6 @@ xrpcserver.SaveXMLRPCServer.register_function?4(acl_level, function, name=None)
xrpcserver.SaveXMLRPCServer.start?4() xrpcserver.SaveXMLRPCServer.start?4()
xrpcserver.SaveXMLRPCServer.stop?4() xrpcserver.SaveXMLRPCServer.stop?4()
xrpcserver.SaveXMLRPCServer?1(addr, logRequests=True, allow_none=False, ipacl=None) xrpcserver.SaveXMLRPCServer?1(addr, logRequests=True, allow_none=False, ipacl=None)
xrpcserver.__author__?9
xrpcserver.__copyright__?9
xrpcserver.__license__?9

View File

@@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyLoad
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
"""Stellt die MQTT Uebertragung fuer IoT-Zwecke bereit.""" """Stellt die MQTT Uebertragung fuer IoT-Zwecke bereit."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import proginit import proginit
from json import load as jload import revpimodio2
from ssl import CERT_NONE from os.path import join
from paho.mqtt.client import Client from paho.mqtt.client import Client
from ssl import CERT_NONE
from threading import Thread, Event from threading import Thread, Event
@@ -19,36 +17,71 @@ class MqttServer(Thread):
def __init__( def __init__(
self, basetopic, sendinterval, host, port=1883, self, basetopic, sendinterval, host, port=1883,
tls_set=False, username="", password=None, client_id=""): tls_set=False, username="", password=None, client_id="",
send_events=False, write_outputs=False):
"""Init MqttServer class. """Init MqttServer class.
@param basetopic Basis-Topic fuer Datenaustausch @param basetopic Basis-Topic fuer Datenaustausch
@param sendinterval Prozessabbild alle n Sekunden senden @param sendinterval Prozessabbild alle n Sekunden senden
@param host Adresse <class 'str'> des MQTT-Servers @param host Adresse <class 'str'> des MQTT-Servers
@param port Portnummer <class 'int'> des MQTT-Servers @param port Portnummer <class 'int'> des MQTT-Servers
@param keepalive MQTT Ping bei leerlauf
@param tls_set TLS fuer Verbindung zum MQTT-Server verwenden @param tls_set TLS fuer Verbindung zum MQTT-Server verwenden
@param username Optional Benutzername fuer MQTT-Server @param username Optional Benutzername fuer MQTT-Server
@param password Optional Password fuer MQTT-Server @param password Optional Password fuer MQTT-Server
@param client_id MQTT ClientID, wenn leer automatisch random erzeugung @param client_id MQTT ClientID, wenn leer automatisch random erzeugung
@param send_events Sendet Werte bei IO Wertaenderung
@param write_outputs Per MQTT auch Outputs schreiben
""" """
# TODO: Parameterprüfung if not isinstance(basetopic, str):
raise ValueError("parameter topic must be <class 'str'>")
if not (isinstance(sendinterval, int) and sendinterval > 0):
raise ValueError(
"parameter sendinterval must be <class 'int'> and gt 0"
)
if not isinstance(host, str):
raise ValueError("parameter host must be <class 'str'>")
if not (isinstance(port, int) and 0 < port < 65535):
raise ValueError(
"parameter sendinterval must be <class 'int'> and 1 - 65535"
)
if not isinstance(tls_set, bool):
raise ValueError("parameter tls_set must be <class 'bool'>")
if not isinstance(username, str):
raise ValueError("parameter username must be <class 'str'>")
if not (password is None or isinstance(password, str)):
raise ValueError("parameter password must be <class 'str'>")
if not isinstance(client_id, str):
raise ValueError("parameter client_id must be <class 'str'>")
if not isinstance(send_events, bool):
raise ValueError("parameter send_events must be <class 'bool'>")
if not isinstance(write_outputs, bool):
raise ValueError("parameter write_outputs must be <class 'bool'>")
super().__init__() super().__init__()
# Klassenvariablen # Klassenvariablen
self.__exit = False self.__exit = False
self._evt_data = Event() self._evt_data = Event()
self._exported_ios = []
self._host = host self._host = host
self._procimglength = self._get_procimglength()
self._port = port self._port = port
self._reloadmodio = False
self._rpi = None
self._rpi_write = None
self._send_events = send_events
self._sendinterval = sendinterval self._sendinterval = sendinterval
self._write_outputs = write_outputs
# RevPiModIO laden oder mit Exception aussteigen
self._loadrevpimodio()
# Topics konfigurieren # Topics konfigurieren
self._mqtt_picontrol = "{}/picontrol".format(basetopic) self._mqtt_evt_io = join(basetopic, "event/{0}")
self._mqtt_pictory = "{}/pictory".format(basetopic) self._mqtt_io = join(basetopic, "io/{0}")
self._mqtt_sendpictory = "{}/needpictory".format(basetopic) self._mqtt_ioset = join(basetopic, "set/#")
self._mqtt_pictory = join(basetopic, "pictory")
self._mqtt_sendpictory = join(basetopic, "needpictory")
self._mq = Client(client_id) self._mq = Client(client_id)
if username != "": if username != "":
@@ -61,123 +94,181 @@ class MqttServer(Thread):
self._mq.on_connect = self._on_connect self._mq.on_connect = self._on_connect
self._mq.on_message = self._on_message self._mq.on_message = self._on_message
def _get_procimglength(self): def _evt_io(self, name, value):
"""Ermittelt aus piCtory Konfiguration die laenge. """Sendet Daten aus Events.
@return Laenge des Prozessabbilds <class 'int'>""" @param name IO-Name
@param value IO-Value"""
if isinstance(value, bytes):
value = int.from_bytes(value, "little")
self._mq.publish(self._mqtt_evt_io.format(name), int(value))
def _loadrevpimodio(self):
"""Instantiiert das RevPiModIO Modul.
@return None or Exception"""
self._reloadmodio = False
self._exported_ios = []
# RevPiModIO-Modul Instantiieren
if self._rpi is not None:
self._rpi.cleanup()
if self._rpi_write is not None:
self._rpi_write.cleanup()
proginit.logger.debug("create revpimodio2 object for MQTT")
try: try:
with open(proginit.pargs.configrsc, "r") as fh: # Lesend und Eventüberwachung
rsc = jload(fh) self._rpi = revpimodio2.RevPiModIO(
except: autorefresh=self._send_events,
return 4096 monitoring=True,
configrsc=proginit.pargs.configrsc,
length = 0 procimg=proginit.pargs.procimg
# piCtory Config prüfen
if "Devices" not in rsc:
return 0
# Letzes piCtory Device laden
last_dev = rsc["Devices"].pop()
length += last_dev["offset"]
# bei mem beginnen, weil nur der höchste IO benötigt wird
for type_iom in ["mem", "out", "inp"]:
lst_iom = sorted(
last_dev[type_iom],
key=lambda x: int(x),
reverse=True
) )
if len(lst_iom) > 0: # Schreibenen Zugriff
# Daten des letzen IOM auswerten if self._write_outputs:
last_iom = last_dev[type_iom][str(lst_iom[0])] self._rpi_write = revpimodio2.RevPiModIO(
bitlength = int(last_iom[2]) configrsc=proginit.pargs.configrsc,
length += int(last_iom[3]) procimg=proginit.pargs.procimg
length += 1 if bitlength == 1 else int(bitlength / 8) )
break
return length except Exception as e:
self._rpi = None
self._rpi_write = None
proginit.logger.error(
"piCtory configuration not loadable for MQTT"
)
raise e
# Exportierte IOs laden
for dev in self._rpi.device:
for io in dev.get_allios(export=True):
io.reg_event(self._evt_io)
self._exported_ios.append(io)
# Eventüberwachung starten
if self._send_events:
self._rpi.mainloop(blocking=False)
proginit.logger.debug("created revpimodio2 object")
def _on_connect(self, client, userdata, flags, rc): def _on_connect(self, client, userdata, flags, rc):
"""Verbindung zu MQTT Broker.""" """Verbindung zu MQTT Broker."""
if rc > 0: if rc > 0:
proginit.warning("can not connect to mqtt broker - will retry") proginit.logger.warning(
"can not connect to mqtt broker - error {0} - will retry"
"".format(rc)
)
else: else:
# piCtory übertragen um alle RevPiMqttIO zu benachrichtigen
self._send_pictory_conf()
# Subscribe piCtory Anforderung # Subscribe piCtory Anforderung
client.subscribe(self._mqtt_sendpictory) client.subscribe(self._mqtt_sendpictory)
if self._write_outputs:
client.subscribe(self._mqtt_ioset)
def _on_disconnect(self, client, userdata, rc): def _on_disconnect(self, client, userdata, rc):
"""Wertet Verbindungsabbruch aus.""" """Wertet Verbindungsabbruch aus."""
if rc != 0: if rc != 0:
proginit.warning( proginit.logger.warning(
"unexpected disconnection from mqtt broker - " "unexpected disconnection from mqtt broker - "
"will try to reconnect" "will try to reconnect"
) )
def _on_message(self, client, userdata, msg): def _on_message(self, client, userdata, msg):
"""Sendet piCtory Konfiguration.""" """Sendet piCtory Konfiguration."""
if msg.topic == self._mqtt_pictory:
# piCtory Konfiguration senden # piCtory Konfiguration senden
self._send_pictory_conf() self._send_pictory_conf()
# Prozessabbild senden else:
self._evt_data.set() lst_topic = msg.topic.split("/")
ioname = lst_topic[-1]
try:
io = self._rpi_write.io[ioname]
except Exception:
proginit.logger.error(
"can not find io '{0}' for MQTT".format(ioname)
)
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:
proginit.logger.error(
"io '{0}' is not marked as export in piCtory for MQTT use"
"".format(ioname)
)
else:
# Convert MQTT Payload to valid Output-Value
value = msg.payload.decode("utf8")
if value.isdecimal():
value = int(value)
elif value == "false":
value = 0
elif value == "true":
value = 1
else:
proginit.logger.error(
"can not convert value '{0}' for output '{1}'"
"".format(value, ioname)
)
return
# Write Value to RevPi
io._parentdevice.syncoutputs()
io.value = value
io._parentdevice.writeprocimg()
def _send_pictory_conf(self): def _send_pictory_conf(self):
"""Sendet piCtory Konfiguration.""" """Sendet piCtory Konfiguration per MQTT."""
with open(proginit.pargs.configrsc, "rb") as fh: try:
fh = open(proginit.pargs.configrsc, "rb")
self._mq.publish(self._mqtt_pictory, fh.read()) self._mq.publish(self._mqtt_pictory, fh.read())
fh.close()
except Exception:
proginit.logger.error(
"can not read and publish piCtory config '{0}'"
"".format(proginit.pargs.configrsc)
)
def newlogfile(self): def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei.""" """Konfiguriert die FileHandler auf neue Logdatei."""
pass pass
def reload_revpimodio(self):
"""Fuehrt im naechsten Zyklus zum Reload."""
self._reloadmodio = True
def run(self): def run(self):
"""Startet die Uebertragung per MQTT.""" """Startet die Uebertragung per MQTT."""
proginit.logger.debug("enter MqttServer.start()") proginit.logger.debug("enter MqttServer.run()")
# Prozessabbild öffnen
try:
fh_proc = open(proginit.pargs.procimg, "r+b", 0)
except:
fh_proc = None
self.__exit = True
proginit.logger.error(
"can not open process image {}".format(proginit.pargs.procimg)
)
# MQTT verbinden # MQTT verbinden
self._mq.connect_async(self._host, self._port, keepalive=60) self._mq.connect_async(self._host, self._port, keepalive=60)
self._mq.loop_start() self._mq.loop_start()
# mainloop # mainloop
buff = b''
err_count = 0
while not self.__exit: while not self.__exit:
self._evt_data.clear() self._evt_data.clear()
# Prozessabbild lesen # RevPiModIO neu laden
try: if self._reloadmodio:
fh_proc.seek(0) self._loadrevpimodio()
buff = fh_proc.read(self._procimglength)
if err_count > 0: # Werte laden, wenn nicht autorefresh
proginit.warning( if not self._send_events:
"resume mqtt publishing after {} errors on " self._rpi.readprocimg()
"processimage".format(err_count)
) # Exportierte IOs übertragen
err_count = 0 for io in self._exported_ios:
except IOError: value = io.value
if err_count == 0: if isinstance(value, bytes):
proginit.logger.error( value = int.from_bytes(value, "little")
"could not read process image for mqtt publishing" self._mq.publish(self._mqtt_io.format(io.name), int(value))
)
err_count += 1
else:
# Prozessabbild übertragen
self._mq.publish(self._mqtt_picontrol, buff)
self._evt_data.wait(self._sendinterval) self._evt_data.wait(self._sendinterval)
@@ -185,11 +276,10 @@ class MqttServer(Thread):
self._mq.loop_stop() self._mq.loop_stop()
self._mq.disconnect() self._mq.disconnect()
# FileHandler schließen # RevPiModIO aufräumen
if fh_proc is not None: self._rpi.cleanup()
fh_proc.close()
proginit.logger.debug("leave MqttServer.start()") proginit.logger.debug("leave MqttServer.run()")
def stop(self): def stop(self):
"""Stoppt die Uebertragung per MQTT.""" """Stoppt die Uebertragung per MQTT."""

View File

@@ -45,7 +45,10 @@ class ProcimgServer():
"ps_setvalue": self.setvalue, "ps_setvalue": self.setvalue,
} }
self.loadrevpimodio() # RevPiModIO laden oder mit Exception aussteigen
ex = self.loadrevpimodio()
if ex is not None:
raise ex
proginit.logger.debug("leave ProcimgServer.__init__()") proginit.logger.debug("leave ProcimgServer.__init__()")
@@ -84,25 +87,28 @@ class ProcimgServer():
def loadrevpimodio(self): def loadrevpimodio(self):
"""Instantiiert das RevPiModIO Modul. """Instantiiert das RevPiModIO Modul.
@return True, wenn erfolgreich, sonst False""" @return None or Exception"""
# RevPiModIO-Modul Instantiieren # RevPiModIO-Modul Instantiieren
if self.rpi is not None: if self.rpi is not None:
self.rpi.cleanup() self.rpi.cleanup()
proginit.logger.debug("create revpimodio2 object") proginit.logger.debug("create revpimodio2 object for ProcimgServer")
try: try:
self.rpi = revpimodio2.RevPiModIO( self.rpi = revpimodio2.RevPiModIO(
configrsc=proginit.pargs.configrsc, configrsc=proginit.pargs.configrsc,
procimg=proginit.pargs.procimg procimg=proginit.pargs.procimg
) )
except Exception: except Exception as e:
self.rpi = None self.rpi = None
proginit.logger.error("piCtory configuration not loadable") proginit.logger.error(
return False "piCtory configuration not loadable for ProcimgServer"
)
return e
# NOTE: Warum das?
self.rpi.syncoutputs(device=0) self.rpi.syncoutputs(device=0)
proginit.logger.debug("created revpimodio2 object") proginit.logger.debug("created revpimodio2 object")
return True
def setvalue(self, device, io, value): def setvalue(self, device, io, value):
"""Setzt einen Wert auf dem RevPi. """Setzt einen Wert auf dem RevPi.

View File

@@ -188,23 +188,27 @@ class RevPiPyLoad():
self.mqtt = 0 self.mqtt = 0
if "MQTT" in self.globalconfig: if "MQTT" in self.globalconfig:
self.mqtt = \ self.mqtt = \
int(self.globalconfig["MQTT"].get("mqtt", 0)) self.globalconfig["MQTT"].getboolean("mqtt", False)
self.mqttbasetopic = \ self.mqttbasetopic = \
self.globalconfig["MQTT"].get("basetopic", "") self.globalconfig["MQTT"].get("basetopic", "")
self.mqttsendinterval = \ self.mqttsendinterval = \
int(self.globalconfig["MQTT"].get("sendinterval", 15)) self.globalconfig["MQTT"].getint("sendinterval", 15)
self.mqtthost = \ self.mqtthost = \
self.globalconfig["MQTT"].get("host", "") self.globalconfig["MQTT"].get("host", "")
self.mqttport = \ self.mqttport = \
int(self.globalconfig["MQTT"].get("port", 1883)) self.globalconfig["MQTT"].getint("port", 1883)
self.mqtttls_set = \ self.mqtttls_set = \
int(self.globalconfig["MQTT"].get("tls_set", 0)) self.globalconfig["MQTT"].getboolean("tls_set", False)
self.mqttusername = \ self.mqttusername = \
self.globalconfig["MQTT"].get("username", "") self.globalconfig["MQTT"].get("username", "")
self.mqttpassword = \ self.mqttpassword = \
self.globalconfig["MQTT"].get("password", "") self.globalconfig["MQTT"].get("password", "")
self.mqttclient_id = \ self.mqttclient_id = \
self.globalconfig["MQTT"].get("client_id", "") self.globalconfig["MQTT"].get("client_id", "")
self.mqttsend_events = \
self.globalconfig["MQTT"].getboolean("send_on_event", False)
self.mqttwrite_outputs = \
self.globalconfig["MQTT"].getboolean("write_outputs", False)
# Konfiguration verarbeiten [PLCSLAVE] # Konfiguration verarbeiten [PLCSLAVE]
self.plcslave = False self.plcslave = False
@@ -348,7 +352,7 @@ class RevPiPyLoad():
self.xml_ps = None self.xml_ps = None
proginit.logger.warning( proginit.logger.warning(
"can not load revpimodio2 module. maybe its not installed " "can not load revpimodio2 module. maybe its not installed "
"or an old version (required at least 2.1.6). if you " "or an old version (required at least 2.2.3). if you "
"like to use the process monitor feature, update/install " "like to use the process monitor feature, update/install "
"revpimodio2: 'apt-get install python3-revpimodio2'" "revpimodio2: 'apt-get install python3-revpimodio2'"
) )
@@ -419,11 +423,17 @@ class RevPiPyLoad():
self.mqtttls_set, self.mqtttls_set,
self.mqttusername, self.mqttusername,
self.mqttpassword, self.mqttpassword,
self.mqttclient_id self.mqttclient_id,
self.mqttsend_events,
self.mqttwrite_outputs,
)
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 "
"like to use the mqtt feature, update/install "
"revpimodio2: 'apt-get install python3-revpimodio2'"
) )
except:
# TODO: Fehlermeldung ausgeben bezüglich paho.mqtt
pass
proginit.logger.debug("leave RevPiPyLoad._plcmqtt()") proginit.logger.debug("leave RevPiPyLoad._plcmqtt()")
return th_plc return th_plc
@@ -701,6 +711,8 @@ class RevPiPyLoad():
dc["username"] = self.mqttusername dc["username"] = self.mqttusername
dc["password"] = self.mqttpassword dc["password"] = self.mqttpassword
dc["client_id"] = self.mqttclient_id dc["client_id"] = self.mqttclient_id
dc["send_events"] = self.mqttsend_events
dc["write_outputs"] = self.mqttwrite_outputs
# PLCSLAVE Sektion # PLCSLAVE Sektion
dc["plcslave"] = self.plcslave dc["plcslave"] = self.plcslave
@@ -934,6 +946,8 @@ class RevPiPyLoad():
"mqttusername": ".*", "mqttusername": ".*",
"mqttpassword": ".*", "mqttpassword": ".*",
"mqttclient_id": ".+", "mqttclient_id": ".+",
"mqttsend_events": "[01]",
"mqttwrite_outputs": "[01]",
}, },
"PLCSLAVE": { "PLCSLAVE": {
"plcslave": "[01]", "plcslave": "[01]",

View File

@@ -31,7 +31,7 @@ setup(
scripts=["data/revpipyload"], scripts=["data/revpipyload"],
install_requires=["revpimodio2 >= 2.1.6"], install_requires=["revpimodio2 >= 2.2.3"],
python_requires=">=3.2", python_requires=">=3.2",
data_files=[ data_files=[

View File

@@ -1,5 +1,5 @@
[DEFAULT] [DEFAULT]
Debian-Version: 1 Debian-Version: 1
Depends3: python3-revpimodio2 (>= 2.1.6) Depends3: python3-revpimodio2 (>= 2.2.3)
Package: revpipyload Package: revpipyload
Suite: stable Suite: stable