From e9279e4a5313425e8f81c41c63410092a6572af9 Mon Sep 17 00:00:00 2001 From: NaruX Date: Tue, 27 Jun 2017 16:12:09 +0200 Subject: [PATCH] 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",