1
0
mirror of https://github.com/naruxde/revpipycontrol.git synced 2025-11-09 07:58:03 +01:00

27 Commits
0.6.1 ... 0.8.0

Author SHA1 Message Date
93e02df73e Style in Devices bei Watch-Mode verbessert
?bersetzungen
linux und mac haben selbe setup.py Einstellungen
2019-09-16 21:17:19 +02:00
63f60f9e36 Mit procimgserver zusammenf?hren 2019-09-16 10:47:48 +02:00
34f133ea6e Konfiguration plcworkdir_set_uid in Optionen integriert
Konfiguraiton replace_ios in Optionen integriert
Dropdownliste f?r forkonfigurierten Pfad von replace_ios eingebaut
2019-09-16 10:45:39 +02:00
472605bb38 Watchmode wertet nun auch byteorder und signed aus 2019-09-15 22:17:06 +02:00
79ea020903 Etikett 0.7.2 zum ?nderungssatz be20c934030f hinzugef?gt 2019-07-01 11:15:49 +02:00
7b61dee1c6 Fehler bei leerem Programmverzeichnis auf dem RevPi 2019-07-01 11:13:51 +02:00
f1163f2e3f added LICENSE.txt 2019-06-10 16:01:21 +02:00
5812dba69d Etikett 0.7.1 zum ?nderungssatz 278fcf116237 hinzugef?gt 2018-10-07 12:13:42 +02:00
7e9afd0944 Etikett 0.7.1 gel?scht 2018-10-07 12:13:34 +02:00
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
36 changed files with 2526 additions and 552 deletions

165
LICENSE.txt Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@@ -3,3 +3,5 @@ include stdeb.cfg
recursive-include data * recursive-include data *
recursive-include revpipycontrol * recursive-include revpipycontrol *
global-exclude *.pyc global-exclude *.pyc
include LICENSE.txt

View File

@@ -10,7 +10,7 @@ aclmanager</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
@@ -49,7 +49,7 @@ Methods</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="#AclManager.__init__">AclManager</a></td> <td><a style="color:#0000FF" href="#AclManager.__init__">AclManager</a></td>
<td>Init RevPiOption-Class.</td> <td>Init AclManger-Class.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#AclManager.__get_acltext">__get_acltext</a></td> <td><a style="color:#0000FF" href="#AclManager.__get_acltext">__get_acltext</a></td>
<td>Getter fuer Leveltexte.</td> <td>Getter fuer Leveltexte.</td>
@@ -107,7 +107,7 @@ Static Methods</h3>
AclManager (Constructor)</h3> AclManager (Constructor)</h3>
<b>AclManager</b>(<i>master, minlevel, maxlevel, acl_str="", readonly=False</i>) <b>AclManager</b>(<i>master, minlevel, maxlevel, acl_str="", readonly=False</i>)
<p> <p>
Init RevPiOption-Class. Init AclManger-Class.
</p><dl> </p><dl>
<dt>Returns:</dt> <dt>Returns:</dt>
<dd> <dd>

View File

@@ -6,7 +6,9 @@
<body style="background-color:#FFFFFF;color:#000000"> <body style="background-color:#FFFFFF;color:#000000">
<h1 style="background-color:#FFFFFF;color:#0000FF"> <h1 style="background-color:#FFFFFF;color:#0000FF">
revpipycontrol.shared</h1> revpipycontrol.shared</h1>
<p>
Shared modules.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">

View File

@@ -13,7 +13,7 @@ Packages</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="index-revpipycontrol.shared.html">shared</a></td> <td><a style="color:#0000FF" href="index-revpipycontrol.shared.html">shared</a></td>
<td></td> <td>Shared modules.</td>
</tr> </tr>
</table> </table>
@@ -24,12 +24,18 @@ Modules</h3>
<td><a style="color:#0000FF" href="aclmanager.html">aclmanager</a></td> <td><a style="color:#0000FF" href="aclmanager.html">aclmanager</a></td>
<td></td> <td></td>
</tr><tr> </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><a style="color:#0000FF" href="mytools.html">mytools</a></td>
<td>Tools-Sammlung.</td> <td>Tools-Sammlung.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="revpicheckclient.html">revpicheckclient</a></td> <td><a style="color:#0000FF" href="revpicheckclient.html">revpicheckclient</a></td>
<td></td> <td></td>
</tr><tr> </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><a style="color:#0000FF" href="revpiinfo.html">revpiinfo</a></td>
<td></td> <td></td>
</tr><tr> </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

@@ -12,7 +12,7 @@ Tools-Sammlung.
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <table>
<tr><td>savefile_connections</td></tr><tr><td>savefile_programpath</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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpicheckclient</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
@@ -87,6 +87,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiCheckClient.maxint">maxint</a></td> <td><a style="color:#0000FF" href="#RevPiCheckClient.maxint">maxint</a></td>
<td>Errechnet maximalen int() Wert f&#252;r Bytes max 22.</td> <td>Errechnet maximalen int() Wert f&#252;r Bytes max 22.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiCheckClient.minint">minint</a></td>
<td>Errechnet maximalen int() Wert f&#252;r Bytes max 22.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiCheckClient.readvalues">readvalues</a></td> <td><a style="color:#0000FF" href="#RevPiCheckClient.readvalues">readvalues</a></td>
<td>Ruft nur Input Werte von RevPi ab und aktualisiert Fenster.</td> <td>Ruft nur Input Werte von RevPi ab und aktualisiert Fenster.</td>
</tr><tr> </tr><tr>
@@ -244,13 +247,29 @@ Versteckt alle Fenster.
</p><a NAME="RevPiCheckClient.maxint" ID="RevPiCheckClient.maxint"></a> </p><a NAME="RevPiCheckClient.maxint" ID="RevPiCheckClient.maxint"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiCheckClient.maxint</h3> RevPiCheckClient.maxint</h3>
<b>maxint</b>(<i>bytelen</i>) <b>maxint</b>(<i>io</i>)
<p> <p>
Errechnet maximalen int() Wert f&#252;r Bytes max 22. Errechnet maximalen int() Wert f&#252;r Bytes max 22.
</p><dl> </p><dl>
<dt><i>bytelen</i></dt> <dt><i>io</i></dt>
<dd> <dd>
Anzahl Bytes IO-Liste, deren Wert berechnet werden soll
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
int() max oder 0 bei &#220;berschreitung
</dd>
</dl><a NAME="RevPiCheckClient.minint" ID="RevPiCheckClient.minint"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiCheckClient.minint</h3>
<b>minint</b>(<i>io</i>)
<p>
Errechnet maximalen int() Wert f&#252;r Bytes max 22.
</p><dl>
<dt><i>io</i></dt>
<dd>
IO-Liste, deren Wert berechnet werden soll
</dd> </dd>
</dl><dl> </dl><dl>
<dt>Returns:</dt> <dt>Returns:</dt>

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,7 +10,7 @@ revpiinfo</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpilegacy</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpilogfile</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpioption</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
@@ -51,9 +51,15 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiOption.__init__">RevPiOption</a></td> <td><a style="color:#0000FF" href="#RevPiOption.__init__">RevPiOption</a></td>
<td>Init RevPiOption-Class.</td> <td>Init RevPiOption-Class.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.__state_replace_ios">__state_replace_ios</a></td>
<td>Konfiguriert Werte f&#252;r replace_io.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption._changesdone">_changesdone</a></td> <td><a style="color:#0000FF" href="#RevPiOption._changesdone">_changesdone</a></td>
<td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td> <td>Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.</td>
</tr><tr> </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><a style="color:#0000FF" href="#RevPiOption._checkclose">_checkclose</a></td>
<td>Pr&#252;ft ob Fenster beendet werden soll.</td> <td>Pr&#252;ft ob Fenster beendet werden soll.</td>
</tr><tr> </tr><tr>
@@ -72,11 +78,17 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiOption.askxmlon">askxmlon</a></td> <td><a style="color:#0000FF" href="#RevPiOption.askxmlon">askxmlon</a></td>
<td>Fragt Nuter, ob wirklicht abgeschaltet werden soll.</td> <td>Fragt Nuter, ob wirklicht abgeschaltet werden soll.</td>
</tr><tr> </tr><tr>
<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.btn_slaveacl">btn_slaveacl</a></td> <td><a style="color:#0000FF" href="#RevPiOption.btn_slaveacl">btn_slaveacl</a></td>
<td>&#214;ffnet Fenster f&#252;r ACL-Verwaltung.</td> <td>&#214;ffnet Fenster f&#252;r ACL-Verwaltung.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiOption.btn_xmlacl">btn_xmlacl</a></td> <td><a style="color:#0000FF" href="#RevPiOption.btn_xmlacl">btn_xmlacl</a></td>
<td>&#214;ffnet Fenster f&#252;r ACL-Verwaltung.</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> </tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -95,6 +107,17 @@ Init RevPiOption-Class.
<dd> <dd>
None None
</dd> </dd>
</dl><a NAME="RevPiOption.__state_replace_ios" ID="RevPiOption.__state_replace_ios"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.__state_replace_ios</h3>
<b>__state_replace_ios</b>(<i>text</i>)
<p>
Konfiguriert Werte f&#252;r replace_io.
</p><dl>
<dt><i>text:</i></dt>
<dd>
Ausgew&#228;hlter Eintrag in Liste
</dd>
</dl><a NAME="RevPiOption._changesdone" ID="RevPiOption._changesdone"></a> </dl><a NAME="RevPiOption._changesdone" ID="RevPiOption._changesdone"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._changesdone</h3> RevPiOption._changesdone</h3>
@@ -106,6 +129,17 @@ Pr&#252;ft ob sich die Einstellungen ge&#228;ndert haben.
<dd> <dd>
True, wenn min. eine Einstellung ge&#228;ndert wurde True, wenn min. eine Einstellung ge&#228;ndert wurde
</dd> </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> </dl><a NAME="RevPiOption._checkclose" ID="RevPiOption._checkclose"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption._checkclose</h3> RevPiOption._checkclose</h3>
@@ -162,6 +196,12 @@ RevPiOption.askxmlon</h3>
<b>askxmlon</b>(<i></i>) <b>askxmlon</b>(<i></i>)
<p> <p>
Fragt Nuter, ob wirklicht abgeschaltet werden soll. Fragt Nuter, ob wirklicht abgeschaltet werden soll.
</p><a NAME="RevPiOption.btn_mqttsettings" ID="RevPiOption.btn_mqttsettings"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.btn_mqttsettings</h3>
<b>btn_mqttsettings</b>(<i></i>)
<p>
&#214;ffnet Fenster f&#252;r MQTT Einstellungen.
</p><a NAME="RevPiOption.btn_slaveacl" ID="RevPiOption.btn_slaveacl"></a> </p><a NAME="RevPiOption.btn_slaveacl" ID="RevPiOption.btn_slaveacl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiOption.btn_slaveacl</h3> RevPiOption.btn_slaveacl</h3>
@@ -174,6 +214,12 @@ RevPiOption.btn_xmlacl</h3>
<b>btn_xmlacl</b>(<i></i>) <b>btn_xmlacl</b>(<i></i>)
<p> <p>
&#214;ffnet Fenster f&#252;r ACL-Verwaltung. &#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> </p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div> <div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /> <hr />

View File

@@ -10,7 +10,7 @@ revpiplclist</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpiprogram</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -10,7 +10,7 @@ revpipycontrol</h1>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <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> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
@@ -78,6 +78,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiPyControl.plcdebug">plcdebug</a></td> <td><a style="color:#0000FF" href="#RevPiPyControl.plcdebug">plcdebug</a></td>
<td>Baut den Debugframe und packt ihn.</td> <td>Baut den Debugframe und packt ihn.</td>
</tr><tr> </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><a style="color:#0000FF" href="#RevPiPyControl.plclist">plclist</a></td>
<td>&#214;ffnet das Fenster f&#252;r die Verbindungen.</td> <td>&#214;ffnet das Fenster f&#252;r die Verbindungen.</td>
</tr><tr> </tr><tr>
@@ -200,7 +203,13 @@ Baut den Debugframe und packt ihn.
<dd> <dd>
None None
</dd> </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"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiPyControl.plclist</h3> RevPiPyControl.plclist</h3>
<b>plclist</b>(<i></i>) <b>plclist</b>(<i></i>)

View File

@@ -12,7 +12,7 @@ Verwaltet IP Adressen und deren ACLs.
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Global Attributes</h3> Global Attributes</h3>
<table> <table>
<tr><td>None</td></tr> <tr><td>__author__</td></tr><tr><td>__copyright__</td></tr><tr><td>__license__</td></tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>

View File

@@ -18,9 +18,29 @@ aclmanager.AclManager.get_acl?4()
aclmanager.AclManager.root?7 aclmanager.AclManager.root?7
aclmanager.AclManager?1(master, minlevel, maxlevel, acl_str="", readonly=False) aclmanager.AclManager?1(master, minlevel, maxlevel, acl_str="", readonly=False)
aclmanager._?8 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.addroot?4(filename)
mytools.gettrans?4(proglang=None) mytools.gettrans?4(proglang=None)
mytools.savefile_connections?7 mytools.savefile_connections?7
mytools.savefile_developer?7
mytools.savefile_programpath?7 mytools.savefile_programpath?7
revpicheckclient.RevPiCheckClient.__chval?6(device, io, event=None) revpicheckclient.RevPiCheckClient.__chval?6(device, io, event=None)
revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None) revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None)
@@ -33,7 +53,8 @@ revpicheckclient.RevPiCheckClient._onfrmconf?5(canvas)
revpicheckclient.RevPiCheckClient._warnwrite?5() revpicheckclient.RevPiCheckClient._warnwrite?5()
revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False) revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False)
revpicheckclient.RevPiCheckClient.hideallwindows?4() revpicheckclient.RevPiCheckClient.hideallwindows?4()
revpicheckclient.RevPiCheckClient.maxint?4(bytelen) revpicheckclient.RevPiCheckClient.maxint?4(io)
revpicheckclient.RevPiCheckClient.minint?4(io)
revpicheckclient.RevPiCheckClient.readvalues?4() revpicheckclient.RevPiCheckClient.readvalues?4()
revpicheckclient.RevPiCheckClient.refreshvalues?4() revpicheckclient.RevPiCheckClient.refreshvalues?4()
revpicheckclient.RevPiCheckClient.tmr_workvalues?4() revpicheckclient.RevPiCheckClient.tmr_workvalues?4()
@@ -43,11 +64,34 @@ revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist)
revpicheckclient.RevPiCheckClient.writevalues?4() revpicheckclient.RevPiCheckClient.writevalues?4()
revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0) revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0)
revpicheckclient._?8 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._checkclose?5(event=None)
revpiinfo.RevPiInfo._createwidgets?5(extended=False) revpiinfo.RevPiInfo._createwidgets?5(extended=False)
revpiinfo.RevPiInfo.visitwebsite?4(event=None) revpiinfo.RevPiInfo.visitwebsite?4(event=None)
revpiinfo.RevPiInfo?1(master, xmlcli, version) revpiinfo.RevPiInfo?1(master, xmlcli, version)
revpiinfo._?8 revpiinfo._?8
revpiinfo.__author__?9
revpiinfo.__copyright__?9
revpiinfo.__license__?9
revpilegacy.RevPiOption._changesdone?5() revpilegacy.RevPiOption._changesdone?5()
revpilegacy.RevPiOption._checkclose?5(event=None) revpilegacy.RevPiOption._checkclose?5(event=None)
revpilegacy.RevPiOption._createwidgets?5() revpilegacy.RevPiOption._createwidgets?5()
@@ -58,6 +102,9 @@ revpilegacy.RevPiOption.xmlmod2_tail?4()
revpilegacy.RevPiOption.xmlmod_tail?4() revpilegacy.RevPiOption.xmlmod_tail?4()
revpilegacy.RevPiOption?1(master, xmlcli) revpilegacy.RevPiOption?1(master, xmlcli)
revpilegacy._?8 revpilegacy._?8
revpilegacy.__author__?9
revpilegacy.__copyright__?9
revpilegacy.__license__?9
revpilogfile.RevPiLogfile._checkclose?5(event=None) revpilogfile.RevPiLogfile._checkclose?5(event=None)
revpilogfile.RevPiLogfile._createwidgets?5() revpilogfile.RevPiLogfile._createwidgets?5()
revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full) revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full)
@@ -67,17 +114,27 @@ revpilogfile.RevPiLogfile.get_applog?4(full=False)
revpilogfile.RevPiLogfile.get_plclog?4(full=False) revpilogfile.RevPiLogfile.get_plclog?4(full=False)
revpilogfile.RevPiLogfile?1(master, xmlcli) revpilogfile.RevPiLogfile?1(master, xmlcli)
revpilogfile._?8 revpilogfile._?8
revpilogfile.__author__?9
revpilogfile.__copyright__?9
revpilogfile.__license__?9
revpioption.RevPiOption.__state_replace_ios?6(text)
revpioption.RevPiOption._changesdone?5() revpioption.RevPiOption._changesdone?5()
revpioption.RevPiOption._changesdone_mqtt?5()
revpioption.RevPiOption._checkclose?5(event=None) revpioption.RevPiOption._checkclose?5(event=None)
revpioption.RevPiOption._checkvalues?5() revpioption.RevPiOption._checkvalues?5()
revpioption.RevPiOption._createwidgets?5() revpioption.RevPiOption._createwidgets?5()
revpioption.RevPiOption._loadappdata?5(refresh=False) revpioption.RevPiOption._loadappdata?5(refresh=False)
revpioption.RevPiOption._setappdata?5() revpioption.RevPiOption._setappdata?5()
revpioption.RevPiOption.askxmlon?4() revpioption.RevPiOption.askxmlon?4()
revpioption.RevPiOption.btn_mqttsettings?4()
revpioption.RevPiOption.btn_slaveacl?4() revpioption.RevPiOption.btn_slaveacl?4()
revpioption.RevPiOption.btn_xmlacl?4() revpioption.RevPiOption.btn_xmlacl?4()
revpioption.RevPiOption.destroy?4()
revpioption.RevPiOption?1(master, xmlcli) revpioption.RevPiOption?1(master, xmlcli)
revpioption._?8 revpioption._?8
revpioption.__author__?9
revpioption.__copyright__?9
revpioption.__license__?9
revpiplclist.RevPiPlcList._checkclose?5(event=None) revpiplclist.RevPiPlcList._checkclose?5(event=None)
revpiplclist.RevPiPlcList._createwidgets?5() revpiplclist.RevPiPlcList._createwidgets?5()
revpiplclist.RevPiPlcList._saveappdata?5() revpiplclist.RevPiPlcList._saveappdata?5()
@@ -92,6 +149,9 @@ revpiplclist.RevPiPlcList.myapp?7
revpiplclist.RevPiPlcList.root?7 revpiplclist.RevPiPlcList.root?7
revpiplclist.RevPiPlcList?1(master) revpiplclist.RevPiPlcList?1(master)
revpiplclist._?8 revpiplclist._?8
revpiplclist.__author__?9
revpiplclist.__copyright__?9
revpiplclist.__license__?9
revpiplclist.get_connections?4() revpiplclist.get_connections?4()
revpiprogram.RevPiProgram._checkclose?5(event=None) revpiprogram.RevPiProgram._checkclose?5(event=None)
revpiprogram.RevPiProgram._createwidgets?5() revpiprogram.RevPiProgram._createwidgets?5()
@@ -107,6 +167,9 @@ revpiprogram.RevPiProgram.plcupload?4()
revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None) revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None)
revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi) revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi)
revpiprogram._?8 revpiprogram._?8
revpiprogram.__author__?9
revpiprogram.__copyright__?9
revpiprogram.__license__?9
revpiprogram._loaddefaults?5(revpiname=None) revpiprogram._loaddefaults?5(revpiname=None)
revpiprogram._savedefaults?5(revpiname, settings) revpiprogram._savedefaults?5(revpiname, settings)
revpipycontrol.RevPiPyControl._btnstate?5() revpipycontrol.RevPiPyControl._btnstate?5()
@@ -119,6 +182,7 @@ revpipycontrol.RevPiPyControl._opt_conn?5(text, reconnect=False)
revpipycontrol.RevPiPyControl.infowindow?4() revpipycontrol.RevPiPyControl.infowindow?4()
revpipycontrol.RevPiPyControl.myapp?7 revpipycontrol.RevPiPyControl.myapp?7
revpipycontrol.RevPiPyControl.plcdebug?4() revpipycontrol.RevPiPyControl.plcdebug?4()
revpipycontrol.RevPiPyControl.plcdevelop?4()
revpipycontrol.RevPiPyControl.plclist?4() revpipycontrol.RevPiPyControl.plclist?4()
revpipycontrol.RevPiPyControl.plclogs?4() revpipycontrol.RevPiPyControl.plclogs?4()
revpipycontrol.RevPiPyControl.plcoptions?4() revpipycontrol.RevPiPyControl.plcoptions?4()
@@ -133,7 +197,13 @@ revpipycontrol.RevPiPyControl.tmr_plcrunning?4()
revpipycontrol.RevPiPyControl.visitwebsite?4() revpipycontrol.RevPiPyControl.visitwebsite?4()
revpipycontrol.RevPiPyControl?1(master=None) revpipycontrol.RevPiPyControl?1(master=None)
revpipycontrol._?8 revpipycontrol._?8
revpipycontrol.pycontrolversion?7 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_acl?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__get_filename?6() revpipycontrol.shared.ipaclmanager.IpAclManager.__get_filename?6()
revpipycontrol.shared.ipaclmanager.IpAclManager.__get_regex_acl?6() revpipycontrol.shared.ipaclmanager.IpAclManager.__get_regex_acl?6()
@@ -147,4 +217,7 @@ revpipycontrol.shared.ipaclmanager.IpAclManager.loadaclfile?4(filename)
revpipycontrol.shared.ipaclmanager.IpAclManager.regex_acl?7 revpipycontrol.shared.ipaclmanager.IpAclManager.regex_acl?7
revpipycontrol.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None) revpipycontrol.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None)
revpipycontrol.shared.ipaclmanager.IpAclManager?1(minlevel, maxlevel, acl=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) revpipycontrol.shared.ipaclmanager.refullmatch?4(regex, string)

View File

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

View File

@@ -1,32 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipycontrol --> <!-- eric project file for project revpipycontrol -->
<!-- Saved: 2018-04-07, 14:53:30 --> <!-- Saved: 2019-09-16, 10:44:39 -->
<!-- Copyright (C) 2018 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2019 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
<Hash>66103e2eaf8a762f14d1fd51d8b1c9dcaf35a275</Hash> <Hash>66103e2eaf8a762f14d1fd51d8b1c9dcaf35a275</Hash>
<ProgLanguage mixed="0">Python3</ProgLanguage> <ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType> <ProjectType>Console</ProjectType>
<Description></Description> <Version>0.8.0</Version>
<Version>0.6.1</Version>
<Author>Sven Sager</Author> <Author>Sven Sager</Author>
<Email>akira@narux.de</Email> <Email>akira@narux.de</Email>
<Eol index="1"/> <Eol index="1"/>
<Sources> <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>revpipycontrol/revpicheckclient.py</Source>
<Source>setup.py</Source> <Source>revpipycontrol/revpidevelop.py</Source>
<Source>revpipycontrol/revpiplclist.py</Source> <Source>revpipycontrol/revpiinfo.py</Source>
<Source>revpipycontrol/revpilegacy.py</Source>
<Source>revpipycontrol/revpilogfile.py</Source> <Source>revpipycontrol/revpilogfile.py</Source>
<Source>revpipycontrol/revpioption.py</Source> <Source>revpipycontrol/revpioption.py</Source>
<Source>revpipycontrol/revpiplclist.py</Source>
<Source>revpipycontrol/revpiprogram.py</Source> <Source>revpipycontrol/revpiprogram.py</Source>
<Source>revpipycontrol/mytools.py</Source> <Source>revpipycontrol/revpipycontrol.py</Source>
<Source>revpipycontrol/revpiinfo.py</Source>
<Source>revpipycontrol/aclmanager.py</Source>
<Source>revpipycontrol/revpilegacy.py</Source>
<Source>revpipycontrol/shared/ipaclmanager.py</Source>
<Source>revpipycontrol/shared/__init__.py</Source> <Source>revpipycontrol/shared/__init__.py</Source>
<Source>revpipycontrol/shared/ipaclmanager.py</Source>
<Source>setup.py</Source>
</Sources> </Sources>
<Forms/> <Forms/>
<Translations/> <Translations/>
@@ -35,8 +36,8 @@
<Others> <Others>
<Other>data</Other> <Other>data</Other>
<Other>doc</Other> <Other>doc</Other>
<Other>stdeb.cfg</Other>
<Other>eric-revpipycontrol.api</Other> <Other>eric-revpipycontrol.api</Other>
<Other>stdeb.cfg</Other>
</Others> </Others>
<MainScript>revpipycontrol/revpipycontrol.py</MainScript> <MainScript>revpipycontrol/revpipycontrol.py</MainScript>
<Vcs> <Vcs>
@@ -141,9 +142,6 @@
</value> </value>
</dict> </dict>
</VcsOptions> </VcsOptions>
<VcsOtherData>
<dict/>
</VcsOtherData>
</Vcs> </Vcs>
<FiletypeAssociations> <FiletypeAssociations>
<FiletypeAssociation pattern="*.idl" type="INTERFACES"/> <FiletypeAssociation pattern="*.idl" type="INTERFACES"/>
@@ -243,14 +241,6 @@
<value> <value>
<bool>False</bool> <bool>False</bool>
</value> </value>
<key>
<string>sourceExtensions</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key> <key>
<string>useRecursion</string> <string>useRecursion</string>
</key> </key>
@@ -265,11 +255,173 @@
<Checkers> <Checkers>
<CheckersParams> <CheckersParams>
<dict> <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> <key>
<string>Pep8Checker</string> <string>Pep8Checker</string>
</key> </key>
<value> <value>
<dict> <dict>
<key>
<string>BuiltinsChecker</string>
</key>
<value>
<dict>
<key>
<string>chr</string>
</key>
<value>
<list>
<string>unichr</string>
</list>
</value>
<key>
<string>str</string>
</key>
<value>
<list>
<string>unicode</string>
</list>
</value>
</dict>
</value>
<key>
<string>CopyrightAuthor</string>
</key>
<value>
<string></string>
</value>
<key>
<string>CopyrightMinFileSize</string>
</key>
<value>
<int>0</int>
</value>
<key> <key>
<string>DocstringType</string> <string>DocstringType</string>
</key> </key>
@@ -286,7 +438,7 @@
<string>ExcludeMessages</string> <string>ExcludeMessages</string>
</key> </key>
<value> <value>
<string>E123,E226,E24</string> <string>E123,E226,E24,C101</string>
</value> </value>
<key> <key>
<string>FixCodes</string> <string>FixCodes</string>
@@ -300,6 +452,12 @@
<value> <value>
<bool>False</bool> <bool>False</bool>
</value> </value>
<key>
<string>FutureChecker</string>
</key>
<value>
<string></string>
</value>
<key> <key>
<string>HangClosing</string> <string>HangClosing</string>
</key> </key>
@@ -312,6 +470,24 @@
<value> <value>
<string></string> <string></string>
</value> </value>
<key>
<string>LineComplexity</string>
</key>
<value>
<int>15</int>
</value>
<key>
<string>LineComplexityScore</string>
</key>
<value>
<int>10</int>
</value>
<key>
<string>MaxCodeComplexity</string>
</key>
<value>
<int>10</int>
</value>
<key> <key>
<string>MaxLineLength</string> <string>MaxLineLength</string>
</key> </key>
@@ -336,6 +512,12 @@
<value> <value>
<bool>False</bool> <bool>False</bool>
</value> </value>
<key>
<string>ValidEncodings</string>
</key>
<value>
<string>latin-1, utf-8</string>
</value>
</dict> </dict>
</value> </value>
</dict> </dict>

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Manager für ACL Einträge.""" u"""Manager für ACL Einträge."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
from mytools import gettrans from mytools import gettrans
@@ -21,7 +20,7 @@ class AclManager(ttk.Frame):
u"""Hauptfenster des ACL-Managers.""" u"""Hauptfenster des ACL-Managers."""
def __init__(self, master, minlevel, maxlevel, acl_str="", readonly=False): def __init__(self, master, minlevel, maxlevel, acl_str="", readonly=False):
u"""Init RevPiOption-Class. u"""Init AclManger-Class.
@return None""" @return None"""
super().__init__(master) super().__init__(master)
self.master.bind("<KeyPress-Escape>", self._checkclose) self.master.bind("<KeyPress-Escape>", self._checkclose)
@@ -56,8 +55,8 @@ class AclManager(ttk.Frame):
self.aclinfo = ttk.Frame(self) self.aclinfo = ttk.Frame(self)
for acltext in self.__dict_acltext: for acltext in self.__dict_acltext:
lbl = ttk.Label(self.aclinfo) lbl = ttk.Label(self.aclinfo)
lbl["text"] = _("Level") + " {}: {}".format( lbl["text"] = _("Level") + " {id}: {text}".format(
acltext, self.__dict_acltext[acltext] id=acltext, text=self.__dict_acltext[acltext]
) )
lbl.pack(anchor="w") lbl.pack(anchor="w")
@@ -276,12 +275,12 @@ class AclManager(ttk.Frame):
ask = tkmsg.askyesno( ask = tkmsg.askyesno(
_("Question"), _("Question"),
_("Do you really want to delete the following item? \n" _("Do you really want to delete the following item? \n"
"\nIP: {} / Level: {}").format(*lst_ipacl), "\nIP: {0} / Level: {1}").format(*lst_ipacl),
parent=self.master, default="no" parent=self.master, default="no"
) )
if ask: if ask:
new_acl = self.__acl.acl.replace( new_acl = self.__acl.acl.replace(
"{},{}".format(*lst_ipacl), "" "{0},{1}".format(*lst_ipacl), ""
).replace(" ", " ") ).replace(" ", " ")
if self.__acl.loadacl(new_acl.strip()): if self.__acl.loadacl(new_acl.strip()):
@@ -354,7 +353,7 @@ class AclManager(ttk.Frame):
def _savefields(self): def _savefields(self):
u"""Übernimmt neuen ACL Eintrag.""" u"""Übernimmt neuen ACL Eintrag."""
new_acl = "{}.{}.{}.{},{}".format( new_acl = "{0}.{1}.{2}.{3},{4}".format(
self.var_ip1.get(), self.var_ip1.get(),
self.var_ip2.get(), self.var_ip2.get(),
self.var_ip3.get(), self.var_ip3.get(),
@@ -386,8 +385,8 @@ class AclManager(ttk.Frame):
acltext = property(__get_acltext, __set_acltext) acltext = property(__get_acltext, __set_acltext)
# Debugging
if __name__ == "__main__": if __name__ == "__main__":
root = AclManager(tkinter.Tk(), 0, 9, " 192.168.50.100,2 127.0.0.*,1") root = AclManager(tkinter.Tk(), 0, 9, " 192.168.50.100,2 127.0.0.*,1")
root.acltext = {0: "Keine Rechte", 1: "Hohe Rechte"} root.acltext = {0: "Keine Rechte", 1: "Hohe Rechte"}
root.mainloop() root.mainloop()
print(root.acl)

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,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
"""Tools-Sammlung.""" """Tools-Sammlung."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import gettext import gettext
import locale import locale
import sys import sys
@@ -15,12 +14,16 @@ from os.path import join as pathjoin
from sys import platform from sys import platform
# Systemwerte und SaveFiles # Systemwerte und SaveFiles
# TODO: Mac einbauen
if platform == "linux": if platform == "linux":
homedir = environ["HOME"] homedir = environ["HOME"]
else: else:
homedir = environ["APPDATA"] homedir = environ["APPDATA"]
savefile_connections = pathjoin( savefile_connections = pathjoin(
homedir, ".revpipyplc", "connections.dat") homedir, ".revpipyplc", "connections.dat")
savefile_developer = pathjoin(
homedir, ".revpipyplc", "developer.dat")
savefile_programpath = pathjoin( savefile_programpath = pathjoin(
homedir, ".revpipyplc", "programpath.dat") homedir, ".revpipyplc", "programpath.dat")

View File

@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# u"""Fenstererweiterung für den 'watch modus'.
# RevPiPyControl
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-
# Webpage: https://revpimodio.org/revpipyplc/ scrollbar-to-a-group-of-widgets-in-tkinter
# (c) Sven Sager, License: LGPLv3
# """
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-
# scrollbar-to-a-group-of-widgets-in-tkinter __author__ = "Sven Sager"
u"""Fenstererweiterung für den 'watch modus'.""" __copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import pickle import pickle
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
@@ -99,8 +101,8 @@ class RevPiCheckClient(tkinter.Frame):
try: try:
newvalue = io[5].get() newvalue = io[5].get()
# Wertebereich prüfen # Wertebereich prüfen
if newvalue < 0 or newvalue > self.maxint(io[1]): if not self.minint(io) <= newvalue <= self.maxint(io):
raise ValueError("too big") raise ValueError("value not valid")
self.__chval(device, io) self.__chval(device, io)
@@ -108,8 +110,11 @@ class RevPiCheckClient(tkinter.Frame):
io[5].set(self.__oldvalue) io[5].set(self.__oldvalue)
tkmsg.showerror( tkmsg.showerror(
_("Error"), _("Error"),
_("Given value for Output '{}' is not valid! \nReset to ""'{}'" _("Given value for Output '{0}' is not valid! \n"
"").format(self.dict_devices[device], self.__oldvalue), "Reset to '{1}'").format(
self.dict_devices[device],
self.__oldvalue
),
parent=self.dict_wins[device] parent=self.dict_wins[device]
) )
@@ -135,10 +140,11 @@ class RevPiCheckClient(tkinter.Frame):
canvas = tkinter.Canvas( canvas = tkinter.Canvas(
frame, frame,
borderwidth=0, borderwidth=0,
width=180, width=190,
heigh=calc_heigh if calc_heigh <= 600 else 600 heigh=calc_heigh if calc_heigh <= 600 else 600
) )
s_frame = tkinter.Frame(canvas) s_frame = tkinter.Frame(canvas)
s_frame.columnconfigure(1, weight=1)
vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview) vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set) canvas.configure(yscrollcommand=vsb.set)
@@ -163,10 +169,10 @@ class RevPiCheckClient(tkinter.Frame):
# IOs generieren # IOs generieren
rowcount = 0 rowcount = 0
for io in lst_io: for io in lst_io:
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] # io = [name,blen,baddr,bmk,bitaddr,(tkinter_var),border,signed]
tkinter.Label(s_frame, text=io[0]).grid( tkinter.Label(s_frame, text=io[0]).grid(
column=0, row=rowcount, sticky="w" column=1, row=rowcount, sticky="w"
) )
if io[4] >= 0: if io[4] >= 0:
@@ -177,10 +183,14 @@ class RevPiCheckClient(tkinter.Frame):
check["state"] = "disabled" if iotype == "inp" else "normal" check["state"] = "disabled" if iotype == "inp" else "normal"
check["text"] = "" check["text"] = ""
check["variable"] = var check["variable"] = var
check.grid(column=1, row=rowcount) check.grid(column=0, row=rowcount)
else: else:
var = tkinter.IntVar() var = tkinter.IntVar()
txt = tkinter.Spinbox(s_frame, to=self.maxint(io[1])) txt = tkinter.Spinbox(
s_frame,
from_=self.minint(io),
to=self.maxint(io),
)
txt.bind( txt.bind(
"<Key>", "<Key>",
lambda event, tkvar=var: self.__saveoldvalue(event, tkvar) lambda event, tkvar=var: self.__saveoldvalue(event, tkvar)
@@ -193,15 +203,17 @@ class RevPiCheckClient(tkinter.Frame):
txt["command"] = \ txt["command"] = \
lambda device=device, io=io: self.__chval(device, io) lambda device=device, io=io: self.__chval(device, io)
txt["state"] = "disabled" if iotype == "inp" or \ txt["state"] = "disabled" if iotype == "inp" or \
self.maxint(io[1]) == 0 else "normal" self.maxint(io) == 0 else "normal"
txt["width"] = 5 width = len(str(self.maxint(io))) + 1
txt["width"] = 7 if width > 7 else width
txt["textvariable"] = var txt["textvariable"] = var
txt.grid(column=1, row=rowcount) txt.grid(column=0, row=rowcount)
# Steuerelementvariable in IO übernehmen (mutabel) # Steuerelementvariable in IO übernehmen (mutabel)
io.append(var) io.insert(5, var)
rowcount += 1 rowcount += 1
s_frame.update()
def _createwidgets(self): def _createwidgets(self):
"""Erstellt den Fensterinhalt.""" """Erstellt den Fensterinhalt."""
@@ -213,12 +225,11 @@ class RevPiCheckClient(tkinter.Frame):
for dev in self.lst_devices: for dev in self.lst_devices:
win = tkinter.Toplevel(self) 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( win.protocol(
"WM_DELETE_WINDOW", "WM_DELETE_WINDOW",
lambda win=win: self.__hidewin(win) lambda win=win: self.__hidewin(win)
) )
win.resizable(False, True)
win.withdraw() win.withdraw()
self.dict_wins[dev] = win self.dict_wins[dev] = win
@@ -230,12 +241,13 @@ class RevPiCheckClient(tkinter.Frame):
for iotype in ["inp", "out"]: for iotype in ["inp", "out"]:
frame = tkinter.Frame(group) frame = tkinter.Frame(group)
frame.pack(side="left", fill="both", expand=True) frame.pack(side="left", fill="both", expand=True)
frame.update()
self._createiogroup(dev, frame, iotype) self._createiogroup(dev, frame, iotype)
# Button erstellen # Button erstellen
btn = tkinter.Button(devgrp) btn = tkinter.Button(devgrp)
btn["command"] = lambda win=win: self.__showwin(win) btn["command"] = lambda win=win: self.__showwin(win)
btn["text"] = "{} | {}".format(dev, self.dict_devices[dev]) btn["text"] = "{0} | {1}".format(dev, self.dict_devices[dev])
btn.pack(**cfxpxy53) btn.pack(**cfxpxy53)
# Steuerungsfunktionen # Steuerungsfunktionen
@@ -311,16 +323,28 @@ class RevPiCheckClient(tkinter.Frame):
try: try:
ba_values = bytearray(self.cli.ps_values().data) ba_values = bytearray(self.cli.ps_values().data)
self.err_workvalues = 0 self.err_workvalues = 0
except: except Exception:
if self.autorw.get(): if self.autorw.get():
self.err_workvalues += 1 self.err_workvalues += 1
else: else:
self.err_workvalues = self.max_errors self.err_workvalues = self.max_errors
if self.err_workvalues >= self.max_errors: if self.err_workvalues >= self.max_errors:
# Fenster zerstören bei zu vielen Fehlern
self.hideallwindows() self.hideallwindows()
if self.autorw.get():
self.autorw.set(False)
self.toggleauto()
self.dowrite.set(False)
self.pack_forget() self.pack_forget()
tkmsg.showerror(
_("Error"),
_("To many errors while reading IO data. "
"Can not show the Watch-Mode."),
parent=self.master
)
return None return None
# Multicall zum Schreiben vorbereiten # Multicall zum Schreiben vorbereiten
@@ -328,7 +352,7 @@ class RevPiCheckClient(tkinter.Frame):
xmlmc = MultiCall(self.cli) xmlmc = MultiCall(self.cli)
for dev in self.dict_devices: for dev in self.dict_devices:
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] # io = [name,blen,baddr,bmk,bitaddr,(tkinter_var),border,signed]
# IO Typ verarbeiten # IO Typ verarbeiten
for iotype in io_dicts: for iotype in io_dicts:
@@ -341,7 +365,9 @@ class RevPiCheckClient(tkinter.Frame):
# Bytes umwandeln # Bytes umwandeln
int_byte = int.from_bytes( int_byte = int.from_bytes(
ba_values[io[2]:io[2] + io[1]], byteorder="little" ba_values[io[2]:io[2] + io[1]],
byteorder="little" if len(io) < 7 else io[6],
signed=False if len(io) < 8 else io[7],
) )
if io[4] >= 0: if io[4] >= 0:
# Bit-IO # Bit-IO
@@ -367,11 +393,35 @@ class RevPiCheckClient(tkinter.Frame):
for win in self.dict_wins: for win in self.dict_wins:
self.dict_wins[win].withdraw() self.dict_wins[win].withdraw()
def maxint(self, bytelen): def maxint(self, io):
u"""Errechnet maximalen int() Wert für Bytes max 22. u"""Errechnet maximalen int() Wert für Bytes max 22.
@param bytelen Anzahl Bytes @param io IO-Liste, deren Wert berechnet werden soll
@return int() max oder 0 bei Überschreitung""" @return int() max oder 0 bei Überschreitung"""
return 0 if bytelen > 22 else 256 ** bytelen - 1 # io = [name,blen,baddr,bmk,bitaddr,(tkinter_var),border,signed]
bytelen = io[1]
if bytelen == 0:
return 0
signed = io[-1] if type(io[-1]) == bool else False
return 0 if bytelen > 22 else int.from_bytes(
(b'\x7f' if signed else b'\xff') + b'\xff' * (bytelen - 1),
byteorder="big"
)
def minint(self, io):
u"""Errechnet maximalen int() Wert für Bytes max 22.
@param io IO-Liste, deren Wert berechnet werden soll
@return int() max oder 0 bei Überschreitung"""
# io = [name,blen,baddr,bmk,bitaddr,(tkinter_var),border,signed]
bytelen = io[1]
if bytelen == 0:
return 0
signed = io[-1] if type(io[-1]) == bool else False
rc = 0 if bytelen > 22 or not signed else int.from_bytes(
b'\x80' + b'\x00' * (bytelen - 1),
byteorder="big",
signed=True
)
return rc
def readvalues(self): def readvalues(self):
u"""Ruft nur Input Werte von RevPi ab und aktualisiert Fenster.""" u"""Ruft nur Input Werte von RevPi ab und aktualisiert Fenster."""
@@ -390,7 +440,7 @@ class RevPiCheckClient(tkinter.Frame):
if not self.autorw.get(): if not self.autorw.get():
try: try:
self.chk_auto["state"] = "normal" self.chk_auto["state"] = "normal"
except: except Exception:
pass pass
return None return None
@@ -436,10 +486,11 @@ class RevPiCheckClient(tkinter.Frame):
# Fehlermeldungen erstellen # Fehlermeldungen erstellen
devicename = self.dict_devices[lst_result[0]] devicename = self.dict_devices[lst_result[0]]
str_errmsg += _( 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]) ).format(devicename, lst_result[1], lst_result[3])
if str_errmsg != "": if str_errmsg != "":
tkmsg.showerror(_("Error"), str_errmsg) tkmsg.showerror(_("Error"), str_errmsg, parent=self.master)
def writevalues(self): def writevalues(self):
u"""Schreibt geänderte Outputs auf den RevPi.""" 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,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Programminformationen anzeigen.""" u"""Programminformationen anzeigen."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter import tkinter
import tkinter.font as tkf import tkinter.font as tkf
import webbrowser import webbrowser
@@ -55,7 +54,7 @@ class RevPiInfo(tkinter.Frame):
lbl.pack(pady=5) lbl.pack(pady=5)
lbl = tkinter.Label(self) lbl = tkinter.Label(self)
lbl["font"] = fntmid lbl["font"] = fntmid
lbl["text"] = _("Version: {}").format(self.version) lbl["text"] = _("Version: {0}").format(self.version)
lbl.bind( lbl.bind(
"<ButtonPress-2>", "<ButtonPress-2>",
lambda event: self._createwidgets(extended=not extended) lambda event: self._createwidgets(extended=not extended)

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Alte Klassen laden hier, bevor sie entsorgt werden.""" u"""Alte Klassen laden hier, bevor sie entsorgt werden."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
from mytools import gettrans from mytools import gettrans
@@ -23,7 +22,7 @@ class RevPiOption(tkinter.Frame):
@return None""" @return None"""
try: try:
self.dc = xmlcli.get_config() self.dc = xmlcli.get_config()
except: except Exception:
self.dc = None self.dc = None
return None return None
@@ -46,17 +45,17 @@ class RevPiOption(tkinter.Frame):
u"""Prüft ob sich die Einstellungen geändert haben. u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde""" @return True, wenn min. eine Einstellung geändert wurde"""
return ( return (
self.var_start.get() != self.dc.get("autostart", "1") self.var_start.get() != self.dc.get("autostart", "1") or
or self.var_reload.get() != self.dc.get("autoreload", "1") self.var_reload.get() != self.dc.get("autoreload", "1") or
or self.var_zexit.get() != self.dc.get("zeroonexit", "0") self.var_zexit.get() != self.dc.get("zeroonexit", "0") or
or self.var_zerr.get() != self.dc.get("zeroonerror", "0") self.var_zerr.get() != self.dc.get("zeroonerror", "0") or
or self.var_startpy.get() != self.dc.get("plcprogram", "none.py") self.var_startpy.get() != self.dc.get("plcprogram", "none.py") or
or self.var_startargs.get() != self.dc.get("plcarguments", "") self.var_startargs.get() != self.dc.get("plcarguments", "") or
or self.var_pythonver.get() != self.dc.get("pythonversion", "3") self.var_pythonver.get() != self.dc.get("pythonversion", "3") or
or self.var_slave.get() != self.dc.get("plcslave", "0") self.var_slave.get() != self.dc.get("plcslave", "0") or
or self.var_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1) self.var_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1) or
or self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2) self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2) or
or self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3) self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3)
# or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123") # or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123")
) )

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Zeigt die Logfiles an.""" u"""Zeigt die Logfiles an."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter import tkinter
from mytools import gettrans from mytools import gettrans
@@ -106,7 +105,7 @@ class RevPiLogfile(tkinter.Frame):
self.applog, self.xmlcli.load_applog, self.mrkapp, full self.applog, self.xmlcli.load_applog, self.mrkapp, full
) )
self.errapp = 0 self.errapp = 0
except: except Exception:
self.errapp += 1 self.errapp += 1
# Timer neu starten # Timer neu starten
@@ -122,7 +121,7 @@ class RevPiLogfile(tkinter.Frame):
self.plclog, self.xmlcli.load_plclog, self.mrkplc, full self.plclog, self.xmlcli.load_plclog, self.mrkplc, full
) )
self.errplc = 0 self.errplc = 0
except: except Exception:
self.errplc += 1 self.errplc += 1
# Timer neu starten # Timer neu starten

View File

@@ -1,14 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Optionsfenster.""" u"""Optionsfenster."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
from aclmanager import AclManager from aclmanager import AclManager
from mqttmanager import MqttManager
from mytools import gettrans from mytools import gettrans
# Übersetzung laden # Übersetzung laden
@@ -24,7 +24,7 @@ class RevPiOption(tkinter.Frame):
@return None""" @return None"""
try: try:
self.dc = xmlcli.get_config() self.dc = xmlcli.get_config()
except: except Exception:
self.dc = None self.dc = None
return None return None
@@ -33,10 +33,34 @@ class RevPiOption(tkinter.Frame):
self.master.protocol("WM_DELETE_WINDOW", self._checkclose) self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both") self.pack(expand=True, fill="both")
self.frm_mqttmgr = None
self.frm_slaveacl = None
self.frm_xmlacl = None
# XML-RPC Server konfigurieren # XML-RPC Server konfigurieren
self.xmlcli = xmlcli self.xmlcli = xmlcli
self.xmlmodus = self.xmlcli.xmlmodus() 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.replace_ios_options = [
_("Do not use replace io file"),
_("Use static file from RevPiPyLoad"),
_("Use dynamic file from work directory"),
_("Give own path and filename"),
]
self.mrk_xmlmodask = False self.mrk_xmlmodask = False
self.dorestart = False self.dorestart = False
@@ -44,26 +68,59 @@ class RevPiOption(tkinter.Frame):
self._createwidgets() self._createwidgets()
self._loadappdata() self._loadappdata()
def __state_replace_ios(self, text):
u"""Konfiguriert Werte für replace_io.
@param text: Ausgewählter Eintrag in Liste"""
selected_id = self.replace_ios_options.index(text)
# Preset value
if selected_id == 0:
self.var_replace_ios.set("")
elif selected_id == 1:
self.var_replace_ios.set("/etc/revpipyload/replace_ios.conf")
else:
self.var_replace_ios.set("replace_ios.conf")
# Set state of input field
self.txt_replace_ios["state"] = "normal" \
if self.xmlmodus >= 4 and \
selected_id == 3 \
else "disabled"
def _changesdone(self): def _changesdone(self):
u"""Prüft ob sich die Einstellungen geändert haben. u"""Prüft ob sich die Einstellungen geändert haben.
@return True, wenn min. eine Einstellung geändert wurde""" @return True, wenn min. eine Einstellung geändert wurde"""
return ( return (
self.var_start.get() != self.dc.get("autostart", 1) self.var_start.get() != self.dc.get("autostart", 1) or
or self.var_reload.get() != self.dc.get("autoreload", 1) self.var_reload.get() != self.dc.get("autoreload", 1) or
or self.var_reload_delay.get() != self.var_reload_delay.get() !=
str(self.dc.get("autoreloaddelay", 5)) str(self.dc.get("autoreloaddelay", 5)) or
or self.var_zexit.get() != self.dc.get("zeroonexit", 0) self.var_zexit.get() != self.dc.get("zeroonexit", 0) or
or self.var_zerr.get() != self.dc.get("zeroonerror", 0) self.var_zerr.get() != self.dc.get("zeroonerror", 0) or
self.var_replace_ios.get() != self.dc.get("replace_ios", "") or
# TODO: rtlevel (0) # TODO: rtlevel (0)
or self.var_startpy.get() != self.dc.get("plcprogram", "none.py") self.var_startpy.get() != self.dc.get("plcprogram", "none.py") or
or self.var_startargs.get() != self.dc.get("plcarguments", "") self.var_startargs.get() != self.dc.get("plcarguments", "") or
or self.var_pythonver.get() != self.dc.get("pythonversion", 3) self.var_pythonver.get() != self.dc.get("pythonversion", 3) or
or self.var_slave.get() != self.dc.get("plcslave", 0) self.var_plcworkdir_set_uid.get() != \
or self.var_slaveacl.get() != self.dc.get("plcslaveacl", "") self.dc.get("plcworkdir_set_uid") or
or self.var_xmlon.get() != self.dc.get("xmlrpc", 0) self.var_slave.get() != self.dc.get("plcslave", 0) or
or self.var_xmlacl.get() != self.dc.get("xmlrpcacl", "") 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): def _checkclose(self, event=None):
u"""Prüft ob Fenster beendet werden soll. u"""Prüft ob Fenster beendet werden soll.
@param event tkinter-Event""" @param event tkinter-Event"""
@@ -105,6 +162,9 @@ class RevPiOption(tkinter.Frame):
# Gruppe Start/Stop # Gruppe Start/Stop
stst = tkinter.LabelFrame(self) stst = tkinter.LabelFrame(self)
stst.columnconfigure(0, weight=1)
stst.columnconfigure(1, weight=1)
stst.columnconfigure(2, weight=1)
stst["text"] = _("Start / Stop behavior") stst["text"] = _("Start / Stop behavior")
stst.grid(columnspan=2, pady=2, sticky="we") stst.grid(columnspan=2, pady=2, sticky="we")
@@ -113,112 +173,148 @@ class RevPiOption(tkinter.Frame):
self.var_reload_delay = tkinter.StringVar(stst) self.var_reload_delay = tkinter.StringVar(stst)
self.var_zexit = tkinter.BooleanVar(stst) self.var_zexit = tkinter.BooleanVar(stst)
self.var_zerr = tkinter.BooleanVar(stst) self.var_zerr = tkinter.BooleanVar(stst)
self.var_replace_ios = tkinter.StringVar(stst)
self.var_replace_ios_options = tkinter.StringVar(stst)
# Row 0
ckb_start = tkinter.Checkbutton(stst) ckb_start = tkinter.Checkbutton(stst)
ckb_start["text"] = _("Start program automatically") ckb_start["text"] = _("Start program automatically")
ckb_start["state"] = xmlstate ckb_start["state"] = xmlstate
ckb_start["variable"] = self.var_start ckb_start["variable"] = self.var_start
ckb_start.grid(columnspan=2, **cpadw) ckb_start.grid(columnspan=3, **cpadw)
# Row 1
ckb_reload = tkinter.Checkbutton(stst) ckb_reload = tkinter.Checkbutton(stst)
ckb_reload["text"] = _("Restart program after exit") ckb_reload["text"] = _("Restart program after exit")
ckb_reload["state"] = xmlstate ckb_reload["state"] = xmlstate
ckb_reload["variable"] = self.var_reload ckb_reload["variable"] = self.var_reload
ckb_reload.grid(columnspan=2, **cpadw) ckb_reload.grid(columnspan=3, **cpadw)
# Row 2
lbl = tkinter.Label(stst) lbl = tkinter.Label(stst)
lbl["text"] = _("Restart after n seconds of delay") lbl["text"] = _("Restart after n seconds of delay")
lbl.grid(**cpadw) lbl.grid(columnspan=2, **cpadw)
sbx = tkinter.Spinbox(stst) sbx = tkinter.Spinbox(stst)
sbx["to"] = 60 sbx["to"] = 60
sbx["from_"] = 5 sbx["from_"] = 5
sbx["textvariable"] = self.var_reload_delay sbx["textvariable"] = self.var_reload_delay
sbx["width"] = 4 sbx["width"] = 4
sbx.grid(column=1, row=2, **cpade) sbx.grid(column=2, row=2, **cpade)
# Row 3
lbl = tkinter.Label(stst) lbl = tkinter.Label(stst)
lbl["text"] = _("Set process image to NULL if program terminates...") lbl["text"] = _("Set process image to NULL if program terminates...")
lbl.grid(columnspan=2, **cpadw) lbl.grid(columnspan=3, **cpadw)
# Row 4
ckb_zexit = tkinter.Checkbutton(stst, justify="left") ckb_zexit = tkinter.Checkbutton(stst, justify="left")
ckb_zexit["state"] = xmlstate ckb_zexit["state"] = xmlstate
ckb_zexit["text"] = _("... successfully") ckb_zexit["text"] = _("... successfully")
ckb_zexit["variable"] = self.var_zexit ckb_zexit["variable"] = self.var_zexit
ckb_zexit.grid(**cpadw) ckb_zexit.grid(column=1, **cpadw)
# Row 5
ckb_zerr = tkinter.Checkbutton(stst, justify="left") ckb_zerr = tkinter.Checkbutton(stst, justify="left")
ckb_zerr["state"] = xmlstate ckb_zerr["state"] = xmlstate
ckb_zerr["text"] = _("... with errors") ckb_zerr["text"] = _("... with errors")
ckb_zerr["variable"] = self.var_zerr ckb_zerr["variable"] = self.var_zerr
ckb_zerr.grid(**cpadw) ckb_zerr.grid(column=1, **cpadw)
# Row 6
lbl = tkinter.Label(stst)
lbl["text"] = _("Replace IO file:")
lbl.grid(row=6, **cpadw)
opt = tkinter.OptionMenu(
stst, self.var_replace_ios_options, *self.replace_ios_options,
command=self.__state_replace_ios
)
opt["state"] = xmlstate
opt["width"] = 30
opt.grid(row=6, column=1, columnspan=2, **cpadwe)
# Row 7
self.txt_replace_ios = tkinter.Entry(stst)
self.txt_replace_ios["state"] = xmlstate
self.txt_replace_ios["textvariable"] = self.var_replace_ios
self.txt_replace_ios.grid(column=1, columnspan=2, **cpadwe)
# Gruppe Programm # Gruppe Programm
prog = tkinter.LabelFrame(self) prog = tkinter.LabelFrame(self)
prog.columnconfigure(0, weight=1) prog.columnconfigure(0, weight=1)
prog.columnconfigure(1, weight=1) prog.columnconfigure(1, weight=1)
prog.columnconfigure(2, weight=1)
prog["text"] = _("PLC program") prog["text"] = _("PLC program")
prog.grid(columnspan=2, pady=2, sticky="we") prog.grid(columnspan=2, pady=2, sticky="we")
self.var_pythonver = tkinter.IntVar(prog) self.var_pythonver = tkinter.IntVar(prog)
self.var_startpy = tkinter.StringVar(prog) self.var_startpy = tkinter.StringVar(prog)
self.var_startargs = tkinter.StringVar(prog) self.var_startargs = tkinter.StringVar(prog)
self.var_slaveacl = tkinter.StringVar(prog) self.var_plcworkdir_set_uid = tkinter.BooleanVar(prog)
self.var_pythonver.set(3) self.var_pythonver.set(3)
# Row 0
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = _("Python version") + ":" lbl["text"] = _("Python version") + ":"
lbl.grid(columnspan=2, row=0, **cpadw) lbl.grid(row=0, **cpadw)
rbn = tkinter.Radiobutton(prog) rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate rbn["state"] = xmlstate
rbn["text"] = "Python2" rbn["text"] = "Python2"
rbn["value"] = 2 rbn["value"] = 2
rbn["variable"] = self.var_pythonver rbn["variable"] = self.var_pythonver
rbn.grid(column=0, row=1, **cpade) rbn.grid(row=0, column=1, **cpade)
rbn = tkinter.Radiobutton(prog) rbn = tkinter.Radiobutton(prog)
rbn["state"] = xmlstate rbn["state"] = xmlstate
rbn["text"] = "Python3" rbn["text"] = "Python3"
rbn["value"] = 3 rbn["value"] = 3
rbn["variable"] = self.var_pythonver rbn["variable"] = self.var_pythonver
rbn.grid(column=1, row=1, **cpadw) rbn.grid(row=0, column=2, **cpadw)
# Row 2 # Row 1
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = _("Python PLC program name") lbl["text"] = _("Python PLC program name")
lbl.grid(columnspan=2, **cpadw) lbl.grid(columnspan=3, **cpadw)
# Row 3 # Row 2
lst = self.xmlcli.get_filelist() lst = self.xmlcli.get_filelist()
lst.sort()
if ".placeholder" in lst:
lst.remove(".placeholder")
if len(lst) == 0: if len(lst) == 0:
lst.append("none") lst.append("none")
opt_startpy = tkinter.OptionMenu( opt_startpy = tkinter.OptionMenu(
prog, self.var_startpy, *lst prog, self.var_startpy, *lst
) )
opt_startpy["state"] = xmlstate opt_startpy["state"] = xmlstate
opt_startpy.grid(columnspan=2, **cpadwe) opt_startpy.grid(columnspan=3, **cpadwe)
# Row 4 # Row 3
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = _("Program arguments") lbl["text"] = _("Program arguments:")
lbl.grid(columnspan=2, **cpadw) lbl.grid(**cpadw)
# Row 5
txt = tkinter.Entry(prog) txt = tkinter.Entry(prog)
txt["textvariable"] = self.var_startargs txt["textvariable"] = self.var_startargs
txt.grid(columnspan=2, **cpadw) txt.grid(row=3, column=1, columnspan=2, **cpadwe)
# Row 4
ckb = tkinter.Checkbutton(prog)
ckb["text"] = _("Set write access to workdirectory")
ckb["state"] = xmlstate
ckb["variable"] = self.var_plcworkdir_set_uid
ckb.grid(columnspan=2, **cpadw)
# Gruppe Services # Gruppe Services
services = tkinter.LabelFrame(self) services = tkinter.LabelFrame(self)
services["text"] = _("RevPiPyLoad server services") services["text"] = _("RevPiPyLoad server services")
services.grid(columnspan=2, pady=2, sticky="we") services.grid(columnspan=2, pady=2, sticky="we")
self.var_slave = tkinter.BooleanVar(services)
self.var_xmlon = tkinter.BooleanVar(services)
self.var_xmlacl = tkinter.StringVar(services)
# RevPiSlave Service # RevPiSlave Service
self.var_slave = tkinter.BooleanVar(services)
self.var_slaveacl = tkinter.StringVar(services)
row = 0 row = 0
ckb_slave = tkinter.Checkbutton(services, justify="left") ckb_slave = tkinter.Checkbutton(services, justify="left")
ckb_slave["state"] = xmlstate ckb_slave["state"] = xmlstate
@@ -229,7 +325,7 @@ class RevPiOption(tkinter.Frame):
btn_slaveacl = tkinter.Button(services, justify="center") btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_slaveacl btn_slaveacl["command"] = self.btn_slaveacl
btn_slaveacl["text"] = _("Edit ACL") btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpade) btn_slaveacl.grid(column=1, row=row, **cpadwe)
row = 1 row = 1
lbl = tkinter.Label(services) lbl = tkinter.Label(services)
@@ -242,8 +338,39 @@ class RevPiOption(tkinter.Frame):
lbl["text"] = _("running") if status else _("stopped") lbl["text"] = _("running") if status else _("stopped")
lbl.grid(column=1, row=row, **cpadwe) lbl.grid(column=1, row=row, **cpadwe)
# XML-RPC Service # MQTT Service
self.var_mqtton = tkinter.BooleanVar(services)
try:
status = self.xmlcli.mqttrunning()
except Exception:
pass
else:
row = 2 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 = tkinter.Checkbutton(services)
ckb_xmlon["command"] = self.askxmlon ckb_xmlon["command"] = self.askxmlon
ckb_xmlon["state"] = xmlstate ckb_xmlon["state"] = xmlstate
@@ -254,7 +381,7 @@ class RevPiOption(tkinter.Frame):
btn_slaveacl = tkinter.Button(services, justify="center") btn_slaveacl = tkinter.Button(services, justify="center")
btn_slaveacl["command"] = self.btn_xmlacl btn_slaveacl["command"] = self.btn_xmlacl
btn_slaveacl["text"] = _("Edit ACL") btn_slaveacl["text"] = _("Edit ACL")
btn_slaveacl.grid(column=1, row=row, **cpade) btn_slaveacl.grid(column=1, row=row, **cpadwe)
# Buttons am Ende # Buttons am Ende
btn_save = tkinter.Button(self) btn_save = tkinter.Button(self)
@@ -279,11 +406,30 @@ class RevPiOption(tkinter.Frame):
self.var_reload_delay.set(self.dc.get("autoreloaddelay", 5)) self.var_reload_delay.set(self.dc.get("autoreloaddelay", 5))
self.var_zexit.set(self.dc.get("zeroonexit", 0)) self.var_zexit.set(self.dc.get("zeroonexit", 0))
self.var_zerr.set(self.dc.get("zeroonerror", 0)) self.var_zerr.set(self.dc.get("zeroonerror", 0))
replace_ios = self.dc.get("replace_ios", "")
self.var_replace_ios.set(replace_ios)
if replace_ios == "":
self.var_replace_ios_options.set(self.replace_ios_options[0])
elif replace_ios == "/etc/revpipyload/replace_ios.conf":
self.var_replace_ios_options.set(self.replace_ios_options[1])
elif replace_ios == "replace_ios.conf":
self.var_replace_ios_options.set(self.replace_ios_options[2])
else:
self.var_replace_ios_options.set(self.replace_ios_options[3])
self.__state_replace_ios(self.var_replace_ios_options.get())
# TODO: rtlevel (0) # TODO: rtlevel (0)
self.var_startpy.set(self.dc.get("plcprogram", "none.py")) self.var_startpy.set(self.dc.get("plcprogram", "none.py"))
self.var_startargs.set(self.dc.get("plcarguments", "")) self.var_startargs.set(self.dc.get("plcarguments", ""))
self.var_pythonver.set(self.dc.get("pythonversion", 3)) self.var_pythonver.set(self.dc.get("pythonversion", 3))
self.var_plcworkdir_set_uid.set(
self.dc.get("plcworkdir_set_uid", False))
# 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_slave.set(self.dc.get("plcslave", 0)) self.var_slave.set(self.dc.get("plcslave", 0))
self.var_slaveacl.set(self.dc.get("plcslaveacl", "")) self.var_slaveacl.set(self.dc.get("plcslaveacl", ""))
@@ -323,13 +469,41 @@ class RevPiOption(tkinter.Frame):
self.dc["plcprogram"] = self.var_startpy.get() self.dc["plcprogram"] = self.var_startpy.get()
self.dc["plcarguments"] = self.var_startargs.get() self.dc["plcarguments"] = self.var_startargs.get()
self.dc["pythonversion"] = self.var_pythonver.get() self.dc["pythonversion"] = self.var_pythonver.get()
self.dc["plcworkdir_set_uid"] = \
int(self.var_plcworkdir_set_uid.get())
# TODO: rtlevel (0) # TODO: rtlevel (0)
self.dc["zeroonerror"] = int(self.var_zerr.get()) self.dc["zeroonerror"] = int(self.var_zerr.get())
self.dc["zeroonexit"] = int(self.var_zexit.get()) self.dc["zeroonexit"] = int(self.var_zexit.get())
self.dc["replace_ios"] = self.var_replace_ios.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["plcslave"] = int(self.var_slave.get())
self.dc["plcslaveacl"] = self.var_slaveacl.get() self.dc["plcslaveacl"] = self.var_slaveacl.get()
# XML Settings
self.dc["xmlrpc"] = int(self.var_xmlon.get()) self.dc["xmlrpc"] = int(self.var_xmlon.get())
self.dc["xmlrpcacl"] = self.var_xmlacl.get() self.dc["xmlrpcacl"] = self.var_xmlacl.get()
@@ -362,34 +536,46 @@ class RevPiOption(tkinter.Frame):
if not self.mrk_xmlmodask: if not self.mrk_xmlmodask:
self.var_xmlon.set(True) self.var_xmlon.set(True)
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 btn_slaveacl(self): def btn_slaveacl(self):
u"""Öffnet Fenster für ACL-Verwaltung.""" u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
win.focus_set() win.focus_set()
win.grab_set() win.grab_set()
slaveacl = AclManager( self.frm_slaveacl = AclManager(
win, 0, 1, win, 0, 1,
self.var_slaveacl.get(), self.var_slaveacl.get(),
readonly=self.xmlmodus < 4 readonly=self.xmlmodus < 4
) )
slaveacl.acltext = { self.frm_slaveacl.acltext = {
0: _("read only"), 0: _("read only"),
1: _("read and write") 1: _("read and write")
} }
self.wait_window(win) self.wait_window(win)
self.var_slaveacl.set(slaveacl.acl) self.var_slaveacl.set(self.frm_slaveacl.acl)
def btn_xmlacl(self): def btn_xmlacl(self):
u"""Öffnet Fenster für ACL-Verwaltung.""" u"""Öffnet Fenster für ACL-Verwaltung."""
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
win.focus_set() win.focus_set()
win.grab_set() win.grab_set()
slaveacl = AclManager( self.frm_xmlacl = AclManager(
win, 0, 4, win, 0, 4,
self.var_xmlacl.get(), self.var_xmlacl.get(),
readonly=self.xmlmodus < 4 readonly=self.xmlmodus < 4
) )
slaveacl.acltext = { self.frm_xmlacl.acltext = {
0: _("Start/Stop PLC program and read logs"), 0: _("Start/Stop PLC program and read logs"),
1: _("+ read IOs in watch modus"), 1: _("+ read IOs in watch modus"),
2: _("+ read properties and download PLC program"), 2: _("+ read properties and download PLC program"),
@@ -397,4 +583,15 @@ class RevPiOption(tkinter.Frame):
4: _("+ set properties") 4: _("+ set properties")
} }
self.wait_window(win) self.wait_window(win)
self.var_xmlacl.set(slaveacl.acl) 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,17 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""Fenster um RevPi-Verbindungen einzurichten.""" u"""Fenster um RevPi-Verbindungen einzurichten."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import os.path import os.path
import pickle import pickle
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
from mytools import gettrans from mytools import gettrans
from mytools import savefile_connections as savefile 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 _loaddefaults as programloaddefaults
from revpiprogram import _savedefaults as programsavedefaults from revpiprogram import _savedefaults as programsavedefaults
from os import makedirs from os import makedirs
@@ -150,15 +151,20 @@ class RevPiPlcList(tkinter.Frame):
with open(savefile, "wb") as fh: with open(savefile, "wb") as fh:
pickle.dump(self._connections, fh) pickle.dump(self._connections, fh)
self.changes = False self.changes = False
except: except Exception:
return False return False
# Andere Einstellungen aufräumen # Andere Einstellungen aufräumen
dict = programloaddefaults() dict_o = developloaddefaults()
for revpi in tuple(dict.keys()): for revpi in tuple(dict_o.keys()):
if revpi not in self._connections: if revpi not in self._connections:
del dict[revpi] del dict_o[revpi]
programsavedefaults(None, dict) 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 return True
@@ -195,7 +201,7 @@ class RevPiPlcList(tkinter.Frame):
item = self.list_conn.get(item_index[0]) item = self.list_conn.get(item_index[0])
ask = tkmsg.askyesno( ask = tkmsg.askyesno(
_("Question"), _("Question"),
_("Do you really want to delete the selected connection '{}'?" _("Do you really want to delete the selected connection '{0}'?"
"").format(item), "").format(item),
parent=self.master parent=self.master
) )
@@ -243,9 +249,9 @@ class RevPiPlcList(tkinter.Frame):
def evt_keypress(self, evt=None): def evt_keypress(self, evt=None):
u"""Passt bei Tastendruck den Status der Buttons an.""" u"""Passt bei Tastendruck den Status der Buttons an."""
okvalue = "normal" if ( okvalue = "normal" if (
self.var_address.get() != "" self.var_address.get() != "" and
and self.var_name.get() != "" self.var_name.get() != "" and
and self.var_port.get() != "" self.var_port.get() != ""
) else "disabled" ) else "disabled"
self.btn_add["state"] = okvalue self.btn_add["state"] = okvalue

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
u"""PLC Programm und Konfig hoch und runterladen.""" u"""PLC Programm und Konfig hoch und runterladen."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "GPLv3"
import gzip import gzip
import os import os
import pickle import pickle
@@ -15,8 +14,8 @@ import tkinter.filedialog as tkfd
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
import zipfile import zipfile
from mytools import gettrans from mytools import gettrans
from mytools import homedir
from mytools import savefile_programpath as savefile from mytools import savefile_programpath as savefile
from os import makedirs
from shutil import rmtree from shutil import rmtree
from tempfile import mkstemp, mkdtemp from tempfile import mkstemp, mkdtemp
from xmlrpc.client import Binary from xmlrpc.client import Binary
@@ -48,7 +47,7 @@ def _savedefaults(revpiname, settings):
""" """
try: try:
makedirs(os.path.dirname(savefile), exist_ok=True) os.makedirs(os.path.dirname(savefile), exist_ok=True)
if revpiname is None: if revpiname is None:
dict_all = settings dict_all = settings
else: else:
@@ -56,7 +55,7 @@ def _savedefaults(revpiname, settings):
dict_all[revpiname] = settings dict_all[revpiname] = settings
with open(savefile, "wb") as fh: with open(savefile, "wb") as fh:
pickle.dump(dict_all, fh) pickle.dump(dict_all, fh)
except: except Exception:
return False return False
return True return True
@@ -82,7 +81,7 @@ class RevPiProgram(tkinter.Frame):
self.xmlstate = "normal" if xmlmode >= 3 else "disabled" self.xmlstate = "normal" if xmlmode >= 3 else "disabled"
# Letzte Einstellungen übernehmen # Letzte Einstellungen übernehmen
self.opt = _loaddefaults() self.opt = _loaddefaults(revpi)
# Fenster bauen # Fenster bauen
self._createwidgets() self._createwidgets()
@@ -325,7 +324,7 @@ class RevPiProgram(tkinter.Frame):
if fh is not None: if fh is not None:
try: try:
fh.write(self.xmlcli.get_pictoryrsc().data) fh.write(self.xmlcli.get_pictoryrsc().data)
except: except Exception:
tkmsg.showerror( tkmsg.showerror(
_("Error"), _("Error"),
_("Could not load and save file!"), _("Could not load and save file!"),
@@ -339,7 +338,7 @@ class RevPiProgram(tkinter.Frame):
) )
# Einstellungen speichern # Einstellungen speichern
self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name) self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name)
self._savedefaults(self.revpi, self.opt) _savedefaults(self.revpi, self.opt)
finally: finally:
fh.close() fh.close()
@@ -356,7 +355,7 @@ class RevPiProgram(tkinter.Frame):
if fh is not None: if fh is not None:
try: try:
fh.write(self.xmlcli.get_procimg().data) fh.write(self.xmlcli.get_procimg().data)
except: except Exception:
tkmsg.showerror( tkmsg.showerror(
_("Error"), _("Error"),
_("Could not load and save file!"), _("Could not load and save file!"),
@@ -370,7 +369,7 @@ class RevPiProgram(tkinter.Frame):
) )
# Einstellungen speichern # Einstellungen speichern
self.opt["getprocimg_dir"] = os.path.dirname(fh.name) self.opt["getprocimg_dir"] = os.path.dirname(fh.name)
self._savedefaults(self.revpi, self.opt) _savedefaults(self.revpi, self.opt)
finally: finally:
fh.close() fh.close()
@@ -418,7 +417,7 @@ class RevPiProgram(tkinter.Frame):
# Einstellungen speichern # Einstellungen speichern
self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name)
self._savedefaults(self.revpi, self.opt) _savedefaults(self.revpi, self.opt)
elif ec == -1: elif ec == -1:
tkmsg.showerror( tkmsg.showerror(
_("Error"), _("Error"),
@@ -561,7 +560,7 @@ class RevPiProgram(tkinter.Frame):
self.opt["typedown"] = self.var_typedown.get() self.opt["typedown"] = self.var_typedown.get()
self.opt["picdown"] = self.var_picdown.get() self.opt["picdown"] = self.var_picdown.get()
except: except Exception:
raise raise
tkmsg.showerror( tkmsg.showerror(
_("Error"), _("Error"),
@@ -576,7 +575,7 @@ class RevPiProgram(tkinter.Frame):
) )
# Einstellungen speichern # Einstellungen speichern
self._savedefaults(self.revpi, self.opt) _savedefaults(self.revpi, self.opt)
finally: finally:
fh.close() fh.close()
@@ -588,6 +587,7 @@ class RevPiProgram(tkinter.Frame):
dirtmp = None dirtmp = None
filelist = [] filelist = []
fileselect = None fileselect = None
foldername = ""
rscfile = None rscfile = None
if tup == 0: if tup == 0:
@@ -595,7 +595,7 @@ class RevPiProgram(tkinter.Frame):
fileselect = tkfd.askopenfilenames( fileselect = tkfd.askopenfilenames(
parent=self.master, parent=self.master,
title="Upload Python program...", title="Upload Python program...",
initialdir=self.opt.get("plcupload_dir", ""), initialdir=self.opt.get("plcupload_dir", homedir),
filetypes=(("Python", "*.py"), (_("All files"), "*.*")) filetypes=(("Python", "*.py"), (_("All files"), "*.*"))
) )
if type(fileselect) == tuple and len(fileselect) > 0: if type(fileselect) == tuple and len(fileselect) > 0:
@@ -608,8 +608,12 @@ class RevPiProgram(tkinter.Frame):
parent=self.master, parent=self.master,
title=_("Folder to upload"), title=_("Folder to upload"),
mustexist=True, 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 != "": if type(dirselect) == str and dirselect != "":
filelist = self.create_filelist(dirselect) filelist = self.create_filelist(dirselect)
@@ -706,7 +710,11 @@ class RevPiProgram(tkinter.Frame):
if dirselect == "": if dirselect == "":
sendname = os.path.basename(fname) sendname = os.path.basename(fname)
else: 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 # Prüfen ob Dateiname bereits als Startprogramm angegeben ist
if sendname == opt_program: if sendname == opt_program:
@@ -716,7 +724,7 @@ class RevPiProgram(tkinter.Frame):
try: try:
ustatus = self.xmlcli.plcupload( ustatus = self.xmlcli.plcupload(
Binary(gzip.compress(fh.read())), sendname) Binary(gzip.compress(fh.read())), sendname)
except: except Exception:
ec = -2 ec = -2
break break
@@ -752,7 +760,7 @@ class RevPiProgram(tkinter.Frame):
self.opt["typeup"] = self.var_typeup.get() self.opt["typeup"] = self.var_typeup.get()
self.opt["picup"] = self.var_picup.get() self.opt["picup"] = self.var_picup.get()
self._savedefaults(self.revpi, self.opt) _savedefaults(self.revpi, self.opt)
elif ec == -1: elif ec == -1:
tkmsg.showerror( tkmsg.showerror(

View File

@@ -1,14 +1,14 @@
#!/usr/bin/python3 #!/usr/bin/python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# u"""RevPiPyControl main program."""
# RevPiPyControl
# Version: see global var pycontrolverion __author__ = "Sven Sager"
# __copyright__ = "Copyright (C) 2018 Sven Sager"
# Webpage: https://revpimodio.org/revpipyplc/ __license__ = "GPLv3"
# (c) Sven Sager, License: LGPLv3 __version__ = "0.8.0"
#
u"""Hauptprogramm."""
import revpicheckclient import revpicheckclient
import revpidevelop
import revpiinfo import revpiinfo
import revpilogfile import revpilogfile
import revpioption import revpioption
@@ -25,8 +25,6 @@ from xmlrpc.client import ServerProxy
# Übersetzung laden # Übersetzung laden
_ = gettrans() _ = gettrans()
pycontrolversion = "0.6.1"
class RevPiPyControl(tkinter.Frame): class RevPiPyControl(tkinter.Frame):
@@ -47,8 +45,9 @@ class RevPiPyControl(tkinter.Frame):
self.xmlfuncs = [] self.xmlfuncs = []
self.xmlmode = 0 self.xmlmode = 0
# Debugger vorbereiten # Frames vorbereiten
self.debugframe = None self.debugframe = None
self.developframe = None
# Globale Fenster # Globale Fenster
self.tkcheckclient = None self.tkcheckclient = None
@@ -75,10 +74,15 @@ class RevPiPyControl(tkinter.Frame):
u"""Schließt alle Fenster.""" u"""Schließt alle Fenster."""
if self.tkcheckclient is not None: if self.tkcheckclient is not None:
self.tkcheckclient.destroy() self.tkcheckclient.destroy()
if self.developframe is not None:
self.developframe._checkclose()
self.developframe.destroy()
self.developframe = None
if self.tklogs is not None: if self.tklogs is not None:
self.tklogs.master.destroy() self.tklogs.master.destroy()
if self.tkoptions is not None: if self.tkoptions is not None:
self.tkoptions.destroy() self.tkoptions.destroy()
self.tkoptions.master.destroy()
if self.tkprogram is not None: if self.tkprogram is not None:
self.tkprogram.destroy() self.tkprogram.destroy()
if self.debugframe is not None: if self.debugframe is not None:
@@ -86,7 +90,7 @@ class RevPiPyControl(tkinter.Frame):
self.debugframe = None self.debugframe = None
try: try:
self.cli.psstop() self.cli.psstop()
except: except Exception:
pass pass
def _closeapp(self, event=None): def _closeapp(self, event=None):
@@ -125,38 +129,43 @@ class RevPiPyControl(tkinter.Frame):
menu1.add_command(label=_("Info..."), command=self.infowindow) menu1.add_command(label=_("Info..."), command=self.infowindow)
self.mbar.add_cascade(label=_("Help"), menu=menu1) self.mbar.add_cascade(label=_("Help"), menu=menu1)
self.var_conn = tkinter.StringVar(self) self.main_frame = tkinter.Frame(self)
self.txt_connect = tkinter.Entry(self, state="readonly", width=40) 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["textvariable"] = self.var_conn
self.txt_connect.pack(fill="x") 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["text"] = _("PLC start")
self.btn_plcstart["command"] = self.plcstart self.btn_plcstart["command"] = self.plcstart
self.btn_plcstart.pack(fill="x") 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["text"] = _("PLC stop")
self.btn_plcstop["command"] = self.plcstop self.btn_plcstop["command"] = self.plcstop
self.btn_plcstop.pack(fill="x") 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["text"] = _("PLC restart")
self.btn_plcrestart["command"] = self.plcrestart self.btn_plcrestart["command"] = self.plcrestart
self.btn_plcrestart.pack(fill="x") 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["text"] = _("PLC logs")
self.btn_plclogs["command"] = self.plclogs self.btn_plclogs["command"] = self.plclogs
self.btn_plclogs.pack(fill="x") self.btn_plclogs.pack(fill="x")
self.var_status = tkinter.StringVar(self) self.var_status = tkinter.StringVar(self.main_frame)
self.txt_status = tkinter.Entry(self) self.txt_status = tkinter.Entry(self.main_frame)
self.txt_status["state"] = "readonly" self.txt_status["state"] = "readonly"
self.txt_status["textvariable"] = self.var_status self.txt_status["textvariable"] = self.var_status
self.txt_status.pack(fill="x") 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["text"] = _("PLC watch mode")
self.btn_debug["command"] = self.plcdebug self.btn_debug["command"] = self.plcdebug
self.btn_debug.pack(fill="x") self.btn_debug.pack(fill="x")
@@ -179,6 +188,8 @@ class RevPiPyControl(tkinter.Frame):
label=_("PLC options..."), command=self.plcoptions) label=_("PLC options..."), command=self.plcoptions)
self.mplc.add_command( self.mplc.add_command(
label=_("PLC program..."), command=self.plcprogram) label=_("PLC program..."), command=self.plcprogram)
self.mplc.add_command(
label=_("PLC developer..."), command=self.plcdevelop)
self.mplc.add_separator() self.mplc.add_separator()
self.mplc.add_command( self.mplc.add_command(
@@ -194,12 +205,12 @@ class RevPiPyControl(tkinter.Frame):
@param text Verbindungsname @param text Verbindungsname
@param reconnect Socket Timeout nicht heruntersetzen""" @param reconnect Socket Timeout nicht heruntersetzen"""
if reconnect: if reconnect:
socket.setdefaulttimeout(10) socket.setdefaulttimeout(6)
else: else:
socket.setdefaulttimeout(2) socket.setdefaulttimeout(2)
sp = ServerProxy( sp = ServerProxy(
"http://{}:{}".format( "http://{0}:{1}".format(
self.dict_conn[text][0], int(self.dict_conn[text][1]) self.dict_conn[text][0], int(self.dict_conn[text][1])
) )
) )
@@ -208,18 +219,18 @@ class RevPiPyControl(tkinter.Frame):
self.xmlfuncs = sp.system.listMethods() self.xmlfuncs = sp.system.listMethods()
self.xmlmode = sp.xmlmodus() self.xmlmode = sp.xmlmodus()
self.revpipyversion = list(map(int, sp.version().split("."))) self.revpipyversion = list(map(int, sp.version().split(".")))
except: except Exception:
self.servererror() self.servererror()
else: else:
self._closeall() self._closeall()
socket.setdefaulttimeout(10) socket.setdefaulttimeout(6)
self.cli = ServerProxy( self.cli = ServerProxy(
"http://{}:{}".format( "http://{0}:{1}".format(
self.dict_conn[text][0], int(self.dict_conn[text][1]) self.dict_conn[text][0], int(self.dict_conn[text][1])
) )
) )
self.revpiname = text 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]) text, self.dict_conn[text][0], int(self.dict_conn[text][1])
)) ))
self.mbar.entryconfig("PLC", state="normal") self.mbar.entryconfig("PLC", state="normal")
@@ -229,7 +240,7 @@ class RevPiPyControl(tkinter.Frame):
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
win.focus_set() win.focus_set()
win.grab_set() win.grab_set()
revpiinfo.RevPiInfo(win, self.cli, pycontrolversion) revpiinfo.RevPiInfo(win, self.cli, __version__)
self.wait_window(win) self.wait_window(win)
self.dict_conn = revpiplclist.get_connections() self.dict_conn = revpiplclist.get_connections()
self._fillconnbar() self._fillconnbar()
@@ -242,23 +253,22 @@ class RevPiPyControl(tkinter.Frame):
if "psstart" not in self.xmlfuncs: if "psstart" not in self.xmlfuncs:
tkmsg.showwarning( tkmsg.showwarning(
_("Warning"), _("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 " "of RevPiPyLoad on your RevPi! You need at least version "
"0.5.3! Maybe the python3-revpimodio2 module is not " "0.5.3! Maybe the python3-revpimodio2 module is not "
"installed on your RevPi at least version 2.0.0." "installed on your RevPi at least version 2.0.0."
"").format(self.cli.version()), "").format(self.cli.version()),
parent=self.master parent=self.master
) )
else: return
# Debugfenster laden
if self.debugframe is None \ # FIXME: Bei neuer piCtory Konfig schneller vernichten
or self.debugframe.err_workvalues >= \ if self.debugframe is None:
self.debugframe.max_errors:
try: try:
self.debugframe = revpicheckclient.RevPiCheckClient( self.debugframe = revpicheckclient.RevPiCheckClient(
self, self.cli, self.xmlmode self.main_frame, self.cli, self.xmlmode
) )
except: except Exception:
tkmsg.showwarning( tkmsg.showwarning(
_("Error"), _("Error"),
_("Can not load piCtory configuration. \n" _("Can not load piCtory configuration. \n"
@@ -269,6 +279,11 @@ class RevPiPyControl(tkinter.Frame):
self.btn_debug["state"] = "normal" self.btn_debug["state"] = "normal"
return None return None
# Fehler prüfen
if self.debugframe.err_workvalues >= self.debugframe.max_errors:
self.debugframe = None
return None
# Show/Hide wechseln # Show/Hide wechseln
if self.debugframe.winfo_viewable(): if self.debugframe.winfo_viewable():
self.debugframe.hideallwindows() self.debugframe.hideallwindows()
@@ -282,6 +297,29 @@ class RevPiPyControl(tkinter.Frame):
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): def plclist(self):
u"""Öffnet das Fenster für die Verbindungen.""" u"""Öffnet das Fenster für die Verbindungen."""
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
@@ -298,7 +336,7 @@ class RevPiPyControl(tkinter.Frame):
if "load_plclog" not in self.xmlfuncs: if "load_plclog" not in self.xmlfuncs:
tkmsg.showwarning( tkmsg.showwarning(
_("Warning"), _("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 " "of RevPiPyLoad on your RevPi! You need at least version "
"0.4.1.").format(self.cli.version()), "0.4.1.").format(self.cli.version()),
parent=self.master parent=self.master
@@ -404,7 +442,7 @@ class RevPiPyControl(tkinter.Frame):
else: else:
try: try:
plcec = self.cli.plcexitcode() plcec = self.cli.plcexitcode()
except: except Exception:
self.errcount += 1 self.errcount += 1
if self.errcount >= 5: if self.errcount >= 5:
self.var_status.set("SERVER ERROR") self.var_status.set("SERVER ERROR")

View File

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

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# IpAclManager
#
# (c) Sven Sager, License: LGPLv3
# Version 0.1.0
#
"""Verwaltet IP Adressen und deren ACLs.""" """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 os import access, R_OK, W_OK
from re import match as rematch from re import match as rematch
@@ -66,7 +65,7 @@ class IpAclManager():
return ACLs als <class 'str'>""" return ACLs als <class 'str'>"""
str_acl = "" str_acl = ""
for aclip in sorted(self.__dict_acl): for aclip in sorted(self.__dict_acl):
str_acl += "{},{} ".format(aclip, self.__dict_acl[aclip]) str_acl += "{0},{1} ".format(aclip, self.__dict_acl[aclip])
return str_acl.strip() return str_acl.strip()
def __get_filename(self): def __get_filename(self):
@@ -173,14 +172,14 @@ class IpAclManager():
if not access(filename, W_OK): if not access(filename, W_OK):
return False return False
header = "# {}Access Control List (acl)\n" \ header = "# {0}Access Control List (acl)\n" \
"# One entry per Line IPADRESS,LEVEL\n" \ "# One entry per Line IPADRESS,LEVEL\n" \
"#\n".format("" if aclname is None else aclname + " ") "#\n".format("" if aclname is None else aclname + " ")
with open(filename, "w") as fh: with open(filename, "w") as fh:
fh.write(header) fh.write(header)
for aclip in sorted(self.__dict_acl): for aclip in sorted(self.__dict_acl):
fh.write("{},{}\n".format(aclip, self.__dict_acl[aclip])) fh.write("{0},{1}\n".format(aclip, self.__dict_acl[aclip]))
return True return True

View File

@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# (c) Sven Sager, License: LGPLv3
#
"""Setupscript fuer RevPiPyLoad.""" """Setupscript fuer RevPiPyLoad."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
import distutils.command.install_egg_info import distutils.command.install_egg_info
from sys import platform from sys import platform
from glob import glob from glob import glob
@@ -18,11 +19,14 @@ class MyEggInfo(distutils.command.install_egg_info.install_egg_info):
globsetup = { globsetup = {
"version": "0.8.0",
"author": "Sven Sager", "author": "Sven Sager",
"author_email": "akira@narux.de", "author_email": "akira@narux.de",
"maintainer": "Sven Sager",
"maintainer_email": "akira@revpimodio.org",
"url": "https://revpimodio.org/revpipyplc/", "url": "https://revpimodio.org/revpipyplc/",
"license": "LGPLv3", "license": "LGPLv3",
"version": "0.6.1",
"name": "revpipycontrol", "name": "revpipycontrol",
@@ -34,39 +38,18 @@ globsetup = {
"Außerdem stellt es einen XML-RPC Server bereit, über den die Software\n" "Außerdem stellt es einen XML-RPC Server bereit, über den die Software\n"
"auf den RevPi geladen werden kann. Das Prozessabbild kann über ein Tool\n" "auf den RevPi geladen werden kann. Das Prozessabbild kann über ein Tool\n"
"zur Laufzeit überwacht werden.", "zur Laufzeit überwacht werden.",
}
if platform == "linux": "install_requires": ["tkinter"],
from setuptools import setup
setup(
maintainer="Sven Sager",
maintainer_email="akira@revpimodio.org",
scripts=["data/revpipycontrol"], "classifiers": [
data_files=[
("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")
),
],
install_requires=["tkinter"],
classifiers=[
"License :: OSI Approved :: " "License :: OSI Approved :: "
"GNU Lesser General Public License v3 (LGPLv3)", "GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: POSIX :: Linux", "Operating System :: POSIX :: Linux",
], ],
cmdclass={"install_egg_info": MyEggInfo}, "cmdclass": {"install_egg_info": MyEggInfo},
**globsetup }
)
elif platform == "win32": if platform == "win32":
import sys import sys
from cx_Freeze import setup, Executable from cx_Freeze import setup, Executable
@@ -90,5 +73,24 @@ elif platform == "win32":
] ]
}}, }},
executables=[exe], executables=[exe],
**globsetup
)
else:
from setuptools import setup
setup(
scripts=["data/revpipycontrol"],
data_files=[
("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")
),
],
**globsetup **globsetup
) )