From b10a9823f2218952ee61db5d1bffe059591446af Mon Sep 17 00:00:00 2001 From: NaruX Date: Wed, 8 Mar 2017 17:53:32 +0100 Subject: [PATCH] Fenstermen? eingebaut RevPiOption eingebaut --- .hgignore | 2 + revpipycontrol.e4p | 5 +- revpipycontrol/revpioption.py | 161 +++++++++++++++++++++++++++++++ revpipycontrol/revpipycontrol.py | 98 +++++++++++-------- 4 files changed, 222 insertions(+), 44 deletions(-) create mode 100644 revpipycontrol/revpioption.py diff --git a/.hgignore b/.hgignore index e69de29..2c9154d 100644 --- a/.hgignore +++ b/.hgignore @@ -0,0 +1,2 @@ +syntax: glob +*.pyc diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index ae308b0..7e7e314 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -9,7 +9,7 @@ Python3 Console - 0.2.0 + 0.2.1 Sven Sager akira@narux.de @@ -20,6 +20,7 @@ setup.py revpipycontrol/revpiplclist.py revpipycontrol/revpilogfile.py + revpipycontrol/revpioption.py diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py new file mode 100644 index 0000000..ff06213 --- /dev/null +++ b/revpipycontrol/revpioption.py @@ -0,0 +1,161 @@ +# +# RevPiPyControl +# +# Webpage: https://revpimodio.org/revpipyplc/ +# (c) Sven Sager, License: LGPLv3 +# +# -*- coding: utf-8 -*- +import tkinter +import tkinter.messagebox as tkmsg + + +class RevPiOption(tkinter.Frame): + + def __init__(self, master, xmlcli): + super().__init__(master) + self.pack() + + self.xmlcli = xmlcli + + # Fenster bauen + self._createwidgets() + self._loadappdata() + + def _createwidgets(self): + self.master.wm_title("RevPi Python PLC Connections") + self.master.wm_resizable(width=False, height=False) + + cpadw = {"padx": 4, "pady": 2, "sticky": "w"} + cpadwe = {"padx": 4, "pady": 2, "sticky": "we"} + + # Gruppe Start/Stop + stst = tkinter.LabelFrame(self) + stst["text"] = "Start / Stopp Verhalten" + stst.grid(columnspan=2, pady=2, sticky="we") + + self.var_start = tkinter.BooleanVar(stst) + self.var_reload = tkinter.BooleanVar(stst) + self.var_zexit = tkinter.BooleanVar(stst) + self.var_zerr = tkinter.BooleanVar(stst) + + ckb_start = tkinter.Checkbutton(stst) + ckb_start["text"] = "Programm automatisch starten" + ckb_start["variable"] = self.var_start + ckb_start.grid(**cpadw) + ckb_reload = tkinter.Checkbutton(stst) + ckb_reload["text"] = "Programm nach Absturz neustarten" + ckb_reload["variable"] = self.var_reload + ckb_reload.grid(**cpadw) + ckb_zexit = tkinter.Checkbutton(stst, justify="left") + ckb_zexit["text"] = "Prozessabbild auf NULL setzen, wenn " + "Programm\nerfolgreich beendet wird" + ckb_zexit["variable"] = self.var_zexit + ckb_zexit.grid(**cpadw) + ckb_zerr = tkinter.Checkbutton(stst, justify="left") + ckb_zerr["text"] = "Prozessabbild auf NULL setzen, wenn " + "Programm\ndurch Absturz beendet wird" + ckb_zerr["variable"] = self.var_zerr + ckb_zerr.grid(**cpadw) + + # Gruppe Programm + prog = tkinter.LabelFrame(self) + prog["text"] = "Programm" + prog.grid(columnspan=2, pady=2, sticky="we") + + self.var_startpy = tkinter.StringVar(prog) + self.var_slave = tkinter.BooleanVar(prog) + + lbl = tkinter.Label(prog) + lbl["text"] = "Python PLC Programname" + lbl.grid(**cpadw) + txt_startpy = tkinter.Entry(prog) + txt_startpy["textvariable"] = self.var_startpy + txt_startpy.grid(**cpadwe) + ckb_slave = tkinter.Checkbutton(prog, justify="left") + ckb_slave["text"] = "RevPi als PLC-Slave verwenden" + ckb_slave["state"] = "disabled" + ckb_slave["variable"] = self.var_slave + ckb_slave.grid(**cpadw) + + # Gruppe XMLRPC + xmlrpc = tkinter.LabelFrame(self) + xmlrpc["text"] = "XML-RPC Server" + xmlrpc.grid(columnspan=2, pady=2, sticky="we") + + self.var_xmlon = tkinter.BooleanVar(xmlrpc) + self.var_xmlport = tkinter.StringVar(xmlrpc) + self.var_xmlport.set("55123") + + ckb_xmlon = tkinter.Checkbutton(xmlrpc) + ckb_xmlon["command"] = self.askxmlon + ckb_xmlon["text"] = "XML-RPC Server aktiv auf RevPi" + ckb_xmlon["variable"] = self.var_xmlon + ckb_xmlon.grid(**cpadw) + lbl = tkinter.Label(xmlrpc) + lbl["text"] = "XML-RPC Serverport" + lbl.grid(**cpadw) + spb_xmlport = tkinter.Spinbox(xmlrpc) + spb_xmlport["to"] = 65535 + spb_xmlport["from"] = 1024 + spb_xmlport["textvariable"] = self.var_xmlport + spb_xmlport.grid(**cpadwe) + + # Buttons + btn_save = tkinter.Button(self) + btn_save["command"] = self._setappdata + btn_save["text"] = "Speichern" + 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.grid(column=1, row=3) + + def _loadappdata(self): + dc = self.xmlcli.get_config() + + self.var_start.set(dc["autostart"]) + self.var_reload.set(dc["autoreload"]) + self.var_zexit.set(dc["zeroonexit"]) + self.var_zerr.set(dc["zeroonerror"]) + + self.var_startpy.set(dc["plcprogram"]) + self.var_slave.set(dc["plcslave"]) + + self.var_xmlon.set(dc["xmlrpc"]) + self.var_xmlport.set(dc["xmlrpcport"]) + + def _setappdata(self): + 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()) + + dc["plcprogram"] = self.var_startpy.get() + dc["plcslave"] = int(self.var_slave.get()) + + dc["xmlrpc"] = int(self.var_xmlon.get()) + dc["xmlrpcport"] = self.var_xmlport.get() + + ask = tkmsg.askyesnocancel( + "Frage", "Die Einstellungen werden jetzt auf den Revolution Pi " + "gespeichert.\nSollen die neuen Einstellungen sofort in Kraft " + "treten? Dies bedeutet einen Neustart des Dienstes und des ggf. " + "laufenden PLC-Programms!", parent=self.master + ) + if ask is not None: + self.xmlcli.set_config(dc, ask) + tkmsg.showinfo( + "Information", "Einstellungen gespeichert.", 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 mit diesem Programm NICHT mehr auf den " + "Revolution Pi zugreifen.", parent=self.master + ) + if not ask: + self.var_xmlon.set(True) diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index cab28c4..f34c6b2 100644 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # # RevPiPyControl -# Version: 0.2.0 +# Version: 0.2.1 # # Webpage: https://revpimodio.org/revpipyplc/ # (c) Sven Sager, License: LGPLv3 @@ -9,10 +9,12 @@ # -*- coding: utf-8 -*- import revpicheckclient import revpilogfile +import revpioption import revpiplclist import socket import tkinter import tkinter.messagebox as tkmsg +from functools import partial from xmlrpc.client import ServerProxy socket.setdefaulttimeout(3) @@ -47,27 +49,22 @@ class RevPiPyControl(tkinter.Frame): self.master.wm_resizable(width=False, height=False) # Menü ganz oben - self.var_opt = tkinter.StringVar(self) - self.lst_opt = [ - "Connections...", - "------------------", - "PLC log...", - "PLC monitor...", - "PLC options...", - "PLC program...", - "------------------", - "Exit", - ] - self.opt_menu = tkinter.OptionMenu( - self, self.var_opt, *self.lst_opt, command=self._opt_do) - self.opt_menu.pack(fill="x") + self.mbar = tkinter.Menu(self.master) + self.master.config(menu=self.mbar) + + menu1 = tkinter.Menu(self.mbar, tearoff=False) + 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) + + self._fillmbar() + self._fillconnbar() - # Verbindungen self.var_conn = tkinter.StringVar(self) - self.lst_conn = sorted(self.dict_conn.keys(), key=lambda x: x.lower()) - self.opt_conn = tkinter.OptionMenu( - self, self.var_conn, *self.lst_conn, command=self._opt_conn) - self.opt_conn.pack(fill="x") + self.txt_connect = tkinter.Entry( + self, textvariable=self.var_conn, state="readonly", width=30) + self.txt_connect.pack(fill="x") self.btn_plcstart = tkinter.Button(self) self.btn_plcstart["text"] = "PLC Start" @@ -93,9 +90,28 @@ class RevPiPyControl(tkinter.Frame): self.txt_status = tkinter.Entry(self) self.txt_status["state"] = "readonly" self.txt_status["textvariable"] = self.var_status - self.txt_status.pack() + 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) + + def _fillconnbar(self): + 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 _opt_conn(self, text): + print(text) sp = ServerProxy( "http://{}:{}".format( self.dict_conn[text][0], int(self.dict_conn[text][1]) @@ -108,27 +124,10 @@ class RevPiPyControl(tkinter.Frame): self.servererror() else: self.cli = sp - - def _opt_do(self, text): - optselect = self.lst_opt.index(text) - if optselect == 0: - # Verbindungen - self.plclist() - elif optselect == 2: - # Logs - self.plclogs() - elif optselect == 3: - pass - # self.plcmonitor() - elif optselect == 4: - # Optionen - pass - elif optselect == 5: - # Programm updown - pass - elif optselect == 7: - self.master.destroy() - self.var_opt.set("") + self.var_conn.set("{} - {}:{}".format( + text, self.dict_conn[text][0], int(self.dict_conn[text][1]) + )) + self.mbar.entryconfig("PLC", state="normal") def plclist(self): win = tkinter.Toplevel(self) @@ -136,15 +135,29 @@ class RevPiPyControl(tkinter.Frame): win.focus_set() win.grab_set() self.wait_window(win) + self.dict_conn = revpiplclist.get_connections() + self._fillconnbar() def plclogs(self): + # TODO: nicht doppelt starten win = tkinter.Toplevel(self) self.tklogs = revpilogfile.RevPiLogfile(win, self.cli) def plcmonitor(self): + # TODO: Monitorfenster #self.tkmonitor = revpicheckclient.RevPiCheckClient(self.master, self.cli) pass + def plcoptions(self): + # TODO: Optionsfenster + win = tkinter.Toplevel(self) + revpioption.RevPiOption(win, self.cli) + self.wait_window(win) + + def plcprogram(self): + # TODO: Programfenster + pass + def plcstart(self): self.cli.plcstart() @@ -158,6 +171,7 @@ class RevPiPyControl(tkinter.Frame): def servererror(self): self.cli = None self._btnstate() + self.mbar.entryconfig("PLC", state="disabled") self.var_conn.set("") tkmsg.showerror("Fehler", "Server ist nicht erreichbar!")