From e9279e4a5313425e8f81c41c63410092a6572af9 Mon Sep 17 00:00:00 2001 From: NaruX Date: Tue, 27 Jun 2017 16:12:09 +0200 Subject: [PATCH 01/13] mktemp auf mkstemp umgestellt PLC monitor aktiviert revpicheckclient auf revpipyloader angepasst Module als einzelnes Fenster anzeigen --- .hgignore | 2 +- doc/revpicheckclient.html | 136 +++++++++++++++++ doc/revpilogfile.html | 114 ++++++++++++++ doc/revpioption.html | 100 +++++++++++++ doc/revpiplclist.html | 151 +++++++++++++++++++ doc/revpiprogram.html | 187 +++++++++++++++++++++++ doc/revpipycontrol.html | 209 ++++++++++++++++++++++++++ revpipycontrol.api | 14 +- revpipycontrol.e4p | 5 +- revpipycontrol/revpicheckclient.py | 230 ++++++++++++++--------------- revpipycontrol/revpiprogram.py | 8 +- revpipycontrol/revpipycontrol.py | 19 ++- setup.py | 2 +- 13 files changed, 1041 insertions(+), 136 deletions(-) create mode 100644 doc/revpicheckclient.html create mode 100644 doc/revpilogfile.html create mode 100644 doc/revpioption.html create mode 100644 doc/revpiplclist.html create mode 100644 doc/revpiprogram.html create mode 100644 doc/revpipycontrol.html diff --git a/.hgignore b/.hgignore index 9e0632f..fe4cdbb 100644 --- a/.hgignore +++ b/.hgignore @@ -3,6 +3,6 @@ syntax: glob deb_dist/* dist/* revpipycontrol.egg-info/* -doc/* deb/* .eric6project/* +*.directory diff --git a/doc/revpicheckclient.html b/doc/revpicheckclient.html new file mode 100644 index 0000000..79c32c2 --- /dev/null +++ b/doc/revpicheckclient.html @@ -0,0 +1,136 @@ + + +revpicheckclient + + + +

+revpicheckclient

+ +

+Global Attributes

+ + +
None
+

+Classes

+ + + + + +
RevPiCheckClient
+

+Functions

+ + +
None
+

+ +

RevPiCheckClient

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
cli
tk
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RevPiCheckClientInstantiiert MyApp-Klasse.
__hidewin
__showwin
_createiogroupErstellt IO-Gruppen.
_createwidgetsErstellt den Fensterinhalt.
_readvaluesAlle Werte der Inputs und Outputs abrufen.
chval
onfrmconf
readvalues
toggleauto
+

+Static Methods

+ + +
None
+ +

+RevPiCheckClient (Constructor)

+RevPiCheckClient(master, xmlcli, xmlmode=0) +

+Instantiiert MyApp-Klasse. +

+

+RevPiCheckClient.__hidewin

+__hidewin(win, event=None) + +

+RevPiCheckClient.__showwin

+__showwin(win) + +

+RevPiCheckClient._createiogroup

+_createiogroup(device, frame, iotype) +

+Erstellt IO-Gruppen. +

+

+RevPiCheckClient._createwidgets

+_createwidgets() +

+Erstellt den Fensterinhalt. +

+

+RevPiCheckClient._readvalues

+_readvalues() +

+Alle Werte der Inputs und Outputs abrufen. +

+

+RevPiCheckClient.chval

+chval(device, io) + +

+RevPiCheckClient.onfrmconf

+onfrmconf(canvas) + +

+RevPiCheckClient.readvalues

+readvalues() + +

+RevPiCheckClient.toggleauto

+toggleauto() + +
Up
+
+ \ No newline at end of file diff --git a/doc/revpilogfile.html b/doc/revpilogfile.html new file mode 100644 index 0000000..e97a54a --- /dev/null +++ b/doc/revpilogfile.html @@ -0,0 +1,114 @@ + + +revpilogfile + + + +

+revpilogfile

+ +

+Global Attributes

+ + +
None
+

+Classes

+ + + + + +
RevPiLogfile
+

+Functions

+ + +
None
+

+ +

RevPiLogfile

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
RevPiLogfile
_createwidgets
btn_clearapp
btn_clearplc
get_applines
get_applog
get_plclines
get_plclog
+

+Static Methods

+ + +
None
+ +

+RevPiLogfile (Constructor)

+RevPiLogfile(master, xmlcli) + +

+RevPiLogfile._createwidgets

+_createwidgets() + +

+RevPiLogfile.btn_clearapp

+btn_clearapp() + +

+RevPiLogfile.btn_clearplc

+btn_clearplc() + +

+RevPiLogfile.get_applines

+get_applines() + +

+RevPiLogfile.get_applog

+get_applog() + +

+RevPiLogfile.get_plclines

+get_plclines() + +

+RevPiLogfile.get_plclog

+get_plclog() + +
Up
+
+ \ No newline at end of file diff --git a/doc/revpioption.html b/doc/revpioption.html new file mode 100644 index 0000000..417e9fd --- /dev/null +++ b/doc/revpioption.html @@ -0,0 +1,100 @@ + + +revpioption + + + +

+revpioption

+ +

+Global Attributes

+ + +
None
+

+Classes

+ + + + + +
RevPiOption
+

+Functions

+ + +
None
+

+ +

RevPiOption

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + +
RevPiOption
_createwidgets
_loadappdata
_setappdata
askxmlon
xmlmods
+

+Static Methods

+ + +
None
+ +

+RevPiOption (Constructor)

+RevPiOption(master, xmlcli, xmlmode) + +

+RevPiOption._createwidgets

+_createwidgets() + +

+RevPiOption._loadappdata

+_loadappdata() + +

+RevPiOption._setappdata

+_setappdata() + +

+RevPiOption.askxmlon

+askxmlon() + +

+RevPiOption.xmlmods

+xmlmods() + +
Up
+
+ \ No newline at end of file diff --git a/doc/revpiplclist.html b/doc/revpiplclist.html new file mode 100644 index 0000000..9d27221 --- /dev/null +++ b/doc/revpiplclist.html @@ -0,0 +1,151 @@ + + +revpiplclist + + + +

+revpiplclist

+ +

+Global Attributes

+ + +
savefile
+

+Classes

+ + + + + +
RevPiPlcList
+

+Functions

+ + + + + +
get_connections
+

+ +

RevPiPlcList

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
myapp
root
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RevPiPlcList
_createwidgets
_loadappdata
_saveappdata
build_listconn
evt_btnadd
evt_btnclose
evt_btnnew
evt_btnremove
evt_btnsave
evt_keypress
evt_listconn
+

+Static Methods

+ + +
None
+ +

+RevPiPlcList (Constructor)

+RevPiPlcList(master) + +

+RevPiPlcList._createwidgets

+_createwidgets() + +

+RevPiPlcList._loadappdata

+_loadappdata() + +

+RevPiPlcList._saveappdata

+_saveappdata() + +

+RevPiPlcList.build_listconn

+build_listconn() + +

+RevPiPlcList.evt_btnadd

+evt_btnadd() + +

+RevPiPlcList.evt_btnclose

+evt_btnclose() + +

+RevPiPlcList.evt_btnnew

+evt_btnnew() + +

+RevPiPlcList.evt_btnremove

+evt_btnremove() + +

+RevPiPlcList.evt_btnsave

+evt_btnsave() + +

+RevPiPlcList.evt_keypress

+evt_keypress(evt=None) + +

+RevPiPlcList.evt_listconn

+evt_listconn(evt=None) + +
Up
+

+ +

get_connections

+get_connections() + +
Up
+
+ \ No newline at end of file diff --git a/doc/revpiprogram.html b/doc/revpiprogram.html new file mode 100644 index 0000000..a00d6cf --- /dev/null +++ b/doc/revpiprogram.html @@ -0,0 +1,187 @@ + + +revpiprogram + + + +

+revpiprogram

+ +

+Global Attributes

+ + +
savefile
+

+Classes

+ + + + + +
RevPiProgram
+

+Functions

+ + +
None
+

+ +

RevPiProgram

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
myapp
root
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RevPiProgram
_createwidgets
_evt_optdown
_evt_optup
_loaddefaultUebernimmt fuer den Pi die letzen Pfade.
_savedefaultsSchreibt fuer den Pi die letzen Pfade.
check_replacedirGibt das rootdir von einem entpackten Verzeichnis zurueck.
create_filelistErstellt eine Dateiliste von einem Verzeichnis.
getpictoryrsc
getprocimg
picontrolreset
plcdownload
plcupload
setpictoryrsc
+

+Static Methods

+ + +
None
+ +

+RevPiProgram (Constructor)

+RevPiProgram(master, xmlcli, xmlmode, revpi) + +

+RevPiProgram._createwidgets

+_createwidgets() + +

+RevPiProgram._evt_optdown

+_evt_optdown(text="") + +

+RevPiProgram._evt_optup

+_evt_optup(text="") + +

+RevPiProgram._loaddefault

+_loaddefault(full=False) +

+Uebernimmt fuer den Pi die letzen Pfade. +

+

+RevPiProgram._savedefaults

+_savedefaults() +

+Schreibt fuer den Pi die letzen Pfade. +

+

+RevPiProgram.check_replacedir

+check_replacedir(rootdir) +

+Gibt das rootdir von einem entpackten Verzeichnis zurueck. +

+ Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt + und ob es eine piCtory Konfiguraiton im rootdir gibt. +

+
rootdir:
+
+Verzeichnis fuer Pruefung +
+
+
Returns:
+
+Abgeaendertes rootdir +
+
+

+RevPiProgram.create_filelist

+create_filelist(rootdir) +

+Erstellt eine Dateiliste von einem Verzeichnis. +

+
rootdir:
+
+Verzeichnis fuer das eine Liste erstellt werden soll +
+
+
Returns:
+
+Dateiliste +
+
+

+RevPiProgram.getpictoryrsc

+getpictoryrsc() + +

+RevPiProgram.getprocimg

+getprocimg() + +

+RevPiProgram.picontrolreset

+picontrolreset() + +

+RevPiProgram.plcdownload

+plcdownload() + +

+RevPiProgram.plcupload

+plcupload() + +

+RevPiProgram.setpictoryrsc

+setpictoryrsc(filename=None) + +
Up
+
+ \ No newline at end of file diff --git a/doc/revpipycontrol.html b/doc/revpipycontrol.html new file mode 100644 index 0000000..11750e5 --- /dev/null +++ b/doc/revpipycontrol.html @@ -0,0 +1,209 @@ + + +revpipycontrol + + + +

+revpipycontrol

+ +

+Global Attributes

+ + +
None
+

+Classes

+ + + + + +
RevPiPyControl
+

+Functions

+ + + + + +
addrootHängt root-dir der Anwendung vor Dateinamen.
+

+ +

RevPiPyControl

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
myapp
root
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RevPiPyControl
_btnstate
_closeall
_createwidgetsErstellt den Fensterinhalt.
_fillconnbar
_fillmbar
_opt_conn
plclist
plclogs
plcmonitorStartet das Monitorfenster.
plcoptionsStartet das Optionsfenster.
plcprogram
plcrestart
plcstart
plcstop
servererrorSetzt alles auf NULL.
tmr_plcrunning
+

+Static Methods

+ + +
None
+ +

+RevPiPyControl (Constructor)

+RevPiPyControl(master=None) + +

+RevPiPyControl._btnstate

+_btnstate() + +

+RevPiPyControl._closeall

+_closeall() + +

+RevPiPyControl._createwidgets

+_createwidgets() +

+Erstellt den Fensterinhalt. +

+

+RevPiPyControl._fillconnbar

+_fillconnbar() + +

+RevPiPyControl._fillmbar

+_fillmbar() + +

+RevPiPyControl._opt_conn

+_opt_conn(text) + +

+RevPiPyControl.plclist

+plclist() + +

+RevPiPyControl.plclogs

+plclogs() + +

+RevPiPyControl.plcmonitor

+plcmonitor() +

+Startet das Monitorfenster. +

+

+RevPiPyControl.plcoptions

+plcoptions() +

+Startet das Optionsfenster. +

+

+RevPiPyControl.plcprogram

+plcprogram() + +

+RevPiPyControl.plcrestart

+plcrestart() + +

+RevPiPyControl.plcstart

+plcstart() + +

+RevPiPyControl.plcstop

+plcstop() + +

+RevPiPyControl.servererror

+servererror() +

+Setzt alles auf NULL. +

+

+RevPiPyControl.tmr_plcrunning

+tmr_plcrunning() + +
Up
+

+ +

addroot

+addroot(filename) +

+Hängt root-dir der Anwendung vor Dateinamen. +

+ Je nach Ausführungsart der Anwendung muss das root-dir über + andere Arten abgerufen werden. +

+
filename:
+
+Datei oder Ordnername +
+
+
Returns:
+
+root dir +
+
+
Up
+
+ \ No newline at end of file diff --git a/revpipycontrol.api b/revpipycontrol.api index 41dff9d..ae08326 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -1,15 +1,15 @@ -revpicheckclient.RevPiCheckClient._autorw?5() +revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None) +revpicheckclient.RevPiCheckClient.__showwin?6(win) revpicheckclient.RevPiCheckClient._createiogroup?5(device, frame, iotype) revpicheckclient.RevPiCheckClient._createwidgets?5() -revpicheckclient.RevPiCheckClient._readvaluesdev?5(device, iotype) -revpicheckclient.RevPiCheckClient._writevaluesdev?5(device) -revpicheckclient.RevPiCheckClient.myapp?7 +revpicheckclient.RevPiCheckClient._readvalues?5() +revpicheckclient.RevPiCheckClient.chval?4(device, io) +revpicheckclient.RevPiCheckClient.cli?7 revpicheckclient.RevPiCheckClient.onfrmconf?4(canvas) revpicheckclient.RevPiCheckClient.readvalues?4() -revpicheckclient.RevPiCheckClient.root?7 +revpicheckclient.RevPiCheckClient.tk?7 revpicheckclient.RevPiCheckClient.toggleauto?4() -revpicheckclient.RevPiCheckClient.writevalues?4() -revpicheckclient.RevPiCheckClient?1(master, xmlcli) +revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0) revpilogfile.RevPiLogfile._createwidgets?5() revpilogfile.RevPiLogfile.btn_clearapp?4() revpilogfile.RevPiLogfile.btn_clearplc?4() diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index 68fd5fa..2908aac 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -9,7 +9,7 @@ Python3 Console - 0.2.12 + 0.4.0 Sven Sager akira@narux.de @@ -30,6 +30,7 @@ data doc revpipycontrol.api + stdeb.cfg revpipycontrol/revpipycontrol.py diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 1076251..e6443ee 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -9,28 +9,29 @@ import pickle import tkinter -from argparse import ArgumentParser -from concurrent.futures import ThreadPoolExecutor -from time import sleep -from xmlrpc.client import ServerProxy, Binary, MultiCall +from threading import Lock +from xmlrpc.client import ServerProxy class RevPiCheckClient(tkinter.Frame): - def __init__(self, master, xmlcli): + def __init__(self, master, xmlcli, xmlmode=0): """Instantiiert MyApp-Klasse.""" super().__init__(master) self.pack(fill="both", expand=True) + # XML-Daten abrufen + self.xmlmode = xmlmode self.cli = xmlcli + self.cli.psstart() + self.lst_devices = self.cli.ps_devices() + self.dict_inps = pickle.loads(self.cli.ps_inps().data) + self.dict_outs = pickle.loads(self.cli.ps_outs().data) - self.lst_devices = self.cli.get_devicenames() - self.lst_group = [] - self.dict_inpvar = {} - self.dict_outvar = {} + self.lk = Lock() self.autorw = tkinter.BooleanVar() - self.fut_autorw = None + self.dowrite = tkinter.BooleanVar() # Fenster aufbauen self._createwidgets() @@ -38,33 +39,6 @@ class RevPiCheckClient(tkinter.Frame): # Aktuelle Werte einlesen self.readvalues() - def _autorw(self): - dict_inp = {} - dict_out = {} - - while self.autorw.get(): - for dev in self.lst_devices: - try: - dict_out[dev] = [ - value[8].get() for value in self.dict_outvar[dev] - ] - except: - print("lasse {} aus".format(dev)) - - dict_inp = self.cli.refreshvalues( - Binary(pickle.dumps(dict_out, 3)) - ) - dict_inp = pickle.loads(dict_inp.data) - - for dev in dict_inp: - for io in self.dict_inpvar[dev]: - try: - io[8].set(dict_inp[dev].pop(0)) - except: - print("lasse {} aus".format(io[0])) - - sleep(0.1) - def onfrmconf(self, canvas): canvas.configure(scrollregion=canvas.bbox("all")) @@ -85,23 +59,34 @@ class RevPiCheckClient(tkinter.Frame): ) rowcount = 0 - for io in self.cli.get_iolist(device, iotype): - # io = [name,default,anzbits,adressbyte,export,adressid,bmk,bitaddress,tkinter_var] + + if iotype == "inp": + lst_io = self.dict_inps[device] + else: + lst_io = self.dict_outs[device] + + for io in lst_io: + # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] tkinter.Label(s_frame, text=io[0]).grid( column=0, row=rowcount, sticky="w" ) - if io[7] >= 0: + if io[4] >= 0: var = tkinter.BooleanVar() check = tkinter.Checkbutton(s_frame) + check["command"] = \ + lambda device=device, io=io: self.chval(device, io) check["state"] = "disabled" if iotype == "inp" else "normal" check["text"] = "" check["variable"] = var check.grid(column=1, row=rowcount) else: var = tkinter.IntVar() - txt = tkinter.Spinbox(s_frame, to=256) + # FIXME: Mehrere Bytes möglich + txt = tkinter.Spinbox(s_frame, to=255 * io[1]) + txt["command"] = \ + lambda device=device, io=io: self.chval(device, io) txt["state"] = "disabled" if iotype == "inp" else "normal" txt["width"] = 4 txt["textvariable"] = var @@ -109,116 +94,127 @@ class RevPiCheckClient(tkinter.Frame): # Steuerelementvariable in IO übernehmen io.append(var) - if iotype == "inp": - self.dict_inpvar[device].append(io) - elif iotype == "out": - self.dict_outvar[device].append(io) rowcount += 1 + def __hidewin(self, win, event=None): + win.withdraw() + + def __showwin(self, win): + if win.winfo_viewable(): + win.withdraw() + else: + win.deiconify() + def _createwidgets(self): """Erstellt den Fensterinhalt.""" # Hauptfenster self.master.wm_title("RevPi Onlineview") + devgrp = tkinter.LabelFrame(self) + devgrp["text"] = "Devices of RevPi" + devgrp.pack(fill="y", side="left") + for dev in self.lst_devices: - # Variablen vorbereiten - self.dict_inpvar[dev] = [] - self.dict_outvar[dev] = [] + win = tkinter.Toplevel(self) + win.wm_title(dev[1]) + win.protocol( + "WM_DELETE_WINDOW", + lambda win=win: self.__hidewin(win) + ) + win.withdraw() # Devicegruppe erstellen - group = tkinter.LabelFrame(self) - group["text"] = dev + group = tkinter.LabelFrame(win) + group["text"] = dev[1] group.pack(side="left", fill="both", expand=True) - self.lst_group.append(group) for iotype in ["inp", "out"]: frame = tkinter.Frame(group) frame.pack(side="left", fill="both", expand=True) - self._createiogroup(dev, frame, iotype) + self._createiogroup(dev[0], frame, iotype) -# self.btn_update = tkinter.Button(self) -# self.btn_update["text"] = "UPDATE" -# self.btn_update["command"] = self._autorw -# self.btn_update.pack(anchor="s", side="bottom", fill="x") + # Button erstellen + btn = tkinter.Button(devgrp) + btn["command"] = lambda win=win: self.__showwin(win) + btn["text"] = dev[1] + btn.pack(fill="x", padx=10, pady=5) - self.btn_write = tkinter.Button(self) - self.btn_write["text"] = "SCHREIBEN" - self.btn_write["command"] = self.writevalues - self.btn_write.pack(side="bottom", fill="x") + # Steuerungsfunktionen + cntgrp = tkinter.LabelFrame(self) + cntgrp["text"] = "Control" + cntgrp.pack(fill="y", side="right") - self.btn_read = tkinter.Button(self) + self.btn_read = tkinter.Button(cntgrp) self.btn_read["text"] = "LESEN" self.btn_read["command"] = self.readvalues - self.btn_read.pack(side="bottom", fill="x") + self.btn_read.pack(fill="x") - check = tkinter.Checkbutton(self) + check = tkinter.Checkbutton(cntgrp) check["command"] = self.toggleauto - check["text"] = "autoupdate" + check["text"] = "autorefresh processimage" check["variable"] = self.autorw - check.pack(side="bottom") + check.pack(anchor="w") - def _readvaluesdev(self, device, iotype): - """Ruft alle aktuellen Werte fuer das Device ab.""" - # Multicall vorbereiten - mc_values = MultiCall(self.cli) + check = tkinter.Checkbutton(cntgrp) + check["state"] = "disabled" if self.xmlmode < 3 else "normal" + check["text"] = "write values to processimage" + check["variable"] = self.dowrite + check.pack(anchor="w") - if iotype == "inp": - lst_ios = self.dict_inpvar[device] - elif iotype == "out": - lst_ios = self.dict_outvar[device] + def chval(self, device, io): + if self.dowrite.get(): + with self.lk: + self.cli.ps_setvalue(device, io[0], io[5].get()) - for io in lst_ios: - mc_values.get_iovalue(device, io[0]) + # Alles neu einlesen wenn nicht AutoRW aktiv ist + if not self.autorw.get(): + self.readvalues() - i = 0 - for value in mc_values(): - value = pickle.loads(value.data) - if type(value) == bytes: - value = int.from_bytes(value, byteorder="little") - - lst_ios[i][8].set(value) - i += 1 - - def _writevaluesdev(self, device): - """Sendet Werte der Outputs fuer ein Device.""" - # Multicall vorbereiten - mc_values = MultiCall(self.cli) - lst_ios = lst_ios = self.dict_outvar[device] - - for io in lst_ios: - mc_values.set_iovalue(device, io[0], pickle.dumps(io[8].get(), 3)) - - # Multicall ausführen - mc_values() - - def readvalues(self): + def _readvalues(self): """Alle Werte der Inputs und Outputs abrufen.""" - # Werte aus Prozessabbild einlesen - self.cli.readprocimg() + + # Werte abrufen + with self.lk: + ba_values = bytearray(self.cli.ps_values().data) for dev in self.lst_devices: - self._readvaluesdev(dev, "inp") - self._readvaluesdev(dev, "out") + # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] + + # IO Typ verarbeiten + for iotype in [self.dict_inps, self.dict_outs]: + # ios verarbeiten + for io in iotype[dev[0]]: + + # Bytes umwandeln + int_byte = int.from_bytes( + ba_values[io[2]:io[2] + io[1]], byteorder="little" + ) + if io[4] >= 0: + # Bit-IO + io[5].set(bool(int_byte & 1 << io[4])) + else: + # Byte-IO + io[5].set(int_byte) + + if self.autorw.get(): + self.master.after(200, self._readvalues) + + def readvalues(self): + if not self.autorw.get(): + self._readvalues() def toggleauto(self): self.btn_read["state"] = "disabled" if self.autorw.get() else "normal" - self.btn_write["state"] = "disabled" if self.autorw.get() else "normal" - if self.autorw.get() \ - and (self.fut_autorw is None or self.fut_autorw.done()): - e = ThreadPoolExecutor(max_workers=1) - self.fut_autorw = e.submit(self._autorw) + if self.autorw.get(): + self._readvalues() - def writevalues(self): - """Alle Outputs senden.""" - pass - #for dev in self.lst_devices: - #self._writevaluesdev(dev) - - # Werte in Prozessabbild schreiben - #self.cli.writeprocimg() +# Testdrive if __name__ == "__main__": - root = tkinter.Tk() - myapp = RevPiCheckClient(root) - myapp.mainloop() + cli = ServerProxy("http://192.168.50.35:55123") + cli.psstart() + + tk = tkinter.Tk() + RevPiCheckClient(tk, cli, 3) + tk.mainloop() diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 01abff2..06dff81 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -17,7 +17,7 @@ from os import environ from os import makedirs from shutil import rmtree from sys import platform -from tempfile import mktemp, mkdtemp +from tempfile import mkstemp, mkdtemp from xmlrpc.client import Binary @@ -363,7 +363,7 @@ class RevPiProgram(tkinter.Frame): message="Die Übertragung der piCtory Konfiguration " "wurde erfolgreich ausgeführt") - #Einstellungen speichern + # Einstellungen speichern self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self._savedefaults() elif ec < 0: @@ -382,7 +382,7 @@ class RevPiProgram(tkinter.Frame): def picontrolreset(self): ask = tkmsg.askyesno( - parent=self.master, title="Frage...", + parent=self.master, title="Frage...", message="Soll piControlReset wirklich durchgeführt werden? \n" "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" ) @@ -415,7 +415,7 @@ class RevPiProgram(tkinter.Frame): ) if type(dirselect) == str and dirselect != "": - fh = open(mktemp(), "wb") + fh = open(mkstemp(), "wb") elif tdown == 1: # Zip diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 4f518d6..c107e62 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -1,12 +1,13 @@ #!/usr/bin/python3 # # RevPiPyControl -# Version: 0.2.12 +# Version: 0.4.0 # # Webpage: https://revpimodio.org/revpipyplc/ # (c) Sven Sager, License: LGPLv3 # # -*- coding: utf-8 -*- +import revpicheckclient import revpilogfile import revpioption import revpiplclist @@ -50,6 +51,7 @@ class RevPiPyControl(tkinter.Frame): self.xmlmode = 0 # Globale Fenster + self.tkcheckclient = None self.tklogs = None self.tkoptions = None self.tkprogram = None @@ -124,7 +126,7 @@ class RevPiPyControl(tkinter.Frame): # PLC Menü self.mplc = tkinter.Menu(self.mbar, tearoff=False) self.mplc.add_command(label="PLC log...", command=self.plclogs) - #self.mplc.add_command(label="PLC monitor...", command=self.plcmonitor) + self.mplc.add_command(label="PLC monitor...", command=self.plcmonitor) self.mplc.add_command(label="PLC options...", command=self.plcoptions) self.mplc.add_command(label="PLC program...", command=self.plcprogram) self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") @@ -167,6 +169,8 @@ class RevPiPyControl(tkinter.Frame): self.mbar.entryconfig("PLC", state="normal") def _closeall(self): + if self.tkcheckclient is not None: + self.tkcheckclient.destroy() if self.tklogs is not None: self.tklogs.master.destroy() if self.tkoptions is not None: @@ -191,10 +195,17 @@ class RevPiPyControl(tkinter.Frame): self.tklogs.focus_set() def plcmonitor(self): - # TODO: Monitorfenster - pass + """Startet das Monitorfenster.""" + if self.tkcheckclient is None or len(self.tkcheckclient.children) == 0: + win = tkinter.Toplevel(self) + self.tkcheckclient = revpicheckclient.RevPiCheckClient( + win, self.cli, self.xmlmode + ) + else: + self.tkcheckclient.focus_set() def plcoptions(self): + """Startet das Optionsfenster.""" if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", diff --git a/setup.py b/setup.py index 0af49cd..2d518aa 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ globsetup = { "author_email": "akira@narux.de", "url": "https://revpimodio.org/revpipyplc/", "license": "LGPLv3", - "version": "0.2.12", + "version": "0.4.0", "name": "revpipycontrol", From 673c338c6b3b61556596eff4eb37b13a8bb0ba1b Mon Sep 17 00:00:00 2001 From: NaruX Date: Wed, 28 Jun 2017 11:55:30 +0200 Subject: [PATCH 02/13] "Monitorfunktion" als Debug zum Hautpfenster hinzugef?gt Disconnect-Men?eintrag eingebaut (Funktion hinzugef?gt) Funktionen f?r "nur lesen" und "nur schreiben" eingebaut Werte schreiben per MultiCall UI-Texte angepasst DocStrings und CodeStyle --- revpipycontrol/revpicheckclient.py | 124 ++++++++++++++++++++--------- revpipycontrol/revpiprogram.py | 13 ++- revpipycontrol/revpipycontrol.py | 118 +++++++++++++++++++-------- 3 files changed, 179 insertions(+), 76 deletions(-) diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index e6443ee..284ec88 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -10,7 +10,7 @@ import pickle import tkinter from threading import Lock -from xmlrpc.client import ServerProxy +from xmlrpc.client import ServerProxy, MultiCall class RevPiCheckClient(tkinter.Frame): @@ -18,17 +18,20 @@ class RevPiCheckClient(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode=0): """Instantiiert MyApp-Klasse.""" super().__init__(master) - self.pack(fill="both", expand=True) # XML-Daten abrufen self.xmlmode = xmlmode self.cli = xmlcli + + # FIXME: Fehlerabfang self.cli.psstart() + self.lst_devices = self.cli.ps_devices() self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) self.lk = Lock() + self.lst_wins = [] self.autorw = tkinter.BooleanVar() self.dowrite = tkinter.BooleanVar() @@ -37,10 +40,25 @@ class RevPiCheckClient(tkinter.Frame): self._createwidgets() # Aktuelle Werte einlesen - self.readvalues() + self.refreshvalues() - def onfrmconf(self, canvas): - canvas.configure(scrollregion=canvas.bbox("all")) + def __chval(self, device, io): + if self.dowrite.get(): + with self.lk: + self.cli.ps_setvalue(device, io[0], io[5].get()) + + # Alles neu einlesen wenn nicht AutoRW aktiv ist + if not self.autorw.get(): + self.refreshvalues() + + def __hidewin(self, win, event=None): + win.withdraw() + + def __showwin(self, win): + if win.winfo_viewable(): + win.withdraw() + else: + win.deiconify() def _createiogroup(self, device, frame, iotype): """Erstellt IO-Gruppen.""" @@ -55,7 +73,7 @@ class RevPiCheckClient(tkinter.Frame): canvas.create_window((4, 4), window=s_frame, anchor="nw") s_frame.bind( - "", lambda event, canvas=canvas: self.onfrmconf(canvas) + "", lambda event, canvas=canvas: self._onfrmconf(canvas) ) rowcount = 0 @@ -76,7 +94,7 @@ class RevPiCheckClient(tkinter.Frame): var = tkinter.BooleanVar() check = tkinter.Checkbutton(s_frame) check["command"] = \ - lambda device=device, io=io: self.chval(device, io) + lambda device=device, io=io: self.__chval(device, io) check["state"] = "disabled" if iotype == "inp" else "normal" check["text"] = "" check["variable"] = var @@ -86,7 +104,7 @@ class RevPiCheckClient(tkinter.Frame): # FIXME: Mehrere Bytes möglich txt = tkinter.Spinbox(s_frame, to=255 * io[1]) 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" else "normal" txt["width"] = 4 txt["textvariable"] = var @@ -97,19 +115,8 @@ class RevPiCheckClient(tkinter.Frame): rowcount += 1 - def __hidewin(self, win, event=None): - win.withdraw() - - def __showwin(self, win): - if win.winfo_viewable(): - win.withdraw() - else: - win.deiconify() - def _createwidgets(self): """Erstellt den Fensterinhalt.""" - # Hauptfenster - self.master.wm_title("RevPi Onlineview") devgrp = tkinter.LabelFrame(self) devgrp["text"] = "Devices of RevPi" @@ -123,6 +130,7 @@ class RevPiCheckClient(tkinter.Frame): lambda win=win: self.__hidewin(win) ) win.withdraw() + self.lst_wins.append(win) # Devicegruppe erstellen group = tkinter.LabelFrame(win) @@ -145,44 +153,56 @@ class RevPiCheckClient(tkinter.Frame): cntgrp["text"] = "Control" cntgrp.pack(fill="y", side="right") + self.btn_refresh = tkinter.Button(cntgrp) + self.btn_refresh["text"] = "Alle IOs lesen" + self.btn_refresh["command"] = self.refreshvalues + self.btn_refresh.pack(fill="x") + self.btn_read = tkinter.Button(cntgrp) - self.btn_read["text"] = "LESEN" + self.btn_read["text"] = "Inputs einlesen" self.btn_read["command"] = self.readvalues self.btn_read.pack(fill="x") + self.btn_write = tkinter.Button(cntgrp) + self.btn_write["text"] = "Outputs schreiben" + self.btn_write["command"] = self.writevalues + self.btn_write.pack(fill="x") + check = tkinter.Checkbutton(cntgrp) check["command"] = self.toggleauto - check["text"] = "autorefresh processimage" + check["text"] = "Autorefresh values" check["variable"] = self.autorw check.pack(anchor="w") check = tkinter.Checkbutton(cntgrp) check["state"] = "disabled" if self.xmlmode < 3 else "normal" - check["text"] = "write values to processimage" + check["text"] = "Write values to RevPi" check["variable"] = self.dowrite check.pack(anchor="w") - def chval(self, device, io): - if self.dowrite.get(): - with self.lk: - self.cli.ps_setvalue(device, io[0], io[5].get()) + def _onfrmconf(self, canvas): + canvas.configure(scrollregion=canvas.bbox("all")) - # Alles neu einlesen wenn nicht AutoRW aktiv ist - if not self.autorw.get(): - self.readvalues() - - def _readvalues(self): + def _workvalues(self, io_dicts=None, writeout=False): """Alle Werte der Inputs und Outputs abrufen.""" + # Abfragelisten vorbereiten + if io_dicts is None: + io_dicts = [self.dict_inps, self.dict_outs] + # Werte abrufen with self.lk: ba_values = bytearray(self.cli.ps_values().data) + # Multicall zum Schreiben vorbereiten + if writeout: + xmlmc = MultiCall(self.cli) + for dev in self.lst_devices: # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] # IO Typ verarbeiten - for iotype in [self.dict_inps, self.dict_outs]: + for iotype in io_dicts: # ios verarbeiten for io in iotype[dev[0]]: @@ -192,22 +212,50 @@ class RevPiCheckClient(tkinter.Frame): ) if io[4] >= 0: # Bit-IO - io[5].set(bool(int_byte & 1 << io[4])) + new_val = bool(int_byte & 1 << io[4]) + if writeout and new_val != io[5].get(): + xmlmc.ps_setvalue(dev[0], io[0], io[5].get()) + else: + io[5].set(new_val) else: # Byte-IO - io[5].set(int_byte) + if writeout and int_byte != io[5].get(): + xmlmc.ps_setvalue(dev[0], io[0], io[5].get()) + else: + io[5].set(int_byte) + + # Werte per Multicall schreiben + if writeout: + with self.lk: + xmlmc() if self.autorw.get(): - self.master.after(200, self._readvalues) + self.master.after(200, self._workvalues) + + def hideallwindows(self): + for win in self.lst_wins: + win.withdraw() def readvalues(self): if not self.autorw.get(): - self._readvalues() + self._workvalues([self.dict_inps]) + + def refreshvalues(self): + if not self.autorw.get(): + self._workvalues() def toggleauto(self): - self.btn_read["state"] = "disabled" if self.autorw.get() else "normal" + stateval = "disabled" if self.autorw.get() else "normal" + self.btn_refresh["state"] = stateval + self.btn_read["state"] = stateval + self.btn_write["state"] = stateval + if self.autorw.get(): - self._readvalues() + self._workvalues() + + def writevalues(self): + if not self.autorw.get(): + self._workvalues([self.dict_outs], True) # Testdrive diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 06dff81..55f41df 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -32,6 +32,7 @@ savefile = os.path.join(homedir, ".revpipyplc", "programpath.dat") class RevPiProgram(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode, revpi): + u"""Init RevPiProgram-Class.""" if xmlmode < 2: return None @@ -223,7 +224,7 @@ class RevPiProgram(tkinter.Frame): return {} def _savedefaults(self): - """Schreibt fuer den Pi die letzen Pfade.""" + u"""Schreibt fuer den Pi die letzen Pfade.""" try: makedirs(os.path.dirname(savefile), exist_ok=True) dict_all = self._loaddefault(full=True) @@ -236,7 +237,7 @@ class RevPiProgram(tkinter.Frame): return True def create_filelist(self, rootdir): - """Erstellt eine Dateiliste von einem Verzeichnis. + u"""Erstellt eine Dateiliste von einem Verzeichnis. @param rootdir: Verzeichnis fuer das eine Liste erstellt werden soll @returns: Dateiliste""" filelist = [] @@ -249,7 +250,7 @@ class RevPiProgram(tkinter.Frame): """Gibt das rootdir von einem entpackten Verzeichnis zurueck. Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt - und ob es eine piCtory Konfiguraiton im rootdir gibt. + und ob es eine piCtory Konfiguration im rootdir gibt. @param rootdir: Verzeichnis fuer Pruefung @returns: Abgeaendertes rootdir @@ -270,6 +271,7 @@ class RevPiProgram(tkinter.Frame): return (rootdir, None) def getpictoryrsc(self): + u"""Läd die piCtory Konfiguration herunter.""" fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, @@ -300,6 +302,7 @@ class RevPiProgram(tkinter.Frame): fh.close() def getprocimg(self): + u"""Läd das aktuelle Prozessabbild herunter.""" fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, @@ -330,6 +333,7 @@ class RevPiProgram(tkinter.Frame): fh.close() def setpictoryrsc(self, filename=None): + u"""Überträgt die angegebene piCtory-Konfiguration.""" if filename is None: fh = tkfd.askopenfile( mode="rb", parent=self.master, @@ -381,6 +385,7 @@ class RevPiProgram(tkinter.Frame): fh.close() def picontrolreset(self): + u"""Fürt ein Reset der piBridge durch.""" ask = tkmsg.askyesno( parent=self.master, title="Frage...", message="Soll piControlReset wirklich durchgeführt werden? \n" @@ -401,6 +406,7 @@ class RevPiProgram(tkinter.Frame): ) def plcdownload(self): + u"""Läd das aktuelle Projekt herunter.""" tdown = self.lst_typedown.index(self.var_typedown.get()) fh = None dirselect = "" @@ -491,6 +497,7 @@ class RevPiProgram(tkinter.Frame): fh.close() def plcupload(self): + u"""Lädt das angegebene Projekt auf den RevPi.""" tup = self.lst_typeup.index(self.var_typeup.get()) dirselect = "" dirtmp = None diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index c107e62..de8cfb5 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -41,6 +41,8 @@ def addroot(filename): class RevPiPyControl(tkinter.Frame): def __init__(self, master=None): + u"""Init RevPiPyControl-Class. + @param master: tkinter master""" super().__init__(master) self.pack(fill="both", expand=True) @@ -48,8 +50,12 @@ class RevPiPyControl(tkinter.Frame): self.dict_conn = revpiplclist.get_connections() self.errcount = 0 self.revpiname = None + self.xmlfuncs = [] self.xmlmode = 0 + # Debugger vorbereiten + self.debugframe = None + # Globale Fenster self.tkcheckclient = None self.tklogs = None @@ -63,14 +69,30 @@ class RevPiPyControl(tkinter.Frame): self.tmr_plcrunning() def _btnstate(self): + u"""Setzt den state der Buttons.""" stateval = "disabled" if self.cli is None else "normal" self.btn_plclogs["state"] = stateval self.btn_plcstart["state"] = stateval self.btn_plcstop["state"] = stateval self.btn_plcrestart["state"] = stateval + self.btn_debug["state"] = stateval + + def _closeall(self): + u"""Schließt alle Fenster.""" + if self.tkcheckclient is not None: + self.tkcheckclient.destroy() + if self.tklogs is not None: + self.tklogs.master.destroy() + if self.tkoptions is not None: + self.tkoptions.destroy() + if self.tkprogram is not None: + self.tkprogram.destroy() + if self.debugframe is not None: + self.debugframe.destroy() + self.debugframe = None def _createwidgets(self): - """Erstellt den Fensterinhalt.""" + u"""Erstellt den Fensterinhalt.""" # Hauptfenster self.master.wm_title("RevPi Python PLC Loader") self.master.wm_iconphoto( @@ -122,26 +144,39 @@ class RevPiPyControl(tkinter.Frame): self.txt_status["textvariable"] = self.var_status self.txt_status.pack(fill="x") - def _fillmbar(self): - # PLC Menü - self.mplc = tkinter.Menu(self.mbar, tearoff=False) - self.mplc.add_command(label="PLC log...", command=self.plclogs) - self.mplc.add_command(label="PLC monitor...", command=self.plcmonitor) - self.mplc.add_command(label="PLC options...", command=self.plcoptions) - self.mplc.add_command(label="PLC program...", command=self.plcprogram) - self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") - - # Connection Menü - self.mconn = tkinter.Menu(self.mbar, tearoff=False) - self.mbar.add_cascade(label="Connect", menu=self.mconn) + self.btn_debug = tkinter.Button(self) + self.btn_debug["text"] = "PLC Debugmodus" + self.btn_debug["command"] = self.plcdebug + self.btn_debug.pack(fill="x") def _fillconnbar(self): + u"""Generiert Menüeinträge für Verbindungen.""" self.mconn.delete(0, "end") for con in sorted(self.dict_conn.keys(), key=lambda x: x.lower()): self.mconn.add_command( label=con, command=partial(self._opt_conn, con) ) + def _fillmbar(self): + u"""Generiert Menüeinträge.""" + # PLC Menü + self.mplc = tkinter.Menu(self.mbar, tearoff=False) + self.mplc.add_command( + label="PLC log...", command=self.plclogs) + self.mplc.add_command( + label="PLC options...", command=self.plcoptions) + self.mplc.add_command( + label="PLC program...", command=self.plcprogram) + self.mplc.add_separator() + + self.mplc.add_command( + label="Disconnect", command=self.serverdisconnect) + self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") + + # Connection Menü + self.mconn = tkinter.Menu(self.mbar, tearoff=False) + self.mbar.add_cascade(label="Connect", menu=self.mconn) + def _opt_conn(self, text): socket.setdefaulttimeout(2) sp = ServerProxy( @@ -151,6 +186,7 @@ class RevPiPyControl(tkinter.Frame): ) # Server prüfen try: + self.xmlfuncs = sp.system.listMethods() self.xmlmode = sp.xmlmodus() except: self.servererror() @@ -168,17 +204,30 @@ class RevPiPyControl(tkinter.Frame): )) self.mbar.entryconfig("PLC", state="normal") - def _closeall(self): - if self.tkcheckclient is not None: - self.tkcheckclient.destroy() - if self.tklogs is not None: - self.tklogs.master.destroy() - if self.tkoptions is not None: - self.tkoptions.destroy() - if self.tkprogram is not None: - self.tkprogram.destroy() + def plcdebug(self): + u"""Baut den Debugframe und packt ihn.""" + self.btn_debug["state"] = "disabled" + + # Debugfenster laden + if self.debugframe is None: + self.debugframe = revpicheckclient.RevPiCheckClient( + self, self.cli, self.xmlmode + ) + + # Show/Hide wechseln + if self.debugframe.winfo_viewable(): + self.debugframe.hideallwindows() + self.debugframe.autorw.set(False) + self.debugframe.toggleauto() + self.debugframe.dowrite.set(False) + self.debugframe.pack_forget() + else: + self.debugframe.pack(fill="y") + + self.btn_debug["state"] = "normal" def plclist(self): + u"""Öffnet das Fenster für die Verbindungen.""" win = tkinter.Toplevel(self) revpiplclist.RevPiPlcList(win) win.focus_set() @@ -188,24 +237,15 @@ class RevPiPyControl(tkinter.Frame): self._fillconnbar() def plclogs(self): + u"""Öffnet das Fenster für Logdateien.""" if self.tklogs is None or len(self.tklogs.children) == 0: win = tkinter.Toplevel(self) self.tklogs = revpilogfile.RevPiLogfile(win, self.cli) else: self.tklogs.focus_set() - def plcmonitor(self): - """Startet das Monitorfenster.""" - if self.tkcheckclient is None or len(self.tkcheckclient.children) == 0: - win = tkinter.Toplevel(self) - self.tkcheckclient = revpicheckclient.RevPiCheckClient( - win, self.cli, self.xmlmode - ) - else: - self.tkcheckclient.focus_set() - def plcoptions(self): - """Startet das Optionsfenster.""" + u"""Startet das Optionsfenster.""" if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", @@ -222,6 +262,7 @@ class RevPiPyControl(tkinter.Frame): self.xmlmode = self.tkoptions.xmlmode def plcprogram(self): + u"""Startet das Programmfenster.""" if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", @@ -237,23 +278,30 @@ class RevPiPyControl(tkinter.Frame): self.wait_window(win) def plcstart(self): + u"""Startet das PLC Programm.""" self.cli.plcstart() def plcstop(self): + u"""Beendet das PLC Programm.""" self.cli.plcstop() def plcrestart(self): + u"""Startet das PLC Programm neu.""" self.cli.plcstop() self.cli.plcstart() - def servererror(self): - """Setzt alles auf NULL.""" + def serverdisconnect(self): + u"""Trennt eine bestehende Verbindung.""" socket.setdefaulttimeout(2) self.cli = None self._btnstate() self.mbar.entryconfig("PLC", state="disabled") self.var_conn.set("") self._closeall() + + def servererror(self): + u"""Setzt alles zurück für neue Verbindungen.""" + self.serverdisconnect() tkmsg.showerror("Fehler", "Server ist nicht erreichbar!") def tmr_plcrunning(self): From 8c8da29915b7be0f0c5e76386b185ec8c40407a1 Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 29 Jun 2017 09:00:19 +0200 Subject: [PATCH 03/13] IO-Fenster nur in Y resizable Scrollrad an Canvas gekoppelt (Linux) Exitcodes angepasst ?bersetzungstools eingebaut ?bersetzungen begonnen --- revpipycontrol.e4p | 3 +- revpipycontrol/mytools.py | 46 +++++ revpipycontrol/revpicheckclient.py | 40 +++-- revpipycontrol/revpiprogram.py | 272 +++++++++++++++++------------ revpipycontrol/revpipycontrol.py | 114 ++++++------ 5 files changed, 297 insertions(+), 178 deletions(-) create mode 100644 revpipycontrol/mytools.py diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index 2908aac..b5d5115 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -21,6 +21,7 @@ revpipycontrol/revpilogfile.py revpipycontrol/revpioption.py revpipycontrol/revpiprogram.py + revpipycontrol/mytools.py diff --git a/revpipycontrol/mytools.py b/revpipycontrol/mytools.py new file mode 100644 index 0000000..858d53a --- /dev/null +++ b/revpipycontrol/mytools.py @@ -0,0 +1,46 @@ +# +# RevPiPyControl +# +# Webpage: https://revpimodio.org/revpipyplc/ +# (c) Sven Sager, License: LGPLv3 +# +# -*- coding: utf-8 -*- +import gettext +import locale +import sys +from os.path import dirname +from os.path import join as pathjoin + + +def addroot(filename): + u"""Hängt root-dir der Anwendung vor Dateinamen. + + Je nach Ausführungsart der Anwendung muss das root-dir über + andere Arten abgerufen werden. + + @param filename: Datei oder Ordnername + @returns: root dir + + """ + if getattr(sys, "frozen", False): + return pathjoin(dirname(sys.executable), filename) + else: + return pathjoin(dirname(__file__), filename) + + +def gettrans(proglang=None): + + # Sprache auswählen + if proglang is None: + # Autodetect Language or switch to static + # proglang = "de" + proglang = locale.getdefaultlocale()[0].split('_')[0] + + # Übersetzungen laden + trans = gettext.translation( + "revpipycontrol", + addroot("locale"), + languages=[proglang], + fallback=True + ) + return trans.gettext diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 284ec88..c15c6ad 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -22,10 +22,7 @@ class RevPiCheckClient(tkinter.Frame): # XML-Daten abrufen self.xmlmode = xmlmode self.cli = xmlcli - - # FIXME: Fehlerabfang self.cli.psstart() - self.lst_devices = self.cli.ps_devices() self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) @@ -62,12 +59,35 @@ class RevPiCheckClient(tkinter.Frame): def _createiogroup(self, device, frame, iotype): """Erstellt IO-Gruppen.""" - # IOs generieren - canvas = tkinter.Canvas(frame, borderwidth=0, width=180, heigh=800) + + # IO-Typen festlegen + if iotype == "inp": + lst_io = self.dict_inps[device] + else: + lst_io = self.dict_outs[device] + + # Fensterinhalt aufbauen + calc_heigh = len(lst_io) * 21 + canvas = tkinter.Canvas( + frame, + borderwidth=0, + width=180, + heigh=calc_heigh if calc_heigh <= 600 else 600 + ) s_frame = tkinter.Frame(canvas) vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview) canvas.configure(yscrollcommand=vsb.set) + # Scrollrad Linux + canvas.bind( + "", + lambda x: canvas.yview_scroll(-1, "units") + ) + canvas.bind( + "", + lambda x: canvas.yview_scroll(1, "units") + ) + vsb.pack(side="right", fill="y") canvas.pack(side="left", fill="both", expand=True) @@ -76,13 +96,8 @@ class RevPiCheckClient(tkinter.Frame): "", lambda event, canvas=canvas: self._onfrmconf(canvas) ) + # IOs generieren rowcount = 0 - - if iotype == "inp": - lst_io = self.dict_inps[device] - else: - lst_io = self.dict_outs[device] - for io in lst_io: # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] @@ -101,8 +116,10 @@ class RevPiCheckClient(tkinter.Frame): check.grid(column=1, row=rowcount) else: var = tkinter.IntVar() + # FIXME: Mehrere Bytes möglich txt = tkinter.Spinbox(s_frame, to=255 * io[1]) + txt["command"] = \ lambda device=device, io=io: self.__chval(device, io) txt["state"] = "disabled" if iotype == "inp" else "normal" @@ -129,6 +146,7 @@ class RevPiCheckClient(tkinter.Frame): "WM_DELETE_WINDOW", lambda win=win: self.__hidewin(win) ) + win.resizable(False, True) win.withdraw() self.lst_wins.append(win) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 55f41df..96d733e 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -13,6 +13,7 @@ import tkinter import tkinter.filedialog as tkfd import tkinter.messagebox as tkmsg import zipfile +from mytools import gettrans from os import environ from os import makedirs from shutil import rmtree @@ -20,6 +21,8 @@ from sys import platform from tempfile import mkstemp, mkdtemp from xmlrpc.client import Binary +# Übersetzung laden +_ = gettrans() # Systemwerte if platform == "linux": @@ -37,7 +40,8 @@ class RevPiProgram(tkinter.Frame): return None super().__init__(master) -# master.protocol("WM_DELETE_WINDOW", self._checkclose) + # FIXME: Warnung kann nerven + # self.master.protocol("WM_DELETE_WINDOW", self._checkclose) self.pack(expand=True, fill="both") self.uploaded = False @@ -55,15 +59,20 @@ class RevPiProgram(tkinter.Frame): self._evt_optdown() self._evt_optup() -# def _checkclose(self): -# if self.uploaded: -# tkmsg.showinfo("Ein PLC Programm wurde hochgeladen. " -# "Bitte die PLC options prüfen ob dort das neue Programm" -# "eingestellt werden muss.") -# self.master.destroy() + def _checkclose(self): + if True or self.uploaded: + tkmsg.showinfo( + parent=self.master, title=_("Information"), + message=_( + "A PLC program has been uploaded. Please check the " + "PLC options to see if the correct program is specified " + "as the start program." + ) + ) + self.master.destroy() def _createwidgets(self): - self.master.wm_title("RevPi Python PLC Programm") + self.master.wm_title(_("RevPi python PLC programm")) self.master.wm_resizable(width=False, height=False) self.rowconfigure(0, weight=1) @@ -77,7 +86,7 @@ class RevPiProgram(tkinter.Frame): # Gruppe Programm prog = tkinter.LabelFrame(self) prog.columnconfigure(0, weight=1) - prog["text"] = "PLC Python programm" + prog["text"] = _("PLC python programm") prog.grid(columnspan=2, pady=2, sticky="we") # Variablen vorbereiten @@ -87,16 +96,26 @@ class RevPiProgram(tkinter.Frame): self.var_typedown = tkinter.StringVar(prog) self.var_typeup = tkinter.StringVar(prog) - self.lst_typedown = ["Dateien", "Zip Archiv", "TGZ Archiv"] - self.lst_typeup = ["Dateien", "Ordner", "Zip Archiv", "TGZ Archiv"] + self.lst_typedown = [_("Files"), _("Zip archive"), _("TGZ archive")] + self.lst_typeup = [ + _("Files"), _("Folder"), _("Zip archive"), _("TGZ archive") + ] self.var_picdown.set(self.opt.get("picdown", False)) self.var_picup.set(self.opt.get("picup", False)) - self.var_typedown.set(self.opt.get("typedown", self.lst_typedown[0])) - self.var_typeup.set(self.opt.get("typeup", self.lst_typeup[0])) + + # Gespeicherte Werte übernehmen + saved_val = self.opt.get("typedown", self.lst_typedown[0]) + self.var_typedown.set( + saved_val if saved_val in self.lst_typedown else _("Files") + ) + saved_val = self.opt.get("typeup", self.lst_typeup[0]) + self.var_typeup.set( + saved_val if saved_val in self.lst_typeup else _("Files") + ) r = 0 lbl = tkinter.Label(prog) - lbl["text"] = "PLC Programm herunterladen als:" + lbl["text"] = _("Download PLC program as:") lbl.grid(column=0, row=r, **cpadw) opt = tkinter.OptionMenu( prog, self.var_typedown, *self.lst_typedown, @@ -106,17 +125,17 @@ class RevPiProgram(tkinter.Frame): r = 1 self.ckb_picdown = tkinter.Checkbutton(prog) - self.ckb_picdown["text"] = "inkl. piCtory Konfiguration" + self.ckb_picdown["text"] = _("include piCtory configuration") self.ckb_picdown["variable"] = self.var_picdown self.ckb_picdown.grid(column=0, row=r, **cpadw) btn = tkinter.Button(prog) btn["command"] = self.plcdownload - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=r, **cpad) r = 2 lbl = tkinter.Label(prog) - lbl["text"] = "PLC Programm hochladen als:" + lbl["text"] = _("Upload PLC program as:") lbl.grid(column=0, row=r, **cpadw) opt = tkinter.OptionMenu( prog, self.var_typeup, *self.lst_typeup, @@ -128,74 +147,74 @@ class RevPiProgram(tkinter.Frame): r = 3 ckb = tkinter.Checkbutton(prog) ckb["state"] = self.xmlstate - ckb["text"] = "vorher alles im Uploadverzeichnis löschen" + ckb["text"] = _("clean upload folder before upload") ckb["variable"] = self.var_cleanup ckb.grid(column=0, row=r, columnspan=2, **cpadw) r = 4 self.ckb_picup = tkinter.Checkbutton(prog) self.ckb_picup["state"] = self.xmlstate - self.ckb_picup["text"] = "enthält piCtory Konfiguration" + self.ckb_picup["text"] = _("includes piCtory configuration") self.ckb_picup["variable"] = self.var_picup self.ckb_picup.grid(column=0, row=r, **cpadw) btn = tkinter.Button(prog) btn["command"] = self.plcupload btn["state"] = self.xmlstate - btn["text"] = "Upload" + btn["text"] = _("Upload") btn.grid(column=1, row=r, **cpad) # Gruppe piCtory picto = tkinter.LabelFrame(self) picto.columnconfigure(0, weight=1) - picto["text"] = "piCtory Konfiguration" + picto["text"] = _("piCtory configuration") picto.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(picto) - lbl["text"] = "piCtory Konfiguration herunterladen" + lbl["text"] = _("Download piCtory configuration") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(picto) btn["command"] = self.getpictoryrsc - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=0, **cpad) lbl = tkinter.Label(picto) - lbl["text"] = "piCtory Konfiguration hochladen" + lbl["text"] = _("Upload piCtory configuration") lbl.grid(column=0, row=1, **cpadw) btn = tkinter.Button(picto) btn["command"] = self.setpictoryrsc btn["state"] = self.xmlstate - btn["text"] = "Upload" + btn["text"] = _("Upload") btn.grid(column=1, row=1, **cpad) # Gruppe ProcImg proc = tkinter.LabelFrame(self) proc.columnconfigure(0, weight=1) - proc["text"] = "piControl0 Prozessabbild" + proc["text"] = _("piControl0 prozess image") proc.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(proc) - lbl["text"] = "Prozessabbild-Dump herunterladen" + lbl["text"] = _("Download process image dump") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(proc) btn["command"] = self.getprocimg - btn["text"] = "Download" + btn["text"] = _("Download") btn.grid(column=1, row=0, **cpad) # Gruppe piControlReset picon = tkinter.LabelFrame(self) picon.columnconfigure(0, weight=1) - picon["text"] = "piControl Reset" + picon["text"] = _("Reset piControl") picon.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(picon) - lbl["text"] = "piControlReset ausführen" + lbl["text"] = _("Execute piControlReset") lbl.grid(column=0, row=0, **cpadw) btn = tkinter.Button(picon) btn["command"] = self.picontrolreset - btn["text"] = "ausführen" + btn["text"] = _("execute") btn.grid(column=1, row=0, **cpad) # Beendenbutton btn = tkinter.Button(self) btn["command"] = self.master.destroy - btn["text"] = "Beenden" + btn["text"] = _("Exit") btn.grid() def _evt_optdown(self, text=""): @@ -275,25 +294,23 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("getpictoryrsc_dir", ""), initialfile=self.revpi + ".rsc", - filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) + filetypes=((_("piCtory Config"), "*.rsc"), (_("All files"), "*.*")) ) if fh is not None: try: fh.write(self.xmlcli.get_pictoryrsc().data) except: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert " - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name) @@ -306,25 +323,23 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("getprocimg_dir", ""), initialfile=self.revpi + ".img", - filetypes=(("Imagefiles", "*.img"), ("All Files", "*.*")) + filetypes=((_("Imagefiles"), "*.img"), (_("All files"), "*.*")) ) if fh is not None: try: fh.write(self.xmlcli.get_procimg().data) except: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert" - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern self.opt["getprocimg_dir"] = os.path.dirname(fh.name) @@ -337,19 +352,23 @@ class RevPiProgram(tkinter.Frame): if filename is None: fh = tkfd.askopenfile( mode="rb", parent=self.master, - title="piCtory Datei öffnen...", + title=_("Open piCtory file..."), initialdir=self.opt.get("setpictoryrsc_dir", ""), initialfile=self.revpi + ".rsc", - filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) + filetypes=( + (_("piCtory config"), "*.rsc"), (_("All files"), "*.*") + ) ) else: fh = open(filename, "rb") if fh is not None: ask = tkmsg.askyesno( - parent=self.master, title="Frage", - message="Soll nach dem Hochladen der piCtory Konfiguration " - "ein Reset am piControl Treiber durchgeführt werden?" + parent=self.master, title=_("Question"), + message=_( + "Should the piControl driver be reset after " + "uploading the piCtory configuration?" + ) ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) @@ -357,52 +376,66 @@ class RevPiProgram(tkinter.Frame): if ec == 0: if ask: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung der piCtory Konfiguration " - "und der Reset von piControl wurden erfolgreich " - "ausgeführt") + parent=self.master, title=_("Success"), + message=_( + "The transfer of the piCtory configuration " + "and the reset of piControl have been " + "successfully executed" + ) + ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung der piCtory Konfiguration " - "wurde erfolgreich ausgeführt") + parent=self.master, title=_("Success"), + message=_( + "The piCtory configuration was " + "successfully transferred" + ) + ) # Einstellungen speichern self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self._savedefaults() elif ec < 0: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die piCtory Konfiguration konnte auf dem " - "Revolution Pi nicht geschrieben werden.") + parent=self.master, title=_("Error"), + message=_( + "The piCtory configuration could not be " + "written on the Revolution Pi." + ) + ) elif ec > 0: tkmsg.showwarning( - parent=self.master, title="Warnung", - message="Die piCtroy Konfiguration wurde erfolgreich " - "gespeichert. \nBeim piControl Reset trat allerdings ein " - "Fehler auf!") + parent=self.master, title=_("Warning"), + message=_( + "The piCtroy configuration has been saved " + "successfully. \nAn error occurred on piControl reset!" + ) + ) fh.close() def picontrolreset(self): u"""Fürt ein Reset der piBridge durch.""" ask = tkmsg.askyesno( - parent=self.master, title="Frage...", - message="Soll piControlReset wirklich durchgeführt werden? \n" - "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" + parent=self.master, title=_("Question"), + message=_( + "Are you sure to reset piControl? \nThe process image " + "and the piBridge are interrupted !!!" + ) ) if ask: ec = self.xmlcli.resetpicontrol() if ec == 0: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="piControlReset erfolgreich durchgeführt" + parent=self.master, title=_("Success"), + message=_("piControlReset executed successfully") ) else: tkmsg.showerror( - parten=self.master, title="Fehler", - message="piControlReset konnte nicht erfolgreich " - "durchgeführt werden" + parten=self.master, title=_("Error"), + message=_( + "piControl reset could not be executed successfully" + ) ) def plcdownload(self): @@ -415,7 +448,7 @@ class RevPiProgram(tkinter.Frame): # Ordner dirselect = tkfd.askdirectory( parent=self.master, - title="Verzeichnis zum Ablegen", + title=_("Directory to save"), mustexist=False, initialdir=self.opt.get("plcdownload_dir", self.revpi) ) @@ -428,10 +461,12 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("plcdownload_file", ""), initialfile=self.revpi + ".zip", - filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) + filetypes=( + (_("Zip archive"), "*.zip"), (_("All files"), "*.*") + ) ) elif tdown == 2: @@ -439,10 +474,12 @@ class RevPiProgram(tkinter.Frame): fh = tkfd.asksaveasfile( mode="wb", parent=self.master, confirmoverwrite=True, - title="Speichern als...", + title=_("Save as..."), initialdir=self.opt.get("plcdownload_file", ""), initialfile=self.revpi + ".tar.gz", - filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) + filetypes=( + (_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*") + ) ) if fh is not None: @@ -480,15 +517,13 @@ class RevPiProgram(tkinter.Frame): except: raise tkmsg.showerror( - parent=self.master, title="Fehler", - message="Datei konnte nicht geladen und gespeichert " - "werden!" + parent=self.master, title=_("Error"), + message=_("Could not load and save file!") ) else: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Datei erfolgreich vom Revolution Pi geladen " - "und gespeichert.", + parent=self.master, title=_("Success"), + message=_("File successfully loaded and saved.") ) # Einstellungen speichern @@ -509,9 +544,9 @@ class RevPiProgram(tkinter.Frame): # Datei fileselect = tkfd.askopenfilenames( parent=self.master, - title="Python Programm übertragen...", + title="Upload Python program...", initialdir=self.opt.get("plcupload_dir", ""), - filetypes=(("Python", "*.py"), ("All Files", "*.*")) + filetypes=(("Python", "*.py"), (_("All files"), "*.*")) ) if type(fileselect) == tuple and len(fileselect) > 0: for file in fileselect: @@ -521,7 +556,7 @@ class RevPiProgram(tkinter.Frame): # Ordner dirselect = tkfd.askdirectory( parent=self.master, - title="Verzeichnis zum Hochladen", + title=_("Folder to upload"), mustexist=True, initialdir=self.opt.get("plcupload_dir", self.revpi) ) @@ -532,10 +567,12 @@ class RevPiProgram(tkinter.Frame): # Zip fileselect = tkfd.askopenfilename( parent=self.master, - title="Zip-Archive übertragen...", + title=_("Upload Zip archive..."), initialdir=self.opt.get("plcupload_file", ""), initialfile=self.revpi + ".zip", - filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) + filetypes=( + (_("Zip archive"), "*.zip"), (_("All files"), "*.*") + ) ) if type(fileselect) == str and fileselect != "": # Zipdatei prüfen @@ -550,18 +587,21 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die angegebene Datei ist kein ZIP-Archiv.") + parent=self.master, title=_("Error"), + message=_("The specified file is not a ZIP archive.") + ) return False elif tup == 3: # TarGz fileselect = tkfd.askopenfilename( parent=self.master, - title="TarGz-Archiv übertragen...", + title=_("Upload TarGz archiv..."), initialdir=self.opt.get("plcupload_file", ""), initialfile=self.revpi + ".tar.gz", - filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) + filetypes=( + (_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*") + ) ) if type(fileselect) == str and fileselect != "": @@ -577,8 +617,9 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Die angegebene Datei ist kein TAR-Archiv.") + parent=self.master, title=_("Error"), + message=_("The specified file is not a TAR archive.") + ) return False # Wenn keine Dateien gewählt @@ -588,9 +629,12 @@ class RevPiProgram(tkinter.Frame): # Vor Übertragung aufräumen wenn ausgewählt if self.var_cleanup.get() and not self.xmlcli.plcuploadclean(): tkmsg.showerror( - parent=self.masger, title="Fehler", - message="Beim Löschen der Dateien auf dem Revolution Pi ist " - "ein Fehler aufgetreten.") + parent=self.masger, title=_("Error"), + message=_( + "There was an error deleting the files on the " + "Revolution Pi." + ) + ) return False # Flag setzen, weil ab hier Veränderungen existieren @@ -625,17 +669,21 @@ class RevPiProgram(tkinter.Frame): if ec == 0: tkmsg.showinfo( - parent=self.master, title="Erfolgreich", - message="Die Übertragung war erfolgreich.") + parent=self.master, title=_("Success"), + message=_("The transfer was successful.") + ) if self.var_picup.get(): if rscfile is not None: self.setpictoryrsc(rscfile) else: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Es wurde im Archiv keine piCtory " - "Konfiguration gefunden") + parent=self.master, title=_("Error"), + message=_( + "There is no piCtory configuration in this " + "archive." + ) + ) # Einstellungen speichern if tup == 0: @@ -651,14 +699,18 @@ class RevPiProgram(tkinter.Frame): elif ec == -1: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Der Revoluton Pi konnte Teile der Übertragung nicht " - "verarbeiten.") + parent=self.master, title=_("Error"), + message=_( + "The Revolution Pi could not process some parts of the " + "transmission." + ) + ) elif ec == -2: tkmsg.showerror( - parent=self.master, title="Fehler", - message="Bei der Übertragung traten Fehler auf") + parent=self.master, title=_("Error"), + message=_("Errors occurred during transmission") + ) # Temp-Dir aufräumen if dirtmp is not None: diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index de8cfb5..dd131cf 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -13,29 +13,15 @@ import revpioption import revpiplclist import revpiprogram import socket -import sys import tkinter import tkinter.messagebox as tkmsg from functools import partial -from os.path import dirname -from os.path import join as pathjoin +from mytools import addroot, gettrans from xmlrpc.client import ServerProxy -def addroot(filename): - u"""Hängt root-dir der Anwendung vor Dateinamen. - - Je nach Ausführungsart der Anwendung muss das root-dir über - andere Arten abgerufen werden. - - @param filename: Datei oder Ordnername - @returns: root dir - - """ - if getattr(sys, "frozen", False): - return pathjoin(dirname(sys.executable), filename) - else: - return pathjoin(dirname(__file__), filename) +# Übersetzung laden +_ = gettrans() class RevPiPyControl(tkinter.Frame): @@ -105,10 +91,10 @@ class RevPiPyControl(tkinter.Frame): self.master.config(menu=self.mbar) menu1 = tkinter.Menu(self.mbar, tearoff=False) - menu1.add_command(label="Connections...", command=self.plclist) + menu1.add_command(label=_("Connections..."), command=self.plclist) menu1.add_separator() - menu1.add_command(label="Exit", command=self.master.destroy) - self.mbar.add_cascade(label="Main", menu=menu1) + menu1.add_command(label=_("Exit"), command=self.master.destroy) + self.mbar.add_cascade(label=_("Main"), menu=menu1) self._fillmbar() self._fillconnbar() @@ -119,22 +105,22 @@ class RevPiPyControl(tkinter.Frame): self.txt_connect.pack(fill="x") self.btn_plcstart = tkinter.Button(self) - self.btn_plcstart["text"] = "PLC Start" + self.btn_plcstart["text"] = _("PLC start") self.btn_plcstart["command"] = self.plcstart self.btn_plcstart.pack(fill="x") self.btn_plcstop = tkinter.Button(self) - self.btn_plcstop["text"] = "PLC Stop" + self.btn_plcstop["text"] = _("PLC stop") self.btn_plcstop["command"] = self.plcstop self.btn_plcstop.pack(fill="x") self.btn_plcrestart = tkinter.Button(self) - self.btn_plcrestart["text"] = "PLC Restart" + self.btn_plcrestart["text"] = _("PLC restart") self.btn_plcrestart["command"] = self.plcrestart self.btn_plcrestart.pack(fill="x") self.btn_plclogs = tkinter.Button(self) - self.btn_plclogs["text"] = "PLC Logs" + self.btn_plclogs["text"] = _("PLC logs") self.btn_plclogs["command"] = self.plclogs self.btn_plclogs.pack(fill="x") @@ -145,7 +131,7 @@ class RevPiPyControl(tkinter.Frame): self.txt_status.pack(fill="x") self.btn_debug = tkinter.Button(self) - self.btn_debug["text"] = "PLC Debugmodus" + self.btn_debug["text"] = _("PLC watch mode") self.btn_debug["command"] = self.plcdebug self.btn_debug.pack(fill="x") @@ -162,20 +148,20 @@ class RevPiPyControl(tkinter.Frame): # PLC Menü self.mplc = tkinter.Menu(self.mbar, tearoff=False) self.mplc.add_command( - label="PLC log...", command=self.plclogs) + label=_("PLC log..."), command=self.plclogs) self.mplc.add_command( - label="PLC options...", command=self.plcoptions) + label=_("PLC options..."), command=self.plcoptions) self.mplc.add_command( - label="PLC program...", command=self.plcprogram) + label=_("PLC program..."), command=self.plcprogram) self.mplc.add_separator() self.mplc.add_command( - label="Disconnect", command=self.serverdisconnect) + label=_("Disconnect"), command=self.serverdisconnect) self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") # Connection Menü self.mconn = tkinter.Menu(self.mbar, tearoff=False) - self.mbar.add_cascade(label="Connect", menu=self.mconn) + self.mbar.add_cascade(label=_("Connect"), menu=self.mconn) def _opt_conn(self, text): socket.setdefaulttimeout(2) @@ -208,23 +194,33 @@ class RevPiPyControl(tkinter.Frame): u"""Baut den Debugframe und packt ihn.""" self.btn_debug["state"] = "disabled" - # Debugfenster laden - if self.debugframe is None: - self.debugframe = revpicheckclient.RevPiCheckClient( - self, self.cli, self.xmlmode + if "psstart" not in self.xmlfuncs: + tkmsg.showwarning( + parent=self.master, title=_("Warning"), + message=_( + "The watch mode ist not supported in version {} " + "of RevPiPyLoad on your RevPi! You need at least version " + "0.4.0." + ).format(self.cli.version()) ) - - # Show/Hide wechseln - if self.debugframe.winfo_viewable(): - self.debugframe.hideallwindows() - self.debugframe.autorw.set(False) - self.debugframe.toggleauto() - self.debugframe.dowrite.set(False) - self.debugframe.pack_forget() else: - self.debugframe.pack(fill="y") + # Debugfenster laden + if self.debugframe is None: + self.debugframe = revpicheckclient.RevPiCheckClient( + self, self.cli, self.xmlmode + ) - self.btn_debug["state"] = "normal" + # Show/Hide wechseln + if self.debugframe.winfo_viewable(): + self.debugframe.hideallwindows() + self.debugframe.autorw.set(False) + self.debugframe.toggleauto() + self.debugframe.dowrite.set(False) + self.debugframe.pack_forget() + else: + self.debugframe.pack(fill="y") + + self.btn_debug["state"] = "normal" def plclist(self): u"""Öffnet das Fenster für die Verbindungen.""" @@ -249,8 +245,10 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", - message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " - "genug eingestellt, um diesen Dialog zu verwenden!" + message=_( + "XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog" + ) ) else: win = tkinter.Toplevel(self) @@ -266,8 +264,10 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( parent=self.master, title="Warnung", - message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " - "genug eingestellt, um diesen Dialog zu verwenden!" + message=_( + "XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog" + ) ) else: win = tkinter.Toplevel(self) @@ -302,20 +302,20 @@ class RevPiPyControl(tkinter.Frame): def servererror(self): u"""Setzt alles zurück für neue Verbindungen.""" self.serverdisconnect() - tkmsg.showerror("Fehler", "Server ist nicht erreichbar!") + tkmsg.showerror(_("Fehler"), _("Server ist nicht erreichbar!")) def tmr_plcrunning(self): self._btnstate() if self.cli is None: self.txt_status["readonlybackground"] = "lightblue" - self.var_status.set("NOT CONNECTED") + self.var_status.set(_("NOT CONNECTED")) else: try: plcec = self.cli.plcexitcode() except: self.errcount += 1 if self.errcount >= 5: - self.var_status.set("SERVER ERROR") + self.var_status.set(_("SERVER ERROR")) self.servererror() else: self.errcount = 0 @@ -323,15 +323,17 @@ class RevPiPyControl(tkinter.Frame): "green" if plcec == -1 else "red" if plcec == -1: - plcec = "RUNNING" + plcec = _("RUNNING") elif plcec == -2: - plcec = "FILE NOT FOUND" + plcec = _("FILE NOT FOUND") + elif plcec == -3: + plcec = _("NOT RUNNING (NO STATUS)") elif plcec == -9: - plcec = "PROGRAM KILLED" + plcec = _("PROGRAM KILLED") elif plcec == -15: - plcec = "PROGRAMS TERMED" + plcec = _("PROGRAM TERMED") elif plcec == 0: - plcec = "NOT RUNNING" + plcec = _("NOT RUNNING") self.var_status.set(plcec) self.master.after(1000, self.tmr_plcrunning) From 624b6f697210297147956e3fa23c37b60725cba9 Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 29 Jun 2017 12:48:22 +0200 Subject: [PATCH 04/13] RevPiPlcList vor Schlie?en sch?tzen Quelltext f?r ?bersetzung angepasst ?bersetzung mit poedit durchgef?hrt --- .../locale/de/LC_MESSAGES/revpipycontrol.po | 551 ++++++++++++++++++ revpipycontrol/mytools.py | 2 +- revpipycontrol/revpicheckclient.py | 18 +- revpipycontrol/revpilogfile.py | 14 +- revpipycontrol/revpioption.py | 68 ++- revpipycontrol/revpiplclist.py | 43 +- revpipycontrol/revpiprogram.py | 13 +- revpipycontrol/revpipycontrol.py | 36 +- 8 files changed, 663 insertions(+), 82 deletions(-) create mode 100644 revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po new file mode 100644 index 0000000..6b325a0 --- /dev/null +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -0,0 +1,551 @@ +msgid "" +msgstr "" +"Project-Id-Version: RevPiPyControl 0.4.0\n" +"POT-Creation-Date: 2017-06-29 12:39+0200\n" +"PO-Revision-Date: 2017-06-29 12:39+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.7.1\n" +"X-Poedit-Basepath: ../../..\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-SearchPath-0: .\n" + +#: revpicheckclient.py:143 +msgid "Devices of RevPi" +msgstr "Devices vom RevPi" + +#: revpicheckclient.py:175 +msgid "Control" +msgstr "Kontrolle" + +#: revpicheckclient.py:179 +msgid "Read all IOs" +msgstr "IOs aktualisieren" + +#: revpicheckclient.py:184 +msgid "Read just Inputs" +msgstr "Inputs lesen" + +#: revpicheckclient.py:189 +msgid "Write Outputs" +msgstr "Outputs schreiben" + +#: revpicheckclient.py:195 +msgid "Autorefresh values" +msgstr "Aktualisiere automatisch" + +#: revpicheckclient.py:201 +msgid "Write values to RevPi" +msgstr "Schreibe Werte auf RevPi" + +#: revpilogfile.py:27 +msgid "RevPi Python PLC Logs" +msgstr "RevPi Python PLC Logdaten" + +#: revpilogfile.py:40 +msgid "RevPiPyLoad - Logfile" +msgstr "RevPiPyLoad - Logdatei" + +#: revpilogfile.py:44 revpilogfile.py:59 +msgid "Clear screen" +msgstr "Leere Ansicht" + +#: revpilogfile.py:55 +msgid "Python PLC program - Logfile" +msgstr "Python PLC Programm - Logdatei" + +#: revpioption.py:33 +msgid "RevPi Python PLC Options" +msgstr "RevPi Python PLC Einstellungen" + +#: revpioption.py:41 +msgid "Start / Stop behavior" +msgstr "Start / Stop Verhalten" + +#: revpioption.py:50 +msgid "Start program automatically" +msgstr "Starte Programm automatisch" + +#: revpioption.py:56 +msgid "Restart program after exit" +msgstr "Starte Programm nach Beenden neu" + +#: revpioption.py:63 +msgid "" +"Set process image to NULL if program\n" +"terminates successfully" +msgstr "" +"\"Prozessabbild auf NULL setzen, wenn Programm\n" +"\"erfolgreich beendet wird\"" + +#: revpioption.py:70 +msgid "" +"Set process image to NULL if program\n" +"terminates with errors" +msgstr "" +"Prozessabbild auf NULL setzen, wenn Programm\n" +"fehlerhaft beendet wird" + +#: revpioption.py:77 +msgid "PLC program" +msgstr "PLC Programm" + +#: revpioption.py:88 +msgid "Python version" +msgstr "Python Version" + +#: revpioption.py:105 +msgid "Python PLC program name" +msgstr "Python PLC Programmname" + +#: revpioption.py:117 +msgid "Program arguments" +msgstr "Programmargumente" + +#: revpioption.py:126 +msgid "Use RevPi as PLC-Slave" +msgstr "RevPi als PLC-Slave verwenden" + +#: revpioption.py:133 +msgid "XML-RPC server" +msgstr "XML-RPC Server" + +#: revpioption.py:145 +msgid "Activate XML-RPC server on RevPi" +msgstr "Aktiviere XML-RPC Server auf RevPi" + +#: revpioption.py:153 +msgid "" +"Allow download of piCtory configuration and\n" +"PLC programm" +msgstr "" +"Download von piCtroy Konfiguration und\n" +"PLC Programm zulassen" + +#: revpioption.py:160 +msgid "" +"Allow upload of piCtory configuration and\n" +"PLC programm" +msgstr "" +"Hochladen von piCtroy Konfiguration und\n" +"PLC Programm zulassen" + +#: revpioption.py:165 +msgid "XML-RPC server port" +msgstr "XML-RPC Serverport" + +#: revpioption.py:179 revpiplclist.py:112 +msgid "Save" +msgstr "Speichern" + +#: revpioption.py:184 revpiplclist.py:115 +msgid "Close" +msgstr "Schließen" + +#: revpioption.py:230 revpioption.py:254 revpiplclist.py:151 +#: revpiplclist.py:176 revpiprogram.py:367 revpiprogram.py:420 +msgid "Question" +msgstr "Frage" + +#: revpioption.py:231 +msgid "" +"The settings are now saved on the Revolution Pi. \n" +"\n" +"Should the new settings take effect immediately? \n" +"This means a restart of the service and the PLC program!" +msgstr "" +"Die Einstellungen werden jetzt auf dem Revolution Pi gespeichert.\n" +"\n" +"Sollen die neuen Einstellungen sofort in Kraft treten?\n" +"Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" + +#: revpioption.py:239 revpiplclist.py:191 revpiprogram.py:65 +msgid "Information" +msgstr "Information" + +#: revpioption.py:240 +msgid "Settings saved" +msgstr "Einstellungen gespeichert" + +#: revpioption.py:245 revpiplclist.py:199 revpiprogram.py:307 +#: revpiprogram.py:336 revpiprogram.py:400 revpiprogram.py:435 +#: revpiprogram.py:520 revpiprogram.py:590 revpiprogram.py:620 +#: revpiprogram.py:632 revpiprogram.py:681 revpiprogram.py:702 +#: revpiprogram.py:711 revpipycontrol.py:308 +msgid "Error" +msgstr "Fehler" + +#: revpioption.py:246 +msgid "The settings could not be saved. This can happen if values are wrong!" +msgstr "" +"Die Einstellungen konnten nicht gesichert werden. Dies kann passieren, wenn " +"Werte falsch sind!" + +#: revpioption.py:255 +msgid "" +"Are you sure you want to deactivate the XML-RPC server? You will NOT be able " +"to access the Revolution Pi with this program." +msgstr "" +"Soll der XML-RPC Server wirklich beendet werden? Sie können dann NICHT mehr " +"mit diesem Programm auf den Revolution Pi zugreifen." + +#: revpiplclist.py:54 +msgid "RevPi Python PLC connections" +msgstr "RevPi Python PLC Verbindungen" + +#: revpiplclist.py:75 +msgid "Name" +msgstr "Name" + +#: revpiplclist.py:82 +msgid "IP address" +msgstr "IP Adresse" + +#: revpiplclist.py:90 +msgid "Port" +msgstr "Port" + +#: revpiplclist.py:99 +msgid "New" +msgstr "Neu" + +#: revpiplclist.py:102 +msgid "Apply" +msgstr "Übernehmen" + +#: revpiplclist.py:106 +msgid "Remove" +msgstr "Entfernen" + +#: revpiplclist.py:152 +msgid "" +"Do you really want to quit? \n" +"Unsaved changes will be lost" +msgstr "" +"Wollen Sie wirklich beenden? \n" +"Nicht gespeicherte Änderungen gehen verloren" + +#: revpiplclist.py:177 +msgid "Do you really want to delete the selected connection '{}'" +msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" + +#: revpiplclist.py:192 +msgid "" +"Successfully saved. \n" +"Do you want to close this window?" +msgstr "" +"Verbindungen erfolgreich gespeichert. \n" +"Möchten Sie dieses Fenster jetzt schließen?" + +#: revpiplclist.py:200 +msgid "Failed to save connections" +msgstr "Verbindungen konnten nicht gespeichert werden" + +#: revpiprogram.py:67 +msgid "" +"A PLC program has been uploaded. Please check the PLC options to see if the " +"correct program is specified as the start program." +msgstr "" +"Ein PLC Programm wurde hochgeladen. Bitte prüfen Sie die PLC Optionen, ob " +"dort das richtige Programm als Startprogramm angegeben ist." + +#: revpiprogram.py:75 +msgid "RevPi Python PLC program" +msgstr "RevPi Python PLC Programm" + +#: revpiprogram.py:89 +msgid "PLC python program" +msgstr "PLC Python Programm" + +#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:109 +#: revpiprogram.py:113 +msgid "Files" +msgstr "Dateien" + +#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:468 +#: revpiprogram.py:574 +msgid "Zip archive" +msgstr "Zip Archiv" + +#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:481 +#: revpiprogram.py:603 +msgid "TGZ archive" +msgstr "TGZ Archiv" + +#: revpiprogram.py:101 +msgid "Folder" +msgstr "Verzeichnis" + +#: revpiprogram.py:118 +msgid "Download PLC program as:" +msgstr "PLC Programm herunterladen als:" + +#: revpiprogram.py:128 +msgid "include piCtory configuration" +msgstr "inkl. piCtory Konfiguration" + +#: revpiprogram.py:133 revpiprogram.py:177 revpiprogram.py:198 +msgid "Download" +msgstr "Herunterladen" + +#: revpiprogram.py:138 +msgid "Upload PLC program as:" +msgstr "PLC Programm hochladen als:" + +#: revpiprogram.py:150 +msgid "clean upload folder before upload" +msgstr "vorher Inhalt im Uploadverzeichnis löschen" + +#: revpiprogram.py:157 +msgid "includes piCtory configuration" +msgstr "enthält piCtory Konfiguration" + +#: revpiprogram.py:163 revpiprogram.py:185 +msgid "Upload" +msgstr "Hochladen" + +#: revpiprogram.py:169 +msgid "piCtory configuration" +msgstr "piCtory Konfiguration" + +#: revpiprogram.py:173 +msgid "Download piCtory configuration" +msgstr "piCtory Konfiguration herunterladen" + +#: revpiprogram.py:180 +msgid "Upload piCtory configuration" +msgstr "piCtory Konfiguration hochladen" + +#: revpiprogram.py:191 +msgid "piControl0 prozess image" +msgstr "piControl0 Prozessabbild" + +#: revpiprogram.py:194 +msgid "Download process image dump" +msgstr "Prozessabbild Dump herunterladen" + +#: revpiprogram.py:204 +msgid "Reset piControl" +msgstr "piControl zurücksetzen" + +#: revpiprogram.py:207 +msgid "Execute piControlReset" +msgstr "piControlReset ausführen" + +#: revpiprogram.py:211 +msgid "execute" +msgstr "ausführen" + +#: revpiprogram.py:217 revpipycontrol.py:96 +msgid "Exit" +msgstr "Beenden" + +#: revpiprogram.py:297 revpiprogram.py:326 revpiprogram.py:464 +#: revpiprogram.py:477 +msgid "Save as..." +msgstr "Speichern unter..." + +#: revpiprogram.py:300 revpiprogram.py:359 +msgid "piCtory config" +msgstr "piCtory Konfiguration" + +#: revpiprogram.py:300 revpiprogram.py:329 revpiprogram.py:359 +#: revpiprogram.py:468 revpiprogram.py:481 revpiprogram.py:549 +#: revpiprogram.py:574 revpiprogram.py:603 +msgid "All files" +msgstr "Alle Dateien" + +#: revpiprogram.py:308 revpiprogram.py:337 revpiprogram.py:521 +msgid "Could not load and save file!" +msgstr "Datei konnte nicht geladen und gespeichert werden!" + +#: revpiprogram.py:312 revpiprogram.py:341 revpiprogram.py:379 +#: revpiprogram.py:388 revpiprogram.py:430 revpiprogram.py:525 +#: revpiprogram.py:672 +msgid "Success" +msgstr "Erfolgreich" + +#: revpiprogram.py:313 revpiprogram.py:342 revpiprogram.py:526 +msgid "File successfully loaded and saved." +msgstr "Dateien erfolgreich übertragen und gespeichert." + +#: revpiprogram.py:329 +msgid "Imagefiles" +msgstr "Image Dateien" + +#: revpiprogram.py:355 +msgid "Open piCtory file..." +msgstr "piCtory Datei öffnen" + +#: revpiprogram.py:369 +msgid "" +"Should the piControl driver be reset after uploading the piCtory " +"configuration?" +msgstr "" +"Soll nach dem Hochladen der piCtory Konfiguration ein Reset am piControl " +"Treiber durchgeführt werden?" + +#: revpiprogram.py:381 +msgid "" +"The transfer of the piCtory configuration and the reset of piControl have " +"been successfully executed" +msgstr "" +"Die Übertragung der piCtory Konfiguration und der Reset von piControl wurden " +"erfolgreich ausgeführt" + +#: revpiprogram.py:390 +msgid "The piCtory configuration was successfully transferred" +msgstr "Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt" + +#: revpiprogram.py:402 +msgid "The piCtory configuration could not be written on the Revolution Pi." +msgstr "" +"Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " +"werden." + +#: revpiprogram.py:408 revpipycontrol.py:199 revpipycontrol.py:247 +#: revpipycontrol.py:267 +msgid "Warning" +msgstr "Warnung" + +#: revpiprogram.py:410 +msgid "" +"The piCtroy configuration has been saved successfully. \n" +"An error occurred on piControl reset!" +msgstr "" +"Die piCtroy Konfiguration wurde erfolgreich gespeichert. \n" +"Beim piControl Reset trat allerdings ein Fehler auf!" + +#: revpiprogram.py:422 +msgid "" +"Are you sure to reset piControl? \n" +"The process image and the piBridge are interrupted !!!" +msgstr "" +"Soll piControlReset wirklich durchgeführt werden? \n" +"Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" + +#: revpiprogram.py:431 +msgid "piControlReset executed successfully" +msgstr "piControl Reset war erfolgreich" + +#: revpiprogram.py:437 +msgid "piControl reset could not be executed successfully" +msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" + +#: revpiprogram.py:451 +msgid "Directory to save" +msgstr "Verzeichnis zum Ablegen" + +#: revpiprogram.py:559 +msgid "Folder to upload" +msgstr "Verzeichnis zum Hochladen" + +#: revpiprogram.py:570 +msgid "Upload Zip archive..." +msgstr "Zip Archiv hochladen..." + +#: revpiprogram.py:591 +msgid "The specified file is not a ZIP archive." +msgstr "Die angegebene Datei ist kein ZIP Archiv" + +#: revpiprogram.py:599 +msgid "Upload TarGz archiv..." +msgstr "TarGz Archiv hochladen..." + +#: revpiprogram.py:621 +msgid "The specified file is not a TAR archive." +msgstr "Die angegebene Datei ist kein TAR Archiv." + +#: revpiprogram.py:634 +msgid "There was an error deleting the files on the Revolution Pi." +msgstr "" +"Beim Löschen der Dateien auf dem Revolution Pi ist ein Fehler aufgetreten." + +#: revpiprogram.py:673 +msgid "The transfer was successful." +msgstr "Die Übertragung war erfolgreich." + +#: revpiprogram.py:683 +msgid "There is no piCtory configuration in this archive." +msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." + +#: revpiprogram.py:704 +msgid "The Revolution Pi could not process some parts of the transmission." +msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." + +#: revpiprogram.py:712 +msgid "Errors occurred during transmission" +msgstr "Bei der Übertragung traten Fehler auf" + +#: revpipycontrol.py:94 +msgid "Connections..." +msgstr "Verbindungen..." + +#: revpipycontrol.py:97 +msgid "Main" +msgstr "Datei" + +#: revpipycontrol.py:108 +msgid "PLC start" +msgstr "PLC Start" + +#: revpipycontrol.py:113 +msgid "PLC stop" +msgstr "PLC Stopp" + +#: revpipycontrol.py:118 +msgid "PLC restart" +msgstr "PLC Neustart" + +#: revpipycontrol.py:123 +msgid "PLC logs" +msgstr "PLC Logs" + +#: revpipycontrol.py:134 +msgid "PLC watch mode" +msgstr "PLC watch Modus" + +#: revpipycontrol.py:151 +msgid "PLC log..." +msgstr "PLC Log..." + +#: revpipycontrol.py:153 +msgid "PLC options..." +msgstr "PLC Optionen..." + +#: revpipycontrol.py:155 +msgid "PLC program..." +msgstr "PLC Programm..." + +#: revpipycontrol.py:159 +msgid "Disconnect" +msgstr "Trennen" + +#: revpipycontrol.py:164 +msgid "Connect" +msgstr "Verbinden" + +#: revpipycontrol.py:201 +msgid "" +"The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " +"You need at least version 0.4.0." +msgstr "" +"Die Debug-Funktion wird von der RevPiPyLoad Version {} auf dem RevPi nicht " +"unterstützt! Sie benötigen mindestens Version 0.4.0." + +#: revpipycontrol.py:249 revpipycontrol.py:269 +msgid "" +"XML-RPC access mode in the RevPiPyLoad configuration is to small to access " +"this dialog" +msgstr "" +"Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " +"diesen Dialog zu verwenden!" + +#: revpipycontrol.py:309 +msgid "Can not reach server!" +msgstr "Server ist nicht erreichbar!" diff --git a/revpipycontrol/mytools.py b/revpipycontrol/mytools.py index 858d53a..941b8c2 100644 --- a/revpipycontrol/mytools.py +++ b/revpipycontrol/mytools.py @@ -33,7 +33,7 @@ def gettrans(proglang=None): # Sprache auswählen if proglang is None: # Autodetect Language or switch to static - # proglang = "de" + # proglang = "en" proglang = locale.getdefaultlocale()[0].split('_')[0] # Übersetzungen laden diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index c15c6ad..ca6941a 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -10,8 +10,12 @@ import pickle import tkinter from threading import Lock +from mytools import gettrans from xmlrpc.client import ServerProxy, MultiCall +# Übersetzung laden +_ = gettrans() + class RevPiCheckClient(tkinter.Frame): @@ -136,7 +140,7 @@ class RevPiCheckClient(tkinter.Frame): """Erstellt den Fensterinhalt.""" devgrp = tkinter.LabelFrame(self) - devgrp["text"] = "Devices of RevPi" + devgrp["text"] = _("Devices of RevPi") devgrp.pack(fill="y", side="left") for dev in self.lst_devices: @@ -168,33 +172,33 @@ class RevPiCheckClient(tkinter.Frame): # Steuerungsfunktionen cntgrp = tkinter.LabelFrame(self) - cntgrp["text"] = "Control" + cntgrp["text"] = _("Control") cntgrp.pack(fill="y", side="right") self.btn_refresh = tkinter.Button(cntgrp) - self.btn_refresh["text"] = "Alle IOs lesen" + self.btn_refresh["text"] = _("Read all IOs") self.btn_refresh["command"] = self.refreshvalues self.btn_refresh.pack(fill="x") self.btn_read = tkinter.Button(cntgrp) - self.btn_read["text"] = "Inputs einlesen" + self.btn_read["text"] = _("Read just Inputs") self.btn_read["command"] = self.readvalues self.btn_read.pack(fill="x") self.btn_write = tkinter.Button(cntgrp) - self.btn_write["text"] = "Outputs schreiben" + self.btn_write["text"] = _("Write Outputs") self.btn_write["command"] = self.writevalues self.btn_write.pack(fill="x") check = tkinter.Checkbutton(cntgrp) check["command"] = self.toggleauto - check["text"] = "Autorefresh values" + check["text"] = _("Autorefresh values") check["variable"] = self.autorw check.pack(anchor="w") check = tkinter.Checkbutton(cntgrp) check["state"] = "disabled" if self.xmlmode < 3 else "normal" - check["text"] = "Write values to RevPi" + check["text"] = _("Write values to RevPi") check["variable"] = self.dowrite check.pack(anchor="w") diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 0de9088..060ed49 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -7,6 +7,10 @@ # -*- coding: utf-8 -*- import pickle import tkinter +from mytools import gettrans + +# Übersetzung laden +_ = gettrans() class RevPiLogfile(tkinter.Frame): @@ -20,7 +24,7 @@ class RevPiLogfile(tkinter.Frame): self._createwidgets() def _createwidgets(self): - self.master.wm_title("RevPi Python PLC Logs") + self.master.wm_title(_("RevPi Python PLC Logs")) self.rowconfigure(0, weight=0) self.rowconfigure(1, weight=1) @@ -33,11 +37,11 @@ class RevPiLogfile(tkinter.Frame): # PLC Log self.lblapplog = tkinter.Label(self) - self.lblapplog["text"] = "RevPyPyLoad - Logfile" + self.lblapplog["text"] = _("RevPiPyLoad - Logfile") self.lblapplog.grid(column=0, row=0, sticky="w") self.btnapplog = tkinter.Button(self) self.btnapplog["command"] = self.btn_clearplc - self.btnapplog["text"] = "Clear screen" + self.btnapplog["text"] = _("Clear screen") self.btnapplog.grid(column=1, row=0, sticky="e") self.plclog = tkinter.Text(self) self.plcscr = tkinter.Scrollbar(self) @@ -48,11 +52,11 @@ class RevPiLogfile(tkinter.Frame): # APP Log self.lblapplog = tkinter.Label(self) - self.lblapplog["text"] = "Python PLC program - Logfile" + self.lblapplog["text"] = _("Python PLC program - Logfile") self.lblapplog.grid(column=3, row=0, sticky="w") self.btnapplog = tkinter.Button(self) self.btnapplog["command"] = self.btn_clearapp - self.btnapplog["text"] = "Clear screen" + self.btnapplog["text"] = _("Clear screen") self.btnapplog.grid(column=4, row=0, sticky="e") self.applog = tkinter.Text(self) self.appscr = tkinter.Scrollbar(self) diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 68dce00..23a59f2 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -7,7 +7,10 @@ # -*- coding: utf-8 -*- import tkinter import tkinter.messagebox as tkmsg +from mytools import gettrans +# Übersetzung laden +_ = gettrans() class RevPiOption(tkinter.Frame): @@ -27,7 +30,7 @@ class RevPiOption(tkinter.Frame): self._loadappdata() def _createwidgets(self): - self.master.wm_title("RevPi Python PLC Options") + self.master.wm_title(_("RevPi Python PLC Options")) self.master.wm_resizable(width=False, height=False) cpadw = {"padx": 4, "pady": 2, "sticky": "w"} @@ -35,7 +38,7 @@ class RevPiOption(tkinter.Frame): # Gruppe Start/Stop stst = tkinter.LabelFrame(self) - stst["text"] = "Start / Stopp Verhalten" + stst["text"] = _("Start / Stop behavior") stst.grid(columnspan=2, pady=2, sticky="we") self.var_start = tkinter.BooleanVar(stst) @@ -44,34 +47,34 @@ class RevPiOption(tkinter.Frame): self.var_zerr = tkinter.BooleanVar(stst) ckb_start = tkinter.Checkbutton(stst) - ckb_start["text"] = "Programm automatisch starten" + ckb_start["text"] = _("Start program automatically") ckb_start["state"] = self.xmlstate ckb_start["variable"] = self.var_start ckb_start.grid(**cpadw) ckb_reload = tkinter.Checkbutton(stst) - ckb_reload["text"] = "Programm nach Beenden neu starten" + ckb_reload["text"] = _("Restart program after exit") ckb_reload["state"] = self.xmlstate ckb_reload["variable"] = self.var_reload ckb_reload.grid(**cpadw) ckb_zexit = tkinter.Checkbutton(stst, justify="left") ckb_zexit["state"] = self.xmlstate - ckb_zexit["text"] = "Prozessabbild auf NULL setzen, wenn " \ - "Programm\nerfolgreich beendet wird" + ckb_zexit["text"] = _("Set process image to NULL if program\n" + "terminates successfully") ckb_zexit["variable"] = self.var_zexit ckb_zexit.grid(**cpadw) ckb_zerr = tkinter.Checkbutton(stst, justify="left") ckb_zerr["state"] = self.xmlstate - ckb_zerr["text"] = "Prozessabbild auf NULL setzen, wenn " \ - "Programm\ndurch Absturz beendet wird" + ckb_zerr["text"] = _("Set process image to NULL if program\n" + "terminates with errors") ckb_zerr["variable"] = self.var_zerr ckb_zerr.grid(**cpadw) # Gruppe Programm prog = tkinter.LabelFrame(self) - prog["text"] = "PLC Programm" + prog["text"] = _("PLC program") prog.grid(columnspan=2, pady=2, sticky="we") self.var_pythonver = tkinter.IntVar(prog) @@ -82,7 +85,7 @@ class RevPiOption(tkinter.Frame): self.var_pythonver.set(3) lbl = tkinter.Label(prog) - lbl["text"] = "Python Version" + lbl["text"] = _("Python version") lbl.grid(columnspan=2, row=0, **cpadw) rbn = tkinter.Radiobutton(prog) rbn["state"] = self.xmlstate @@ -99,7 +102,7 @@ class RevPiOption(tkinter.Frame): rbn.grid(column=1, row=1, **cpadw) lbl = tkinter.Label(prog) - lbl["text"] = "Python PLC Programname" + lbl["text"] = _("Python PLC program name") lbl.grid(columnspan=2, **cpadw) lst = self.xmlcli.get_filelist() @@ -111,7 +114,7 @@ class RevPiOption(tkinter.Frame): opt_startpy.grid(columnspan=2, **cpadwe) lbl = tkinter.Label(prog) - lbl["text"] = "Programm Argumente" + lbl["text"] = _("Program arguments") lbl.grid(columnspan=2, **cpadw) txt = tkinter.Entry(prog) @@ -120,14 +123,14 @@ class RevPiOption(tkinter.Frame): ckb_slave = tkinter.Checkbutton(prog, justify="left") ckb_slave["state"] = self.xmlstate - ckb_slave["text"] = "RevPi als PLC-Slave verwenden" + ckb_slave["text"] = _("Use RevPi as PLC-Slave") ckb_slave["state"] = "disabled" ckb_slave["variable"] = self.var_slave ckb_slave.grid(columnspan=2, **cpadw) # Gruppe XMLRPC xmlrpc = tkinter.LabelFrame(self) - xmlrpc["text"] = "XML-RPC Server" + xmlrpc["text"] = _("XML-RPC server") xmlrpc.grid(columnspan=2, pady=2, sticky="we") self.var_xmlon = tkinter.BooleanVar(xmlrpc) @@ -139,7 +142,7 @@ class RevPiOption(tkinter.Frame): ckb_xmlon = tkinter.Checkbutton(xmlrpc) ckb_xmlon["command"] = self.askxmlon ckb_xmlon["state"] = self.xmlstate - ckb_xmlon["text"] = "XML-RPC Server aktiv auf RevPi" + ckb_xmlon["text"] = _("Activate XML-RPC server on RevPi") ckb_xmlon["variable"] = self.var_xmlon ckb_xmlon.grid(**cpadw) @@ -147,19 +150,19 @@ class RevPiOption(tkinter.Frame): self.ckb_xmlmod2["command"] = self.xmlmods self.ckb_xmlmod2["state"] = self.xmlstate self.ckb_xmlmod2["text"] = \ - "Download von piCtory Konfiguration und\nPLC Programm zulassen" + _("Allow download of piCtory configuration and\nPLC programm") self.ckb_xmlmod2["variable"] = self.var_xmlmod2 self.ckb_xmlmod2.grid(**cpadw) self.ckb_xmlmod3 = tkinter.Checkbutton(xmlrpc, justify="left") self.ckb_xmlmod3["state"] = self.xmlstate self.ckb_xmlmod3["text"] = \ - "Upload von piCtory Konfiguration und\nPLC Programm zualssen" + _("Allow upload of piCtory configuration and\nPLC programm") self.ckb_xmlmod3["variable"] = self.var_xmlmod3 self.ckb_xmlmod3.grid(**cpadw) lbl = tkinter.Label(xmlrpc) - lbl["text"] = "XML-RPC Serverport" + lbl["text"] = _("XML-RPC server port") lbl.grid(**cpadw) spb_xmlport = tkinter.Spinbox(xmlrpc) @@ -173,12 +176,12 @@ class RevPiOption(tkinter.Frame): btn_save = tkinter.Button(self) btn_save["command"] = self._setappdata btn_save["state"] = self.xmlstate - btn_save["text"] = "Speichern" + btn_save["text"] = _("Save") btn_save.grid(column=0, row=3) btn_close = tkinter.Button(self) btn_close["command"] = self.master.destroy - btn_close["text"] = "Schließen" + btn_close["text"] = _("Close") btn_close.grid(column=1, row=3) def _loadappdata(self): @@ -224,30 +227,35 @@ class RevPiOption(tkinter.Frame): self.xmlmode = dc["xmlrpc"] ask = tkmsg.askyesnocancel( - "Frage", "Die Einstellungen werden jetzt auf dem Revolution Pi " - "gespeichert. \n\nSollen die neuen Einstellungen sofort in Kraft " - "treten? \nDies bedeutet einen Neustart des Dienstes und des ggf. " - "laufenden PLC-Programms!", parent=self.master + _("Question"), + _("The settings are now saved on the Revolution Pi. \n\n" + "Should the new settings take effect immediately? \nThis " + "means a restart of the service and the PLC program!"), + parent=self.master ) if ask is not None: if self.xmlcli.set_config(dc, ask): tkmsg.showinfo( - "Information", "Einstellungen gespeichert.", + _("Information"), + _("Settings saved"), parent=self.master ) else: tkmsg.showerror( - "Fehler", "Die Einstellungen konnten nicht gesichert" - "werden. Dies kann passieren, wenn Werte falsch sind!", + _("Error"), + _("The settings could not be saved. This can happen if " + "values are wrong!"), parent=self.master ) def askxmlon(self): if not self.var_xmlon.get(): ask = tkmsg.askyesno( - "Frage", "Soll der XML-RPC Server wirklich beendet werden? " - "Sie können dann NICHT mehr mit diesem Programm auf den " - "Revolution Pi zugreifen.", parent=self.master + _("Question"), + _("Are you sure you want to deactivate the XML-RPC server? " + "You will NOT be able to access the Revolution Pi with " + "this program."), + parent=self.master ) if not ask: self.var_xmlon.set(True) diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index db7a039..801b845 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -9,10 +9,14 @@ import os.path import pickle import tkinter import tkinter.messagebox as tkmsg +from mytools import gettrans from os import environ from os import makedirs from sys import platform +# Übersetzungen laden +_ = gettrans() + # Systemwerte if platform == "linux": homedir = environ["HOME"] @@ -47,8 +51,9 @@ class RevPiPlcList(tkinter.Frame): self._loadappdata() def _createwidgets(self): - self.master.wm_title("RevPi Python PLC Connections") + self.master.wm_title(_("RevPi Python PLC connections")) self.master.wm_resizable(width=False, height=False) + self.master.protocol("WM_DELETE_WINDOW", self.evt_btnclose) # Listbox mit vorhandenen Verbindungen self.scr_conn = tkinter.Scrollbar(self) @@ -66,14 +71,14 @@ class RevPiPlcList(tkinter.Frame): self.var_port.set("55123") # Eingabefelder für Adresse und Namen - tkinter.Label(self, text="Name").grid( + tkinter.Label(self, text=_("Name")).grid( column=2, row=0, sticky="wn", padx=5, pady=5) self.txt_name = tkinter.Entry(self, textvariable=self.var_name) self.txt_name.bind("", self.evt_keypress) self.txt_name.grid( column=3, row=0, columnspan=3, sticky="n", padx=5, pady=5) - tkinter.Label(self, text="IP-Adresse").grid( + tkinter.Label(self, text=_("IP address")).grid( column=2, row=1, sticky="wn", padx=5, pady=5 ) self.txt_address = tkinter.Entry(self, textvariable=self.var_address) @@ -81,7 +86,7 @@ class RevPiPlcList(tkinter.Frame): self.txt_address.grid( column=3, row=1, columnspan=3, sticky="n", padx=5, pady=5) - tkinter.Label(self, text="Port").grid( + tkinter.Label(self, text=_("Port")).grid( column=2, row=2, sticky="wn", padx=5, pady=5) self.txt_port = tkinter.Entry(self, textvariable=self.var_port) self.txt_port.bind("", self.evt_keypress) @@ -90,23 +95,23 @@ class RevPiPlcList(tkinter.Frame): # Listenbutton self.btn_new = tkinter.Button( - self, text="Neu", command=self.evt_btnnew) + self, text=_("New"), command=self.evt_btnnew) self.btn_new.grid(column=2, row=3, sticky="s") self.btn_add = tkinter.Button( - self, text="Übernehmen", command=self.evt_btnadd, + self, text=_("Apply"), command=self.evt_btnadd, state="disabled") self.btn_add.grid(column=3, row=3, sticky="s") self.btn_remove = tkinter.Button( - self, text="Entfernen", command=self.evt_btnremove, + self, text=_("Remove"), command=self.evt_btnremove, state="disabled") self.btn_remove.grid(column=4, row=3, sticky="s") # Fensterbuttons self.btn_save = tkinter.Button( - self, text="Speichern", command=self.evt_btnsave) + self, text=_("Save"), command=self.evt_btnsave) self.btn_save.grid(column=3, row=9, sticky="se") self.btn_close = tkinter.Button( - self, text="Schließen", command=self.evt_btnclose) + self, text=_("Close"), command=self.evt_btnclose) self.btn_close.grid(column=4, row=9, sticky="se") def _loadappdata(self): @@ -142,9 +147,10 @@ class RevPiPlcList(tkinter.Frame): def evt_btnclose(self): if self.changes: ask = tkmsg.askyesno( - parent=self.master, title="Frage...", - message="Wollen Sie wirklich beenden?\n" - "Nicht gespeicherte Änderungen gehen verloren", + _("Question"), + _("Do you really want to quit? \nUnsaved changes will " + "be lost"), + parent=self.master ) else: ask = True @@ -166,9 +172,9 @@ class RevPiPlcList(tkinter.Frame): if len(item_index) == 1: item = self.list_conn.get(item_index[0]) ask = tkmsg.askyesno( - "Frage", - "Wollen Sie die Ausgewählte Verbindung '{}' wirklich " - "löschen?".format(item), + _("Question"), + _("Do you really want to delete the selected connection '{}'" + "").format(item), parent=self.master ) if ask: @@ -181,15 +187,16 @@ class RevPiPlcList(tkinter.Frame): def evt_btnsave(self): if self._saveappdata(): ask = tkmsg.askyesno( - "Information", "Verbindungen erfolgreich gespeichert.\n" - "Möchten Sie dieses Fenster jetzt schließen?", + _("Information"), + _("Successfully saved. \nDo you want to close this window?"), parent=self.master ) if ask: self.master.destroy() else: tkmsg.showerror( - "Fehler", "Verbindungen konnten nicht gespeichert werden", + _("Error"), + _("Failed to save connections"), parent=self.master ) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 96d733e..1e6df5e 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -62,17 +62,18 @@ class RevPiProgram(tkinter.Frame): def _checkclose(self): if True or self.uploaded: tkmsg.showinfo( - parent=self.master, title=_("Information"), - message=_( + _("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 ) self.master.destroy() def _createwidgets(self): - self.master.wm_title(_("RevPi python PLC programm")) + self.master.wm_title(_("RevPi Python PLC program")) self.master.wm_resizable(width=False, height=False) self.rowconfigure(0, weight=1) @@ -86,7 +87,7 @@ class RevPiProgram(tkinter.Frame): # Gruppe Programm prog = tkinter.LabelFrame(self) prog.columnconfigure(0, weight=1) - prog["text"] = _("PLC python programm") + prog["text"] = _("PLC python program") prog.grid(columnspan=2, pady=2, sticky="we") # Variablen vorbereiten @@ -297,7 +298,7 @@ class RevPiProgram(tkinter.Frame): title=_("Save as..."), initialdir=self.opt.get("getpictoryrsc_dir", ""), initialfile=self.revpi + ".rsc", - filetypes=((_("piCtory Config"), "*.rsc"), (_("All files"), "*.*")) + filetypes=((_("piCtory config"), "*.rsc"), (_("All files"), "*.*")) ) if fh is not None: try: diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index dd131cf..241b634 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -244,11 +244,12 @@ class RevPiPyControl(tkinter.Frame): u"""Startet das Optionsfenster.""" if self.xmlmode < 2: tkmsg.showwarning( - parent=self.master, title="Warnung", - message=_( + _("Warning"), + _( "XML-RPC access mode in the RevPiPyLoad " "configuration is to small to access this dialog" - ) + ), + parent=self.master ) else: win = tkinter.Toplevel(self) @@ -263,11 +264,12 @@ class RevPiPyControl(tkinter.Frame): u"""Startet das Programmfenster.""" if self.xmlmode < 2: tkmsg.showwarning( - parent=self.master, title="Warnung", - message=_( + _("Warning"), + _( "XML-RPC access mode in the RevPiPyLoad " "configuration is to small to access this dialog" - ) + ), + parent=self.master ) else: win = tkinter.Toplevel(self) @@ -302,20 +304,24 @@ class RevPiPyControl(tkinter.Frame): def servererror(self): u"""Setzt alles zurück für neue Verbindungen.""" self.serverdisconnect() - tkmsg.showerror(_("Fehler"), _("Server ist nicht erreichbar!")) + tkmsg.showerror( + _("Error"), + _("Can not reach server!"), + parent=self.master + ) def tmr_plcrunning(self): self._btnstate() if self.cli is None: self.txt_status["readonlybackground"] = "lightblue" - self.var_status.set(_("NOT CONNECTED")) + self.var_status.set("NOT CONNECTED") else: try: plcec = self.cli.plcexitcode() except: self.errcount += 1 if self.errcount >= 5: - self.var_status.set(_("SERVER ERROR")) + self.var_status.set("SERVER ERROR") self.servererror() else: self.errcount = 0 @@ -323,17 +329,17 @@ class RevPiPyControl(tkinter.Frame): "green" if plcec == -1 else "red" if plcec == -1: - plcec = _("RUNNING") + plcec = "RUNNING" elif plcec == -2: - plcec = _("FILE NOT FOUND") + plcec = "FILE NOT FOUND" elif plcec == -3: - plcec = _("NOT RUNNING (NO STATUS)") + plcec = "NOT RUNNING (NO STATUS)" elif plcec == -9: - plcec = _("PROGRAM KILLED") + plcec = "PROGRAM KILLED" elif plcec == -15: - plcec = _("PROGRAM TERMED") + plcec = "PROGRAM TERMED" elif plcec == 0: - plcec = _("NOT RUNNING") + plcec = "NOT RUNNING" self.var_status.set(plcec) self.master.after(1000, self.tmr_plcrunning) From 1f668b153c539aed9321143281c9c986beb3c699 Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 29 Jun 2017 13:03:39 +0200 Subject: [PATCH 05/13] Codestyle von tkinter.messagebox angepasst --- .../locale/de/LC_MESSAGES/revpipycontrol.po | 154 +++++++++--------- revpipycontrol/revpioption.py | 7 +- revpipycontrol/revpiprogram.py | 149 +++++++++-------- revpipycontrol/revpipycontrol.py | 9 +- 4 files changed, 160 insertions(+), 159 deletions(-) diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 6b325a0..73a88ce 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-29 12:39+0200\n" -"PO-Revision-Date: 2017-06-29 12:39+0200\n" +"POT-Creation-Date: 2017-06-29 12:59+0200\n" +"PO-Revision-Date: 2017-06-29 13:03+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -139,16 +139,16 @@ msgstr "" msgid "XML-RPC server port" msgstr "XML-RPC Serverport" -#: revpioption.py:179 revpiplclist.py:112 +#: revpioption.py:179 revpiplclist.py:111 msgid "Save" msgstr "Speichern" -#: revpioption.py:184 revpiplclist.py:115 +#: revpioption.py:184 revpiplclist.py:114 msgid "Close" msgstr "Schließen" -#: revpioption.py:230 revpioption.py:254 revpiplclist.py:151 -#: revpiplclist.py:176 revpiprogram.py:367 revpiprogram.py:420 +#: revpioption.py:230 revpioption.py:254 revpiplclist.py:150 +#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 msgid "Question" msgstr "Frage" @@ -164,7 +164,7 @@ msgstr "" "Sollen die neuen Einstellungen sofort in Kraft treten?\n" "Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" -#: revpioption.py:239 revpiplclist.py:191 revpiprogram.py:65 +#: revpioption.py:239 revpiplclist.py:190 revpiprogram.py:65 msgid "Information" msgstr "Information" @@ -172,11 +172,11 @@ msgstr "Information" msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: revpioption.py:245 revpiplclist.py:199 revpiprogram.py:307 -#: revpiprogram.py:336 revpiprogram.py:400 revpiprogram.py:435 -#: revpiprogram.py:520 revpiprogram.py:590 revpiprogram.py:620 -#: revpiprogram.py:632 revpiprogram.py:681 revpiprogram.py:702 -#: revpiprogram.py:711 revpipycontrol.py:308 +#: revpioption.py:245 revpiplclist.py:198 revpiprogram.py:306 +#: revpiprogram.py:337 revpiprogram.py:400 revpiprogram.py:433 +#: revpiprogram.py:517 revpiprogram.py:589 revpiprogram.py:620 +#: revpiprogram.py:633 revpiprogram.py:682 revpiprogram.py:702 +#: revpiprogram.py:710 revpipycontrol.py:307 msgid "Error" msgstr "Fehler" @@ -198,31 +198,31 @@ msgstr "" msgid "RevPi Python PLC connections" msgstr "RevPi Python PLC Verbindungen" -#: revpiplclist.py:75 +#: revpiplclist.py:74 msgid "Name" msgstr "Name" -#: revpiplclist.py:82 +#: revpiplclist.py:81 msgid "IP address" msgstr "IP Adresse" -#: revpiplclist.py:90 +#: revpiplclist.py:89 msgid "Port" msgstr "Port" -#: revpiplclist.py:99 +#: revpiplclist.py:98 msgid "New" msgstr "Neu" -#: revpiplclist.py:102 +#: revpiplclist.py:101 msgid "Apply" msgstr "Übernehmen" -#: revpiplclist.py:106 +#: revpiplclist.py:105 msgid "Remove" msgstr "Entfernen" -#: revpiplclist.py:152 +#: revpiplclist.py:151 msgid "" "Do you really want to quit? \n" "Unsaved changes will be lost" @@ -230,11 +230,11 @@ msgstr "" "Wollen Sie wirklich beenden? \n" "Nicht gespeicherte Änderungen gehen verloren" -#: revpiplclist.py:177 +#: revpiplclist.py:176 msgid "Do you really want to delete the selected connection '{}'" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" -#: revpiplclist.py:192 +#: revpiplclist.py:191 msgid "" "Successfully saved. \n" "Do you want to close this window?" @@ -242,11 +242,11 @@ msgstr "" "Verbindungen erfolgreich gespeichert. \n" "Möchten Sie dieses Fenster jetzt schließen?" -#: revpiplclist.py:200 +#: revpiplclist.py:199 msgid "Failed to save connections" msgstr "Verbindungen konnten nicht gespeichert werden" -#: revpiprogram.py:67 +#: revpiprogram.py:66 msgid "" "A PLC program has been uploaded. Please check the PLC options to see if the " "correct program is specified as the start program." @@ -254,135 +254,135 @@ msgstr "" "Ein PLC Programm wurde hochgeladen. Bitte prüfen Sie die PLC Optionen, ob " "dort das richtige Programm als Startprogramm angegeben ist." -#: revpiprogram.py:75 +#: revpiprogram.py:74 msgid "RevPi Python PLC program" msgstr "RevPi Python PLC Programm" -#: revpiprogram.py:89 +#: revpiprogram.py:88 msgid "PLC python program" msgstr "PLC Python Programm" -#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:109 -#: revpiprogram.py:113 +#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:108 +#: revpiprogram.py:112 msgid "Files" msgstr "Dateien" -#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:468 -#: revpiprogram.py:574 +#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:465 +#: revpiprogram.py:573 msgid "Zip archive" msgstr "Zip Archiv" -#: revpiprogram.py:99 revpiprogram.py:101 revpiprogram.py:481 +#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:478 #: revpiprogram.py:603 msgid "TGZ archive" msgstr "TGZ Archiv" -#: revpiprogram.py:101 +#: revpiprogram.py:100 msgid "Folder" msgstr "Verzeichnis" -#: revpiprogram.py:118 +#: revpiprogram.py:117 msgid "Download PLC program as:" msgstr "PLC Programm herunterladen als:" -#: revpiprogram.py:128 +#: revpiprogram.py:127 msgid "include piCtory configuration" msgstr "inkl. piCtory Konfiguration" -#: revpiprogram.py:133 revpiprogram.py:177 revpiprogram.py:198 +#: revpiprogram.py:132 revpiprogram.py:176 revpiprogram.py:197 msgid "Download" msgstr "Herunterladen" -#: revpiprogram.py:138 +#: revpiprogram.py:137 msgid "Upload PLC program as:" msgstr "PLC Programm hochladen als:" -#: revpiprogram.py:150 +#: revpiprogram.py:149 msgid "clean upload folder before upload" msgstr "vorher Inhalt im Uploadverzeichnis löschen" -#: revpiprogram.py:157 +#: revpiprogram.py:156 msgid "includes piCtory configuration" msgstr "enthält piCtory Konfiguration" -#: revpiprogram.py:163 revpiprogram.py:185 +#: revpiprogram.py:162 revpiprogram.py:184 msgid "Upload" msgstr "Hochladen" -#: revpiprogram.py:169 +#: revpiprogram.py:168 msgid "piCtory configuration" msgstr "piCtory Konfiguration" -#: revpiprogram.py:173 +#: revpiprogram.py:172 msgid "Download piCtory configuration" msgstr "piCtory Konfiguration herunterladen" -#: revpiprogram.py:180 +#: revpiprogram.py:179 msgid "Upload piCtory configuration" msgstr "piCtory Konfiguration hochladen" -#: revpiprogram.py:191 +#: revpiprogram.py:190 msgid "piControl0 prozess image" msgstr "piControl0 Prozessabbild" -#: revpiprogram.py:194 +#: revpiprogram.py:193 msgid "Download process image dump" msgstr "Prozessabbild Dump herunterladen" -#: revpiprogram.py:204 +#: revpiprogram.py:203 msgid "Reset piControl" msgstr "piControl zurücksetzen" -#: revpiprogram.py:207 +#: revpiprogram.py:206 msgid "Execute piControlReset" msgstr "piControlReset ausführen" -#: revpiprogram.py:211 +#: revpiprogram.py:210 msgid "execute" msgstr "ausführen" -#: revpiprogram.py:217 revpipycontrol.py:96 +#: revpiprogram.py:216 revpipycontrol.py:96 msgid "Exit" msgstr "Beenden" -#: revpiprogram.py:297 revpiprogram.py:326 revpiprogram.py:464 -#: revpiprogram.py:477 +#: revpiprogram.py:296 revpiprogram.py:327 revpiprogram.py:461 +#: revpiprogram.py:474 msgid "Save as..." msgstr "Speichern unter..." -#: revpiprogram.py:300 revpiprogram.py:359 +#: revpiprogram.py:299 revpiprogram.py:362 msgid "piCtory config" msgstr "piCtory Konfiguration" -#: revpiprogram.py:300 revpiprogram.py:329 revpiprogram.py:359 -#: revpiprogram.py:468 revpiprogram.py:481 revpiprogram.py:549 -#: revpiprogram.py:574 revpiprogram.py:603 +#: revpiprogram.py:299 revpiprogram.py:330 revpiprogram.py:362 +#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:548 +#: revpiprogram.py:573 revpiprogram.py:603 msgid "All files" msgstr "Alle Dateien" -#: revpiprogram.py:308 revpiprogram.py:337 revpiprogram.py:521 +#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:518 msgid "Could not load and save file!" msgstr "Datei konnte nicht geladen und gespeichert werden!" -#: revpiprogram.py:312 revpiprogram.py:341 revpiprogram.py:379 -#: revpiprogram.py:388 revpiprogram.py:430 revpiprogram.py:525 +#: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:381 +#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:523 #: revpiprogram.py:672 msgid "Success" msgstr "Erfolgreich" -#: revpiprogram.py:313 revpiprogram.py:342 revpiprogram.py:526 +#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:524 msgid "File successfully loaded and saved." msgstr "Dateien erfolgreich übertragen und gespeichert." -#: revpiprogram.py:329 +#: revpiprogram.py:330 msgid "Imagefiles" msgstr "Image Dateien" -#: revpiprogram.py:355 +#: revpiprogram.py:358 msgid "Open piCtory file..." msgstr "piCtory Datei öffnen" -#: revpiprogram.py:369 +#: revpiprogram.py:371 msgid "" "Should the piControl driver be reset after uploading the piCtory " "configuration?" @@ -390,7 +390,7 @@ msgstr "" "Soll nach dem Hochladen der piCtory Konfiguration ein Reset am piControl " "Treiber durchgeführt werden?" -#: revpiprogram.py:381 +#: revpiprogram.py:382 msgid "" "The transfer of the piCtory configuration and the reset of piControl have " "been successfully executed" @@ -402,18 +402,18 @@ msgstr "" msgid "The piCtory configuration was successfully transferred" msgstr "Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt" -#: revpiprogram.py:402 +#: revpiprogram.py:401 msgid "The piCtory configuration could not be written on the Revolution Pi." msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:408 revpipycontrol.py:199 revpipycontrol.py:247 -#: revpipycontrol.py:267 +#: revpiprogram.py:407 revpipycontrol.py:199 revpipycontrol.py:246 +#: revpipycontrol.py:266 msgid "Warning" msgstr "Warnung" -#: revpiprogram.py:410 +#: revpiprogram.py:408 msgid "" "The piCtroy configuration has been saved successfully. \n" "An error occurred on piControl reset!" @@ -421,7 +421,7 @@ msgstr "" "Die piCtroy Konfiguration wurde erfolgreich gespeichert. \n" "Beim piControl Reset trat allerdings ein Fehler auf!" -#: revpiprogram.py:422 +#: revpiprogram.py:419 msgid "" "Are you sure to reset piControl? \n" "The process image and the piBridge are interrupted !!!" @@ -429,27 +429,27 @@ msgstr "" "Soll piControlReset wirklich durchgeführt werden? \n" "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" -#: revpiprogram.py:431 +#: revpiprogram.py:428 msgid "piControlReset executed successfully" msgstr "piControl Reset war erfolgreich" -#: revpiprogram.py:437 +#: revpiprogram.py:434 msgid "piControl reset could not be executed successfully" msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" -#: revpiprogram.py:451 +#: revpiprogram.py:448 msgid "Directory to save" msgstr "Verzeichnis zum Ablegen" -#: revpiprogram.py:559 +#: revpiprogram.py:558 msgid "Folder to upload" msgstr "Verzeichnis zum Hochladen" -#: revpiprogram.py:570 +#: revpiprogram.py:569 msgid "Upload Zip archive..." msgstr "Zip Archiv hochladen..." -#: revpiprogram.py:591 +#: revpiprogram.py:590 msgid "The specified file is not a ZIP archive." msgstr "Die angegebene Datei ist kein ZIP Archiv" @@ -474,11 +474,11 @@ msgstr "Die Übertragung war erfolgreich." msgid "There is no piCtory configuration in this archive." msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." -#: revpiprogram.py:704 +#: revpiprogram.py:703 msgid "The Revolution Pi could not process some parts of the transmission." msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." -#: revpiprogram.py:712 +#: revpiprogram.py:711 msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" @@ -530,7 +530,7 @@ msgstr "Trennen" msgid "Connect" msgstr "Verbinden" -#: revpipycontrol.py:201 +#: revpipycontrol.py:200 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " "You need at least version 0.4.0." @@ -538,7 +538,7 @@ msgstr "" "Die Debug-Funktion wird von der RevPiPyLoad Version {} auf dem RevPi nicht " "unterstützt! Sie benötigen mindestens Version 0.4.0." -#: revpipycontrol.py:249 revpipycontrol.py:269 +#: revpipycontrol.py:248 revpipycontrol.py:268 msgid "" "XML-RPC access mode in the RevPiPyLoad configuration is to small to access " "this dialog" @@ -546,6 +546,6 @@ msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:309 +#: revpipycontrol.py:308 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 23a59f2..2d3c955 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -12,6 +12,7 @@ from mytools import gettrans # Übersetzung laden _ = gettrans() + class RevPiOption(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode): @@ -60,14 +61,16 @@ class RevPiOption(tkinter.Frame): ckb_zexit = tkinter.Checkbutton(stst, justify="left") ckb_zexit["state"] = self.xmlstate - ckb_zexit["text"] = _("Set process image to NULL if program\n" + ckb_zexit["text"] = _( + "Set process image to NULL if program\n" "terminates successfully") ckb_zexit["variable"] = self.var_zexit ckb_zexit.grid(**cpadw) ckb_zerr = tkinter.Checkbutton(stst, justify="left") ckb_zerr["state"] = self.xmlstate - ckb_zerr["text"] = _("Set process image to NULL if program\n" + ckb_zerr["text"] = _( + "Set process image to NULL if program\n" "terminates with errors") ckb_zerr["variable"] = self.var_zerr ckb_zerr.grid(**cpadw) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 1e6df5e..3047f59 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -63,11 +63,9 @@ class RevPiProgram(tkinter.Frame): if True or self.uploaded: tkmsg.showinfo( _("Information"), - _( - "A PLC program has been uploaded. Please check the " + _("A PLC program has been uploaded. Please check the " "PLC options to see if the correct program is specified " - "as the start program." - ), + "as the start program."), parent=self.master ) self.master.destroy() @@ -305,13 +303,15 @@ class RevPiProgram(tkinter.Frame): fh.write(self.xmlcli.get_pictoryrsc().data) except: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("Could not load and save file!") + _("Error"), + _("Could not load and save file!"), + parent=self.master, ) else: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_("File successfully loaded and saved.") + _("Success"), + _("File successfully loaded and saved."), + parent=self.master ) # Einstellungen speichern self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name) @@ -334,13 +334,15 @@ class RevPiProgram(tkinter.Frame): fh.write(self.xmlcli.get_procimg().data) except: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("Could not load and save file!") + _("Error"), + _("Could not load and save file!"), + parent=self.master ) else: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_("File successfully loaded and saved.") + _("Success"), + _("File successfully loaded and saved."), + parent=self.master ) # Einstellungen speichern self.opt["getprocimg_dir"] = os.path.dirname(fh.name) @@ -365,11 +367,10 @@ class RevPiProgram(tkinter.Frame): if fh is not None: ask = tkmsg.askyesno( - parent=self.master, title=_("Question"), - message=_( - "Should the piControl driver be reset after " - "uploading the piCtory configuration?" - ) + _("Question"), + _("Should the piControl driver be reset after " + "uploading the piCtory configuration?"), + parent=self.master ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) @@ -377,20 +378,18 @@ class RevPiProgram(tkinter.Frame): if ec == 0: if ask: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_( - "The transfer of the piCtory configuration " + _("Success"), + _("The transfer of the piCtory configuration " "and the reset of piControl have been " - "successfully executed" - ) + "successfully executed"), + parent=self.master ) else: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_( - "The piCtory configuration was " - "successfully transferred" - ) + _("Success"), + _("The piCtory configuration was " + "successfully transferred"), + parent=self.master ) # Einstellungen speichern @@ -398,19 +397,17 @@ class RevPiProgram(tkinter.Frame): self._savedefaults() elif ec < 0: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_( - "The piCtory configuration could not be " - "written on the Revolution Pi." - ) + _("Error"), + _("The piCtory configuration could not be " + "written on the Revolution Pi."), + parent=self.master ) elif ec > 0: tkmsg.showwarning( - parent=self.master, title=_("Warning"), - message=_( - "The piCtroy configuration has been saved " - "successfully. \nAn error occurred on piControl reset!" - ) + _("Warning"), + _("The piCtroy configuration has been saved successfully." + " \nAn error occurred on piControl reset!"), + parent=self.master ) fh.close() @@ -418,25 +415,24 @@ class RevPiProgram(tkinter.Frame): def picontrolreset(self): u"""Fürt ein Reset der piBridge durch.""" ask = tkmsg.askyesno( - parent=self.master, title=_("Question"), - message=_( - "Are you sure to reset piControl? \nThe process image " - "and the piBridge are interrupted !!!" - ) + _("Question"), + _("Are you sure to reset piControl? \nThe process image " + "and the piBridge are interrupted !!!"), + parent=self.master ) if ask: ec = self.xmlcli.resetpicontrol() if ec == 0: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_("piControlReset executed successfully") + _("Success"), + _("piControlReset executed successfully"), + parent=self.master ) else: tkmsg.showerror( - parten=self.master, title=_("Error"), - message=_( - "piControl reset could not be executed successfully" - ) + _("Error"), + _("piControl reset could not be executed successfully"), + parten=self.master ) def plcdownload(self): @@ -518,13 +514,15 @@ class RevPiProgram(tkinter.Frame): except: raise tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("Could not load and save file!") + _("Error"), + _("Could not load and save file!"), + parent=self.master ) else: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_("File successfully loaded and saved.") + _("Success"), + _("File successfully loaded and saved."), + parent=self.master ) # Einstellungen speichern @@ -588,8 +586,9 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("The specified file is not a ZIP archive.") + _("Error"), + _("The specified file is not a ZIP archive."), + parent=self.master ) return False @@ -618,8 +617,9 @@ class RevPiProgram(tkinter.Frame): else: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("The specified file is not a TAR archive.") + _("Error"), + _("The specified file is not a TAR archive."), + parent=self.master ) return False @@ -630,11 +630,10 @@ class RevPiProgram(tkinter.Frame): # Vor Übertragung aufräumen wenn ausgewählt if self.var_cleanup.get() and not self.xmlcli.plcuploadclean(): tkmsg.showerror( - parent=self.masger, title=_("Error"), - message=_( - "There was an error deleting the files on the " - "Revolution Pi." - ) + _("Error"), + _("There was an error deleting the files on the " + "Revolution Pi."), + parent=self.master ) return False @@ -670,8 +669,9 @@ class RevPiProgram(tkinter.Frame): if ec == 0: tkmsg.showinfo( - parent=self.master, title=_("Success"), - message=_("The transfer was successful.") + _("Success"), + _("The transfer was successful."), + parent=self.master ) if self.var_picup.get(): @@ -679,11 +679,10 @@ class RevPiProgram(tkinter.Frame): self.setpictoryrsc(rscfile) else: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_( - "There is no piCtory configuration in this " - "archive." - ) + _("Error"), + _("There is no piCtory configuration in this " + "archive."), + parent=self.master ) # Einstellungen speichern @@ -700,17 +699,17 @@ class RevPiProgram(tkinter.Frame): elif ec == -1: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_( - "The Revolution Pi could not process some parts of the " - "transmission." - ) + _("Error"), + _("The Revolution Pi could not process some parts of the " + "transmission."), + parent=self.master ) elif ec == -2: tkmsg.showerror( - parent=self.master, title=_("Error"), - message=_("Errors occurred during transmission") + _("Error"), + _("Errors occurred during transmission"), + parent=self.master ) # Temp-Dir aufräumen diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 241b634..2051e76 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -196,12 +196,11 @@ class RevPiPyControl(tkinter.Frame): if "psstart" not in self.xmlfuncs: tkmsg.showwarning( - parent=self.master, title=_("Warning"), - message=_( - "The watch mode ist not supported in version {} " + _("Warning"), + _("The watch mode ist not supported in version {} " "of RevPiPyLoad on your RevPi! You need at least version " - "0.4.0." - ).format(self.cli.version()) + "0.4.0.").format(self.cli.version()), + parent=self.master ) else: # Debugfenster laden From a60431e45633a2104dc25130453e04a4d61310e6 Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 29 Jun 2017 20:11:55 +0200 Subject: [PATCH 06/13] RevPiLogfile auf neue Byte?bertragung angepasst Reaktion auf Fehlerbytes vom RevPi f?r Logfile In Dialogfenster ESC zum schlie?en eingebaut _checkclose Funktionen zur Pr?fung auf ?nderung und Schlie?en hinzugef?gt --- revpipycontrol.e4p | 4 +- .../locale/de/LC_MESSAGES/revpipycontrol.po | 202 ++++++++++-------- revpipycontrol/revpilogfile.py | 117 +++++++--- revpipycontrol/revpioption.py | 70 ++++-- revpipycontrol/revpiplclist.py | 32 +-- revpipycontrol/revpiprogram.py | 22 +- revpipycontrol/revpipycontrol.py | 41 +++- setup.py | 2 +- 8 files changed, 314 insertions(+), 176 deletions(-) diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index b5d5115..4e778ae 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -9,7 +9,7 @@ Python3 Console - 0.4.0 + 0.4.1 Sven Sager akira@narux.de diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 73a88ce..0fd8feb 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-29 12:59+0200\n" -"PO-Revision-Date: 2017-06-29 13:03+0200\n" +"POT-Creation-Date: 2017-06-29 20:10+0200\n" +"PO-Revision-Date: 2017-06-29 20:10+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -43,39 +43,56 @@ msgstr "Aktualisiere automatisch" msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" -#: revpilogfile.py:27 +#: revpilogfile.py:37 msgid "RevPi Python PLC Logs" msgstr "RevPi Python PLC Logdaten" -#: revpilogfile.py:40 +#: revpilogfile.py:50 msgid "RevPiPyLoad - Logfile" msgstr "RevPiPyLoad - Logdatei" -#: revpilogfile.py:44 revpilogfile.py:59 +#: revpilogfile.py:54 revpilogfile.py:69 msgid "Clear screen" msgstr "Leere Ansicht" -#: revpilogfile.py:55 +#: revpilogfile.py:65 msgid "Python PLC program - Logfile" msgstr "Python PLC Programm - Logdatei" -#: revpioption.py:33 +#: revpilogfile.py:145 +msgid "Can not access log file on the RevPi" +msgstr "RevPi kann auf Logdatei nicht zugreifen" + +#: revpioption.py:61 revpioption.py:273 revpioption.py:298 revpiplclist.py:58 +#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 +msgid "Question" +msgstr "Frage" + +#: revpioption.py:62 revpiplclist.py:59 +msgid "" +"Do you really want to quit? \n" +"Unsaved changes will be lost" +msgstr "" +"Wollen Sie wirklich beenden? \n" +"Nicht gespeicherte Änderungen gehen verloren" + +#: revpioption.py:72 msgid "RevPi Python PLC Options" msgstr "RevPi Python PLC Einstellungen" -#: revpioption.py:41 +#: revpioption.py:80 msgid "Start / Stop behavior" msgstr "Start / Stop Verhalten" -#: revpioption.py:50 +#: revpioption.py:89 msgid "Start program automatically" msgstr "Starte Programm automatisch" -#: revpioption.py:56 +#: revpioption.py:95 msgid "Restart program after exit" msgstr "Starte Programm nach Beenden neu" -#: revpioption.py:63 +#: revpioption.py:103 msgid "" "Set process image to NULL if program\n" "terminates successfully" @@ -83,7 +100,7 @@ msgstr "" "\"Prozessabbild auf NULL setzen, wenn Programm\n" "\"erfolgreich beendet wird\"" -#: revpioption.py:70 +#: revpioption.py:111 msgid "" "Set process image to NULL if program\n" "terminates with errors" @@ -91,35 +108,35 @@ msgstr "" "Prozessabbild auf NULL setzen, wenn Programm\n" "fehlerhaft beendet wird" -#: revpioption.py:77 +#: revpioption.py:118 msgid "PLC program" msgstr "PLC Programm" -#: revpioption.py:88 +#: revpioption.py:129 msgid "Python version" msgstr "Python Version" -#: revpioption.py:105 +#: revpioption.py:146 msgid "Python PLC program name" msgstr "Python PLC Programmname" -#: revpioption.py:117 +#: revpioption.py:158 msgid "Program arguments" msgstr "Programmargumente" -#: revpioption.py:126 +#: revpioption.py:167 msgid "Use RevPi as PLC-Slave" msgstr "RevPi als PLC-Slave verwenden" -#: revpioption.py:133 +#: revpioption.py:174 msgid "XML-RPC server" msgstr "XML-RPC Server" -#: revpioption.py:145 +#: revpioption.py:186 msgid "Activate XML-RPC server on RevPi" msgstr "Aktiviere XML-RPC Server auf RevPi" -#: revpioption.py:153 +#: revpioption.py:194 msgid "" "Allow download of piCtory configuration and\n" "PLC programm" @@ -127,7 +144,7 @@ msgstr "" "Download von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:160 +#: revpioption.py:201 msgid "" "Allow upload of piCtory configuration and\n" "PLC programm" @@ -135,24 +152,19 @@ msgstr "" "Hochladen von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:165 +#: revpioption.py:206 msgid "XML-RPC server port" msgstr "XML-RPC Serverport" -#: revpioption.py:179 revpiplclist.py:111 +#: revpioption.py:220 revpiplclist.py:125 msgid "Save" msgstr "Speichern" -#: revpioption.py:184 revpiplclist.py:114 +#: revpioption.py:225 revpiplclist.py:128 msgid "Close" msgstr "Schließen" -#: revpioption.py:230 revpioption.py:254 revpiplclist.py:150 -#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 -msgid "Question" -msgstr "Frage" - -#: revpioption.py:231 +#: revpioption.py:274 msgid "" "The settings are now saved on the Revolution Pi. \n" "\n" @@ -164,29 +176,29 @@ msgstr "" "Sollen die neuen Einstellungen sofort in Kraft treten?\n" "Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" -#: revpioption.py:239 revpiplclist.py:190 revpiprogram.py:65 +#: revpioption.py:282 revpiplclist.py:190 revpiprogram.py:65 msgid "Information" msgstr "Information" -#: revpioption.py:240 +#: revpioption.py:283 msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: revpioption.py:245 revpiplclist.py:198 revpiprogram.py:306 +#: revpioption.py:288 revpiplclist.py:198 revpiprogram.py:306 #: revpiprogram.py:337 revpiprogram.py:400 revpiprogram.py:433 -#: revpiprogram.py:517 revpiprogram.py:589 revpiprogram.py:620 -#: revpiprogram.py:633 revpiprogram.py:682 revpiprogram.py:702 -#: revpiprogram.py:710 revpipycontrol.py:307 +#: revpiprogram.py:515 revpiprogram.py:587 revpiprogram.py:618 +#: revpiprogram.py:631 revpiprogram.py:686 revpiprogram.py:706 +#: revpiprogram.py:714 revpipycontrol.py:325 msgid "Error" msgstr "Fehler" -#: revpioption.py:246 +#: revpioption.py:289 msgid "The settings could not be saved. This can happen if values are wrong!" msgstr "" "Die Einstellungen konnten nicht gesichert werden. Dies kann passieren, wenn " "Werte falsch sind!" -#: revpioption.py:255 +#: revpioption.py:299 msgid "" "Are you sure you want to deactivate the XML-RPC server? You will NOT be able " "to access the Revolution Pi with this program." @@ -194,42 +206,34 @@ msgstr "" "Soll der XML-RPC Server wirklich beendet werden? Sie können dann NICHT mehr " "mit diesem Programm auf den Revolution Pi zugreifen." -#: revpiplclist.py:54 +#: revpiplclist.py:68 msgid "RevPi Python PLC connections" msgstr "RevPi Python PLC Verbindungen" -#: revpiplclist.py:74 +#: revpiplclist.py:88 msgid "Name" msgstr "Name" -#: revpiplclist.py:81 +#: revpiplclist.py:95 msgid "IP address" msgstr "IP Adresse" -#: revpiplclist.py:89 +#: revpiplclist.py:103 msgid "Port" msgstr "Port" -#: revpiplclist.py:98 +#: revpiplclist.py:112 msgid "New" msgstr "Neu" -#: revpiplclist.py:101 +#: revpiplclist.py:115 msgid "Apply" msgstr "Übernehmen" -#: revpiplclist.py:105 +#: revpiplclist.py:119 msgid "Remove" msgstr "Entfernen" -#: revpiplclist.py:151 -msgid "" -"Do you really want to quit? \n" -"Unsaved changes will be lost" -msgstr "" -"Wollen Sie wirklich beenden? \n" -"Nicht gespeicherte Änderungen gehen verloren" - #: revpiplclist.py:176 msgid "Do you really want to delete the selected connection '{}'" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" @@ -268,12 +272,12 @@ msgid "Files" msgstr "Dateien" #: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:465 -#: revpiprogram.py:573 +#: revpiprogram.py:571 msgid "Zip archive" msgstr "Zip Archiv" #: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:478 -#: revpiprogram.py:603 +#: revpiprogram.py:601 msgid "TGZ archive" msgstr "TGZ Archiv" @@ -341,7 +345,7 @@ msgstr "piControlReset ausführen" msgid "execute" msgstr "ausführen" -#: revpiprogram.py:216 revpipycontrol.py:96 +#: revpiprogram.py:216 revpipycontrol.py:95 msgid "Exit" msgstr "Beenden" @@ -355,22 +359,22 @@ msgid "piCtory config" msgstr "piCtory Konfiguration" #: revpiprogram.py:299 revpiprogram.py:330 revpiprogram.py:362 -#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:548 -#: revpiprogram.py:573 revpiprogram.py:603 +#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:546 +#: revpiprogram.py:571 revpiprogram.py:601 msgid "All files" msgstr "Alle Dateien" -#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:518 +#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:516 msgid "Could not load and save file!" msgstr "Datei konnte nicht geladen und gespeichert werden!" #: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:381 -#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:523 -#: revpiprogram.py:672 +#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:521 +#: revpiprogram.py:676 msgid "Success" msgstr "Erfolgreich" -#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:524 +#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:522 msgid "File successfully loaded and saved." msgstr "Dateien erfolgreich übertragen und gespeichert." @@ -408,8 +412,8 @@ msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:407 revpipycontrol.py:199 revpipycontrol.py:246 -#: revpipycontrol.py:266 +#: revpiprogram.py:407 revpipycontrol.py:211 revpipycontrol.py:250 +#: revpipycontrol.py:268 revpipycontrol.py:286 msgid "Warning" msgstr "Warnung" @@ -441,104 +445,124 @@ msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" msgid "Directory to save" msgstr "Verzeichnis zum Ablegen" -#: revpiprogram.py:558 +#: revpiprogram.py:556 msgid "Folder to upload" msgstr "Verzeichnis zum Hochladen" -#: revpiprogram.py:569 +#: revpiprogram.py:567 msgid "Upload Zip archive..." msgstr "Zip Archiv hochladen..." -#: revpiprogram.py:590 +#: revpiprogram.py:588 msgid "The specified file is not a ZIP archive." msgstr "Die angegebene Datei ist kein ZIP Archiv" -#: revpiprogram.py:599 +#: revpiprogram.py:597 msgid "Upload TarGz archiv..." msgstr "TarGz Archiv hochladen..." -#: revpiprogram.py:621 +#: revpiprogram.py:619 msgid "The specified file is not a TAR archive." msgstr "Die angegebene Datei ist kein TAR Archiv." -#: revpiprogram.py:634 +#: revpiprogram.py:632 msgid "There was an error deleting the files on the Revolution Pi." msgstr "" "Beim Löschen der Dateien auf dem Revolution Pi ist ein Fehler aufgetreten." -#: revpiprogram.py:673 +#: revpiprogram.py:677 msgid "The transfer was successful." msgstr "Die Übertragung war erfolgreich." -#: revpiprogram.py:683 +#: revpiprogram.py:687 msgid "There is no piCtory configuration in this archive." msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." -#: revpiprogram.py:703 +#: revpiprogram.py:707 msgid "The Revolution Pi could not process some parts of the transmission." msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." -#: revpiprogram.py:711 +#: revpiprogram.py:715 msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" -#: revpipycontrol.py:94 +#: revpipycontrol.py:93 msgid "Connections..." msgstr "Verbindungen..." -#: revpipycontrol.py:97 +#: revpipycontrol.py:96 msgid "Main" msgstr "Datei" +#: revpipycontrol.py:104 +msgid "Visit website..." +msgstr "Webseite besuchen..." + +#: revpipycontrol.py:106 +msgid "Info..." +msgstr "Info..." + #: revpipycontrol.py:108 +msgid "Help" +msgstr "Hilfe" + +#: revpipycontrol.py:116 msgid "PLC start" msgstr "PLC Start" -#: revpipycontrol.py:113 +#: revpipycontrol.py:121 msgid "PLC stop" msgstr "PLC Stopp" -#: revpipycontrol.py:118 +#: revpipycontrol.py:126 msgid "PLC restart" msgstr "PLC Neustart" -#: revpipycontrol.py:123 +#: revpipycontrol.py:131 msgid "PLC logs" msgstr "PLC Logs" -#: revpipycontrol.py:134 +#: revpipycontrol.py:142 msgid "PLC watch mode" msgstr "PLC watch Modus" -#: revpipycontrol.py:151 +#: revpipycontrol.py:159 msgid "PLC log..." msgstr "PLC Log..." -#: revpipycontrol.py:153 +#: revpipycontrol.py:161 msgid "PLC options..." msgstr "PLC Optionen..." -#: revpipycontrol.py:155 +#: revpipycontrol.py:163 msgid "PLC program..." msgstr "PLC Programm..." -#: revpipycontrol.py:159 +#: revpipycontrol.py:167 msgid "Disconnect" msgstr "Trennen" -#: revpipycontrol.py:164 +#: revpipycontrol.py:172 msgid "Connect" msgstr "Verbinden" -#: revpipycontrol.py:200 +#: revpipycontrol.py:212 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " "You need at least version 0.4.0." msgstr "" -"Die Debug-Funktion wird von der RevPiPyLoad Version {} auf dem RevPi nicht " +"Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " "unterstützt! Sie benötigen mindestens Version 0.4.0." -#: revpipycontrol.py:248 revpipycontrol.py:268 +#: revpipycontrol.py:251 +msgid "" +"This version of Logviewer ist not supported in version {} of RevPiPyLoad on " +"your RevPi! You need at least version 0.4.1." +msgstr "" +"Diese Version vom Logbetrachter wird in der RevPiPyLoad Version {} auf Ihrem " +"RevPi nicht unterstützt! Sie benötigen mindestens Version 0.4.1." + +#: revpipycontrol.py:269 revpipycontrol.py:287 msgid "" "XML-RPC access mode in the RevPiPyLoad configuration is to small to access " "this dialog" @@ -546,6 +570,6 @@ msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:308 +#: revpipycontrol.py:326 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 060ed49..646bea3 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -5,7 +5,6 @@ # (c) Sven Sager, License: LGPLv3 # # -*- coding: utf-8 -*- -import pickle import tkinter from mytools import gettrans @@ -16,14 +15,25 @@ _ = gettrans() class RevPiLogfile(tkinter.Frame): def __init__(self, master, xmlcli): + u"""Init RevPiLogfile-Class.""" super().__init__(master) + self.master.bind("", self._closewin) self.pack(fill="both", expand=True) self.xmlcli = xmlcli + # Systemvariablen + self.loadblock = 16384 + self.mrkapp = 0 + self.mrkplc = 0 + # Fenster bauen self._createwidgets() + def _closewin(self, event): + self.master.destroy() + def _createwidgets(self): + u"""Erstellt alle Widgets.""" self.master.wm_title(_("RevPi Python PLC Logs")) self.rowconfigure(0, weight=0) @@ -65,47 +75,84 @@ class RevPiLogfile(tkinter.Frame): self.applog["yscrollcommand"] = self.appscr.set self.appscr["command"] = self.applog.yview - self.get_applog() - self.get_plclog() - - # Timer zum nachladen aktivieren - self.master.after(1000, self.get_applines) - self.master.after(1000, self.get_plclines) + # Logtimer zum Laden starten + self.get_applog(full=True) + self.get_plclog(full=True) def btn_clearapp(self): + u"""Leert die Logliste der App.""" self.applog.delete(1.0, tkinter.END) def btn_clearplc(self): + u"""Leert die Logliste des PLC.""" self.plclog.delete(1.0, tkinter.END) - def get_applines(self): - roll = self.applog.yview()[1] == 1.0 - try: - for line in pickle.loads(self.xmlcli.get_applines().data): - self.applog.insert(tkinter.END, line) - except: - pass - if roll: - self.applog.see(tkinter.END) - self.master.after(1000, self.get_applines) + def get_applog(self, full=False): + u"""Ruft App Logbuch ab. + @param full: Ganzes Logbuch laden""" - def get_applog(self): - self.applog.delete(1.0, tkinter.END) - self.applog.insert(1.0, pickle.loads(self.xmlcli.get_applog().data)) - self.applog.see(tkinter.END) + # Logs abrufen und letzte Position merken + self.mrkapp = self._load_log( + self.applog, self.xmlcli.load_applog, self.mrkapp, full + ) - def get_plclines(self): - roll = self.plclog.yview()[1] == 1.0 - try: - for line in pickle.loads(self.xmlcli.get_plclines().data): - self.plclog.insert(tkinter.END, line) - except: - pass - if roll: - self.plclog.see(tkinter.END) - self.master.after(1000, self.get_plclines) + # Timer neu starten + self.master.after(1000, self.get_applog) - def get_plclog(self): - self.plclog.delete(1.0, tkinter.END) - self.plclog.insert(1.0, pickle.loads(self.xmlcli.get_plclog().data)) - self.plclog.see(tkinter.END) + def get_plclog(self, full=False): + u"""Ruft PLC Logbuch ab. + @param full: Ganzes Logbuch laden""" + + # Logs abrufen und letzte Position merken + self.mrkplc = self._load_log( + self.plclog, self.xmlcli.load_plclog, self.mrkplc, full + ) + + # Timer neu starten + self.master.after(1000, self.get_plclog) + + def _load_log(self, textwidget, xmlcall, startposition, full): + u"""Läd die angegebenen Logfiles herunter. + + @param textwidget: Widget in das Logs eingefügt werden sollen + @param xmlcall: xmlrpc Funktion zum Abrufen der Logdaten + @param startposition: Startposition ab der Logdaten kommen sollen + @param full: Komplettes Logbuch laden + @returns: Ende der Datei (neue Startposition) + + """ + roll = textwidget.yview()[1] == 1.0 + startposition = 0 if full else startposition + logbytes = b'' + while True: + # Datenblock vom XML-RPC Server holen + bytebuff = xmlcall(startposition, self.loadblock).data + + logbytes += bytebuff + startposition += len(bytebuff) + + # Prüfen ob alle Daten übertragen wurden + if len(bytebuff) < self.loadblock: + break + + if full: + textwidget.delete(1.0, tkinter.END) + + if bytebuff == b'\x16': #  + # Kein Zugriff auf Logdatei + textwidget.delete(1.0, tkinter.END) + textwidget.insert( + tkinter.END, _("Can not access log file on the RevPi") + ) + elif bytebuff == b'\x19': #  + # Logdatei neu begonnen + startposition = 0 + else: + # Text in Widget übernehmen + textwidget.insert(tkinter.END, logbytes.decode("utf-8")) + + # Automatisch ans Ende rollen + if roll or full: + textwidget.see(tkinter.END) + + return startposition diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 2d3c955..2d0afb4 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -16,10 +16,14 @@ _ = gettrans() class RevPiOption(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode): + u"""Init RevPiOption-Class. + @returns: None""" if xmlmode < 2: return None super().__init__(master) + self.master.bind("", self._checkclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) self.pack(expand=True, fill="both") self.xmlcli = xmlcli @@ -30,7 +34,41 @@ class RevPiOption(tkinter.Frame): self._createwidgets() self._loadappdata() + def _changesdone(self): + u"""Prüft ob sich die Einstellungen geändert haben. + @returns: True, wenn min. eine Einstellung geändert wurde""" + return ( + self.var_start.get() != self.dc.get("autostart", "1") + or self.var_reload.get() != self.dc.get("autoreload", "1") + or self.var_zexit.get() != self.dc.get("zeroonexit", "0") + or self.var_zerr.get() != self.dc.get("zeroonerror", "0") + or self.var_startpy.get() != self.dc.get("plcprogram", "none.py") + or self.var_startargs.get() != self.dc.get("plcarguments", "") + or self.var_pythonver.get() != self.dc.get("pythonversion", "3") + or self.var_slave.get() != self.dc.get("plcslave", "0") + or self.var_xmlon.get() != (self.dc.get("xmlrpc", 0) >= 1) + or self.var_xmlmod2.get() != (self.dc.get("xmlrpc", 0) >= 2) + or self.var_xmlmod3.get() != (self.dc.get("xmlrpc", 0) >= 3) + or self.var_xmlport.get() != self.dc.get("xmlrpcport", "55123") + ) + + def _checkclose(self, event=None): + u"""Prüft ob Fenster beendet werden soll. + @param event: tkinter-Event""" + ask = True + if self._changesdone(): + ask = tkmsg.askyesno( + _("Question"), + _("Do you really want to quit? \nUnsaved changes will " + "be lost"), + parent=self.master + ) + + if ask: + self.master.destroy() + def _createwidgets(self): + u"""Erstellt Widgets.""" self.master.wm_title(_("RevPi Python PLC Options")) self.master.wm_resizable(width=False, height=False) @@ -183,30 +221,32 @@ class RevPiOption(tkinter.Frame): btn_save.grid(column=0, row=3) btn_close = tkinter.Button(self) - btn_close["command"] = self.master.destroy + btn_close["command"] = self._checkclose btn_close["text"] = _("Close") btn_close.grid(column=1, row=3) def _loadappdata(self): - dc = self.xmlcli.get_config() + u"""Läd aktuelle Einstellungen vom RevPi.""" + self.dc = self.xmlcli.get_config() - self.var_start.set(dc.get("autostart", "1")) - self.var_reload.set(dc.get("autoreload", "1")) - self.var_zexit.set(dc.get("zeroonexit", "0")) - self.var_zerr.set(dc.get("zeroonerror", "0")) + self.var_start.set(self.dc.get("autostart", "1")) + self.var_reload.set(self.dc.get("autoreload", "1")) + self.var_zexit.set(self.dc.get("zeroonexit", "0")) + self.var_zerr.set(self.dc.get("zeroonerror", "0")) - self.var_startpy.set(dc.get("plcprogram", "none.py")) - self.var_startargs.set(dc.get("plcarguments", "")) - self.var_pythonver.set(dc.get("pythonversion", "3")) - self.var_slave.set(dc.get("plcslave", "0")) + self.var_startpy.set(self.dc.get("plcprogram", "none.py")) + self.var_startargs.set(self.dc.get("plcarguments", "")) + self.var_pythonver.set(self.dc.get("pythonversion", "3")) + self.var_slave.set(self.dc.get("plcslave", "0")) - self.var_xmlon.set(dc.get("xmlrpc", 0) >= 1) - self.var_xmlmod2.set(dc.get("xmlrpc", 0) >= 2) - self.var_xmlmod3.set(dc.get("xmlrpc", 0) >= 3) + self.var_xmlon.set(self.dc.get("xmlrpc", 0) >= 1) + self.var_xmlmod2.set(self.dc.get("xmlrpc", 0) >= 2) + self.var_xmlmod3.set(self.dc.get("xmlrpc", 0) >= 3) - self.var_xmlport.set(dc.get("xmlrpcport", "55123")) + self.var_xmlport.set(self.dc.get("xmlrpcport", "55123")) def _setappdata(self): + u"""Speichert geänderte Einstellungen auf RevPi.""" dc = {} dc["autostart"] = int(self.var_start.get()) dc["autoreload"] = int(self.var_reload.get()) @@ -252,6 +292,7 @@ class RevPiOption(tkinter.Frame): ) def askxmlon(self): + u"""Fragt Nuter, ob wirklicht abgeschaltet werden soll.""" if not self.var_xmlon.get(): ask = tkmsg.askyesno( _("Question"), @@ -266,6 +307,7 @@ class RevPiOption(tkinter.Frame): self.xmlmods() def xmlmods(self): + u"""Passt XML-Optionszugriff an.""" self.ckb_xmlmod2["state"] = \ "normal" if self.var_xmlon.get() else "disabled" self.ckb_xmlmod3["state"] = \ diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index 801b845..309c826 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -39,6 +39,7 @@ class RevPiPlcList(tkinter.Frame): def __init__(self, master): super().__init__(master) + self.master.bind("", self._checkclose) self.pack() self.changes = False @@ -50,10 +51,23 @@ class RevPiPlcList(tkinter.Frame): self._createwidgets() self._loadappdata() + def _checkclose(self, event=None): + ask = True + if self.changes: + ask = tkmsg.askyesno( + _("Question"), + _("Do you really want to quit? \nUnsaved changes will " + "be lost"), + parent=self.master + ) + + if ask: + self.master.destroy() + def _createwidgets(self): self.master.wm_title(_("RevPi Python PLC connections")) self.master.wm_resizable(width=False, height=False) - self.master.protocol("WM_DELETE_WINDOW", self.evt_btnclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) # Listbox mit vorhandenen Verbindungen self.scr_conn = tkinter.Scrollbar(self) @@ -111,7 +125,7 @@ class RevPiPlcList(tkinter.Frame): self, text=_("Save"), command=self.evt_btnsave) self.btn_save.grid(column=3, row=9, sticky="se") self.btn_close = tkinter.Button( - self, text=_("Close"), command=self.evt_btnclose) + self, text=_("Close"), command=self._checkclose) self.btn_close.grid(column=4, row=9, sticky="se") def _loadappdata(self): @@ -144,20 +158,6 @@ class RevPiPlcList(tkinter.Frame): self.evt_btnnew() self.changes = True - def evt_btnclose(self): - if self.changes: - ask = tkmsg.askyesno( - _("Question"), - _("Do you really want to quit? \nUnsaved changes will " - "be lost"), - parent=self.master - ) - else: - ask = True - - if ask: - self.master.destroy() - def evt_btnnew(self): self.list_conn.select_clear(0, "end") self.evt_listconn() diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 3047f59..269eddd 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -40,8 +40,8 @@ class RevPiProgram(tkinter.Frame): return None super().__init__(master) - # FIXME: Warnung kann nerven - # self.master.protocol("WM_DELETE_WINDOW", self._checkclose) + self.master.protocol("WM_DELETE_WINDOW", self._checkclose) + self.master.bind("", self._checkclose) self.pack(expand=True, fill="both") self.uploaded = False @@ -59,8 +59,8 @@ class RevPiProgram(tkinter.Frame): self._evt_optdown() self._evt_optup() - def _checkclose(self): - if True or self.uploaded: + def _checkclose(self, event=None): + if self.uploaded: tkmsg.showinfo( _("Information"), _("A PLC program has been uploaded. Please check the " @@ -212,7 +212,7 @@ class RevPiProgram(tkinter.Frame): # Beendenbutton btn = tkinter.Button(self) - btn["command"] = self.master.destroy + btn["command"] = self._checkclose btn["text"] = _("Exit") btn.grid() @@ -374,7 +374,7 @@ class RevPiProgram(tkinter.Frame): ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) - print(ec) + if ec == 0: if ask: tkmsg.showinfo( @@ -496,9 +496,7 @@ class RevPiProgram(tkinter.Frame): fh_pack = tarfile.open(fh.name) # Unterverzeichnis streichen - rootname = "" for taritem in fh_pack.getmembers(): - print(rootname) if not taritem.name == "revpipyload": taritem.name = \ taritem.name.replace("revpipyload/", "") @@ -637,7 +635,9 @@ class RevPiProgram(tkinter.Frame): ) return False - # Flag setzen, weil ab hier Veränderungen existieren + # Aktuell konfiguriertes Programm lesen (für uploaded Flag) + opt_program = self.xmlcli.get_config() + opt_program = opt_program.get("plcprogram", "none.py") self.uploaded = True ec = 0 @@ -655,6 +655,10 @@ class RevPiProgram(tkinter.Frame): else: sendname = fname.replace(dirselect, "")[1:] + # Prüfen ob Dateiname bereits als Startprogramm angegeben ist + if sendname == opt_program: + self.uploaded = False + # Datei übertragen try: ustatus = self.xmlcli.plcupload( diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 2051e76..a46989b 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # # RevPiPyControl -# Version: 0.4.0 +# Version: 0.4.1 # # Webpage: https://revpimodio.org/revpipyplc/ # (c) Sven Sager, License: LGPLv3 @@ -19,7 +19,6 @@ from functools import partial from mytools import addroot, gettrans from xmlrpc.client import ServerProxy - # Übersetzung laden _ = gettrans() @@ -99,6 +98,15 @@ class RevPiPyControl(tkinter.Frame): self._fillmbar() self._fillconnbar() + # Hilfe Menü + menu1 = tkinter.Menu(self.mbar, tearoff=False) + menu1.add_command( + label=_("Visit website..."), command=self.visitwebsite) + menu1.add_separator() + menu1.add_command(label=_("Info..."), command=self.infowindow) + # TODO: Menü einbauen + self.mbar.add_cascade(label=_("Help"), menu=menu1) + self.var_conn = tkinter.StringVar(self) self.txt_connect = tkinter.Entry( self, textvariable=self.var_conn, state="readonly", width=30) @@ -190,6 +198,10 @@ class RevPiPyControl(tkinter.Frame): )) self.mbar.entryconfig("PLC", state="normal") + def infowindow(self): + # TODO: Infofenster aufrufen + pass + def plcdebug(self): u"""Baut den Debugframe und packt ihn.""" self.btn_debug["state"] = "disabled" @@ -233,6 +245,16 @@ class RevPiPyControl(tkinter.Frame): def plclogs(self): u"""Öffnet das Fenster für Logdateien.""" + if "load_plclog" not in self.xmlfuncs: + tkmsg.showwarning( + _("Warning"), + _("This version of Logviewer ist not supported in version {} " + "of RevPiPyLoad on your RevPi! You need at least version " + "0.4.1.").format(self.cli.version()), + parent=self.master + ) + return None + if self.tklogs is None or len(self.tklogs.children) == 0: win = tkinter.Toplevel(self) self.tklogs = revpilogfile.RevPiLogfile(win, self.cli) @@ -244,10 +266,8 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( _("Warning"), - _( - "XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog" - ), + _("XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog"), parent=self.master ) else: @@ -264,10 +284,8 @@ class RevPiPyControl(tkinter.Frame): if self.xmlmode < 2: tkmsg.showwarning( _("Warning"), - _( - "XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog" - ), + _("XML-RPC access mode in the RevPiPyLoad " + "configuration is to small to access this dialog"), parent=self.master ) else: @@ -343,6 +361,9 @@ class RevPiPyControl(tkinter.Frame): self.master.after(1000, self.tmr_plcrunning) + def visitwebsite(self): + # TODO: Webseite besuchen + pass if __name__ == "__main__": root = tkinter.Tk() diff --git a/setup.py b/setup.py index 2d518aa..60d64c8 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ globsetup = { "author_email": "akira@narux.de", "url": "https://revpimodio.org/revpipyplc/", "license": "LGPLv3", - "version": "0.4.0", + "version": "0.4.1", "name": "revpipycontrol", From 1fec478e3f92441f845112b9927d9c928d3c4f95 Mon Sep 17 00:00:00 2001 From: NaruX Date: Fri, 30 Jun 2017 13:50:39 +0200 Subject: [PATCH 07/13] Sicherheitswarnung vor dem Output schreiben integriert Hauptfenster alles aufr?umen vor destroy() Wertepr?fung bei RevPiCheckClient int() Werten Bearbeitungsfunktion bei RevPiCheckClient eingebaut Hilfemen? mit Webbrowser aufruf eingebaut --- .hgignore | 1 + doc/revpicheckclient.html | 186 ++++++++++++++--- doc/revpilogfile.html | 97 ++++++--- doc/revpioption.html | 71 +++++-- doc/revpiplclist.html | 16 +- doc/revpiprogram.html | 51 +++-- doc/revpipycontrol.html | 160 +++++++++------ revpipycontrol.api | 52 +++-- revpipycontrol.bas | 1 + revpipycontrol.e4p | 3 +- .../locale/de/LC_MESSAGES/revpipycontrol.po | 113 ++++++---- revpipycontrol/revpicheckclient.py | 194 ++++++++++++++---- revpipycontrol/revpiprogram.py | 8 +- revpipycontrol/revpipycontrol.py | 30 ++- 14 files changed, 718 insertions(+), 265 deletions(-) diff --git a/.hgignore b/.hgignore index fe4cdbb..a10df60 100644 --- a/.hgignore +++ b/.hgignore @@ -6,3 +6,4 @@ revpipycontrol.egg-info/* deb/* .eric6project/* *.directory +*.mo diff --git a/doc/revpicheckclient.html b/doc/revpicheckclient.html index 79c32c2..3e8cd4b 100644 --- a/doc/revpicheckclient.html +++ b/doc/revpicheckclient.html @@ -10,7 +10,7 @@ revpicheckclient

Global Attributes

- +
None
_

Classes

@@ -35,7 +35,7 @@ tkinter.Frame

Class Attributes

- +
cli
tk
None

Class Methods

@@ -49,11 +49,20 @@ Methods RevPiCheckClient Instantiiert MyApp-Klasse. +__chval +Schreibt neuen Output Wert auf den RevPi. + __hidewin - +Verbergt übergebenes Fenster. + +__saveoldvalue +Speichert bei Keypress aktuellen Wert für wiederherstellung. __showwin - +Zeigt oder verbergt übergebenes Fenster. + +__spinboxkey +Prüft die Eingabe auf plausibilität. _createiogroup Erstellt IO-Gruppen. @@ -61,20 +70,35 @@ Methods _createwidgets Erstellt den Fensterinhalt. -_readvalues +_onfrmconf +Erstellt Fenster in einem Canvas. + +_warnwrite +Warnung für Benutzer über Schreibfunktion einmal fragen. + +_workvalues Alle Werte der Inputs und Outputs abrufen. -chval - - -onfrmconf - +hideallwindows +Versteckt alle Fenster. readvalues - +Ruft nur Input Werte von RevPi ab und aktualisiert Fenster. + +refreshvalues +Ruft alle IO Werte von RevPi ab und aktualisiert Fenster. toggleauto - +Schaltet zwischen Autorefresh um und aktualisiert Widgets. + +togglewrite +Schaltet zwischen DoWrite um und aktiviert Schreibfunktion. + +validatereturn +Überprüft die Rückgaben der setvalue Funktion. + +writevalues +Schreibt geänderte Outputs auf den RevPi.

@@ -88,49 +112,147 @@ RevPiCheckClient (Constructor)

RevPiCheckClient(master, xmlcli, xmlmode=0)

Instantiiert MyApp-Klasse. +

+

+RevPiCheckClient.__chval

+__chval(device, io, event=None) +

+Schreibt neuen Output Wert auf den RevPi.

RevPiCheckClient.__hidewin

__hidewin(win, event=None) - +

+Verbergt übergebenes Fenster. +

+
win:
+
+Fenster zum verbergen +
event:
+
+Tkinter Event +
+
+

+RevPiCheckClient.__saveoldvalue

+__saveoldvalue(event, tkvar) +

+Speichert bei Keypress aktuellen Wert für wiederherstellung. +

RevPiCheckClient.__showwin

__showwin(win) - -

-RevPiCheckClient._createiogroup

-_createiogroup(device, frame, iotype)

-Erstellt IO-Gruppen. -

+Zeigt oder verbergt übergebenes Fenster. +

+
win:
+
+Fenster zum anzeigen/verbergen +
+
+

+RevPiCheckClient.__spinboxkey

+__spinboxkey(device, io, event=None) +

+Prüft die Eingabe auf plausibilität. +

+
event:
+
+tkinter Event +
io:
+
+IO Liste mit tkinter Variable +
+

RevPiCheckClient._createwidgets

_createwidgets()

Erstellt den Fensterinhalt. -

+

-RevPiCheckClient._readvalues

-_readvalues() +RevPiCheckClient._onfrmconf +_onfrmconf(canvas) +

+Erstellt Fenster in einem Canvas. +

+
canvas:
+
+Canvas in dem Objekte erstellt werden sollen +
+
+

+RevPiCheckClient._warnwrite

+_warnwrite() +

+Warnung für Benutzer über Schreibfunktion einmal fragen. +

+
Returns:
+
+True, wenn Warnung einmal mit OK bestätigt wurde +
+
+

+RevPiCheckClient._workvalues

+_workvalues(io_dicts=None, writeout=False)

Alle Werte der Inputs und Outputs abrufen. -

+

+
io_dicts:
+
+Arbeit nur für dieses Dict() +
writeout:
+
+Änderungen auf RevPi schreiben +
+

-RevPiCheckClient.chval

-chval(device, io) - -

-RevPiCheckClient.onfrmconf

-onfrmconf(canvas) - +RevPiCheckClient.hideallwindows +hideallwindows() +

+Versteckt alle Fenster. +

RevPiCheckClient.readvalues

readvalues() - +

+Ruft nur Input Werte von RevPi ab und aktualisiert Fenster. +

+

+RevPiCheckClient.refreshvalues

+refreshvalues() +

+Ruft alle IO Werte von RevPi ab und aktualisiert Fenster. +

RevPiCheckClient.toggleauto

toggleauto() - +

+Schaltet zwischen Autorefresh um und aktualisiert Widgets. +

+

+RevPiCheckClient.togglewrite

+togglewrite() +

+Schaltet zwischen DoWrite um und aktiviert Schreibfunktion. +

+

+RevPiCheckClient.validatereturn

+validatereturn(returnlist) +

+Überprüft die Rückgaben der setvalue Funktion. +

+
returnlist:
+
+list() der xml Rückgabe +
+
+

+RevPiCheckClient.writevalues

+writevalues() +

+Schreibt geänderte Outputs auf den RevPi. +


\ No newline at end of file diff --git a/doc/revpilogfile.html b/doc/revpilogfile.html index e97a54a..79fb54b 100644 --- a/doc/revpilogfile.html +++ b/doc/revpilogfile.html @@ -10,7 +10,7 @@ revpilogfile

Global Attributes

- +
None
_

Classes

@@ -47,28 +47,28 @@ Methods + + + - + + + + - + - - - - + - - - - + - +
RevPiLogfileInit RevPiLogfile-Class.
_closewin
_createwidgetsErstellt alle Widgets.
_load_logLäd die angegebenen Logfiles herunter.
btn_clearappLeert die Logliste der App.
btn_clearplc
get_applinesLeert die Logliste des PLC.
get_applog
get_plclinesRuft App Logbuch ab.
get_plclogRuft PLC Logbuch ab.

@@ -80,35 +80,78 @@ Static Methods

RevPiLogfile (Constructor)

RevPiLogfile(master, xmlcli) +

+Init RevPiLogfile-Class. +

+

+RevPiLogfile._closewin

+_closewin(event)

RevPiLogfile._createwidgets

_createwidgets() - +

+Erstellt alle Widgets. +

+

+RevPiLogfile._load_log

+_load_log(textwidget, xmlcall, startposition, full) +

+Läd die angegebenen Logfiles herunter. +

+
textwidget:
+
+Widget in das Logs eingefügt werden sollen +
xmlcall:
+
+xmlrpc Funktion zum Abrufen der Logdaten +
startposition:
+
+Startposition ab der Logdaten kommen sollen +
full:
+
+Komplettes Logbuch laden +
+
+
Returns:
+
+Ende der Datei (neue Startposition) +
+

RevPiLogfile.btn_clearapp

btn_clearapp() - +

+Leert die Logliste der App. +

RevPiLogfile.btn_clearplc

btn_clearplc() - -

-RevPiLogfile.get_applines

-get_applines() - +

+Leert die Logliste des PLC. +

RevPiLogfile.get_applog

-get_applog() - -

-RevPiLogfile.get_plclines

-get_plclines() - +get_applog(full=False) +

+Ruft App Logbuch ab. +

+
full:
+
+Ganzes Logbuch laden +
+

RevPiLogfile.get_plclog

-get_plclog() - +get_plclog(full=False) +

+Ruft PLC Logbuch ab. +

+
full:
+
+Ganzes Logbuch laden +
+

\ No newline at end of file diff --git a/doc/revpioption.html b/doc/revpioption.html index 417e9fd..2a321f8 100644 --- a/doc/revpioption.html +++ b/doc/revpioption.html @@ -10,7 +10,7 @@ revpioption

Global Attributes

- +
None
_

Classes

@@ -47,22 +47,28 @@ Methods - + + + + + + + - + - + - + - + - +
RevPiOptionInit RevPiOption-Class.
_changesdonePrüft ob sich die Einstellungen geändert haben.
_checkclosePrüft ob Fenster beendet werden soll.
_createwidgetsErstellt Widgets.
_loadappdataLäd aktuelle Einstellungen vom RevPi.
_setappdataSpeichert geänderte Einstellungen auf RevPi.
askxmlonFragt Nuter, ob wirklicht abgeschaltet werden soll.
xmlmodsPasst XML-Optionszugriff an.

@@ -74,27 +80,66 @@ Static Methods

RevPiOption (Constructor)

RevPiOption(master, xmlcli, xmlmode) - +

+Init RevPiOption-Class. +

+
Returns:
+
+None +
+
+

+RevPiOption._changesdone

+_changesdone() +

+Prüft ob sich die Einstellungen geändert haben. +

+
Returns:
+
+True, wenn min. eine Einstellung geändert wurde +
+
+

+RevPiOption._checkclose

+_checkclose(event=None) +

+Prüft ob Fenster beendet werden soll. +

+
event:
+
+tkinter-Event +
+

RevPiOption._createwidgets

_createwidgets() - +

+Erstellt Widgets. +

RevPiOption._loadappdata

_loadappdata() - +

+Läd aktuelle Einstellungen vom RevPi. +

RevPiOption._setappdata

_setappdata() - +

+Speichert geänderte Einstellungen auf RevPi. +

RevPiOption.askxmlon

askxmlon() - +

+Fragt Nuter, ob wirklicht abgeschaltet werden soll. +

RevPiOption.xmlmods

xmlmods() - +

+Passt XML-Optionszugriff an. +


\ No newline at end of file diff --git a/doc/revpiplclist.html b/doc/revpiplclist.html index 9d27221..b7c66e1 100644 --- a/doc/revpiplclist.html +++ b/doc/revpiplclist.html @@ -10,7 +10,7 @@ revpiplclist

Global Attributes

- +
savefile
_
savefile

Classes

@@ -52,6 +52,9 @@ Methods RevPiPlcList +_checkclose + + _createwidgets @@ -67,9 +70,6 @@ Methods evt_btnadd -evt_btnclose - - evt_btnnew @@ -95,6 +95,10 @@ Static Methods

RevPiPlcList (Constructor)

RevPiPlcList(master) + +

+RevPiPlcList._checkclose

+_checkclose(event=None)

RevPiPlcList._createwidgets

@@ -115,10 +119,6 @@ RevPiPlcList.build_listconn

RevPiPlcList.evt_btnadd

evt_btnadd() - -

-RevPiPlcList.evt_btnclose

-evt_btnclose()

RevPiPlcList.evt_btnnew

diff --git a/doc/revpiprogram.html b/doc/revpiprogram.html index a00d6cf..d61ebd0 100644 --- a/doc/revpiprogram.html +++ b/doc/revpiprogram.html @@ -10,7 +10,7 @@ revpiprogram

Global Attributes

- +
savefile
_
savefile

Classes

@@ -35,7 +35,7 @@ tkinter.Frame

Class Attributes

- +
myapp
root
None

Class Methods

@@ -47,6 +47,9 @@ Methods + + + @@ -71,22 +74,22 @@ Methods - + - + - + - + - + - +
RevPiProgramInit RevPiProgram-Class.
_checkclose
_createwidgets Erstellt eine Dateiliste von einem Verzeichnis.
getpictoryrscLäd die piCtory Konfiguration herunter.
getprocimgLäd das aktuelle Prozessabbild herunter.
picontrolresetFürt ein Reset der piBridge durch.
plcdownloadLäd das aktuelle Projekt herunter.
plcuploadLädt das angegebene Projekt auf den RevPi.
setpictoryrscÜberträgt die angegebene piCtory-Konfiguration.

@@ -98,6 +101,12 @@ Static Methods

RevPiProgram (Constructor)

RevPiProgram(master, xmlcli, xmlmode, revpi) +

+Init RevPiProgram-Class. +

+

+RevPiProgram._checkclose

+_checkclose(event=None)

RevPiProgram._createwidgets

@@ -130,7 +139,7 @@ RevPiProgram.check_replacedir Gibt das rootdir von einem entpackten Verzeichnis zurueck.

Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt - und ob es eine piCtory Konfiguraiton im rootdir gibt. + und ob es eine piCtory Konfiguration im rootdir gibt.

rootdir:
@@ -161,27 +170,39 @@ Dateiliste

RevPiProgram.getpictoryrsc

getpictoryrsc() - +

+Läd die piCtory Konfiguration herunter. +

RevPiProgram.getprocimg

getprocimg() - +

+Läd das aktuelle Prozessabbild herunter. +

RevPiProgram.picontrolreset

picontrolreset() - +

+Fürt ein Reset der piBridge durch. +

RevPiProgram.plcdownload

plcdownload() - +

+Läd das aktuelle Projekt herunter. +

RevPiProgram.plcupload

plcupload() - +

+Lädt das angegebene Projekt auf den RevPi. +

RevPiProgram.setpictoryrsc

setpictoryrsc(filename=None) - +

+Überträgt die angegebene piCtory-Konfiguration. +


\ No newline at end of file diff --git a/doc/revpipycontrol.html b/doc/revpipycontrol.html index 11750e5..819a6c4 100644 --- a/doc/revpipycontrol.html +++ b/doc/revpipycontrol.html @@ -10,7 +10,7 @@ revpipycontrol

Global Attributes

- +
None
_

Classes

@@ -23,10 +23,7 @@ Classes

Functions

- - - - +
addrootHängt root-dir der Anwendung vor Dateinamen.
None


@@ -50,55 +47,67 @@ Methods - + - + - + + + + - + - + + + + + + + - + - - - - + - + - + - + - + + + + - + + + +
RevPiPyControlInit RevPiPyControl-Class.
_btnstateSetzt den state der Buttons.
_closeallSchließt alle Fenster.
_closeappRäumt auf und beendet Programm.
_createwidgets Erstellt den Fensterinhalt.
_fillconnbarGeneriert Menüeinträge für Verbindungen.
_fillmbarGeneriert Menüeinträge.
_opt_conn
infowindowÖffnet das Fenster für die Verbindungen.
plcdebugBaut den Debugframe und packt ihn.
plclistÖffnet das Fenster für die Verbindungen.
plclogs
plcmonitorStartet das Monitorfenster.Öffnet das Fenster für Logdateien.
plcoptions Startet das Optionsfenster.
plcprogramStartet das Programmfenster.
plcrestartStartet das PLC Programm neu.
plcstartStartet das PLC Programm.
plcstopBeendet das PLC Programm.
serverdisconnectTrennt eine bestehende Verbindung.
servererrorSetzt alles auf NULL.Setzt alles zurück für neue Verbindungen.
tmr_plcrunning
visitwebsiteÖffnet auf dem System einen Webbrowser zur Projektseite.

@@ -110,15 +119,37 @@ Static Methods

RevPiPyControl (Constructor)

RevPiPyControl(master=None) - +

+Init RevPiPyControl-Class. +

+
master:
+
+tkinter master +
+

RevPiPyControl._btnstate

_btnstate() - +

+Setzt den state der Buttons. +

RevPiPyControl._closeall

_closeall() - +

+Schließt alle Fenster. +

+

+RevPiPyControl._closeapp

+_closeapp(event=None) +

+Räumt auf und beendet Programm. +

+
event:
+
+tkinter Event +
+

RevPiPyControl._createwidgets

_createwidgets() @@ -128,28 +159,42 @@ Erstellt den Fensterinhalt.

RevPiPyControl._fillconnbar

_fillconnbar() - +

+Generiert Menüeinträge für Verbindungen. +

RevPiPyControl._fillmbar

_fillmbar() - +

+Generiert Menüeinträge. +

RevPiPyControl._opt_conn

_opt_conn(text) - + +

+RevPiPyControl.infowindow

+infowindow() +

+Öffnet das Fenster für die Verbindungen. +

+

+RevPiPyControl.plcdebug

+plcdebug() +

+Baut den Debugframe und packt ihn. +

RevPiPyControl.plclist

plclist() - +

+Öffnet das Fenster für die Verbindungen. +

RevPiPyControl.plclogs

plclogs() - -

-RevPiPyControl.plcmonitor

-plcmonitor()

-Startet das Monitorfenster. +Öffnet das Fenster für Logdateien.

RevPiPyControl.plcoptions

@@ -160,50 +205,49 @@ Startet das Optionsfenster.

RevPiPyControl.plcprogram

plcprogram() - +

+Startet das Programmfenster. +

RevPiPyControl.plcrestart

plcrestart() - +

+Startet das PLC Programm neu. +

RevPiPyControl.plcstart

plcstart() - +

+Startet das PLC Programm. +

RevPiPyControl.plcstop

plcstop() - +

+Beendet das PLC Programm. +

+

+RevPiPyControl.serverdisconnect

+serverdisconnect() +

+Trennt eine bestehende Verbindung. +

RevPiPyControl.servererror

servererror()

-Setzt alles auf NULL. +Setzt alles zurück für neue Verbindungen.

RevPiPyControl.tmr_plcrunning

tmr_plcrunning() - - -

- -

addroot

-addroot(filename) + +

+RevPiPyControl.visitwebsite

+visitwebsite()

-Hängt root-dir der Anwendung vor Dateinamen. -

- Je nach Ausführungsart der Anwendung muss das root-dir über - andere Arten abgerufen werden. -

-
filename:
-
-Datei oder Ordnername -
-
-
Returns:
-
-root dir -
-
+Öffnet auf dem System einen Webbrowser zur Projektseite. +


\ No newline at end of file diff --git a/revpipycontrol.api b/revpipycontrol.api index ae08326..91279e4 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -1,35 +1,54 @@ +mytools.addroot?4(filename) +mytools.gettrans?4(proglang=None) +revpicheckclient.RevPiCheckClient.__chval?6(device, io, event=None) revpicheckclient.RevPiCheckClient.__hidewin?6(win, event=None) +revpicheckclient.RevPiCheckClient.__saveoldvalue?6(event, tkvar) revpicheckclient.RevPiCheckClient.__showwin?6(win) +revpicheckclient.RevPiCheckClient.__spinboxkey?6(device, io, event=None) revpicheckclient.RevPiCheckClient._createiogroup?5(device, frame, iotype) revpicheckclient.RevPiCheckClient._createwidgets?5() -revpicheckclient.RevPiCheckClient._readvalues?5() -revpicheckclient.RevPiCheckClient.chval?4(device, io) -revpicheckclient.RevPiCheckClient.cli?7 -revpicheckclient.RevPiCheckClient.onfrmconf?4(canvas) +revpicheckclient.RevPiCheckClient._onfrmconf?5(canvas) +revpicheckclient.RevPiCheckClient._warnwrite?5() +revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False) +revpicheckclient.RevPiCheckClient.hideallwindows?4() revpicheckclient.RevPiCheckClient.readvalues?4() -revpicheckclient.RevPiCheckClient.tk?7 +revpicheckclient.RevPiCheckClient.refreshvalues?4() revpicheckclient.RevPiCheckClient.toggleauto?4() +revpicheckclient.RevPiCheckClient.togglewrite?4() +revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist) +revpicheckclient.RevPiCheckClient.writevalues?4() revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0) +revpicheckclient._?8 +revpiinfo.RevPiInfo._closewin?5(event=None) +revpiinfo.RevPiInfo._createwidgets?5() +revpiinfo.RevPiInfo.app?7 +revpiinfo.RevPiInfo.root?7 +revpiinfo.RevPiInfo?1(master) +revpiinfo._?8 +revpilogfile.RevPiLogfile._closewin?5(event) revpilogfile.RevPiLogfile._createwidgets?5() +revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full) revpilogfile.RevPiLogfile.btn_clearapp?4() revpilogfile.RevPiLogfile.btn_clearplc?4() -revpilogfile.RevPiLogfile.get_applines?4() -revpilogfile.RevPiLogfile.get_applog?4() -revpilogfile.RevPiLogfile.get_plclines?4() -revpilogfile.RevPiLogfile.get_plclog?4() +revpilogfile.RevPiLogfile.get_applog?4(full=False) +revpilogfile.RevPiLogfile.get_plclog?4(full=False) revpilogfile.RevPiLogfile?1(master, xmlcli) +revpilogfile._?8 +revpioption.RevPiOption._changesdone?5() +revpioption.RevPiOption._checkclose?5(event=None) revpioption.RevPiOption._createwidgets?5() revpioption.RevPiOption._loadappdata?5() revpioption.RevPiOption._setappdata?5() revpioption.RevPiOption.askxmlon?4() revpioption.RevPiOption.xmlmods?4() revpioption.RevPiOption?1(master, xmlcli, xmlmode) +revpioption._?8 +revpiplclist.RevPiPlcList._checkclose?5(event=None) revpiplclist.RevPiPlcList._createwidgets?5() revpiplclist.RevPiPlcList._loadappdata?5() revpiplclist.RevPiPlcList._saveappdata?5() revpiplclist.RevPiPlcList.build_listconn?4() revpiplclist.RevPiPlcList.evt_btnadd?4() -revpiplclist.RevPiPlcList.evt_btnclose?4() revpiplclist.RevPiPlcList.evt_btnnew?4() revpiplclist.RevPiPlcList.evt_btnremove?4() revpiplclist.RevPiPlcList.evt_btnsave?4() @@ -38,8 +57,10 @@ revpiplclist.RevPiPlcList.evt_listconn?4(evt=None) revpiplclist.RevPiPlcList.myapp?7 revpiplclist.RevPiPlcList.root?7 revpiplclist.RevPiPlcList?1(master) +revpiplclist._?8 revpiplclist.get_connections?4() revpiplclist.savefile?7 +revpiprogram.RevPiProgram._checkclose?5(event=None) revpiprogram.RevPiProgram._createwidgets?5() revpiprogram.RevPiProgram._evt_optdown?5(text="") revpiprogram.RevPiProgram._evt_optup?5(text="") @@ -49,31 +70,34 @@ revpiprogram.RevPiProgram.check_replacedir?4(rootdir) revpiprogram.RevPiProgram.create_filelist?4(rootdir) revpiprogram.RevPiProgram.getpictoryrsc?4() revpiprogram.RevPiProgram.getprocimg?4() -revpiprogram.RevPiProgram.myapp?7 revpiprogram.RevPiProgram.picontrolreset?4() revpiprogram.RevPiProgram.plcdownload?4() revpiprogram.RevPiProgram.plcupload?4() -revpiprogram.RevPiProgram.root?7 revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None) revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi) +revpiprogram._?8 revpiprogram.savefile?7 revpipycontrol.RevPiPyControl._btnstate?5() revpipycontrol.RevPiPyControl._closeall?5() +revpipycontrol.RevPiPyControl._closeapp?5(event=None) revpipycontrol.RevPiPyControl._createwidgets?5() revpipycontrol.RevPiPyControl._fillconnbar?5() revpipycontrol.RevPiPyControl._fillmbar?5() revpipycontrol.RevPiPyControl._opt_conn?5(text) +revpipycontrol.RevPiPyControl.infowindow?4() revpipycontrol.RevPiPyControl.myapp?7 +revpipycontrol.RevPiPyControl.plcdebug?4() revpipycontrol.RevPiPyControl.plclist?4() revpipycontrol.RevPiPyControl.plclogs?4() -revpipycontrol.RevPiPyControl.plcmonitor?4() revpipycontrol.RevPiPyControl.plcoptions?4() revpipycontrol.RevPiPyControl.plcprogram?4() revpipycontrol.RevPiPyControl.plcrestart?4() revpipycontrol.RevPiPyControl.plcstart?4() revpipycontrol.RevPiPyControl.plcstop?4() revpipycontrol.RevPiPyControl.root?7 +revpipycontrol.RevPiPyControl.serverdisconnect?4() revpipycontrol.RevPiPyControl.servererror?4() revpipycontrol.RevPiPyControl.tmr_plcrunning?4() +revpipycontrol.RevPiPyControl.visitwebsite?4() revpipycontrol.RevPiPyControl?1(master=None) -revpipycontrol.addroot?4(filename) +revpipycontrol._?8 diff --git a/revpipycontrol.bas b/revpipycontrol.bas index c02ecc3..32a817a 100644 --- a/revpipycontrol.bas +++ b/revpipycontrol.bas @@ -1,4 +1,5 @@ RevPiCheckClient tkinter.Frame +RevPiInfo tkinter.Frame RevPiLogfile tkinter.Frame RevPiOption tkinter.Frame RevPiPlcList tkinter.Frame diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index 4e778ae..24fdc69 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -22,6 +22,7 @@ revpipycontrol/revpioption.py revpipycontrol/revpiprogram.py revpipycontrol/mytools.py + revpipycontrol/revpiinfo.py diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 0fd8feb..521bfb6 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-29 20:10+0200\n" -"PO-Revision-Date: 2017-06-29 20:10+0200\n" +"POT-Creation-Date: 2017-06-30 13:50+0200\n" +"PO-Revision-Date: 2017-06-30 13:50+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -15,34 +15,72 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SearchPath-0: .\n" -#: revpicheckclient.py:143 +#: revpicheckclient.py:103 revpicheckclient.py:395 revpioption.py:288 +#: revpiplclist.py:198 revpiprogram.py:306 revpiprogram.py:337 +#: revpiprogram.py:400 revpiprogram.py:433 revpiprogram.py:515 +#: revpiprogram.py:587 revpiprogram.py:618 revpiprogram.py:631 +#: revpiprogram.py:686 revpiprogram.py:706 revpiprogram.py:714 +#: revpipycontrol.py:342 +msgid "Error" +msgstr "Fehler" + +#: revpicheckclient.py:104 +msgid "" +"Given value for Output '{}' is not valid! \n" +"Reset to '{}'" +msgstr "" +"Angegebener Wert bei Output '{}' ist nicht gültig! \n" +"Setze auf '{}' zurück" + +#: revpicheckclient.py:202 msgid "Devices of RevPi" msgstr "Devices vom RevPi" -#: revpicheckclient.py:175 +#: revpicheckclient.py:234 msgid "Control" msgstr "Kontrolle" -#: revpicheckclient.py:179 +#: revpicheckclient.py:238 msgid "Read all IOs" msgstr "IOs aktualisieren" -#: revpicheckclient.py:184 +#: revpicheckclient.py:243 msgid "Read just Inputs" msgstr "Inputs lesen" -#: revpicheckclient.py:189 +#: revpicheckclient.py:248 msgid "Write Outputs" msgstr "Outputs schreiben" -#: revpicheckclient.py:195 +#: revpicheckclient.py:254 msgid "Autorefresh values" msgstr "Aktualisiere automatisch" -#: revpicheckclient.py:201 +#: revpicheckclient.py:262 msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" +#: revpicheckclient.py:276 revpiprogram.py:407 revpipycontrol.py:228 +#: revpipycontrol.py:267 revpipycontrol.py:285 revpipycontrol.py:303 +msgid "Warning" +msgstr "Warnung" + +#: revpicheckclient.py:277 +msgid "" +"You want to set outputs on the RevPi! Note that these are set " +"IMMEDIATELY!!! \n" +"If another control program is running on the RevPi, it could interfere and " +"reset the outputs." +msgstr "" +"Sie wollen Outputs auf dem RevPi setzen! Beachten Sie, dass diese SOFORT " +"gesetzt werden!!! \n" +"Wenn auf dem RevPi ein anderes Programm zur Steuerung läuft, könnte dies " +"gestört werden und die Ausgänge wieder zurücksetzen." + +#: revpicheckclient.py:392 +msgid "Error set value of device '{}' Output '{}': {} \n" +msgstr "Fehler beim Setzen auf Device '{}' bei Output '{}': {}\n" + #: revpilogfile.py:37 msgid "RevPi Python PLC Logs" msgstr "RevPi Python PLC Logdaten" @@ -184,14 +222,6 @@ msgstr "Information" msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: revpioption.py:288 revpiplclist.py:198 revpiprogram.py:306 -#: revpiprogram.py:337 revpiprogram.py:400 revpiprogram.py:433 -#: revpiprogram.py:515 revpiprogram.py:587 revpiprogram.py:618 -#: revpiprogram.py:631 revpiprogram.py:686 revpiprogram.py:706 -#: revpiprogram.py:714 revpipycontrol.py:325 -msgid "Error" -msgstr "Fehler" - #: revpioption.py:289 msgid "The settings could not be saved. This can happen if values are wrong!" msgstr "" @@ -345,7 +375,7 @@ msgstr "piControlReset ausführen" msgid "execute" msgstr "ausführen" -#: revpiprogram.py:216 revpipycontrol.py:95 +#: revpiprogram.py:216 revpipycontrol.py:107 msgid "Exit" msgstr "Beenden" @@ -412,11 +442,6 @@ msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:407 revpipycontrol.py:211 revpipycontrol.py:250 -#: revpipycontrol.py:268 revpipycontrol.py:286 -msgid "Warning" -msgstr "Warnung" - #: revpiprogram.py:408 msgid "" "The piCtroy configuration has been saved successfully. \n" @@ -486,67 +511,67 @@ msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" -#: revpipycontrol.py:93 +#: revpipycontrol.py:105 msgid "Connections..." msgstr "Verbindungen..." -#: revpipycontrol.py:96 +#: revpipycontrol.py:108 msgid "Main" msgstr "Datei" -#: revpipycontrol.py:104 +#: revpipycontrol.py:116 msgid "Visit website..." msgstr "Webseite besuchen..." -#: revpipycontrol.py:106 +#: revpipycontrol.py:118 msgid "Info..." msgstr "Info..." -#: revpipycontrol.py:108 +#: revpipycontrol.py:119 msgid "Help" msgstr "Hilfe" -#: revpipycontrol.py:116 +#: revpipycontrol.py:127 msgid "PLC start" msgstr "PLC Start" -#: revpipycontrol.py:121 +#: revpipycontrol.py:132 msgid "PLC stop" msgstr "PLC Stopp" -#: revpipycontrol.py:126 +#: revpipycontrol.py:137 msgid "PLC restart" msgstr "PLC Neustart" -#: revpipycontrol.py:131 +#: revpipycontrol.py:142 msgid "PLC logs" msgstr "PLC Logs" -#: revpipycontrol.py:142 +#: revpipycontrol.py:153 msgid "PLC watch mode" msgstr "PLC watch Modus" -#: revpipycontrol.py:159 +#: revpipycontrol.py:170 msgid "PLC log..." msgstr "PLC Log..." -#: revpipycontrol.py:161 +#: revpipycontrol.py:172 msgid "PLC options..." msgstr "PLC Optionen..." -#: revpipycontrol.py:163 +#: revpipycontrol.py:174 msgid "PLC program..." msgstr "PLC Programm..." -#: revpipycontrol.py:167 +#: revpipycontrol.py:178 msgid "Disconnect" msgstr "Trennen" -#: revpipycontrol.py:172 +#: revpipycontrol.py:183 msgid "Connect" msgstr "Verbinden" -#: revpipycontrol.py:212 +#: revpipycontrol.py:229 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " "You need at least version 0.4.0." @@ -554,7 +579,7 @@ msgstr "" "Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " "unterstützt! Sie benötigen mindestens Version 0.4.0." -#: revpipycontrol.py:251 +#: revpipycontrol.py:268 msgid "" "This version of Logviewer ist not supported in version {} of RevPiPyLoad on " "your RevPi! You need at least version 0.4.1." @@ -562,7 +587,7 @@ msgstr "" "Diese Version vom Logbetrachter wird in der RevPiPyLoad Version {} auf Ihrem " "RevPi nicht unterstützt! Sie benötigen mindestens Version 0.4.1." -#: revpipycontrol.py:269 revpipycontrol.py:287 +#: revpipycontrol.py:286 revpipycontrol.py:304 msgid "" "XML-RPC access mode in the RevPiPyLoad configuration is to small to access " "this dialog" @@ -570,6 +595,10 @@ msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:326 +#: revpipycontrol.py:343 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" + +#~ msgid "Given value for Output '{}' is not valid! Reset to '{}'" +#~ msgstr "" +#~ "Angegebener Wert bei Output '{}' ist nicht gültig! Setze auf '{}' zurück" diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index ca6941a..a9b4f27 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -9,8 +9,9 @@ import pickle import tkinter -from threading import Lock +import tkinter.messagebox as tkmsg from mytools import gettrans +from threading import Lock from xmlrpc.client import ServerProxy, MultiCall # Übersetzung laden @@ -27,12 +28,15 @@ class RevPiCheckClient(tkinter.Frame): self.xmlmode = xmlmode self.cli = xmlcli self.cli.psstart() - self.lst_devices = self.cli.ps_devices() + self.dict_devices = {v[0]: v[1] for v in self.cli.ps_devices()} self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) self.lk = Lock() - self.lst_wins = [] + self.dict_wins = {} + self.__checkwrite = True + self.__lockedvar = None + self.__oldvalue = None self.autorw = tkinter.BooleanVar() self.dowrite = tkinter.BooleanVar() @@ -43,27 +47,76 @@ class RevPiCheckClient(tkinter.Frame): # Aktuelle Werte einlesen self.refreshvalues() - def __chval(self, device, io): - if self.dowrite.get(): + def __chval(self, device, io, event=None): + u"""Schreibt neuen Output Wert auf den RevPi.""" + if self.dowrite.get() and self._warnwrite(): with self.lk: - self.cli.ps_setvalue(device, io[0], io[5].get()) + self.validatereturn( + self.cli.ps_setvalue(device, io[0], io[5].get()) + ) # Alles neu einlesen wenn nicht AutoRW aktiv ist if not self.autorw.get(): self.refreshvalues() + self.__lockedvar = None + def __hidewin(self, win, event=None): + u"""Verbergt übergebenes Fenster. + @param win: Fenster zum verbergen + @param event: Tkinter Event""" win.withdraw() + def __saveoldvalue(self, event, tkvar): + u"""Speichert bei Keypress aktuellen Wert für wiederherstellung.""" + if self.__lockedvar is None: + self.__lockedvar = tkvar + try: + self.__oldvalue = tkvar.get() + except Exception: + pass + def __showwin(self, win): + u"""Zeigt oder verbergt übergebenes Fenster. + @param win: Fenster zum anzeigen/verbergen""" if win.winfo_viewable(): win.withdraw() else: win.deiconify() - def _createiogroup(self, device, frame, iotype): - """Erstellt IO-Gruppen.""" + def __spinboxkey(self, device, io, event=None): + u"""Prüft die Eingabe auf plausibilität. + @param event: tkinter Event + @param io: IO Liste mit tkinter Variable""" + # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] + try: + newvalue = io[5].get() + # Wertebereich prüfen + if newvalue < 0 or newvalue > 255 * io[1]: + raise ValueError("too big") + self.__chval(device, io) + + except Exception: + io[5].set(self.__oldvalue) + tkmsg.showerror( + _("Error"), + _("Given value for Output '{}' is not valid! \nReset to ""'{}'" + "").format(self.dict_devices[device], self.__oldvalue), + parent=self.dict_wins[device] + ) + + # Focus zurücksetzen + event.widget.focus_set() + + def _createiogroup(self, device, frame, iotype): + u"""Erstellt IO-Gruppen. + + @param device: Deviceposition + @param frame: tkinter Frame + @iotype: 'inp' oder 'out' als str() + + """ # IO-Typen festlegen if iotype == "inp": lst_io = self.dict_inps[device] @@ -120,10 +173,16 @@ class RevPiCheckClient(tkinter.Frame): check.grid(column=1, row=rowcount) else: var = tkinter.IntVar() - - # FIXME: Mehrere Bytes möglich txt = tkinter.Spinbox(s_frame, to=255 * io[1]) - + txt.bind( + "", + lambda event, tkvar=var: self.__saveoldvalue(event, tkvar) + ) + txt.bind( + "", + lambda event, device=device, io=io: + self.__spinboxkey(device, io, event) + ) txt["command"] = \ lambda device=device, io=io: self.__chval(device, io) txt["state"] = "disabled" if iotype == "inp" else "normal" @@ -131,7 +190,7 @@ class RevPiCheckClient(tkinter.Frame): txt["textvariable"] = var txt.grid(column=1, row=rowcount) - # Steuerelementvariable in IO übernehmen + # Steuerelementvariable in IO übernehmen (mutabel) io.append(var) rowcount += 1 @@ -143,31 +202,31 @@ class RevPiCheckClient(tkinter.Frame): devgrp["text"] = _("Devices of RevPi") devgrp.pack(fill="y", side="left") - for dev in self.lst_devices: + for dev in self.dict_devices: win = tkinter.Toplevel(self) - win.wm_title(dev[1]) + win.wm_title(self.dict_devices[dev]) win.protocol( "WM_DELETE_WINDOW", lambda win=win: self.__hidewin(win) ) win.resizable(False, True) win.withdraw() - self.lst_wins.append(win) + self.dict_wins[dev] = win # Devicegruppe erstellen group = tkinter.LabelFrame(win) - group["text"] = dev[1] + group["text"] = self.dict_devices[dev] group.pack(side="left", fill="both", expand=True) for iotype in ["inp", "out"]: frame = tkinter.Frame(group) frame.pack(side="left", fill="both", expand=True) - self._createiogroup(dev[0], frame, iotype) + self._createiogroup(dev, frame, iotype) # Button erstellen btn = tkinter.Button(devgrp) btn["command"] = lambda win=win: self.__showwin(win) - btn["text"] = dev[1] + btn["text"] = self.dict_devices[dev] btn.pack(fill="x", padx=10, pady=5) # Steuerungsfunktionen @@ -196,17 +255,38 @@ class RevPiCheckClient(tkinter.Frame): check["variable"] = self.autorw check.pack(anchor="w") - check = tkinter.Checkbutton(cntgrp) - check["state"] = "disabled" if self.xmlmode < 3 else "normal" - check["text"] = _("Write values to RevPi") - check["variable"] = self.dowrite - check.pack(anchor="w") + self.chk_dowrite = tkinter.Checkbutton(cntgrp) + self.chk_dowrite["command"] = self.togglewrite + self.chk_dowrite["state"] = "normal" if self.xmlmode >= 3 \ + and self.autorw.get() else "disabled" + self.chk_dowrite["text"] = _("Write values to RevPi") + self.chk_dowrite["variable"] = self.dowrite + self.chk_dowrite.pack(anchor="w") def _onfrmconf(self, canvas): + u"""Erstellt Fenster in einem Canvas. + @param canvas: Canvas in dem Objekte erstellt werden sollen""" canvas.configure(scrollregion=canvas.bbox("all")) + def _warnwrite(self): + u"""Warnung für Benutzer über Schreibfunktion einmal fragen. + @returns: True, wenn Warnung einmal mit OK bestätigt wurde""" + if self.__checkwrite: + self.__checkwrite = not tkmsg.askokcancel( + _("Warning"), + _("You want to set outputs on the RevPi! Note that these are " + "set IMMEDIATELY!!! \nIf another control program is " + "running on the RevPi, it could interfere and reset the " + "outputs."), + icon=tkmsg.WARNING, + parent=self.master + ) + return not self.__checkwrite + def _workvalues(self, io_dicts=None, writeout=False): - """Alle Werte der Inputs und Outputs abrufen.""" + u"""Alle Werte der Inputs und Outputs abrufen. + @param io_dicts: Arbeit nur für dieses Dict() + @param writeout: Änderungen auf RevPi schreiben""" # Abfragelisten vorbereiten if io_dicts is None: @@ -220,13 +300,17 @@ class RevPiCheckClient(tkinter.Frame): if writeout: xmlmc = MultiCall(self.cli) - for dev in self.lst_devices: + for dev in self.dict_devices: # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] # IO Typ verarbeiten for iotype in io_dicts: # ios verarbeiten - for io in iotype[dev[0]]: + for io in iotype[dev]: + + # Gesperrte Variable überspringen + if io[5] == self.__lockedvar: + continue # Bytes umwandeln int_byte = int.from_bytes( @@ -236,55 +320,81 @@ class RevPiCheckClient(tkinter.Frame): # Bit-IO new_val = bool(int_byte & 1 << io[4]) if writeout and new_val != io[5].get(): - xmlmc.ps_setvalue(dev[0], io[0], io[5].get()) + xmlmc.ps_setvalue(dev, io[0], io[5].get()) else: io[5].set(new_val) else: # Byte-IO if writeout and int_byte != io[5].get(): - xmlmc.ps_setvalue(dev[0], io[0], io[5].get()) + xmlmc.ps_setvalue(dev, io[0], io[5].get()) else: io[5].set(int_byte) # Werte per Multicall schreiben if writeout: with self.lk: - xmlmc() + self.validatereturn(xmlmc()) if self.autorw.get(): self.master.after(200, self._workvalues) def hideallwindows(self): - for win in self.lst_wins: - win.withdraw() + u"""Versteckt alle Fenster.""" + for win in self.dict_wins: + self.dict_wins[win].withdraw() def readvalues(self): + u"""Ruft nur Input Werte von RevPi ab und aktualisiert Fenster.""" if not self.autorw.get(): self._workvalues([self.dict_inps]) def refreshvalues(self): + u"""Ruft alle IO Werte von RevPi ab und aktualisiert Fenster.""" if not self.autorw.get(): self._workvalues() def toggleauto(self): + u"""Schaltet zwischen Autorefresh um und aktualisiert Widgets.""" stateval = "disabled" if self.autorw.get() else "normal" self.btn_refresh["state"] = stateval self.btn_read["state"] = stateval self.btn_write["state"] = stateval + self.chk_dowrite["state"] = "normal" if self.xmlmode >= 3 \ + and self.autorw.get() else "disabled" + if self.autorw.get(): self._workvalues() + else: + self.dowrite.set(False) + + def togglewrite(self): + u"""Schaltet zwischen DoWrite um und aktiviert Schreibfunktion.""" + if self._warnwrite(): + self.refreshvalues() + else: + self.dowrite.set(False) + + def validatereturn(self, returnlist): + u"""Überprüft die Rückgaben der setvalue Funktion. + @param returnlist: list() der xml Rückgabe""" + if type(returnlist[0]) != list: + returnlist = [returnlist] + + str_errmsg = "" + for lst_result in returnlist: + # [device, io, status, msg] + + if not lst_result[2]: + # Fehlermeldungen erstellen + devicename = self.dict_devices[lst_result[0]] + str_errmsg += _( + "Error set value of device '{}' Output '{}': {} \n" + ).format(devicename, lst_result[1], lst_result[3]) + if str_errmsg != "": + tkmsg.showerror(_("Error"), str_errmsg) def writevalues(self): - if not self.autorw.get(): + u"""Schreibt geänderte Outputs auf den RevPi.""" + if self._warnwrite() and not self.autorw.get(): self._workvalues([self.dict_outs], True) - - -# Testdrive -if __name__ == "__main__": - cli = ServerProxy("http://192.168.50.35:55123") - cli.psstart() - - tk = tkinter.Tk() - RevPiCheckClient(tk, cli, 3) - tk.mainloop() diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 269eddd..d9cd70c 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -646,7 +646,7 @@ class RevPiProgram(tkinter.Frame): if fname == rscfile: continue - # TODO: Fehlerabfang bei Dateilesen + # FIXME: Fehlerabfang bei Dateilesen with open(fname, "rb") as fh: # Dateinamen ermitteln @@ -719,9 +719,3 @@ class RevPiProgram(tkinter.Frame): # Temp-Dir aufräumen if dirtmp is not None: rmtree(dirtmp) - - -if __name__ == "__main__": - root = tkinter.Tk() - myapp = RevPiProgram(root, None, "test") - root.mainloop() diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index a46989b..8f234d0 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -1,13 +1,14 @@ #!/usr/bin/python3 # # RevPiPyControl -# Version: 0.4.1 +# Version: see global var pycontrolverion # # Webpage: https://revpimodio.org/revpipyplc/ # (c) Sven Sager, License: LGPLv3 # # -*- coding: utf-8 -*- import revpicheckclient +import revpiinfo import revpilogfile import revpioption import revpiplclist @@ -15,6 +16,7 @@ import revpiprogram import socket import tkinter import tkinter.messagebox as tkmsg +import webbrowser from functools import partial from mytools import addroot, gettrans from xmlrpc.client import ServerProxy @@ -22,6 +24,8 @@ from xmlrpc.client import ServerProxy # Übersetzung laden _ = gettrans() +pycontrolversion = "0.4.1" + class RevPiPyControl(tkinter.Frame): @@ -29,6 +33,7 @@ class RevPiPyControl(tkinter.Frame): u"""Init RevPiPyControl-Class. @param master: tkinter master""" super().__init__(master) + self.master.protocol("WM_DELETE_WINDOW", self._closeapp) self.pack(fill="both", expand=True) self.cli = None @@ -74,8 +79,15 @@ class RevPiPyControl(tkinter.Frame): self.tkprogram.destroy() if self.debugframe is not None: self.debugframe.destroy() + self.cli.psstop() self.debugframe = None + def _closeapp(self, event=None): + u"""Räumt auf und beendet Programm. + @param event: tkinter Event""" + self._closeall() + self.master.destroy() + def _createwidgets(self): u"""Erstellt den Fensterinhalt.""" # Hauptfenster @@ -104,7 +116,6 @@ class RevPiPyControl(tkinter.Frame): label=_("Visit website..."), command=self.visitwebsite) menu1.add_separator() menu1.add_command(label=_("Info..."), command=self.infowindow) - # TODO: Menü einbauen self.mbar.add_cascade(label=_("Help"), menu=menu1) self.var_conn = tkinter.StringVar(self) @@ -199,8 +210,14 @@ class RevPiPyControl(tkinter.Frame): self.mbar.entryconfig("PLC", state="normal") def infowindow(self): - # TODO: Infofenster aufrufen - pass + u"""Öffnet das Fenster für die Verbindungen.""" + win = tkinter.Toplevel(self) + revpiinfo.RevPiInfo(win) + win.focus_set() + win.grab_set() + self.wait_window(win) + self.dict_conn = revpiplclist.get_connections() + self._fillconnbar() def plcdebug(self): u"""Baut den Debugframe und packt ihn.""" @@ -362,8 +379,9 @@ class RevPiPyControl(tkinter.Frame): self.master.after(1000, self.tmr_plcrunning) def visitwebsite(self): - # TODO: Webseite besuchen - pass + u"""Öffnet auf dem System einen Webbrowser zur Projektseite.""" + webbrowser.open("https://revpimodio.org") + if __name__ == "__main__": root = tkinter.Tk() From 256a95aa8b0313b12b8f97b8e24d300c29280cc2 Mon Sep 17 00:00:00 2001 From: NaruX Date: Fri, 30 Jun 2017 21:06:06 +0200 Subject: [PATCH 08/13] Buxfix: mkstemp Umstellung R?ckmeldungen bei piCtory Konfiguration detailierter Info-Fenster eingebunden --- doc/mytools.html | 59 +++++ doc/revpiinfo.html | 99 ++++++++ doc/revpilogfile.html | 19 +- doc/revpiplclist.html | 53 +++-- doc/revpipycontrol.html | 6 +- revpipycontrol.api | 12 +- .../locale/de/LC_MESSAGES/revpipycontrol.po | 220 ++++++++++++------ revpipycontrol/revpicheckclient.py | 2 +- revpipycontrol/revpiinfo.py | 150 ++++++++++++ revpipycontrol/revpilogfile.py | 6 +- revpipycontrol/revpiplclist.py | 19 +- revpipycontrol/revpiprogram.py | 41 +++- revpipycontrol/revpipycontrol.py | 4 +- 13 files changed, 568 insertions(+), 122 deletions(-) create mode 100644 doc/mytools.html create mode 100644 doc/revpiinfo.html create mode 100644 revpipycontrol/revpiinfo.py diff --git a/doc/mytools.html b/doc/mytools.html new file mode 100644 index 0000000..f7b99f6 --- /dev/null +++ b/doc/mytools.html @@ -0,0 +1,59 @@ + + +mytools + + + +

+mytools

+ +

+Global Attributes

+ + +
None
+

+Classes

+ + +
None
+

+Functions

+ + + + + + + + +
addrootHängt root-dir der Anwendung vor Dateinamen.
gettrans
+

+ +

addroot

+addroot(filename) +

+Hängt root-dir der Anwendung vor Dateinamen. +

+ Je nach Ausführungsart der Anwendung muss das root-dir über + andere Arten abgerufen werden. +

+
filename:
+
+Datei oder Ordnername +
+
+
Returns:
+
+root dir +
+
+ +

+ +

gettrans

+gettrans(proglang=None) + + +
+ \ No newline at end of file diff --git a/doc/revpiinfo.html b/doc/revpiinfo.html new file mode 100644 index 0000000..3ff9473 --- /dev/null +++ b/doc/revpiinfo.html @@ -0,0 +1,99 @@ + + +revpiinfo + + + +

+revpiinfo

+ +

+Global Attributes

+ + +
_
+

+Classes

+ + + + + +
RevPiInfo
+

+Functions

+ + +
None
+

+ +

RevPiInfo

+ +

+Derived from

+tkinter.Frame +

+Class Attributes

+ + +
app
cli
root
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + +
RevPiInfoInit RevPiLogfile-Class.
_checkclosePrüft ob Fenster beendet werden soll.
_createwidgetsErstellt alle Widgets.
visitwebsiteÖffnet auf dem System einen Webbrowser zur Projektseite.
+

+Static Methods

+ + +
None
+ +

+RevPiInfo (Constructor)

+RevPiInfo(master, xmlcli, version) +

+Init RevPiLogfile-Class. +

+

+RevPiInfo._checkclose

+_checkclose(event=None) +

+Prüft ob Fenster beendet werden soll. +

+
event:
+
+tkinter-Event +
+
+

+RevPiInfo._createwidgets

+_createwidgets(extended=False) +

+Erstellt alle Widgets. +

+

+RevPiInfo.visitwebsite

+visitwebsite(event=None) +

+Öffnet auf dem System einen Webbrowser zur Projektseite. +

+ +
+ \ No newline at end of file diff --git a/doc/revpilogfile.html b/doc/revpilogfile.html index 79fb54b..ce4abb1 100644 --- a/doc/revpilogfile.html +++ b/doc/revpilogfile.html @@ -49,8 +49,8 @@ Methods RevPiLogfile Init RevPiLogfile-Class. -_closewin - +_checkclose +Prüft ob Fenster beendet werden soll. _createwidgets Erstellt alle Widgets. @@ -82,11 +82,18 @@ RevPiLogfile (Constructor) RevPiLogfile(master, xmlcli)

Init RevPiLogfile-Class. -

+

-RevPiLogfile._closewin

-_closewin(event) - +RevPiLogfile._checkclose +_checkclose(event=None) +

+Prüft ob Fenster beendet werden soll. +

+
event:
+
+tkinter-Event +
+

RevPiLogfile._createwidgets

_createwidgets() diff --git a/doc/revpiplclist.html b/doc/revpiplclist.html index b7c66e1..cd2168b 100644 --- a/doc/revpiplclist.html +++ b/doc/revpiplclist.html @@ -25,7 +25,7 @@ Functions - +
get_connectionsVerbindungen aus Datei laden.


@@ -50,22 +50,19 @@ Methods - + - + - - - - + - + - + @@ -95,27 +92,43 @@ Static Methods

RevPiPlcList (Constructor)

RevPiPlcList(master) - +

+Init RevPiPlcList-class. +

+
master:
+
+tkinter master +
+

RevPiPlcList._checkclose

_checkclose(event=None) - +

+Prüft ob Fenster beendet werden soll. +

+
event:
+
+tkinter-Event +
+

RevPiPlcList._createwidgets

_createwidgets() - -

-RevPiPlcList._loadappdata

-_loadappdata() - +

+Erstellt alle Widgets. +

RevPiPlcList._saveappdata

_saveappdata() - +

+Speichert Verbindungen im home Dir. +

RevPiPlcList.build_listconn

build_listconn() - +

+Füllt Verbindungsliste. +

RevPiPlcList.evt_btnadd

evt_btnadd() @@ -145,7 +158,9 @@ RevPiPlcList.evt_listconn

get_connections

get_connections() - +

+Verbindungen aus Datei laden. +


\ No newline at end of file diff --git a/doc/revpipycontrol.html b/doc/revpipycontrol.html index 819a6c4..e66a046 100644 --- a/doc/revpipycontrol.html +++ b/doc/revpipycontrol.html @@ -10,7 +10,7 @@ revpipycontrol

Global Attributes

RevPiPlcListInit RevPiPlcList-class.
_checkclosePrüft ob Fenster beendet werden soll.
_createwidgets
_loadappdataErstellt alle Widgets.
_saveappdataSpeichert Verbindungen im home Dir.
build_listconnFüllt Verbindungsliste.
evt_btnadd
- +
_
_
pycontrolversion

Classes

@@ -71,7 +71,7 @@ Methods infowindow -Öffnet das Fenster für die Verbindungen. +Öffnet das Fenster für die Info. plcdebug Baut den Debugframe und packt ihn. @@ -176,7 +176,7 @@ RevPiPyControl._opt_conn RevPiPyControl.infowindow infowindow()

-Öffnet das Fenster für die Verbindungen. +Öffnet das Fenster für die Info.

RevPiPyControl.plcdebug

diff --git a/revpipycontrol.api b/revpipycontrol.api index 91279e4..b0b3957 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -19,13 +19,15 @@ revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist) revpicheckclient.RevPiCheckClient.writevalues?4() revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0) revpicheckclient._?8 -revpiinfo.RevPiInfo._closewin?5(event=None) -revpiinfo.RevPiInfo._createwidgets?5() +revpiinfo.RevPiInfo._checkclose?5(event=None) +revpiinfo.RevPiInfo._createwidgets?5(extended=False) revpiinfo.RevPiInfo.app?7 +revpiinfo.RevPiInfo.cli?7 revpiinfo.RevPiInfo.root?7 -revpiinfo.RevPiInfo?1(master) +revpiinfo.RevPiInfo.visitwebsite?4(event=None) +revpiinfo.RevPiInfo?1(master, xmlcli, version) revpiinfo._?8 -revpilogfile.RevPiLogfile._closewin?5(event) +revpilogfile.RevPiLogfile._checkclose?5(event=None) revpilogfile.RevPiLogfile._createwidgets?5() revpilogfile.RevPiLogfile._load_log?5(textwidget, xmlcall, startposition, full) revpilogfile.RevPiLogfile.btn_clearapp?4() @@ -45,7 +47,6 @@ revpioption.RevPiOption?1(master, xmlcli, xmlmode) revpioption._?8 revpiplclist.RevPiPlcList._checkclose?5(event=None) revpiplclist.RevPiPlcList._createwidgets?5() -revpiplclist.RevPiPlcList._loadappdata?5() revpiplclist.RevPiPlcList._saveappdata?5() revpiplclist.RevPiPlcList.build_listconn?4() revpiplclist.RevPiPlcList.evt_btnadd?4() @@ -101,3 +102,4 @@ revpipycontrol.RevPiPyControl.tmr_plcrunning?4() revpipycontrol.RevPiPyControl.visitwebsite?4() revpipycontrol.RevPiPyControl?1(master=None) revpipycontrol._?8 +revpipycontrol.pycontrolversion?7 diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 521bfb6..493f953 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-30 13:50+0200\n" -"PO-Revision-Date: 2017-06-30 13:50+0200\n" +"POT-Creation-Date: 2017-06-30 21:05+0200\n" +"PO-Revision-Date: 2017-06-30 21:05+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -16,11 +16,12 @@ msgstr "" "X-Poedit-SearchPath-0: .\n" #: revpicheckclient.py:103 revpicheckclient.py:395 revpioption.py:288 -#: revpiplclist.py:198 revpiprogram.py:306 revpiprogram.py:337 -#: revpiprogram.py:400 revpiprogram.py:433 revpiprogram.py:515 -#: revpiprogram.py:587 revpiprogram.py:618 revpiprogram.py:631 -#: revpiprogram.py:686 revpiprogram.py:706 revpiprogram.py:714 -#: revpipycontrol.py:342 +#: revpiplclist.py:199 revpiprogram.py:306 revpiprogram.py:337 +#: revpiprogram.py:401 revpiprogram.py:407 revpiprogram.py:413 +#: revpiprogram.py:421 revpiprogram.py:427 revpiprogram.py:460 +#: revpiprogram.py:544 revpiprogram.py:616 revpiprogram.py:647 +#: revpiprogram.py:660 revpiprogram.py:715 revpiprogram.py:735 +#: revpiprogram.py:743 revpipycontrol.py:342 msgid "Error" msgstr "Fehler" @@ -60,7 +61,7 @@ msgstr "Aktualisiere automatisch" msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" -#: revpicheckclient.py:276 revpiprogram.py:407 revpipycontrol.py:228 +#: revpicheckclient.py:276 revpiprogram.py:434 revpipycontrol.py:228 #: revpipycontrol.py:267 revpipycontrol.py:285 revpipycontrol.py:303 msgid "Warning" msgstr "Warnung" @@ -81,32 +82,79 @@ msgstr "" msgid "Error set value of device '{}' Output '{}': {} \n" msgstr "Fehler beim Setzen auf Device '{}' bei Output '{}': {}\n" -#: revpilogfile.py:37 +#: revpiinfo.py:38 +msgid "RevPi Python PLC info" +msgstr "RevPi Python PLC Information" + +#: revpiinfo.py:51 +msgid "RevPi Python PLC - Control" +msgstr "RevPi Python PLC - Kontrollcenter" + +#: revpiinfo.py:55 +msgid "Version: {}" +msgstr "Version: {}" + +#: revpiinfo.py:78 +msgid "RevPiPyLoad version on RevPi:" +msgstr "RevPiPyLoad Version am RevPi:" + +#: revpiinfo.py:83 +msgid "not conn." +msgstr "nicht verb." + +#: revpiinfo.py:91 +msgid "" +"\n" +"RevPiModIO, RevPiPyLoad and RevPiPyControl\n" +"are community driven projects. They are all\n" +"free and open source software.\n" +"All of them comes with ABSOLUTELY NO\n" +"WARRANTY, to the extent permitted by \n" +"applicable law.\n" +"\n" +"\n" +"(c) Sven Sager, License: LGPLv3" +msgstr "" +"\n" +"RevPiModIO, RevPiPyLoad und RevPiPyControl\n" +"sind gemeinschaftsorientierte Projekte. Sie sind\n" +"alle frei und Open Source Software.\n" +"Alle kommen mit ABSOLUT KEINER\n" +"GARANTIE, soweit gesetzlich zulässig.\n" +"\n" +"\n" +"(c) Sven Sager, Lizenz: LGPLv3" + +#: revpiinfo.py:136 revpioption.py:225 revpiplclist.py:133 +msgid "Close" +msgstr "Schließen" + +#: revpilogfile.py:39 msgid "RevPi Python PLC Logs" msgstr "RevPi Python PLC Logdaten" -#: revpilogfile.py:50 +#: revpilogfile.py:52 msgid "RevPiPyLoad - Logfile" msgstr "RevPiPyLoad - Logdatei" -#: revpilogfile.py:54 revpilogfile.py:69 +#: revpilogfile.py:56 revpilogfile.py:71 msgid "Clear screen" msgstr "Leere Ansicht" -#: revpilogfile.py:65 +#: revpilogfile.py:67 msgid "Python PLC program - Logfile" msgstr "Python PLC Programm - Logdatei" -#: revpilogfile.py:145 +#: revpilogfile.py:147 msgid "Can not access log file on the RevPi" msgstr "RevPi kann auf Logdatei nicht zugreifen" -#: revpioption.py:61 revpioption.py:273 revpioption.py:298 revpiplclist.py:58 -#: revpiplclist.py:175 revpiprogram.py:370 revpiprogram.py:418 +#: revpioption.py:61 revpioption.py:273 revpioption.py:298 revpiplclist.py:62 +#: revpiplclist.py:176 revpiprogram.py:370 revpiprogram.py:445 msgid "Question" msgstr "Frage" -#: revpioption.py:62 revpiplclist.py:59 +#: revpioption.py:62 revpiplclist.py:63 msgid "" "Do you really want to quit? \n" "Unsaved changes will be lost" @@ -194,14 +242,10 @@ msgstr "" msgid "XML-RPC server port" msgstr "XML-RPC Serverport" -#: revpioption.py:220 revpiplclist.py:125 +#: revpioption.py:220 revpiplclist.py:130 msgid "Save" msgstr "Speichern" -#: revpioption.py:225 revpiplclist.py:128 -msgid "Close" -msgstr "Schließen" - #: revpioption.py:274 msgid "" "The settings are now saved on the Revolution Pi. \n" @@ -214,7 +258,7 @@ msgstr "" "Sollen die neuen Einstellungen sofort in Kraft treten?\n" "Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" -#: revpioption.py:282 revpiplclist.py:190 revpiprogram.py:65 +#: revpioption.py:282 revpiplclist.py:191 revpiprogram.py:65 msgid "Information" msgstr "Information" @@ -236,39 +280,39 @@ msgstr "" "Soll der XML-RPC Server wirklich beendet werden? Sie können dann NICHT mehr " "mit diesem Programm auf den Revolution Pi zugreifen." -#: revpiplclist.py:68 +#: revpiplclist.py:73 msgid "RevPi Python PLC connections" msgstr "RevPi Python PLC Verbindungen" -#: revpiplclist.py:88 +#: revpiplclist.py:93 msgid "Name" msgstr "Name" -#: revpiplclist.py:95 +#: revpiplclist.py:100 msgid "IP address" msgstr "IP Adresse" -#: revpiplclist.py:103 +#: revpiplclist.py:108 msgid "Port" msgstr "Port" -#: revpiplclist.py:112 +#: revpiplclist.py:117 msgid "New" msgstr "Neu" -#: revpiplclist.py:115 +#: revpiplclist.py:120 msgid "Apply" msgstr "Übernehmen" -#: revpiplclist.py:119 +#: revpiplclist.py:124 msgid "Remove" msgstr "Entfernen" -#: revpiplclist.py:176 +#: revpiplclist.py:177 msgid "Do you really want to delete the selected connection '{}'" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" -#: revpiplclist.py:191 +#: revpiplclist.py:192 msgid "" "Successfully saved. \n" "Do you want to close this window?" @@ -276,7 +320,7 @@ msgstr "" "Verbindungen erfolgreich gespeichert. \n" "Möchten Sie dieses Fenster jetzt schließen?" -#: revpiplclist.py:199 +#: revpiplclist.py:200 msgid "Failed to save connections" msgstr "Verbindungen konnten nicht gespeichert werden" @@ -301,13 +345,13 @@ msgstr "PLC Python Programm" msgid "Files" msgstr "Dateien" -#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:465 -#: revpiprogram.py:571 +#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:492 +#: revpiprogram.py:600 msgid "Zip archive" msgstr "Zip Archiv" -#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:478 -#: revpiprogram.py:601 +#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:505 +#: revpiprogram.py:630 msgid "TGZ archive" msgstr "TGZ Archiv" @@ -379,8 +423,8 @@ msgstr "ausführen" msgid "Exit" msgstr "Beenden" -#: revpiprogram.py:296 revpiprogram.py:327 revpiprogram.py:461 -#: revpiprogram.py:474 +#: revpiprogram.py:296 revpiprogram.py:327 revpiprogram.py:488 +#: revpiprogram.py:501 msgid "Save as..." msgstr "Speichern unter..." @@ -389,22 +433,22 @@ msgid "piCtory config" msgstr "piCtory Konfiguration" #: revpiprogram.py:299 revpiprogram.py:330 revpiprogram.py:362 -#: revpiprogram.py:465 revpiprogram.py:478 revpiprogram.py:546 -#: revpiprogram.py:571 revpiprogram.py:601 +#: revpiprogram.py:492 revpiprogram.py:505 revpiprogram.py:575 +#: revpiprogram.py:600 revpiprogram.py:630 msgid "All files" msgstr "Alle Dateien" -#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:516 +#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:545 msgid "Could not load and save file!" msgstr "Datei konnte nicht geladen und gespeichert werden!" -#: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:381 -#: revpiprogram.py:389 revpiprogram.py:427 revpiprogram.py:521 -#: revpiprogram.py:676 +#: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:382 +#: revpiprogram.py:390 revpiprogram.py:454 revpiprogram.py:550 +#: revpiprogram.py:705 msgid "Success" msgstr "Erfolgreich" -#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:522 +#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:551 msgid "File successfully loaded and saved." msgstr "Dateien erfolgreich übertragen und gespeichert." @@ -424,25 +468,46 @@ msgstr "" "Soll nach dem Hochladen der piCtory Konfiguration ein Reset am piControl " "Treiber durchgeführt werden?" -#: revpiprogram.py:382 +#: revpiprogram.py:383 msgid "" "The transfer of the piCtory configuration and the reset of piControl have " -"been successfully executed" +"been successfully executed." msgstr "" "Die Übertragung der piCtory Konfiguration und der Reset von piControl wurden " -"erfolgreich ausgeführt" +"erfolgreich ausgeführt." -#: revpiprogram.py:390 -msgid "The piCtory configuration was successfully transferred" -msgstr "Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt" +#: revpiprogram.py:391 +msgid "The piCtory configuration was successfully transferred." +msgstr "" +"Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt." -#: revpiprogram.py:401 +#: revpiprogram.py:402 +msgid "Can not process the transferred file." +msgstr "Kann die übertragene Datei nicht verarbeiten." + +#: revpiprogram.py:408 +msgid "Can not find main elements in piCtory file." +msgstr "Kann Hauptelemente in datei nicht finden." + +#: revpiprogram.py:414 +msgid "" +"Contained devices could not be found on Revolution Pi. The configuration may " +"be from a newer piCtory version!" +msgstr "" +"Enthaltene Geräte konnten auf dem Revolution Pi nicht gefunden werden. " +"Möglicherweise stammt die Konfiguration von einer neueren piCtory Version." + +#: revpiprogram.py:422 +msgid "Could not load RAP catalog on Revolution Pi." +msgstr "Konnte Katalog auf nicht laden." + +#: revpiprogram.py:428 msgid "The piCtory configuration could not be written on the Revolution Pi." msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:408 +#: revpiprogram.py:435 msgid "" "The piCtroy configuration has been saved successfully. \n" "An error occurred on piControl reset!" @@ -450,7 +515,7 @@ msgstr "" "Die piCtroy Konfiguration wurde erfolgreich gespeichert. \n" "Beim piControl Reset trat allerdings ein Fehler auf!" -#: revpiprogram.py:419 +#: revpiprogram.py:446 msgid "" "Are you sure to reset piControl? \n" "The process image and the piBridge are interrupted !!!" @@ -458,56 +523,56 @@ msgstr "" "Soll piControlReset wirklich durchgeführt werden? \n" "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" -#: revpiprogram.py:428 +#: revpiprogram.py:455 msgid "piControlReset executed successfully" msgstr "piControl Reset war erfolgreich" -#: revpiprogram.py:434 +#: revpiprogram.py:461 msgid "piControl reset could not be executed successfully" msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" -#: revpiprogram.py:448 +#: revpiprogram.py:475 msgid "Directory to save" msgstr "Verzeichnis zum Ablegen" -#: revpiprogram.py:556 +#: revpiprogram.py:585 msgid "Folder to upload" msgstr "Verzeichnis zum Hochladen" -#: revpiprogram.py:567 +#: revpiprogram.py:596 msgid "Upload Zip archive..." msgstr "Zip Archiv hochladen..." -#: revpiprogram.py:588 +#: revpiprogram.py:617 msgid "The specified file is not a ZIP archive." msgstr "Die angegebene Datei ist kein ZIP Archiv" -#: revpiprogram.py:597 +#: revpiprogram.py:626 msgid "Upload TarGz archiv..." msgstr "TarGz Archiv hochladen..." -#: revpiprogram.py:619 +#: revpiprogram.py:648 msgid "The specified file is not a TAR archive." msgstr "Die angegebene Datei ist kein TAR Archiv." -#: revpiprogram.py:632 +#: revpiprogram.py:661 msgid "There was an error deleting the files on the Revolution Pi." msgstr "" "Beim Löschen der Dateien auf dem Revolution Pi ist ein Fehler aufgetreten." -#: revpiprogram.py:677 -msgid "The transfer was successful." -msgstr "Die Übertragung war erfolgreich." +#: revpiprogram.py:706 +msgid "The PLC program was transferred successfully." +msgstr "Das PLC Programm wurde erfolgreich übertragen." -#: revpiprogram.py:687 +#: revpiprogram.py:716 msgid "There is no piCtory configuration in this archive." msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." -#: revpiprogram.py:707 +#: revpiprogram.py:736 msgid "The Revolution Pi could not process some parts of the transmission." msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." -#: revpiprogram.py:715 +#: revpiprogram.py:744 msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" @@ -599,6 +664,23 @@ msgstr "" msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" +#~ msgid "Quit" +#~ msgstr "Beenden" + +#~ msgid "The transfer was successful." +#~ msgstr "Die Übertragung war erfolgreich." + +#~ msgid "" +#~ "The transfer of the piCtory configuration and the reset of piControl have " +#~ "been successfully executed" +#~ msgstr "" +#~ "Die Übertragung der piCtory Konfiguration und der Reset von piControl " +#~ "wurden erfolgreich ausgeführt" + +#~ msgid "The piCtory configuration was successfully transferred" +#~ msgstr "" +#~ "Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt" + #~ msgid "Given value for Output '{}' is not valid! Reset to '{}'" #~ msgstr "" #~ "Angegebener Wert bei Output '{}' ist nicht gültig! Setze auf '{}' zurück" diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index a9b4f27..9e4d429 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -12,7 +12,7 @@ import tkinter import tkinter.messagebox as tkmsg from mytools import gettrans from threading import Lock -from xmlrpc.client import ServerProxy, MultiCall +from xmlrpc.client import MultiCall # Übersetzung laden _ = gettrans() diff --git a/revpipycontrol/revpiinfo.py b/revpipycontrol/revpiinfo.py new file mode 100644 index 0000000..8b37be9 --- /dev/null +++ b/revpipycontrol/revpiinfo.py @@ -0,0 +1,150 @@ +# +# RevPiPyControl +# +# Webpage: https://revpimodio.org/revpipyplc/ +# (c) Sven Sager, License: LGPLv3 +# +# -*- coding: utf-8 -*- +import tkinter +import tkinter.font as tkf +import webbrowser +from mytools import gettrans + +# Übersetzung laden +_ = gettrans() + + +class RevPiInfo(tkinter.Frame): + + def __init__(self, master, xmlcli, version): + u"""Init RevPiLogfile-Class.""" + self.master = master + self.xmlcli = xmlcli + + # Systemvariablen + self.version = version + + # Fenster bauen + self._createwidgets() + + def _checkclose(self, event=None): + u"""Prüft ob Fenster beendet werden soll. + @param event: tkinter-Event""" + self.master.destroy() + + def _createwidgets(self, extended=False): + u"""Erstellt alle Widgets.""" + super().__init__(self.master) + self.master.wm_title(_("RevPi Python PLC info")) + self.master.bind("", self._checkclose) + self.master.resizable(False, False) + self.pack(fill="both", expand=True) + + # Fonts laden + fntlarge = tkf.Font(size=20, weight="bold") + fntmid = tkf.Font(size=15) + fntbold = tkf.Font(size=10, weight="bold") + + # Kopfdaten + lbl = tkinter.Label(self) + lbl["font"] = fntlarge + lbl["text"] = _("RevPi Python PLC - Control") + lbl.pack(pady=5) + lbl = tkinter.Label(self) + lbl["font"] = fntmid + lbl["text"] = _("Version: {}").format(self.version) + lbl.bind( + "", + lambda event: self._createwidgets(extended=not extended) + ) + lbl.pack(pady=5) + + # Mittelframe geteilt (links/rechts) --------------------------------- + frame_main = tkinter.Frame(self) + frame_main.pack(anchor="nw", fill="x", pady=5) + + # Rows konfigurieren + frame_main.rowconfigure(0, weight=0) + frame_main.rowconfigure(1, weight=1) + frame_main.rowconfigure(2, weight=1) + + int_row = 0 + cpadnw = {"padx": 4, "pady": 2, "sticky": "nw"} + cpadsw = {"padx": 4, "pady": 2, "sticky": "sw"} + + # Linke Seite Mittelframe ---------------- + lbl = tkinter.Label(frame_main) + lbl["font"] = fntbold + lbl["text"] = _("RevPiPyLoad version on RevPi:") + lbl.grid(column=0, row=int_row, **cpadnw) + + lbl = tkinter.Label(frame_main) + lbl["font"] = fntbold + lbl["text"] = _("not conn.") if self.xmlcli is None \ + else self.xmlcli.version() + lbl.grid(column=1, row=int_row, **cpadnw) + + int_row += 1 # 1 + lbl = tkinter.Label(frame_main) + lbl["justify"] = "left" + lbl["text"] = _( + "\nRevPiModIO, RevPiPyLoad and RevPiPyControl\n" + "are community driven projects. They are all\n" + "free and open source software.\n" + "All of them comes with ABSOLUTELY NO\n" + "WARRANTY, to the extent permitted by \n" + "applicable law.\n" + "\n" + "\n" + "(c) Sven Sager, License: LGPLv3" + ) + lbl.grid(column=0, row=int_row, columnspan=2, **cpadnw) + + int_row += 1 # 2 + lbl = tkinter.Label(frame_main) + lbl.bind("", self.visitwebsite) + lbl["fg"] = "blue" + lbl["text"] = "https://revpimodio.org/" + lbl.grid(column=0, row=int_row, columnspan=2, **cpadsw) + + # int_row += 1 # 3 + + # Rechte Seite Mittelframe --------------- + + # Funktionen der Gegenstelle + frame_func = tkinter.Frame(frame_main) + txt_xmlfunc = tkinter.Text(frame_func, width=30, height=15) + scr_xmlfunc = tkinter.Scrollbar(frame_func) + if extended: + txt_xmlfunc.insert(tkinter.END, "\n".join( + [] if self.xmlcli is None else self.xmlcli.system.listMethods() + )) + else: + txt_xmlfunc.insert(tkinter.END, "\n".join( + [] if self.xmlcli is None else self.xmlcli.get_filelist() + )) + txt_xmlfunc["yscrollcommand"] = scr_xmlfunc.set + txt_xmlfunc["state"] = "disabled" + scr_xmlfunc["command"] = txt_xmlfunc.yview + txt_xmlfunc.pack(side="left") + scr_xmlfunc.pack(fill="y", side="right") + frame_func.grid(column=3, row=0, rowspan=int_row + 1, **cpadnw) + + # Unten Beenden-Button ----------------------------------------------- + self.btnapplog = tkinter.Button(self) + self.btnapplog["command"] = self._checkclose + self.btnapplog["text"] = _("Close") + self.btnapplog.pack(fill="x", padx=100) + + def visitwebsite(self, event=None): + u"""Öffnet auf dem System einen Webbrowser zur Projektseite.""" + webbrowser.open("https://revpimodio.org") + + +# TODO: Remove testdrive +if __name__ == "__main__": + from xmlrpc.client import ServerProxy + cli = ServerProxy("http://192.168.50.35:55123") + root = tkinter.Tk() + app = RevPiInfo(root, cli, "0.4.0") + app.mainloop() diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 646bea3..7c82297 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -17,7 +17,7 @@ class RevPiLogfile(tkinter.Frame): def __init__(self, master, xmlcli): u"""Init RevPiLogfile-Class.""" super().__init__(master) - self.master.bind("", self._closewin) + self.master.bind("", self._checkclose) self.pack(fill="both", expand=True) self.xmlcli = xmlcli @@ -29,7 +29,9 @@ class RevPiLogfile(tkinter.Frame): # Fenster bauen self._createwidgets() - def _closewin(self, event): + def _checkclose(self, event=None): + u"""Prüft ob Fenster beendet werden soll. + @param event: tkinter-Event""" self.master.destroy() def _createwidgets(self): diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index 309c826..fbc821d 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -25,8 +25,8 @@ else: savefile = os.path.join(homedir, ".revpipyplc", "connections.dat") -# Für andere Module zum Laden der Connections def get_connections(): + u"""Verbindungen aus Datei laden.""" if os.path.exists(savefile): fh = open(savefile, "rb") connections = pickle.load(fh) @@ -38,6 +38,8 @@ def get_connections(): class RevPiPlcList(tkinter.Frame): def __init__(self, master): + u"""Init RevPiPlcList-class. + @param master: tkinter master""" super().__init__(master) self.master.bind("", self._checkclose) self.pack() @@ -45,13 +47,15 @@ class RevPiPlcList(tkinter.Frame): self.changes = False # Daten laden - self._connections = {} + self._connections = get_connections() # Fenster bauen self._createwidgets() - self._loadappdata() + self.build_listconn() def _checkclose(self, event=None): + u"""Prüft ob Fenster beendet werden soll. + @param event: tkinter-Event""" ask = True if self.changes: ask = tkmsg.askyesno( @@ -65,6 +69,7 @@ class RevPiPlcList(tkinter.Frame): self.master.destroy() def _createwidgets(self): + u"""Erstellt alle Widgets.""" self.master.wm_title(_("RevPi Python PLC connections")) self.master.wm_resizable(width=False, height=False) self.master.protocol("WM_DELETE_WINDOW", self._checkclose) @@ -128,13 +133,8 @@ class RevPiPlcList(tkinter.Frame): self, text=_("Close"), command=self._checkclose) self.btn_close.grid(column=4, row=9, sticky="se") - def _loadappdata(self): - if os.path.exists(savefile): - fh = open(savefile, "rb") - self._connections = pickle.load(fh) - self.build_listconn() - def _saveappdata(self): + u"""Speichert Verbindungen im home Dir.""" try: makedirs(os.path.dirname(savefile), exist_ok=True) fh = open(savefile, "wb") @@ -145,6 +145,7 @@ class RevPiPlcList(tkinter.Frame): return True def build_listconn(self): + u"""Füllt Verbindungsliste.""" self.list_conn.delete(0, "end") lst_conns = sorted(self._connections.keys(), key=lambda x: x.lower()) self.list_conn.insert("end", *lst_conns) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index d9cd70c..a2b876a 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -374,6 +374,7 @@ class RevPiProgram(tkinter.Frame): ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) + print(ec) if ec == 0: if ask: @@ -381,20 +382,46 @@ class RevPiProgram(tkinter.Frame): _("Success"), _("The transfer of the piCtory configuration " "and the reset of piControl have been " - "successfully executed"), + "successfully executed."), parent=self.master ) else: tkmsg.showinfo( _("Success"), _("The piCtory configuration was " - "successfully transferred"), + "successfully transferred."), parent=self.master ) # Einstellungen speichern self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self._savedefaults() + elif ec == -1: + tkmsg.showerror( + _("Error"), + _("Can not process the transferred file."), + parent=self.master + ) + elif ec == -2: + tkmsg.showerror( + _("Error"), + _("Can not find main elements in piCtory file."), + parent=self.master + ) + elif ec == -4: + tkmsg.showerror( + _("Error"), + _("Contained devices could not be found on Revolution " + "Pi. The configuration may be from a newer piCtory " + "version!"), + parent=self.master + ) + elif ec == -5: + tkmsg.showerror( + _("Error"), + _("Could not load RAP catalog on Revolution Pi."), + parent=self.master + ) elif ec < 0: tkmsg.showerror( _("Error"), @@ -451,7 +478,7 @@ class RevPiProgram(tkinter.Frame): ) if type(dirselect) == str and dirselect != "": - fh = open(mkstemp(), "wb") + fh = open(mkstemp()[1], "wb") elif tdown == 1: # Zip @@ -482,10 +509,12 @@ class RevPiProgram(tkinter.Frame): if fh is not None: if tdown == 1: plcfile = self.xmlcli.plcdownload( - "zip", self.var_picdown.get()) + "zip", self.var_picdown.get() + ) else: plcfile = self.xmlcli.plcdownload( - "tar", self.var_picdown.get()) + "tar", self.var_picdown.get() + ) try: fh.write(plcfile.data) @@ -674,7 +703,7 @@ class RevPiProgram(tkinter.Frame): if ec == 0: tkmsg.showinfo( _("Success"), - _("The transfer was successful."), + _("The PLC program was transferred successfully."), parent=self.master ) diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 8f234d0..d6d65d2 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -210,9 +210,9 @@ class RevPiPyControl(tkinter.Frame): self.mbar.entryconfig("PLC", state="normal") def infowindow(self): - u"""Öffnet das Fenster für die Verbindungen.""" + u"""Öffnet das Fenster für die Info.""" win = tkinter.Toplevel(self) - revpiinfo.RevPiInfo(win) + revpiinfo.RevPiInfo(win, self.cli, pycontrolversion) win.focus_set() win.grab_set() self.wait_window(win) From 0653c6c8eb1905db8234b98937f4caa54d854512 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sat, 1 Jul 2017 13:37:06 +0200 Subject: [PATCH 09/13] docstrings angepasst --- doc/mytools.html | 2 +- doc/revpicheckclient.html | 35 +++++++++++---- doc/revpiinfo.html | 2 +- doc/revpilogfile.html | 14 +++--- doc/revpioption.html | 2 +- doc/revpiplclist.html | 54 ++++++++++++++++------- doc/revpiprogram.html | 70 +++++++++++++++++++++++------- doc/revpipycontrol.html | 28 +++++++++--- revpipycontrol/mytools.py | 4 +- revpipycontrol/revpicheckclient.py | 26 +++++------ revpipycontrol/revpiinfo.py | 2 +- revpipycontrol/revpilogfile.py | 16 +++---- revpipycontrol/revpioption.py | 6 +-- revpipycontrol/revpiplclist.py | 16 +++++-- revpipycontrol/revpiprogram.py | 28 ++++++++---- revpipycontrol/revpipycontrol.py | 10 +++-- 16 files changed, 215 insertions(+), 100 deletions(-) diff --git a/doc/mytools.html b/doc/mytools.html index f7b99f6..c8a2a96 100644 --- a/doc/mytools.html +++ b/doc/mytools.html @@ -38,7 +38,7 @@ Hängt root-dir der Anwendung vor Dateinamen. Je nach Ausführungsart der Anwendung muss das root-dir über andere Arten abgerufen werden.

-
filename:
+
filename
Datei oder Ordnername
diff --git a/doc/revpicheckclient.html b/doc/revpicheckclient.html index 3e8cd4b..86a6fc2 100644 --- a/doc/revpicheckclient.html +++ b/doc/revpicheckclient.html @@ -125,10 +125,10 @@ RevPiCheckClient.__hidewin

Verbergt übergebenes Fenster.

-
win:
+
win
Fenster zum verbergen -
event:
+
event
Tkinter Event
@@ -145,7 +145,7 @@ RevPiCheckClient.__showwin

Zeigt oder verbergt übergebenes Fenster.

-
win:
+
win
Fenster zum anzeigen/verbergen
@@ -156,13 +156,30 @@ RevPiCheckClient.__spinboxkey

Prüft die Eingabe auf plausibilität.

-
event:
+
event
tkinter Event -
io:
+
io
IO Liste mit tkinter Variable
+
+

+RevPiCheckClient._createiogroup

+_createiogroup(device, frame, iotype) +

+Erstellt IO-Gruppen. +

+
device
+
+Deviceposition +
frame
+
+tkinter Frame +
iotype
+
+'inp' oder 'out' als str() +

RevPiCheckClient._createwidgets

@@ -176,7 +193,7 @@ RevPiCheckClient._onfrmconf

Erstellt Fenster in einem Canvas.

-
canvas:
+
canvas
Canvas in dem Objekte erstellt werden sollen
@@ -198,10 +215,10 @@ RevPiCheckClient._workvalues

Alle Werte der Inputs und Outputs abrufen.

-
io_dicts:
+
io_dicts
Arbeit nur für dieses Dict() -
writeout:
+
writeout
Änderungen auf RevPi schreiben
@@ -242,7 +259,7 @@ RevPiCheckClient.validatereturn

Überprüft die Rückgaben der setvalue Funktion.

-
returnlist:
+
returnlist
list() der xml Rückgabe
diff --git a/doc/revpiinfo.html b/doc/revpiinfo.html index 3ff9473..e6f5ae0 100644 --- a/doc/revpiinfo.html +++ b/doc/revpiinfo.html @@ -77,7 +77,7 @@ RevPiInfo._checkclose

Prüft ob Fenster beendet werden soll.

-
event:
+
event
tkinter-Event
diff --git a/doc/revpilogfile.html b/doc/revpilogfile.html index ce4abb1..3e0242b 100644 --- a/doc/revpilogfile.html +++ b/doc/revpilogfile.html @@ -89,7 +89,7 @@ RevPiLogfile._checkclose

Prüft ob Fenster beendet werden soll.

-
event:
+
event
tkinter-Event
@@ -106,16 +106,16 @@ RevPiLogfile._load_log

Läd die angegebenen Logfiles herunter.

-
textwidget:
+
textwidget
Widget in das Logs eingefügt werden sollen -
xmlcall:
+
xmlcall
xmlrpc Funktion zum Abrufen der Logdaten -
startposition:
+
startposition
Startposition ab der Logdaten kommen sollen -
full:
+
full
Komplettes Logbuch laden
@@ -143,7 +143,7 @@ RevPiLogfile.get_applog

Ruft App Logbuch ab.

-
full:
+
full
Ganzes Logbuch laden
@@ -154,7 +154,7 @@ RevPiLogfile.get_plclog

Ruft PLC Logbuch ab.

-
full:
+
full
Ganzes Logbuch laden
diff --git a/doc/revpioption.html b/doc/revpioption.html index 2a321f8..07894e3 100644 --- a/doc/revpioption.html +++ b/doc/revpioption.html @@ -105,7 +105,7 @@ RevPiOption._checkclose

Prüft ob Fenster beendet werden soll.

-
event:
+
event
tkinter-Event
diff --git a/doc/revpiplclist.html b/doc/revpiplclist.html index cd2168b..d2f8095 100644 --- a/doc/revpiplclist.html +++ b/doc/revpiplclist.html @@ -65,22 +65,22 @@ Methods Füllt Verbindungsliste. evt_btnadd - +Verbindungseinstellungen übernehmen. evt_btnnew - +Neue Verbindung erstellen. evt_btnremove - +Verbindung löschen. evt_btnsave - +Alle Verbindungen speichern. evt_keypress - +Passt bei Tastendruck den Status der Buttons an. evt_listconn - +Übernimmt Einstellungen in Eingabefelder.

@@ -95,7 +95,7 @@ RevPiPlcList (Constructor)

Init RevPiPlcList-class.

-
master:
+
master
tkinter master
@@ -106,7 +106,7 @@ RevPiPlcList._checkclose

Prüft ob Fenster beendet werden soll.

-
event:
+
event
tkinter-Event
@@ -122,7 +122,12 @@ RevPiPlcList._saveappdata _saveappdata()

Speichert Verbindungen im home Dir. -

+

+
Returns:
+
+True, bei erfolgreicher Verarbeitung +
+

RevPiPlcList.build_listconn

build_listconn() @@ -132,27 +137,39 @@ Füllt Verbindungsliste.

RevPiPlcList.evt_btnadd

evt_btnadd() - +

+Verbindungseinstellungen übernehmen. +

RevPiPlcList.evt_btnnew

evt_btnnew() - +

+Neue Verbindung erstellen. +

RevPiPlcList.evt_btnremove

evt_btnremove() - +

+Verbindung löschen. +

RevPiPlcList.evt_btnsave

evt_btnsave() - +

+Alle Verbindungen speichern. +

RevPiPlcList.evt_keypress

evt_keypress(evt=None) - +

+Passt bei Tastendruck den Status der Buttons an. +

RevPiPlcList.evt_listconn

evt_listconn(evt=None) - +

+Übernimmt Einstellungen in Eingabefelder. +



@@ -160,7 +177,12 @@ RevPiPlcList.evt_listconn get_connections()

Verbindungen aus Datei laden. -

+

+
Returns:
+
+dict() mit Verbindungen +
+

\ No newline at end of file diff --git a/doc/revpiprogram.html b/doc/revpiprogram.html index d61ebd0..4709afd 100644 --- a/doc/revpiprogram.html +++ b/doc/revpiprogram.html @@ -50,19 +50,19 @@ Methods Init RevPiProgram-Class. _checkclose - +Prüft ob Fenster beendet werden soll. _createwidgets - +Erstellt alle Widgets. _evt_optdown - +Passt je nach gewählter Option den Status der Widgets an. _evt_optup - +Passt je nach gewählter Option den Status der Widgets an. _loaddefault -Uebernimmt fuer den Pi die letzen Pfade. +Übernimmt für den Pi die letzen Pfade. _savedefaults Schreibt fuer den Pi die letzen Pfade. @@ -103,35 +103,68 @@ RevPiProgram (Constructor) RevPiProgram(master, xmlcli, xmlmode, revpi)

Init RevPiProgram-Class. -

+

+
Returns:
+
+None +
+

RevPiProgram._checkclose

_checkclose(event=None) - +

+Prüft ob Fenster beendet werden soll. +

+
event
+
+tkinter-Event +
+

RevPiProgram._createwidgets

_createwidgets() - +

+Erstellt alle Widgets. +

RevPiProgram._evt_optdown

_evt_optdown(text="") - +

+Passt je nach gewählter Option den Status der Widgets an. +

RevPiProgram._evt_optup

_evt_optup(text="") - +

+Passt je nach gewählter Option den Status der Widgets an. +

RevPiProgram._loaddefault

_loaddefault(full=False)

-Uebernimmt fuer den Pi die letzen Pfade. -

+Übernimmt für den Pi die letzen Pfade. +

+
full
+
+Einstellungen für alle Verbindungen laden +
+
+
Returns:
+
+dict() mit Einstellungen +
+

RevPiProgram._savedefaults

_savedefaults()

Schreibt fuer den Pi die letzen Pfade. -

+

+
Returns:
+
+True, bei erfolgreicher Verarbeitung +
+

RevPiProgram.check_replacedir

check_replacedir(rootdir) @@ -141,7 +174,7 @@ Gibt das rootdir von einem entpackten Verzeichnis zurueck. Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt und ob es eine piCtory Konfiguration im rootdir gibt.

-
rootdir:
+
rootdir
Verzeichnis fuer Pruefung
@@ -157,7 +190,7 @@ RevPiProgram.create_filelist

Erstellt eine Dateiliste von einem Verzeichnis.

-
rootdir:
+
rootdir
Verzeichnis fuer das eine Liste erstellt werden soll
@@ -196,7 +229,12 @@ RevPiProgram.plcupload plcupload()

Lädt das angegebene Projekt auf den RevPi. -

+

+
Returns:
+
+True, bei erfolgreicher Verarbeitung +
+

RevPiProgram.setpictoryrsc

setpictoryrsc(filename=None) diff --git a/doc/revpipycontrol.html b/doc/revpipycontrol.html index e66a046..e2d9ffd 100644 --- a/doc/revpipycontrol.html +++ b/doc/revpipycontrol.html @@ -68,7 +68,7 @@ Methods Generiert Menüeinträge. _opt_conn - +Stellt eine neue Verbindung zu RevPiPyLoad her. infowindow Öffnet das Fenster für die Info. @@ -104,7 +104,7 @@ Methods Setzt alles zurück für neue Verbindungen. tmr_plcrunning - +Timer der den Status des PLC Programms prüft. visitwebsite Öffnet auf dem System einen Webbrowser zur Projektseite. @@ -122,7 +122,7 @@ RevPiPyControl (Constructor)

Init RevPiPyControl-Class.

-
master:
+
master
tkinter master
@@ -145,7 +145,7 @@ RevPiPyControl._closeapp

Räumt auf und beendet Programm.

-
event:
+
event
tkinter Event
@@ -171,7 +171,14 @@ Generiert Menüeinträge.

RevPiPyControl._opt_conn

_opt_conn(text) - +

+Stellt eine neue Verbindung zu RevPiPyLoad her. +

+
text
+
+Verbindungsname +
+

RevPiPyControl.infowindow

infowindow() @@ -195,7 +202,12 @@ RevPiPyControl.plclogs plclogs()

Öffnet das Fenster für Logdateien. -

+

+
Returns:
+
+None +
+

RevPiPyControl.plcoptions

plcoptions() @@ -241,7 +253,9 @@ Setzt alles zurück für neue Verbindungen.

RevPiPyControl.tmr_plcrunning

tmr_plcrunning() - +

+Timer der den Status des PLC Programms prüft. +

RevPiPyControl.visitwebsite

visitwebsite() diff --git a/revpipycontrol/mytools.py b/revpipycontrol/mytools.py index 941b8c2..fb90979 100644 --- a/revpipycontrol/mytools.py +++ b/revpipycontrol/mytools.py @@ -18,8 +18,8 @@ def addroot(filename): Je nach Ausführungsart der Anwendung muss das root-dir über andere Arten abgerufen werden. - @param filename: Datei oder Ordnername - @returns: root dir + @param filename Datei oder Ordnername + @return root dir """ if getattr(sys, "frozen", False): diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 9e4d429..4c196c4 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -63,8 +63,8 @@ class RevPiCheckClient(tkinter.Frame): def __hidewin(self, win, event=None): u"""Verbergt übergebenes Fenster. - @param win: Fenster zum verbergen - @param event: Tkinter Event""" + @param win Fenster zum verbergen + @param event Tkinter Event""" win.withdraw() def __saveoldvalue(self, event, tkvar): @@ -78,7 +78,7 @@ class RevPiCheckClient(tkinter.Frame): def __showwin(self, win): u"""Zeigt oder verbergt übergebenes Fenster. - @param win: Fenster zum anzeigen/verbergen""" + @param win Fenster zum anzeigen/verbergen""" if win.winfo_viewable(): win.withdraw() else: @@ -86,8 +86,8 @@ class RevPiCheckClient(tkinter.Frame): def __spinboxkey(self, device, io, event=None): u"""Prüft die Eingabe auf plausibilität. - @param event: tkinter Event - @param io: IO Liste mit tkinter Variable""" + @param event tkinter Event + @param io IO Liste mit tkinter Variable""" # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] try: newvalue = io[5].get() @@ -112,9 +112,9 @@ class RevPiCheckClient(tkinter.Frame): def _createiogroup(self, device, frame, iotype): u"""Erstellt IO-Gruppen. - @param device: Deviceposition - @param frame: tkinter Frame - @iotype: 'inp' oder 'out' als str() + @param device Deviceposition + @param frame tkinter Frame + @param iotype 'inp' oder 'out' als str() """ # IO-Typen festlegen @@ -265,12 +265,12 @@ class RevPiCheckClient(tkinter.Frame): def _onfrmconf(self, canvas): u"""Erstellt Fenster in einem Canvas. - @param canvas: Canvas in dem Objekte erstellt werden sollen""" + @param canvas Canvas in dem Objekte erstellt werden sollen""" canvas.configure(scrollregion=canvas.bbox("all")) def _warnwrite(self): u"""Warnung für Benutzer über Schreibfunktion einmal fragen. - @returns: True, wenn Warnung einmal mit OK bestätigt wurde""" + @return True, wenn Warnung einmal mit OK bestätigt wurde""" if self.__checkwrite: self.__checkwrite = not tkmsg.askokcancel( _("Warning"), @@ -285,8 +285,8 @@ class RevPiCheckClient(tkinter.Frame): def _workvalues(self, io_dicts=None, writeout=False): u"""Alle Werte der Inputs und Outputs abrufen. - @param io_dicts: Arbeit nur für dieses Dict() - @param writeout: Änderungen auf RevPi schreiben""" + @param io_dicts Arbeit nur für dieses Dict() + @param writeout Änderungen auf RevPi schreiben""" # Abfragelisten vorbereiten if io_dicts is None: @@ -377,7 +377,7 @@ class RevPiCheckClient(tkinter.Frame): def validatereturn(self, returnlist): u"""Überprüft die Rückgaben der setvalue Funktion. - @param returnlist: list() der xml Rückgabe""" + @param returnlist list() der xml Rückgabe""" if type(returnlist[0]) != list: returnlist = [returnlist] diff --git a/revpipycontrol/revpiinfo.py b/revpipycontrol/revpiinfo.py index 8b37be9..12e6346 100644 --- a/revpipycontrol/revpiinfo.py +++ b/revpipycontrol/revpiinfo.py @@ -29,7 +29,7 @@ class RevPiInfo(tkinter.Frame): def _checkclose(self, event=None): u"""Prüft ob Fenster beendet werden soll. - @param event: tkinter-Event""" + @param event tkinter-Event""" self.master.destroy() def _createwidgets(self, extended=False): diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 7c82297..06d8770 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -31,7 +31,7 @@ class RevPiLogfile(tkinter.Frame): def _checkclose(self, event=None): u"""Prüft ob Fenster beendet werden soll. - @param event: tkinter-Event""" + @param event tkinter-Event""" self.master.destroy() def _createwidgets(self): @@ -91,7 +91,7 @@ class RevPiLogfile(tkinter.Frame): def get_applog(self, full=False): u"""Ruft App Logbuch ab. - @param full: Ganzes Logbuch laden""" + @param full Ganzes Logbuch laden""" # Logs abrufen und letzte Position merken self.mrkapp = self._load_log( @@ -103,7 +103,7 @@ class RevPiLogfile(tkinter.Frame): def get_plclog(self, full=False): u"""Ruft PLC Logbuch ab. - @param full: Ganzes Logbuch laden""" + @param full Ganzes Logbuch laden""" # Logs abrufen und letzte Position merken self.mrkplc = self._load_log( @@ -116,11 +116,11 @@ class RevPiLogfile(tkinter.Frame): def _load_log(self, textwidget, xmlcall, startposition, full): u"""Läd die angegebenen Logfiles herunter. - @param textwidget: Widget in das Logs eingefügt werden sollen - @param xmlcall: xmlrpc Funktion zum Abrufen der Logdaten - @param startposition: Startposition ab der Logdaten kommen sollen - @param full: Komplettes Logbuch laden - @returns: Ende der Datei (neue Startposition) + @param textwidget Widget in das Logs eingefügt werden sollen + @param xmlcall xmlrpc Funktion zum Abrufen der Logdaten + @param startposition Startposition ab der Logdaten kommen sollen + @param full Komplettes Logbuch laden + @return Ende der Datei (neue Startposition) """ roll = textwidget.yview()[1] == 1.0 diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 2d0afb4..8c67122 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -17,7 +17,7 @@ class RevPiOption(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode): u"""Init RevPiOption-Class. - @returns: None""" + @return None""" if xmlmode < 2: return None @@ -36,7 +36,7 @@ class RevPiOption(tkinter.Frame): def _changesdone(self): u"""Prüft ob sich die Einstellungen geändert haben. - @returns: True, wenn min. eine Einstellung geändert wurde""" + @return True, wenn min. eine Einstellung geändert wurde""" return ( self.var_start.get() != self.dc.get("autostart", "1") or self.var_reload.get() != self.dc.get("autoreload", "1") @@ -54,7 +54,7 @@ class RevPiOption(tkinter.Frame): def _checkclose(self, event=None): u"""Prüft ob Fenster beendet werden soll. - @param event: tkinter-Event""" + @param event tkinter-Event""" ask = True if self._changesdone(): ask = tkmsg.askyesno( diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index fbc821d..7721aab 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -26,7 +26,8 @@ savefile = os.path.join(homedir, ".revpipyplc", "connections.dat") def get_connections(): - u"""Verbindungen aus Datei laden.""" + u"""Verbindungen aus Datei laden. + @return dict() mit Verbindungen""" if os.path.exists(savefile): fh = open(savefile, "rb") connections = pickle.load(fh) @@ -39,7 +40,7 @@ class RevPiPlcList(tkinter.Frame): def __init__(self, master): u"""Init RevPiPlcList-class. - @param master: tkinter master""" + @param master tkinter master""" super().__init__(master) self.master.bind("", self._checkclose) self.pack() @@ -55,7 +56,7 @@ class RevPiPlcList(tkinter.Frame): def _checkclose(self, event=None): u"""Prüft ob Fenster beendet werden soll. - @param event: tkinter-Event""" + @param event tkinter-Event""" ask = True if self.changes: ask = tkmsg.askyesno( @@ -134,7 +135,8 @@ class RevPiPlcList(tkinter.Frame): self.btn_close.grid(column=4, row=9, sticky="se") def _saveappdata(self): - u"""Speichert Verbindungen im home Dir.""" + u"""Speichert Verbindungen im home Dir. + @return True, bei erfolgreicher Verarbeitung""" try: makedirs(os.path.dirname(savefile), exist_ok=True) fh = open(savefile, "wb") @@ -151,6 +153,7 @@ class RevPiPlcList(tkinter.Frame): self.list_conn.insert("end", *lst_conns) def evt_btnadd(self): + u"""Verbindungseinstellungen übernehmen.""" # TODO: Daten prüfen self._connections[self.var_name.get()] = \ (self.var_address.get(), self.var_port.get()) @@ -160,6 +163,7 @@ class RevPiPlcList(tkinter.Frame): self.changes = True def evt_btnnew(self): + u"""Neue Verbindung erstellen.""" self.list_conn.select_clear(0, "end") self.evt_listconn() @@ -169,6 +173,7 @@ class RevPiPlcList(tkinter.Frame): self.var_port.set("55123") def evt_btnremove(self): + u"""Verbindung löschen.""" item_index = self.list_conn.curselection() if len(item_index) == 1: item = self.list_conn.get(item_index[0]) @@ -186,6 +191,7 @@ class RevPiPlcList(tkinter.Frame): self.changes = True def evt_btnsave(self): + u"""Alle Verbindungen speichern.""" if self._saveappdata(): ask = tkmsg.askyesno( _("Information"), @@ -202,6 +208,7 @@ class RevPiPlcList(tkinter.Frame): ) def evt_listconn(self, evt=None): + u"""Übernimmt Einstellungen in Eingabefelder.""" item_index = self.list_conn.curselection() if len(item_index) == 1: @@ -219,6 +226,7 @@ class RevPiPlcList(tkinter.Frame): self.btn_remove["state"] = "disabled" def evt_keypress(self, evt=None): + u"""Passt bei Tastendruck den Status der Buttons an.""" okvalue = "normal" if ( self.var_address.get() != "" and self.var_name.get() != "" diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index a2b876a..8666705 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -35,7 +35,8 @@ savefile = os.path.join(homedir, ".revpipyplc", "programpath.dat") class RevPiProgram(tkinter.Frame): def __init__(self, master, xmlcli, xmlmode, revpi): - u"""Init RevPiProgram-Class.""" + u"""Init RevPiProgram-Class. + @return None""" if xmlmode < 2: return None @@ -60,6 +61,8 @@ class RevPiProgram(tkinter.Frame): self._evt_optup() def _checkclose(self, event=None): + u"""Prüft ob Fenster beendet werden soll. + @param event tkinter-Event""" if self.uploaded: tkmsg.showinfo( _("Information"), @@ -71,6 +74,7 @@ class RevPiProgram(tkinter.Frame): self.master.destroy() def _createwidgets(self): + u"""Erstellt alle Widgets.""" self.master.wm_title(_("RevPi Python PLC program")) self.master.wm_resizable(width=False, height=False) @@ -217,6 +221,7 @@ class RevPiProgram(tkinter.Frame): btn.grid() def _evt_optdown(self, text=""): + u"""Passt je nach gewählter Option den Status der Widgets an.""" if self.lst_typedown.index(self.var_typedown.get()) == 0: self.var_picdown.set(False) self.ckb_picdown["state"] = "disable" @@ -224,6 +229,7 @@ class RevPiProgram(tkinter.Frame): self.ckb_picdown["state"] = "normal" def _evt_optup(self, text=""): + u"""Passt je nach gewählter Option den Status der Widgets an.""" if self.lst_typeup.index(self.var_typeup.get()) <= 1: self.var_picup.set(False) self.ckb_picup["state"] = "disable" @@ -231,7 +237,9 @@ class RevPiProgram(tkinter.Frame): self.ckb_picup["state"] = "normal" def _loaddefault(self, full=False): - """Uebernimmt fuer den Pi die letzen Pfade.""" + u"""Übernimmt für den Pi die letzen Pfade. + @param full Einstellungen für alle Verbindungen laden + @return dict() mit Einstellungen""" if os.path.exists(savefile): fh = open(savefile, "rb") dict_all = pickle.load(fh) @@ -242,7 +250,8 @@ class RevPiProgram(tkinter.Frame): return {} def _savedefaults(self): - u"""Schreibt fuer den Pi die letzen Pfade.""" + u"""Schreibt fuer den Pi die letzen Pfade. + @return True, bei erfolgreicher Verarbeitung""" try: makedirs(os.path.dirname(savefile), exist_ok=True) dict_all = self._loaddefault(full=True) @@ -256,8 +265,8 @@ class RevPiProgram(tkinter.Frame): def create_filelist(self, rootdir): u"""Erstellt eine Dateiliste von einem Verzeichnis. - @param rootdir: Verzeichnis fuer das eine Liste erstellt werden soll - @returns: Dateiliste""" + @param rootdir Verzeichnis fuer das eine Liste erstellt werden soll + @return Dateiliste""" filelist = [] for tup_dir in os.walk(rootdir): for fname in tup_dir[2]: @@ -269,8 +278,8 @@ class RevPiProgram(tkinter.Frame): Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt und ob es eine piCtory Konfiguration im rootdir gibt. - @param rootdir: Verzeichnis fuer Pruefung - @returns: Abgeaendertes rootdir + @param rootdir Verzeichnis fuer Pruefung + @return Abgeaendertes rootdir """ lst_dir = os.listdir(rootdir) @@ -558,7 +567,8 @@ class RevPiProgram(tkinter.Frame): fh.close() def plcupload(self): - u"""Lädt das angegebene Projekt auf den RevPi.""" + u"""Lädt das angegebene Projekt auf den RevPi. + @return True, bei erfolgreicher Verarbeitung""" tup = self.lst_typeup.index(self.var_typeup.get()) dirselect = "" dirtmp = None @@ -748,3 +758,5 @@ class RevPiProgram(tkinter.Frame): # Temp-Dir aufräumen if dirtmp is not None: rmtree(dirtmp) + + return True diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index d6d65d2..1b15651 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -31,7 +31,7 @@ class RevPiPyControl(tkinter.Frame): def __init__(self, master=None): u"""Init RevPiPyControl-Class. - @param master: tkinter master""" + @param master tkinter master""" super().__init__(master) self.master.protocol("WM_DELETE_WINDOW", self._closeapp) self.pack(fill="both", expand=True) @@ -84,7 +84,7 @@ class RevPiPyControl(tkinter.Frame): def _closeapp(self, event=None): u"""Räumt auf und beendet Programm. - @param event: tkinter Event""" + @param event tkinter Event""" self._closeall() self.master.destroy() @@ -183,6 +183,8 @@ class RevPiPyControl(tkinter.Frame): self.mbar.add_cascade(label=_("Connect"), menu=self.mconn) def _opt_conn(self, text): + u"""Stellt eine neue Verbindung zu RevPiPyLoad her. + @param text Verbindungsname""" socket.setdefaulttimeout(2) sp = ServerProxy( "http://{}:{}".format( @@ -261,7 +263,8 @@ class RevPiPyControl(tkinter.Frame): self._fillconnbar() def plclogs(self): - u"""Öffnet das Fenster für Logdateien.""" + u"""Öffnet das Fenster für Logdateien. + @return None""" if "load_plclog" not in self.xmlfuncs: tkmsg.showwarning( _("Warning"), @@ -345,6 +348,7 @@ class RevPiPyControl(tkinter.Frame): ) def tmr_plcrunning(self): + u"""Timer der den Status des PLC Programms prüft.""" self._btnstate() if self.cli is None: self.txt_status["readonlybackground"] = "lightblue" From 145468d35bf497b71fc37895ee6b39a61a0b5217 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sat, 1 Jul 2017 16:08:11 +0200 Subject: [PATCH 10/13] Sortierung der Devices beibehalten RevPiOption Einstellungen in globalem dc RevPiOption Interaktion bei Meldungen verbessert RevPiCheckClient auf kleine xml Einstellungen angepasst RevPiInfo Text-Feld angepasst auf kleine xml Einstellung bugfix: RevPiPyControl.serverdisconnect() bugfix: RevPiCheckClient Doppelter Timerstart verhindert --- doc/revpicheckclient.html | 16 +++- doc/revpioption.html | 28 +++++-- revpipycontrol.api | 8 +- revpipycontrol/revpicheckclient.py | 41 +++++++--- revpipycontrol/revpiinfo.py | 36 ++++----- revpipycontrol/revpioption.py | 117 +++++++++++++++++------------ revpipycontrol/revpipycontrol.py | 13 ++-- 7 files changed, 167 insertions(+), 92 deletions(-) diff --git a/doc/revpicheckclient.html b/doc/revpicheckclient.html index 86a6fc2..a93b9e8 100644 --- a/doc/revpicheckclient.html +++ b/doc/revpicheckclient.html @@ -88,6 +88,9 @@ Methods refreshvalues Ruft alle IO Werte von RevPi ab und aktualisiert Fenster. +tmr_workvalues +Timer für zyklische Abfrage. + toggleauto Schaltet zwischen Autorefresh um und aktualisiert Widgets. @@ -240,7 +243,18 @@ RevPiCheckClient.refreshvalues refreshvalues()

Ruft alle IO Werte von RevPi ab und aktualisiert Fenster. -

+

+

+RevPiCheckClient.tmr_workvalues

+tmr_workvalues() +

+Timer für zyklische Abfrage. +

+
Returns:
+
+None +
+

RevPiCheckClient.toggleauto

toggleauto() diff --git a/doc/revpioption.html b/doc/revpioption.html index 07894e3..b9f7c15 100644 --- a/doc/revpioption.html +++ b/doc/revpioption.html @@ -67,7 +67,10 @@ Methods askxmlon Fragt Nuter, ob wirklicht abgeschaltet werden soll. -xmlmods +xmlmod2_tail +Passt XML-Optionszugriff an. + +xmlmod_tail Passt XML-Optionszugriff an. @@ -79,7 +82,7 @@ Static Methods

RevPiOption (Constructor)

-RevPiOption(master, xmlcli, xmlmode) +RevPiOption(master, xmlcli)

Init RevPiOption-Class.

@@ -118,10 +121,15 @@ Erstellt Widgets.

RevPiOption._loadappdata

-_loadappdata() +_loadappdata(refresh=False)

Läd aktuelle Einstellungen vom RevPi. -

+

+
refresh
+
+Wenn True, werden Einstellungen heruntergeladen. +
+

RevPiOption._setappdata

_setappdata() @@ -133,10 +141,16 @@ RevPiOption.askxmlon askxmlon()

Fragt Nuter, ob wirklicht abgeschaltet werden soll. -

+

-RevPiOption.xmlmods

-xmlmods() +RevPiOption.xmlmod2_tail +xmlmod2_tail() +

+Passt XML-Optionszugriff an. +

+

+RevPiOption.xmlmod_tail

+xmlmod_tail()

Passt XML-Optionszugriff an.

diff --git a/revpipycontrol.api b/revpipycontrol.api index b0b3957..e2e9583 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -13,6 +13,7 @@ revpicheckclient.RevPiCheckClient._workvalues?5(io_dicts=None, writeout=False) revpicheckclient.RevPiCheckClient.hideallwindows?4() revpicheckclient.RevPiCheckClient.readvalues?4() revpicheckclient.RevPiCheckClient.refreshvalues?4() +revpicheckclient.RevPiCheckClient.tmr_workvalues?4() revpicheckclient.RevPiCheckClient.toggleauto?4() revpicheckclient.RevPiCheckClient.togglewrite?4() revpicheckclient.RevPiCheckClient.validatereturn?4(returnlist) @@ -39,11 +40,12 @@ revpilogfile._?8 revpioption.RevPiOption._changesdone?5() revpioption.RevPiOption._checkclose?5(event=None) revpioption.RevPiOption._createwidgets?5() -revpioption.RevPiOption._loadappdata?5() +revpioption.RevPiOption._loadappdata?5(refresh=False) revpioption.RevPiOption._setappdata?5() revpioption.RevPiOption.askxmlon?4() -revpioption.RevPiOption.xmlmods?4() -revpioption.RevPiOption?1(master, xmlcli, xmlmode) +revpioption.RevPiOption.xmlmod2_tail?4() +revpioption.RevPiOption.xmlmod_tail?4() +revpioption.RevPiOption?1(master, xmlcli) revpioption._?8 revpiplclist.RevPiPlcList._checkclose?5(event=None) revpiplclist.RevPiPlcList._createwidgets?5() diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 4c196c4..57bc865 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -28,7 +28,9 @@ class RevPiCheckClient(tkinter.Frame): self.xmlmode = xmlmode self.cli = xmlcli self.cli.psstart() - self.dict_devices = {v[0]: v[1] for v in self.cli.ps_devices()} + self.lst_devices = self.cli.ps_devices() + self.dict_devices = {v[0]: v[1] for v in self.lst_devices} + self.lst_devices = [d[0] for d in self.lst_devices] self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) @@ -202,7 +204,7 @@ class RevPiCheckClient(tkinter.Frame): devgrp["text"] = _("Devices of RevPi") devgrp.pack(fill="y", side="left") - for dev in self.dict_devices: + for dev in self.lst_devices: win = tkinter.Toplevel(self) win.wm_title(self.dict_devices[dev]) win.protocol( @@ -245,15 +247,17 @@ class RevPiCheckClient(tkinter.Frame): self.btn_read.pack(fill="x") self.btn_write = tkinter.Button(cntgrp) + self.btn_write["state"] = "normal" if self.xmlmode >= 3 \ + else "disabled" self.btn_write["text"] = _("Write Outputs") self.btn_write["command"] = self.writevalues self.btn_write.pack(fill="x") - check = tkinter.Checkbutton(cntgrp) - check["command"] = self.toggleauto - check["text"] = _("Autorefresh values") - check["variable"] = self.autorw - check.pack(anchor="w") + self.chk_auto = tkinter.Checkbutton(cntgrp) + self.chk_auto["command"] = self.toggleauto + self.chk_auto["text"] = _("Autorefresh values") + self.chk_auto["variable"] = self.autorw + self.chk_auto.pack(anchor="w") self.chk_dowrite = tkinter.Checkbutton(cntgrp) self.chk_dowrite["command"] = self.togglewrite @@ -335,9 +339,6 @@ class RevPiCheckClient(tkinter.Frame): with self.lk: self.validatereturn(xmlmc()) - if self.autorw.get(): - self.master.after(200, self._workvalues) - def hideallwindows(self): u"""Versteckt alle Fenster.""" for win in self.dict_wins: @@ -353,19 +354,35 @@ class RevPiCheckClient(tkinter.Frame): if not self.autorw.get(): self._workvalues() + def tmr_workvalues(self): + u"""Timer für zyklische Abfrage. + @return None""" + # Verbleibener Timer könnte schon ungültig sein + if not self.autorw.get(): + try: + self.chk_auto["state"] = "normal" + except: + pass + return None + + self._workvalues() + self.master.after(200, self.tmr_workvalues) + def toggleauto(self): u"""Schaltet zwischen Autorefresh um und aktualisiert Widgets.""" stateval = "disabled" if self.autorw.get() else "normal" self.btn_refresh["state"] = stateval self.btn_read["state"] = stateval - self.btn_write["state"] = stateval + self.btn_write["state"] = stateval if self.xmlmode >= 3 \ + else "disabled" self.chk_dowrite["state"] = "normal" if self.xmlmode >= 3 \ and self.autorw.get() else "disabled" if self.autorw.get(): - self._workvalues() + self.tmr_workvalues() else: + self.chk_auto["state"] = "disabled" self.dowrite.set(False) def togglewrite(self): diff --git a/revpipycontrol/revpiinfo.py b/revpipycontrol/revpiinfo.py index 12e6346..eccf1b3 100644 --- a/revpipycontrol/revpiinfo.py +++ b/revpipycontrol/revpiinfo.py @@ -112,23 +112,25 @@ class RevPiInfo(tkinter.Frame): # Rechte Seite Mittelframe --------------- # Funktionen der Gegenstelle - frame_func = tkinter.Frame(frame_main) - txt_xmlfunc = tkinter.Text(frame_func, width=30, height=15) - scr_xmlfunc = tkinter.Scrollbar(frame_func) - if extended: - txt_xmlfunc.insert(tkinter.END, "\n".join( - [] if self.xmlcli is None else self.xmlcli.system.listMethods() - )) - else: - txt_xmlfunc.insert(tkinter.END, "\n".join( - [] if self.xmlcli is None else self.xmlcli.get_filelist() - )) - txt_xmlfunc["yscrollcommand"] = scr_xmlfunc.set - txt_xmlfunc["state"] = "disabled" - scr_xmlfunc["command"] = txt_xmlfunc.yview - txt_xmlfunc.pack(side="left") - scr_xmlfunc.pack(fill="y", side="right") - frame_func.grid(column=3, row=0, rowspan=int_row + 1, **cpadnw) + if self.xmlcli is not None: + frame_func = tkinter.Frame(frame_main) + txt_xmlfunc = tkinter.Text(frame_func, width=30, height=15) + scr_xmlfunc = tkinter.Scrollbar(frame_func) + if extended: + txt_xmlfunc.insert(tkinter.END, "\n".join( + self.xmlcli.system.listMethods() + )) + elif "get_filelist" in self.xmlcli.system.listMethods(): + txt_xmlfunc.insert(tkinter.END, "\n".join( + self.xmlcli.get_filelist() + )) + txt_xmlfunc["yscrollcommand"] = scr_xmlfunc.set + txt_xmlfunc["state"] = "disabled" + scr_xmlfunc["command"] = txt_xmlfunc.yview + txt_xmlfunc.pack(side="left") + scr_xmlfunc.pack(fill="y", side="right") + if txt_xmlfunc.get(1.0) != "\n": + frame_func.grid(column=3, row=0, rowspan=int_row + 1, **cpadnw) # Unten Beenden-Button ----------------------------------------------- self.btnapplog = tkinter.Button(self) diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index 8c67122..f758429 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -15,10 +15,13 @@ _ = gettrans() class RevPiOption(tkinter.Frame): - def __init__(self, master, xmlcli, xmlmode): + def __init__(self, master, xmlcli): u"""Init RevPiOption-Class. @return None""" - if xmlmode < 2: + try: + self.dc = xmlcli.get_config() + except: + self.dc = None return None super().__init__(master) @@ -27,8 +30,9 @@ class RevPiOption(tkinter.Frame): self.pack(expand=True, fill="both") self.xmlcli = xmlcli - self.xmlmode = xmlmode - self.xmlstate = "normal" if xmlmode == 3 else "disabled" + self.mrk_var_xmlmod2 = False + self.mrk_var_xmlmod3 = False + self.mrk_xmlmodask = False # Fenster bauen self._createwidgets() @@ -61,7 +65,7 @@ class RevPiOption(tkinter.Frame): _("Question"), _("Do you really want to quit? \nUnsaved changes will " "be lost"), - parent=self.master + parent=self.master, default="no" ) if ask: @@ -72,6 +76,8 @@ class RevPiOption(tkinter.Frame): self.master.wm_title(_("RevPi Python PLC Options")) self.master.wm_resizable(width=False, height=False) + xmlstate = "normal" if self.dc["xmlrpc"] >= 3 else "disabled" + cpadw = {"padx": 4, "pady": 2, "sticky": "w"} cpadwe = {"padx": 4, "pady": 2, "sticky": "we"} @@ -87,18 +93,18 @@ class RevPiOption(tkinter.Frame): ckb_start = tkinter.Checkbutton(stst) ckb_start["text"] = _("Start program automatically") - ckb_start["state"] = self.xmlstate + ckb_start["state"] = xmlstate ckb_start["variable"] = self.var_start ckb_start.grid(**cpadw) ckb_reload = tkinter.Checkbutton(stst) ckb_reload["text"] = _("Restart program after exit") - ckb_reload["state"] = self.xmlstate + ckb_reload["state"] = xmlstate ckb_reload["variable"] = self.var_reload ckb_reload.grid(**cpadw) ckb_zexit = tkinter.Checkbutton(stst, justify="left") - ckb_zexit["state"] = self.xmlstate + ckb_zexit["state"] = xmlstate ckb_zexit["text"] = _( "Set process image to NULL if program\n" "terminates successfully") @@ -106,7 +112,7 @@ class RevPiOption(tkinter.Frame): ckb_zexit.grid(**cpadw) ckb_zerr = tkinter.Checkbutton(stst, justify="left") - ckb_zerr["state"] = self.xmlstate + ckb_zerr["state"] = xmlstate ckb_zerr["text"] = _( "Set process image to NULL if program\n" "terminates with errors") @@ -129,14 +135,14 @@ class RevPiOption(tkinter.Frame): lbl["text"] = _("Python version") lbl.grid(columnspan=2, row=0, **cpadw) rbn = tkinter.Radiobutton(prog) - rbn["state"] = self.xmlstate + rbn["state"] = xmlstate rbn["text"] = "Python2" rbn["value"] = 2 rbn["variable"] = self.var_pythonver rbn.grid(column=0, row=1, **cpadw) rbn = tkinter.Radiobutton(prog) - rbn["state"] = self.xmlstate + rbn["state"] = xmlstate rbn["text"] = "Python3" rbn["value"] = 3 rbn["variable"] = self.var_pythonver @@ -151,7 +157,7 @@ class RevPiOption(tkinter.Frame): lst.append("none") opt_startpy = tkinter.OptionMenu( prog, self.var_startpy, *lst) - opt_startpy["state"] = self.xmlstate + opt_startpy["state"] = xmlstate opt_startpy.grid(columnspan=2, **cpadwe) lbl = tkinter.Label(prog) @@ -163,7 +169,7 @@ class RevPiOption(tkinter.Frame): txt.grid(columnspan=2, **cpadw) ckb_slave = tkinter.Checkbutton(prog, justify="left") - ckb_slave["state"] = self.xmlstate + ckb_slave["state"] = xmlstate ckb_slave["text"] = _("Use RevPi as PLC-Slave") ckb_slave["state"] = "disabled" ckb_slave["variable"] = self.var_slave @@ -182,21 +188,21 @@ class RevPiOption(tkinter.Frame): ckb_xmlon = tkinter.Checkbutton(xmlrpc) ckb_xmlon["command"] = self.askxmlon - ckb_xmlon["state"] = self.xmlstate + ckb_xmlon["state"] = xmlstate ckb_xmlon["text"] = _("Activate XML-RPC server on RevPi") ckb_xmlon["variable"] = self.var_xmlon ckb_xmlon.grid(**cpadw) self.ckb_xmlmod2 = tkinter.Checkbutton(xmlrpc, justify="left") - self.ckb_xmlmod2["command"] = self.xmlmods - self.ckb_xmlmod2["state"] = self.xmlstate + self.ckb_xmlmod2["command"] = self.xmlmod2_tail + self.ckb_xmlmod2["state"] = xmlstate self.ckb_xmlmod2["text"] = \ _("Allow download of piCtory configuration and\nPLC programm") self.ckb_xmlmod2["variable"] = self.var_xmlmod2 self.ckb_xmlmod2.grid(**cpadw) self.ckb_xmlmod3 = tkinter.Checkbutton(xmlrpc, justify="left") - self.ckb_xmlmod3["state"] = self.xmlstate + self.ckb_xmlmod3["state"] = xmlstate self.ckb_xmlmod3["text"] = \ _("Allow upload of piCtory configuration and\nPLC programm") self.ckb_xmlmod3["variable"] = self.var_xmlmod3 @@ -209,14 +215,14 @@ class RevPiOption(tkinter.Frame): spb_xmlport = tkinter.Spinbox(xmlrpc) spb_xmlport["to"] = 65535 spb_xmlport["from"] = 1024 - spb_xmlport["state"] = self.xmlstate + spb_xmlport["state"] = xmlstate spb_xmlport["textvariable"] = self.var_xmlport spb_xmlport.grid(**cpadwe) # Buttons btn_save = tkinter.Button(self) btn_save["command"] = self._setappdata - btn_save["state"] = self.xmlstate + btn_save["state"] = xmlstate btn_save["text"] = _("Save") btn_save.grid(column=0, row=3) @@ -225,9 +231,11 @@ class RevPiOption(tkinter.Frame): btn_close["text"] = _("Close") btn_close.grid(column=1, row=3) - def _loadappdata(self): - u"""Läd aktuelle Einstellungen vom RevPi.""" - self.dc = self.xmlcli.get_config() + def _loadappdata(self, refresh=False): + u"""Läd aktuelle Einstellungen vom RevPi. + @param refresh Wenn True, werden Einstellungen heruntergeladen.""" + if refresh: + self.dc = self.xmlcli.get_config() self.var_start.set(self.dc.get("autostart", "1")) self.var_reload.set(self.dc.get("autoreload", "1")) @@ -241,33 +249,33 @@ class RevPiOption(tkinter.Frame): self.var_xmlon.set(self.dc.get("xmlrpc", 0) >= 1) self.var_xmlmod2.set(self.dc.get("xmlrpc", 0) >= 2) + self.mrk_var_xmlmod2 = self.var_xmlmod2.get() self.var_xmlmod3.set(self.dc.get("xmlrpc", 0) >= 3) + self.mrk_var_xmlmod3 = self.var_xmlmod3.get() self.var_xmlport.set(self.dc.get("xmlrpcport", "55123")) def _setappdata(self): u"""Speichert geänderte Einstellungen auf RevPi.""" - dc = {} - dc["autostart"] = int(self.var_start.get()) - dc["autoreload"] = int(self.var_reload.get()) - dc["zeroonexit"] = int(self.var_zexit.get()) - dc["zeroonerror"] = int(self.var_zerr.get()) + self.dc["autostart"] = int(self.var_start.get()) + self.dc["autoreload"] = int(self.var_reload.get()) + self.dc["zeroonexit"] = int(self.var_zexit.get()) + self.dc["zeroonerror"] = int(self.var_zerr.get()) - dc["plcprogram"] = self.var_startpy.get() - dc["plcarguments"] = self.var_startargs.get() - dc["pythonversion"] = self.var_pythonver.get() - dc["plcslave"] = int(self.var_slave.get()) + self.dc["plcprogram"] = self.var_startpy.get() + self.dc["plcarguments"] = self.var_startargs.get() + self.dc["pythonversion"] = self.var_pythonver.get() + self.dc["plcslave"] = int(self.var_slave.get()) - dc["xmlrpc"] = 0 + self.dc["xmlrpc"] = 0 if self.var_xmlon.get(): - dc["xmlrpc"] += 1 + self.dc["xmlrpc"] += 1 if self.var_xmlmod2.get(): - dc["xmlrpc"] += 1 + self.dc["xmlrpc"] += 1 if self.var_xmlmod3.get(): - dc["xmlrpc"] += 1 + self.dc["xmlrpc"] += 1 - dc["xmlrpcport"] = self.var_xmlport.get() - self.xmlmode = dc["xmlrpc"] + self.dc["xmlrpcport"] = self.var_xmlport.get() ask = tkmsg.askyesnocancel( _("Question"), @@ -277,12 +285,13 @@ class RevPiOption(tkinter.Frame): parent=self.master ) if ask is not None: - if self.xmlcli.set_config(dc, ask): + if self.xmlcli.set_config(self.dc, ask): tkmsg.showinfo( _("Information"), _("Settings saved"), parent=self.master ) + self._checkclose() else: tkmsg.showerror( _("Error"), @@ -293,22 +302,36 @@ class RevPiOption(tkinter.Frame): def askxmlon(self): u"""Fragt Nuter, ob wirklicht abgeschaltet werden soll.""" - if not self.var_xmlon.get(): - ask = tkmsg.askyesno( + if not (self.var_xmlon.get() or self.mrk_xmlmodask): + self.mrk_xmlmodask = tkmsg.askyesno( _("Question"), _("Are you sure you want to deactivate the XML-RPC server? " "You will NOT be able to access the Revolution Pi with " "this program."), parent=self.master ) - if not ask: + if not self.mrk_xmlmodask: self.var_xmlon.set(True) - self.xmlmods() + self.xmlmod_tail() - def xmlmods(self): + def xmlmod_tail(self): u"""Passt XML-Optionszugriff an.""" - self.ckb_xmlmod2["state"] = \ - "normal" if self.var_xmlon.get() else "disabled" - self.ckb_xmlmod3["state"] = \ - "normal" if self.var_xmlmod2.get() else "disabled" + if self.var_xmlon.get(): + self.var_xmlmod2.set(self.mrk_var_xmlmod2) + self.ckb_xmlmod2["state"] = "normal" + else: + self.mrk_var_xmlmod2 = self.var_xmlmod2.get() + self.var_xmlmod2.set(False) + self.ckb_xmlmod2["state"] = "disabled" + self.xmlmod2_tail() + + def xmlmod2_tail(self): + u"""Passt XML-Optionszugriff an.""" + if self.var_xmlmod2.get(): + self.var_xmlmod3.set(self.mrk_var_xmlmod3) + self.ckb_xmlmod3["state"] = "normal" + else: + self.mrk_var_xmlmod3 = self.var_xmlmod3.get() + self.var_xmlmod3.set(False) + self.ckb_xmlmod3["state"] = "disabled" diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 1b15651..3333975 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -78,6 +78,7 @@ class RevPiPyControl(tkinter.Frame): if self.tkprogram is not None: self.tkprogram.destroy() if self.debugframe is not None: + self.plcdebug() self.debugframe.destroy() self.cli.psstop() self.debugframe = None @@ -243,8 +244,9 @@ class RevPiPyControl(tkinter.Frame): # Show/Hide wechseln if self.debugframe.winfo_viewable(): self.debugframe.hideallwindows() - self.debugframe.autorw.set(False) - self.debugframe.toggleauto() + if self.debugframe.autorw.get(): + self.debugframe.autorw.set(False) + self.debugframe.toggleauto() self.debugframe.dowrite.set(False) self.debugframe.pack_forget() else: @@ -293,11 +295,12 @@ class RevPiPyControl(tkinter.Frame): else: win = tkinter.Toplevel(self) self.tkoptions = \ - revpioption.RevPiOption(win, self.cli, self.xmlmode) + revpioption.RevPiOption(win, self.cli) win.focus_set() win.grab_set() self.wait_window(win) - self.xmlmode = self.tkoptions.xmlmode + if self.tkoptions.dc is not None: + self.xmlmode = self.tkoptions.dc["xmlrpc"] def plcprogram(self): u"""Startet das Programmfenster.""" @@ -331,12 +334,12 @@ class RevPiPyControl(tkinter.Frame): def serverdisconnect(self): u"""Trennt eine bestehende Verbindung.""" + self._closeall() socket.setdefaulttimeout(2) self.cli = None self._btnstate() self.mbar.entryconfig("PLC", state="disabled") self.var_conn.set("") - self._closeall() def servererror(self): u"""Setzt alles zurück für neue Verbindungen.""" From 15b59be6d8a4cb4178f2c7cf44d49e0c621688f9 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sun, 2 Jul 2017 11:36:17 +0200 Subject: [PATCH 11/13] Bugfix: RevPiLogfile ignoriert bei Dienstneustart xml exception Bugfix: RevPiOption ignorierte Abbrechen-Schaltfl?che beim speichern Bugfix: WindowHandling bei gesicherten Fenstern Bugfix: Optionsspeicherung und neustart RevPiCheckclient Designanpassungen locale in setup ?bernommen --- doc/index.html | 41 +++ doc/revpiinfo.html | 2 +- doc/revpioption.html | 7 +- doc/revpipycontrol.html | 5 +- revpipycontrol.api | 5 +- revpipycontrol.e4p | 8 +- .../locale/de/LC_MESSAGES/revpipycontrol.po | 266 +++++++++--------- revpipycontrol/revpicheckclient.py | 15 +- revpipycontrol/revpiinfo.py | 9 - revpipycontrol/revpilogfile.py | 22 +- revpipycontrol/revpioption.py | 50 ++-- revpipycontrol/revpipycontrol.py | 43 +-- setup.py | 2 +- 13 files changed, 272 insertions(+), 203 deletions(-) create mode 100644 doc/index.html diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..621e3bb --- /dev/null +++ b/doc/index.html @@ -0,0 +1,41 @@ + + +Table of contents + + + +

+Table of contents

+ + + +

+Modules

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
mytools
revpicheckclient
revpiinfo
revpilogfile
revpioption
revpiplclist
revpiprogram
revpipycontrol
+ \ No newline at end of file diff --git a/doc/revpiinfo.html b/doc/revpiinfo.html index e6f5ae0..ebc2484 100644 --- a/doc/revpiinfo.html +++ b/doc/revpiinfo.html @@ -35,7 +35,7 @@ tkinter.Frame

Class Attributes

- +
app
cli
root
None

Class Methods

diff --git a/doc/revpioption.html b/doc/revpioption.html index b9f7c15..1c42b8d 100644 --- a/doc/revpioption.html +++ b/doc/revpioption.html @@ -135,7 +135,12 @@ RevPiOption._setappdata _setappdata()

Speichert geänderte Einstellungen auf RevPi. -

+

+
Returns:
+
+None +
+

RevPiOption.askxmlon

askxmlon() diff --git a/doc/revpipycontrol.html b/doc/revpipycontrol.html index e2d9ffd..25d825a 100644 --- a/doc/revpipycontrol.html +++ b/doc/revpipycontrol.html @@ -170,13 +170,16 @@ Generiert Menüeinträge.

RevPiPyControl._opt_conn

-_opt_conn(text) +_opt_conn(text, reconnect=False)

Stellt eine neue Verbindung zu RevPiPyLoad her.

text
Verbindungsname +
reconnect
+
+Socket Timeout nicht heruntersetzen

diff --git a/revpipycontrol.api b/revpipycontrol.api index e2e9583..0fcb54c 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -22,9 +22,6 @@ revpicheckclient.RevPiCheckClient?1(master, xmlcli, xmlmode=0) revpicheckclient._?8 revpiinfo.RevPiInfo._checkclose?5(event=None) revpiinfo.RevPiInfo._createwidgets?5(extended=False) -revpiinfo.RevPiInfo.app?7 -revpiinfo.RevPiInfo.cli?7 -revpiinfo.RevPiInfo.root?7 revpiinfo.RevPiInfo.visitwebsite?4(event=None) revpiinfo.RevPiInfo?1(master, xmlcli, version) revpiinfo._?8 @@ -86,7 +83,7 @@ revpipycontrol.RevPiPyControl._closeapp?5(event=None) revpipycontrol.RevPiPyControl._createwidgets?5() revpipycontrol.RevPiPyControl._fillconnbar?5() revpipycontrol.RevPiPyControl._fillmbar?5() -revpipycontrol.RevPiPyControl._opt_conn?5(text) +revpipycontrol.RevPiPyControl._opt_conn?5(text, reconnect=False) revpipycontrol.RevPiPyControl.infowindow?4() revpipycontrol.RevPiPyControl.myapp?7 revpipycontrol.RevPiPyControl.plcdebug?4() diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index 24fdc69..38de6f1 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -227,12 +227,6 @@ setup.py - - noindex - - - True - outputDirectory diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 493f953..7698dff 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-06-30 21:05+0200\n" -"PO-Revision-Date: 2017-06-30 21:05+0200\n" +"POT-Creation-Date: 2017-07-02 11:32+0200\n" +"PO-Revision-Date: 2017-07-02 11:33+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -15,17 +15,17 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SearchPath-0: .\n" -#: revpicheckclient.py:103 revpicheckclient.py:395 revpioption.py:288 -#: revpiplclist.py:199 revpiprogram.py:306 revpiprogram.py:337 -#: revpiprogram.py:401 revpiprogram.py:407 revpiprogram.py:413 -#: revpiprogram.py:421 revpiprogram.py:427 revpiprogram.py:460 -#: revpiprogram.py:544 revpiprogram.py:616 revpiprogram.py:647 -#: revpiprogram.py:660 revpiprogram.py:715 revpiprogram.py:735 -#: revpiprogram.py:743 revpipycontrol.py:342 +#: revpicheckclient.py:104 revpicheckclient.py:412 revpioption.py:309 +#: revpiplclist.py:205 revpiprogram.py:315 revpiprogram.py:346 +#: revpiprogram.py:410 revpiprogram.py:416 revpiprogram.py:422 +#: revpiprogram.py:430 revpiprogram.py:436 revpiprogram.py:469 +#: revpiprogram.py:553 revpiprogram.py:626 revpiprogram.py:657 +#: revpiprogram.py:670 revpiprogram.py:725 revpiprogram.py:745 +#: revpiprogram.py:753 revpipycontrol.py:359 msgid "Error" msgstr "Fehler" -#: revpicheckclient.py:104 +#: revpicheckclient.py:105 msgid "" "Given value for Output '{}' is not valid! \n" "Reset to '{}'" @@ -33,40 +33,40 @@ msgstr "" "Angegebener Wert bei Output '{}' ist nicht gültig! \n" "Setze auf '{}' zurück" -#: revpicheckclient.py:202 +#: revpicheckclient.py:204 msgid "Devices of RevPi" msgstr "Devices vom RevPi" -#: revpicheckclient.py:234 +#: revpicheckclient.py:236 msgid "Control" msgstr "Kontrolle" -#: revpicheckclient.py:238 +#: revpicheckclient.py:240 msgid "Read all IOs" msgstr "IOs aktualisieren" -#: revpicheckclient.py:243 +#: revpicheckclient.py:245 msgid "Read just Inputs" msgstr "Inputs lesen" -#: revpicheckclient.py:248 +#: revpicheckclient.py:252 msgid "Write Outputs" msgstr "Outputs schreiben" -#: revpicheckclient.py:254 +#: revpicheckclient.py:258 msgid "Autorefresh values" msgstr "Aktualisiere automatisch" -#: revpicheckclient.py:262 +#: revpicheckclient.py:266 msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" -#: revpicheckclient.py:276 revpiprogram.py:434 revpipycontrol.py:228 -#: revpipycontrol.py:267 revpipycontrol.py:285 revpipycontrol.py:303 +#: revpicheckclient.py:280 revpiprogram.py:443 revpipycontrol.py:235 +#: revpipycontrol.py:276 revpipycontrol.py:294 revpipycontrol.py:320 msgid "Warning" msgstr "Warnung" -#: revpicheckclient.py:277 +#: revpicheckclient.py:281 msgid "" "You want to set outputs on the RevPi! Note that these are set " "IMMEDIATELY!!! \n" @@ -78,7 +78,7 @@ msgstr "" "Wenn auf dem RevPi ein anderes Programm zur Steuerung läuft, könnte dies " "gestört werden und die Ausgänge wieder zurücksetzen." -#: revpicheckclient.py:392 +#: revpicheckclient.py:409 msgid "Error set value of device '{}' Output '{}': {} \n" msgstr "Fehler beim Setzen auf Device '{}' bei Output '{}': {}\n" @@ -125,36 +125,36 @@ msgstr "" "\n" "(c) Sven Sager, Lizenz: LGPLv3" -#: revpiinfo.py:136 revpioption.py:225 revpiplclist.py:133 +#: revpiinfo.py:138 revpioption.py:232 revpiplclist.py:134 msgid "Close" msgstr "Schließen" -#: revpilogfile.py:39 +#: revpilogfile.py:41 msgid "RevPi Python PLC Logs" msgstr "RevPi Python PLC Logdaten" -#: revpilogfile.py:52 +#: revpilogfile.py:54 msgid "RevPiPyLoad - Logfile" msgstr "RevPiPyLoad - Logdatei" -#: revpilogfile.py:56 revpilogfile.py:71 +#: revpilogfile.py:58 revpilogfile.py:73 msgid "Clear screen" msgstr "Leere Ansicht" -#: revpilogfile.py:67 +#: revpilogfile.py:69 msgid "Python PLC program - Logfile" msgstr "Python PLC Programm - Logdatei" -#: revpilogfile.py:147 +#: revpilogfile.py:157 msgid "Can not access log file on the RevPi" msgstr "RevPi kann auf Logdatei nicht zugreifen" -#: revpioption.py:61 revpioption.py:273 revpioption.py:298 revpiplclist.py:62 -#: revpiplclist.py:176 revpiprogram.py:370 revpiprogram.py:445 +#: revpioption.py:66 revpioption.py:272 revpioption.py:319 revpiplclist.py:63 +#: revpiplclist.py:181 revpiprogram.py:379 revpiprogram.py:454 msgid "Question" msgstr "Frage" -#: revpioption.py:62 revpiplclist.py:63 +#: revpioption.py:67 revpiplclist.py:64 msgid "" "Do you really want to quit? \n" "Unsaved changes will be lost" @@ -162,23 +162,23 @@ msgstr "" "Wollen Sie wirklich beenden? \n" "Nicht gespeicherte Änderungen gehen verloren" -#: revpioption.py:72 +#: revpioption.py:77 msgid "RevPi Python PLC Options" msgstr "RevPi Python PLC Einstellungen" -#: revpioption.py:80 +#: revpioption.py:87 msgid "Start / Stop behavior" msgstr "Start / Stop Verhalten" -#: revpioption.py:89 +#: revpioption.py:96 msgid "Start program automatically" msgstr "Starte Programm automatisch" -#: revpioption.py:95 +#: revpioption.py:102 msgid "Restart program after exit" msgstr "Starte Programm nach Beenden neu" -#: revpioption.py:103 +#: revpioption.py:110 msgid "" "Set process image to NULL if program\n" "terminates successfully" @@ -186,7 +186,7 @@ msgstr "" "\"Prozessabbild auf NULL setzen, wenn Programm\n" "\"erfolgreich beendet wird\"" -#: revpioption.py:111 +#: revpioption.py:118 msgid "" "Set process image to NULL if program\n" "terminates with errors" @@ -194,35 +194,35 @@ msgstr "" "Prozessabbild auf NULL setzen, wenn Programm\n" "fehlerhaft beendet wird" -#: revpioption.py:118 +#: revpioption.py:125 msgid "PLC program" msgstr "PLC Programm" -#: revpioption.py:129 +#: revpioption.py:136 msgid "Python version" msgstr "Python Version" -#: revpioption.py:146 +#: revpioption.py:153 msgid "Python PLC program name" msgstr "Python PLC Programmname" -#: revpioption.py:158 +#: revpioption.py:165 msgid "Program arguments" msgstr "Programmargumente" -#: revpioption.py:167 +#: revpioption.py:174 msgid "Use RevPi as PLC-Slave" msgstr "RevPi als PLC-Slave verwenden" -#: revpioption.py:174 +#: revpioption.py:181 msgid "XML-RPC server" msgstr "XML-RPC Server" -#: revpioption.py:186 +#: revpioption.py:193 msgid "Activate XML-RPC server on RevPi" msgstr "Aktiviere XML-RPC Server auf RevPi" -#: revpioption.py:194 +#: revpioption.py:201 msgid "" "Allow download of piCtory configuration and\n" "PLC programm" @@ -230,7 +230,7 @@ msgstr "" "Download von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:201 +#: revpioption.py:208 msgid "" "Allow upload of piCtory configuration and\n" "PLC programm" @@ -238,15 +238,23 @@ msgstr "" "Hochladen von piCtroy Konfiguration und\n" "PLC Programm zulassen" -#: revpioption.py:206 +#: revpioption.py:213 msgid "XML-RPC server port" msgstr "XML-RPC Serverport" -#: revpioption.py:220 revpiplclist.py:130 +#: revpioption.py:227 revpiplclist.py:131 msgid "Save" msgstr "Speichern" -#: revpioption.py:274 +#: revpioption.py:265 revpioption.py:301 revpiplclist.py:197 revpiprogram.py:68 +msgid "Information" +msgstr "Information" + +#: revpioption.py:266 +msgid "You have not made any changes to save." +msgstr "Sie haben keine Änderungen zum Speichern vorgenommen." + +#: revpioption.py:273 msgid "" "The settings are now saved on the Revolution Pi. \n" "\n" @@ -258,21 +266,17 @@ msgstr "" "Sollen die neuen Einstellungen sofort in Kraft treten?\n" "Dies bedeutet einen Neustart des Dienstes und des laufenden PLC-Programms!" -#: revpioption.py:282 revpiplclist.py:191 revpiprogram.py:65 -msgid "Information" -msgstr "Information" - -#: revpioption.py:283 +#: revpioption.py:302 msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: revpioption.py:289 +#: revpioption.py:310 msgid "The settings could not be saved. This can happen if values are wrong!" msgstr "" "Die Einstellungen konnten nicht gesichert werden. Dies kann passieren, wenn " "Werte falsch sind!" -#: revpioption.py:299 +#: revpioption.py:320 msgid "" "Are you sure you want to deactivate the XML-RPC server? You will NOT be able " "to access the Revolution Pi with this program." @@ -280,39 +284,39 @@ msgstr "" "Soll der XML-RPC Server wirklich beendet werden? Sie können dann NICHT mehr " "mit diesem Programm auf den Revolution Pi zugreifen." -#: revpiplclist.py:73 +#: revpiplclist.py:74 msgid "RevPi Python PLC connections" msgstr "RevPi Python PLC Verbindungen" -#: revpiplclist.py:93 +#: revpiplclist.py:94 msgid "Name" msgstr "Name" -#: revpiplclist.py:100 +#: revpiplclist.py:101 msgid "IP address" msgstr "IP Adresse" -#: revpiplclist.py:108 +#: revpiplclist.py:109 msgid "Port" msgstr "Port" -#: revpiplclist.py:117 +#: revpiplclist.py:118 msgid "New" msgstr "Neu" -#: revpiplclist.py:120 +#: revpiplclist.py:121 msgid "Apply" msgstr "Übernehmen" -#: revpiplclist.py:124 +#: revpiplclist.py:125 msgid "Remove" msgstr "Entfernen" -#: revpiplclist.py:177 +#: revpiplclist.py:182 msgid "Do you really want to delete the selected connection '{}'" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" -#: revpiplclist.py:192 +#: revpiplclist.py:198 msgid "" "Successfully saved. \n" "Do you want to close this window?" @@ -320,11 +324,11 @@ msgstr "" "Verbindungen erfolgreich gespeichert. \n" "Möchten Sie dieses Fenster jetzt schließen?" -#: revpiplclist.py:200 +#: revpiplclist.py:206 msgid "Failed to save connections" msgstr "Verbindungen konnten nicht gespeichert werden" -#: revpiprogram.py:66 +#: revpiprogram.py:69 msgid "" "A PLC program has been uploaded. Please check the PLC options to see if the " "correct program is specified as the start program." @@ -332,135 +336,135 @@ msgstr "" "Ein PLC Programm wurde hochgeladen. Bitte prüfen Sie die PLC Optionen, ob " "dort das richtige Programm als Startprogramm angegeben ist." -#: revpiprogram.py:74 +#: revpiprogram.py:78 msgid "RevPi Python PLC program" msgstr "RevPi Python PLC Programm" -#: revpiprogram.py:88 +#: revpiprogram.py:92 msgid "PLC python program" msgstr "PLC Python Programm" -#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:108 -#: revpiprogram.py:112 +#: revpiprogram.py:102 revpiprogram.py:104 revpiprogram.py:112 +#: revpiprogram.py:116 msgid "Files" msgstr "Dateien" -#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:492 -#: revpiprogram.py:600 +#: revpiprogram.py:102 revpiprogram.py:104 revpiprogram.py:501 +#: revpiprogram.py:610 msgid "Zip archive" msgstr "Zip Archiv" -#: revpiprogram.py:98 revpiprogram.py:100 revpiprogram.py:505 -#: revpiprogram.py:630 +#: revpiprogram.py:102 revpiprogram.py:104 revpiprogram.py:514 +#: revpiprogram.py:640 msgid "TGZ archive" msgstr "TGZ Archiv" -#: revpiprogram.py:100 +#: revpiprogram.py:104 msgid "Folder" msgstr "Verzeichnis" -#: revpiprogram.py:117 +#: revpiprogram.py:121 msgid "Download PLC program as:" msgstr "PLC Programm herunterladen als:" -#: revpiprogram.py:127 +#: revpiprogram.py:131 msgid "include piCtory configuration" msgstr "inkl. piCtory Konfiguration" -#: revpiprogram.py:132 revpiprogram.py:176 revpiprogram.py:197 +#: revpiprogram.py:136 revpiprogram.py:180 revpiprogram.py:201 msgid "Download" msgstr "Herunterladen" -#: revpiprogram.py:137 +#: revpiprogram.py:141 msgid "Upload PLC program as:" msgstr "PLC Programm hochladen als:" -#: revpiprogram.py:149 +#: revpiprogram.py:153 msgid "clean upload folder before upload" msgstr "vorher Inhalt im Uploadverzeichnis löschen" -#: revpiprogram.py:156 +#: revpiprogram.py:160 msgid "includes piCtory configuration" msgstr "enthält piCtory Konfiguration" -#: revpiprogram.py:162 revpiprogram.py:184 +#: revpiprogram.py:166 revpiprogram.py:188 msgid "Upload" msgstr "Hochladen" -#: revpiprogram.py:168 +#: revpiprogram.py:172 msgid "piCtory configuration" msgstr "piCtory Konfiguration" -#: revpiprogram.py:172 +#: revpiprogram.py:176 msgid "Download piCtory configuration" msgstr "piCtory Konfiguration herunterladen" -#: revpiprogram.py:179 +#: revpiprogram.py:183 msgid "Upload piCtory configuration" msgstr "piCtory Konfiguration hochladen" -#: revpiprogram.py:190 +#: revpiprogram.py:194 msgid "piControl0 prozess image" msgstr "piControl0 Prozessabbild" -#: revpiprogram.py:193 +#: revpiprogram.py:197 msgid "Download process image dump" msgstr "Prozessabbild Dump herunterladen" -#: revpiprogram.py:203 +#: revpiprogram.py:207 msgid "Reset piControl" msgstr "piControl zurücksetzen" -#: revpiprogram.py:206 +#: revpiprogram.py:210 msgid "Execute piControlReset" msgstr "piControlReset ausführen" -#: revpiprogram.py:210 +#: revpiprogram.py:214 msgid "execute" msgstr "ausführen" -#: revpiprogram.py:216 revpipycontrol.py:107 +#: revpiprogram.py:220 revpipycontrol.py:107 msgid "Exit" msgstr "Beenden" -#: revpiprogram.py:296 revpiprogram.py:327 revpiprogram.py:488 -#: revpiprogram.py:501 +#: revpiprogram.py:305 revpiprogram.py:336 revpiprogram.py:497 +#: revpiprogram.py:510 msgid "Save as..." msgstr "Speichern unter..." -#: revpiprogram.py:299 revpiprogram.py:362 +#: revpiprogram.py:308 revpiprogram.py:371 msgid "piCtory config" msgstr "piCtory Konfiguration" -#: revpiprogram.py:299 revpiprogram.py:330 revpiprogram.py:362 -#: revpiprogram.py:492 revpiprogram.py:505 revpiprogram.py:575 -#: revpiprogram.py:600 revpiprogram.py:630 +#: revpiprogram.py:308 revpiprogram.py:339 revpiprogram.py:371 +#: revpiprogram.py:501 revpiprogram.py:514 revpiprogram.py:585 +#: revpiprogram.py:610 revpiprogram.py:640 msgid "All files" msgstr "Alle Dateien" -#: revpiprogram.py:307 revpiprogram.py:338 revpiprogram.py:545 +#: revpiprogram.py:316 revpiprogram.py:347 revpiprogram.py:554 msgid "Could not load and save file!" msgstr "Datei konnte nicht geladen und gespeichert werden!" -#: revpiprogram.py:312 revpiprogram.py:343 revpiprogram.py:382 -#: revpiprogram.py:390 revpiprogram.py:454 revpiprogram.py:550 -#: revpiprogram.py:705 +#: revpiprogram.py:321 revpiprogram.py:352 revpiprogram.py:391 +#: revpiprogram.py:399 revpiprogram.py:463 revpiprogram.py:559 +#: revpiprogram.py:715 msgid "Success" msgstr "Erfolgreich" -#: revpiprogram.py:313 revpiprogram.py:344 revpiprogram.py:551 +#: revpiprogram.py:322 revpiprogram.py:353 revpiprogram.py:560 msgid "File successfully loaded and saved." msgstr "Dateien erfolgreich übertragen und gespeichert." -#: revpiprogram.py:330 +#: revpiprogram.py:339 msgid "Imagefiles" msgstr "Image Dateien" -#: revpiprogram.py:358 +#: revpiprogram.py:367 msgid "Open piCtory file..." msgstr "piCtory Datei öffnen" -#: revpiprogram.py:371 +#: revpiprogram.py:380 msgid "" "Should the piControl driver be reset after uploading the piCtory " "configuration?" @@ -468,7 +472,7 @@ msgstr "" "Soll nach dem Hochladen der piCtory Konfiguration ein Reset am piControl " "Treiber durchgeführt werden?" -#: revpiprogram.py:383 +#: revpiprogram.py:392 msgid "" "The transfer of the piCtory configuration and the reset of piControl have " "been successfully executed." @@ -476,20 +480,20 @@ msgstr "" "Die Übertragung der piCtory Konfiguration und der Reset von piControl wurden " "erfolgreich ausgeführt." -#: revpiprogram.py:391 +#: revpiprogram.py:400 msgid "The piCtory configuration was successfully transferred." msgstr "" "Die Übertragung der piCtory Konfiguration wurde erfolgreich ausgeführt." -#: revpiprogram.py:402 +#: revpiprogram.py:411 msgid "Can not process the transferred file." msgstr "Kann die übertragene Datei nicht verarbeiten." -#: revpiprogram.py:408 +#: revpiprogram.py:417 msgid "Can not find main elements in piCtory file." msgstr "Kann Hauptelemente in datei nicht finden." -#: revpiprogram.py:414 +#: revpiprogram.py:423 msgid "" "Contained devices could not be found on Revolution Pi. The configuration may " "be from a newer piCtory version!" @@ -497,17 +501,17 @@ msgstr "" "Enthaltene Geräte konnten auf dem Revolution Pi nicht gefunden werden. " "Möglicherweise stammt die Konfiguration von einer neueren piCtory Version." -#: revpiprogram.py:422 +#: revpiprogram.py:431 msgid "Could not load RAP catalog on Revolution Pi." msgstr "Konnte Katalog auf nicht laden." -#: revpiprogram.py:428 +#: revpiprogram.py:437 msgid "The piCtory configuration could not be written on the Revolution Pi." msgstr "" "Die piCtory Konfiguration konnte auf dem Revolution Pi nicht geschrieben " "werden." -#: revpiprogram.py:435 +#: revpiprogram.py:444 msgid "" "The piCtroy configuration has been saved successfully. \n" "An error occurred on piControl reset!" @@ -515,7 +519,7 @@ msgstr "" "Die piCtroy Konfiguration wurde erfolgreich gespeichert. \n" "Beim piControl Reset trat allerdings ein Fehler auf!" -#: revpiprogram.py:446 +#: revpiprogram.py:455 msgid "" "Are you sure to reset piControl? \n" "The process image and the piBridge are interrupted !!!" @@ -523,56 +527,56 @@ msgstr "" "Soll piControlReset wirklich durchgeführt werden? \n" "Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" -#: revpiprogram.py:455 +#: revpiprogram.py:464 msgid "piControlReset executed successfully" msgstr "piControl Reset war erfolgreich" -#: revpiprogram.py:461 +#: revpiprogram.py:470 msgid "piControl reset could not be executed successfully" msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" -#: revpiprogram.py:475 +#: revpiprogram.py:484 msgid "Directory to save" msgstr "Verzeichnis zum Ablegen" -#: revpiprogram.py:585 +#: revpiprogram.py:595 msgid "Folder to upload" msgstr "Verzeichnis zum Hochladen" -#: revpiprogram.py:596 +#: revpiprogram.py:606 msgid "Upload Zip archive..." msgstr "Zip Archiv hochladen..." -#: revpiprogram.py:617 +#: revpiprogram.py:627 msgid "The specified file is not a ZIP archive." msgstr "Die angegebene Datei ist kein ZIP Archiv" -#: revpiprogram.py:626 +#: revpiprogram.py:636 msgid "Upload TarGz archiv..." msgstr "TarGz Archiv hochladen..." -#: revpiprogram.py:648 +#: revpiprogram.py:658 msgid "The specified file is not a TAR archive." msgstr "Die angegebene Datei ist kein TAR Archiv." -#: revpiprogram.py:661 +#: revpiprogram.py:671 msgid "There was an error deleting the files on the Revolution Pi." msgstr "" "Beim Löschen der Dateien auf dem Revolution Pi ist ein Fehler aufgetreten." -#: revpiprogram.py:706 +#: revpiprogram.py:716 msgid "The PLC program was transferred successfully." msgstr "Das PLC Programm wurde erfolgreich übertragen." -#: revpiprogram.py:716 +#: revpiprogram.py:726 msgid "There is no piCtory configuration in this archive." msgstr "Es wurde keine piCtory Konfiguration im Archiv gefunden." -#: revpiprogram.py:736 +#: revpiprogram.py:746 msgid "The Revolution Pi could not process some parts of the transmission." msgstr "Der Revoluton Pi konnte Teile der Übertragung nicht verarbeiten." -#: revpiprogram.py:744 +#: revpiprogram.py:754 msgid "Errors occurred during transmission" msgstr "Bei der Übertragung traten Fehler auf" @@ -636,7 +640,7 @@ msgstr "Trennen" msgid "Connect" msgstr "Verbinden" -#: revpipycontrol.py:229 +#: revpipycontrol.py:236 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " "You need at least version 0.4.0." @@ -644,7 +648,7 @@ msgstr "" "Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " "unterstützt! Sie benötigen mindestens Version 0.4.0." -#: revpipycontrol.py:268 +#: revpipycontrol.py:277 msgid "" "This version of Logviewer ist not supported in version {} of RevPiPyLoad on " "your RevPi! You need at least version 0.4.1." @@ -652,7 +656,7 @@ msgstr "" "Diese Version vom Logbetrachter wird in der RevPiPyLoad Version {} auf Ihrem " "RevPi nicht unterstützt! Sie benötigen mindestens Version 0.4.1." -#: revpipycontrol.py:286 revpipycontrol.py:304 +#: revpipycontrol.py:295 revpipycontrol.py:321 msgid "" "XML-RPC access mode in the RevPiPyLoad configuration is to small to access " "this dialog" @@ -660,7 +664,7 @@ msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:343 +#: revpipycontrol.py:360 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 57bc865..e2c27b1 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -199,10 +199,11 @@ class RevPiCheckClient(tkinter.Frame): def _createwidgets(self): """Erstellt den Fensterinhalt.""" + cFxPxy53 = {"fill": "x", "padx": 5, "pady": 3} devgrp = tkinter.LabelFrame(self) devgrp["text"] = _("Devices of RevPi") - devgrp.pack(fill="y", side="left") + devgrp.pack(expand=True, fill="both", side="left") for dev in self.lst_devices: win = tkinter.Toplevel(self) @@ -229,29 +230,29 @@ class RevPiCheckClient(tkinter.Frame): btn = tkinter.Button(devgrp) btn["command"] = lambda win=win: self.__showwin(win) btn["text"] = self.dict_devices[dev] - btn.pack(fill="x", padx=10, pady=5) + btn.pack(**cFxPxy53) # Steuerungsfunktionen cntgrp = tkinter.LabelFrame(self) cntgrp["text"] = _("Control") - cntgrp.pack(fill="y", side="right") + cntgrp.pack(expand=True, fill="both", side="right") self.btn_refresh = tkinter.Button(cntgrp) self.btn_refresh["text"] = _("Read all IOs") self.btn_refresh["command"] = self.refreshvalues - self.btn_refresh.pack(fill="x") + self.btn_refresh.pack(**cFxPxy53) self.btn_read = tkinter.Button(cntgrp) self.btn_read["text"] = _("Read just Inputs") self.btn_read["command"] = self.readvalues - self.btn_read.pack(fill="x") + self.btn_read.pack(**cFxPxy53) self.btn_write = tkinter.Button(cntgrp) self.btn_write["state"] = "normal" if self.xmlmode >= 3 \ else "disabled" self.btn_write["text"] = _("Write Outputs") self.btn_write["command"] = self.writevalues - self.btn_write.pack(fill="x") + self.btn_write.pack(**cFxPxy53) self.chk_auto = tkinter.Checkbutton(cntgrp) self.chk_auto["command"] = self.toggleauto @@ -361,11 +362,11 @@ class RevPiCheckClient(tkinter.Frame): if not self.autorw.get(): try: self.chk_auto["state"] = "normal" + self._workvalues() except: pass return None - self._workvalues() self.master.after(200, self.tmr_workvalues) def toggleauto(self): diff --git a/revpipycontrol/revpiinfo.py b/revpipycontrol/revpiinfo.py index eccf1b3..775ba9b 100644 --- a/revpipycontrol/revpiinfo.py +++ b/revpipycontrol/revpiinfo.py @@ -141,12 +141,3 @@ class RevPiInfo(tkinter.Frame): def visitwebsite(self, event=None): u"""Öffnet auf dem System einen Webbrowser zur Projektseite.""" webbrowser.open("https://revpimodio.org") - - -# TODO: Remove testdrive -if __name__ == "__main__": - from xmlrpc.client import ServerProxy - cli = ServerProxy("http://192.168.50.35:55123") - root = tkinter.Tk() - app = RevPiInfo(root, cli, "0.4.0") - app.mainloop() diff --git a/revpipycontrol/revpilogfile.py b/revpipycontrol/revpilogfile.py index 06d8770..5595303 100644 --- a/revpipycontrol/revpilogfile.py +++ b/revpipycontrol/revpilogfile.py @@ -23,6 +23,8 @@ class RevPiLogfile(tkinter.Frame): # Systemvariablen self.loadblock = 16384 + self.errapp = 0 + self.errplc = 0 self.mrkapp = 0 self.mrkplc = 0 @@ -94,9 +96,13 @@ class RevPiLogfile(tkinter.Frame): @param full Ganzes Logbuch laden""" # Logs abrufen und letzte Position merken - self.mrkapp = self._load_log( - self.applog, self.xmlcli.load_applog, self.mrkapp, full - ) + try: + self.mrkapp = self._load_log( + self.applog, self.xmlcli.load_applog, self.mrkapp, full + ) + self.errapp = 0 + except: + self.errapp += 1 # Timer neu starten self.master.after(1000, self.get_applog) @@ -106,9 +112,13 @@ class RevPiLogfile(tkinter.Frame): @param full Ganzes Logbuch laden""" # Logs abrufen und letzte Position merken - self.mrkplc = self._load_log( - self.plclog, self.xmlcli.load_plclog, self.mrkplc, full - ) + try: + self.mrkplc = self._load_log( + self.plclog, self.xmlcli.load_plclog, self.mrkplc, full + ) + self.errplc = 0 + except: + self.errplc += 1 # Timer neu starten self.master.after(1000, self.get_plclog) diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index f758429..c7bfd1d 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -33,6 +33,7 @@ class RevPiOption(tkinter.Frame): self.mrk_var_xmlmod2 = False self.mrk_var_xmlmod3 = False self.mrk_xmlmodask = False + self.dorestart = False # Fenster bauen self._createwidgets() @@ -256,26 +257,16 @@ class RevPiOption(tkinter.Frame): self.var_xmlport.set(self.dc.get("xmlrpcport", "55123")) def _setappdata(self): - u"""Speichert geänderte Einstellungen auf RevPi.""" - self.dc["autostart"] = int(self.var_start.get()) - self.dc["autoreload"] = int(self.var_reload.get()) - self.dc["zeroonexit"] = int(self.var_zexit.get()) - self.dc["zeroonerror"] = int(self.var_zerr.get()) + u"""Speichert geänderte Einstellungen auf RevPi. + @return None""" - self.dc["plcprogram"] = self.var_startpy.get() - self.dc["plcarguments"] = self.var_startargs.get() - self.dc["pythonversion"] = self.var_pythonver.get() - self.dc["plcslave"] = int(self.var_slave.get()) - - self.dc["xmlrpc"] = 0 - if self.var_xmlon.get(): - self.dc["xmlrpc"] += 1 - if self.var_xmlmod2.get(): - self.dc["xmlrpc"] += 1 - if self.var_xmlmod3.get(): - self.dc["xmlrpc"] += 1 - - self.dc["xmlrpcport"] = self.var_xmlport.get() + if not self._changesdone(): + tkmsg.showinfo( + _("Information"), + _("You have not made any changes to save."), + ) + self._checkclose() + return None ask = tkmsg.askyesnocancel( _("Question"), @@ -285,12 +276,33 @@ class RevPiOption(tkinter.Frame): parent=self.master ) if ask is not None: + self.dc["autostart"] = int(self.var_start.get()) + self.dc["autoreload"] = int(self.var_reload.get()) + self.dc["zeroonexit"] = int(self.var_zexit.get()) + self.dc["zeroonerror"] = int(self.var_zerr.get()) + + self.dc["plcprogram"] = self.var_startpy.get() + self.dc["plcarguments"] = self.var_startargs.get() + self.dc["pythonversion"] = self.var_pythonver.get() + self.dc["plcslave"] = int(self.var_slave.get()) + + self.dc["xmlrpc"] = 0 + if self.var_xmlon.get(): + self.dc["xmlrpc"] += 1 + if self.var_xmlmod2.get(): + self.dc["xmlrpc"] += 1 + if self.var_xmlmod3.get(): + self.dc["xmlrpc"] += 1 + + self.dc["xmlrpcport"] = self.var_xmlport.get() + if self.xmlcli.set_config(self.dc, ask): tkmsg.showinfo( _("Information"), _("Settings saved"), parent=self.master ) + self.dorestart = ask self._checkclose() else: tkmsg.showerror( diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 3333975..0665a03 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -17,7 +17,6 @@ import socket import tkinter import tkinter.messagebox as tkmsg import webbrowser -from functools import partial from mytools import addroot, gettrans from xmlrpc.client import ServerProxy @@ -120,8 +119,8 @@ class RevPiPyControl(tkinter.Frame): self.mbar.add_cascade(label=_("Help"), menu=menu1) self.var_conn = tkinter.StringVar(self) - self.txt_connect = tkinter.Entry( - self, textvariable=self.var_conn, state="readonly", width=30) + self.txt_connect = tkinter.Entry(self, state="readonly", width=40) + self.txt_connect["textvariable"] = self.var_conn self.txt_connect.pack(fill="x") self.btn_plcstart = tkinter.Button(self) @@ -160,7 +159,7 @@ class RevPiPyControl(tkinter.Frame): self.mconn.delete(0, "end") for con in sorted(self.dict_conn.keys(), key=lambda x: x.lower()): self.mconn.add_command( - label=con, command=partial(self._opt_conn, con) + label=con, command=lambda con=con: self._opt_conn(con) ) def _fillmbar(self): @@ -183,10 +182,15 @@ class RevPiPyControl(tkinter.Frame): self.mconn = tkinter.Menu(self.mbar, tearoff=False) self.mbar.add_cascade(label=_("Connect"), menu=self.mconn) - def _opt_conn(self, text): + def _opt_conn(self, text, reconnect=False): u"""Stellt eine neue Verbindung zu RevPiPyLoad her. - @param text Verbindungsname""" - socket.setdefaulttimeout(2) + @param text Verbindungsname + @param reconnect Socket Timeout nicht heruntersetzen""" + if reconnect: + socket.setdefaulttimeout(15) + else: + socket.setdefaulttimeout(2) + sp = ServerProxy( "http://{}:{}".format( self.dict_conn[text][0], int(self.dict_conn[text][1]) @@ -215,9 +219,9 @@ class RevPiPyControl(tkinter.Frame): def infowindow(self): u"""Öffnet das Fenster für die Info.""" win = tkinter.Toplevel(self) - revpiinfo.RevPiInfo(win, self.cli, pycontrolversion) win.focus_set() win.grab_set() + revpiinfo.RevPiInfo(win, self.cli, pycontrolversion) self.wait_window(win) self.dict_conn = revpiplclist.get_connections() self._fillconnbar() @@ -250,16 +254,16 @@ class RevPiPyControl(tkinter.Frame): self.debugframe.dowrite.set(False) self.debugframe.pack_forget() else: - self.debugframe.pack(fill="y") + self.debugframe.pack(fill="x") self.btn_debug["state"] = "normal" def plclist(self): u"""Öffnet das Fenster für die Verbindungen.""" win = tkinter.Toplevel(self) - revpiplclist.RevPiPlcList(win) win.focus_set() win.grab_set() + revpiplclist.RevPiPlcList(win) self.wait_window(win) self.dict_conn = revpiplclist.get_connections() self._fillconnbar() @@ -294,13 +298,20 @@ class RevPiPyControl(tkinter.Frame): ) else: win = tkinter.Toplevel(self) - self.tkoptions = \ - revpioption.RevPiOption(win, self.cli) win.focus_set() win.grab_set() + self.tkoptions = \ + revpioption.RevPiOption(win, self.cli) self.wait_window(win) - if self.tkoptions.dc is not None: - self.xmlmode = self.tkoptions.dc["xmlrpc"] + if self.tkoptions.dc is not None and self.tkoptions.dorestart: + + # Wenn XML-Modus anders und Dienstneustart + if self.xmlmode != self.tkoptions.dc["xmlrpc"]: + self.serverdisconnect() + self._opt_conn(self.revpiname, True) + + if self.debugframe is not None: + self.cli.psstart() def plcprogram(self): u"""Startet das Programmfenster.""" @@ -313,10 +324,10 @@ class RevPiPyControl(tkinter.Frame): ) else: win = tkinter.Toplevel(self) - self.tkprogram = revpiprogram.RevPiProgram( - win, self.cli, self.xmlmode, self.revpiname) win.focus_set() win.grab_set() + self.tkprogram = revpiprogram.RevPiProgram( + win, self.cli, self.xmlmode, self.revpiname) self.wait_window(win) def plcstart(self): diff --git a/setup.py b/setup.py index 60d64c8..65c5ec7 100644 --- a/setup.py +++ b/setup.py @@ -82,7 +82,7 @@ elif platform == "win32": options={"build_exe": { "include_files": [ "revpipycontrol/revpipycontrol.png", - # "m4server/locale" + "revpipycontrol/locale" ] }}, executables=[exe], From 7fc879bbe1626966d0df976813a5fb6e7588ecf8 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sun, 2 Jul 2017 22:21:29 +0200 Subject: [PATCH 12/13] RevPiCheckClient Fehler z?hlen und ggf. Fenster verwerfen RevPiCheckControl baut RevPiCheckClient nach max Fehler neu auf --- doc/revpicheckclient.html | 5 +++++ revpipycontrol/revpicheckclient.py | 33 +++++++++++++++++++++++------- revpipycontrol/revpipycontrol.py | 4 +++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/doc/revpicheckclient.html b/doc/revpicheckclient.html index a93b9e8..7b5ca6f 100644 --- a/doc/revpicheckclient.html +++ b/doc/revpicheckclient.html @@ -225,6 +225,11 @@ Arbeit nur für dieses Dict()
Änderungen auf RevPi schreiben
+

+
Returns:
+
+None +

RevPiCheckClient.hideallwindows

diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index e2c27b1..9226f2e 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -33,6 +33,8 @@ class RevPiCheckClient(tkinter.Frame): self.lst_devices = [d[0] for d in self.lst_devices] self.dict_inps = pickle.loads(self.cli.ps_inps().data) self.dict_outs = pickle.loads(self.cli.ps_outs().data) + self.err_workvalues = 0 + self.max_errors = 25 self.lk = Lock() self.dict_wins = {} @@ -94,7 +96,7 @@ class RevPiCheckClient(tkinter.Frame): try: newvalue = io[5].get() # Wertebereich prüfen - if newvalue < 0 or newvalue > 255 * io[1]: + if newvalue < 0 or newvalue > 256 ** io[1] - 1: raise ValueError("too big") self.__chval(device, io) @@ -175,7 +177,7 @@ class RevPiCheckClient(tkinter.Frame): check.grid(column=1, row=rowcount) else: var = tkinter.IntVar() - txt = tkinter.Spinbox(s_frame, to=255 * io[1]) + txt = tkinter.Spinbox(s_frame, to=256 ** io[1] - 1) txt.bind( "", lambda event, tkvar=var: self.__saveoldvalue(event, tkvar) @@ -188,7 +190,7 @@ class RevPiCheckClient(tkinter.Frame): txt["command"] = \ lambda device=device, io=io: self.__chval(device, io) txt["state"] = "disabled" if iotype == "inp" else "normal" - txt["width"] = 4 + txt["width"] = 5 txt["textvariable"] = var txt.grid(column=1, row=rowcount) @@ -290,16 +292,32 @@ class RevPiCheckClient(tkinter.Frame): def _workvalues(self, io_dicts=None, writeout=False): u"""Alle Werte der Inputs und Outputs abrufen. - @param io_dicts Arbeit nur für dieses Dict() - @param writeout Änderungen auf RevPi schreiben""" + @param io_dicts Arbeit nur für dieses Dict() + @param writeout Änderungen auf RevPi schreiben + @return None + + """ # Abfragelisten vorbereiten if io_dicts is None: io_dicts = [self.dict_inps, self.dict_outs] # Werte abrufen with self.lk: - ba_values = bytearray(self.cli.ps_values().data) + try: + ba_values = bytearray(self.cli.ps_values().data) + self.err_workvalues = 0 + except: + if self.autorw.get(): + self.err_workvalues += 1 + else: + self.err_workvalues = self.max_errors + + if self.err_workvalues >= self.max_errors: + self.hideallwindows() + self.pack_forget() + + return None # Multicall zum Schreiben vorbereiten if writeout: @@ -362,11 +380,12 @@ class RevPiCheckClient(tkinter.Frame): if not self.autorw.get(): try: self.chk_auto["state"] = "normal" - self._workvalues() except: pass return None + self._workvalues() + self.master.after(200, self.tmr_workvalues) def toggleauto(self): diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index 0665a03..c0ca4c1 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -240,7 +240,9 @@ class RevPiPyControl(tkinter.Frame): ) else: # Debugfenster laden - if self.debugframe is None: + if self.debugframe is None \ + or self.debugframe.err_workvalues >= \ + self.debugframe.max_errors: self.debugframe = revpicheckclient.RevPiCheckClient( self, self.cli, self.xmlmode ) From cdaff8fe4ea42dedcc5e2e3db25a74b78b715b91 Mon Sep 17 00:00:00 2001 From: NaruX Date: Mon, 3 Jul 2017 10:40:22 +0200 Subject: [PATCH 13/13] Translation --- .../locale/de/LC_MESSAGES/revpipycontrol.po | 120 +++++++++++------- revpipycontrol/revpiplclist.py | 2 +- revpipycontrol/revpiprogram.py | 5 +- revpipycontrol/revpipycontrol.py | 8 +- 4 files changed, 84 insertions(+), 51 deletions(-) diff --git a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po index 7698dff..5b858a2 100644 --- a/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po +++ b/revpipycontrol/locale/de/LC_MESSAGES/revpipycontrol.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: RevPiPyControl 0.4.0\n" -"POT-Creation-Date: 2017-07-02 11:32+0200\n" -"PO-Revision-Date: 2017-07-02 11:33+0200\n" +"POT-Creation-Date: 2017-07-03 10:36+0200\n" +"PO-Revision-Date: 2017-07-03 10:36+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -15,58 +15,58 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SearchPath-0: .\n" -#: revpicheckclient.py:104 revpicheckclient.py:412 revpioption.py:309 +#: revpicheckclient.py:107 revpicheckclient.py:432 revpioption.py:309 #: revpiplclist.py:205 revpiprogram.py:315 revpiprogram.py:346 #: revpiprogram.py:410 revpiprogram.py:416 revpiprogram.py:422 #: revpiprogram.py:430 revpiprogram.py:436 revpiprogram.py:469 #: revpiprogram.py:553 revpiprogram.py:626 revpiprogram.py:657 #: revpiprogram.py:670 revpiprogram.py:725 revpiprogram.py:745 -#: revpiprogram.py:753 revpipycontrol.py:359 +#: revpiprogram.py:753 revpipycontrol.py:363 msgid "Error" msgstr "Fehler" -#: revpicheckclient.py:105 +#: revpicheckclient.py:108 msgid "" "Given value for Output '{}' is not valid! \n" "Reset to '{}'" msgstr "" -"Angegebener Wert bei Output '{}' ist nicht gültig! \n" +"Angegebener Wert für Output '{}' ist nicht gültig! \n" "Setze auf '{}' zurück" -#: revpicheckclient.py:204 +#: revpicheckclient.py:207 msgid "Devices of RevPi" msgstr "Devices vom RevPi" -#: revpicheckclient.py:236 +#: revpicheckclient.py:239 msgid "Control" msgstr "Kontrolle" -#: revpicheckclient.py:240 +#: revpicheckclient.py:243 msgid "Read all IOs" -msgstr "IOs aktualisieren" +msgstr "Lese alle IOs" -#: revpicheckclient.py:245 +#: revpicheckclient.py:248 msgid "Read just Inputs" -msgstr "Inputs lesen" +msgstr "Nur Inputs lesen" -#: revpicheckclient.py:252 +#: revpicheckclient.py:255 msgid "Write Outputs" msgstr "Outputs schreiben" -#: revpicheckclient.py:258 +#: revpicheckclient.py:261 msgid "Autorefresh values" -msgstr "Aktualisiere automatisch" +msgstr "Aktualisiere Werte automatisch" -#: revpicheckclient.py:266 +#: revpicheckclient.py:269 msgid "Write values to RevPi" msgstr "Schreibe Werte auf RevPi" -#: revpicheckclient.py:280 revpiprogram.py:443 revpipycontrol.py:235 -#: revpipycontrol.py:276 revpipycontrol.py:294 revpipycontrol.py:320 +#: revpicheckclient.py:283 revpiprogram.py:443 revpipycontrol.py:235 +#: revpipycontrol.py:280 revpipycontrol.py:298 revpipycontrol.py:324 msgid "Warning" msgstr "Warnung" -#: revpicheckclient.py:281 +#: revpicheckclient.py:284 msgid "" "You want to set outputs on the RevPi! Note that these are set " "IMMEDIATELY!!! \n" @@ -78,9 +78,9 @@ msgstr "" "Wenn auf dem RevPi ein anderes Programm zur Steuerung läuft, könnte dies " "gestört werden und die Ausgänge wieder zurücksetzen." -#: revpicheckclient.py:409 +#: revpicheckclient.py:429 msgid "Error set value of device '{}' Output '{}': {} \n" -msgstr "Fehler beim Setzen auf Device '{}' bei Output '{}': {}\n" +msgstr "Fehler beim Setzen der Werte auf Device '{}' bei Output '{}': {}\n" #: revpiinfo.py:38 msgid "RevPi Python PLC info" @@ -96,7 +96,7 @@ msgstr "Version: {}" #: revpiinfo.py:78 msgid "RevPiPyLoad version on RevPi:" -msgstr "RevPiPyLoad Version am RevPi:" +msgstr "RevPiPyLoad Version auf RevPi:" #: revpiinfo.py:83 msgid "not conn." @@ -147,7 +147,7 @@ msgstr "Python PLC Programm - Logdatei" #: revpilogfile.py:157 msgid "Can not access log file on the RevPi" -msgstr "RevPi kann auf Logdatei nicht zugreifen" +msgstr "Auf die Logdatei des RevPi kann nicht zugegriffen werden" #: revpioption.py:66 revpioption.py:272 revpioption.py:319 revpiplclist.py:63 #: revpiplclist.py:181 revpiprogram.py:379 revpiprogram.py:454 @@ -183,8 +183,8 @@ msgid "" "Set process image to NULL if program\n" "terminates successfully" msgstr "" -"\"Prozessabbild auf NULL setzen, wenn Programm\n" -"\"erfolgreich beendet wird\"" +"Prozessabbild auf NULL setzen, wenn Programm\n" +"erfolgreich beendet wird" #: revpioption.py:118 msgid "" @@ -313,7 +313,7 @@ msgid "Remove" msgstr "Entfernen" #: revpiplclist.py:182 -msgid "Do you really want to delete the selected connection '{}'" +msgid "Do you really want to delete the selected connection '{}'?" msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" #: revpiplclist.py:198 @@ -381,7 +381,7 @@ msgstr "PLC Programm hochladen als:" #: revpiprogram.py:153 msgid "clean upload folder before upload" -msgstr "vorher Inhalt im Uploadverzeichnis löschen" +msgstr "Uploadverzeichnis vor dem Upload leeren" #: revpiprogram.py:160 msgid "includes piCtory configuration" @@ -404,7 +404,7 @@ msgid "Upload piCtory configuration" msgstr "piCtory Konfiguration hochladen" #: revpiprogram.py:194 -msgid "piControl0 prozess image" +msgid "piControl0 process image" msgstr "piControl0 Prozessabbild" #: revpiprogram.py:197 @@ -462,7 +462,7 @@ msgstr "Image Dateien" #: revpiprogram.py:367 msgid "Open piCtory file..." -msgstr "piCtory Datei öffnen" +msgstr "piCtory Datei öffnen..." #: revpiprogram.py:380 msgid "" @@ -491,7 +491,7 @@ msgstr "Kann die übertragene Datei nicht verarbeiten." #: revpiprogram.py:417 msgid "Can not find main elements in piCtory file." -msgstr "Kann Hauptelemente in datei nicht finden." +msgstr "Kann Hauptelemente in piCtory datei nicht finden." #: revpiprogram.py:423 msgid "" @@ -499,11 +499,11 @@ msgid "" "be from a newer piCtory version!" msgstr "" "Enthaltene Geräte konnten auf dem Revolution Pi nicht gefunden werden. " -"Möglicherweise stammt die Konfiguration von einer neueren piCtory Version." +"Möglicherweise stammt die Konfiguration von einer neueren piCtory Version!" #: revpiprogram.py:431 msgid "Could not load RAP catalog on Revolution Pi." -msgstr "Konnte Katalog auf nicht laden." +msgstr "Konnte RAP Katalog auf dem Revolution Pi nicht laden." #: revpiprogram.py:437 msgid "The piCtory configuration could not be written on the Revolution Pi." @@ -525,11 +525,11 @@ msgid "" "The process image and the piBridge are interrupted !!!" msgstr "" "Soll piControlReset wirklich durchgeführt werden? \n" -"Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" +"Das Prozessabbild und die piBridge werden dann unterbrochen!!!" #: revpiprogram.py:464 -msgid "piControlReset executed successfully" -msgstr "piControl Reset war erfolgreich" +msgid "piControl reset executed successfully" +msgstr "piControl reset wurde erfolgreich ausgeführt" #: revpiprogram.py:470 msgid "piControl reset could not be executed successfully" @@ -537,7 +537,7 @@ msgstr "piControl Reset konnte nicht erfolgreich durchgeführt werden" #: revpiprogram.py:484 msgid "Directory to save" -msgstr "Verzeichnis zum Ablegen" +msgstr "Verzeichnis zum speichern" #: revpiprogram.py:595 msgid "Folder to upload" @@ -549,7 +549,7 @@ msgstr "Zip Archiv hochladen..." #: revpiprogram.py:627 msgid "The specified file is not a ZIP archive." -msgstr "Die angegebene Datei ist kein ZIP Archiv" +msgstr "Die angegebene Datei ist kein ZIP Archiv." #: revpiprogram.py:636 msgid "Upload TarGz archiv..." @@ -643,12 +643,14 @@ msgstr "Verbinden" #: revpipycontrol.py:236 msgid "" "The watch mode ist not supported in version {} of RevPiPyLoad on your RevPi! " -"You need at least version 0.4.0." +"You need at least version 0.4.0. Or the python3-revpimodio module is not " +"installton your RevPi at least version 0.15.0." msgstr "" "Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " -"unterstützt! Sie benötigen mindestens Version 0.4.0." +"unterstützt! Sie benötigen mindestens Version 0.4.0. Oder das python3-" +"revpimodio Modul ist auf dem RevPi nicht in min. Version 0.15.0 installiert." -#: revpipycontrol.py:277 +#: revpipycontrol.py:281 msgid "" "This version of Logviewer ist not supported in version {} of RevPiPyLoad on " "your RevPi! You need at least version 0.4.1." @@ -656,18 +658,48 @@ msgstr "" "Diese Version vom Logbetrachter wird in der RevPiPyLoad Version {} auf Ihrem " "RevPi nicht unterstützt! Sie benötigen mindestens Version 0.4.1." -#: revpipycontrol.py:295 revpipycontrol.py:321 +#: revpipycontrol.py:299 revpipycontrol.py:325 msgid "" -"XML-RPC access mode in the RevPiPyLoad configuration is to small to access " -"this dialog" +"XML-RPC access mode in the RevPiPyLoad configuration is too small to access " +"this dialog!" msgstr "" "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " "diesen Dialog zu verwenden!" -#: revpipycontrol.py:360 +#: revpipycontrol.py:364 msgid "Can not reach server!" msgstr "Server ist nicht erreichbar!" +#~ msgid "" +#~ "The watch mode ist not supported in version {} of RevPiPyLoad on your " +#~ "RevPi! You need at least version 0.4.0." +#~ msgstr "" +#~ "Der Watch-Modus wird von der RevPiPyLoad Version {} auf dem RevPi nicht " +#~ "unterstützt! Sie benötigen mindestens Version 0.4.0." + +#~ msgid "" +#~ "XML-RPC access mode in the RevPiPyLoad configuration is too small to " +#~ "access this dialog" +#~ msgstr "" +#~ "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " +#~ "diesen Dialog zu verwenden!" + +#~ msgid "Do you really want to delete the selected connection '{}'" +#~ msgstr "Wollen Sie die ausgewählte Verbindung '{}' wirklich löschen?" + +#~ msgid "piControl0 prozess image" +#~ msgstr "piControl0 Prozessabbild" + +#~ msgid "piControlReset executed successfully" +#~ msgstr "piControl Reset war erfolgreich" + +#~ msgid "" +#~ "XML-RPC access mode in the RevPiPyLoad configuration is to small to " +#~ "access this dialog" +#~ msgstr "" +#~ "Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch genug eingestellt, um " +#~ "diesen Dialog zu verwenden!" + #~ msgid "Quit" #~ msgstr "Beenden" diff --git a/revpipycontrol/revpiplclist.py b/revpipycontrol/revpiplclist.py index 7721aab..8c59b6a 100644 --- a/revpipycontrol/revpiplclist.py +++ b/revpipycontrol/revpiplclist.py @@ -179,7 +179,7 @@ class RevPiPlcList(tkinter.Frame): item = self.list_conn.get(item_index[0]) ask = tkmsg.askyesno( _("Question"), - _("Do you really want to delete the selected connection '{}'" + _("Do you really want to delete the selected connection '{}'?" "").format(item), parent=self.master ) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index 8666705..4eea90e 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -191,7 +191,7 @@ class RevPiProgram(tkinter.Frame): # Gruppe ProcImg proc = tkinter.LabelFrame(self) proc.columnconfigure(0, weight=1) - proc["text"] = _("piControl0 prozess image") + proc["text"] = _("piControl0 process image") proc.grid(columnspan=2, pady=2, sticky="we") lbl = tkinter.Label(proc) lbl["text"] = _("Download process image dump") @@ -383,7 +383,6 @@ class RevPiProgram(tkinter.Frame): ) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) - print(ec) if ec == 0: if ask: @@ -461,7 +460,7 @@ class RevPiProgram(tkinter.Frame): if ec == 0: tkmsg.showinfo( _("Success"), - _("piControlReset executed successfully"), + _("piControl reset executed successfully"), parent=self.master ) else: diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index c0ca4c1..0dd4773 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -235,7 +235,9 @@ class RevPiPyControl(tkinter.Frame): _("Warning"), _("The watch mode ist not supported in version {} " "of RevPiPyLoad on your RevPi! You need at least version " - "0.4.0.").format(self.cli.version()), + "0.4.0. Or the python3-revpimodio module is not installt" + "on your RevPi at least version 0.15.0." + "").format(self.cli.version()), parent=self.master ) else: @@ -295,7 +297,7 @@ class RevPiPyControl(tkinter.Frame): tkmsg.showwarning( _("Warning"), _("XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog"), + "configuration is too small to access this dialog!"), parent=self.master ) else: @@ -321,7 +323,7 @@ class RevPiPyControl(tkinter.Frame): tkmsg.showwarning( _("Warning"), _("XML-RPC access mode in the RevPiPyLoad " - "configuration is to small to access this dialog"), + "configuration is too small to access this dialog!"), parent=self.master ) else: