mirror of
https://github.com/naruxde/revpipycontrol.git
synced 2025-11-08 15:43:52 +01:00
"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
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
import pickle
|
import pickle
|
||||||
import tkinter
|
import tkinter
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from xmlrpc.client import ServerProxy
|
from xmlrpc.client import ServerProxy, MultiCall
|
||||||
|
|
||||||
|
|
||||||
class RevPiCheckClient(tkinter.Frame):
|
class RevPiCheckClient(tkinter.Frame):
|
||||||
@@ -18,17 +18,20 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
def __init__(self, master, xmlcli, xmlmode=0):
|
def __init__(self, master, xmlcli, xmlmode=0):
|
||||||
"""Instantiiert MyApp-Klasse."""
|
"""Instantiiert MyApp-Klasse."""
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.pack(fill="both", expand=True)
|
|
||||||
|
|
||||||
# XML-Daten abrufen
|
# XML-Daten abrufen
|
||||||
self.xmlmode = xmlmode
|
self.xmlmode = xmlmode
|
||||||
self.cli = xmlcli
|
self.cli = xmlcli
|
||||||
|
|
||||||
|
# FIXME: Fehlerabfang
|
||||||
self.cli.psstart()
|
self.cli.psstart()
|
||||||
|
|
||||||
self.lst_devices = self.cli.ps_devices()
|
self.lst_devices = self.cli.ps_devices()
|
||||||
self.dict_inps = pickle.loads(self.cli.ps_inps().data)
|
self.dict_inps = pickle.loads(self.cli.ps_inps().data)
|
||||||
self.dict_outs = pickle.loads(self.cli.ps_outs().data)
|
self.dict_outs = pickle.loads(self.cli.ps_outs().data)
|
||||||
|
|
||||||
self.lk = Lock()
|
self.lk = Lock()
|
||||||
|
self.lst_wins = []
|
||||||
|
|
||||||
self.autorw = tkinter.BooleanVar()
|
self.autorw = tkinter.BooleanVar()
|
||||||
self.dowrite = tkinter.BooleanVar()
|
self.dowrite = tkinter.BooleanVar()
|
||||||
@@ -37,10 +40,25 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
self._createwidgets()
|
self._createwidgets()
|
||||||
|
|
||||||
# Aktuelle Werte einlesen
|
# Aktuelle Werte einlesen
|
||||||
self.readvalues()
|
self.refreshvalues()
|
||||||
|
|
||||||
def onfrmconf(self, canvas):
|
def __chval(self, device, io):
|
||||||
canvas.configure(scrollregion=canvas.bbox("all"))
|
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):
|
def _createiogroup(self, device, frame, iotype):
|
||||||
"""Erstellt IO-Gruppen."""
|
"""Erstellt IO-Gruppen."""
|
||||||
@@ -55,7 +73,7 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
|
|
||||||
canvas.create_window((4, 4), window=s_frame, anchor="nw")
|
canvas.create_window((4, 4), window=s_frame, anchor="nw")
|
||||||
s_frame.bind(
|
s_frame.bind(
|
||||||
"<Configure>", lambda event, canvas=canvas: self.onfrmconf(canvas)
|
"<Configure>", lambda event, canvas=canvas: self._onfrmconf(canvas)
|
||||||
)
|
)
|
||||||
|
|
||||||
rowcount = 0
|
rowcount = 0
|
||||||
@@ -76,7 +94,7 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
var = tkinter.BooleanVar()
|
var = tkinter.BooleanVar()
|
||||||
check = tkinter.Checkbutton(s_frame)
|
check = tkinter.Checkbutton(s_frame)
|
||||||
check["command"] = \
|
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["state"] = "disabled" if iotype == "inp" else "normal"
|
||||||
check["text"] = ""
|
check["text"] = ""
|
||||||
check["variable"] = var
|
check["variable"] = var
|
||||||
@@ -86,7 +104,7 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
# FIXME: Mehrere Bytes möglich
|
# FIXME: Mehrere Bytes möglich
|
||||||
txt = tkinter.Spinbox(s_frame, to=255 * io[1])
|
txt = tkinter.Spinbox(s_frame, to=255 * io[1])
|
||||||
txt["command"] = \
|
txt["command"] = \
|
||||||
lambda device=device, io=io: self.chval(device, io)
|
lambda device=device, io=io: self.__chval(device, io)
|
||||||
txt["state"] = "disabled" if iotype == "inp" else "normal"
|
txt["state"] = "disabled" if iotype == "inp" else "normal"
|
||||||
txt["width"] = 4
|
txt["width"] = 4
|
||||||
txt["textvariable"] = var
|
txt["textvariable"] = var
|
||||||
@@ -97,19 +115,8 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
|
|
||||||
rowcount += 1
|
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):
|
def _createwidgets(self):
|
||||||
"""Erstellt den Fensterinhalt."""
|
"""Erstellt den Fensterinhalt."""
|
||||||
# Hauptfenster
|
|
||||||
self.master.wm_title("RevPi Onlineview")
|
|
||||||
|
|
||||||
devgrp = tkinter.LabelFrame(self)
|
devgrp = tkinter.LabelFrame(self)
|
||||||
devgrp["text"] = "Devices of RevPi"
|
devgrp["text"] = "Devices of RevPi"
|
||||||
@@ -123,6 +130,7 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
lambda win=win: self.__hidewin(win)
|
lambda win=win: self.__hidewin(win)
|
||||||
)
|
)
|
||||||
win.withdraw()
|
win.withdraw()
|
||||||
|
self.lst_wins.append(win)
|
||||||
|
|
||||||
# Devicegruppe erstellen
|
# Devicegruppe erstellen
|
||||||
group = tkinter.LabelFrame(win)
|
group = tkinter.LabelFrame(win)
|
||||||
@@ -145,44 +153,56 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
cntgrp["text"] = "Control"
|
cntgrp["text"] = "Control"
|
||||||
cntgrp.pack(fill="y", side="right")
|
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 = tkinter.Button(cntgrp)
|
||||||
self.btn_read["text"] = "LESEN"
|
self.btn_read["text"] = "Inputs einlesen"
|
||||||
self.btn_read["command"] = self.readvalues
|
self.btn_read["command"] = self.readvalues
|
||||||
self.btn_read.pack(fill="x")
|
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 = tkinter.Checkbutton(cntgrp)
|
||||||
check["command"] = self.toggleauto
|
check["command"] = self.toggleauto
|
||||||
check["text"] = "autorefresh processimage"
|
check["text"] = "Autorefresh values"
|
||||||
check["variable"] = self.autorw
|
check["variable"] = self.autorw
|
||||||
check.pack(anchor="w")
|
check.pack(anchor="w")
|
||||||
|
|
||||||
check = tkinter.Checkbutton(cntgrp)
|
check = tkinter.Checkbutton(cntgrp)
|
||||||
check["state"] = "disabled" if self.xmlmode < 3 else "normal"
|
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["variable"] = self.dowrite
|
||||||
check.pack(anchor="w")
|
check.pack(anchor="w")
|
||||||
|
|
||||||
def chval(self, device, io):
|
def _onfrmconf(self, canvas):
|
||||||
if self.dowrite.get():
|
canvas.configure(scrollregion=canvas.bbox("all"))
|
||||||
with self.lk:
|
|
||||||
self.cli.ps_setvalue(device, io[0], io[5].get())
|
|
||||||
|
|
||||||
# Alles neu einlesen wenn nicht AutoRW aktiv ist
|
def _workvalues(self, io_dicts=None, writeout=False):
|
||||||
if not self.autorw.get():
|
|
||||||
self.readvalues()
|
|
||||||
|
|
||||||
def _readvalues(self):
|
|
||||||
"""Alle Werte der Inputs und Outputs abrufen."""
|
"""Alle Werte der Inputs und Outputs abrufen."""
|
||||||
|
|
||||||
|
# Abfragelisten vorbereiten
|
||||||
|
if io_dicts is None:
|
||||||
|
io_dicts = [self.dict_inps, self.dict_outs]
|
||||||
|
|
||||||
# Werte abrufen
|
# Werte abrufen
|
||||||
with self.lk:
|
with self.lk:
|
||||||
ba_values = bytearray(self.cli.ps_values().data)
|
ba_values = bytearray(self.cli.ps_values().data)
|
||||||
|
|
||||||
|
# Multicall zum Schreiben vorbereiten
|
||||||
|
if writeout:
|
||||||
|
xmlmc = MultiCall(self.cli)
|
||||||
|
|
||||||
for dev in self.lst_devices:
|
for dev in self.lst_devices:
|
||||||
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)]
|
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)]
|
||||||
|
|
||||||
# IO Typ verarbeiten
|
# IO Typ verarbeiten
|
||||||
for iotype in [self.dict_inps, self.dict_outs]:
|
for iotype in io_dicts:
|
||||||
# ios verarbeiten
|
# ios verarbeiten
|
||||||
for io in iotype[dev[0]]:
|
for io in iotype[dev[0]]:
|
||||||
|
|
||||||
@@ -192,22 +212,50 @@ class RevPiCheckClient(tkinter.Frame):
|
|||||||
)
|
)
|
||||||
if io[4] >= 0:
|
if io[4] >= 0:
|
||||||
# Bit-IO
|
# 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:
|
else:
|
||||||
# Byte-IO
|
# 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():
|
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):
|
def readvalues(self):
|
||||||
if not self.autorw.get():
|
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):
|
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():
|
if self.autorw.get():
|
||||||
self._readvalues()
|
self._workvalues()
|
||||||
|
|
||||||
|
def writevalues(self):
|
||||||
|
if not self.autorw.get():
|
||||||
|
self._workvalues([self.dict_outs], True)
|
||||||
|
|
||||||
|
|
||||||
# Testdrive
|
# Testdrive
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ savefile = os.path.join(homedir, ".revpipyplc", "programpath.dat")
|
|||||||
class RevPiProgram(tkinter.Frame):
|
class RevPiProgram(tkinter.Frame):
|
||||||
|
|
||||||
def __init__(self, master, xmlcli, xmlmode, revpi):
|
def __init__(self, master, xmlcli, xmlmode, revpi):
|
||||||
|
u"""Init RevPiProgram-Class."""
|
||||||
if xmlmode < 2:
|
if xmlmode < 2:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
def _savedefaults(self):
|
def _savedefaults(self):
|
||||||
"""Schreibt fuer den Pi die letzen Pfade."""
|
u"""Schreibt fuer den Pi die letzen Pfade."""
|
||||||
try:
|
try:
|
||||||
makedirs(os.path.dirname(savefile), exist_ok=True)
|
makedirs(os.path.dirname(savefile), exist_ok=True)
|
||||||
dict_all = self._loaddefault(full=True)
|
dict_all = self._loaddefault(full=True)
|
||||||
@@ -236,7 +237,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def create_filelist(self, rootdir):
|
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
|
@param rootdir: Verzeichnis fuer das eine Liste erstellt werden soll
|
||||||
@returns: Dateiliste"""
|
@returns: Dateiliste"""
|
||||||
filelist = []
|
filelist = []
|
||||||
@@ -249,7 +250,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
"""Gibt das rootdir von einem entpackten Verzeichnis zurueck.
|
"""Gibt das rootdir von einem entpackten Verzeichnis zurueck.
|
||||||
|
|
||||||
Dabei wird geprueft, ob es sich um einen einzelnen Ordner handelt
|
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
|
@param rootdir: Verzeichnis fuer Pruefung
|
||||||
@returns: Abgeaendertes rootdir
|
@returns: Abgeaendertes rootdir
|
||||||
|
|
||||||
@@ -270,6 +271,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
return (rootdir, None)
|
return (rootdir, None)
|
||||||
|
|
||||||
def getpictoryrsc(self):
|
def getpictoryrsc(self):
|
||||||
|
u"""Läd die piCtory Konfiguration herunter."""
|
||||||
fh = tkfd.asksaveasfile(
|
fh = tkfd.asksaveasfile(
|
||||||
mode="wb", parent=self.master,
|
mode="wb", parent=self.master,
|
||||||
confirmoverwrite=True,
|
confirmoverwrite=True,
|
||||||
@@ -300,6 +302,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
def getprocimg(self):
|
def getprocimg(self):
|
||||||
|
u"""Läd das aktuelle Prozessabbild herunter."""
|
||||||
fh = tkfd.asksaveasfile(
|
fh = tkfd.asksaveasfile(
|
||||||
mode="wb", parent=self.master,
|
mode="wb", parent=self.master,
|
||||||
confirmoverwrite=True,
|
confirmoverwrite=True,
|
||||||
@@ -330,6 +333,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
def setpictoryrsc(self, filename=None):
|
def setpictoryrsc(self, filename=None):
|
||||||
|
u"""Überträgt die angegebene piCtory-Konfiguration."""
|
||||||
if filename is None:
|
if filename is None:
|
||||||
fh = tkfd.askopenfile(
|
fh = tkfd.askopenfile(
|
||||||
mode="rb", parent=self.master,
|
mode="rb", parent=self.master,
|
||||||
@@ -381,6 +385,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
def picontrolreset(self):
|
def picontrolreset(self):
|
||||||
|
u"""Fürt ein Reset der piBridge durch."""
|
||||||
ask = tkmsg.askyesno(
|
ask = tkmsg.askyesno(
|
||||||
parent=self.master, title="Frage...",
|
parent=self.master, title="Frage...",
|
||||||
message="Soll piControlReset wirklich durchgeführt werden? \n"
|
message="Soll piControlReset wirklich durchgeführt werden? \n"
|
||||||
@@ -401,6 +406,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def plcdownload(self):
|
def plcdownload(self):
|
||||||
|
u"""Läd das aktuelle Projekt herunter."""
|
||||||
tdown = self.lst_typedown.index(self.var_typedown.get())
|
tdown = self.lst_typedown.index(self.var_typedown.get())
|
||||||
fh = None
|
fh = None
|
||||||
dirselect = ""
|
dirselect = ""
|
||||||
@@ -491,6 +497,7 @@ class RevPiProgram(tkinter.Frame):
|
|||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
def plcupload(self):
|
def plcupload(self):
|
||||||
|
u"""Lädt das angegebene Projekt auf den RevPi."""
|
||||||
tup = self.lst_typeup.index(self.var_typeup.get())
|
tup = self.lst_typeup.index(self.var_typeup.get())
|
||||||
dirselect = ""
|
dirselect = ""
|
||||||
dirtmp = None
|
dirtmp = None
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ def addroot(filename):
|
|||||||
class RevPiPyControl(tkinter.Frame):
|
class RevPiPyControl(tkinter.Frame):
|
||||||
|
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
|
u"""Init RevPiPyControl-Class.
|
||||||
|
@param master: tkinter master"""
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.pack(fill="both", expand=True)
|
self.pack(fill="both", expand=True)
|
||||||
|
|
||||||
@@ -48,8 +50,12 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self.dict_conn = revpiplclist.get_connections()
|
self.dict_conn = revpiplclist.get_connections()
|
||||||
self.errcount = 0
|
self.errcount = 0
|
||||||
self.revpiname = None
|
self.revpiname = None
|
||||||
|
self.xmlfuncs = []
|
||||||
self.xmlmode = 0
|
self.xmlmode = 0
|
||||||
|
|
||||||
|
# Debugger vorbereiten
|
||||||
|
self.debugframe = None
|
||||||
|
|
||||||
# Globale Fenster
|
# Globale Fenster
|
||||||
self.tkcheckclient = None
|
self.tkcheckclient = None
|
||||||
self.tklogs = None
|
self.tklogs = None
|
||||||
@@ -63,14 +69,30 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self.tmr_plcrunning()
|
self.tmr_plcrunning()
|
||||||
|
|
||||||
def _btnstate(self):
|
def _btnstate(self):
|
||||||
|
u"""Setzt den state der Buttons."""
|
||||||
stateval = "disabled" if self.cli is None else "normal"
|
stateval = "disabled" if self.cli is None else "normal"
|
||||||
self.btn_plclogs["state"] = stateval
|
self.btn_plclogs["state"] = stateval
|
||||||
self.btn_plcstart["state"] = stateval
|
self.btn_plcstart["state"] = stateval
|
||||||
self.btn_plcstop["state"] = stateval
|
self.btn_plcstop["state"] = stateval
|
||||||
self.btn_plcrestart["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):
|
def _createwidgets(self):
|
||||||
"""Erstellt den Fensterinhalt."""
|
u"""Erstellt den Fensterinhalt."""
|
||||||
# Hauptfenster
|
# Hauptfenster
|
||||||
self.master.wm_title("RevPi Python PLC Loader")
|
self.master.wm_title("RevPi Python PLC Loader")
|
||||||
self.master.wm_iconphoto(
|
self.master.wm_iconphoto(
|
||||||
@@ -122,26 +144,39 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self.txt_status["textvariable"] = self.var_status
|
self.txt_status["textvariable"] = self.var_status
|
||||||
self.txt_status.pack(fill="x")
|
self.txt_status.pack(fill="x")
|
||||||
|
|
||||||
def _fillmbar(self):
|
self.btn_debug = tkinter.Button(self)
|
||||||
# PLC Menü
|
self.btn_debug["text"] = "PLC Debugmodus"
|
||||||
self.mplc = tkinter.Menu(self.mbar, tearoff=False)
|
self.btn_debug["command"] = self.plcdebug
|
||||||
self.mplc.add_command(label="PLC log...", command=self.plclogs)
|
self.btn_debug.pack(fill="x")
|
||||||
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):
|
def _fillconnbar(self):
|
||||||
|
u"""Generiert Menüeinträge für Verbindungen."""
|
||||||
self.mconn.delete(0, "end")
|
self.mconn.delete(0, "end")
|
||||||
for con in sorted(self.dict_conn.keys(), key=lambda x: x.lower()):
|
for con in sorted(self.dict_conn.keys(), key=lambda x: x.lower()):
|
||||||
self.mconn.add_command(
|
self.mconn.add_command(
|
||||||
label=con, command=partial(self._opt_conn, con)
|
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):
|
def _opt_conn(self, text):
|
||||||
socket.setdefaulttimeout(2)
|
socket.setdefaulttimeout(2)
|
||||||
sp = ServerProxy(
|
sp = ServerProxy(
|
||||||
@@ -151,6 +186,7 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
)
|
)
|
||||||
# Server prüfen
|
# Server prüfen
|
||||||
try:
|
try:
|
||||||
|
self.xmlfuncs = sp.system.listMethods()
|
||||||
self.xmlmode = sp.xmlmodus()
|
self.xmlmode = sp.xmlmodus()
|
||||||
except:
|
except:
|
||||||
self.servererror()
|
self.servererror()
|
||||||
@@ -168,17 +204,30 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
))
|
))
|
||||||
self.mbar.entryconfig("PLC", state="normal")
|
self.mbar.entryconfig("PLC", state="normal")
|
||||||
|
|
||||||
def _closeall(self):
|
def plcdebug(self):
|
||||||
if self.tkcheckclient is not None:
|
u"""Baut den Debugframe und packt ihn."""
|
||||||
self.tkcheckclient.destroy()
|
self.btn_debug["state"] = "disabled"
|
||||||
if self.tklogs is not None:
|
|
||||||
self.tklogs.master.destroy()
|
# Debugfenster laden
|
||||||
if self.tkoptions is not None:
|
if self.debugframe is None:
|
||||||
self.tkoptions.destroy()
|
self.debugframe = revpicheckclient.RevPiCheckClient(
|
||||||
if self.tkprogram is not None:
|
self, self.cli, self.xmlmode
|
||||||
self.tkprogram.destroy()
|
)
|
||||||
|
|
||||||
|
# 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):
|
def plclist(self):
|
||||||
|
u"""Öffnet das Fenster für die Verbindungen."""
|
||||||
win = tkinter.Toplevel(self)
|
win = tkinter.Toplevel(self)
|
||||||
revpiplclist.RevPiPlcList(win)
|
revpiplclist.RevPiPlcList(win)
|
||||||
win.focus_set()
|
win.focus_set()
|
||||||
@@ -188,24 +237,15 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self._fillconnbar()
|
self._fillconnbar()
|
||||||
|
|
||||||
def plclogs(self):
|
def plclogs(self):
|
||||||
|
u"""Öffnet das Fenster für Logdateien."""
|
||||||
if self.tklogs is None or len(self.tklogs.children) == 0:
|
if self.tklogs is None or len(self.tklogs.children) == 0:
|
||||||
win = tkinter.Toplevel(self)
|
win = tkinter.Toplevel(self)
|
||||||
self.tklogs = revpilogfile.RevPiLogfile(win, self.cli)
|
self.tklogs = revpilogfile.RevPiLogfile(win, self.cli)
|
||||||
else:
|
else:
|
||||||
self.tklogs.focus_set()
|
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):
|
def plcoptions(self):
|
||||||
"""Startet das Optionsfenster."""
|
u"""Startet das Optionsfenster."""
|
||||||
if self.xmlmode < 2:
|
if self.xmlmode < 2:
|
||||||
tkmsg.showwarning(
|
tkmsg.showwarning(
|
||||||
parent=self.master, title="Warnung",
|
parent=self.master, title="Warnung",
|
||||||
@@ -222,6 +262,7 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self.xmlmode = self.tkoptions.xmlmode
|
self.xmlmode = self.tkoptions.xmlmode
|
||||||
|
|
||||||
def plcprogram(self):
|
def plcprogram(self):
|
||||||
|
u"""Startet das Programmfenster."""
|
||||||
if self.xmlmode < 2:
|
if self.xmlmode < 2:
|
||||||
tkmsg.showwarning(
|
tkmsg.showwarning(
|
||||||
parent=self.master, title="Warnung",
|
parent=self.master, title="Warnung",
|
||||||
@@ -237,23 +278,30 @@ class RevPiPyControl(tkinter.Frame):
|
|||||||
self.wait_window(win)
|
self.wait_window(win)
|
||||||
|
|
||||||
def plcstart(self):
|
def plcstart(self):
|
||||||
|
u"""Startet das PLC Programm."""
|
||||||
self.cli.plcstart()
|
self.cli.plcstart()
|
||||||
|
|
||||||
def plcstop(self):
|
def plcstop(self):
|
||||||
|
u"""Beendet das PLC Programm."""
|
||||||
self.cli.plcstop()
|
self.cli.plcstop()
|
||||||
|
|
||||||
def plcrestart(self):
|
def plcrestart(self):
|
||||||
|
u"""Startet das PLC Programm neu."""
|
||||||
self.cli.plcstop()
|
self.cli.plcstop()
|
||||||
self.cli.plcstart()
|
self.cli.plcstart()
|
||||||
|
|
||||||
def servererror(self):
|
def serverdisconnect(self):
|
||||||
"""Setzt alles auf NULL."""
|
u"""Trennt eine bestehende Verbindung."""
|
||||||
socket.setdefaulttimeout(2)
|
socket.setdefaulttimeout(2)
|
||||||
self.cli = None
|
self.cli = None
|
||||||
self._btnstate()
|
self._btnstate()
|
||||||
self.mbar.entryconfig("PLC", state="disabled")
|
self.mbar.entryconfig("PLC", state="disabled")
|
||||||
self.var_conn.set("")
|
self.var_conn.set("")
|
||||||
self._closeall()
|
self._closeall()
|
||||||
|
|
||||||
|
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):
|
def tmr_plcrunning(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user