1
0
mirror of https://github.com/naruxde/revpipycontrol.git synced 2025-11-08 15:43:52 +01:00

simple log viewer

This commit is contained in:
2017-02-26 18:36:34 +01:00
parent e49b48c36e
commit ed23ce2b48
3 changed files with 406 additions and 12 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipycontrol --> <!-- eric project file for project revpipycontrol -->
<!-- Saved: 2017-02-15, 20:52:17 --> <!-- Saved: 2017-02-26, 18:33:07 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
@@ -16,6 +16,7 @@
<Sources> <Sources>
<Source>revpipycontrol/__init__.py</Source> <Source>revpipycontrol/__init__.py</Source>
<Source>revpipycontrol/revpipycontrol.py</Source> <Source>revpipycontrol/revpipycontrol.py</Source>
<Source>revpipycontrol/revpicheckclient.py</Source>
</Sources> </Sources>
<Forms/> <Forms/>
<Translations/> <Translations/>
@@ -23,7 +24,110 @@
<Interfaces/> <Interfaces/>
<Others/> <Others/>
<Vcs> <Vcs>
<VcsType>None</VcsType> <VcsType>Mercurial</VcsType>
<VcsOptions>
<dict>
<key>
<string>add</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>checkout</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>commit</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>diff</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>export</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>global</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>history</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>log</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>remove</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>status</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>tag</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
<key>
<string>update</string>
</key>
<value>
<list>
<string></string>
</list>
</value>
</dict>
</VcsOptions>
<VcsOtherData>
<dict/>
</VcsOtherData>
</Vcs> </Vcs>
<FiletypeAssociations> <FiletypeAssociations>
<FiletypeAssociation pattern="*.idl" type="INTERFACES"/> <FiletypeAssociation pattern="*.idl" type="INTERFACES"/>

View File

@@ -0,0 +1,230 @@
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-scrollbar-to-a-group-of-widgets-in-tkinter
import pickle
import tkinter
from argparse import ArgumentParser
from concurrent.futures import ThreadPoolExecutor
from time import sleep
from xmlrpc.client import ServerProxy, Binary, MultiCall
class RevPiCheckClient(tkinter.Frame):
def __init__(self, master, xmlcli=None):
"""Instantiiert MyApp-Klasse."""
super().__init__(master)
self.pack(fill="both", expand=True)
# Command arguments
parser = ArgumentParser(
description="Revolution Pi IO-Client"
)
parser.add_argument(
"-a", "--address", dest="address", default="127.0.0.1",
help="Server address (Default: 127.0.0.1)"
)
parser.add_argument(
"-p", "--port", dest="port", type=int, default=55074,
help="Use port to connect to server (Default: 55074)"
)
self.pargs = parser.parse_args()
self.cli = xmlcli if xmlcli is not None else ServerProxy(
"http://{}:{}".format(self.pargs.address, self.pargs.port)
)
self.lst_devices = self.cli.get_devicenames()
self.lst_group = []
self.dict_inpvar = {}
self.dict_outvar = {}
self.autorw = tkinter.BooleanVar()
self.fut_autorw = None
# Fenster aufbauen
self._createwidgets()
# 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 onFrameConfigure(self, canvas):
canvas.configure(scrollregion=canvas.bbox("all"))
def _createiogroup(self, device, frame, iotype):
"""Erstellt IO-Gruppen."""
# IOs generieren
canvas = tkinter.Canvas(frame, borderwidth=0, width=180, heigh=800)
s_frame = tkinter.Frame(canvas)
vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True)
canvas.create_window((4, 4), window=s_frame, anchor="nw")
s_frame.bind("<Configure>", lambda event, canvas=canvas: self.onFrameConfigure(canvas))
rowcount = 0
for io in self.cli.get_iolist(device, iotype):
# io = [name,default,anzbits,adressbyte,export,adressid,bmk,bitaddress,tkinter_var]
tkinter.Label(s_frame, text=io[0]).grid(column=0, row=rowcount, sticky="w")
if io[7] >= 0:
var = tkinter.BooleanVar()
check = tkinter.Checkbutton(s_frame)
check["state"] = "disabled" if iotype == "inp" else "normal"
check["text"] = ""
check["variable"] = var
check.grid(column=1, row=rowcount)
#check.pack(anchor="e", side="right")
else:
var = tkinter.IntVar()
#txt = tkinter.Spinbox(fra_group, to=256)
txt = tkinter.Spinbox(s_frame, to=256)
txt["state"] = "disabled" if iotype == "inp" else "normal"
txt["width"] = 4
txt["textvariable"] = var
txt.grid(column=1, row=rowcount)
#txt.pack(anchor="e", side="right")
# 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 _createwidgets(self):
"""Erstellt den Fensterinhalt."""
# Hauptfenster
self.master.wm_title("RevPi Onlineview")
for dev in self.lst_devices:
# Variablen vorbereiten
self.dict_inpvar[dev] = []
self.dict_outvar[dev] = []
# Devicegruppe erstellen
group = tkinter.LabelFrame(self)
group["text"] = dev
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.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")
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")
self.btn_read = tkinter.Button(self)
self.btn_read["text"] = "LESEN"
self.btn_read["command"] = self.readvalues
self.btn_read.pack(side="bottom", fill="x")
check = tkinter.Checkbutton(self)
check["command"] = self.toggleauto
check["text"] = "autoupdate"
check["variable"] = self.autorw
check.pack(side="bottom")
def _readvaluesdev(self, device, iotype):
"""Ruft alle aktuellen Werte fuer das Device ab."""
# Multicall vorbereiten
mc_values = MultiCall(self.cli)
if iotype == "inp":
lst_ios = self.dict_inpvar[device]
elif iotype == "out":
lst_ios = self.dict_outvar[device]
for io in lst_ios:
mc_values.get_iovalue(device, io[0])
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):
"""Alle Werte der Inputs und Outputs abrufen."""
# Werte aus Prozessabbild einlesen
self.cli.readprocimg()
for dev in self.lst_devices:
self._readvaluesdev(dev, "inp")
self._readvaluesdev(dev, "out")
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)
def writevalues(self):
"""Alle Outputs senden."""
pass
#for dev in self.lst_devices:
#self._writevaluesdev(dev)
# Werte in Prozessabbild schreiben
#self.cli.writeprocimg()
if __name__ == "__main__":
root = tkinter.Tk()
myapp = RevPiCheckClient(root)
myapp.mainloop()

View File

@@ -3,11 +3,53 @@
# (c) Sven Sager, License: GPLv3 # (c) Sven Sager, License: GPLv3
# #
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import revpicheckclient
import tkinter import tkinter
from argparse import ArgumentParser from argparse import ArgumentParser
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from xmlrpc.client import ServerProxy, Binary from xmlrpc.client import ServerProxy, Binary
class RevPiPyLogs(tkinter.Frame):
def __init__(self, master, xmlcli):
super().__init__(master)
self.pack(fill="both", expand=True)
self.xmlcli = xmlcli
self._createwidgets()
def _createwidgets(self):
self.master.wm_title("RevPi Python PLC Logs")
# PLC Log
self.plclog = tkinter.Text(self)
self.plcscr = tkinter.Scrollbar(self)
self.plclog.pack(side="left", expand=True, fill="both")
self.plcscr.pack(side="left", fill="y")
self.plclog["yscrollcommand"] = self.plcscr.set
self.plcscr["command"] = self.plclog.yview
# APP Log
self.applog = tkinter.Text(self)
self.appscr = tkinter.Scrollbar(self)
self.appscr.pack(side="right", fill="y")
self.applog.pack(side="right", expand=True, fill="both")
self.applog["yscrollcommand"] = self.appscr.set
self.appscr["command"] = self.applog.yview
self.get_applog()
self.get_plclog()
def get_applog(self):
self.applog.delete(1.0, tkinter.END)
self.applog.insert(1.0, self.xmlcli.get_applog())
self.applog.see(tkinter.END)
def get_plclog(self):
self.plclog.delete(1.0, tkinter.END)
self.plclog.insert(1.0, self.xmlcli.get_plclog())
self.plclog.see(tkinter.END)
class RevPiPyControl(tkinter.Frame): class RevPiPyControl(tkinter.Frame):
def __init__(self, master=None): def __init__(self, master=None):
@@ -34,7 +76,7 @@ class RevPiPyControl(tkinter.Frame):
# Fenster aufbauen # Fenster aufbauen
self._createwidgets() self._createwidgets()
# Daten aktualisieren # Daten aktualisieren
self.plcrunning() self.plcrunning()
@@ -42,44 +84,62 @@ class RevPiPyControl(tkinter.Frame):
"""Erstellt den Fensterinhalt.""" """Erstellt den Fensterinhalt."""
# Hauptfenster # Hauptfenster
self.master.wm_title("RevPi Python PLC Loader") self.master.wm_title("RevPi Python PLC Loader")
self.var_status = tkinter.StringVar() self.var_status = tkinter.StringVar()
self.txt_status = tkinter.Entry() self.txt_status = tkinter.Entry()
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")
self.btn_plcrunning = tkinter.Button(self) self.btn_plcrunning = tkinter.Button(self)
self.btn_plcrunning["text"] = "PLC Status" self.btn_plcrunning["text"] = "PLC Status"
self.btn_plcrunning["command"] = self.plcrunning self.btn_plcrunning["command"] = self.plcrunning
self.btn_plcrunning.pack(fill="x") self.btn_plcrunning.pack(fill="x")
self.btn_plcstart = tkinter.Button(self) self.btn_plcstart = tkinter.Button(self)
self.btn_plcstart["text"] = "PLC Start" self.btn_plcstart["text"] = "PLC Start"
self.btn_plcstart["command"] = self.plcstart self.btn_plcstart["command"] = self.plcstart
self.btn_plcstart.pack(fill="x") self.btn_plcstart.pack(fill="x")
self.btn_plcstop = tkinter.Button(self) self.btn_plcstop = tkinter.Button(self)
self.btn_plcstop["text"] = "PLC Stop" self.btn_plcstop["text"] = "PLC Stop"
self.btn_plcstop["command"] = self.plcstop self.btn_plcstop["command"] = self.plcstop
self.btn_plcstop.pack(fill="x") self.btn_plcstop.pack(fill="x")
self.btn_plcrestart = tkinter.Button(self) self.btn_plcrestart = tkinter.Button(self)
self.btn_plcrestart["text"] = "PLC Restart" self.btn_plcrestart["text"] = "PLC Restart"
self.btn_plcrestart["command"] = self.plcrestart self.btn_plcrestart["command"] = self.plcrestart
self.btn_plcrestart.pack(fill="x") self.btn_plcrestart.pack(fill="x")
def plcstart(self): # self.btn_plcrestart = tkinter.Button(self)
# self.btn_plcrestart["text"] = "PLC Monitor"
# self.btn_plcrestart["command"] = self.plcmonitor
# self.btn_plcrestart.pack(fill="x")
self.btn_plcrestart = tkinter.Button(self)
self.btn_plcrestart["text"] = "PLC Logs"
self.btn_plcrestart["command"] = self.plclogs
self.btn_plcrestart.pack(fill="x")
def plclogs(self):
root = tkinter.Tk()
self.tklogs = RevPiPyLogs(root, self.cli)
def plcmonitor(self):
root = tkinter.Tk()
self.tkmonitor = revpicheckclient.RevPiCheckClient(root, self.cli)
def plcstart (self):
self.cli.plcstart() self.cli.plcstart()
self.plcrunning() self.plcrunning()
def plcstop(self): def plcstop(self):
self.cli.plcstop() self.cli.plcstop()
self.plcrunning() self.plcrunning()
def plcrestart(self): def plcrestart(self):
self.cli.plcrestart() self.cli.plcrestart()
self.plcrunning() self.plcrunning()
def plcrunning(self): def plcrunning(self):
if self.cli.plcrunning(): if self.cli.plcrunning():
self.btn_plcrunning["activebackground"] = "green" self.btn_plcrunning["activebackground"] = "green"