Modul picontrolserver angelegt und PLCSlave-Funktionen verschoben

Kleine Anpassungen durch Übernehme von default-Zweig
This commit is contained in:
2017-09-13 10:00:46 +02:00
parent b791307ec8
commit cf0f136c07
7 changed files with 599 additions and 911 deletions

View File

@@ -16,6 +16,9 @@ Modules</h3>
<td><a style="color:#0000FF" href="logsystem.html">logsystem</a></td>
<td>Modul fuer die Verwaltung der Logdateien.</td>
</tr><tr>
<td><a style="color:#0000FF" href="picontrolserver.html">picontrolserver</a></td>
<td>Modul fuer die Verwaltung der PLC-Slave Funktionen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="plcsystem.html">plcsystem</a></td>
<td>Modul fuer die Verwaltung der PLC Funktionen.</td>
</tr><tr>

190
doc/picontrolserver.html Normal file
View File

@@ -0,0 +1,190 @@
<!DOCTYPE html>
<html><head>
<title>picontrolserver</title>
<meta charset="UTF-8">
</head>
<body style="background-color:#FFFFFF;color:#000000"><a NAME="top" ID="top"></a>
<h1 style="background-color:#FFFFFF;color:#0000FF">
picontrolserver</h1>
<p>
Modul fuer die Verwaltung der PLC-Slave Funktionen.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiSlave">RevPiSlave</a></td>
<td>RevPi PLC-Server.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev">RevPiSlaveDev</a></td>
<td>Klasse um eine RevPiModIO Verbindung zu verwalten.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
</table>
<hr /><hr />
<a NAME="RevPiSlave" ID="RevPiSlave"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiSlave</h2>
<p>
RevPi PLC-Server.
</p><p>
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
neue Verbindungen. Dieser werden dann als RevPiSlaveDev abgebildet.
</p><p>
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiSlave.__init__">RevPiSlave</a></td>
<td>Instantiiert RevPiSlave-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.newlogfile">newlogfile</a></td>
<td>Konfiguriert die FileHandler auf neue Logdatei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.run">run</a></td>
<td>Startet Serverkomponente fuer die Annahme neuer Verbindungen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.stop">stop</a></td>
<td>Beendet Slaveausfuehrung.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiSlave.__init__" ID="RevPiSlave.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave (Constructor)</h3>
<b>RevPiSlave</b>(<i>acl, port=55234</i>)
<p>
Instantiiert RevPiSlave-Klasse.
</p><dl>
<dt><i>acl</i></dt>
<dd>
Stringliste mit Leerstellen getrennt
</dd><dt><i>port</i></dt>
<dd>
Listen Port fuer plc Slaveserver
</dd>
</dl><a NAME="RevPiSlave.newlogfile" ID="RevPiSlave.newlogfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.newlogfile</h3>
<b>newlogfile</b>(<i></i>)
<p>
Konfiguriert die FileHandler auf neue Logdatei.
</p><a NAME="RevPiSlave.run" ID="RevPiSlave.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.run</h3>
<b>run</b>(<i></i>)
<p>
Startet Serverkomponente fuer die Annahme neuer Verbindungen.
</p><a NAME="RevPiSlave.stop" ID="RevPiSlave.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendet Slaveausfuehrung.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="RevPiSlaveDev" ID="RevPiSlaveDev"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiSlaveDev</h2>
<p>
Klasse um eine RevPiModIO Verbindung zu verwalten.
</p><p>
Diese Klasste stellt die Funktionen zur Verfuegung um Daten ueber das
Netzwerk mit dem Prozessabbild auszutauschen.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.__init__">RevPiSlaveDev</a></td>
<td>Init RevPiSlaveDev-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.run">run</a></td>
<td>Verarbeitet Anfragen von Remoteteilnehmer.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.stop">stop</a></td>
<td>Beendet Verbindungsthread.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiSlaveDev.__init__" ID="RevPiSlaveDev.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev (Constructor)</h3>
<b>RevPiSlaveDev</b>(<i>devcon, acl</i>)
<p>
Init RevPiSlaveDev-Class.
</p><dl>
<dt><i>devcon</i></dt>
<dd>
Tuple der Verbindung
</dd><dt><i>deadtime</i></dt>
<dd>
Timeout der Vararbeitung
</dd><dt><i>acl</i></dt>
<dd>
Berechtigungslevel
</dd>
</dl><a NAME="RevPiSlaveDev.run" ID="RevPiSlaveDev.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.run</h3>
<b>run</b>(<i></i>)
<p>
Verarbeitet Anfragen von Remoteteilnehmer.
</p><a NAME="RevPiSlaveDev.stop" ID="RevPiSlaveDev.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendet Verbindungsthread.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -32,29 +32,14 @@ begrenzt werden!
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>configrsc</td></tr><tr><td>picontrolreset</td></tr><tr><td>procimg</td></tr><tr><td>pyloadverion</td></tr><tr><td>rapcatalog</td></tr><tr><td>re_ipacl</td></tr>
<tr><td>pyloadversion</td></tr><tr><td>re_ipacl</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#LogReader">LogReader</a></td>
<td>Ermoeglicht den Zugriff auf die Logdateien.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter">PipeLogwriter</a></td>
<td>File PIPE fuer das Schreiben des APP Log.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc">RevPiPlc</a></td>
<td>Verwaltet das PLC Python Programm.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPyLoad">RevPiPyLoad</a></td>
<td>Hauptklasse, die alle Funktionen zur Verfuegung stellt.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave">RevPiSlave</a></td>
<td>RevPi PLC-Server.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev">RevPiSlaveDev</a></td>
<td>Klasse um eine RevPiModIO Verbindung zu verwalten.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -64,344 +49,11 @@ Functions</h3>
<td><a style="color:#0000FF" href="#_ipmatch">_ipmatch</a></td>
<td>Prueft IP gegen ACL List und gibt ACL aus.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#_zeroprocimg">_zeroprocimg</a></td>
<td>Setzt Prozessabbild auf NULL.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#refullmatch">refullmatch</a></td>
<td>re.fullmatch wegen alter python version aus wheezy nachgebaut.</td>
</tr>
</table>
<hr /><hr />
<a NAME="LogReader" ID="LogReader"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">LogReader</h2>
<p>
Ermoeglicht den Zugriff auf die Logdateien.
</p><p>
Beinhaltet Funktionen fuer den Abruf der gesamten Logdatei fuer das
RevPiPyLoad-System und die Logdatei der PLC-Anwendung.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
None
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#LogReader.__init__">LogReader</a></td>
<td>Instantiiert LogReader-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#LogReader.closeall">closeall</a></td>
<td>Fuehrt close auf File Handler durch.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#LogReader.load_applog">load_applog</a></td>
<td>Uebertraegt Logdaten des PLC Programms Binaer.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#LogReader.load_plclog">load_plclog</a></td>
<td>Uebertraegt Logdaten des Loaders Binaer.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="LogReader.__init__" ID="LogReader.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
LogReader (Constructor)</h3>
<b>LogReader</b>(<i></i>)
<p>
Instantiiert LogReader-Klasse.
</p><a NAME="LogReader.closeall" ID="LogReader.closeall"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
LogReader.closeall</h3>
<b>closeall</b>(<i></i>)
<p>
Fuehrt close auf File Handler durch.
</p><a NAME="LogReader.load_applog" ID="LogReader.load_applog"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
LogReader.load_applog</h3>
<b>load_applog</b>(<i>start, count</i>)
<p>
Uebertraegt Logdaten des PLC Programms Binaer.
</p><dl>
<dt><i>start</i></dt>
<dd>
Startbyte
</dd><dt><i>count</i></dt>
<dd>
Max. Byteanzahl zum uebertragen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
Binary() der Logdatei
</dd>
</dl><a NAME="LogReader.load_plclog" ID="LogReader.load_plclog"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
LogReader.load_plclog</h3>
<b>load_plclog</b>(<i>start, count</i>)
<p>
Uebertraegt Logdaten des Loaders Binaer.
</p><dl>
<dt><i>start</i></dt>
<dd>
Startbyte
</dd><dt><i>count</i></dt>
<dd>
Max. Byteanzahl zum uebertragen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
Binary() der Logdatei
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="PipeLogwriter" ID="PipeLogwriter"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">PipeLogwriter</h2>
<p>
File PIPE fuer das Schreiben des APP Log.
</p><p>
Spezieller LogFile-Handler fuer die Ausgabe des subprocess fuer das Python
PLC Programm. Die Ausgabe kann nicht auf einen neuen FileHandler
umgeschrieben werden. Dadurch waere es nicht moeglich nach einem logrotate
die neue Datei zu verwenden. Ueber die PIPE wird dies umgangen.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.__init__">PipeLogwriter</a></td>
<td>Instantiiert PipeLogwriter-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.__del__">__del__</a></td>
<td>Close file handler.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter._configurefh">_configurefh</a></td>
<td>Konfiguriert den FileHandler fuer Ausgaben der PLCAPP.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.logline">logline</a></td>
<td>Schreibt eine Zeile in die Logdatei oder stdout.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.newlogfile">newlogfile</a></td>
<td>Konfiguriert den FileHandler auf eine neue Logdatei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.run">run</a></td>
<td>Prueft auf neue Logzeilen und schreibt diese.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#PipeLogwriter.stop">stop</a></td>
<td>Beendetden Thread und die FileHandler werden geschlossen.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="PipeLogwriter.__init__" ID="PipeLogwriter.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter (Constructor)</h3>
<b>PipeLogwriter</b>(<i>logfilename</i>)
<p>
Instantiiert PipeLogwriter-Klasse.
</p><dl>
<dt><i>logfilename</i></dt>
<dd>
Dateiname fuer Logdatei
</dd>
</dl><a NAME="PipeLogwriter.__del__" ID="PipeLogwriter.__del__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter.__del__</h3>
<b>__del__</b>(<i></i>)
<p>
Close file handler.
</p><a NAME="PipeLogwriter._configurefh" ID="PipeLogwriter._configurefh"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter._configurefh</h3>
<b>_configurefh</b>(<i></i>)
<p>
Konfiguriert den FileHandler fuer Ausgaben der PLCAPP.
</p><dl>
<dt>Returns:</dt>
<dd>
FileHandler-Objekt
</dd>
</dl><a NAME="PipeLogwriter.logline" ID="PipeLogwriter.logline"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter.logline</h3>
<b>logline</b>(<i>message</i>)
<p>
Schreibt eine Zeile in die Logdatei oder stdout.
</p><dl>
<dt><i>message</i></dt>
<dd>
Logzeile zum Schreiben
</dd>
</dl><a NAME="PipeLogwriter.newlogfile" ID="PipeLogwriter.newlogfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter.newlogfile</h3>
<b>newlogfile</b>(<i></i>)
<p>
Konfiguriert den FileHandler auf eine neue Logdatei.
</p><a NAME="PipeLogwriter.run" ID="PipeLogwriter.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter.run</h3>
<b>run</b>(<i></i>)
<p>
Prueft auf neue Logzeilen und schreibt diese.
</p><a NAME="PipeLogwriter.stop" ID="PipeLogwriter.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
PipeLogwriter.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendetden Thread und die FileHandler werden geschlossen.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="RevPiPlc" ID="RevPiPlc"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiPlc</h2>
<p>
Verwaltet das PLC Python Programm.
</p><p>
Dieser Thread startet das PLC Python Programm und ueberwacht es. Sollte es
abstuerzen kann es automatisch neu gestartet werden. Die Ausgaben des
Programms werden in eine Logdatei umgeleitet, damit der Entwickler sein
Programm analysieren und debuggen kann.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiPlc.__init__">RevPiPlc</a></td>
<td>Instantiiert RevPiPlc-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc._configureplw">_configureplw</a></td>
<td>Konfiguriert den PipeLogwriter fuer Ausgaben der PLCAPP.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc._setuppopen">_setuppopen</a></td>
<td>Setzt UID und GID fuer das PLC Programm.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc._spopen">_spopen</a></td>
<td>Startet das PLC Programm.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc.newlogfile">newlogfile</a></td>
<td>Konfiguriert die FileHandler auf neue Logdatei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc.run">run</a></td>
<td>Fuehrt PLC-Programm aus und ueberwacht es.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPlc.stop">stop</a></td>
<td>Beendet PLC-Programm.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiPlc.__init__" ID="RevPiPlc.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc (Constructor)</h3>
<b>RevPiPlc</b>(<i>program, arguments, pversion</i>)
<p>
Instantiiert RevPiPlc-Klasse.
</p><a NAME="RevPiPlc._configureplw" ID="RevPiPlc._configureplw"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc._configureplw</h3>
<b>_configureplw</b>(<i></i>)
<p>
Konfiguriert den PipeLogwriter fuer Ausgaben der PLCAPP.
</p><dl>
<dt>Returns:</dt>
<dd>
PipeLogwriter()
</dd>
</dl><a NAME="RevPiPlc._setuppopen" ID="RevPiPlc._setuppopen"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc._setuppopen</h3>
<b>_setuppopen</b>(<i></i>)
<p>
Setzt UID und GID fuer das PLC Programm.
</p><a NAME="RevPiPlc._spopen" ID="RevPiPlc._spopen"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc._spopen</h3>
<b>_spopen</b>(<i>lst_proc</i>)
<p>
Startet das PLC Programm.
</p><dl>
<dt><i>lst_proc</i></dt>
<dd>
Prozessliste
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
subprocess
</dd>
</dl><a NAME="RevPiPlc.newlogfile" ID="RevPiPlc.newlogfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc.newlogfile</h3>
<b>newlogfile</b>(<i></i>)
<p>
Konfiguriert die FileHandler auf neue Logdatei.
</p><a NAME="RevPiPlc.run" ID="RevPiPlc.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc.run</h3>
<b>run</b>(<i></i>)
<p>
Fuehrt PLC-Programm aus und ueberwacht es.
</p><a NAME="RevPiPlc.stop" ID="RevPiPlc.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPlc.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendet PLC-Programm.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="RevPiPyLoad" ID="RevPiPyLoad"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiPyLoad</h2>
<p>
@@ -826,162 +478,6 @@ Statuscode:
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="RevPiSlave" ID="RevPiSlave"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiSlave</h2>
<p>
RevPi PLC-Server.
</p><p>
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
neue Verbindungen. Dieser werden dann als RevPiSlaveDev abgebildet.
</p><p>
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiSlave.__init__">RevPiSlave</a></td>
<td>Instantiiert RevPiSlave-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.newlogfile">newlogfile</a></td>
<td>Konfiguriert die FileHandler auf neue Logdatei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.run">run</a></td>
<td>Startet Serverkomponente fuer die Annahme neuer Verbindungen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.stop">stop</a></td>
<td>Beendet Slaveausfuehrung.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiSlave.__init__" ID="RevPiSlave.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave (Constructor)</h3>
<b>RevPiSlave</b>(<i>acl, port=55234</i>)
<p>
Instantiiert RevPiSlave-Klasse.
</p><dl>
<dt><i>acl</i></dt>
<dd>
Stringliste mit Leerstellen getrennt
</dd><dt><i>port</i></dt>
<dd>
Listen Port fuer plc Slaveserver
</dd>
</dl><a NAME="RevPiSlave.newlogfile" ID="RevPiSlave.newlogfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.newlogfile</h3>
<b>newlogfile</b>(<i></i>)
<p>
Konfiguriert die FileHandler auf neue Logdatei.
</p><a NAME="RevPiSlave.run" ID="RevPiSlave.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.run</h3>
<b>run</b>(<i></i>)
<p>
Startet Serverkomponente fuer die Annahme neuer Verbindungen.
</p><a NAME="RevPiSlave.stop" ID="RevPiSlave.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendet Slaveausfuehrung.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="RevPiSlaveDev" ID="RevPiSlaveDev"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiSlaveDev</h2>
<p>
Klasse um eine RevPiModIO Verbindung zu verwalten.
</p><p>
Diese Klasste stellt die Funktionen zur Verfuegung um Daten ueber das
Netzwerk mit dem Prozessabbild auszutauschen.
</p><p>
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Thread
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.__init__">RevPiSlaveDev</a></td>
<td>Init RevPiSlaveDev-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.run">run</a></td>
<td>Verarbeitet Anfragen von Remoteteilnehmer.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.stop">stop</a></td>
<td>Beendet Verbindungsthread.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiSlaveDev.__init__" ID="RevPiSlaveDev.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev (Constructor)</h3>
<b>RevPiSlaveDev</b>(<i>devcon, acl</i>)
<p>
Init RevPiSlaveDev-Class.
</p><dl>
<dt><i>devcon</i></dt>
<dd>
Tuple der Verbindung
</dd><dt><i>deadtime</i></dt>
<dd>
Timeout der Vararbeitung
</dd><dt><i>acl</i></dt>
<dd>
Berechtigungslevel
</dd>
</dl><a NAME="RevPiSlaveDev.run" ID="RevPiSlaveDev.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.run</h3>
<b>run</b>(<i></i>)
<p>
Verarbeitet Anfragen von Remoteteilnehmer.
</p><a NAME="RevPiSlaveDev.stop" ID="RevPiSlaveDev.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.stop</h3>
<b>stop</b>(<i></i>)
<p>
Beendet Verbindungsthread.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_ipmatch" ID="_ipmatch"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_ipmatch</h2>
<b>_ipmatch</b>(<i>ipaddress, dict_acl</i>)
@@ -1003,14 +499,6 @@ int() ACL Wert oder -1 wenn nicht gefunden
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_zeroprocimg" ID="_zeroprocimg"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_zeroprocimg</h2>
<b>_zeroprocimg</b>(<i></i>)
<p>
Setzt Prozessabbild auf NULL.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="refullmatch" ID="refullmatch"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">refullmatch</h2>
<b>refullmatch</b>(<i>regex, string</i>)

View File

@@ -1,3 +1,28 @@
logsystem.LogReader.closeall?4()
logsystem.LogReader.load_applog?4(start, count)
logsystem.LogReader.load_plclog?4(start, count)
logsystem.LogReader?1()
logsystem.PipeLogwriter.__del__?6()
logsystem.PipeLogwriter._configurefh?5()
logsystem.PipeLogwriter.logline?4(message)
logsystem.PipeLogwriter.newlogfile?4()
logsystem.PipeLogwriter.run?4()
logsystem.PipeLogwriter.stop?4()
logsystem.PipeLogwriter?1(logfilename)
picontrolserver.RevPiSlave.newlogfile?4()
picontrolserver.RevPiSlave.run?4()
picontrolserver.RevPiSlave.stop?4()
picontrolserver.RevPiSlave?1(acl, port=55234)
picontrolserver.RevPiSlaveDev.run?4()
picontrolserver.RevPiSlaveDev.stop?4()
picontrolserver.RevPiSlaveDev?1(devcon, acl)
plcsystem.RevPiPlc._configureplw?5()
plcsystem.RevPiPlc._setuppopen?5()
plcsystem.RevPiPlc._spopen?5(lst_proc)
plcsystem.RevPiPlc.newlogfile?4()
plcsystem.RevPiPlc.run?4()
plcsystem.RevPiPlc.stop?4()
plcsystem.RevPiPlc?1(program, arguments, pversion)
procimgserver.ProcimgServer.devices?4()
procimgserver.ProcimgServer.ios?4(type)
procimgserver.ProcimgServer.loadrevpimodio?4()
@@ -5,7 +30,8 @@ procimgserver.ProcimgServer.setvalue?4(device, io, value)
procimgserver.ProcimgServer.start?4()
procimgserver.ProcimgServer.stop?4()
procimgserver.ProcimgServer.values?4()
procimgserver.ProcimgServer?1(logger, xmlserver, configrsc, procimg, aclmode)
procimgserver.ProcimgServer?1(xmlserver, aclmode)
proginit._zeroprocimg?5(self)
proginit.cleanup?4()
proginit.configure?4()
proginit.forked?7
@@ -14,25 +40,9 @@ proginit.logapp?7
proginit.logger?7
proginit.logplc?7
proginit.pargs?7
proginit.picontrolreset?7
proginit.rapcatalog?7
proginit.startdir?7
revpipyload.LogReader.closeall?4()
revpipyload.LogReader.load_applog?4(start, count)
revpipyload.LogReader.load_plclog?4(start, count)
revpipyload.LogReader?1()
revpipyload.PipeLogwriter.__del__?6()
revpipyload.PipeLogwriter._configurefh?5()
revpipyload.PipeLogwriter.logline?4(message)
revpipyload.PipeLogwriter.newlogfile?4()
revpipyload.PipeLogwriter.run?4()
revpipyload.PipeLogwriter.stop?4()
revpipyload.PipeLogwriter?1(logfilename)
revpipyload.RevPiPlc._configureplw?5()
revpipyload.RevPiPlc._setuppopen?5()
revpipyload.RevPiPlc._spopen?5(lst_proc)
revpipyload.RevPiPlc.newlogfile?4()
revpipyload.RevPiPlc.run?4()
revpipyload.RevPiPlc.stop?4()
revpipyload.RevPiPlc?1(program, arguments, pversion)
revpipyload.RevPiPyLoad._loadconfig?5()
revpipyload.RevPiPyLoad._plcthread?5()
revpipyload.RevPiPyLoad._sigexit?5(signum, frame)
@@ -61,19 +71,7 @@ revpipyload.RevPiPyLoad.xml_reload?4()
revpipyload.RevPiPyLoad.xml_setconfig?4(dc, loadnow=False)
revpipyload.RevPiPyLoad.xml_setpictoryrsc?4(filebytes, reset=False)
revpipyload.RevPiPyLoad?1()
revpipyload.RevPiSlave.newlogfile?4()
revpipyload.RevPiSlave.run?4()
revpipyload.RevPiSlave.stop?4()
revpipyload.RevPiSlave?1(acl, port=55234)
revpipyload.RevPiSlaveDev.run?4()
revpipyload.RevPiSlaveDev.stop?4()
revpipyload.RevPiSlaveDev?1(devcon, acl)
revpipyload._ipmatch?5(ipaddress, dict_acl)
revpipyload._zeroprocimg?5()
revpipyload.configrsc?7
revpipyload.picontrolreset?7
revpipyload.procimg?7
revpipyload.pyloadverion?7
revpipyload.rapcatalog?7
revpipyload.pyloadversion?7
revpipyload.re_ipacl?7
revpipyload.refullmatch?4(regex, string)

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipyload -->
<!-- Saved: 2017-09-12, 10:20:24 -->
<!-- Saved: 2017-09-12, 16:51:56 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1">
<Language>en_US</Language>
@@ -20,6 +20,7 @@
<Source>revpipyload/procimgserver.py</Source>
<Source>revpipyload/logsystem.py</Source>
<Source>revpipyload/plcsystem.py</Source>
<Source>revpipyload/picontrolserver.py</Source>
</Sources>
<Forms/>
<Translations/>

View File

@@ -0,0 +1,362 @@
# -*- coding: utf-8 -*-
#
# RevPiPyLoad
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
"""Modul fuer die Verwaltung der PLC-Slave Funktionen."""
import proginit
import socket
from threading import Event, Thread
from timeit import default_timer
from revpipyload import _ipmatch
class RevPiSlave(Thread):
"""RevPi PLC-Server.
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
neue Verbindungen. Dieser werden dann als RevPiSlaveDev abgebildet.
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
"""
def __init__(self, acl, port=55234):
"""Instantiiert RevPiSlave-Klasse.
@param acl Stringliste mit Leerstellen getrennt
@param port Listen Port fuer plc Slaveserver"""
super().__init__()
self._evt_exit = Event()
self.exitcode = None
self._port = port
self.so = None
self._th_dev = []
self.zeroonerror = False
self.zeroonexit = False
# ACLs aufbereiten
self.dict_acl = {}
for host in acl.split():
aclsplit = host.split(",")
self.dict_acl[aclsplit[0]] = \
0 if len(aclsplit) == 1 else int(aclsplit[1])
def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei."""
pass
def run(self):
"""Startet Serverkomponente fuer die Annahme neuer Verbindungen."""
proginit.logger.debug("enter RevPiSlave.run()")
# Socket öffnen und konfigurieren
self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while not self._evt_exit.is_set():
try:
self.so.bind(("", self._port))
except:
proginit.logger.warning("can not bind socket - retry")
self._evt_exit.wait(1)
else:
break
self.so.listen(15)
# Mit Socket arbeiten
while not self._evt_exit.is_set():
self.exitcode = -1
# Verbindung annehmen
proginit.logger.debug("accept new connection")
try:
tup_sock = self.so.accept()
except:
if not self._evt_exit.is_set():
proginit.logger.exception("accept exception")
continue
# ACL prüfen
aclstatus = _ipmatch(tup_sock[1][0], self.dict_acl)
if aclstatus == -1:
tup_sock[0].close()
proginit.logger.warning(
"host ip '{}' does not match revpiacl - disconnect"
"".format(tup_sock[1][0])
)
else:
# Thread starten
th = RevPiSlaveDev(tup_sock, aclstatus)
th.start()
self._th_dev.append(th)
# Liste von toten threads befreien
self._th_dev = [
th_check for th_check in self._th_dev if th_check.is_alive()
]
# Alle Threads beenden
for th in self._th_dev:
th.stop()
# Socket schließen
self.so.close()
self.so = None
self.exitcode = 0
proginit.logger.debug("leave RevPiSlave.run()")
def stop(self):
"""Beendet Slaveausfuehrung."""
proginit.logger.debug("enter RevPiSlave.stop()")
self._evt_exit.set()
if self.so is not None:
try:
self.so.shutdown(socket.SHUT_RDWR)
except:
pass
proginit.logger.debug("leave RevPiSlave.stop()")
class RevPiSlaveDev(Thread):
"""Klasse um eine RevPiModIO Verbindung zu verwalten.
Diese Klasste stellt die Funktionen zur Verfuegung um Daten ueber das
Netzwerk mit dem Prozessabbild auszutauschen.
"""
def __init__(self, devcon, acl):
"""Init RevPiSlaveDev-Class.
@param devcon Tuple der Verbindung
@param deadtime Timeout der Vararbeitung
@param acl Berechtigungslevel
"""
super().__init__()
self._acl = acl
self.daemon = True
self._deadtime = None
self._devcon, self._addr = devcon
self._evt_exit = Event()
self._writeerror = False
# Sicherheitsbytes
self.ey_dict = {}
def run(self):
"""Verarbeitet Anfragen von Remoteteilnehmer."""
proginit.logger.debug("enter RevPiSlaveDev.run()")
proginit.logger.info(
"got new connection from host {} with acl {}".format(
self._addr, self._acl)
)
# Prozessabbild öffnen
fh_proc = open(proginit.pargs.procimg, "r+b", 0)
dirty = True
while not self._evt_exit.is_set():
# Laufzeitberechnung starten
ot = default_timer()
# Meldung erhalten
try:
netcmd = self._devcon.recv(16)
except:
break
# Wenn Meldung ungültig ist aussteigen
if netcmd[0:1] != b'\x01' or netcmd[-1:] != b'\x17':
if netcmd != b'':
proginit.logger.error(
"net cmd not valid {}".format(netcmd)
)
break
cmd = netcmd[1:3]
if cmd == b'DA':
# Processabbild übertragen
# bCMiiii00000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
fh_proc.seek(position)
try:
self._devcon.sendall(fh_proc.read(length))
except:
proginit.logger.error("error while send read data")
break
elif cmd == b'SD' and self._acl == 1:
# Ausgänge empfangen, wenn acl es erlaubt
# bCMiiiic0000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
control = netcmd[7:8]
if control == b'\x1d' and length > 0:
try:
block = self._devcon.recv(length)
except:
proginit.logger.error("error while recv data to write")
self._writeerror = True
break
fh_proc.seek(position)
# Länge der Daten prüfen
if len(block) == length:
fh_proc.write(block)
else:
proginit.logger.error("got wrong length to write")
break
# Record seperator character
if control == b'\x1c':
if self._writeerror:
self._devcon.send(b'\xff')
else:
self._devcon.send(b'\x1e')
self._writeerror = False
elif cmd == b'\x06\x16':
# Just sync
self._devcon.send(b'\x06\x16')
elif cmd == b'CF':
# Socket konfigurieren
# bCMii0000000000b = 16
timeoutms = int.from_bytes(netcmd[3:5], byteorder="little")
self._deadtime = timeoutms / 1000
self._devcon.settimeout(self._deadtime)
# Record seperator character
self._devcon.send(b'\x1e')
elif cmd == b'EY':
# Bytes bei Verbindungsabbruch schreiben
# bCMiiiix0000000b = 16
position = int.from_bytes(
netcmd[3:5], byteorder="little"
)
length = int.from_bytes(
netcmd[5:7], byteorder="little"
)
if netcmd[7:8] == b'\xFF':
# Dirtybytes löschen
if position in self.ey_dict:
del self.ey_dict[position]
# Record seperator character
self._devcon.send(b'\x1e')
proginit.logger.info(
"cleared dirty bytes on position {}"
"".format(position)
)
else:
# Dirtybytes hinzufügen
bytesbuff = bytearray()
try:
while not self._evt_exit.is_set() \
and len(bytesbuff) < length:
block = self._devcon.recv(1024)
bytesbuff += block
if block == b'':
break
except:
proginit.logger.error("error while recv dirty bytes")
break
# Länge der Daten prüfen
if len(bytesbuff) == length:
self.ey_dict[position] = bytesbuff
else:
proginit.logger.error("got wrong length to write")
break
# Record seperator character
self._devcon.send(b'\x1e')
proginit.logger.info(
"got dirty bytes to write on error on position {}"
"".format(position)
)
elif cmd == b'PI':
# piCtory Konfiguration senden
proginit.logger.debug(
"transfair pictory configuration: {}"
"".format(proginit.pargs.configrsc)
)
fh_pic = open(proginit.pargs.configrsc, "rb")
while True:
data = fh_pic.read(1024)
if data:
# FIXME: Fehler fangen
self._devcon.send(data)
else:
fh_pic.close()
break
# End-of-Transmission character
self._devcon.send(b'\x04')
continue
elif cmd == b'EX':
# Sauber Verbindung verlassen
dirty = False
self._evt_exit.set()
continue
else:
# Kein gültiges CMD gefunden, abbruch!
break
# Verarbeitungszeit prüfen
if self._deadtime is not None:
comtime = default_timer() - ot
if comtime > self._deadtime:
proginit.logger.warning(
"runtime more than {} ms: {}!".format(
int(self._deadtime * 1000), comtime
)
)
# TODO: Soll ein Fehler ausgelöst werden?
# Dirty verlassen
if dirty:
for pos in self.ey_dict:
fh_proc.seek(pos)
fh_proc.write(self.ey_dict[pos])
proginit.logger.error("dirty shutdown of connection")
fh_proc.close()
self._devcon.close()
self._devcon = None
proginit.logger.info("disconnected from {}".format(self._addr))
proginit.logger.debug("leave RevPiSlaveDev.run()")
def stop(self):
"""Beendet Verbindungsthread."""
proginit.logger.debug("enter RevPiSlaveDev.stop()")
self._evt_exit.set()
if self._devcon is not None:
self._devcon.shutdown(socket.SHUT_RDWR)
proginit.logger.debug("leave RevPiSlaveDev.stop()")

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# RevPiPyLoad
# Version: see global var pyloadverion
# Version: see global var pyloadversion
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
@@ -32,11 +32,11 @@ begrenzt werden!
"""
import gzip
import logsystem
import picontrolserver
import plcsystem
import proginit
import os
import signal
import socket
import tarfile
import zipfile
from concurrent import futures
@@ -47,12 +47,10 @@ from shutil import rmtree
from tempfile import mkstemp
from threading import Event
from time import asctime
from timeit import default_timer
from xmlrpc.client import Binary
from xmlrpc.server import SimpleXMLRPCServer
pyloadverion = "0.4.3"
pyloadverion = "0.5.0"
pyloadversion = "0.5.0"
re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*"
@@ -83,362 +81,6 @@ def refullmatch(regex, string):
return m is not None and m.end() == len(string)
def _zeroprocimg():
"""Setzt Prozessabbild auf NULL."""
if os.path.exists(procimg):
f = open(procimg, "w+b", 0)
f.write(bytes(4096))
class RevPiSlave(Thread):
"""RevPi PLC-Server.
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
neue Verbindungen. Dieser werden dann als RevPiSlaveDev abgebildet.
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
"""
def __init__(self, acl, port=55234):
"""Instantiiert RevPiSlave-Klasse.
@param acl Stringliste mit Leerstellen getrennt
@param port Listen Port fuer plc Slaveserver"""
super().__init__()
self._evt_exit = Event()
self.exitcode = None
self._port = port
self.so = None
self._th_dev = []
self.zeroonerror = False
self.zeroonexit = False
# ACLs aufbereiten
self.dict_acl = {}
for host in acl.split():
aclsplit = host.split(",")
self.dict_acl[aclsplit[0]] = \
0 if len(aclsplit) == 1 else int(aclsplit[1])
def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei."""
pass
def run(self):
"""Startet Serverkomponente fuer die Annahme neuer Verbindungen."""
proginit.logger.debug("enter RevPiSlave.run()")
# Socket öffnen und konfigurieren
self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while not self._evt_exit.is_set():
try:
self.so.bind(("", self._port))
except:
proginit.logger.warning("can not bind socket - retry")
self._evt_exit.wait(1)
else:
break
self.so.listen(15)
# Mit Socket arbeiten
while not self._evt_exit.is_set():
self.exitcode = -1
# Verbindung annehmen
proginit.logger.debug("accept new connection")
try:
tup_sock = self.so.accept()
except:
if not self._evt_exit.is_set():
proginit.logger.exception("accept exception")
continue
# ACL prüfen
aclstatus = _ipmatch(tup_sock[1][0], self.dict_acl)
if aclstatus == -1:
tup_sock[0].close()
proginit.logger.warning(
"host ip '{}' does not match revpiacl - disconnect"
"".format(tup_sock[1][0])
)
else:
# Thread starten
th = RevPiSlaveDev(tup_sock, aclstatus)
th.start()
self._th_dev.append(th)
# Liste von toten threads befreien
self._th_dev = [
th_check for th_check in self._th_dev if th_check.is_alive()
]
# Alle Threads beenden
for th in self._th_dev:
th.stop()
# Socket schließen
self.so.close()
self.so = None
self.exitcode = 0
proginit.logger.debug("leave RevPiSlave.run()")
def stop(self):
"""Beendet Slaveausfuehrung."""
proginit.logger.debug("enter RevPiSlave.stop()")
self._evt_exit.set()
if self.so is not None:
try:
self.so.shutdown(socket.SHUT_RDWR)
except:
pass
proginit.logger.debug("leave RevPiSlave.stop()")
class RevPiSlaveDev(Thread):
"""Klasse um eine RevPiModIO Verbindung zu verwalten.
Diese Klasste stellt die Funktionen zur Verfuegung um Daten ueber das
Netzwerk mit dem Prozessabbild auszutauschen.
"""
def __init__(self, devcon, acl):
"""Init RevPiSlaveDev-Class.
@param devcon Tuple der Verbindung
@param deadtime Timeout der Vararbeitung
@param acl Berechtigungslevel
"""
super().__init__()
self._acl = acl
self.daemon = True
self._deadtime = None
self._devcon, self._addr = devcon
self._evt_exit = Event()
self._writeerror = False
# Sicherheitsbytes
self.ey_dict = {}
def run(self):
"""Verarbeitet Anfragen von Remoteteilnehmer."""
proginit.logger.debug("enter RevPiSlaveDev.run()")
proginit.logger.info(
"got new connection from host {} with acl {}".format(
self._addr, self._acl)
)
# Prozessabbild öffnen
fh_proc = open(procimg, "r+b", 0)
dirty = True
while not self._evt_exit.is_set():
# Laufzeitberechnung starten
ot = default_timer()
# Meldung erhalten
try:
netcmd = self._devcon.recv(16)
except:
break
# Wenn Meldung ungültig ist aussteigen
if netcmd[0:1] != b'\x01' or netcmd[-1:] != b'\x17':
if netcmd != b'':
proginit.logger.error(
"net cmd not valid {}".format(netcmd)
)
break
cmd = netcmd[1:3]
if cmd == b'DA':
# Processabbild übertragen
# bCMiiii00000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
fh_proc.seek(position)
try:
self._devcon.sendall(fh_proc.read(length))
except:
proginit.logger.error("error while send read data")
break
elif cmd == b'SD' and self._acl == 1:
# Ausgänge empfangen, wenn acl es erlaubt
# bCMiiiic0000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
control = netcmd[7:8]
if control == b'\x1d' and length > 0:
try:
block = self._devcon.recv(length)
except:
proginit.logger.error("error while recv data to write")
self._writeerror = True
break
fh_proc.seek(position)
# Länge der Daten prüfen
if len(block) == length:
fh_proc.write(block)
else:
proginit.logger.error("got wrong length to write")
break
# Record seperator character
if control == b'\x1c':
if self._writeerror:
self._devcon.send(b'\xff')
else:
self._devcon.send(b'\x1e')
self._writeerror = False
elif cmd == b'\x06\x16':
# Just sync
self._devcon.send(b'\x06\x16')
elif cmd == b'CF':
# Socket konfigurieren
# bCMii0000000000b = 16
timeoutms = int.from_bytes(netcmd[3:5], byteorder="little")
self._deadtime = timeoutms / 1000
self._devcon.settimeout(self._deadtime)
# Record seperator character
self._devcon.send(b'\x1e')
elif cmd == b'EY':
# Bytes bei Verbindungsabbruch schreiben
# bCMiiiix0000000b = 16
position = int.from_bytes(
netcmd[3:5], byteorder="little"
)
length = int.from_bytes(
netcmd[5:7], byteorder="little"
)
if netcmd[7:8] == b'\xFF':
# Dirtybytes löschen
if position in self.ey_dict:
del self.ey_dict[position]
# Record seperator character
self._devcon.send(b'\x1e')
proginit.logger.info(
"cleared dirty bytes on position {}"
"".format(position)
)
else:
# Dirtybytes hinzufügen
bytesbuff = bytearray()
try:
while not self._evt_exit.is_set() \
and len(bytesbuff) < length:
block = self._devcon.recv(1024)
bytesbuff += block
if block == b'':
break
except:
proginit.logger.error("error while recv dirty bytes")
break
# Länge der Daten prüfen
if len(bytesbuff) == length:
self.ey_dict[position] = bytesbuff
else:
proginit.logger.error("got wrong length to write")
break
# Record seperator character
self._devcon.send(b'\x1e')
proginit.logger.info(
"got dirty bytes to write on error on position {}"
"".format(position)
)
elif cmd == b'PI':
# piCtory Konfiguration senden
proginit.logger.debug(
"transfair pictory configuration: {}".format(configrsc)
)
fh_pic = open(configrsc, "rb")
while True:
data = fh_pic.read(1024)
if data:
# FIXME: Fehler fangen
self._devcon.send(data)
else:
fh_pic.close()
break
# End-of-Transmission character
self._devcon.send(b'\x04')
continue
elif cmd == b'EX':
# Sauber Verbindung verlassen
dirty = False
self._evt_exit.set()
continue
else:
# Kein gültiges CMD gefunden, abbruch!
break
# Verarbeitungszeit prüfen
if self._deadtime is not None:
comtime = default_timer() - ot
if comtime > self._deadtime:
proginit.logger.warning(
"runtime more than {} ms: {}!".format(
int(self._deadtime * 1000), comtime
)
)
# TODO: Soll ein Fehler ausgelöst werden?
# Dirty verlassen
if dirty:
for pos in self.ey_dict:
fh_proc.seek(pos)
fh_proc.write(self.ey_dict[pos])
proginit.logger.error("dirty shutdown of connection")
fh_proc.close()
self._devcon.close()
self._devcon = None
proginit.logger.info("disconnected from {}".format(self._addr))
proginit.logger.debug("leave RevPiSlaveDev.run()")
def stop(self):
"""Beendet Verbindungsthread."""
proginit.logger.debug("enter RevPiSlaveDev.stop()")
self._evt_exit.set()
if self._devcon is not None:
self._devcon.shutdown(socket.SHUT_RDWR)
proginit.logger.debug("leave RevPiSlaveDev.stop()")
class RevPiPyLoad():
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt.
@@ -546,7 +188,9 @@ class RevPiPyLoad():
# PLC Thread konfigurieren
self.plc = self._plcthread()
if self.plcslave:
self.th_plcslave = RevPiSlave(self.plcslaveacl, self.plcslaveport)
self.th_plcslave = picontrolserver.RevPiSlave(
self.plcslaveacl, self.plcslaveport
)
else:
self.th_plcslave = None
@@ -612,15 +256,17 @@ class RevPiPyLoad():
self.xsrv.register_function(
lambda: os.system(proginit.picontrolreset),
"resetpicontrol")
self.xsrv.register_function(
self.xml_plcslavestop, "plcslavestop")
self.xsrv.register_function(
lambda: os.system(picontrolreset), "resetpicontrol")
lambda: os.system(proginit.picontrolreset),
"resetpicontrol")
self.xsrv.register_function(
self.xml_setconfig, "set_config")
self.xsrv.register_function(
self.xml_setpictoryrsc, "set_pictoryrsc")
self.xsrv.register_function(lambda: pyloadverion, "version")
self.xsrv.register_function(lambda: pyloadversion, "version")
self.xsrv.register_function(lambda: self.xmlrpc, "xmlmodus")
proginit.logger.debug("created xmlrpc server")
@@ -1119,7 +765,7 @@ class RevPiPyLoad():
if self.th_plcslave is not None and self.th_plcslave.is_alive():
return -2
else:
self.th_plcslave = RevPiSlave(
self.th_plcslave = picontrolserver.RevPiSlave(
self.plcslaveacl, self.plcslaveport
)
self.th_plcslave.start()