1
0
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:
2017-06-28 11:55:30 +02:00
parent e9279e4a53
commit 673c338c6b
3 changed files with 179 additions and 76 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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):