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

Programm up-download eingebaut

This commit is contained in:
2017-03-09 20:26:58 +01:00
parent b10a9823f2
commit fb3de16ef7
5 changed files with 376 additions and 17 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-03-08, 17:49:43 --> <!-- Saved: 2017-03-09, 20:23:30 -->
<!-- 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>
@@ -21,12 +21,14 @@
<Source>revpipycontrol/revpiplclist.py</Source> <Source>revpipycontrol/revpiplclist.py</Source>
<Source>revpipycontrol/revpilogfile.py</Source> <Source>revpipycontrol/revpilogfile.py</Source>
<Source>revpipycontrol/revpioption.py</Source> <Source>revpipycontrol/revpioption.py</Source>
<Source>revpipycontrol/revpiprogram.py</Source>
</Sources> </Sources>
<Forms/> <Forms/>
<Translations/> <Translations/>
<Resources/> <Resources/>
<Interfaces/> <Interfaces/>
<Others/> <Others/>
<MainScript>revpipycontrol/revpipycontrol.py</MainScript>
<Vcs> <Vcs>
<VcsType>Mercurial</VcsType> <VcsType>Mercurial</VcsType>
<VcsOptions> <VcsOptions>
@@ -194,7 +196,7 @@
<string>MaxLineLength</string> <string>MaxLineLength</string>
</key> </key>
<value> <value>
<int>80</int> <int>79</int>
</value> </value>
<key> <key>
<string>NoFixCodes</string> <string>NoFixCodes</string>

View File

@@ -13,7 +13,7 @@ class RevPiOption(tkinter.Frame):
def __init__(self, master, xmlcli): def __init__(self, master, xmlcli):
super().__init__(master) super().__init__(master)
self.pack() self.pack(expand=True, fill="both")
self.xmlcli = xmlcli self.xmlcli = xmlcli
@@ -68,9 +68,12 @@ class RevPiOption(tkinter.Frame):
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = "Python PLC Programname" lbl["text"] = "Python PLC Programname"
lbl.grid(**cpadw) lbl.grid(**cpadw)
txt_startpy = tkinter.Entry(prog) # txt_startpy = tkinter.Entry(prog)
txt_startpy["textvariable"] = self.var_startpy # txt_startpy["textvariable"] = self.var_startpy
txt_startpy.grid(**cpadwe) # txt_startpy.grid(**cpadwe)
opt_startpy = tkinter.OptionMenu(
prog, self.var_startpy, *self.xmlcli.get_filelist())
opt_startpy.grid(**cpadwe)
ckb_slave = tkinter.Checkbutton(prog, justify="left") ckb_slave = tkinter.Checkbutton(prog, justify="left")
ckb_slave["text"] = "RevPi als PLC-Slave verwenden" ckb_slave["text"] = "RevPi als PLC-Slave verwenden"
ckb_slave["state"] = "disabled" ckb_slave["state"] = "disabled"
@@ -140,8 +143,8 @@ class RevPiOption(tkinter.Frame):
ask = tkmsg.askyesnocancel( ask = tkmsg.askyesnocancel(
"Frage", "Die Einstellungen werden jetzt auf den Revolution Pi " "Frage", "Die Einstellungen werden jetzt auf den Revolution Pi "
"gespeichert.\nSollen die neuen Einstellungen sofort in Kraft " "gespeichert. \n\nSollen die neuen Einstellungen sofort in Kraft "
"treten? Dies bedeutet einen Neustart des Dienstes und des ggf. " "treten? \nDies bedeutet einen Neustart des Dienstes und des ggf. "
"laufenden PLC-Programms!", parent=self.master "laufenden PLC-Programms!", parent=self.master
) )
if ask is not None: if ask is not None:

View File

@@ -20,6 +20,7 @@ else:
homedir = environ["APPDATA"] homedir = environ["APPDATA"]
savefile = os.path.join(homedir, ".revpipyplc", "connections.dat") savefile = os.path.join(homedir, ".revpipyplc", "connections.dat")
def get_connections(): def get_connections():
if os.path.exists(savefile): if os.path.exists(savefile):
fh = open(savefile, "rb") fh = open(savefile, "rb")
@@ -65,7 +66,7 @@ class RevPiPlcList(tkinter.Frame):
self.txt_name = tkinter.Entry(self, textvariable=self.var_name) self.txt_name = tkinter.Entry(self, textvariable=self.var_name)
self.txt_name.bind("<KeyRelease>", self.evt_keypress) self.txt_name.bind("<KeyRelease>", self.evt_keypress)
self.txt_name.grid( self.txt_name.grid(
column=3, row=0, columnspan=3, sticky="n", padx=5, pady=5) column=3, row=0, columnspan=3, sticky="n", padx=5, pady=5)
tkinter.Label(self, text="IP-Adresse").grid( tkinter.Label(self, text="IP-Adresse").grid(
column=2, row=1, sticky="wn", padx=5, pady=5 column=2, row=1, sticky="wn", padx=5, pady=5
@@ -87,10 +88,12 @@ class RevPiPlcList(tkinter.Frame):
self, text="Neu", command=self.evt_btnnew) self, text="Neu", command=self.evt_btnnew)
self.btn_new.grid(column=2, row=3, sticky="s") self.btn_new.grid(column=2, row=3, sticky="s")
self.btn_add = tkinter.Button( self.btn_add = tkinter.Button(
self, text="Übernehmen", command=self.evt_btnadd, state="disabled") self, text="Übernehmen", command=self.evt_btnadd,
state="disabled")
self.btn_add.grid(column=3, row=3, sticky="s") self.btn_add.grid(column=3, row=3, sticky="s")
self.btn_remove = tkinter.Button( self.btn_remove = tkinter.Button(
self, text="Entfernen", command=self.evt_btnremove, state="disabled") self, text="Entfernen", command=self.evt_btnremove,
state="disabled")
self.btn_remove.grid(column=4, row=3, sticky="s") self.btn_remove.grid(column=4, row=3, sticky="s")
# Fensterbuttons # Fensterbuttons
@@ -119,7 +122,7 @@ class RevPiPlcList(tkinter.Frame):
def build_listconn(self): def build_listconn(self):
self.list_conn.delete(0, "end") self.list_conn.delete(0, "end")
lst_conns = sorted(self._connections.keys(), key=lambda x: x.lower()) lst_conns = sorted(self._connections.keys(), key=lambda x: x.lower())
self.list_conn.insert("end",*lst_conns) self.list_conn.insert("end", *lst_conns)
def evt_btnadd(self): def evt_btnadd(self):
# TODO: Daten prüfen # TODO: Daten prüfen
@@ -197,7 +200,8 @@ class RevPiPlcList(tkinter.Frame):
self.btn_remove["state"] = "disabled" self.btn_remove["state"] = "disabled"
def evt_keypress(self, evt=None): def evt_keypress(self, evt=None):
okvalue = "normal" if (self.var_address.get() != "" okvalue = "normal" if (
self.var_address.get() != ""
and self.var_name.get() != "" and self.var_name.get() != ""
and self.var_port.get() != "" and self.var_port.get() != ""
) else "disabled" ) else "disabled"

View File

@@ -0,0 +1,345 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
import tarfile
import tkinter
import tkinter.filedialog as tkfd
import tkinter.messagebox as tkmsg
from os import makedirs
from tempfile import mktemp
from xmlrpc.client import Binary
class RevPiProgram(tkinter.Frame):
def __init__(self, master, xmlcli, revpi):
super().__init__(master)
# master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both")
self.uploaded = False
self.revpi = revpi
self.xmlcli = xmlcli
# Fenster bauen
self._createwidgets()
self._evt_optdown()
self._evt_optup()
# def _checkclose(self):
# if self.uploaded:
# tkmsg.showinfo("Ein PLC Programm wurde hochgeladen. "
# "Bitte die PLC options prüfen ob dort das neue Programm"
# "eingestellt werden muss.")
# self.master.destroy()
def _createwidgets(self):
self.master.wm_title("RevPi Python PLC Programm")
self.master.wm_resizable(width=False, height=False)
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
cpad = {"padx": 4, "pady": 2}
cpade = {"padx": 4, "pady": 2, "sticky": "e"}
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
cpadwe = {"padx": 4, "pady": 2, "sticky": "we"}
# Gruppe Programm
prog = tkinter.LabelFrame(self)
prog.columnconfigure(0, weight=1)
prog["text"] = "PLC Pythonprogramm"
prog.grid(columnspan=2, pady=2, sticky="we")
# Variablen vorbereiten
self.var_picdown = tkinter.BooleanVar(prog)
self.var_picup = tkinter.BooleanVar(prog)
self.var_cleanup = tkinter.BooleanVar(prog)
self.var_typedown = tkinter.StringVar(prog)
self.var_typeup = tkinter.StringVar(prog)
self.lst_typedown = ["Dateien", "Zip Archiv", "TGZ Archiv"]
self.lst_typeup = ["Datei", "Ordner", "Zip Archiv", "TGZ Archiv"]
self.var_typedown.set(self.lst_typedown[0])
self.var_typeup.set(self.lst_typeup[0])
r = 0
lbl = tkinter.Label(prog)
lbl["text"] = "PLC Programm herunterladen als:"
lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu(
prog, self.var_typedown, *self.lst_typedown,
command=self._evt_optdown)
opt["width"] = 10
opt.grid(column=1, row=r, **cpad)
r = 1
self.ckb_picdown = tkinter.Checkbutton(prog)
self.ckb_picdown["text"] = "inkl. piCtory Konfiguration"
self.ckb_picdown["variable"] = self.var_picdown
self.ckb_picdown.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog)
btn["command"] = self.plcdownload
btn["text"] = "Download"
btn.grid(column=1, row=r, **cpad)
r = 2
lbl = tkinter.Label(prog)
lbl["text"] = "PLC Programm hochladen als:"
lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu(
prog, self.var_typeup, *self.lst_typeup,
command=self._evt_optup)
opt["width"] = 10
opt.grid(column=1, row=r, **cpad)
r = 3
self.ckb_picup = tkinter.Checkbutton(prog)
self.ckb_picup["text"] = "enthält piCtory Konfiguration"
self.ckb_picup["variable"] = self.var_picup
self.ckb_picup.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog)
btn["command"] = self.plcupload
btn["text"] = "Upload"
btn.grid(column=1, row=r, **cpad)
r = 4
ckb = tkinter.Checkbutton(prog)
ckb["text"] = "vorher alles im Uploadverzeichnis löschen"
ckb["variable"] = self.var_cleanup
ckb.grid(column=0, row=r, columnspan=2, **cpadw)
# Gruppe piCtory
picto = tkinter.LabelFrame(self)
picto.columnconfigure(0, weight=1)
picto["text"] = "piCtory Konfiguration"
picto.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(picto)
lbl["text"] = "piCtory Konfiguration herunterladen"
lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(picto)
btn["command"] = self.getpictoryrsc
btn["text"] = "Download"
btn.grid(column=1, row=0, **cpad)
lbl = tkinter.Label(picto)
lbl["text"] = "piCtory Konfiguration hochladen"
lbl.grid(column=0, row=1, **cpadw)
btn = tkinter.Button(picto)
btn["command"] = self.setpictoryrsc
btn["text"] = "Upload"
btn.grid(column=1, row=1, **cpad)
# Gruppe ProcImg
proc = tkinter.LabelFrame(self)
proc.columnconfigure(0, weight=1)
proc["text"] = "piControl0 Prozessabbild"
proc.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(proc)
lbl["text"] = "Prozessabbild herunterladen"
lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(proc)
btn["command"] = self.getprocimg
btn["text"] = "Download"
btn.grid(column=1, row=0, **cpad)
# Beendenbutton
btn = tkinter.Button(self)
btn["command"] = self.master.destroy
btn["text"] = "Beenden"
btn.grid()
def _evt_optdown(self, text=""):
if self.lst_typedown.index(self.var_typedown.get()) == 0:
self.var_picdown.set(False)
self.ckb_picdown["state"] = "disable"
else:
self.ckb_picdown["state"] = "normal"
def _evt_optup(self, text=""):
if self.lst_typeup.index(self.var_typeup.get()) == 0:
self.var_picup.set(False)
self.ckb_picup["state"] = "disable"
else:
self.ckb_picup["state"] = "normal"
def getpictoryrsc(self):
fh = tkfd.asksaveasfile(
mode="wb", parent=self.master,
confirmoverwrite=True,
title="Speichern als...",
initialfile=self.revpi + ".rsc",
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*"))
)
if fh is not None:
try:
fh.write(self.xmlcli.get_pictoryrsc().data)
except:
tkmsg.showerror(
parent=self.master, title="Fehler",
message="Datei konnte nicht geladen und gespeichert "
"werden!"
)
else:
tkmsg.showinfo(
parent=self.master, title="Erfolgreich",
message="Datei erfolgreich vom Revolution Pi geladen "
"und gespeichert.",
)
finally:
fh.close()
def getprocimg(self):
fh = tkfd.asksaveasfile(
mode="wb", parent=self.master,
confirmoverwrite=True,
title="Speichern als...",
initialfile=self.revpi + ".img",
filetypes=(("Imagefiles", "*.img"), ("All Files", "*.*"))
)
if fh is not None:
try:
fh.write(self.xmlcli.get_procimg().data)
except:
tkmsg.showerror(
parent=self.master, title="Fehler",
message="Datei konnte nicht geladen und gespeichert"
"werden!"
)
else:
tkmsg.showinfo(
parent=self.master, title="Erfolgreich",
message="Datei erfolgreich vom Revolution Pi geladen "
"und gespeichert.",
)
finally:
fh.close()
def setpictoryrsc(self):
print("setpictoryrsc")
fh = tkfd.askopenfile(
mode="rb", parent=self.master,
title="piCtory Datei öffnen...",
initialfile=self.revpi + ".rsc",
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*"))
)
if fh is not None:
# TODO: Test, ob es wirklich piCtory ist
ask = tkmsg.askyesno(
parent=self.master, title="Frage",
message="Soll nach dem Hochladen ein reset am piControl "
"Treiber durchgeführt werden?",
)
ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask)
if ec == 0:
if ask:
tkmsg.showinfo(
parent=self.master, title="Erfolgreich",
message="Die Übertragung der piCtory Konfiguration "
"und der Reset von piControl wurden erfolgreich "
"ausgeführt")
else:
tkmsg.showinfo(
parent=self.master, title="Erfolgreich",
message="Die Übertragung der piCtory Konfiguration "
"wurde erfolgreich ausgeführt")
elif ec < 0:
tkmsg.showerror(
parent=self.master, title="Fehler",
message="Die piCtory Konfiguration konnte auf dem "
"Revolution Pi nicht geschrieben werden.")
elif ec > 0:
tkmsg.showwarning(
parent=self.master, title="Warnung",
message="Die piCtroy Konfiguration wurde erfolgreich "
"gespeichert. \nBeim piControl Reset trat allerdings ein "
"Fehler auf!")
fh.close()
def plcdownload(self):
tdown = self.lst_typedown.index(self.var_typedown.get())
fh = None
dir = ""
if tdown == 0:
# Ordner
dir = tkfd.askdirectory(
parent=self.master, title="Verzeichnis zum Ablegen",
mustexist=False, initialdir=self.revpi)
if type(dir) == str and dir != "":
fh = open(mktemp(), "wb")
elif tdown == 1:
# Zip
fh = tkfd.asksaveasfile(
mode="wb", parent=self.master,
confirmoverwrite=True,
title="Speichern als...",
initialfile=self.revpi + ".zip",
filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*"))
)
elif tdown == 2:
# TarGz
fh = tkfd.asksaveasfile(
mode="wb", parent=self.master,
confirmoverwrite=True,
title="Speichern als...",
initialfile=self.revpi + ".tar.gz",
filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*"))
)
if fh is not None:
if tdown == 1:
plcfile = self.xmlcli.plcdownload("zip")
else:
plcfile = self.xmlcli.plcdownload("tar")
try:
fh.write(plcfile.data)
# Optional entpacken
if tdown == 0:
fh.close()
makedirs(dir, exist_ok=True)
fh_pack = tarfile.open(fh.name)
fh_pack.extractall(dir)
fh_pack.close()
except:
raise
tkmsg.showerror(
parent=self.master, title="Fehler",
message="Datei konnte nicht geladen und gespeichert "
"werden!"
)
else:
tkmsg.showinfo(
parent=self.master, title="Erfolgreich",
message="Datei erfolgreich vom Revolution Pi geladen "
"und gespeichert.",
)
finally:
fh.close()
print("plcdownload", tdown)
def plcupload(self):
tup = self.lst_typeup.index(self.var_typeup.get())
print("plcupload", tup)
self.uploaded = True
if __name__ == "__main__":
root = tkinter.Tk()
myapp = RevPiProgram(root, None, "test")
root.mainloop()

View File

@@ -11,6 +11,7 @@ import revpicheckclient
import revpilogfile import revpilogfile
import revpioption import revpioption
import revpiplclist import revpiplclist
import revpiprogram
import socket import socket
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
@@ -28,6 +29,7 @@ class RevPiPyControl(tkinter.Frame):
self.cli = None self.cli = None
self.dict_conn = revpiplclist.get_connections() self.dict_conn = revpiplclist.get_connections()
self.revpiname = None
# Fenster aufbauen # Fenster aufbauen
self._createwidgets() self._createwidgets()
@@ -108,10 +110,11 @@ class RevPiPyControl(tkinter.Frame):
def _fillconnbar(self): def _fillconnbar(self):
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(label=con, command=partial(self._opt_conn, con)) self.mconn.add_command(
label=con, command=partial(self._opt_conn, con)
)
def _opt_conn(self, text): def _opt_conn(self, text):
print(text)
sp = ServerProxy( sp = ServerProxy(
"http://{}:{}".format( "http://{}:{}".format(
self.dict_conn[text][0], int(self.dict_conn[text][1]) self.dict_conn[text][0], int(self.dict_conn[text][1])
@@ -124,6 +127,7 @@ class RevPiPyControl(tkinter.Frame):
self.servererror() self.servererror()
else: else:
self.cli = sp self.cli = sp
self.revpiname = text
self.var_conn.set("{} - {}:{}".format( self.var_conn.set("{} - {}:{}".format(
text, self.dict_conn[text][0], int(self.dict_conn[text][1]) text, self.dict_conn[text][0], int(self.dict_conn[text][1])
)) ))
@@ -149,14 +153,15 @@ class RevPiPyControl(tkinter.Frame):
pass pass
def plcoptions(self): def plcoptions(self):
# TODO: Optionsfenster
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
revpioption.RevPiOption(win, self.cli) revpioption.RevPiOption(win, self.cli)
self.wait_window(win) self.wait_window(win)
def plcprogram(self): def plcprogram(self):
# TODO: Programfenster # TODO: Programfenster
pass win = tkinter.Toplevel(self)
revpiprogram.RevPiProgram(win, self.cli, self.revpiname)
self.wait_window(win)
def plcstart(self): def plcstart(self):
self.cli.plcstart() self.cli.plcstart()