From 145468d35bf497b71fc37895ee6b39a61a0b5217 Mon Sep 17 00:00:00 2001
From: NaruX
Ruft alle IO Werte von RevPi ab und aktualisiert Fenster.
-
+Timer für zyklische Abfrage.
+
Init RevPiOption-Class.
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()
+RevPiCheckClient.tmr_workvalues
+tmr_workvalues()
+
+
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.
+
+
@@ -79,7 +82,7 @@ Static Methods
xmlmod_tail
Passt XML-Optionszugriff an.
RevPiOption (Constructor)
-RevPiOption(master, xmlcli, xmlmode)
+RevPiOption(master, xmlcli)
@@ -118,10 +121,15 @@ Erstellt Widgets.
Läd aktuelle Einstellungen vom RevPi. -
+Fragt Nuter, ob wirklicht abgeschaltet werden soll. -
++Passt XML-Optionszugriff an. +
+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."""