1
0
mirror of https://github.com/naruxde/revpipycontrol.git synced 2025-11-08 23:53:52 +01:00

28 Commits
0.4.2 ... 0.7.1

Author SHA1 Message Date
79c737ea2f Im Entwirckler einen "Nur hochladen" Button eingebaut
?bersetzung
2018-10-07 12:13:17 +02:00
55c1349edf Etikett 0.7.1 zum ?nderungssatz d6da987846e1 hinzugef?gt 2018-10-07 12:11:56 +02:00
df308600c2 Mit mqtt zusammenf?hren 2018-10-07 12:01:46 +02:00
fb88271364 setting mqttsend_events zu mqttsend_on_event ge?ndert
?bersetzung
2018-10-07 12:01:23 +02:00
fa8fc6a7ce Optionfenster schlie?t bei destroy alle Unterfenster mit
MQTT Settings ingetriert
2018-09-24 10:18:57 +02:00
df4c82579d Mit default zusammenf?hren 2018-09-03 12:25:08 +02:00
220de03774 Programme auf RevPi sortiert anzeigen 2018-09-03 12:20:18 +02:00
f2dd6416ea Watch-Mode IO-Name und IO-Value Seiten getauscht
?bersetzung
Mit develop zusammenf?hren
2018-08-14 09:22:21 +02:00
7d3957a9d1 Fehlerabfang f?r Watch-Mode verbessert 2018-08-14 08:53:56 +02:00
ef912fa907 ?bersetzungen 2018-08-12 17:07:32 +02:00
0fc9af633c Dateiliste sortiert ausgeben
New code style
2018-08-12 16:57:08 +02:00
1d9c28d48b ?bersetzungen 2018-08-02 14:55:01 +02:00
554f19d090 Developer als Frame zu Hauptfenster gelegt
Sockettimeout auf 6 Sekunden ver?ndert
2018-08-02 14:17:07 +02:00
e42cc1a6d2 Wenn Ordner ?bertragen werden soll, wird dieser auch auf RevPi angelegt
Developer-Dialog begonnen
2018-07-31 18:36:12 +02:00
6c2578f84c Etikett 0.6.2 zum ?nderungssatz 995b947a4cc0 hinzugef?gt 2018-06-27 12:45:30 +02:00
37e6dd6a75 Voreinstellungen vom Programmfenster werden wieder ?bernommen 2018-06-27 08:55:49 +02:00
348ef65716 Diensteinstellungen f?r MQTT Publisher in Optionen eingebaut 2018-05-25 08:23:43 +02:00
6ac9466850 Etikett 0.6.1 zum ?nderungssatz 6d55e403b528 hinzugef?gt 2018-04-07 15:18:31 +02:00
56cf5a7b09 Fehlermeldung angepasst, wenn ACL f?r Verbindungs-IP nicht gesetzt ist 2018-04-07 14:57:04 +02:00
3c05f9f024 Umbau f?r make_py Script
msg-Fenster hatte falschen parent
2018-04-07 14:34:49 +02:00
2751a2bd35 Mit revpislave zusammenf?hren 2018-04-07 14:04:35 +02:00
e32383048f ?bersetzung 2018-04-07 14:04:07 +02:00
7fefb1aece RevPiPyLoad Dienste als Gruppe anzeigen
Status der Dienste integriert
FileHandler wurden in Programmfenster nicht geschlossen
programpath.dat wird aufger?umt, wenn RevPi Liste gespeichert wird
2018-04-07 13:39:21 +02:00
a60d029f39 AclManger angepasst, wenn zu leer hinzugef?gt wird
AclManager springt bei IP Eingabe weiter und zur?ck
IpAclManager ausgelagert in shared
shared ?bernehmen (setup.py)
Anzeigelevel angepasst
Einstellungen werden ?bertragen, da RevPiPyLoad diese dynamisch verarbeitet
Codestyle
2018-04-05 15:51:51 +02:00
e322b1d43b Wertepr?fung f?r Optionen
autoreloaddelay in Optionen ?bernommen
ACL Manager schlie?t beim Speichern automatisch
Legacy-Optionen f?r alte RevPiPyLoads laden
2018-04-03 12:05:37 +02:00
a8442b5969 ACL Manger eingebaut 2018-04-03 10:35:58 +02:00
c7d5e4432a codestyle 2017-12-20 15:01:54 +01:00
adc1158f5c Etikett 0.4.2 zum ?nderungssatz 1ee4049416b4 hinzugef?gt 2017-07-06 14:07:39 +02:00
37 changed files with 4547 additions and 786 deletions

256
doc/aclmanager.html Normal file
View File

@@ -0,0 +1,256 @@
<!DOCTYPE html>
<html><head>
<title>aclmanager</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">
aclmanager</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#AclManager">AclManager</a></td>
<td>Hauptfenster des ACL-Managers.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
</table>
<hr /><hr />
<a NAME="AclManager" ID="AclManager"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">AclManager</h2>
<p>
Hauptfenster des ACL-Managers.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
ttk.Frame
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>acl</td></tr><tr><td>acltext</td></tr><tr><td>root</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="#AclManager.__init__">AclManager</a></td>
<td>Init AclManger-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager.__get_acltext">__get_acltext</a></td>
<td>Getter fuer Leveltexte.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager.__set_acltext">__set_acltext</a></td>
<td>Setter fuer Leveltexte.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._ask_delete">_ask_delete</a></td>
<td>L&#246;scht ein Eintrag der Liste.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._checkback">_checkback</a></td>
<td>Springt bei Backspace in vorheriges Feld.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._checkdot">_checkdot</a></td>
<td>Pr&#252;ft auf .</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._clearfields">_clearfields</a></td>
<td>Leert die Eingabefelder.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._createwidgets">_createwidgets</a></td>
<td>Erstellt Widgets.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._loadfields">_loadfields</a></td>
<td>&#220;bernimmt Listeneintrag in Editfelder.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._refreshacls">_refreshacls</a></td>
<td>Leert die ACL Liste und f&#252;llt sie neu.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._save">_save</a></td>
<td>&#220;bernimt die &#196;nderungen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._savefields">_savefields</a></td>
<td>&#220;bernimmt neuen ACL Eintrag.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager._status_editremove">_status_editremove</a></td>
<td>Setzt state der Buttons.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#AclManager.get_acl">get_acl</a></td>
<td>Gibt die Konfigurierten ACL zur&#252;ck.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="AclManager.__init__" ID="AclManager.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager (Constructor)</h3>
<b>AclManager</b>(<i>master, minlevel, maxlevel, acl_str="", readonly=False</i>)
<p>
Init AclManger-Class.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="AclManager.__get_acltext" ID="AclManager.__get_acltext"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager.__get_acltext</h3>
<b>__get_acltext</b>(<i></i>)
<p>
Getter fuer Leveltexte.
</p><dl>
<dt>Returns:</dt>
<dd>
Leveltexte als <class 'dict'>
</dd>
</dl><a NAME="AclManager.__set_acltext" ID="AclManager.__set_acltext"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager.__set_acltext</h3>
<b>__set_acltext</b>(<i>value</i>)
<p>
Setter fuer Leveltexte.
</p><dl>
<dt><i>value</i></dt>
<dd>
Leveltexte als <class 'dict'>
</dd>
</dl><a NAME="AclManager._ask_delete" ID="AclManager._ask_delete"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._ask_delete</h3>
<b>_ask_delete</b>(<i></i>)
<p>
L&#246;scht ein Eintrag der Liste.
</p><a NAME="AclManager._changesdone" ID="AclManager._changesdone"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._changesdone</h3>
<b>_changesdone</b>(<i></i>)
<p>
Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd>
</dl><a NAME="AclManager._checkback" ID="AclManager._checkback"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._checkback</h3>
<b>_checkback</b>(<i>event, tkvar, pretxt</i>)
<p>
Springt bei Backspace in vorheriges Feld.
</p><dl>
<dt><i>event</i></dt>
<dd>
TK Event
</dd><dt><i>tkvar</i></dt>
<dd>
TK Variable zum pr&#252;fen
</dd><dt><i>nexttxt</i></dt>
<dd>
Vorheriges IP Feld f&#252;r Fokus
</dd>
</dl><a NAME="AclManager._checkclose" ID="AclManager._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._checkclose</h3>
<b>_checkclose</b>(<i>event=None</i>)
<p>
Pr&#252;ft ob Fenster beendet werden soll.
</p><dl>
<dt><i>event</i></dt>
<dd>
tkinter-Event
</dd>
</dl><a NAME="AclManager._checkdot" ID="AclManager._checkdot"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._checkdot</h3>
<b>_checkdot</b>(<i>event, tkvar, nexttxt</i>)
<p>
Pr&#252;ft auf . und geht weiter.
</p><dl>
<dt><i>event</i></dt>
<dd>
TK Event
</dd><dt><i>tkvar</i></dt>
<dd>
TK Variable zum pr&#252;fen
</dd><dt><i>nexttxt</i></dt>
<dd>
N&#228;chstes IP Feld f&#252;r Fokus
</dd>
</dl><a NAME="AclManager._clearfields" ID="AclManager._clearfields"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._clearfields</h3>
<b>_clearfields</b>(<i></i>)
<p>
Leert die Eingabefelder.
</p><a NAME="AclManager._createwidgets" ID="AclManager._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._createwidgets</h3>
<b>_createwidgets</b>(<i></i>)
<p>
Erstellt Widgets.
</p><a NAME="AclManager._loadfields" ID="AclManager._loadfields"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._loadfields</h3>
<b>_loadfields</b>(<i></i>)
<p>
&#220;bernimmt Listeneintrag in Editfelder.
</p><a NAME="AclManager._refreshacls" ID="AclManager._refreshacls"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._refreshacls</h3>
<b>_refreshacls</b>(<i></i>)
<p>
Leert die ACL Liste und f&#252;llt sie neu.
</p><a NAME="AclManager._save" ID="AclManager._save"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._save</h3>
<b>_save</b>(<i></i>)
<p>
&#220;bernimt die &#196;nderungen.
</p><a NAME="AclManager._savefields" ID="AclManager._savefields"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._savefields</h3>
<b>_savefields</b>(<i></i>)
<p>
&#220;bernimmt neuen ACL Eintrag.
</p><a NAME="AclManager._status_editremove" ID="AclManager._status_editremove"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager._status_editremove</h3>
<b>_status_editremove</b>(<i>tkevt</i>)
<p>
Setzt state der Buttons.
</p><a NAME="AclManager.get_acl" ID="AclManager.get_acl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
AclManager.get_acl</h3>
<b>get_acl</b>(<i></i>)
<p>
Gibt die Konfigurierten ACL zur&#252;ck.
</p><dl>
<dt>Returns:</dt>
<dd>
ACL als <class 'str'>
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html><head>
<title>revpipycontrol.shared</title>
<meta charset="UTF-8">
</head>
<body style="background-color:#FFFFFF;color:#000000">
<h1 style="background-color:#FFFFFF;color:#0000FF">
revpipycontrol.shared</h1>
<p>
Shared modules.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Modules</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="revpipycontrol.shared.ipaclmanager.html">ipaclmanager</a></td>
<td>Verwaltet IP Adressen und deren ACLs.</td>
</tr>
</table>
</body></html>

View File

@@ -8,20 +8,40 @@
Table of contents</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Packages</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="index-revpipycontrol.shared.html">shared</a></td>
<td>Shared modules.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Modules</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="mytools.html">mytools</a></td>
<td><a style="color:#0000FF" href="aclmanager.html">aclmanager</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="mqttmanager.html">mqttmanager</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="mytools.html">mytools</a></td>
<td>Tools-Sammlung.</td>
</tr><tr>
<td><a style="color:#0000FF" href="revpicheckclient.html">revpicheckclient</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="revpidevelop.html">revpidevelop</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="revpiinfo.html">revpiinfo</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="revpilegacy.html">revpilegacy</a></td>
<td></td>
</tr><tr>
<td><a style="color:#0000FF" href="revpilogfile.html">revpilogfile</a></td>
<td></td>
</tr><tr>

134
doc/mqttmanager.html Normal file
View File

@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html><head>
<title>mqttmanager</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">
mqttmanager</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#MqttManager">MqttManager</a></td>
<td>Hauptfenster der MQTT-Einstellungen.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
</table>
<hr /><hr />
<a NAME="MqttManager" ID="MqttManager"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">MqttManager</h2>
<p>
Hauptfenster der MQTT-Einstellungen.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>dict_mqttsettings</td></tr><tr><td>root</td></tr><tr><td>settings</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="#MqttManager.__init__">MqttManager</a></td>
<td>Init MqttManager-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttManager._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttManager._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttManager._createwidgets">_createwidgets</a></td>
<td>Erstellt Widgets.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttManager._save">_save</a></td>
<td>&#220;bernimt die &#196;nderungen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#MqttManager.get_settings">get_settings</a></td>
<td>Gibt die MQTT Konfiguration zur&#252;ck.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="MqttManager.__init__" ID="MqttManager.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager (Constructor)</h3>
<b>MqttManager</b>(<i>master, settings, readonly=False</i>)
<p>
Init MqttManager-Class.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="MqttManager._changesdone" ID="MqttManager._changesdone"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager._changesdone</h3>
<b>_changesdone</b>(<i></i>)
<p>
Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd>
</dl><a NAME="MqttManager._checkclose" ID="MqttManager._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager._checkclose</h3>
<b>_checkclose</b>(<i>event=None</i>)
<p>
Pr&#252;ft ob Fenster beendet werden soll.
</p><dl>
<dt><i>event</i></dt>
<dd>
tkinter-Event
</dd>
</dl><a NAME="MqttManager._createwidgets" ID="MqttManager._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager._createwidgets</h3>
<b>_createwidgets</b>(<i></i>)
<p>
Erstellt Widgets.
</p><a NAME="MqttManager._save" ID="MqttManager._save"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager._save</h3>
<b>_save</b>(<i></i>)
<p>
&#220;bernimt die &#196;nderungen.
</p><a NAME="MqttManager.get_settings" ID="MqttManager.get_settings"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
MqttManager.get_settings</h3>
<b>get_settings</b>(<i></i>)
<p>
Gibt die MQTT Konfiguration zur&#252;ck.
</p><dl>
<dt>Returns:</dt>
<dd>
Settings als <class 'dict'>
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -6,11 +6,13 @@
<body style="background-color:#FFFFFF;color:#000000"><a NAME="top" ID="top"></a>
<h1 style="background-color:#FFFFFF;color:#0000FF">
mytools</h1>
<p>
Tools-Sammlung.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>None</td></tr>
<tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr><tr><td>savefile_connections</td></tr><tr><td>savefile_developer</td></tr><tr><td>savefile_programpath</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
@@ -25,7 +27,7 @@ Functions</h3>
<td>H&#228;ngt root-dir der Anwendung vor Dateinamen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#gettrans">gettrans</a></td>
<td></td>
<td>Wertet die Sprache des OS aus und gibt &#220;bersetzung zur&#252;ck.</td>
</tr>
</table>
<hr /><hr />
@@ -53,7 +55,19 @@ root dir
<a NAME="gettrans" ID="gettrans"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">gettrans</h2>
<b>gettrans</b>(<i>proglang=None</i>)
<p>
Wertet die Sprache des OS aus und gibt &#220;bersetzung zur&#252;ck.
</p><dl>
<dt><i>proglang</i></dt>
<dd>
Bestimmte Sprache laden
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
gettext &#220;bersetzung f&#252;r Zuweisung an '_'
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -10,14 +10,14 @@ revpicheckclient</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiCheckClient">RevPiCheckClient</a></td>
<td></td>
<td>Baut Fenstererweiterung f&#252;r 'watch modus'.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -28,7 +28,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiCheckClient" ID="RevPiCheckClient"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiCheckClient</h2>
<p>
Baut Fenstererweiterung f&#252;r 'watch modus'.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame

197
doc/revpidevelop.html Normal file
View File

@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html><head>
<title>revpidevelop</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">
revpidevelop</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiDevelop">RevPiDevelop</a></td>
<td>Zeigt Debugfenster an.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#_loaddefaults">_loaddefaults</a></td>
<td>&#220;bernimmt f&#252;r den Pi die letzen Pfade.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#_savedefaults">_savedefaults</a></td>
<td>Schreibt fuer den Pi die letzen Pfade.</td>
</tr>
</table>
<hr /><hr />
<a NAME="RevPiDevelop" ID="RevPiDevelop"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiDevelop</h2>
<p>
Zeigt Debugfenster an.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
ttk.Frame
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>app</td></tr><tr><td>cli</td></tr><tr><td>root</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="#RevPiDevelop.__init__">RevPiDevelop</a></td>
<td>Init RevPiDevelop-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop._createwidgets">_createwidgets</a></td>
<td>Erstellt alle Widgets.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop.btn_domyjob">btn_domyjob</a></td>
<td>Hochladen und neu starten.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop.btn_selectpath">btn_selectpath</a></td>
<td>L&#228;sst dem Benuzter ein Verzeichnis ausw&#228;hlen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop.load_pathfiles">load_pathfiles</a></td>
<td>Aktualisiert die Dateiliste.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop.refresh_stats">refresh_stats</a></td>
<td>Passt die Widgets an.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiDevelop.select_pathfiles">select_pathfiles</a></td>
<td>Setzt state der Buttons.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiDevelop.__init__" ID="RevPiDevelop.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop (Constructor)</h3>
<b>RevPiDevelop</b>(<i>master, xmlcli, xmlmode, revpi</i>)
<p>
Init RevPiDevelop-Class.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="RevPiDevelop._checkclose" ID="RevPiDevelop._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop._checkclose</h3>
<b>_checkclose</b>(<i>event=None</i>)
<p>
Pr&#252;ft ob Fenster beendet werden soll.
</p><dl>
<dt><i>event</i></dt>
<dd>
tkinter-Event
</dd>
</dl><a NAME="RevPiDevelop._createwidgets" ID="RevPiDevelop._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop._createwidgets</h3>
<b>_createwidgets</b>(<i></i>)
<p>
Erstellt alle Widgets.
</p><a NAME="RevPiDevelop.btn_domyjob" ID="RevPiDevelop.btn_domyjob"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop.btn_domyjob</h3>
<b>btn_domyjob</b>(<i>stop_restart=True</i>)
<p>
Hochladen und neu starten.
</p><dl>
<dt><i>stop_restart</i></dt>
<dd>
Bestehendes Programm Beenden/Starten
</dd>
</dl><a NAME="RevPiDevelop.btn_selectpath" ID="RevPiDevelop.btn_selectpath"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop.btn_selectpath</h3>
<b>btn_selectpath</b>(<i></i>)
<p>
L&#228;sst dem Benuzter ein Verzeichnis ausw&#228;hlen.
</p><a NAME="RevPiDevelop.load_pathfiles" ID="RevPiDevelop.load_pathfiles"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop.load_pathfiles</h3>
<b>load_pathfiles</b>(<i>silent=False</i>)
<p>
Aktualisiert die Dateiliste.
</p><dl>
<dt><i>silent</i></dt>
<dd>
Keinen Dialog anzeigen
</dd>
</dl><a NAME="RevPiDevelop.refresh_stats" ID="RevPiDevelop.refresh_stats"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop.refresh_stats</h3>
<b>refresh_stats</b>(<i></i>)
<p>
Passt die Widgets an.
</p><a NAME="RevPiDevelop.select_pathfiles" ID="RevPiDevelop.select_pathfiles"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiDevelop.select_pathfiles</h3>
<b>select_pathfiles</b>(<i>tkevt</i>)
<p>
Setzt state der Buttons.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_loaddefaults" ID="_loaddefaults"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_loaddefaults</h2>
<b>_loaddefaults</b>(<i>revpiname=None</i>)
<p>
&#220;bernimmt f&#252;r den Pi die letzen Pfade.
</p><dl>
<dt><i>revpiname</i></dt>
<dd>
Einstellungen nur f&#252;r RevPi laden
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
<class 'dict'> mit Einstellungen
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_savedefaults" ID="_savedefaults"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_savedefaults</h2>
<b>_savedefaults</b>(<i>revpiname, settings</i>)
<p>
Schreibt fuer den Pi die letzen Pfade.
</p><dl>
<dt><i>revpiname</i></dt>
<dd>
Einstellungen sind f&#252;r diesen RevPi
</dd><dt><i>settings</i></dt>
<dd>
<class 'dict'> mit Einstellungen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, bei erfolgreicher Verarbeitung
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -10,14 +10,14 @@ revpiinfo</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiInfo">RevPiInfo</a></td>
<td></td>
<td>Baut Frame f&#252;r Programminformationen.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -28,7 +28,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiInfo" ID="RevPiInfo"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiInfo</h2>
<p>
Baut Frame f&#252;r Programminformationen.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame

166
doc/revpilegacy.html Normal file
View File

@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html><head>
<title>revpilegacy</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">
revpilegacy</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiOption">RevPiOption</a></td>
<td>Optionen f&#252;r RevPiPyload vor 0.6.0.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
</table>
<hr /><hr />
<a NAME="RevPiOption" ID="RevPiOption"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiOption</h2>
<p>
Optionen f&#252;r RevPiPyload vor 0.6.0.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
<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="#RevPiOption.__init__">RevPiOption</a></td>
<td>Init RevPiOption-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._createwidgets">_createwidgets</a></td>
<td>Erstellt Widgets.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._loadappdata">_loadappdata</a></td>
<td>L&#228;d aktuelle Einstellungen vom RevPi.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._setappdata">_setappdata</a></td>
<td>Speichert ge&#228;nderte Einstellungen auf RevPi.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.askxmlon">askxmlon</a></td>
<td>Fragt Nuter, ob wirklicht abgeschaltet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod2_tail">xmlmod2_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod_tail">xmlmod_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiOption.__init__" ID="RevPiOption.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption (Constructor)</h3>
<b>RevPiOption</b>(<i>master, xmlcli</i>)
<p>
Init RevPiOption-Class.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="RevPiOption._changesdone" ID="RevPiOption._changesdone"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._changesdone</h3>
<b>_changesdone</b>(<i></i>)
<p>
Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd>
</dl><a NAME="RevPiOption._checkclose" ID="RevPiOption._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._checkclose</h3>
<b>_checkclose</b>(<i>event=None</i>)
<p>
Pr&#252;ft ob Fenster beendet werden soll.
</p><dl>
<dt><i>event</i></dt>
<dd>
tkinter-Event
</dd>
</dl><a NAME="RevPiOption._createwidgets" ID="RevPiOption._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._createwidgets</h3>
<b>_createwidgets</b>(<i></i>)
<p>
Erstellt Widgets.
</p><a NAME="RevPiOption._loadappdata" ID="RevPiOption._loadappdata"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._loadappdata</h3>
<b>_loadappdata</b>(<i>refresh=False</i>)
<p>
L&#228;d aktuelle Einstellungen vom RevPi.
</p><dl>
<dt><i>refresh</i></dt>
<dd>
Wenn True, werden Einstellungen heruntergeladen.
</dd>
</dl><a NAME="RevPiOption._setappdata" ID="RevPiOption._setappdata"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._setappdata</h3>
<b>_setappdata</b>(<i></i>)
<p>
Speichert ge&#228;nderte Einstellungen auf RevPi.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="RevPiOption.askxmlon" ID="RevPiOption.askxmlon"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.askxmlon</h3>
<b>askxmlon</b>(<i></i>)
<p>
Fragt Nuter, ob wirklicht abgeschaltet werden soll.
</p><a NAME="RevPiOption.xmlmod2_tail" ID="RevPiOption.xmlmod2_tail"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod2_tail</h3>
<b>xmlmod2_tail</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
</p><a NAME="RevPiOption.xmlmod_tail" ID="RevPiOption.xmlmod_tail"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod_tail</h3>
<b>xmlmod_tail</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -10,14 +10,14 @@ revpilogfile</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiLogfile">RevPiLogfile</a></td>
<td></td>
<td>Baut Fenster f&#252;r Logfiles.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -28,7 +28,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiLogfile" ID="RevPiLogfile"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiLogfile</h2>
<p>
Baut Fenster f&#252;r Logfiles.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame

View File

@@ -10,14 +10,14 @@ revpioption</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiOption">RevPiOption</a></td>
<td></td>
<td>Zeigt Optionen von RevPiPyLoad an.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -28,7 +28,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiOption" ID="RevPiOption"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiOption</h2>
<p>
Zeigt Optionen von RevPiPyLoad an.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
@@ -52,9 +54,15 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiOption._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._changesdone_mqtt">_changesdone_mqtt</a></td>
<td>Pr&#252;ft ob MQTT-Settings ge&#228;ndert wurden.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._checkvalues">_checkvalues</a></td>
<td>Pr&#252;ft alle Werte auf G&#252;ltigkeit.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._createwidgets">_createwidgets</a></td>
<td>Erstellt Widgets.</td>
</tr><tr>
@@ -67,11 +75,17 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiOption.askxmlon">askxmlon</a></td>
<td>Fragt Nuter, ob wirklicht abgeschaltet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod2_tail">xmlmod2_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
<td><a style="color:#0000FF" href="#RevPiOption.btn_mqttsettings">btn_mqttsettings</a></td>
<td>&#214;ffnet Fenster f&#252;r MQTT Einstellungen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod_tail">xmlmod_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
<td><a style="color:#0000FF" href="#RevPiOption.btn_slaveacl">btn_slaveacl</a></td>
<td>&#214;ffnet Fenster f&#252;r ACL-Verwaltung.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.btn_xmlacl">btn_xmlacl</a></td>
<td>&#214;ffnet Fenster f&#252;r ACL-Verwaltung.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.destroy">destroy</a></td>
<td>Beendet alle Unterfenster und sich selbst.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -101,6 +115,17 @@ Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
<dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd>
</dl><a NAME="RevPiOption._changesdone_mqtt" ID="RevPiOption._changesdone_mqtt"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._changesdone_mqtt</h3>
<b>_changesdone_mqtt</b>(<i></i>)
<p>
Pr&#252;ft ob MQTT-Settings ge&#228;ndert wurden.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn &#196;nderungen existieren
</dd>
</dl><a NAME="RevPiOption._checkclose" ID="RevPiOption._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._checkclose</h3>
@@ -112,6 +137,17 @@ Pr&#252;ft ob Fenster beendet werden soll.
<dd>
tkinter-Event
</dd>
</dl><a NAME="RevPiOption._checkvalues" ID="RevPiOption._checkvalues"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._checkvalues</h3>
<b>_checkvalues</b>(<i></i>)
<p>
Pr&#252;ft alle Werte auf G&#252;ltigkeit.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn alle Werte g&#252;ltig sind
</dd>
</dl><a NAME="RevPiOption._createwidgets" ID="RevPiOption._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._createwidgets</h3>
@@ -146,18 +182,30 @@ RevPiOption.askxmlon</h3>
<b>askxmlon</b>(<i></i>)
<p>
Fragt Nuter, ob wirklicht abgeschaltet werden soll.
</p><a NAME="RevPiOption.xmlmod2_tail" ID="RevPiOption.xmlmod2_tail"></a>
</p><a NAME="RevPiOption.btn_mqttsettings" ID="RevPiOption.btn_mqttsettings"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod2_tail</h3>
<b>xmlmod2_tail</b>(<i></i>)
RevPiOption.btn_mqttsettings</h3>
<b>btn_mqttsettings</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
</p><a NAME="RevPiOption.xmlmod_tail" ID="RevPiOption.xmlmod_tail"></a>
&#214;ffnet Fenster f&#252;r MQTT Einstellungen.
</p><a NAME="RevPiOption.btn_slaveacl" ID="RevPiOption.btn_slaveacl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod_tail</h3>
<b>xmlmod_tail</b>(<i></i>)
RevPiOption.btn_slaveacl</h3>
<b>btn_slaveacl</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
&#214;ffnet Fenster f&#252;r ACL-Verwaltung.
</p><a NAME="RevPiOption.btn_xmlacl" ID="RevPiOption.btn_xmlacl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.btn_xmlacl</h3>
<b>btn_xmlacl</b>(<i></i>)
<p>
&#214;ffnet Fenster f&#252;r ACL-Verwaltung.
</p><a NAME="RevPiOption.destroy" ID="RevPiOption.destroy"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.destroy</h3>
<b>destroy</b>(<i></i>)
<p>
Beendet alle Unterfenster und sich selbst.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />

164
doc/revpioptionlegacy.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html><head>
<title>revpioptionlegacy</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">
revpioptionlegacy</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiOption">RevPiOption</a></td>
<td></td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
</table>
<hr /><hr />
<a NAME="RevPiOption" ID="RevPiOption"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiOption</h2>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
<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="#RevPiOption.__init__">RevPiOption</a></td>
<td>Init RevPiOption-Class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._createwidgets">_createwidgets</a></td>
<td>Erstellt Widgets.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._loadappdata">_loadappdata</a></td>
<td>L&#228;d aktuelle Einstellungen vom RevPi.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._setappdata">_setappdata</a></td>
<td>Speichert ge&#228;nderte Einstellungen auf RevPi.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.askxmlon">askxmlon</a></td>
<td>Fragt Nuter, ob wirklicht abgeschaltet werden soll.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod2_tail">xmlmod2_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.xmlmod_tail">xmlmod_tail</a></td>
<td>Passt XML-Optionszugriff an.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="RevPiOption.__init__" ID="RevPiOption.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption (Constructor)</h3>
<b>RevPiOption</b>(<i>master, xmlcli</i>)
<p>
Init RevPiOption-Class.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="RevPiOption._changesdone" ID="RevPiOption._changesdone"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._changesdone</h3>
<b>_changesdone</b>(<i></i>)
<p>
Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
</p><dl>
<dt>Returns:</dt>
<dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd>
</dl><a NAME="RevPiOption._checkclose" ID="RevPiOption._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._checkclose</h3>
<b>_checkclose</b>(<i>event=None</i>)
<p>
Pr&#252;ft ob Fenster beendet werden soll.
</p><dl>
<dt><i>event</i></dt>
<dd>
tkinter-Event
</dd>
</dl><a NAME="RevPiOption._createwidgets" ID="RevPiOption._createwidgets"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._createwidgets</h3>
<b>_createwidgets</b>(<i></i>)
<p>
Erstellt Widgets.
</p><a NAME="RevPiOption._loadappdata" ID="RevPiOption._loadappdata"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._loadappdata</h3>
<b>_loadappdata</b>(<i>refresh=False</i>)
<p>
L&#228;d aktuelle Einstellungen vom RevPi.
</p><dl>
<dt><i>refresh</i></dt>
<dd>
Wenn True, werden Einstellungen heruntergeladen.
</dd>
</dl><a NAME="RevPiOption._setappdata" ID="RevPiOption._setappdata"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._setappdata</h3>
<b>_setappdata</b>(<i></i>)
<p>
Speichert ge&#228;nderte Einstellungen auf RevPi.
</p><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl><a NAME="RevPiOption.askxmlon" ID="RevPiOption.askxmlon"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.askxmlon</h3>
<b>askxmlon</b>(<i></i>)
<p>
Fragt Nuter, ob wirklicht abgeschaltet werden soll.
</p><a NAME="RevPiOption.xmlmod2_tail" ID="RevPiOption.xmlmod2_tail"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod2_tail</h3>
<b>xmlmod2_tail</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
</p><a NAME="RevPiOption.xmlmod_tail" ID="RevPiOption.xmlmod_tail"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.xmlmod_tail</h3>
<b>xmlmod_tail</b>(<i></i>)
<p>
Passt XML-Optionszugriff an.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -10,14 +10,14 @@ revpiplclist</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>savefile</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiPlcList">RevPiPlcList</a></td>
<td></td>
<td>TK Fenster.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -31,7 +31,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiPlcList" ID="RevPiPlcList"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiPlcList</h2>
<p>
TK Fenster.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame

View File

@@ -10,25 +10,33 @@ revpiprogram</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>savefile</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiProgram">RevPiProgram</a></td>
<td></td>
<td>Zeigt Programmfenster an.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<tr><td>None</td></tr>
<tr>
<td><a style="color:#0000FF" href="#_loaddefaults">_loaddefaults</a></td>
<td>&#220;bernimmt f&#252;r den Pi die letzen Pfade.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#_savedefaults">_savedefaults</a></td>
<td>Schreibt fuer den Pi die letzen Pfade.</td>
</tr>
</table>
<hr /><hr />
<a NAME="RevPiProgram" ID="RevPiProgram"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiProgram</h2>
<p>
Zeigt Programmfenster an.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
@@ -61,12 +69,6 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiProgram._evt_optup">_evt_optup</a></td>
<td>Passt je nach gew&#228;hlter Option den Status der Widgets an.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiProgram._loaddefault">_loaddefault</a></td>
<td>&#220;bernimmt f&#252;r den Pi die letzen Pfade.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiProgram._savedefaults">_savedefaults</a></td>
<td>Schreibt fuer den Pi die letzen Pfade.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiProgram.check_replacedir">check_replacedir</a></td>
<td>Gibt das rootdir von einem entpackten Verzeichnis zurueck.</td>
</tr><tr>
@@ -137,34 +139,7 @@ RevPiProgram._evt_optup</h3>
<b>_evt_optup</b>(<i>text=""</i>)
<p>
Passt je nach gew&#228;hlter Option den Status der Widgets an.
</p><a NAME="RevPiProgram._loaddefault" ID="RevPiProgram._loaddefault"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiProgram._loaddefault</h3>
<b>_loaddefault</b>(<i>full=False</i>)
<p>
&#220;bernimmt f&#252;r den Pi die letzen Pfade.
</p><dl>
<dt><i>full</i></dt>
<dd>
Einstellungen f&#252;r alle Verbindungen laden
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
dict() mit Einstellungen
</dd>
</dl><a NAME="RevPiProgram._savedefaults" ID="RevPiProgram._savedefaults"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiProgram._savedefaults</h3>
<b>_savedefaults</b>(<i></i>)
<p>
Schreibt fuer den Pi die letzen Pfade.
</p><dl>
<dt>Returns:</dt>
<dd>
True, bei erfolgreicher Verarbeitung
</dd>
</dl><a NAME="RevPiProgram.check_replacedir" ID="RevPiProgram.check_replacedir"></a>
</p><a NAME="RevPiProgram.check_replacedir" ID="RevPiProgram.check_replacedir"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiProgram.check_replacedir</h3>
<b>check_replacedir</b>(<i>rootdir</i>)
@@ -242,5 +217,44 @@ RevPiProgram.setpictoryrsc</h3>
&#220;bertr&#228;gt die angegebene piCtory-Konfiguration.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_loaddefaults" ID="_loaddefaults"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_loaddefaults</h2>
<b>_loaddefaults</b>(<i>revpiname=None</i>)
<p>
&#220;bernimmt f&#252;r den Pi die letzen Pfade.
</p><dl>
<dt><i>revpiname</i></dt>
<dd>
Einstellungen nur f&#252;r RevPi laden
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
<class 'dict'> mit Einstellungen
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_savedefaults" ID="_savedefaults"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_savedefaults</h2>
<b>_savedefaults</b>(<i>revpiname, settings</i>)
<p>
Schreibt fuer den Pi die letzen Pfade.
</p><dl>
<dt><i>revpiname</i></dt>
<dd>
Einstellungen sind f&#252;r diesen RevPi
</dd><dt><i>settings</i></dt>
<dd>
<class 'dict'> mit Einstellungen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, bei erfolgreicher Verarbeitung
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

View File

@@ -10,14 +10,14 @@ revpipycontrol</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>_</td></tr><tr><td>pycontrolversion</td></tr>
<tr><td>_</td></tr><tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr><tr><td>__version__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#RevPiPyControl">RevPiPyControl</a></td>
<td></td>
<td>Baut Hauptprogramm auf.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -28,7 +28,9 @@ Functions</h3>
<hr /><hr />
<a NAME="RevPiPyControl" ID="RevPiPyControl"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">RevPiPyControl</h2>
<p>
Baut Hauptprogramm auf.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
tkinter.Frame
@@ -76,6 +78,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiPyControl.plcdebug">plcdebug</a></td>
<td>Baut den Debugframe und packt ihn.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPyControl.plcdevelop">plcdevelop</a></td>
<td>Startet das Developfenster.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiPyControl.plclist">plclist</a></td>
<td>&#214;ffnet das Fenster f&#252;r die Verbindungen.</td>
</tr><tr>
@@ -198,7 +203,13 @@ Baut den Debugframe und packt ihn.
<dd>
None
</dd>
</dl><a NAME="RevPiPyControl.plclist" ID="RevPiPyControl.plclist"></a>
</dl><a NAME="RevPiPyControl.plcdevelop" ID="RevPiPyControl.plcdevelop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPyControl.plcdevelop</h3>
<b>plcdevelop</b>(<i></i>)
<p>
Startet das Developfenster.
</p><a NAME="RevPiPyControl.plclist" ID="RevPiPyControl.plclist"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPyControl.plclist</h3>
<b>plclist</b>(<i></i>)

View File

@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html><head>
<title>revpipycontrol.shared.ipaclmanager</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">
revpipycontrol.shared.ipaclmanager</h1>
<p>
Verwaltet IP Adressen und deren ACLs.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3>
<table>
<tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#IpAclManager">IpAclManager</a></td>
<td>Verwaltung fuer IP Adressen und deren ACL Level.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3>
<table>
<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="IpAclManager" ID="IpAclManager"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">IpAclManager</h2>
<p>
Verwaltung fuer IP Adressen und deren ACL Level.
</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>acl</td></tr><tr><td>filename</td></tr><tr><td>regex_acl</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="#IpAclManager.__init__">IpAclManager</a></td>
<td>Init IpAclManager class.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.__get_acl">__get_acl</a></td>
<td>Getter fuer den rohen ACL-String.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.__get_filename">__get_filename</a></td>
<td>Getter fuer Dateinamen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.__get_regex_acl">__get_regex_acl</a></td>
<td>Gibt formatierten RegEx-String zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.__iter__">__iter__</a></td>
<td>Gibt einzelne ACLs als <class 'tuple'> aus.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.__set_acl">__set_acl</a></td>
<td>Uebernimmt neue ACL-Liste fuer die Ausertung der Level.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.get_acllevel">get_acllevel</a></td>
<td>Prueft IP gegen ACL List und gibt ACL-Wert aus.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.loadacl">loadacl</a></td>
<td>Laed ACL String und gibt erfolg zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.loadaclfile">loadaclfile</a></td>
<td>Laed ACL Definitionen aus Datei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IpAclManager.writeaclfile">writeaclfile</a></td>
<td>Schreibt ACL Definitionen in Datei.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="IpAclManager.__init__" ID="IpAclManager.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager (Constructor)</h3>
<b>IpAclManager</b>(<i>minlevel, maxlevel, acl=None</i>)
<p>
Init IpAclManager class.
</p><dl>
<dt><i>minlevel</i></dt>
<dd>
Smallest access level (min. 0)
</dd><dt><i>maxlevel</i></dt>
<dd>
Biggest access level (max. 9)
</dd><dt><i>acl</i></dt>
<dd>
ACL Liste fuer Berechtigungen als <class 'str'>
</dd>
</dl><a NAME="IpAclManager.__get_acl" ID="IpAclManager.__get_acl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.__get_acl</h3>
<b>__get_acl</b>(<i></i>)
<p>
Getter fuer den rohen ACL-String.
return ACLs als <class 'str'>
</p><a NAME="IpAclManager.__get_filename" ID="IpAclManager.__get_filename"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.__get_filename</h3>
<b>__get_filename</b>(<i></i>)
<p>
Getter fuer Dateinamen.
</p><dl>
<dt>Returns:</dt>
<dd>
Filename der ACL <class 'str'>
</dd>
</dl><a NAME="IpAclManager.__get_regex_acl" ID="IpAclManager.__get_regex_acl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.__get_regex_acl</h3>
<b>__get_regex_acl</b>(<i></i>)
<p>
Gibt formatierten RegEx-String zurueck.
return RegEx Code als <class 'str'>
</p><a NAME="IpAclManager.__iter__" ID="IpAclManager.__iter__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.__iter__</h3>
<b>__iter__</b>(<i></i>)
<p>
Gibt einzelne ACLs als <class 'tuple'> aus.
</p><a NAME="IpAclManager.__set_acl" ID="IpAclManager.__set_acl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.__set_acl</h3>
<b>__set_acl</b>(<i>value</i>)
<p>
Uebernimmt neue ACL-Liste fuer die Ausertung der Level.
</p><dl>
<dt><i>value</i></dt>
<dd>
Neue ACL-Liste als <class 'str'>
</dd>
</dl><a NAME="IpAclManager.get_acllevel" ID="IpAclManager.get_acllevel"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.get_acllevel</h3>
<b>get_acllevel</b>(<i>ipaddress</i>)
<p>
Prueft IP gegen ACL List und gibt ACL-Wert aus.
</p><dl>
<dt><i>ipaddress</i></dt>
<dd>
zum pruefen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
<class 'int'> ACL Wert oder -1 wenn nicht gefunden
</dd>
</dl><a NAME="IpAclManager.loadacl" ID="IpAclManager.loadacl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.loadacl</h3>
<b>loadacl</b>(<i>str_acl</i>)
<p>
Laed ACL String und gibt erfolg zurueck.
</p><dl>
<dt><i>str_acl</i></dt>
<dd>
ACL als <class 'str'>
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn erfolgreich uebernommen
</dd>
</dl><a NAME="IpAclManager.loadaclfile" ID="IpAclManager.loadaclfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.loadaclfile</h3>
<b>loadaclfile</b>(<i>filename</i>)
<p>
Laed ACL Definitionen aus Datei.
</p><dl>
<dt><i>filename</i></dt>
<dd>
Dateiname fuer Definitionen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn Laden erfolgreich war
</dd>
</dl><a NAME="IpAclManager.writeaclfile" ID="IpAclManager.writeaclfile"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IpAclManager.writeaclfile</h3>
<b>writeaclfile</b>(<i>filename=None, aclname=None</i>)
<p>
Schreibt ACL Definitionen in Datei.
</p><dl>
<dt><i>filename</i></dt>
<dd>
Dateiname fuer Definitionen
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn Schreiben erfolgreich war
</dd>
</dl>
<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>)
<p>
re.fullmatch wegen alter python version aus wheezy nachgebaut.
</p><dl>
<dt><i>regex</i></dt>
<dd>
RegEx Statement
</dd><dt><i>string</i></dt>
<dd>
Zeichenfolge gegen die getestet wird
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn komplett passt sonst False
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr />
</body></html>

221
eric-revpipycontrol.api Normal file
View File

@@ -0,0 +1,221 @@
aclmanager.AclManager.__get_acltext?6()
aclmanager.AclManager.__set_acltext?6(value)
aclmanager.AclManager._ask_delete?5()
aclmanager.AclManager._changesdone?5()
aclmanager.AclManager._checkback?5(event, tkvar, pretxt)
aclmanager.AclManager._checkclose?5(event=None)
aclmanager.AclManager._checkdot?5(event, tkvar, nexttxt)
aclmanager.AclManager._clearfields?5()
aclmanager.AclManager._createwidgets?5()
aclmanager.AclManager._loadfields?5()
aclmanager.AclManager._refreshacls?5()
aclmanager.AclManager._save?5()
aclmanager.AclManager._savefields?5()
aclmanager.AclManager._status_editremove?5(tkevt)
aclmanager.AclManager.acl?7
aclmanager.AclManager.acltext?7
aclmanager.AclManager.get_acl?4()
aclmanager.AclManager.root?7
aclmanager.AclManager?1(master, minlevel, maxlevel, acl_str="", readonly=False)
aclmanager._?8
aclmanager.__author__?9
aclmanager.__copyright__?9
aclmanager.__license__?9
mqttmanager.MqttManager._changesdone?5()
mqttmanager.MqttManager._checkclose?5(event=None)
mqttmanager.MqttManager._createwidgets?5()
mqttmanager.MqttManager._save?5()
mqttmanager.MqttManager.dict_mqttsettings?7
mqttmanager.MqttManager.get_settings?4()
mqttmanager.MqttManager.root?7
mqttmanager.MqttManager.settings?7
mqttmanager.MqttManager?1(master, settings, readonly=False)
mqttmanager._?8
mqttmanager.__author__?9
mqttmanager.__copyright__?9
mqttmanager.__license__?9
mytools.__author__?9
mytools.__copyright__?9
mytools.__license__?9
mytools.addroot?4(filename)
mytools.gettrans?4(proglang=None)
mytools.savefile_connections?7
mytools.savefile_developer?7
mytools.savefile_programpath?7
revpicheckclient.RevPiCheckClient.__chval?6(device, io, event=None)
revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None)
revpicheckclient.RevPiCheckClient.__saveoldvalue?6(event, tkvar)
revpicheckclient.RevPiCheckClient.__showwin?6(win)
revpicheckclient.RevPiCheckClient.__spinboxkey?6(device, io, event=None)
revpicheckclient.RevPiCheckClient._createiogroup?5(device, frame, iotype)
revpicheckclient.RevPiCheckClient._createwidgets?5()
revpicheckclient.RevPiCheckClient._onfrmconf?5(canvas)
revpicheckclient.RevPiCheckClient._warnwrite?5()
revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False)
revpicheckclient.RevPiCheckClient.hideallwindows?4()
revpicheckclient.RevPiCheckClient.maxint?4(bytelen)
revpicheckclient.RevPiCheckClient.readvalues?4()
revpicheckclient.RevPiCheckClient.refreshvalues?4()
revpicheckclient.RevPiCheckClient.tmr_workvalues?4()
revpicheckclient.RevPiCheckClient.toggleauto?4()
revpicheckclient.RevPiCheckClient.togglewrite?4()
revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist)
revpicheckclient.RevPiCheckClient.writevalues?4()
revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0)
revpicheckclient._?8
revpicheckclient.__author__?9
revpicheckclient.__copyright__?9
revpicheckclient.__license__?9
revpidevelop.RevPiDevelop._checkclose?5(event=None)
revpidevelop.RevPiDevelop._createwidgets?5()
revpidevelop.RevPiDevelop.app?7
revpidevelop.RevPiDevelop.btn_domyjob?4(stop_restart=True)
revpidevelop.RevPiDevelop.btn_selectpath?4()
revpidevelop.RevPiDevelop.cli?7
revpidevelop.RevPiDevelop.load_pathfiles?4(silent=False)
revpidevelop.RevPiDevelop.refresh_stats?4()
revpidevelop.RevPiDevelop.root?7
revpidevelop.RevPiDevelop.select_pathfiles?4(tkevt)
revpidevelop.RevPiDevelop?1(master, xmlcli, xmlmode, revpi)
revpidevelop._?8
revpidevelop.__author__?9
revpidevelop.__copyright__?9
revpidevelop.__license__?9
revpidevelop._loaddefaults?5(revpiname=None)
revpidevelop._savedefaults?5(revpiname, settings)
revpiinfo.RevPiInfo._checkclose?5(event=None)
revpiinfo.RevPiInfo._createwidgets?5(extended=False)
revpiinfo.RevPiInfo.visitwebsite?4(event=None)
revpiinfo.RevPiInfo?1(master, xmlcli, version)
revpiinfo._?8
revpiinfo.__author__?9
revpiinfo.__copyright__?9
revpiinfo.__license__?9
revpilegacy.RevPiOption._changesdone?5()
revpilegacy.RevPiOption._checkclose?5(event=None)
revpilegacy.RevPiOption._createwidgets?5()
revpilegacy.RevPiOption._loadappdata?5(refresh=False)
revpilegacy.RevPiOption._setappdata?5()
revpilegacy.RevPiOption.askxmlon?4()
revpilegacy.RevPiOption.xmlmod2_tail?4()
revpilegacy.RevPiOption.xmlmod_tail?4()
revpilegacy.RevPiOption?1(master, xmlcli)
revpilegacy._?8
revpilegacy.__author__?9
revpilegacy.__copyright__?9
revpilegacy.__license__?9
revpilogfile.RevPiLogfile._checkclose?5(event=None)
revpilogfile.RevPiLogfile._createwidgets?5()
revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full)
revpilogfile.RevPiLogfile.btn_clearapp?4()
revpilogfile.RevPiLogfile.btn_clearplc?4()
revpilogfile.RevPiLogfile.get_applog?4(full=False)
revpilogfile.RevPiLogfile.get_plclog?4(full=False)
revpilogfile.RevPiLogfile?1(master, xmlcli)
revpilogfile._?8
revpilogfile.__author__?9
revpilogfile.__copyright__?9
revpilogfile.__license__?9
revpioption.RevPiOption._changesdone?5()
revpioption.RevPiOption._changesdone_mqtt?5()
revpioption.RevPiOption._checkclose?5(event=None)
revpioption.RevPiOption._checkvalues?5()
revpioption.RevPiOption._createwidgets?5()
revpioption.RevPiOption._loadappdata?5(refresh=False)
revpioption.RevPiOption._setappdata?5()
revpioption.RevPiOption.askxmlon?4()
revpioption.RevPiOption.btn_mqttsettings?4()
revpioption.RevPiOption.btn_slaveacl?4()
revpioption.RevPiOption.btn_xmlacl?4()
revpioption.RevPiOption.destroy?4()
revpioption.RevPiOption?1(master, xmlcli)
revpioption._?8
revpioption.__author__?9
revpioption.__copyright__?9
revpioption.__license__?9
revpiplclist.RevPiPlcList._checkclose?5(event=None)
revpiplclist.RevPiPlcList._createwidgets?5()
revpiplclist.RevPiPlcList._saveappdata?5()
revpiplclist.RevPiPlcList.build_listconn?4()
revpiplclist.RevPiPlcList.evt_btnadd?4()
revpiplclist.RevPiPlcList.evt_btnnew?4()
revpiplclist.RevPiPlcList.evt_btnremove?4()
revpiplclist.RevPiPlcList.evt_btnsave?4()
revpiplclist.RevPiPlcList.evt_keypress?4(evt=None)
revpiplclist.RevPiPlcList.evt_listconn?4(evt=None)
revpiplclist.RevPiPlcList.myapp?7
revpiplclist.RevPiPlcList.root?7
revpiplclist.RevPiPlcList?1(master)
revpiplclist._?8
revpiplclist.__author__?9
revpiplclist.__copyright__?9
revpiplclist.__license__?9
revpiplclist.get_connections?4()
revpiprogram.RevPiProgram._checkclose?5(event=None)
revpiprogram.RevPiProgram._createwidgets?5()
revpiprogram.RevPiProgram._evt_optdown?5(text="")
revpiprogram.RevPiProgram._evt_optup?5(text="")
revpiprogram.RevPiProgram.check_replacedir?4(rootdir)
revpiprogram.RevPiProgram.create_filelist?4(rootdir)
revpiprogram.RevPiProgram.getpictoryrsc?4()
revpiprogram.RevPiProgram.getprocimg?4()
revpiprogram.RevPiProgram.picontrolreset?4()
revpiprogram.RevPiProgram.plcdownload?4()
revpiprogram.RevPiProgram.plcupload?4()
revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None)
revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi)
revpiprogram._?8
revpiprogram.__author__?9
revpiprogram.__copyright__?9
revpiprogram.__license__?9
revpiprogram._loaddefaults?5(revpiname=None)
revpiprogram._savedefaults?5(revpiname, settings)
revpipycontrol.RevPiPyControl._btnstate?5()
revpipycontrol.RevPiPyControl._closeall?5()
revpipycontrol.RevPiPyControl._closeapp?5(event=None)
revpipycontrol.RevPiPyControl._createwidgets?5()
revpipycontrol.RevPiPyControl._fillconnbar?5()
revpipycontrol.RevPiPyControl._fillmbar?5()
revpipycontrol.RevPiPyControl._opt_conn?5(text, reconnect=False)
revpipycontrol.RevPiPyControl.infowindow?4()
revpipycontrol.RevPiPyControl.myapp?7
revpipycontrol.RevPiPyControl.plcdebug?4()
revpipycontrol.RevPiPyControl.plcdevelop?4()
revpipycontrol.RevPiPyControl.plclist?4()
revpipycontrol.RevPiPyControl.plclogs?4()
revpipycontrol.RevPiPyControl.plcoptions?4()
revpipycontrol.RevPiPyControl.plcprogram?4()
revpipycontrol.RevPiPyControl.plcrestart?4()
revpipycontrol.RevPiPyControl.plcstart?4()
revpipycontrol.RevPiPyControl.plcstop?4()
revpipycontrol.RevPiPyControl.root?7
revpipycontrol.RevPiPyControl.serverdisconnect?4()
revpipycontrol.RevPiPyControl.servererror?4()
revpipycontrol.RevPiPyControl.tmr_plcrunning?4()
revpipycontrol.RevPiPyControl.visitwebsite?4()
revpipycontrol.RevPiPyControl?1(master=None)
revpipycontrol._?8
revpipycontrol.__author__?9
revpipycontrol.__copyright__?9
revpipycontrol.__license__?9
revpipycontrol.__version__?9
revpipycontrol.shared.__author__?9
revpipycontrol.shared.__copyright__?9
revpipycontrol.shared.__license__?9
revpipycontrol.shared.ipaclmanager.IpAclManager.__get_acl?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__get_filename?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__get_regex_acl?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__iter__?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__set_acl?6(value)
revpipycontrol.shared.ipaclmanager.IpAclManager.acl?7
revpipycontrol.shared.ipaclmanager.IpAclManager.filename?7
revpipycontrol.shared.ipaclmanager.IpAclManager.get_acllevel?4(ipaddress)
revpipycontrol.shared.ipaclmanager.IpAclManager.loadacl?4(str_acl)
revpipycontrol.shared.ipaclmanager.IpAclManager.loadaclfile?4(filename)
revpipycontrol.shared.ipaclmanager.IpAclManager.regex_acl?7
revpipycontrol.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None)
revpipycontrol.shared.ipaclmanager.IpAclManager?1(minlevel, maxlevel, acl=None)
revpipycontrol.shared.ipaclmanager.__author__?9
revpipycontrol.shared.ipaclmanager.__copyright__?9
revpipycontrol.shared.ipaclmanager.__license__?9
revpipycontrol.shared.ipaclmanager.refullmatch?4(regex, string)

View File

@@ -1,4 +1,7 @@
AclManager ttk.Frame
MqttManager tkinter.Frame
RevPiCheckClient tkinter.Frame
RevPiDevelop ttk.Frame
RevPiInfo tkinter.Frame
RevPiLogfile tkinter.Frame
RevPiOption tkinter.Frame

View File

@@ -1,105 +0,0 @@
mytools.addroot?4(filename)
mytools.gettrans?4(proglang=None)
revpicheckclient.RevPiCheckClient.__chval?6(device, io, event=None)
revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None)
revpicheckclient.RevPiCheckClient.__saveoldvalue?6(event, tkvar)
revpicheckclient.RevPiCheckClient.__showwin?6(win)
revpicheckclient.RevPiCheckClient.__spinboxkey?6(device, io, event=None)
revpicheckclient.RevPiCheckClient._createiogroup?5(device, frame, iotype)
revpicheckclient.RevPiCheckClient._createwidgets?5()
revpicheckclient.RevPiCheckClient._onfrmconf?5(canvas)
revpicheckclient.RevPiCheckClient._warnwrite?5()
revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False)
revpicheckclient.RevPiCheckClient.hideallwindows?4()
revpicheckclient.RevPiCheckClient.maxint?4(bytelen)
revpicheckclient.RevPiCheckClient.readvalues?4()
revpicheckclient.RevPiCheckClient.refreshvalues?4()
revpicheckclient.RevPiCheckClient.tmr_workvalues?4()
revpicheckclient.RevPiCheckClient.toggleauto?4()
revpicheckclient.RevPiCheckClient.togglewrite?4()
revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist)
revpicheckclient.RevPiCheckClient.writevalues?4()
revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0)
revpicheckclient._?8
revpiinfo.RevPiInfo._checkclose?5(event=None)
revpiinfo.RevPiInfo._createwidgets?5(extended=False)
revpiinfo.RevPiInfo.visitwebsite?4(event=None)
revpiinfo.RevPiInfo?1(master, xmlcli, version)
revpiinfo._?8
revpilogfile.RevPiLogfile._checkclose?5(event=None)
revpilogfile.RevPiLogfile._createwidgets?5()
revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full)
revpilogfile.RevPiLogfile.btn_clearapp?4()
revpilogfile.RevPiLogfile.btn_clearplc?4()
revpilogfile.RevPiLogfile.get_applog?4(full=False)
revpilogfile.RevPiLogfile.get_plclog?4(full=False)
revpilogfile.RevPiLogfile?1(master, xmlcli)
revpilogfile._?8
revpioption.RevPiOption._changesdone?5()
revpioption.RevPiOption._checkclose?5(event=None)
revpioption.RevPiOption._createwidgets?5()
revpioption.RevPiOption._loadappdata?5(refresh=False)
revpioption.RevPiOption._setappdata?5()
revpioption.RevPiOption.askxmlon?4()
revpioption.RevPiOption.xmlmod2_tail?4()
revpioption.RevPiOption.xmlmod_tail?4()
revpioption.RevPiOption?1(master, xmlcli)
revpioption._?8
revpiplclist.RevPiPlcList._checkclose?5(event=None)
revpiplclist.RevPiPlcList._createwidgets?5()
revpiplclist.RevPiPlcList._saveappdata?5()
revpiplclist.RevPiPlcList.build_listconn?4()
revpiplclist.RevPiPlcList.evt_btnadd?4()
revpiplclist.RevPiPlcList.evt_btnnew?4()
revpiplclist.RevPiPlcList.evt_btnremove?4()
revpiplclist.RevPiPlcList.evt_btnsave?4()
revpiplclist.RevPiPlcList.evt_keypress?4(evt=None)
revpiplclist.RevPiPlcList.evt_listconn?4(evt=None)
revpiplclist.RevPiPlcList.myapp?7
revpiplclist.RevPiPlcList.root?7
revpiplclist.RevPiPlcList?1(master)
revpiplclist._?8
revpiplclist.get_connections?4()
revpiplclist.savefile?7
revpiprogram.RevPiProgram._checkclose?5(event=None)
revpiprogram.RevPiProgram._createwidgets?5()
revpiprogram.RevPiProgram._evt_optdown?5(text="")
revpiprogram.RevPiProgram._evt_optup?5(text="")
revpiprogram.RevPiProgram._loaddefault?5(full=False)
revpiprogram.RevPiProgram._savedefaults?5()
revpiprogram.RevPiProgram.check_replacedir?4(rootdir)
revpiprogram.RevPiProgram.create_filelist?4(rootdir)
revpiprogram.RevPiProgram.getpictoryrsc?4()
revpiprogram.RevPiProgram.getprocimg?4()
revpiprogram.RevPiProgram.picontrolreset?4()
revpiprogram.RevPiProgram.plcdownload?4()
revpiprogram.RevPiProgram.plcupload?4()
revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None)
revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi)
revpiprogram._?8
revpiprogram.savefile?7
revpipycontrol.RevPiPyControl._btnstate?5()
revpipycontrol.RevPiPyControl._closeall?5()
revpipycontrol.RevPiPyControl._closeapp?5(event=None)
revpipycontrol.RevPiPyControl._createwidgets?5()
revpipycontrol.RevPiPyControl._fillconnbar?5()
revpipycontrol.RevPiPyControl._fillmbar?5()
revpipycontrol.RevPiPyControl._opt_conn?5(text, reconnect=False)
revpipycontrol.RevPiPyControl.infowindow?4()
revpipycontrol.RevPiPyControl.myapp?7
revpipycontrol.RevPiPyControl.plcdebug?4()
revpipycontrol.RevPiPyControl.plclist?4()
revpipycontrol.RevPiPyControl.plclogs?4()
revpipycontrol.RevPiPyControl.plcoptions?4()
revpipycontrol.RevPiPyControl.plcprogram?4()
revpipycontrol.RevPiPyControl.plcrestart?4()
revpipycontrol.RevPiPyControl.plcstart?4()
revpipycontrol.RevPiPyControl.plcstop?4()
revpipycontrol.RevPiPyControl.root?7
revpipycontrol.RevPiPyControl.serverdisconnect?4()
revpipycontrol.RevPiPyControl.servererror?4()
revpipycontrol.RevPiPyControl.tmr_plcrunning?4()
revpipycontrol.RevPiPyControl.visitwebsite?4()
revpipycontrol.RevPiPyControl?1(master=None)
revpipycontrol._?8
revpipycontrol.pycontrolversion?7

View File

@@ -1,28 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipycontrol -->
<!-- Saved: 2017-07-06, 13:33:38 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<!-- Saved: 2018-10-07, 12:09:56 -->
<!-- Copyright (C) 2018 Sven Sager, akira@narux.de -->
<Project version="5.1">
<Language>en_US</Language>
<Hash>66103e2eaf8a762f14d1fd51d8b1c9dcaf35a275</Hash>
<ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType>
<Description></Description>
<Version>0.4.2</Version>
<Version>0.7.1</Version>
<Author>Sven Sager</Author>
<Email>akira@narux.de</Email>
<Eol index="-1"/>
<Eol index="1"/>
<Sources>
<Source>revpipycontrol/revpipycontrol.py</Source>
<Source>revpipycontrol/aclmanager.py</Source>
<Source>revpipycontrol/mqttmanager.py</Source>
<Source>revpipycontrol/mytools.py</Source>
<Source>revpipycontrol/revpicheckclient.py</Source>
<Source>setup.py</Source>
<Source>revpipycontrol/revpiplclist.py</Source>
<Source>revpipycontrol/revpidevelop.py</Source>
<Source>revpipycontrol/revpiinfo.py</Source>
<Source>revpipycontrol/revpilegacy.py</Source>
<Source>revpipycontrol/revpilogfile.py</Source>
<Source>revpipycontrol/revpioption.py</Source>
<Source>revpipycontrol/revpiplclist.py</Source>
<Source>revpipycontrol/revpiprogram.py</Source>
<Source>revpipycontrol/mytools.py</Source>
<Source>revpipycontrol/revpiinfo.py</Source>
<Source>revpipycontrol/revpipycontrol.py</Source>
<Source>revpipycontrol/shared/__init__.py</Source>
<Source>revpipycontrol/shared/ipaclmanager.py</Source>
<Source>setup.py</Source>
</Sources>
<Forms/>
<Translations/>
@@ -31,7 +36,7 @@
<Others>
<Other>data</Other>
<Other>doc</Other>
<Other>revpipycontrol.api</Other>
<Other>eric-revpipycontrol.api</Other>
<Other>stdeb.cfg</Other>
</Others>
<MainScript>revpipycontrol/revpipycontrol.py</MainScript>
@@ -137,9 +142,6 @@
</value>
</dict>
</VcsOptions>
<VcsOtherData>
<dict/>
</VcsOtherData>
</Vcs>
<FiletypeAssociations>
<FiletypeAssociation pattern="*.idl" type="INTERFACES"/>
@@ -193,7 +195,7 @@
<string>outputFile</string>
</key>
<value>
<string>revpipycontrol.api</string>
<string>eric-revpipycontrol.api</string>
</value>
<key>
<string>useRecursion</string>
@@ -239,14 +241,6 @@
<value>
<bool>False</bool>
</value>
<key>
<string>sourceExtensions</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>useRecursion</string>
</key>
@@ -261,6 +255,133 @@
<Checkers>
<CheckersParams>
<dict>
<key>
<string>PYLINT</string>
</key>
<value>
<dict>
<key>
<string>configFile</string>
</key>
<value>
<string>/home/akira/Entwicklung/eric/revpipyplc/revpipycontrol/default.cnf</string>
</value>
<key>
<string>dialogReport</string>
</key>
<value>
<bool>False</bool>
</value>
<key>
<string>disabledMessages</string>
</key>
<value>
<string></string>
</value>
<key>
<string>enableBasic</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableClasses</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableDesign</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableExceptions</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableFormat</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableImports</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableLogging</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableMetrics</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableMiscellaneous</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableNewstyle</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableSimilarities</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableStringFormat</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableTypecheck</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enableVariables</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>enabledMessages</string>
</key>
<value>
<string></string>
</value>
<key>
<string>htmlReport</string>
</key>
<value>
<bool>True</bool>
</value>
<key>
<string>txtReport</string>
</key>
<value>
<bool>False</bool>
</value>
</dict>
</value>
<key>
<string>Pep8Checker</string>
</key>

View File

@@ -0,0 +1,392 @@
# -*- coding: utf-8 -*-
u"""Manager für ACL Einträge."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
import tkinter.messagebox as tkmsg
from mytools import gettrans
from shared.ipaclmanager import IpAclManager
from tkinter import ttk
# Übersetzung laden
_ = gettrans()
class AclManager(ttk.Frame):
u"""Hauptfenster des ACL-Managers."""
def __init__(self, master, minlevel, maxlevel, acl_str="", readonly=False):
u"""Init AclManger-Class.
@return None"""
super().__init__(master)
self.master.bind("<KeyPress-Escape>", self._checkclose)
self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
# Daten laden
self.__acl = IpAclManager(minlevel, maxlevel, acl_str)
self.__dict_acltext = {}
self.__oldacl = self.__acl.acl
self.__ro = "disabled" if readonly else "normal"
self.maxlevel = maxlevel
self.minlevel = minlevel
# Fenster bauen
self._createwidgets()
def __get_acltext(self):
"""Getter fuer Leveltexte.
@return Leveltexte als <class 'dict'>"""
return self.__dict_acltext.copy()
def __set_acltext(self, value):
"""Setter fuer Leveltexte.
@param value Leveltexte als <class 'dict'>"""
if type(value) != dict:
raise ValueError("value must be <class 'dict'>")
self.__dict_acltext = value.copy()
# Infotexte aufbauen
self.aclinfo.destroy()
self.aclinfo = ttk.Frame(self)
for acltext in self.__dict_acltext:
lbl = ttk.Label(self.aclinfo)
lbl["text"] = _("Level") + " {id}: {text}".format(
id=acltext, text=self.__dict_acltext[acltext]
)
lbl.pack(anchor="w")
self.aclinfo.pack(anchor="w", padx=4, pady=4)
def _changesdone(self):
u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde"""
return not self.__acl.acl == self.__oldacl
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
ask = True
if self._changesdone():
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to quit? \nUnsaved changes will "
"be lost"),
parent=self.master, default="no"
)
if ask:
self.master.destroy()
def _createwidgets(self):
u"""Erstellt Widgets."""
self.master.wm_title(_("IP access control list"))
self.master.wm_resizable(width=False, height=False)
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
# Gruppe Bestehende ACL ######################################
gb_acl = ttk.LabelFrame(self)
gb_acl["text"] = _("Existing ACLs")
gb_acl.columnconfigure(0, weight=1)
gb_acl.columnconfigure(1, weight=1)
gb_acl.pack(expand=True, fill="both", padx=4, pady=4)
row = 0
frame = ttk.Frame(gb_acl)
frame.columnconfigure(0, weight=1)
scb_acl = ttk.Scrollbar(frame)
self.trv_acl = ttk.Treeview(frame)
self.trv_acl["columns"] = ("level")
self.trv_acl["yscrollcommand"] = scb_acl.set
self.trv_acl.heading("level", text=_("Access level"))
self.trv_acl.column("level", width=100)
self.trv_acl.bind("<<TreeviewSelect>>", self._status_editremove)
self._refreshacls()
self.trv_acl.grid(row=0, column=0, sticky="we")
scb_acl["command"] = self.trv_acl.yview
scb_acl.grid(row=0, column=1, sticky="ns")
frame.grid(row=row, columnspan=2, sticky="we")
row = 1
# Edit / Remove button
self.btn_edit = ttk.Button(gb_acl)
self.btn_edit["command"] = self._loadfields
self.btn_edit["text"] = _("load entry")
self.btn_edit["state"] = "disabled"
self.btn_edit.grid(row=row, column=0, pady=4)
self.btn_remove = ttk.Button(gb_acl)
self.btn_remove["command"] = self._ask_delete
self.btn_remove["text"] = _("remove entry")
self.btn_remove["state"] = "disabled"
self.btn_remove.grid(row=row, column=1, pady=4)
# ############################################################
# Gruppe Bearbeiten ##########################################
gb_edit = ttk.LabelFrame(self)
gb_edit["text"] = _("Edit acess control list")
gb_edit.pack(expand=True, fill="both", padx=4, pady=4)
frame = ttk.Frame(gb_edit)
frame.grid()
row = 0
lbl = ttk.Label(frame)
lbl["text"] = _("IP address") + ": "
lbl.grid(row=row, column=0, **cpadw)
# Variablen IP / Level
self.var_ip1 = tkinter.StringVar(frame)
self.var_ip2 = tkinter.StringVar(frame)
self.var_ip3 = tkinter.StringVar(frame)
self.var_ip4 = tkinter.StringVar(frame)
self.var_acl = tkinter.StringVar(frame, self.minlevel)
ip_block1 = ttk.Entry(frame, width=4)
ip_block2 = ttk.Entry(frame, width=4)
ip_block3 = ttk.Entry(frame, width=4)
ip_block4 = ttk.Entry(frame, width=4)
ip_block1.bind(
"<KeyRelease>",
lambda event, tkvar=self.var_ip1: self._checkdot(
event, tkvar, ip_block2
)
)
ip_block1["state"] = self.__ro
ip_block1["textvariable"] = self.var_ip1
ip_block1.grid(row=row, column=1)
ip_block2.bind(
"<KeyRelease>",
lambda event, tkvar=self.var_ip2: self._checkdot(
event, tkvar, ip_block3
)
)
ip_block2.bind(
"<Key>",
lambda event, tkvar=self.var_ip2: self._checkback(
event, tkvar, ip_block1
)
)
ip_block2["state"] = self.__ro
ip_block2["textvariable"] = self.var_ip2
ip_block2.grid(row=row, column=3)
ip_block3.bind(
"<KeyRelease>",
lambda event, tkvar=self.var_ip3: self._checkdot(
event, tkvar, ip_block4
)
)
ip_block3.bind(
"<Key>",
lambda event, tkvar=self.var_ip3: self._checkback(
event, tkvar, ip_block2
)
)
ip_block3["state"] = self.__ro
ip_block3["textvariable"] = self.var_ip3
ip_block3.grid(row=row, column=5)
ip_block4.bind(
"<KeyRelease>",
lambda event, tkvar=self.var_ip4: self._checkdot(
event, tkvar, None
)
)
ip_block4.bind(
"<Key>",
lambda event, tkvar=self.var_ip4: self._checkback(
event, tkvar, ip_block3
)
)
ip_block4["state"] = self.__ro
ip_block4["textvariable"] = self.var_ip4
ip_block4.grid(row=row, column=7)
# Punkte zwischen IP-Feldern
for i in range(2, 7, 2):
lbl = ttk.Label(frame, text=".")
lbl.grid(row=row, column=i)
row = 1
lbl = ttk.Label(frame)
lbl["text"] = _("Access level") + ": "
lbl.grid(row=row, column=0, **cpadw)
self.sb_level = tkinter.Spinbox(frame, width=4)
self.sb_level["from_"] = self.minlevel
self.sb_level["to"] = self.maxlevel
self.sb_level["state"] = self.__ro
self.sb_level["textvariable"] = self.var_acl
self.sb_level.grid(row=row, column=1, columnspan=8, sticky="w")
# Buttons neben IP-Eintrag
self.btn_add = ttk.Button(gb_edit)
self.btn_add["command"] = self._savefields
self.btn_add["state"] = self.__ro
self.btn_add["text"] = _("add to list")
self.btn_add.grid(column=0, row=1, sticky="e", padx=4, pady=4)
self.btn_clear = ttk.Button(gb_edit)
self.btn_clear["command"] = self._clearfields
self.btn_clear["state"] = self.__ro
self.btn_clear["text"] = _("clear")
self.btn_clear.grid(column=1, row=1, padx=4, pady=4)
# ############################################################
frame = ttk.Frame(self)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.pack(expand=True, fill="both", pady=4)
# Buttons
btn_save = ttk.Button(frame)
btn_save["command"] = self._save
btn_save["state"] = self.__ro
btn_save["text"] = _("Save")
btn_save.grid(column=0, row=0)
btn_close = ttk.Button(frame)
btn_close["command"] = self._checkclose
btn_close["text"] = _("Close")
btn_close.grid(column=1, row=0)
# Infotexte vorbereiten
self.aclinfo = ttk.Frame(self)
def _ask_delete(self):
u"""Löscht ein Eintrag der Liste."""
str_acl = self.trv_acl.focus()
if str_acl != "":
lst_ipacl = str_acl.split()
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to delete the following item? \n"
"\nIP: {0} / Level: {1}").format(*lst_ipacl),
parent=self.master, default="no"
)
if ask:
new_acl = self.__acl.acl.replace(
"{0},{1}".format(*lst_ipacl), ""
).replace(" ", " ")
if self.__acl.loadacl(new_acl.strip()):
# Liste neu aufbauen
self._refreshacls()
else:
tkmsg.showerror(
_("Error"),
_("Can not delete ACL! Check format."),
parent=self.master
)
def _checkback(self, event, tkvar, pretxt):
u"""Springt bei Backspace in vorheriges Feld.
@param event TK Event
@param tkvar TK Variable zum prüfen
@param nexttxt Vorheriges IP Feld für Fokus
"""
if pretxt is not None and event.keycode == 22 and tkvar.get() == "":
pretxt.focus_set()
def _checkdot(self, event, tkvar, nexttxt):
u"""Prüft auf . und geht weiter.
@param event TK Event
@param tkvar TK Variable zum prüfen
@param nexttxt Nächstes IP Feld für Fokus
"""
val = tkvar.get()
if val.find(".") >= 0:
tkvar.set(val[:-1])
if nexttxt is not None:
nexttxt.focus_set()
def _clearfields(self):
u"""Leert die Eingabefelder."""
self.var_ip1.set("")
self.var_ip2.set("")
self.var_ip3.set("")
self.var_ip4.set("")
self.var_acl.set(self.minlevel)
def _loadfields(self):
u"""Übernimmt Listeneintrag in Editfelder."""
str_acl = self.trv_acl.focus()
if str_acl != "":
lst_ip, acl = str_acl.split()
lst_ip = lst_ip.split(".")
self.var_ip1.set(lst_ip[0])
self.var_ip2.set(lst_ip[1])
self.var_ip3.set(lst_ip[2])
self.var_ip4.set(lst_ip[3])
self.var_acl.set(acl)
def _refreshacls(self):
u"""Leert die ACL Liste und füllt sie neu."""
self.trv_acl.delete(*self.trv_acl.get_children())
for tup_acl in self.__acl:
self.trv_acl.insert(
"", "end", tup_acl, text=tup_acl[0], values=tup_acl[1]
)
def _save(self):
u"""Übernimt die Änderungen."""
self.__oldacl = self.__acl.acl
self._checkclose()
def _savefields(self):
u"""Übernimmt neuen ACL Eintrag."""
new_acl = "{0}.{1}.{2}.{3},{4}".format(
self.var_ip1.get(),
self.var_ip2.get(),
self.var_ip3.get(),
self.var_ip4.get(),
self.var_acl.get()
)
if self.__acl.loadacl((self.__acl.acl + " " + new_acl).strip()):
self._refreshacls()
else:
tkmsg.showerror(
_("Error"),
_("Can not load new ACL! Check format."),
parent=self.master
)
def _status_editremove(self, tkevt):
u"""Setzt state der Buttons."""
if self.__ro == "normal":
status = "disabled" if self.trv_acl.focus() == "" else "normal"
self.btn_edit["state"] = status
self.btn_remove["state"] = status
def get_acl(self):
u"""Gibt die Konfigurierten ACL zurück.
@return ACL als <class 'str'>"""
return self.__oldacl
acl = property(get_acl)
acltext = property(__get_acltext, __set_acltext)
# Debugging
if __name__ == "__main__":
root = AclManager(tkinter.Tk(), 0, 9, " 192.168.50.100,2 127.0.0.*,1")
root.acltext = {0: "Keine Rechte", 1: "Hohe Rechte"}
root.mainloop()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
# -*- coding: utf-8 -*-
u"""Optionen für das MQTT System."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
import tkinter.messagebox as tkmsg
from mytools import gettrans
# Übersetzung laden
_ = gettrans()
class MqttManager(tkinter.Frame):
u"""Hauptfenster der MQTT-Einstellungen."""
def __init__(self, master, settings, readonly=False):
u"""Init MqttManager-Class.
@return None"""
if not isinstance(settings, dict):
raise ValueError("parameter settings must be <class 'dict'>")
if not isinstance(readonly, bool):
raise ValueError("parameter readonly must be <class 'bool'>")
super().__init__(master)
self.master.bind("<KeyPress-Escape>", self._checkclose)
self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
# Daten laden
self.__ro = "disabled" if readonly else "normal"
self.__settings = settings
# Fenster bauen
self._createwidgets()
def _changesdone(self):
u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde"""
return (
self.var_basetopic.get() != self.__settings["mqttbasetopic"] or
self.var_send_events.get() !=
self.__settings["mqttsend_on_event"] or
self.var_client_id.get() != self.__settings["mqttclient_id"] or
self.var_password.get() != self.__settings["mqttpassword"] or
self.var_port.get() != str(self.__settings["mqttport"]) or
self.var_tls_set.get() != self.__settings["mqtttls_set"] or
self.var_username.get() != self.__settings["mqttusername"] or
self.var_broker_address.get() !=
self.__settings["mqttbroker_address"] or
self.var_sendinterval.get() !=
str(self.__settings["mqttsendinterval"]) or
self.var_write_outputs.get() !=
self.__settings["mqttwrite_outputs"]
)
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
ask = True
if self._changesdone():
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to quit? \nUnsaved changes will "
"be lost"),
parent=self.master, default="no"
)
if ask:
self.master.destroy()
def _createwidgets(self):
u"""Erstellt Widgets."""
self.master.wm_title(_("MQTT Settings"))
self.master.wm_resizable(width=False, height=False)
# cpade = {"padx": 4, "pady": 2, "sticky": "e"}
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
# Gruppe MQTT System ######################################
# Basetopic
gb = tkinter.LabelFrame(self)
gb["text"] = _("MQTT base topic")
gb.columnconfigure(0, weight=1)
gb.pack(expand=True, fill="both", padx=4, pady=4)
self.var_basetopic = tkinter.StringVar(
gb, self.__settings["mqttbasetopic"])
row = 0
lbl = tkinter.Label(gb)
lbl["text"] = _("Base topic") + ":"
lbl.grid(row=row, column=0, **cpadw)
txt = tkinter.Entry(gb)
txt["state"] = self.__ro
txt["textvariable"] = self.var_basetopic
txt["width"] = 34
txt.grid(row=row, column=1, **cpadwe)
row += 1
lbl = tkinter.Label(gb)
lbl["justify"] = "left"
lbl["text"] = _(
"""The base topic is the first part of any mqtt topic, the
Revolution Pi will publish. You can use any character
includig '/' to structure the messages on your broker.
For example: revpi0000/data"""
)
lbl.grid(row=row, column=0, columnspan=2, **cpadw)
# Publish settings
gb = tkinter.LabelFrame(self)
gb["text"] = _("MQTT publish settings")
gb.columnconfigure(0, weight=1)
gb.pack(expand=True, fill="both", padx=4, pady=4)
self.var_send_events = tkinter.BooleanVar(
gb, self.__settings["mqttsend_on_event"])
self.var_sendinterval = tkinter.StringVar(
gb, self.__settings["mqttsendinterval"])
self.var_write_outputs = tkinter.BooleanVar(
gb, self.__settings["mqttwrite_outputs"])
row = 0
lbl = tkinter.Label(gb)
lbl["text"] = _("Publish all exported values every n seconds") + ":"
lbl.grid(row=row, column=0, **cpadw)
sb = tkinter.Spinbox(gb)
sb["state"] = self.__ro
sb["textvariable"] = self.var_sendinterval
sb["width"] = 5
sb.grid(row=row, column=1, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["justify"] = "left"
lbl["text"] = _("Topic: \t[basetopic]/io/[ioname]")
lbl.grid(row=row, columnspan=2, **cpadw)
row += 1
cb = tkinter.Checkbutton(gb)
cb["state"] = self.__ro
cb["text"] = _("Send exported values immediately on value change")
cb["variable"] = self.var_send_events
cb.grid(row=row, columnspan=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["justify"] = "left"
lbl["text"] = _("Topic: \t[basetopic]/event/[ioname]")
lbl.grid(row=row, columnspan=2, **cpadw)
# Subscribe settings
gb = tkinter.LabelFrame(self)
gb["text"] = _("MQTT set outputs")
gb.columnconfigure(0, weight=1)
gb.pack(expand=True, fill="both", padx=4, pady=4)
row = 0
cb = tkinter.Checkbutton(gb)
cb["state"] = self.__ro
cb["text"] = _("Allow MQTT to to set outputs on Revolution Pi")
cb["variable"] = self.var_write_outputs
cb.grid(row=row, columnspan=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["justify"] = "left"
lbl["text"] = _(
"""The Revolution Pi will subscribe a topic on which your mqtt
client can publish messages with the new io value as payload.
Publish values with topic: \t[basetopic]/set/[outputname]"""
)
lbl.grid(row=row, columnspan=2, **cpadw)
# ############################################################
# Gruppe Broker ##########################################
gb = tkinter.LabelFrame(self)
gb["text"] = _("MQTT broker settings")
gb.pack(expand=True, fill="both", padx=4, pady=4)
gb.columnconfigure(2, weight=1)
# Variablen
self.var_client_id = tkinter.StringVar(
gb, self.__settings["mqttclient_id"])
self.var_broker_address = tkinter.StringVar(
gb, self.__settings["mqttbroker_address"])
self.var_password = tkinter.StringVar(
gb, self.__settings["mqttpassword"])
self.var_port = tkinter.StringVar(
gb, self.__settings["mqttport"])
self.var_tls_set = tkinter.BooleanVar(
gb, self.__settings["mqtttls_set"])
self.var_username = tkinter.StringVar(
gb, self.__settings["mqttusername"])
row = 0
lbl = tkinter.Label(gb)
lbl["text"] = _("Broker address") + ":"
lbl.grid(row=row, column=0, **cpadw)
txt = tkinter.Entry(gb)
txt["state"] = self.__ro
txt["textvariable"] = self.var_broker_address
txt.grid(row=row, column=1, columnspan=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["text"] = _("Broker port") + ":"
lbl.grid(row=row, column=0, **cpadw)
sb = tkinter.Spinbox(gb)
sb["state"] = self.__ro
sb["textvariable"] = self.var_port
sb["width"] = 6
sb.grid(row=row, column=1, **cpadw)
ckb = tkinter.Checkbutton(gb)
ckb["state"] = self.__ro
ckb["text"] = _("Use TLS") + ":"
ckb["variable"] = self.var_tls_set
ckb.grid(row=row, column=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["text"] = _("Username") + ":"
lbl.grid(row=row, column=0, **cpadw)
txt = tkinter.Entry(gb)
txt["state"] = self.__ro
txt["textvariable"] = self.var_username
txt.grid(row=row, column=1, columnspan=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["text"] = _("Password") + ":"
lbl.grid(row=row, column=0, **cpadw)
txt = tkinter.Entry(gb)
txt["state"] = self.__ro
txt["textvariable"] = self.var_password
txt.grid(row=row, column=1, columnspan=2, **cpadw)
row += 1
lbl = tkinter.Label(gb)
lbl["text"] = _("Client ID") + ":"
lbl.grid(row=row, column=0, **cpadw)
txt = tkinter.Entry(gb)
txt["state"] = self.__ro
txt["textvariable"] = self.var_client_id
txt["width"] = 30
txt.grid(row=row, column=1, columnspan=2, **cpadw)
# ############################################################
frame = tkinter.Frame(self)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.pack(expand=True, fill="both", pady=4)
# Buttons
btn_save = tkinter.Button(frame)
btn_save["command"] = self._save
btn_save["state"] = self.__ro
btn_save["text"] = _("Save")
btn_save.grid(column=0, row=0)
btn_close = tkinter.Button(frame)
btn_close["command"] = self._checkclose
btn_close["text"] = _("Close")
btn_close.grid(column=1, row=0)
def _save(self):
u"""Übernimt die Änderungen."""
# TODO: Wertprüfung
# Wertübernahme
self.__settings["mqttbasetopic"] = self.var_basetopic.get()
self.__settings["mqttsendinterval"] = int(self.var_sendinterval.get())
self.__settings["mqttsend_on_event"] = int(self.var_send_events.get())
self.__settings["mqttwrite_outputs"] = \
int(self.var_write_outputs.get())
self.__settings["mqttbroker_address"] = self.var_broker_address.get()
self.__settings["mqtttls_set"] = int(self.var_tls_set.get())
self.__settings["mqttport"] = int(self.var_port.get())
self.__settings["mqttusername"] = self.var_username.get()
self.__settings["mqttpassword"] = self.var_password.get()
self.__settings["mqttclient_id"] = self.var_client_id.get()
self._checkclose()
def get_settings(self):
u"""Gibt die MQTT Konfiguration zurück.
@return Settings als <class 'dict'>"""
return self.__settings
settings = property(get_settings)
# Debugging
if __name__ == "__main__":
dict_mqttsettings = {
"mqttbasetopic": "revpi01",
"mqttclient_id": "",
"mqttbroker_address": "127.0.0.1",
"mqttpassword": "",
"mqttport": 1883,
"mqttsend_on_event": 0,
"mqttsendinterval": 30,
"mqtttls_set": 0,
"mqttusername": "",
"mqttwrite_outputs": 0,
}
root = MqttManager(tkinter.Tk(), dict_mqttsettings)
root.mainloop()

View File

@@ -1,15 +1,30 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
"""Tools-Sammlung."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import gettext
import locale
import sys
from os import environ
from os.path import dirname
from os.path import join as pathjoin
from sys import platform
# Systemwerte und SaveFiles
if platform == "linux":
homedir = environ["HOME"]
else:
homedir = environ["APPDATA"]
savefile_connections = pathjoin(
homedir, ".revpipyplc", "connections.dat")
savefile_developer = pathjoin(
homedir, ".revpipyplc", "developer.dat")
savefile_programpath = pathjoin(
homedir, ".revpipyplc", "programpath.dat")
def addroot(filename):
@@ -29,7 +44,12 @@ def addroot(filename):
def gettrans(proglang=None):
u"""Wertet die Sprache des OS aus und gibt Übersetzung zurück.
@param proglang Bestimmte Sprache laden
@return gettext Übersetzung für Zuweisung an '_'
"""
# Sprache auswählen
if proglang is None:
# Autodetect Language or switch to static

View File

@@ -1,11 +1,14 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-
# scrollbar-to-a-group-of-widgets-in-tkinter
# -*- coding: utf-8 -*-
u"""Fenstererweiterung für den 'watch modus'.
Thranks to: http://stackoverflow.com/questions/3085696/adding-a-
scrollbar-to-a-group-of-widgets-in-tkinter
"""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import pickle
import tkinter
@@ -20,6 +23,8 @@ _ = gettrans()
class RevPiCheckClient(tkinter.Frame):
u"""Baut Fenstererweiterung für 'watch modus'."""
def __init__(self, master, xmlcli, xmlmode=0):
"""Instantiiert MyApp-Klasse."""
super().__init__(master)
@@ -105,8 +110,11 @@ class RevPiCheckClient(tkinter.Frame):
io[5].set(self.__oldvalue)
tkmsg.showerror(
_("Error"),
_("Given value for Output '{}' is not valid! \nReset to ""'{}'"
"").format(self.dict_devices[device], self.__oldvalue),
_("Given value for Output '{0}' is not valid! \n"
"Reset to '{1}'").format(
self.dict_devices[device],
self.__oldvalue
),
parent=self.dict_wins[device]
)
@@ -132,7 +140,7 @@ class RevPiCheckClient(tkinter.Frame):
canvas = tkinter.Canvas(
frame,
borderwidth=0,
width=180,
width=190,
heigh=calc_heigh if calc_heigh <= 600 else 600
)
s_frame = tkinter.Frame(canvas)
@@ -163,7 +171,7 @@ class RevPiCheckClient(tkinter.Frame):
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)]
tkinter.Label(s_frame, text=io[0]).grid(
column=0, row=rowcount, sticky="w"
column=1, row=rowcount, sticky="w"
)
if io[4] >= 0:
@@ -174,7 +182,7 @@ class RevPiCheckClient(tkinter.Frame):
check["state"] = "disabled" if iotype == "inp" else "normal"
check["text"] = ""
check["variable"] = var
check.grid(column=1, row=rowcount)
check.grid(column=0, row=rowcount)
else:
var = tkinter.IntVar()
txt = tkinter.Spinbox(s_frame, to=self.maxint(io[1]))
@@ -193,7 +201,7 @@ class RevPiCheckClient(tkinter.Frame):
self.maxint(io[1]) == 0 else "normal"
txt["width"] = 5
txt["textvariable"] = var
txt.grid(column=1, row=rowcount)
txt.grid(column=0, row=rowcount)
# Steuerelementvariable in IO übernehmen (mutabel)
io.append(var)
@@ -202,7 +210,7 @@ class RevPiCheckClient(tkinter.Frame):
def _createwidgets(self):
"""Erstellt den Fensterinhalt."""
cFxPxy53 = {"fill": "x", "padx": 5, "pady": 3}
cfxpxy53 = {"fill": "x", "padx": 5, "pady": 3}
devgrp = tkinter.LabelFrame(self)
devgrp["text"] = _("Devices of RevPi")
@@ -210,7 +218,7 @@ class RevPiCheckClient(tkinter.Frame):
for dev in self.lst_devices:
win = tkinter.Toplevel(self)
win.wm_title("{} | {}".format(dev, self.dict_devices[dev]))
win.wm_title("{0} | {1}".format(dev, self.dict_devices[dev]))
win.protocol(
"WM_DELETE_WINDOW",
lambda win=win: self.__hidewin(win)
@@ -232,8 +240,8 @@ class RevPiCheckClient(tkinter.Frame):
# Button erstellen
btn = tkinter.Button(devgrp)
btn["command"] = lambda win=win: self.__showwin(win)
btn["text"] = "{} | {}".format(dev, self.dict_devices[dev])
btn.pack(**cFxPxy53)
btn["text"] = "{0} | {1}".format(dev, self.dict_devices[dev])
btn.pack(**cfxpxy53)
# Steuerungsfunktionen
cntgrp = tkinter.LabelFrame(self)
@@ -243,19 +251,19 @@ class RevPiCheckClient(tkinter.Frame):
self.btn_refresh = tkinter.Button(cntgrp)
self.btn_refresh["text"] = _("Read all IOs")
self.btn_refresh["command"] = self.refreshvalues
self.btn_refresh.pack(**cFxPxy53)
self.btn_refresh.pack(**cfxpxy53)
self.btn_read = tkinter.Button(cntgrp)
self.btn_read["text"] = _("Read just Inputs")
self.btn_read["command"] = self.readvalues
self.btn_read.pack(**cFxPxy53)
self.btn_read.pack(**cfxpxy53)
self.btn_write = tkinter.Button(cntgrp)
self.btn_write["state"] = "normal" if self.xmlmode >= 3 \
else "disabled"
self.btn_write["text"] = _("Write Outputs")
self.btn_write["command"] = self.writevalues
self.btn_write.pack(**cFxPxy53)
self.btn_write.pack(**cfxpxy53)
self.chk_auto = tkinter.Checkbutton(cntgrp)
self.chk_auto["command"] = self.toggleauto
@@ -308,16 +316,28 @@ class RevPiCheckClient(tkinter.Frame):
try:
ba_values = bytearray(self.cli.ps_values().data)
self.err_workvalues = 0
except:
except Exception:
if self.autorw.get():
self.err_workvalues += 1
else:
self.err_workvalues = self.max_errors
if self.err_workvalues >= self.max_errors:
# Fenster zerstören bei zu vielen Fehlern
self.hideallwindows()
if self.autorw.get():
self.autorw.set(False)
self.toggleauto()
self.dowrite.set(False)
self.pack_forget()
tkmsg.showerror(
_("Error"),
_("To many errors while reading IO data. "
"Can not show the Watch-Mode."),
parent=self.master
)
return None
# Multicall zum Schreiben vorbereiten
@@ -387,7 +407,7 @@ class RevPiCheckClient(tkinter.Frame):
if not self.autorw.get():
try:
self.chk_auto["state"] = "normal"
except:
except Exception:
pass
return None
@@ -433,10 +453,11 @@ class RevPiCheckClient(tkinter.Frame):
# Fehlermeldungen erstellen
devicename = self.dict_devices[lst_result[0]]
str_errmsg += _(
"Error set value of device '{}' Output '{}': {} \n"
"Error set value of device '{0}' Output '{1}': {2} \n"
).format(devicename, lst_result[1], lst_result[3])
if str_errmsg != "":
tkmsg.showerror(_("Error"), str_errmsg)
tkmsg.showerror(_("Error"), str_errmsg, parent=self.master)
def writevalues(self):
u"""Schreibt geänderte Outputs auf den RevPi."""

View File

@@ -0,0 +1,318 @@
# -*- coding: utf-8 -*-
u"""PLC Programm und Konfig hoch und runterladen."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import gzip
import os
import pickle
import tkinter
import tkinter.filedialog as tkfd
import tkinter.messagebox as tkmsg
from mytools import homedir
from mytools import gettrans
from mytools import savefile_developer as savefile
from tkinter import ttk
from xmlrpc.client import Binary
# Übersetzung laden
_ = gettrans()
def _loaddefaults(revpiname=None):
u"""Übernimmt für den Pi die letzen Pfade.
@param revpiname Einstellungen nur für RevPi laden
@return <class 'dict'> mit Einstellungen"""
if os.path.exists(savefile):
with open(savefile, "rb") as fh:
dict_all = pickle.load(fh)
if revpiname is None:
return dict_all
else:
return dict_all.get(revpiname, {})
return {}
def _savedefaults(revpiname, settings):
u"""Schreibt fuer den Pi die letzen Pfade.
@param revpiname Einstellungen sind für diesen RevPi
@param settings <class 'dict'> mit Einstellungen
@return True, bei erfolgreicher Verarbeitung
"""
try:
os.makedirs(os.path.dirname(savefile), exist_ok=True)
if revpiname is None:
dict_all = settings
else:
dict_all = _loaddefaults()
dict_all[revpiname] = settings
with open(savefile, "wb") as fh:
pickle.dump(dict_all, fh)
except Exception:
return False
return True
class RevPiDevelop(ttk.Frame):
u"""Zeigt Debugfenster an."""
def __init__(self, master, xmlcli, xmlmode, revpi):
u"""Init RevPiDevelop-Class.
@return None"""
if xmlmode < 3:
return None
super().__init__(master)
self.pack(expand=True, fill="both")
self.revpi = revpi
self.xmlcli = xmlcli
# Letzte Einstellungen übernehmen
self.opt = _loaddefaults(revpi)
# Einstellungen
self.pathselected = self.opt.get("pathselected", False)
self.watchpath = self.opt.get("watchpath", homedir)
self.watchfiles = self.opt.get("watchfiles", [])
# Fenster bauen
self._createwidgets()
# Alte Einstellungen anwenden
if self.pathselected:
self.load_pathfiles(silent=True)
self.refresh_stats()
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
# Einstellungen speichern
self.opt["pathselected"] = self.pathselected
self.opt["watchpath"] = self.watchpath
self.opt["watchfiles"] = self.watchfiles
_savedefaults(self.revpi, self.opt)
def _createwidgets(self):
u"""Erstellt alle Widgets."""
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
# cpad = {"padx": 4, "pady": 2}
# cpade = {"padx": 4, "pady": 2, "sticky": "e"}
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
# Gruppe Develop
devel = ttk.LabelFrame(self)
devel.columnconfigure(0, weight=1)
devel["text"] = _("File watcher for PLC development")
devel.grid(**cpadwe)
r = 0
lbl = ttk.Label(devel)
lbl["text"] = _("Path to list files:")
lbl.grid(row=r, **cpadw)
btn = ttk.Button(devel)
btn["command"] = self.btn_selectpath
btn["text"] = _("Select path")
btn.grid(row=r, column=1, **cpadw)
r += 1
self.lbl_path = ttk.Label(devel)
self.lbl_path["width"] = 50
self.lbl_path.grid(row=r, column=0, columnspan=2, **cpadw)
# Listbox
r += 1
trv = ttk.Frame(devel)
trv.columnconfigure(0, weight=1)
trv.grid(row=r, columnspan=2, sticky="we")
scb_files = ttk.Scrollbar(trv)
self.trv_files = ttk.Treeview(trv)
self.trv_files.bind("<<TreeviewSelect>>", self.select_pathfiles)
self.trv_files["height"] = 15
self.trv_files["yscrollcommand"] = scb_files.set
self.trv_files.grid(row=0, column=0, sticky="we")
scb_files["command"] = self.trv_files.yview
scb_files.grid(row=0, column=1, sticky="ns")
# Uploadbutton
r += 1
btnlist = ttk.Frame(devel)
btnlist.columnconfigure(1, weight=1)
btnlist.grid(row=r, columnspan=2, sticky="we")
self.btn_jobs = ttk.Button(btnlist)
self.btn_jobs["command"] = lambda: self.btn_domyjob(stop_restart=True)
self.btn_jobs["text"] = _("Stop / Upload / Start")
self.btn_jobs.grid(row=0, column=0, **cpadwe)
self.btn_jobs = ttk.Button(btnlist)
self.btn_jobs["command"] = lambda: self.btn_domyjob(stop_restart=False)
self.btn_jobs["text"] = _("Just upload")
self.btn_jobs.grid(row=0, column=1, **cpadwe)
def btn_domyjob(self, stop_restart=True):
u"""Hochladen und neu starten.
@param stop_restart Bestehendes Programm Beenden/Starten"""
if stop_restart:
# PLC Programm anhalten
self.xmlcli.plcstop()
# Aktuell konfiguriertes Programm lesen (für uploaded Flag)
opt_program = self.xmlcli.get_config()
opt_program = opt_program.get("plcprogram", "none.py")
uploaded = True
ec = 0
for fname in self.watchfiles:
# FIXME: Fehlerabfang bei Dateilesen
with open(fname, "rb") as fh:
# Ordnernamen vom System entfernen
sendname = fname.replace(self.watchpath, "")[1:]
# Prüfen ob Dateiname bereits als Startprogramm angegeben ist
if sendname == opt_program:
uploaded = False
# Datei übertragen
try:
ustatus = self.xmlcli.plcupload(
Binary(gzip.compress(fh.read())), sendname
)
except Exception:
ec = -2
break
if not ustatus:
ec = -1
break
if ec == 0:
# Wenn eines der Dateien nicht das Hauptprogram ist, info
if uploaded:
tkmsg.showinfo(
_("Information"),
_("A PLC program has been uploaded. Please check the "
"PLC options to see if the correct program is "
"specified as the start program."),
parent=self.master
)
elif ec == -1:
tkmsg.showerror(
_("Error"),
_("The Revolution Pi could not process some parts of the "
"transmission."),
parent=self.master
)
elif ec == -2:
tkmsg.showerror(
_("Error"),
_("Errors occurred during transmission"),
parent=self.master
)
if stop_restart:
# PLC Programm starten
self.xmlcli.plcstart()
def btn_selectpath(self):
u"""Lässt dem Benuzter ein Verzeichnis auswählen."""
dirselect = tkfd.askdirectory(
parent=self.master,
title=_("Directory to watch"),
mustexist=False,
initialdir=self.watchpath
)
if not dirselect:
return
# Neuen Pfad übernehmen
if os.path.exists(dirselect):
self.pathselected = True
self.watchpath = dirselect
self.load_pathfiles()
else:
tkmsg.showerror(
_("Error"),
_("Can not open the selected folder."),
parent=self.master
)
self.refresh_stats()
def load_pathfiles(self, silent=False):
u"""Aktualisiert die Dateiliste.
@param silent Keinen Dialog anzeigen"""
# Liste leeren
self.trv_files.delete(*self.trv_files.get_children())
# Dateiliste erstellen
filecount = 0
for tup_walk in os.walk(self.watchpath):
for filename in sorted(tup_walk[2]):
fullname = os.path.join(tup_walk[0], filename)
self.trv_files.insert(
"", "end", fullname,
text=fullname.replace(self.watchpath, "")[1:],
values=fullname
)
# Dateiobergrenze
filecount += 1
if filecount >= 1000:
break
if filecount >= 1000:
if not silent:
tkmsg.showwarning(
_("Warning"),
_("Found more than 1000 files! Only 1000 files can be "
"shown in this dialog, all other will be ignored."
""),
parent=self.master
)
break
# Alle Elemente für Selection prüfen und anwenden
for watchfile in self.watchfiles.copy():
try:
self.trv_files.item(watchfile)
except Exception:
self.watchfiles.remove(watchfile)
self.trv_files.selection_set(self.watchfiles)
def select_pathfiles(self, tkevt):
u"""Setzt state der Buttons."""
self.watchfiles = list(self.trv_files.selection())
self.refresh_stats()
def refresh_stats(self):
u"""Passt die Widgets an."""
self.btn_jobs["state"] = "normal" if len(self.watchfiles) > 0 \
else "disabled"
self.lbl_path["text"] = self.watchpath
# Debugging
if __name__ == "__main__":
from xmlrpc.client import ServerProxy
cli = ServerProxy("http://localhost:55123")
root = tkinter.Tk()
app = RevPiDevelop(root, cli, 3, "debugging")
app.mainloop()

View File

@@ -1,10 +1,10 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""Programminformationen anzeigen."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
import tkinter.font as tkf
import webbrowser
@@ -16,6 +16,8 @@ _ = gettrans()
class RevPiInfo(tkinter.Frame):
u"""Baut Frame für Programminformationen."""
def __init__(self, master, xmlcli, version):
u"""Init RevPiLogfile-Class."""
self.master = master
@@ -52,7 +54,7 @@ class RevPiInfo(tkinter.Frame):
lbl.pack(pady=5)
lbl = tkinter.Label(self)
lbl["font"] = fntmid
lbl["text"] = _("Version: {}").format(self.version)
lbl["text"] = _("Version: {0}").format(self.version)
lbl.bind(
"<ButtonPress-2>",
lambda event: self._createwidgets(extended=not extended)

View File

@@ -0,0 +1,358 @@
# -*- coding: utf-8 -*-
u"""Alte Klassen laden hier, bevor sie entsorgt werden."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
import tkinter.messagebox as tkmsg
from mytools import gettrans
# Übersetzung laden
_ = gettrans()
class RevPiOption(tkinter.Frame):
u"""Optionen für RevPiPyload vor 0.6.0."""
def __init__(self, master, xmlcli):
u"""Init RevPiOption-Class.
@return None"""
try:
self.dc = xmlcli.get_config()
except Exception:
self.dc = None
return None
super().__init__(master)
self.master.bind("<KeyPress-Escape>", self._checkclose)
self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
self.xmlcli = xmlcli
self.mrk_var_xmlmod2 = False
self.mrk_var_xmlmod3 = False
self.mrk_xmlmodask = False
self.dorestart = False
# Fenster bauen
self._createwidgets()
self._loadappdata()
def _changesdone(self):
u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde"""
return (
self.var_start.get() != self.dc.get("autostart", "1") or
self.var_reload.get() != self.dc.get("autoreload", "1") or
self.var_zexit.get() != self.dc.get("zeroonexit", "0") or
self.var_zerr.get() != self.dc.get("zeroonerror", "0") or
self.var_startpy.get() != self.dc.get("plcprogram", "none.py") or
self.var_startargs.get() != self.dc.get("plcarguments", "") or
self.var_pythonver.get() != self.dc.get("pythonversion", "3") or
self.var_slave.get() != self.dc.get("plcslave", "0") or
self.var_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1) or
self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2) or
self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3)
# or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123")
)
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
ask = True
if self._changesdone():
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to quit? \nUnsaved changes will "
"be lost"),
parent=self.master, default="no"
)
if ask:
self.master.destroy()
def _createwidgets(self):
u"""Erstellt Widgets."""
self.master.wm_title(_("RevPi Python PLC Options"))
self.master.wm_resizable(width=False, height=False)
xmlstate = "normal" if self.dc["xmlrpc"] >= 3 else "disabled"
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
# Gruppe Start/Stop
stst = tkinter.LabelFrame(self)
stst["text"] = _("Start / Stop behavior")
stst.grid(columnspan=2, pady=2, sticky="we")
self.var_start = tkinter.BooleanVar(stst)
self.var_reload = tkinter.BooleanVar(stst)
self.var_zexit = tkinter.BooleanVar(stst)
self.var_zerr = tkinter.BooleanVar(stst)
ckb_start = tkinter.Checkbutton(stst)
ckb_start["text"] = _("Start program automatically")
ckb_start["state"] = xmlstate
ckb_start["variable"] = self.var_start
ckb_start.grid(**cpadw)
ckb_reload = tkinter.Checkbutton(stst)
ckb_reload["text"] = _("Restart program after exit")
ckb_reload["state"] = xmlstate
ckb_reload["variable"] = self.var_reload
ckb_reload.grid(**cpadw)
lbl = tkinter.Label(stst)
lbl["text"] = _("Set process image to NULL if program terminates...")
lbl.grid(**cpadw)
ckb_zexit = tkinter.Checkbutton(stst, justify="left")
ckb_zexit["state"] = xmlstate
ckb_zexit["text"] = _("... successfully")
ckb_zexit["variable"] = self.var_zexit
ckb_zexit.grid(**cpadw)
ckb_zerr = tkinter.Checkbutton(stst, justify="left")
ckb_zerr["state"] = xmlstate
ckb_zerr["text"] = _("... with errors")
ckb_zerr["variable"] = self.var_zerr
ckb_zerr.grid(**cpadw)
# Gruppe Programm
prog = tkinter.LabelFrame(self)
prog["text"] = _("PLC program")
prog.grid(columnspan=2, pady=2, sticky="we")
self.var_pythonver = tkinter.IntVar(prog)
self.var_startpy = tkinter.StringVar(prog)
self.var_startargs = tkinter.StringVar(prog)
self.var_slave = tkinter.BooleanVar(prog)
self.var_pythonver.set(3)
lbl = tkinter.Label(prog)
lbl["text"] = _("Python version")
lbl.grid(columnspan=2, row=0, **cpadw)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
rbn["text"] = "Python2"
rbn["value"] = 2
rbn["variable"] = self.var_pythonver
rbn.grid(column=0, row=1, **cpadw)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
rbn["text"] = "Python3"
rbn["value"] = 3
rbn["variable"] = self.var_pythonver
rbn.grid(column=1, row=1, **cpadw)
# Row 2
lbl = tkinter.Label(prog)
lbl["text"] = _("Python PLC program name")
lbl.grid(columnspan=2, **cpadw)
# Row 3
lst = self.xmlcli.get_filelist()
if len(lst) == 0:
lst.append("none")
opt_startpy = tkinter.OptionMenu(
prog, self.var_startpy, *lst
)
opt_startpy["state"] = xmlstate
opt_startpy.grid(columnspan=2, **cpadwe)
# Row 4
lbl = tkinter.Label(prog)
lbl["text"] = _("Program arguments")
lbl.grid(columnspan=2, **cpadw)
# Row 5
txt = tkinter.Entry(prog)
txt["textvariable"] = self.var_startargs
txt.grid(columnspan=2, **cpadw)
# Row 6
ckb_slave = tkinter.Checkbutton(prog, justify="left")
ckb_slave["state"] = xmlstate
ckb_slave["text"] = _("Use RevPi as PLC-Slave")
ckb_slave["variable"] = self.var_slave
ckb_slave.grid(column=0, **cpadw)
# Gruppe XMLRPC
xmlrpc = tkinter.LabelFrame(self)
xmlrpc["text"] = _("XML-RPC server")
xmlrpc.grid(columnspan=2, pady=2, sticky="we")
self.var_xmlon = tkinter.BooleanVar(xmlrpc)
self.var_xmlmod2 = tkinter.BooleanVar(xmlrpc)
self.var_xmlmod3 = tkinter.BooleanVar(xmlrpc)
# self.var_xmlport = tkinter.StringVar(xmlrpc)
# self.var_xmlport.set("55123")
ckb_xmlon = tkinter.Checkbutton(xmlrpc)
ckb_xmlon["command"] = self.askxmlon
ckb_xmlon["state"] = xmlstate
ckb_xmlon["text"] = _("Activate XML-RPC server on RevPi")
ckb_xmlon["variable"] = self.var_xmlon
ckb_xmlon.grid(**cpadw)
self.ckb_xmlmod2 = tkinter.Checkbutton(xmlrpc, justify="left")
self.ckb_xmlmod2["command"] = self.xmlmod2_tail
self.ckb_xmlmod2["state"] = xmlstate
self.ckb_xmlmod2["text"] = \
_("Allow download of piCtory configuration and\nPLC programm")
self.ckb_xmlmod2["variable"] = self.var_xmlmod2
self.ckb_xmlmod2.grid(**cpadw)
self.ckb_xmlmod3 = tkinter.Checkbutton(xmlrpc, justify="left")
self.ckb_xmlmod3["state"] = xmlstate
self.ckb_xmlmod3["text"] = \
_("Allow upload of piCtory configuration and\nPLC programm")
self.ckb_xmlmod3["variable"] = self.var_xmlmod3
self.ckb_xmlmod3.grid(**cpadw)
lbl = tkinter.Label(xmlrpc)
lbl["text"] = _("XML-RPC server port")
lbl.grid(**cpadw)
# spb_xmlport = tkinter.Spinbox(xmlrpc)
# spb_xmlport["to"] = 65535
# spb_xmlport["from"] = 1024
# spb_xmlport["state"] = xmlstate
# spb_xmlport["textvariable"] = self.var_xmlport
# spb_xmlport.grid(**cpadwe)
# Buttons
btn_save = tkinter.Button(self)
btn_save["command"] = self._setappdata
btn_save["state"] = xmlstate
btn_save["text"] = _("Save")
btn_save.grid(column=0, row=3)
btn_close = tkinter.Button(self)
btn_close["command"] = self._checkclose
btn_close["text"] = _("Close")
btn_close.grid(column=1, row=3)
def _loadappdata(self, refresh=False):
u"""Läd aktuelle Einstellungen vom RevPi.
@param refresh Wenn True, werden Einstellungen heruntergeladen."""
if refresh:
self.dc = self.xmlcli.get_config()
self.var_start.set(self.dc.get("autostart", "1"))
self.var_reload.set(self.dc.get("autoreload", "1"))
self.var_zexit.set(self.dc.get("zeroonexit", "0"))
self.var_zerr.set(self.dc.get("zeroonerror", "0"))
self.var_startpy.set(self.dc.get("plcprogram", "none.py"))
self.var_startargs.set(self.dc.get("plcarguments", ""))
self.var_pythonver.set(self.dc.get("pythonversion", "3"))
self.var_slave.set(self.dc.get("plcslave", "0"))
self.var_xmlon.set(self.dc.get("xmlrpc", 0) >= 1)
self.var_xmlmod2.set(self.dc.get("xmlrpc", 0) >= 2)
self.mrk_var_xmlmod2 = self.var_xmlmod2.get()
self.var_xmlmod3.set(self.dc.get("xmlrpc", 0) >= 3)
self.mrk_var_xmlmod3 = self.var_xmlmod3.get()
# self.var_xmlport.set(self.dc.get("xmlrpcport", "55123"))
def _setappdata(self):
u"""Speichert geänderte Einstellungen auf RevPi.
@return None"""
if not self._changesdone():
tkmsg.showinfo(
_("Information"),
_("You have not made any changes to save."),
parent=self.master
)
self._checkclose()
return None
ask = tkmsg.askyesnocancel(
_("Question"),
_("The settings are now saved on the Revolution Pi. \n\n"
"Should the new settings take effect immediately? \nThis "
"means a restart of the service and the PLC program!"),
parent=self.master
)
if ask is not None:
self.dc["autostart"] = int(self.var_start.get())
self.dc["autoreload"] = int(self.var_reload.get())
self.dc["zeroonexit"] = int(self.var_zexit.get())
self.dc["zeroonerror"] = int(self.var_zerr.get())
self.dc["plcprogram"] = self.var_startpy.get()
self.dc["plcarguments"] = self.var_startargs.get()
self.dc["pythonversion"] = self.var_pythonver.get()
self.dc["plcslave"] = int(self.var_slave.get())
self.dc["xmlrpc"] = 0
if self.var_xmlon.get():
self.dc["xmlrpc"] += 1
if self.var_xmlmod2.get():
self.dc["xmlrpc"] += 1
if self.var_xmlmod3.get():
self.dc["xmlrpc"] += 1
# self.dc["xmlrpcport"] = self.var_xmlport.get()
if self.xmlcli.set_config(self.dc, ask):
tkmsg.showinfo(
_("Information"),
_("Settings saved"),
parent=self.master
)
self.dorestart = ask
self._checkclose()
else:
tkmsg.showerror(
_("Error"),
_("The settings could not be saved. This can happen if "
"values are wrong!"),
parent=self.master
)
def askxmlon(self):
u"""Fragt Nuter, ob wirklicht abgeschaltet werden soll."""
if not (self.var_xmlon.get() or self.mrk_xmlmodask):
self.mrk_xmlmodask = tkmsg.askyesno(
_("Question"),
_("Are you sure you want to deactivate the XML-RPC server? "
"You will NOT be able to access the Revolution Pi with "
"this program."),
parent=self.master
)
if not self.mrk_xmlmodask:
self.var_xmlon.set(True)
self.xmlmod_tail()
def xmlmod_tail(self):
u"""Passt XML-Optionszugriff an."""
if self.var_xmlon.get():
self.var_xmlmod2.set(self.mrk_var_xmlmod2)
self.ckb_xmlmod2["state"] = "normal"
else:
self.mrk_var_xmlmod2 = self.var_xmlmod2.get()
self.var_xmlmod2.set(False)
self.ckb_xmlmod2["state"] = "disabled"
self.xmlmod2_tail()
def xmlmod2_tail(self):
u"""Passt XML-Optionszugriff an."""
if self.var_xmlmod2.get():
self.var_xmlmod3.set(self.mrk_var_xmlmod3)
self.ckb_xmlmod3["state"] = "normal"
else:
self.mrk_var_xmlmod3 = self.var_xmlmod3.get()
self.var_xmlmod3.set(False)
self.ckb_xmlmod3["state"] = "disabled"

View File

@@ -1,10 +1,10 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""Zeigt die Logfiles an."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
from mytools import gettrans
@@ -14,6 +14,8 @@ _ = gettrans()
class RevPiLogfile(tkinter.Frame):
u"""Baut Fenster für Logfiles."""
def __init__(self, master, xmlcli):
u"""Init RevPiLogfile-Class."""
super().__init__(master)
@@ -57,6 +59,7 @@ class RevPiLogfile(tkinter.Frame):
self.btnapplog["command"] = self.btn_clearplc
self.btnapplog["text"] = _("Clear screen")
self.btnapplog.grid(column=1, row=0, sticky="e")
self.plclog = tkinter.Text(self)
self.plcscr = tkinter.Scrollbar(self)
self.plclog.grid(sticky="wnse", columnspan=2, column=0, row=1)
@@ -72,6 +75,7 @@ class RevPiLogfile(tkinter.Frame):
self.btnapplog["command"] = self.btn_clearapp
self.btnapplog["text"] = _("Clear screen")
self.btnapplog.grid(column=4, row=0, sticky="e")
self.applog = tkinter.Text(self)
self.appscr = tkinter.Scrollbar(self)
self.applog.grid(sticky="nesw", columnspan=2, column=3, row=1)
@@ -101,7 +105,7 @@ class RevPiLogfile(tkinter.Frame):
self.applog, self.xmlcli.load_applog, self.mrkapp, full
)
self.errapp = 0
except:
except Exception:
self.errapp += 1
# Timer neu starten
@@ -117,7 +121,7 @@ class RevPiLogfile(tkinter.Frame):
self.plclog, self.xmlcli.load_plclog, self.mrkplc, full
)
self.errplc = 0
except:
except Exception:
self.errplc += 1
# Timer neu starten
@@ -150,13 +154,13 @@ class RevPiLogfile(tkinter.Frame):
if full:
textwidget.delete(1.0, tkinter.END)
if bytebuff == b'\x16': # 
if bytebuff == b'\x16': # 'ESC'
# Kein Zugriff auf Logdatei
textwidget.delete(1.0, tkinter.END)
textwidget.insert(
tkinter.END, _("Can not access log file on the RevPi")
)
elif bytebuff == b'\x19': # 
elif bytebuff == b'\x19': # 'EndOfMedia'
# Logdatei neu begonnen
startposition = 0
else:

View File

@@ -1,12 +1,14 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""Optionsfenster."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter
import tkinter.messagebox as tkmsg
from aclmanager import AclManager
from mqttmanager import MqttManager
from mytools import gettrans
# Übersetzung laden
@@ -15,12 +17,14 @@ _ = gettrans()
class RevPiOption(tkinter.Frame):
u"""Zeigt Optionen von RevPiPyLoad an."""
def __init__(self, master, xmlcli):
u"""Init RevPiOption-Class.
@return None"""
try:
self.dc = xmlcli.get_config()
except:
except Exception:
self.dc = None
return None
@@ -29,9 +33,27 @@ class RevPiOption(tkinter.Frame):
self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
self.frm_mqttmgr = None
self.frm_slaveacl = None
self.frm_xmlacl = None
# XML-RPC Server konfigurieren
self.xmlcli = xmlcli
self.mrk_var_xmlmod2 = False
self.mrk_var_xmlmod3 = False
self.xmlmodus = self.xmlcli.xmlmodus()
self._dict_mqttsettings = {
"mqttbasetopic": "revpi01",
"mqttclient_id": "",
"mqttbroker_address": "127.0.0.1",
"mqttpassword": "",
"mqttport": 1883,
"mqttsend_on_event": 0,
"mqttsendinterval": 30,
"mqtttls_set": 0,
"mqttusername": "",
"mqttwrite_outputs": 0,
}
self.mrk_xmlmodask = False
self.dorestart = False
@@ -43,20 +65,33 @@ class RevPiOption(tkinter.Frame):
u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde"""
return (
self.var_start.get() != self.dc.get("autostart", "1")
or self.var_reload.get() != self.dc.get("autoreload", "1")
or self.var_zexit.get() != self.dc.get("zeroonexit", "0")
or self.var_zerr.get() != self.dc.get("zeroonerror", "0")
or self.var_startpy.get() != self.dc.get("plcprogram", "none.py")
or self.var_startargs.get() != self.dc.get("plcarguments", "")
or self.var_pythonver.get() != self.dc.get("pythonversion", "3")
or self.var_slave.get() != self.dc.get("plcslave", "0")
or self.var_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1)
or self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2)
or self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3)
or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123")
self.var_start.get() != self.dc.get("autostart", 1) or
self.var_reload.get() != self.dc.get("autoreload", 1) or
self.var_reload_delay.get() !=
str(self.dc.get("autoreloaddelay", 5)) or
self.var_zexit.get() != self.dc.get("zeroonexit", 0) or
self.var_zerr.get() != self.dc.get("zeroonerror", 0) or
# TODO: rtlevel (0)
self.var_startpy.get() != self.dc.get("plcprogram", "none.py") or
self.var_startargs.get() != self.dc.get("plcarguments", "") or
self.var_pythonver.get() != self.dc.get("pythonversion", 3) or
self.var_slave.get() != self.dc.get("plcslave", 0) or
self.var_slaveacl.get() != self.dc.get("plcslaveacl", "") or
self.var_mqtton.get() != self.dc.get("mqtt", 0) or
self.var_xmlon.get() != self.dc.get("xmlrpc", 0) or
self.var_xmlacl.get() != self.dc.get("xmlrpcacl", "") or
self._changesdone_mqtt()
)
def _changesdone_mqtt(self):
u"""Prüft ob MQTT-Settings geändert wurden.
@return True, wenn Änderungen existieren"""
for key in self._dict_mqttsettings:
if key in self.dc:
if self._dict_mqttsettings[key] != self.dc[key]:
return True
return False
def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event"""
@@ -72,13 +107,27 @@ class RevPiOption(tkinter.Frame):
if ask:
self.master.destroy()
def _checkvalues(self):
u"""Prüft alle Werte auf Gültigkeit.
@return True, wenn alle Werte gültig sind"""
if not self.var_reload_delay.get().isdigit():
tkmsg.showerror(
_("Error"),
_("The value of 'restart delay' ist not valid."),
parent=self.master
)
return False
return True
def _createwidgets(self):
u"""Erstellt Widgets."""
self.master.wm_title(_("RevPi Python PLC Options"))
self.master.wm_resizable(width=False, height=False)
xmlstate = "normal" if self.dc["xmlrpc"] >= 3 else "disabled"
xmlstate = "normal" if self.xmlmodus >= 4 else "disabled"
cpade = {"padx": 4, "pady": 2, "sticky": "e"}
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
@@ -89,6 +138,7 @@ class RevPiOption(tkinter.Frame):
self.var_start = tkinter.BooleanVar(stst)
self.var_reload = tkinter.BooleanVar(stst)
self.var_reload_delay = tkinter.StringVar(stst)
self.var_zexit = tkinter.BooleanVar(stst)
self.var_zerr = tkinter.BooleanVar(stst)
@@ -96,51 +146,63 @@ class RevPiOption(tkinter.Frame):
ckb_start["text"] = _("Start program automatically")
ckb_start["state"] = xmlstate
ckb_start["variable"] = self.var_start
ckb_start.grid(**cpadw)
ckb_start.grid(columnspan=2, **cpadw)
ckb_reload = tkinter.Checkbutton(stst)
ckb_reload["text"] = _("Restart program after exit")
ckb_reload["state"] = xmlstate
ckb_reload["variable"] = self.var_reload
ckb_reload.grid(**cpadw)
ckb_reload.grid(columnspan=2, **cpadw)
lbl = tkinter.Label(stst)
lbl["text"] = _("Restart after n seconds of delay")
lbl.grid(**cpadw)
sbx = tkinter.Spinbox(stst)
sbx["to"] = 60
sbx["from_"] = 5
sbx["textvariable"] = self.var_reload_delay
sbx["width"] = 4
sbx.grid(column=1, row=2, **cpade)
lbl = tkinter.Label(stst)
lbl["text"] = _("Set process image to NULL if program terminates...")
lbl.grid(columnspan=2, **cpadw)
ckb_zexit = tkinter.Checkbutton(stst, justify="left")
ckb_zexit["state"] = xmlstate
ckb_zexit["text"] = _(
"Set process image to NULL if program\n"
"terminates successfully")
ckb_zexit["text"] = _("... successfully")
ckb_zexit["variable"] = self.var_zexit
ckb_zexit.grid(**cpadw)
ckb_zerr = tkinter.Checkbutton(stst, justify="left")
ckb_zerr["state"] = xmlstate
ckb_zerr["text"] = _(
"Set process image to NULL if program\n"
"terminates with errors")
ckb_zerr["text"] = _("... with errors")
ckb_zerr["variable"] = self.var_zerr
ckb_zerr.grid(**cpadw)
# Gruppe Programm
prog = tkinter.LabelFrame(self)
prog.columnconfigure(0, weight=1)
prog.columnconfigure(1, weight=1)
prog["text"] = _("PLC program")
prog.grid(columnspan=2, pady=2, sticky="we")
self.var_pythonver = tkinter.IntVar(prog)
self.var_startpy = tkinter.StringVar(prog)
self.var_startargs = tkinter.StringVar(prog)
self.var_slave = tkinter.BooleanVar(prog)
self.var_pythonver.set(3)
lbl = tkinter.Label(prog)
lbl["text"] = _("Python version")
lbl["text"] = _("Python version") + ":"
lbl.grid(columnspan=2, row=0, **cpadw)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
rbn["text"] = "Python2"
rbn["value"] = 2
rbn["variable"] = self.var_pythonver
rbn.grid(column=0, row=1, **cpadw)
rbn.grid(column=0, row=1, **cpade)
rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate
@@ -149,78 +211,111 @@ class RevPiOption(tkinter.Frame):
rbn["variable"] = self.var_pythonver
rbn.grid(column=1, row=1, **cpadw)
# Row 2
lbl = tkinter.Label(prog)
lbl["text"] = _("Python PLC program name")
lbl.grid(columnspan=2, **cpadw)
# Row 3
lst = self.xmlcli.get_filelist()
lst.sort()
if len(lst) == 0:
lst.append("none")
if ".placeholder" in lst:
lst.remove(".placeholder")
opt_startpy = tkinter.OptionMenu(
prog, self.var_startpy, *lst)
prog, self.var_startpy, *lst
)
opt_startpy["state"] = xmlstate
opt_startpy.grid(columnspan=2, **cpadwe)
# Row 4
lbl = tkinter.Label(prog)
lbl["text"] = _("Program arguments")
lbl.grid(columnspan=2, **cpadw)
# Row 5
txt = tkinter.Entry(prog)
txt["textvariable"] = self.var_startargs
txt.grid(columnspan=2, **cpadw)
ckb_slave = tkinter.Checkbutton(prog, justify="left")
# Gruppe Services
services = tkinter.LabelFrame(self)
services["text"] = _("RevPiPyLoad server services")
services.grid(columnspan=2, pady=2, sticky="we")
# RevPiSlave Service
self.var_slave = tkinter.BooleanVar(services)
self.var_slaveacl = tkinter.StringVar(services)
row = 0
ckb_slave = tkinter.Checkbutton(services, justify="left")
ckb_slave["state"] = xmlstate
ckb_slave["text"] = _("Use RevPi as PLC-Slave")
ckb_slave["state"] = "disabled"
ckb_slave["variable"] = self.var_slave
ckb_slave.grid(columnspan=2, **cpadw)
ckb_slave.grid(column=0, **cpadw)
# Gruppe XMLRPC
xmlrpc = tkinter.LabelFrame(self)
xmlrpc["text"] = _("XML-RPC server")
xmlrpc.grid(columnspan=2, pady=2, sticky="we")
btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_slaveacl
btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpadwe)
self.var_xmlon = tkinter.BooleanVar(xmlrpc)
self.var_xmlmod2 = tkinter.BooleanVar(xmlrpc)
self.var_xmlmod3 = tkinter.BooleanVar(xmlrpc)
self.var_xmlport = tkinter.StringVar(xmlrpc)
self.var_xmlport.set("55123")
row = 1
lbl = tkinter.Label(services)
lbl["text"] = _("RevPi-Slave service is:")
lbl.grid(column=0, **cpade)
ckb_xmlon = tkinter.Checkbutton(xmlrpc)
status = self.xmlcli.plcslaverunning()
lbl = tkinter.Label(services)
lbl["fg"] = "green" if status else "red"
lbl["text"] = _("running") if status else _("stopped")
lbl.grid(column=1, row=row, **cpadwe)
# MQTT Service
self.var_mqtton = tkinter.BooleanVar(services)
try:
status = self.xmlcli.mqttrunning()
except Exception:
pass
else:
row = 2
ckb_slave = tkinter.Checkbutton(services, justify="left")
ckb_slave["state"] = xmlstate
ckb_slave["text"] = _("MQTT process image publisher")
ckb_slave["variable"] = self.var_mqtton
ckb_slave.grid(column=0, **cpadw)
btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_mqttsettings
btn_slaveacl["text"] = _("Settings")
btn_slaveacl.grid(column=1, row=row, **cpadwe)
row = 3
lbl = tkinter.Label(services)
lbl["text"] = _("MQTT publish service is:")
lbl.grid(column=0, **cpade)
lbl = tkinter.Label(services)
lbl["fg"] = "green" if status else "red"
lbl["text"] = _("running") if status else _("stopped")
lbl.grid(column=1, row=row, **cpadwe)
# XML-RPC Service
self.var_xmlon = tkinter.BooleanVar(services)
self.var_xmlacl = tkinter.StringVar(services)
row = 4
ckb_xmlon = tkinter.Checkbutton(services)
ckb_xmlon["command"] = self.askxmlon
ckb_xmlon["state"] = xmlstate
ckb_xmlon["text"] = _("Activate XML-RPC server on RevPi")
ckb_xmlon["variable"] = self.var_xmlon
ckb_xmlon.grid(**cpadw)
self.ckb_xmlmod2 = tkinter.Checkbutton(xmlrpc, justify="left")
self.ckb_xmlmod2["command"] = self.xmlmod2_tail
self.ckb_xmlmod2["state"] = xmlstate
self.ckb_xmlmod2["text"] = \
_("Allow download of piCtory configuration and\nPLC programm")
self.ckb_xmlmod2["variable"] = self.var_xmlmod2
self.ckb_xmlmod2.grid(**cpadw)
btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_xmlacl
btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpadwe)
self.ckb_xmlmod3 = tkinter.Checkbutton(xmlrpc, justify="left")
self.ckb_xmlmod3["state"] = xmlstate
self.ckb_xmlmod3["text"] = \
_("Allow upload of piCtory configuration and\nPLC programm")
self.ckb_xmlmod3["variable"] = self.var_xmlmod3
self.ckb_xmlmod3.grid(**cpadw)
lbl = tkinter.Label(xmlrpc)
lbl["text"] = _("XML-RPC server port")
lbl.grid(**cpadw)
spb_xmlport = tkinter.Spinbox(xmlrpc)
spb_xmlport["to"] = 65535
spb_xmlport["from"] = 1024
spb_xmlport["state"] = xmlstate
spb_xmlport["textvariable"] = self.var_xmlport
spb_xmlport.grid(**cpadwe)
# Buttons
# Buttons am Ende
btn_save = tkinter.Button(self)
btn_save["command"] = self._setappdata
btn_save["state"] = xmlstate
@@ -238,23 +333,28 @@ class RevPiOption(tkinter.Frame):
if refresh:
self.dc = self.xmlcli.get_config()
self.var_start.set(self.dc.get("autostart", "1"))
self.var_reload.set(self.dc.get("autoreload", "1"))
self.var_zexit.set(self.dc.get("zeroonexit", "0"))
self.var_zerr.set(self.dc.get("zeroonerror", "0"))
self.var_start.set(self.dc.get("autostart", 1))
self.var_reload.set(self.dc.get("autoreload", 1))
self.var_reload_delay.set(self.dc.get("autoreloaddelay", 5))
self.var_zexit.set(self.dc.get("zeroonexit", 0))
self.var_zerr.set(self.dc.get("zeroonerror", 0))
# TODO: rtlevel (0)
self.var_startpy.set(self.dc.get("plcprogram", "none.py"))
self.var_startargs.set(self.dc.get("plcarguments", ""))
self.var_pythonver.set(self.dc.get("pythonversion", "3"))
self.var_slave.set(self.dc.get("plcslave", "0"))
self.var_pythonver.set(self.dc.get("pythonversion", 3))
self.var_xmlon.set(self.dc.get("xmlrpc", 0) >= 1)
self.var_xmlmod2.set(self.dc.get("xmlrpc", 0) >= 2)
self.mrk_var_xmlmod2 = self.var_xmlmod2.get()
self.var_xmlmod3.set(self.dc.get("xmlrpc", 0) >= 3)
self.mrk_var_xmlmod3 = self.var_xmlmod3.get()
# MQTT Einstellungen laden
self.var_mqtton.set(self.dc.get("mqtt", 0))
for key in self._dict_mqttsettings:
if key in self.dc:
self._dict_mqttsettings[key] = self.dc[key]
self.var_xmlport.set(self.dc.get("xmlrpcport", "55123"))
self.var_slave.set(self.dc.get("plcslave", 0))
self.var_slaveacl.set(self.dc.get("plcslaveacl", ""))
self.var_xmlon.set(self.dc.get("xmlrpc", 0))
self.var_xmlacl.set(self.dc.get("xmlrpcacl", ""))
def _setappdata(self):
u"""Speichert geänderte Einstellungen auf RevPi.
@@ -264,37 +364,64 @@ class RevPiOption(tkinter.Frame):
tkmsg.showinfo(
_("Information"),
_("You have not made any changes to save."),
parent=self.master
)
self._checkclose()
return None
ask = tkmsg.askyesnocancel(
# Gültigkeitsprüfung
if not self._checkvalues():
return None
ask = tkmsg.askokcancel(
_("Question"),
_("The settings are now saved on the Revolution Pi. \n\n"
"Should the new settings take effect immediately? \nThis "
"means a restart of the service and the PLC program!"),
_("The settings will be set on the Revolution Pi now. \n\n"
"If you made changes on the 'PCL Program' section, your plc "
"program will restart! \n"
"ACL changes and service settings are applied immediately."),
parent=self.master
)
if ask is not None:
self.dc["autostart"] = int(self.var_start.get())
if ask:
self.dc["autoreload"] = int(self.var_reload.get())
self.dc["zeroonexit"] = int(self.var_zexit.get())
self.dc["zeroonerror"] = int(self.var_zerr.get())
self.dc["autoreloaddelay"] = int(self.var_reload_delay.get())
self.dc["autostart"] = int(self.var_start.get())
self.dc["plcprogram"] = self.var_startpy.get()
self.dc["plcarguments"] = self.var_startargs.get()
self.dc["pythonversion"] = self.var_pythonver.get()
# TODO: rtlevel (0)
self.dc["zeroonerror"] = int(self.var_zerr.get())
self.dc["zeroonexit"] = int(self.var_zexit.get())
# MQTT Settings
self.dc["mqtt"] = int(self.var_mqtton.get())
self.dc["mqttbasetopic"] = \
self._dict_mqttsettings["mqttbasetopic"]
self.dc["mqttclient_id"] = \
self._dict_mqttsettings["mqttclient_id"]
self.dc["mqttbroker_address"] = \
self._dict_mqttsettings["mqttbroker_address"]
self.dc["mqttpassword"] = \
self._dict_mqttsettings["mqttpassword"]
self.dc["mqttusername"] = \
self._dict_mqttsettings["mqttusername"]
self.dc["mqttport"] = \
int(self._dict_mqttsettings["mqttport"])
self.dc["mqttsend_on_event"] = \
int(self._dict_mqttsettings["mqttsend_on_event"])
self.dc["mqttsendinterval"] = \
int(self._dict_mqttsettings["mqttsendinterval"])
self.dc["mqtttls_set"] = \
int(self._dict_mqttsettings["mqtttls_set"])
self.dc["mqttwrite_outputs"] = \
int(self._dict_mqttsettings["mqttwrite_outputs"])
# PLCSlave Settings
self.dc["plcslave"] = int(self.var_slave.get())
self.dc["plcslaveacl"] = self.var_slaveacl.get()
self.dc["xmlrpc"] = 0
if self.var_xmlon.get():
self.dc["xmlrpc"] += 1
if self.var_xmlmod2.get():
self.dc["xmlrpc"] += 1
if self.var_xmlmod3.get():
self.dc["xmlrpc"] += 1
self.dc["xmlrpcport"] = self.var_xmlport.get()
# XML Settings
self.dc["xmlrpc"] = int(self.var_xmlon.get())
self.dc["xmlrpcacl"] = self.var_xmlacl.get()
if self.xmlcli.set_config(self.dc, ask):
tkmsg.showinfo(
@@ -325,25 +452,62 @@ class RevPiOption(tkinter.Frame):
if not self.mrk_xmlmodask:
self.var_xmlon.set(True)
self.xmlmod_tail()
def btn_mqttsettings(self):
u"""Öffnet Fenster für MQTT Einstellungen."""
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
self.frm_mqttmgr = MqttManager(
win, self._dict_mqttsettings,
readonly=self.xmlmodus < 4
)
self.wait_window(win)
self._dict_mqttsettings = self.frm_mqttmgr.settings
def xmlmod_tail(self):
u"""Passt XML-Optionszugriff an."""
if self.var_xmlon.get():
self.var_xmlmod2.set(self.mrk_var_xmlmod2)
self.ckb_xmlmod2["state"] = "normal"
else:
self.mrk_var_xmlmod2 = self.var_xmlmod2.get()
self.var_xmlmod2.set(False)
self.ckb_xmlmod2["state"] = "disabled"
self.xmlmod2_tail()
def btn_slaveacl(self):
u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
self.frm_slaveacl = AclManager(
win, 0, 1,
self.var_slaveacl.get(),
readonly=self.xmlmodus < 4
)
self.frm_slaveacl.acltext = {
0: _("read only"),
1: _("read and write")
}
self.wait_window(win)
self.var_slaveacl.set(self.frm_slaveacl.acl)
def xmlmod2_tail(self):
u"""Passt XML-Optionszugriff an."""
if self.var_xmlmod2.get():
self.var_xmlmod3.set(self.mrk_var_xmlmod3)
self.ckb_xmlmod3["state"] = "normal"
else:
self.mrk_var_xmlmod3 = self.var_xmlmod3.get()
self.var_xmlmod3.set(False)
self.ckb_xmlmod3["state"] = "disabled"
def btn_xmlacl(self):
u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
self.frm_xmlacl = AclManager(
win, 0, 4,
self.var_xmlacl.get(),
readonly=self.xmlmodus < 4
)
self.frm_xmlacl.acltext = {
0: _("Start/Stop PLC program and read logs"),
1: _("+ read IOs in watch modus"),
2: _("+ read properties and download PLC program"),
3: _("+ upload PLC program"),
4: _("+ set properties")
}
self.wait_window(win)
self.var_xmlacl.set(self.frm_xmlacl.acl)
def destroy(self):
u"""Beendet alle Unterfenster und sich selbst."""
if self.frm_mqttmgr is not None:
self.frm_mqttmgr.master.destroy()
if self.frm_slaveacl is not None:
self.frm_slaveacl.master.destroy()
if self.frm_xmlacl is not None:
self.frm_xmlacl.master.destroy()
super().destroy()

View File

@@ -1,36 +1,33 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""Fenster um RevPi-Verbindungen einzurichten."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import os.path
import pickle
import tkinter
import tkinter.messagebox as tkmsg
from mytools import gettrans
from os import environ
from mytools import savefile_connections as savefile
from revpidevelop import _loaddefaults as developloaddefaults
from revpidevelop import _savedefaults as developsavedefaults
from revpiprogram import _loaddefaults as programloaddefaults
from revpiprogram import _savedefaults as programsavedefaults
from os import makedirs
from sys import platform
# Übersetzungen laden
_ = gettrans()
# Systemwerte
if platform == "linux":
homedir = environ["HOME"]
else:
homedir = environ["APPDATA"]
savefile = os.path.join(homedir, ".revpipyplc", "connections.dat")
def get_connections():
u"""Verbindungen aus Datei laden.
@return dict() mit Verbindungen"""
if os.path.exists(savefile):
fh = open(savefile, "rb")
connections = pickle.load(fh)
with open(savefile, "rb") as fh:
connections = pickle.load(fh)
return connections
else:
return {}
@@ -38,6 +35,8 @@ def get_connections():
class RevPiPlcList(tkinter.Frame):
u"""TK Fenster."""
def __init__(self, master):
u"""Init RevPiPlcList-class.
@param master tkinter master"""
@@ -92,11 +91,13 @@ class RevPiPlcList(tkinter.Frame):
# Eingabefelder für Adresse und Namen
tkinter.Label(self, text=_("Name")).grid(
column=2, row=0, sticky="wn", padx=5, pady=5)
column=2, row=0, sticky="wn", padx=5, pady=5
)
self.txt_name = tkinter.Entry(self, textvariable=self.var_name)
self.txt_name.bind("<KeyRelease>", self.evt_keypress)
self.txt_name.grid(
column=3, row=0, columnspan=3, sticky="n", padx=5, pady=5)
column=3, row=0, columnspan=3, sticky="n", padx=5, pady=5
)
tkinter.Label(self, text=_("IP address")).grid(
column=2, row=1, sticky="wn", padx=5, pady=5
@@ -104,34 +105,42 @@ class RevPiPlcList(tkinter.Frame):
self.txt_address = tkinter.Entry(self, textvariable=self.var_address)
self.txt_address.bind("<KeyRelease>", self.evt_keypress)
self.txt_address.grid(
column=3, row=1, columnspan=3, sticky="n", padx=5, pady=5)
column=3, row=1, columnspan=3, sticky="n", padx=5, pady=5
)
tkinter.Label(self, text=_("Port")).grid(
column=2, row=2, sticky="wn", padx=5, pady=5)
column=2, row=2, sticky="wn", padx=5, pady=5
)
self.txt_port = tkinter.Entry(self, textvariable=self.var_port)
self.txt_port.bind("<KeyRelease>", self.evt_keypress)
self.txt_port.grid(
column=3, row=2, columnspan=3, sticky="n", padx=5, pady=5)
column=3, row=2, columnspan=3, sticky="n", padx=5, pady=5
)
# Listenbutton
self.btn_new = tkinter.Button(
self, text=_("New"), command=self.evt_btnnew)
self, text=_("New"), command=self.evt_btnnew
)
self.btn_new.grid(column=2, row=3, sticky="s")
self.btn_add = tkinter.Button(
self, text=_("Apply"), command=self.evt_btnadd,
state="disabled")
self, text=_("Apply"),
command=self.evt_btnadd, state="disabled"
)
self.btn_add.grid(column=3, row=3, sticky="s")
self.btn_remove = tkinter.Button(
self, text=_("Remove"), command=self.evt_btnremove,
state="disabled")
self, text=_("Remove"),
command=self.evt_btnremove, state="disabled"
)
self.btn_remove.grid(column=4, row=3, sticky="s")
# Fensterbuttons
self.btn_save = tkinter.Button(
self, text=_("Save"), command=self.evt_btnsave)
self, text=_("Save"), command=self.evt_btnsave
)
self.btn_save.grid(column=3, row=9, sticky="se")
self.btn_close = tkinter.Button(
self, text=_("Close"), command=self._checkclose)
self, text=_("Close"), command=self._checkclose
)
self.btn_close.grid(column=4, row=9, sticky="se")
def _saveappdata(self):
@@ -139,11 +148,24 @@ class RevPiPlcList(tkinter.Frame):
@return True, bei erfolgreicher Verarbeitung"""
try:
makedirs(os.path.dirname(savefile), exist_ok=True)
fh = open(savefile, "wb")
pickle.dump(self._connections, fh)
with open(savefile, "wb") as fh:
pickle.dump(self._connections, fh)
self.changes = False
except:
except Exception:
return False
# Andere Einstellungen aufräumen
dict_o = developloaddefaults()
for revpi in tuple(dict_o.keys()):
if revpi not in self._connections:
del dict_o[revpi]
developsavedefaults(None, dict_o)
dict_o = programloaddefaults()
for revpi in tuple(dict_o.keys()):
if revpi not in self._connections:
del dict_o[revpi]
programsavedefaults(None, dict_o)
return True
def build_listconn(self):
@@ -179,7 +201,7 @@ class RevPiPlcList(tkinter.Frame):
item = self.list_conn.get(item_index[0])
ask = tkmsg.askyesno(
_("Question"),
_("Do you really want to delete the selected connection '{}'?"
_("Do you really want to delete the selected connection '{0}'?"
"").format(item),
parent=self.master
)
@@ -220,7 +242,6 @@ class RevPiPlcList(tkinter.Frame):
self.var_port.set(self._connections[item][1])
self.btn_add["state"] == "normal"
self.btn_remove["state"] = "normal"
else:
self.btn_remove["state"] = "disabled"
@@ -228,9 +249,9 @@ class RevPiPlcList(tkinter.Frame):
def evt_keypress(self, evt=None):
u"""Passt bei Tastendruck den Status der Buttons an."""
okvalue = "normal" if (
self.var_address.get() != ""
and self.var_name.get() != ""
and self.var_port.get() != ""
self.var_address.get() != "" and
self.var_name.get() != "" and
self.var_port.get() != ""
) else "disabled"
self.btn_add["state"] = okvalue

View File

@@ -1,10 +1,10 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""PLC Programm und Konfig hoch und runterladen."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import gzip
import os
import pickle
@@ -14,26 +14,56 @@ import tkinter.filedialog as tkfd
import tkinter.messagebox as tkmsg
import zipfile
from mytools import gettrans
from os import environ
from os import makedirs
from mytools import homedir
from mytools import savefile_programpath as savefile
from shutil import rmtree
from sys import platform
from tempfile import mkstemp, mkdtemp
from xmlrpc.client import Binary
# Übersetzung laden
_ = gettrans()
# Systemwerte
if platform == "linux":
homedir = environ["HOME"]
else:
homedir = environ["APPDATA"]
savefile = os.path.join(homedir, ".revpipyplc", "programpath.dat")
def _loaddefaults(revpiname=None):
u"""Übernimmt für den Pi die letzen Pfade.
@param revpiname Einstellungen nur für RevPi laden
@return <class 'dict'> mit Einstellungen"""
if os.path.exists(savefile):
with open(savefile, "rb") as fh:
dict_all = pickle.load(fh)
if revpiname is None:
return dict_all
else:
return dict_all.get(revpiname, {})
return {}
def _savedefaults(revpiname, settings):
u"""Schreibt fuer den Pi die letzen Pfade.
@param revpiname Einstellungen sind für diesen RevPi
@param settings <class 'dict'> mit Einstellungen
@return True, bei erfolgreicher Verarbeitung
"""
try:
os.makedirs(os.path.dirname(savefile), exist_ok=True)
if revpiname is None:
dict_all = settings
else:
dict_all = _loaddefaults()
dict_all[revpiname] = settings
with open(savefile, "wb") as fh:
pickle.dump(dict_all, fh)
except Exception:
return False
return True
class RevPiProgram(tkinter.Frame):
u"""Zeigt Programmfenster an."""
def __init__(self, master, xmlcli, xmlmode, revpi):
u"""Init RevPiProgram-Class.
@return None"""
@@ -48,11 +78,10 @@ class RevPiProgram(tkinter.Frame):
self.uploaded = False
self.revpi = revpi
self.xmlcli = xmlcli
self.xmlmode = xmlmode
self.xmlstate = "normal" if xmlmode == 3 else "disabled"
self.xmlstate = "normal" if xmlmode >= 3 else "disabled"
# Letzte Einstellungen übernehmen
self.opt = self._loaddefault()
self.opt = _loaddefaults(revpi)
# Fenster bauen
self._createwidgets()
@@ -121,8 +150,9 @@ class RevPiProgram(tkinter.Frame):
lbl["text"] = _("Download PLC program as:")
lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu(
prog, self.var_typedown, *self.lst_typedown,
command=self._evt_optdown)
prog, self.var_typedown, command=self._evt_optdown,
*self.lst_typedown
)
opt["width"] = 10
opt.grid(column=1, row=r, **cpad)
@@ -131,6 +161,7 @@ class RevPiProgram(tkinter.Frame):
self.ckb_picdown["text"] = _("include piCtory configuration")
self.ckb_picdown["variable"] = self.var_picdown
self.ckb_picdown.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog)
btn["command"] = self.plcdownload
btn["text"] = _("Download")
@@ -140,9 +171,11 @@ class RevPiProgram(tkinter.Frame):
lbl = tkinter.Label(prog)
lbl["text"] = _("Upload PLC program as:")
lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu(
prog, self.var_typeup, *self.lst_typeup,
command=self._evt_optup)
prog, self.var_typeup, command=self._evt_optup,
*self.lst_typeup
)
opt["state"] = self.xmlstate
opt["width"] = 10
opt.grid(column=1, row=r, **cpad)
@@ -160,6 +193,7 @@ class RevPiProgram(tkinter.Frame):
self.ckb_picup["text"] = _("includes piCtory configuration")
self.ckb_picup["variable"] = self.var_picup
self.ckb_picup.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog)
btn["command"] = self.plcupload
btn["state"] = self.xmlstate
@@ -175,13 +209,16 @@ class RevPiProgram(tkinter.Frame):
lbl = tkinter.Label(picto)
lbl["text"] = _("Download piCtory configuration")
lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(picto)
btn["command"] = self.getpictoryrsc
btn["text"] = _("Download")
btn.grid(column=1, row=0, **cpad)
lbl = tkinter.Label(picto)
lbl["text"] = _("Upload piCtory configuration")
lbl.grid(column=0, row=1, **cpadw)
btn = tkinter.Button(picto)
btn["command"] = self.setpictoryrsc
btn["state"] = self.xmlstate
@@ -193,9 +230,11 @@ class RevPiProgram(tkinter.Frame):
proc.columnconfigure(0, weight=1)
proc["text"] = _("piControl0 process image")
proc.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(proc)
lbl["text"] = _("Download process image dump")
lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(proc)
btn["command"] = self.getprocimg
btn["text"] = _("Download")
@@ -206,9 +245,11 @@ class RevPiProgram(tkinter.Frame):
picon.columnconfigure(0, weight=1)
picon["text"] = _("Reset piControl")
picon.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(picon)
lbl["text"] = _("Execute piControlReset")
lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(picon)
btn["command"] = self.picontrolreset
btn["text"] = _("execute")
@@ -236,33 +277,6 @@ class RevPiProgram(tkinter.Frame):
else:
self.ckb_picup["state"] = "normal"
def _loaddefault(self, full=False):
u"""Übernimmt für den Pi die letzen Pfade.
@param full Einstellungen für alle Verbindungen laden
@return dict() mit Einstellungen"""
if os.path.exists(savefile):
fh = open(savefile, "rb")
dict_all = pickle.load(fh)
if full:
return dict_all
else:
return dict_all.get(self.revpi, {})
return {}
def _savedefaults(self):
u"""Schreibt fuer den Pi die letzen Pfade.
@return True, bei erfolgreicher Verarbeitung"""
try:
makedirs(os.path.dirname(savefile), exist_ok=True)
dict_all = self._loaddefault(full=True)
dict_all[self.revpi] = self.opt
fh = open(savefile, "wb")
pickle.dump(dict_all, fh)
self.changes = False
except:
return False
return True
def create_filelist(self, rootdir):
u"""Erstellt eine Dateiliste von einem Verzeichnis.
@param rootdir Verzeichnis fuer das eine Liste erstellt werden soll
@@ -310,7 +324,7 @@ class RevPiProgram(tkinter.Frame):
if fh is not None:
try:
fh.write(self.xmlcli.get_pictoryrsc().data)
except:
except Exception:
tkmsg.showerror(
_("Error"),
_("Could not load and save file!"),
@@ -324,7 +338,7 @@ class RevPiProgram(tkinter.Frame):
)
# Einstellungen speichern
self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name)
self._savedefaults()
_savedefaults(self.revpi, self.opt)
finally:
fh.close()
@@ -341,7 +355,7 @@ class RevPiProgram(tkinter.Frame):
if fh is not None:
try:
fh.write(self.xmlcli.get_procimg().data)
except:
except Exception:
tkmsg.showerror(
_("Error"),
_("Could not load and save file!"),
@@ -355,7 +369,7 @@ class RevPiProgram(tkinter.Frame):
)
# Einstellungen speichern
self.opt["getprocimg_dir"] = os.path.dirname(fh.name)
self._savedefaults()
_savedefaults(self.revpi, self.opt)
finally:
fh.close()
@@ -403,7 +417,7 @@ class RevPiProgram(tkinter.Frame):
# Einstellungen speichern
self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name)
self._savedefaults()
_savedefaults(self.revpi, self.opt)
elif ec == -1:
tkmsg.showerror(
_("Error"),
@@ -546,7 +560,7 @@ class RevPiProgram(tkinter.Frame):
self.opt["typedown"] = self.var_typedown.get()
self.opt["picdown"] = self.var_picdown.get()
except:
except Exception:
raise
tkmsg.showerror(
_("Error"),
@@ -561,7 +575,7 @@ class RevPiProgram(tkinter.Frame):
)
# Einstellungen speichern
self._savedefaults()
_savedefaults(self.revpi, self.opt)
finally:
fh.close()
@@ -573,6 +587,7 @@ class RevPiProgram(tkinter.Frame):
dirtmp = None
filelist = []
fileselect = None
foldername = ""
rscfile = None
if tup == 0:
@@ -580,7 +595,7 @@ class RevPiProgram(tkinter.Frame):
fileselect = tkfd.askopenfilenames(
parent=self.master,
title="Upload Python program...",
initialdir=self.opt.get("plcupload_dir", ""),
initialdir=self.opt.get("plcupload_dir", homedir),
filetypes=(("Python", "*.py"), (_("All files"), "*.*"))
)
if type(fileselect) == tuple and len(fileselect) > 0:
@@ -593,8 +608,12 @@ class RevPiProgram(tkinter.Frame):
parent=self.master,
title=_("Folder to upload"),
mustexist=True,
initialdir=self.opt.get("plcupload_dir", self.revpi)
initialdir=self.opt.get("plcupload_dir", homedir)
)
# Ordnernamen merken um diesen auf RevPi anzulegen
foldername = os.path.basename(dirselect)
if type(dirselect) == str and dirselect != "":
filelist = self.create_filelist(dirselect)
@@ -691,7 +710,11 @@ class RevPiProgram(tkinter.Frame):
if dirselect == "":
sendname = os.path.basename(fname)
else:
sendname = fname.replace(dirselect, "")[1:]
# Ordnernamen in Dateipfad für RevPi übernehmen
sendname = os.path.join(
foldername,
fname.replace(dirselect, "")[1:]
)
# Prüfen ob Dateiname bereits als Startprogramm angegeben ist
if sendname == opt_program:
@@ -701,7 +724,7 @@ class RevPiProgram(tkinter.Frame):
try:
ustatus = self.xmlcli.plcupload(
Binary(gzip.compress(fh.read())), sendname)
except:
except Exception:
ec = -2
break
@@ -737,7 +760,7 @@ class RevPiProgram(tkinter.Frame):
self.opt["typeup"] = self.var_typeup.get()
self.opt["picup"] = self.var_picup.get()
self._savedefaults()
_savedefaults(self.revpi, self.opt)
elif ec == -1:
tkmsg.showerror(

View File

@@ -1,16 +1,18 @@
#!/usr/bin/python3
#
# RevPiPyControl
# Version: see global var pycontrolverion
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
u"""RevPiPyControl main program."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
__version__ = "0.7.1"
import revpicheckclient
import revpidevelop
import revpiinfo
import revpilogfile
import revpioption
import revpilegacy
import revpiplclist
import revpiprogram
import socket
@@ -23,11 +25,11 @@ from xmlrpc.client import ServerProxy
# Übersetzung laden
_ = gettrans()
pycontrolversion = "0.4.2"
class RevPiPyControl(tkinter.Frame):
u"""Baut Hauptprogramm auf."""
def __init__(self, master=None):
u"""Init RevPiPyControl-Class.
@param master tkinter master"""
@@ -39,11 +41,13 @@ class RevPiPyControl(tkinter.Frame):
self.dict_conn = revpiplclist.get_connections()
self.errcount = 0
self.revpiname = None
self.revpipyversion = [0, 0, 0]
self.xmlfuncs = []
self.xmlmode = 0
# Debugger vorbereiten
# Frames vorbereiten
self.debugframe = None
self.developframe = None
# Globale Fenster
self.tkcheckclient = None
@@ -70,10 +74,15 @@ class RevPiPyControl(tkinter.Frame):
u"""Schließt alle Fenster."""
if self.tkcheckclient is not None:
self.tkcheckclient.destroy()
if self.developframe is not None:
self.developframe._checkclose()
self.developframe.destroy()
self.developframe = None
if self.tklogs is not None:
self.tklogs.master.destroy()
if self.tkoptions is not None:
self.tkoptions.destroy()
self.tkoptions.master.destroy()
if self.tkprogram is not None:
self.tkprogram.destroy()
if self.debugframe is not None:
@@ -81,7 +90,7 @@ class RevPiPyControl(tkinter.Frame):
self.debugframe = None
try:
self.cli.psstop()
except:
except Exception:
pass
def _closeapp(self, event=None):
@@ -120,38 +129,43 @@ class RevPiPyControl(tkinter.Frame):
menu1.add_command(label=_("Info..."), command=self.infowindow)
self.mbar.add_cascade(label=_("Help"), menu=menu1)
self.var_conn = tkinter.StringVar(self)
self.txt_connect = tkinter.Entry(self, state="readonly", width=40)
self.main_frame = tkinter.Frame(self)
self.main_frame.pack(side="left", fill="y")
self.var_conn = tkinter.StringVar(self.main_frame)
self.txt_connect = tkinter.Entry(
self.main_frame, state="readonly", width=40
)
self.txt_connect["textvariable"] = self.var_conn
self.txt_connect.pack(fill="x")
self.btn_plcstart = tkinter.Button(self)
self.btn_plcstart = tkinter.Button(self.main_frame)
self.btn_plcstart["text"] = _("PLC start")
self.btn_plcstart["command"] = self.plcstart
self.btn_plcstart.pack(fill="x")
self.btn_plcstop = tkinter.Button(self)
self.btn_plcstop = tkinter.Button(self.main_frame)
self.btn_plcstop["text"] = _("PLC stop")
self.btn_plcstop["command"] = self.plcstop
self.btn_plcstop.pack(fill="x")
self.btn_plcrestart = tkinter.Button(self)
self.btn_plcrestart = tkinter.Button(self.main_frame)
self.btn_plcrestart["text"] = _("PLC restart")
self.btn_plcrestart["command"] = self.plcrestart
self.btn_plcrestart.pack(fill="x")
self.btn_plclogs = tkinter.Button(self)
self.btn_plclogs = tkinter.Button(self.main_frame)
self.btn_plclogs["text"] = _("PLC logs")
self.btn_plclogs["command"] = self.plclogs
self.btn_plclogs.pack(fill="x")
self.var_status = tkinter.StringVar(self)
self.txt_status = tkinter.Entry(self)
self.var_status = tkinter.StringVar(self.main_frame)
self.txt_status = tkinter.Entry(self.main_frame)
self.txt_status["state"] = "readonly"
self.txt_status["textvariable"] = self.var_status
self.txt_status.pack(fill="x")
self.btn_debug = tkinter.Button(self)
self.btn_debug = tkinter.Button(self.main_frame)
self.btn_debug["text"] = _("PLC watch mode")
self.btn_debug["command"] = self.plcdebug
self.btn_debug.pack(fill="x")
@@ -174,6 +188,8 @@ class RevPiPyControl(tkinter.Frame):
label=_("PLC options..."), command=self.plcoptions)
self.mplc.add_command(
label=_("PLC program..."), command=self.plcprogram)
self.mplc.add_command(
label=_("PLC developer..."), command=self.plcdevelop)
self.mplc.add_separator()
self.mplc.add_command(
@@ -189,12 +205,12 @@ class RevPiPyControl(tkinter.Frame):
@param text Verbindungsname
@param reconnect Socket Timeout nicht heruntersetzen"""
if reconnect:
socket.setdefaulttimeout(10)
socket.setdefaulttimeout(6)
else:
socket.setdefaulttimeout(2)
sp = ServerProxy(
"http://{}:{}".format(
"http://{0}:{1}".format(
self.dict_conn[text][0], int(self.dict_conn[text][1])
)
)
@@ -202,18 +218,19 @@ class RevPiPyControl(tkinter.Frame):
try:
self.xmlfuncs = sp.system.listMethods()
self.xmlmode = sp.xmlmodus()
except:
self.revpipyversion = list(map(int, sp.version().split(".")))
except Exception:
self.servererror()
else:
self._closeall()
socket.setdefaulttimeout(10)
socket.setdefaulttimeout(6)
self.cli = ServerProxy(
"http://{}:{}".format(
"http://{0}:{1}".format(
self.dict_conn[text][0], int(self.dict_conn[text][1])
)
)
self.revpiname = text
self.var_conn.set("{} - {}:{}".format(
self.var_conn.set("{0} - {1}:{2}".format(
text, self.dict_conn[text][0], int(self.dict_conn[text][1])
))
self.mbar.entryconfig("PLC", state="normal")
@@ -223,7 +240,7 @@ class RevPiPyControl(tkinter.Frame):
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
revpiinfo.RevPiInfo(win, self.cli, pycontrolversion)
revpiinfo.RevPiInfo(win, self.cli, __version__)
self.wait_window(win)
self.dict_conn = revpiplclist.get_connections()
self._fillconnbar()
@@ -236,45 +253,72 @@ class RevPiPyControl(tkinter.Frame):
if "psstart" not in self.xmlfuncs:
tkmsg.showwarning(
_("Warning"),
_("The watch mode ist not supported in version {} "
_("The watch mode ist not supported in version {0} "
"of RevPiPyLoad on your RevPi! You need at least version "
"0.4.0. Or the python3-revpimodio module is not installt"
"on your RevPi at least version 0.15.0."
"0.5.3! Maybe the python3-revpimodio2 module is not "
"installed on your RevPi at least version 2.0.0."
"").format(self.cli.version()),
parent=self.master
)
return
# FIXME: Bei neuer piCtory Konfig schneller vernichten
if self.debugframe is None:
try:
self.debugframe = revpicheckclient.RevPiCheckClient(
self.main_frame, self.cli, self.xmlmode
)
except Exception:
tkmsg.showwarning(
_("Error"),
_("Can not load piCtory configuration. \n"
"Did you create a hardware configuration? "
"Please check this in piCtory!"),
parent=self.master
)
self.btn_debug["state"] = "normal"
return None
# Fehler prüfen
if self.debugframe.err_workvalues >= self.debugframe.max_errors:
self.debugframe = None
return None
# Show/Hide wechseln
if self.debugframe.winfo_viewable():
self.debugframe.hideallwindows()
if self.debugframe.autorw.get():
self.debugframe.autorw.set(False)
self.debugframe.toggleauto()
self.debugframe.dowrite.set(False)
self.debugframe.pack_forget()
else:
# Debugfenster laden
if self.debugframe is None \
or self.debugframe.err_workvalues >= \
self.debugframe.max_errors:
try:
self.debugframe = revpicheckclient.RevPiCheckClient(
self, self.cli, self.xmlmode
)
except:
tkmsg.showwarning(
_("Error"),
_("Can not load piCtory configuration. \n"
"Have you created a hardware configuration? "
"Please check this in piCtory!"),
parent=self.master
)
self.btn_debug["state"] = "normal"
return None
self.debugframe.pack(fill="x")
# Show/Hide wechseln
if self.debugframe.winfo_viewable():
self.debugframe.hideallwindows()
if self.debugframe.autorw.get():
self.debugframe.autorw.set(False)
self.debugframe.toggleauto()
self.debugframe.dowrite.set(False)
self.debugframe.pack_forget()
else:
self.debugframe.pack(fill="x")
self.btn_debug["state"] = "normal"
self.btn_debug["state"] = "normal"
def plcdevelop(self):
u"""Startet das Developfenster."""
if self.xmlmode < 3:
tkmsg.showwarning(
_("Warning"),
_("XML-RPC access mode in the RevPiPyLoad "
"configuration is too small to access this dialog!"),
parent=self.master
)
return
# Developframe laden
if self.developframe is None:
self.developframe = revpidevelop.RevPiDevelop(
self, self.cli, self.xmlmode, self.revpiname
)
if self.developframe.winfo_viewable():
self.developframe._checkclose()
self.developframe.pack_forget()
else:
self.developframe.pack(side="right") # fill="x")
def plclist(self):
u"""Öffnet das Fenster für die Verbindungen."""
@@ -292,7 +336,7 @@ class RevPiPyControl(tkinter.Frame):
if "load_plclog" not in self.xmlfuncs:
tkmsg.showwarning(
_("Warning"),
_("This version of Logviewer ist not supported in version {} "
_("This version of Logviewer ist not supported in version {0} "
"of RevPiPyLoad on your RevPi! You need at least version "
"0.4.1.").format(self.cli.version()),
parent=self.master
@@ -318,13 +362,20 @@ class RevPiPyControl(tkinter.Frame):
win = tkinter.Toplevel(self)
win.focus_set()
win.grab_set()
self.tkoptions = \
revpioption.RevPiOption(win, self.cli)
# Gegenstelle prüfen und passende Optionen laden
if self.revpipyversion[0] == 0 and self.revpipyversion[1] < 6:
self.tkoptions = \
revpilegacy.RevPiOption(win, self.cli)
else:
self.tkoptions = \
revpioption.RevPiOption(win, self.cli)
self.wait_window(win)
if self.tkoptions.dc is not None and self.tkoptions.dorestart:
# Wenn XML-Modus anders und Dienstneustart
if self.xmlmode != self.tkoptions.dc["xmlrpc"]:
if self.xmlmode != self.cli.xmlmodus():
self.serverdisconnect()
self._opt_conn(self.revpiname, True)
@@ -375,7 +426,10 @@ class RevPiPyControl(tkinter.Frame):
self.serverdisconnect()
tkmsg.showerror(
_("Error"),
_("Can not reach server!"),
_("Can not connect to RevPi XML-RPC Service! \n\n"
"This could have the following reasons: The RevPi is not "
"online, the XML-RPC service is not running or the ACL "
"permission is not set for your IP!!!"),
parent=self.master
)
@@ -388,7 +442,7 @@ class RevPiPyControl(tkinter.Frame):
else:
try:
plcec = self.cli.plcexitcode()
except:
except Exception:
self.errcount += 1
if self.errcount >= 5:
self.var_status.set("SERVER ERROR")

View File

@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
"""Shared modules."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"

View File

@@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
"""Verwaltet IP Adressen und deren ACLs."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
from os import access, R_OK, W_OK
from re import match as rematch
def refullmatch(regex, string):
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
@param regex RegEx Statement
@param string Zeichenfolge gegen die getestet wird
@return True, wenn komplett passt sonst False
"""
m = rematch(regex, string)
return m is not None and m.end() == len(string)
class IpAclManager():
"""Verwaltung fuer IP Adressen und deren ACL Level."""
def __init__(self, minlevel, maxlevel, acl=None):
"""Init IpAclManager class.
@param minlevel Smallest access level (min. 0)
@param maxlevel Biggest access level (max. 9)
@param acl ACL Liste fuer Berechtigungen als <class 'str'>
"""
if type(minlevel) != int:
raise ValueError("parameter minlevel must be <class 'int'>")
if type(maxlevel) != int:
raise ValueError("parameter maxlevel must be <class 'int'>")
if minlevel < 0:
raise ValueError("minlevel must be 0 or more")
if maxlevel > 9:
raise ValueError("maxlevel maximum is 9")
if minlevel > maxlevel:
raise ValueError("minlevel is smaller than maxlevel")
self.__dict_acl = {}
self.__dict_regex = {}
self.__dict_knownips = {}
self.__filename = None
self.__re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[" \
+ str(minlevel) + "-" + str(maxlevel) + "] ?)*"
# Liste erstellen, wenn übergeben
if acl is not None:
self.__set_acl(acl)
def __iter__(self):
"""Gibt einzelne ACLs als <class 'tuple'> aus."""
for aclip in sorted(self.__dict_acl):
yield (aclip, self.__dict_acl[aclip])
def __get_acl(self):
"""Getter fuer den rohen ACL-String.
return ACLs als <class 'str'>"""
str_acl = ""
for aclip in sorted(self.__dict_acl):
str_acl += "{0},{1} ".format(aclip, self.__dict_acl[aclip])
return str_acl.strip()
def __get_filename(self):
"""Getter fuer Dateinamen.
@return Filename der ACL <class 'str'>"""
return "" if self.__filename is None else self.__filename
def __get_regex_acl(self):
"""Gibt formatierten RegEx-String zurueck.
return RegEx Code als <class 'str'>"""
return self.__re_ipacl
def __set_acl(self, value):
"""Uebernimmt neue ACL-Liste fuer die Ausertung der Level.
@param value Neue ACL-Liste als <class 'str'>"""
if type(value) != str:
raise ValueError("parameter acl must be <class 'str'>")
value = value.strip()
if not refullmatch(self.__re_ipacl, value):
raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1")
# Klassenwerte übernehmen
self.__dict_acl = {}
self.__dict_regex = {}
self.__dict_knownips = {}
# Liste neu füllen mit regex Strings
for ip_level in value.split():
ip, level = ip_level.split(",", 1)
self.__dict_acl[ip] = int(level)
self.__dict_regex[ip] = \
ip.replace(".", "\\.").replace("*", "\\d{1,3}")
def get_acllevel(self, ipaddress):
"""Prueft IP gegen ACL List und gibt ACL-Wert aus.
@param ipaddress zum pruefen
@return <class 'int'> ACL Wert oder -1 wenn nicht gefunden"""
# Bei bereits aufgelösten IPs direkt ACL auswerten
if ipaddress in self.__dict_knownips:
return self.__dict_knownips[ipaddress]
for aclip in sorted(self.__dict_acl, reverse=True):
if refullmatch(self.__dict_regex[aclip], ipaddress):
# IP und Level merken
self.__dict_knownips[ipaddress] = self.__dict_acl[aclip]
# Level zurückgeben
return self.__dict_acl[aclip]
return -1
def loadacl(self, str_acl):
"""Laed ACL String und gibt erfolg zurueck.
@param str_acl ACL als <class 'str'>
@return True, wenn erfolgreich uebernommen"""
if not refullmatch(self.__re_ipacl, str_acl):
return False
self.__set_acl(str_acl)
return True
def loadaclfile(self, filename):
"""Laed ACL Definitionen aus Datei.
@param filename Dateiname fuer Definitionen
@return True, wenn Laden erfolgreich war"""
if type(filename) != str:
raise ValueError("parameter filename must be <class 'str'>")
# Zugriffsrecht prüfen
if not access(filename, R_OK):
return False
str_acl = ""
with open(filename, "r") as fh:
while True:
buff = fh.readline()
if buff == "":
break
buff = buff.split("#")[0].strip()
if len(buff) > 0:
str_acl += buff + " "
acl_okay = self.loadacl(str_acl.strip())
if acl_okay:
# Dateinamen für Schreiben übernehmen
self.__filename = filename
return acl_okay
def writeaclfile(self, filename=None, aclname=None):
"""Schreibt ACL Definitionen in Datei.
@param filename Dateiname fuer Definitionen
@return True, wenn Schreiben erfolgreich war"""
if filename is not None and type(filename) != str:
raise ValueError("parameter filename must be <class 'str'>")
if aclname is not None and type(aclname) != str:
raise ValueError("parameter aclname must be <class 'str'>")
# Dateinamen prüfen
if filename is None and self.__filename is not None:
filename = self.__filename
# Zugriffsrecht prüfen
if not access(filename, W_OK):
return False
header = "# {0}Access Control List (acl)\n" \
"# One entry per Line IPADRESS,LEVEL\n" \
"#\n".format("" if aclname is None else aclname + " ")
with open(filename, "w") as fh:
fh.write(header)
for aclip in sorted(self.__dict_acl):
fh.write("{0},{1}\n".format(aclip, self.__dict_acl[aclip]))
return True
acl = property(__get_acl, __set_acl)
filename = property(__get_filename)
regex_acl = property(__get_regex_acl)

View File

@@ -1,9 +1,9 @@
#! /usr/bin/env python3
#
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
"""Setupscript fuer RevPiPyLoad."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
import distutils.command.install_egg_info
from sys import platform
from glob import glob
@@ -23,7 +23,7 @@ globsetup = {
"author_email": "akira@narux.de",
"url": "https://revpimodio.org/revpipyplc/",
"license": "LGPLv3",
"version": "0.4.2",
"version": "0.7.1",
"name": "revpipycontrol",
@@ -49,6 +49,7 @@ if platform == "linux":
("share/applications", ["data/revpipycontrol.desktop"]),
("share/icons/hicolor/32x32/apps", ["data/revpipycontrol.png"]),
("share/revpipycontrol", glob("revpipycontrol/*.*")),
("share/revpipycontrol/shared", glob("revpipycontrol/shared/*.*")),
(
"share/revpipycontrol/locale/de/LC_MESSAGES",
glob("revpipycontrol/locale/de/LC_MESSAGES/*.mo")

View File

@@ -3,3 +3,4 @@ Debian-Version=1
Depends3=python3-tk
Section=universe/x11
Suite=stable
X-Python3-Version: >=3.4