1
0
mirror of https://github.com/naruxde/revpipycontrol.git synced 2025-11-09 07:58:03 +01:00

IO-Fenster nur in Y resizable

Scrollrad an Canvas gekoppelt (Linux)
Exitcodes angepasst
?bersetzungstools eingebaut
?bersetzungen begonnen
This commit is contained in:
2017-06-29 09:00:19 +02:00
parent 673c338c6b
commit 8c8da29915
5 changed files with 297 additions and 178 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-06-27, 16:07:48 --> <!-- Saved: 2017-06-28, 17:00:06 -->
<!-- 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,6 +21,7 @@
<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> <Source>revpipycontrol/revpiprogram.py</Source>
<Source>revpipycontrol/mytools.py</Source>
</Sources> </Sources>
<Forms/> <Forms/>
<Translations/> <Translations/>

46
revpipycontrol/mytools.py Normal file
View File

@@ -0,0 +1,46 @@
#
# RevPiPyControl
#
# Webpage: https://revpimodio.org/revpipyplc/
# (c) Sven Sager, License: LGPLv3
#
# -*- coding: utf-8 -*-
import gettext
import locale
import sys
from os.path import dirname
from os.path import join as pathjoin
def addroot(filename):
u"""Hängt root-dir der Anwendung vor Dateinamen.
Je nach Ausführungsart der Anwendung muss das root-dir über
andere Arten abgerufen werden.
@param filename: Datei oder Ordnername
@returns: root dir
"""
if getattr(sys, "frozen", False):
return pathjoin(dirname(sys.executable), filename)
else:
return pathjoin(dirname(__file__), filename)
def gettrans(proglang=None):
# Sprache auswählen
if proglang is None:
# Autodetect Language or switch to static
# proglang = "de"
proglang = locale.getdefaultlocale()[0].split('_')[0]
# Übersetzungen laden
trans = gettext.translation(
"revpipycontrol",
addroot("locale"),
languages=[proglang],
fallback=True
)
return trans.gettext

View File

@@ -22,10 +22,7 @@ class RevPiCheckClient(tkinter.Frame):
# 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)
@@ -62,12 +59,35 @@ class RevPiCheckClient(tkinter.Frame):
def _createiogroup(self, device, frame, iotype): def _createiogroup(self, device, frame, iotype):
"""Erstellt IO-Gruppen.""" """Erstellt IO-Gruppen."""
# IOs generieren
canvas = tkinter.Canvas(frame, borderwidth=0, width=180, heigh=800) # IO-Typen festlegen
if iotype == "inp":
lst_io = self.dict_inps[device]
else:
lst_io = self.dict_outs[device]
# Fensterinhalt aufbauen
calc_heigh = len(lst_io) * 21
canvas = tkinter.Canvas(
frame,
borderwidth=0,
width=180,
heigh=calc_heigh if calc_heigh <= 600 else 600
)
s_frame = tkinter.Frame(canvas) s_frame = tkinter.Frame(canvas)
vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview) vsb = tkinter.Scrollbar(frame, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set) canvas.configure(yscrollcommand=vsb.set)
# Scrollrad Linux
canvas.bind(
"<ButtonPress-4>",
lambda x: canvas.yview_scroll(-1, "units")
)
canvas.bind(
"<ButtonPress-5>",
lambda x: canvas.yview_scroll(1, "units")
)
vsb.pack(side="right", fill="y") vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True) canvas.pack(side="left", fill="both", expand=True)
@@ -76,13 +96,8 @@ class RevPiCheckClient(tkinter.Frame):
"<Configure>", lambda event, canvas=canvas: self._onfrmconf(canvas) "<Configure>", lambda event, canvas=canvas: self._onfrmconf(canvas)
) )
# IOs generieren
rowcount = 0 rowcount = 0
if iotype == "inp":
lst_io = self.dict_inps[device]
else:
lst_io = self.dict_outs[device]
for io in lst_io: for io in lst_io:
# io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)] # io = [name,bytelen,byteaddr,bmk,bitaddress,(tkinter_var)]
@@ -101,8 +116,10 @@ class RevPiCheckClient(tkinter.Frame):
check.grid(column=1, row=rowcount) check.grid(column=1, row=rowcount)
else: else:
var = tkinter.IntVar() var = tkinter.IntVar()
# 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"
@@ -129,6 +146,7 @@ class RevPiCheckClient(tkinter.Frame):
"WM_DELETE_WINDOW", "WM_DELETE_WINDOW",
lambda win=win: self.__hidewin(win) lambda win=win: self.__hidewin(win)
) )
win.resizable(False, True)
win.withdraw() win.withdraw()
self.lst_wins.append(win) self.lst_wins.append(win)

View File

@@ -13,6 +13,7 @@ import tkinter
import tkinter.filedialog as tkfd import tkinter.filedialog as tkfd
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
import zipfile import zipfile
from mytools import gettrans
from os import environ from os import environ
from os import makedirs from os import makedirs
from shutil import rmtree from shutil import rmtree
@@ -20,6 +21,8 @@ from sys import platform
from tempfile import mkstemp, mkdtemp from tempfile import mkstemp, mkdtemp
from xmlrpc.client import Binary from xmlrpc.client import Binary
# Übersetzung laden
_ = gettrans()
# Systemwerte # Systemwerte
if platform == "linux": if platform == "linux":
@@ -37,7 +40,8 @@ class RevPiProgram(tkinter.Frame):
return None return None
super().__init__(master) super().__init__(master)
# master.protocol("WM_DELETE_WINDOW", self._checkclose) # FIXME: Warnung kann nerven
# self.master.protocol("WM_DELETE_WINDOW", self._checkclose)
self.pack(expand=True, fill="both") self.pack(expand=True, fill="both")
self.uploaded = False self.uploaded = False
@@ -55,15 +59,20 @@ class RevPiProgram(tkinter.Frame):
self._evt_optdown() self._evt_optdown()
self._evt_optup() self._evt_optup()
# def _checkclose(self): def _checkclose(self):
# if self.uploaded: if True or self.uploaded:
# tkmsg.showinfo("Ein PLC Programm wurde hochgeladen. " tkmsg.showinfo(
# "Bitte die PLC options prüfen ob dort das neue Programm" parent=self.master, title=_("Information"),
# "eingestellt werden muss.") message=_(
# self.master.destroy() "A PLC program has been uploaded. Please check the "
"PLC options to see if the correct program is specified "
"as the start program."
)
)
self.master.destroy()
def _createwidgets(self): def _createwidgets(self):
self.master.wm_title("RevPi Python PLC Programm") self.master.wm_title(_("RevPi python PLC programm"))
self.master.wm_resizable(width=False, height=False) self.master.wm_resizable(width=False, height=False)
self.rowconfigure(0, weight=1) self.rowconfigure(0, weight=1)
@@ -77,7 +86,7 @@ class RevPiProgram(tkinter.Frame):
# Gruppe Programm # Gruppe Programm
prog = tkinter.LabelFrame(self) prog = tkinter.LabelFrame(self)
prog.columnconfigure(0, weight=1) prog.columnconfigure(0, weight=1)
prog["text"] = "PLC Python programm" prog["text"] = _("PLC python programm")
prog.grid(columnspan=2, pady=2, sticky="we") prog.grid(columnspan=2, pady=2, sticky="we")
# Variablen vorbereiten # Variablen vorbereiten
@@ -87,16 +96,26 @@ class RevPiProgram(tkinter.Frame):
self.var_typedown = tkinter.StringVar(prog) self.var_typedown = tkinter.StringVar(prog)
self.var_typeup = tkinter.StringVar(prog) self.var_typeup = tkinter.StringVar(prog)
self.lst_typedown = ["Dateien", "Zip Archiv", "TGZ Archiv"] self.lst_typedown = [_("Files"), _("Zip archive"), _("TGZ archive")]
self.lst_typeup = ["Dateien", "Ordner", "Zip Archiv", "TGZ Archiv"] self.lst_typeup = [
_("Files"), _("Folder"), _("Zip archive"), _("TGZ archive")
]
self.var_picdown.set(self.opt.get("picdown", False)) self.var_picdown.set(self.opt.get("picdown", False))
self.var_picup.set(self.opt.get("picup", False)) self.var_picup.set(self.opt.get("picup", False))
self.var_typedown.set(self.opt.get("typedown", self.lst_typedown[0]))
self.var_typeup.set(self.opt.get("typeup", self.lst_typeup[0])) # Gespeicherte Werte übernehmen
saved_val = self.opt.get("typedown", self.lst_typedown[0])
self.var_typedown.set(
saved_val if saved_val in self.lst_typedown else _("Files")
)
saved_val = self.opt.get("typeup", self.lst_typeup[0])
self.var_typeup.set(
saved_val if saved_val in self.lst_typeup else _("Files")
)
r = 0 r = 0
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = "PLC Programm herunterladen als:" lbl["text"] = _("Download PLC program as:")
lbl.grid(column=0, row=r, **cpadw) lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu( opt = tkinter.OptionMenu(
prog, self.var_typedown, *self.lst_typedown, prog, self.var_typedown, *self.lst_typedown,
@@ -106,17 +125,17 @@ class RevPiProgram(tkinter.Frame):
r = 1 r = 1
self.ckb_picdown = tkinter.Checkbutton(prog) self.ckb_picdown = tkinter.Checkbutton(prog)
self.ckb_picdown["text"] = "inkl. piCtory Konfiguration" self.ckb_picdown["text"] = _("include piCtory configuration")
self.ckb_picdown["variable"] = self.var_picdown self.ckb_picdown["variable"] = self.var_picdown
self.ckb_picdown.grid(column=0, row=r, **cpadw) self.ckb_picdown.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog) btn = tkinter.Button(prog)
btn["command"] = self.plcdownload btn["command"] = self.plcdownload
btn["text"] = "Download" btn["text"] = _("Download")
btn.grid(column=1, row=r, **cpad) btn.grid(column=1, row=r, **cpad)
r = 2 r = 2
lbl = tkinter.Label(prog) lbl = tkinter.Label(prog)
lbl["text"] = "PLC Programm hochladen als:" lbl["text"] = _("Upload PLC program as:")
lbl.grid(column=0, row=r, **cpadw) lbl.grid(column=0, row=r, **cpadw)
opt = tkinter.OptionMenu( opt = tkinter.OptionMenu(
prog, self.var_typeup, *self.lst_typeup, prog, self.var_typeup, *self.lst_typeup,
@@ -128,74 +147,74 @@ class RevPiProgram(tkinter.Frame):
r = 3 r = 3
ckb = tkinter.Checkbutton(prog) ckb = tkinter.Checkbutton(prog)
ckb["state"] = self.xmlstate ckb["state"] = self.xmlstate
ckb["text"] = "vorher alles im Uploadverzeichnis löschen" ckb["text"] = _("clean upload folder before upload")
ckb["variable"] = self.var_cleanup ckb["variable"] = self.var_cleanup
ckb.grid(column=0, row=r, columnspan=2, **cpadw) ckb.grid(column=0, row=r, columnspan=2, **cpadw)
r = 4 r = 4
self.ckb_picup = tkinter.Checkbutton(prog) self.ckb_picup = tkinter.Checkbutton(prog)
self.ckb_picup["state"] = self.xmlstate self.ckb_picup["state"] = self.xmlstate
self.ckb_picup["text"] = "enthält piCtory Konfiguration" self.ckb_picup["text"] = _("includes piCtory configuration")
self.ckb_picup["variable"] = self.var_picup self.ckb_picup["variable"] = self.var_picup
self.ckb_picup.grid(column=0, row=r, **cpadw) self.ckb_picup.grid(column=0, row=r, **cpadw)
btn = tkinter.Button(prog) btn = tkinter.Button(prog)
btn["command"] = self.plcupload btn["command"] = self.plcupload
btn["state"] = self.xmlstate btn["state"] = self.xmlstate
btn["text"] = "Upload" btn["text"] = _("Upload")
btn.grid(column=1, row=r, **cpad) btn.grid(column=1, row=r, **cpad)
# Gruppe piCtory # Gruppe piCtory
picto = tkinter.LabelFrame(self) picto = tkinter.LabelFrame(self)
picto.columnconfigure(0, weight=1) picto.columnconfigure(0, weight=1)
picto["text"] = "piCtory Konfiguration" picto["text"] = _("piCtory configuration")
picto.grid(columnspan=2, pady=2, sticky="we") picto.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(picto) lbl = tkinter.Label(picto)
lbl["text"] = "piCtory Konfiguration herunterladen" lbl["text"] = _("Download piCtory configuration")
lbl.grid(column=0, row=0, **cpadw) lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(picto) btn = tkinter.Button(picto)
btn["command"] = self.getpictoryrsc btn["command"] = self.getpictoryrsc
btn["text"] = "Download" btn["text"] = _("Download")
btn.grid(column=1, row=0, **cpad) btn.grid(column=1, row=0, **cpad)
lbl = tkinter.Label(picto) lbl = tkinter.Label(picto)
lbl["text"] = "piCtory Konfiguration hochladen" lbl["text"] = _("Upload piCtory configuration")
lbl.grid(column=0, row=1, **cpadw) lbl.grid(column=0, row=1, **cpadw)
btn = tkinter.Button(picto) btn = tkinter.Button(picto)
btn["command"] = self.setpictoryrsc btn["command"] = self.setpictoryrsc
btn["state"] = self.xmlstate btn["state"] = self.xmlstate
btn["text"] = "Upload" btn["text"] = _("Upload")
btn.grid(column=1, row=1, **cpad) btn.grid(column=1, row=1, **cpad)
# Gruppe ProcImg # Gruppe ProcImg
proc = tkinter.LabelFrame(self) proc = tkinter.LabelFrame(self)
proc.columnconfigure(0, weight=1) proc.columnconfigure(0, weight=1)
proc["text"] = "piControl0 Prozessabbild" proc["text"] = _("piControl0 prozess image")
proc.grid(columnspan=2, pady=2, sticky="we") proc.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(proc) lbl = tkinter.Label(proc)
lbl["text"] = "Prozessabbild-Dump herunterladen" lbl["text"] = _("Download process image dump")
lbl.grid(column=0, row=0, **cpadw) lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(proc) btn = tkinter.Button(proc)
btn["command"] = self.getprocimg btn["command"] = self.getprocimg
btn["text"] = "Download" btn["text"] = _("Download")
btn.grid(column=1, row=0, **cpad) btn.grid(column=1, row=0, **cpad)
# Gruppe piControlReset # Gruppe piControlReset
picon = tkinter.LabelFrame(self) picon = tkinter.LabelFrame(self)
picon.columnconfigure(0, weight=1) picon.columnconfigure(0, weight=1)
picon["text"] = "piControl Reset" picon["text"] = _("Reset piControl")
picon.grid(columnspan=2, pady=2, sticky="we") picon.grid(columnspan=2, pady=2, sticky="we")
lbl = tkinter.Label(picon) lbl = tkinter.Label(picon)
lbl["text"] = "piControlReset ausführen" lbl["text"] = _("Execute piControlReset")
lbl.grid(column=0, row=0, **cpadw) lbl.grid(column=0, row=0, **cpadw)
btn = tkinter.Button(picon) btn = tkinter.Button(picon)
btn["command"] = self.picontrolreset btn["command"] = self.picontrolreset
btn["text"] = "ausführen" btn["text"] = _("execute")
btn.grid(column=1, row=0, **cpad) btn.grid(column=1, row=0, **cpad)
# Beendenbutton # Beendenbutton
btn = tkinter.Button(self) btn = tkinter.Button(self)
btn["command"] = self.master.destroy btn["command"] = self.master.destroy
btn["text"] = "Beenden" btn["text"] = _("Exit")
btn.grid() btn.grid()
def _evt_optdown(self, text=""): def _evt_optdown(self, text=""):
@@ -275,25 +294,23 @@ class RevPiProgram(tkinter.Frame):
fh = tkfd.asksaveasfile( fh = tkfd.asksaveasfile(
mode="wb", parent=self.master, mode="wb", parent=self.master,
confirmoverwrite=True, confirmoverwrite=True,
title="Speichern als...", title=_("Save as..."),
initialdir=self.opt.get("getpictoryrsc_dir", ""), initialdir=self.opt.get("getpictoryrsc_dir", ""),
initialfile=self.revpi + ".rsc", initialfile=self.revpi + ".rsc",
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) filetypes=((_("piCtory Config"), "*.rsc"), (_("All files"), "*.*"))
) )
if fh is not None: if fh is not None:
try: try:
fh.write(self.xmlcli.get_pictoryrsc().data) fh.write(self.xmlcli.get_pictoryrsc().data)
except: except:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Datei konnte nicht geladen und gespeichert " message=_("Could not load and save file!")
"werden!"
) )
else: else:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Datei erfolgreich vom Revolution Pi geladen " message=_("File successfully loaded and saved.")
"und gespeichert.",
) )
# Einstellungen speichern # Einstellungen speichern
self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name) self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name)
@@ -306,25 +323,23 @@ class RevPiProgram(tkinter.Frame):
fh = tkfd.asksaveasfile( fh = tkfd.asksaveasfile(
mode="wb", parent=self.master, mode="wb", parent=self.master,
confirmoverwrite=True, confirmoverwrite=True,
title="Speichern als...", title=_("Save as..."),
initialdir=self.opt.get("getprocimg_dir", ""), initialdir=self.opt.get("getprocimg_dir", ""),
initialfile=self.revpi + ".img", initialfile=self.revpi + ".img",
filetypes=(("Imagefiles", "*.img"), ("All Files", "*.*")) filetypes=((_("Imagefiles"), "*.img"), (_("All files"), "*.*"))
) )
if fh is not None: if fh is not None:
try: try:
fh.write(self.xmlcli.get_procimg().data) fh.write(self.xmlcli.get_procimg().data)
except: except:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Datei konnte nicht geladen und gespeichert" message=_("Could not load and save file!")
"werden!"
) )
else: else:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Datei erfolgreich vom Revolution Pi geladen " message=_("File successfully loaded and saved.")
"und gespeichert.",
) )
# Einstellungen speichern # Einstellungen speichern
self.opt["getprocimg_dir"] = os.path.dirname(fh.name) self.opt["getprocimg_dir"] = os.path.dirname(fh.name)
@@ -337,19 +352,23 @@ class RevPiProgram(tkinter.Frame):
if filename is None: if filename is None:
fh = tkfd.askopenfile( fh = tkfd.askopenfile(
mode="rb", parent=self.master, mode="rb", parent=self.master,
title="piCtory Datei öffnen...", title=_("Open piCtory file..."),
initialdir=self.opt.get("setpictoryrsc_dir", ""), initialdir=self.opt.get("setpictoryrsc_dir", ""),
initialfile=self.revpi + ".rsc", initialfile=self.revpi + ".rsc",
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*")) filetypes=(
(_("piCtory config"), "*.rsc"), (_("All files"), "*.*")
)
) )
else: else:
fh = open(filename, "rb") fh = open(filename, "rb")
if fh is not None: if fh is not None:
ask = tkmsg.askyesno( ask = tkmsg.askyesno(
parent=self.master, title="Frage", parent=self.master, title=_("Question"),
message="Soll nach dem Hochladen der piCtory Konfiguration " message=_(
"ein Reset am piControl Treiber durchgeführt werden?" "Should the piControl driver be reset after "
"uploading the piCtory configuration?"
)
) )
ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask) ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask)
@@ -357,52 +376,66 @@ class RevPiProgram(tkinter.Frame):
if ec == 0: if ec == 0:
if ask: if ask:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Die Übertragung der piCtory Konfiguration " message=_(
"und der Reset von piControl wurden erfolgreich " "The transfer of the piCtory configuration "
"ausgeführt") "and the reset of piControl have been "
"successfully executed"
)
)
else: else:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Die Übertragung der piCtory Konfiguration " message=_(
"wurde erfolgreich ausgeführt") "The piCtory configuration was "
"successfully transferred"
)
)
# Einstellungen speichern # Einstellungen speichern
self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name) self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name)
self._savedefaults() self._savedefaults()
elif ec < 0: elif ec < 0:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Die piCtory Konfiguration konnte auf dem " message=_(
"Revolution Pi nicht geschrieben werden.") "The piCtory configuration could not be "
"written on the Revolution Pi."
)
)
elif ec > 0: elif ec > 0:
tkmsg.showwarning( tkmsg.showwarning(
parent=self.master, title="Warnung", parent=self.master, title=_("Warning"),
message="Die piCtroy Konfiguration wurde erfolgreich " message=_(
"gespeichert. \nBeim piControl Reset trat allerdings ein " "The piCtroy configuration has been saved "
"Fehler auf!") "successfully. \nAn error occurred on piControl reset!"
)
)
fh.close() fh.close()
def picontrolreset(self): def picontrolreset(self):
u"""Fürt ein Reset der piBridge durch.""" u"""Fürt ein Reset der piBridge durch."""
ask = tkmsg.askyesno( ask = tkmsg.askyesno(
parent=self.master, title="Frage...", parent=self.master, title=_("Question"),
message="Soll piControlReset wirklich durchgeführt werden? \n" message=_(
"Das Prozessabbild und die Steuerung werden dann unterbrochen!!!" "Are you sure to reset piControl? \nThe process image "
"and the piBridge are interrupted !!!"
)
) )
if ask: if ask:
ec = self.xmlcli.resetpicontrol() ec = self.xmlcli.resetpicontrol()
if ec == 0: if ec == 0:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="piControlReset erfolgreich durchgeführt" message=_("piControlReset executed successfully")
) )
else: else:
tkmsg.showerror( tkmsg.showerror(
parten=self.master, title="Fehler", parten=self.master, title=_("Error"),
message="piControlReset konnte nicht erfolgreich " message=_(
"durchgeführt werden" "piControl reset could not be executed successfully"
)
) )
def plcdownload(self): def plcdownload(self):
@@ -415,7 +448,7 @@ class RevPiProgram(tkinter.Frame):
# Ordner # Ordner
dirselect = tkfd.askdirectory( dirselect = tkfd.askdirectory(
parent=self.master, parent=self.master,
title="Verzeichnis zum Ablegen", title=_("Directory to save"),
mustexist=False, mustexist=False,
initialdir=self.opt.get("plcdownload_dir", self.revpi) initialdir=self.opt.get("plcdownload_dir", self.revpi)
) )
@@ -428,10 +461,12 @@ class RevPiProgram(tkinter.Frame):
fh = tkfd.asksaveasfile( fh = tkfd.asksaveasfile(
mode="wb", parent=self.master, mode="wb", parent=self.master,
confirmoverwrite=True, confirmoverwrite=True,
title="Speichern als...", title=_("Save as..."),
initialdir=self.opt.get("plcdownload_file", ""), initialdir=self.opt.get("plcdownload_file", ""),
initialfile=self.revpi + ".zip", initialfile=self.revpi + ".zip",
filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) filetypes=(
(_("Zip archive"), "*.zip"), (_("All files"), "*.*")
)
) )
elif tdown == 2: elif tdown == 2:
@@ -439,10 +474,12 @@ class RevPiProgram(tkinter.Frame):
fh = tkfd.asksaveasfile( fh = tkfd.asksaveasfile(
mode="wb", parent=self.master, mode="wb", parent=self.master,
confirmoverwrite=True, confirmoverwrite=True,
title="Speichern als...", title=_("Save as..."),
initialdir=self.opt.get("plcdownload_file", ""), initialdir=self.opt.get("plcdownload_file", ""),
initialfile=self.revpi + ".tar.gz", initialfile=self.revpi + ".tar.gz",
filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) filetypes=(
(_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*")
)
) )
if fh is not None: if fh is not None:
@@ -480,15 +517,13 @@ class RevPiProgram(tkinter.Frame):
except: except:
raise raise
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Datei konnte nicht geladen und gespeichert " message=_("Could not load and save file!")
"werden!"
) )
else: else:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Datei erfolgreich vom Revolution Pi geladen " message=_("File successfully loaded and saved.")
"und gespeichert.",
) )
# Einstellungen speichern # Einstellungen speichern
@@ -509,9 +544,9 @@ class RevPiProgram(tkinter.Frame):
# Datei # Datei
fileselect = tkfd.askopenfilenames( fileselect = tkfd.askopenfilenames(
parent=self.master, parent=self.master,
title="Python Programm übertragen...", title="Upload Python program...",
initialdir=self.opt.get("plcupload_dir", ""), initialdir=self.opt.get("plcupload_dir", ""),
filetypes=(("Python", "*.py"), ("All Files", "*.*")) filetypes=(("Python", "*.py"), (_("All files"), "*.*"))
) )
if type(fileselect) == tuple and len(fileselect) > 0: if type(fileselect) == tuple and len(fileselect) > 0:
for file in fileselect: for file in fileselect:
@@ -521,7 +556,7 @@ class RevPiProgram(tkinter.Frame):
# Ordner # Ordner
dirselect = tkfd.askdirectory( dirselect = tkfd.askdirectory(
parent=self.master, parent=self.master,
title="Verzeichnis zum Hochladen", title=_("Folder to upload"),
mustexist=True, mustexist=True,
initialdir=self.opt.get("plcupload_dir", self.revpi) initialdir=self.opt.get("plcupload_dir", self.revpi)
) )
@@ -532,10 +567,12 @@ class RevPiProgram(tkinter.Frame):
# Zip # Zip
fileselect = tkfd.askopenfilename( fileselect = tkfd.askopenfilename(
parent=self.master, parent=self.master,
title="Zip-Archive übertragen...", title=_("Upload Zip archive..."),
initialdir=self.opt.get("plcupload_file", ""), initialdir=self.opt.get("plcupload_file", ""),
initialfile=self.revpi + ".zip", initialfile=self.revpi + ".zip",
filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*")) filetypes=(
(_("Zip archive"), "*.zip"), (_("All files"), "*.*")
)
) )
if type(fileselect) == str and fileselect != "": if type(fileselect) == str and fileselect != "":
# Zipdatei prüfen # Zipdatei prüfen
@@ -550,18 +587,21 @@ class RevPiProgram(tkinter.Frame):
else: else:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Die angegebene Datei ist kein ZIP-Archiv.") message=_("The specified file is not a ZIP archive.")
)
return False return False
elif tup == 3: elif tup == 3:
# TarGz # TarGz
fileselect = tkfd.askopenfilename( fileselect = tkfd.askopenfilename(
parent=self.master, parent=self.master,
title="TarGz-Archiv übertragen...", title=_("Upload TarGz archiv..."),
initialdir=self.opt.get("plcupload_file", ""), initialdir=self.opt.get("plcupload_file", ""),
initialfile=self.revpi + ".tar.gz", initialfile=self.revpi + ".tar.gz",
filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*")) filetypes=(
(_("TGZ archive"), "*.tar.gz"), (_("All files"), "*.*")
)
) )
if type(fileselect) == str and fileselect != "": if type(fileselect) == str and fileselect != "":
@@ -577,8 +617,9 @@ class RevPiProgram(tkinter.Frame):
else: else:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Die angegebene Datei ist kein TAR-Archiv.") message=_("The specified file is not a TAR archive.")
)
return False return False
# Wenn keine Dateien gewählt # Wenn keine Dateien gewählt
@@ -588,9 +629,12 @@ class RevPiProgram(tkinter.Frame):
# Vor Übertragung aufräumen wenn ausgewählt # Vor Übertragung aufräumen wenn ausgewählt
if self.var_cleanup.get() and not self.xmlcli.plcuploadclean(): if self.var_cleanup.get() and not self.xmlcli.plcuploadclean():
tkmsg.showerror( tkmsg.showerror(
parent=self.masger, title="Fehler", parent=self.masger, title=_("Error"),
message="Beim Löschen der Dateien auf dem Revolution Pi ist " message=_(
"ein Fehler aufgetreten.") "There was an error deleting the files on the "
"Revolution Pi."
)
)
return False return False
# Flag setzen, weil ab hier Veränderungen existieren # Flag setzen, weil ab hier Veränderungen existieren
@@ -625,17 +669,21 @@ class RevPiProgram(tkinter.Frame):
if ec == 0: if ec == 0:
tkmsg.showinfo( tkmsg.showinfo(
parent=self.master, title="Erfolgreich", parent=self.master, title=_("Success"),
message="Die Übertragung war erfolgreich.") message=_("The transfer was successful.")
)
if self.var_picup.get(): if self.var_picup.get():
if rscfile is not None: if rscfile is not None:
self.setpictoryrsc(rscfile) self.setpictoryrsc(rscfile)
else: else:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Es wurde im Archiv keine piCtory " message=_(
"Konfiguration gefunden") "There is no piCtory configuration in this "
"archive."
)
)
# Einstellungen speichern # Einstellungen speichern
if tup == 0: if tup == 0:
@@ -651,14 +699,18 @@ class RevPiProgram(tkinter.Frame):
elif ec == -1: elif ec == -1:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Der Revoluton Pi konnte Teile der Übertragung nicht " message=_(
"verarbeiten.") "The Revolution Pi could not process some parts of the "
"transmission."
)
)
elif ec == -2: elif ec == -2:
tkmsg.showerror( tkmsg.showerror(
parent=self.master, title="Fehler", parent=self.master, title=_("Error"),
message="Bei der Übertragung traten Fehler auf") message=_("Errors occurred during transmission")
)
# Temp-Dir aufräumen # Temp-Dir aufräumen
if dirtmp is not None: if dirtmp is not None:

View File

@@ -13,29 +13,15 @@ import revpioption
import revpiplclist import revpiplclist
import revpiprogram import revpiprogram
import socket import socket
import sys
import tkinter import tkinter
import tkinter.messagebox as tkmsg import tkinter.messagebox as tkmsg
from functools import partial from functools import partial
from os.path import dirname from mytools import addroot, gettrans
from os.path import join as pathjoin
from xmlrpc.client import ServerProxy from xmlrpc.client import ServerProxy
def addroot(filename): # Übersetzung laden
u"""Hängt root-dir der Anwendung vor Dateinamen. _ = gettrans()
Je nach Ausführungsart der Anwendung muss das root-dir über
andere Arten abgerufen werden.
@param filename: Datei oder Ordnername
@returns: root dir
"""
if getattr(sys, "frozen", False):
return pathjoin(dirname(sys.executable), filename)
else:
return pathjoin(dirname(__file__), filename)
class RevPiPyControl(tkinter.Frame): class RevPiPyControl(tkinter.Frame):
@@ -105,10 +91,10 @@ class RevPiPyControl(tkinter.Frame):
self.master.config(menu=self.mbar) self.master.config(menu=self.mbar)
menu1 = tkinter.Menu(self.mbar, tearoff=False) menu1 = tkinter.Menu(self.mbar, tearoff=False)
menu1.add_command(label="Connections...", command=self.plclist) menu1.add_command(label=_("Connections..."), command=self.plclist)
menu1.add_separator() menu1.add_separator()
menu1.add_command(label="Exit", command=self.master.destroy) menu1.add_command(label=_("Exit"), command=self.master.destroy)
self.mbar.add_cascade(label="Main", menu=menu1) self.mbar.add_cascade(label=_("Main"), menu=menu1)
self._fillmbar() self._fillmbar()
self._fillconnbar() self._fillconnbar()
@@ -119,22 +105,22 @@ class RevPiPyControl(tkinter.Frame):
self.txt_connect.pack(fill="x") self.txt_connect.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")
self.btn_plclogs = tkinter.Button(self) self.btn_plclogs = tkinter.Button(self)
self.btn_plclogs["text"] = "PLC Logs" self.btn_plclogs["text"] = _("PLC logs")
self.btn_plclogs["command"] = self.plclogs self.btn_plclogs["command"] = self.plclogs
self.btn_plclogs.pack(fill="x") self.btn_plclogs.pack(fill="x")
@@ -145,7 +131,7 @@ class RevPiPyControl(tkinter.Frame):
self.txt_status.pack(fill="x") self.txt_status.pack(fill="x")
self.btn_debug = tkinter.Button(self) self.btn_debug = tkinter.Button(self)
self.btn_debug["text"] = "PLC Debugmodus" self.btn_debug["text"] = _("PLC watch mode")
self.btn_debug["command"] = self.plcdebug self.btn_debug["command"] = self.plcdebug
self.btn_debug.pack(fill="x") self.btn_debug.pack(fill="x")
@@ -162,20 +148,20 @@ class RevPiPyControl(tkinter.Frame):
# PLC Menü # PLC Menü
self.mplc = tkinter.Menu(self.mbar, tearoff=False) self.mplc = tkinter.Menu(self.mbar, tearoff=False)
self.mplc.add_command( self.mplc.add_command(
label="PLC log...", command=self.plclogs) label=_("PLC log..."), command=self.plclogs)
self.mplc.add_command( self.mplc.add_command(
label="PLC options...", command=self.plcoptions) label=_("PLC options..."), command=self.plcoptions)
self.mplc.add_command( self.mplc.add_command(
label="PLC program...", command=self.plcprogram) label=_("PLC program..."), command=self.plcprogram)
self.mplc.add_separator() self.mplc.add_separator()
self.mplc.add_command( self.mplc.add_command(
label="Disconnect", command=self.serverdisconnect) label=_("Disconnect"), command=self.serverdisconnect)
self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled") self.mbar.add_cascade(label="PLC", menu=self.mplc, state="disabled")
# Connection Menü # Connection Menü
self.mconn = tkinter.Menu(self.mbar, tearoff=False) self.mconn = tkinter.Menu(self.mbar, tearoff=False)
self.mbar.add_cascade(label="Connect", menu=self.mconn) 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)
@@ -208,6 +194,16 @@ class RevPiPyControl(tkinter.Frame):
u"""Baut den Debugframe und packt ihn.""" u"""Baut den Debugframe und packt ihn."""
self.btn_debug["state"] = "disabled" self.btn_debug["state"] = "disabled"
if "psstart" not in self.xmlfuncs:
tkmsg.showwarning(
parent=self.master, title=_("Warning"),
message=_(
"The watch mode ist not supported in version {} "
"of RevPiPyLoad on your RevPi! You need at least version "
"0.4.0."
).format(self.cli.version())
)
else:
# Debugfenster laden # Debugfenster laden
if self.debugframe is None: if self.debugframe is None:
self.debugframe = revpicheckclient.RevPiCheckClient( self.debugframe = revpicheckclient.RevPiCheckClient(
@@ -249,8 +245,10 @@ class RevPiPyControl(tkinter.Frame):
if self.xmlmode < 2: if self.xmlmode < 2:
tkmsg.showwarning( tkmsg.showwarning(
parent=self.master, title="Warnung", parent=self.master, title="Warnung",
message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " message=_(
"genug eingestellt, um diesen Dialog zu verwenden!" "XML-RPC access mode in the RevPiPyLoad "
"configuration is to small to access this dialog"
)
) )
else: else:
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
@@ -266,8 +264,10 @@ class RevPiPyControl(tkinter.Frame):
if self.xmlmode < 2: if self.xmlmode < 2:
tkmsg.showwarning( tkmsg.showwarning(
parent=self.master, title="Warnung", parent=self.master, title="Warnung",
message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch " message=_(
"genug eingestellt, um diesen Dialog zu verwenden!" "XML-RPC access mode in the RevPiPyLoad "
"configuration is to small to access this dialog"
)
) )
else: else:
win = tkinter.Toplevel(self) win = tkinter.Toplevel(self)
@@ -302,20 +302,20 @@ class RevPiPyControl(tkinter.Frame):
def servererror(self): def servererror(self):
u"""Setzt alles zurück für neue Verbindungen.""" u"""Setzt alles zurück für neue Verbindungen."""
self.serverdisconnect() self.serverdisconnect()
tkmsg.showerror("Fehler", "Server ist nicht erreichbar!") tkmsg.showerror(_("Fehler"), _("Server ist nicht erreichbar!"))
def tmr_plcrunning(self): def tmr_plcrunning(self):
self._btnstate() self._btnstate()
if self.cli is None: if self.cli is None:
self.txt_status["readonlybackground"] = "lightblue" self.txt_status["readonlybackground"] = "lightblue"
self.var_status.set("NOT CONNECTED") self.var_status.set(_("NOT CONNECTED"))
else: else:
try: try:
plcec = self.cli.plcexitcode() plcec = self.cli.plcexitcode()
except: except:
self.errcount += 1 self.errcount += 1
if self.errcount >= 5: if self.errcount >= 5:
self.var_status.set("SERVER ERROR") self.var_status.set(_("SERVER ERROR"))
self.servererror() self.servererror()
else: else:
self.errcount = 0 self.errcount = 0
@@ -323,15 +323,17 @@ class RevPiPyControl(tkinter.Frame):
"green" if plcec == -1 else "red" "green" if plcec == -1 else "red"
if plcec == -1: if plcec == -1:
plcec = "RUNNING" plcec = _("RUNNING")
elif plcec == -2: elif plcec == -2:
plcec = "FILE NOT FOUND" plcec = _("FILE NOT FOUND")
elif plcec == -3:
plcec = _("NOT RUNNING (NO STATUS)")
elif plcec == -9: elif plcec == -9:
plcec = "PROGRAM KILLED" plcec = _("PROGRAM KILLED")
elif plcec == -15: elif plcec == -15:
plcec = "PROGRAMS TERMED" plcec = _("PROGRAM TERMED")
elif plcec == 0: elif plcec == 0:
plcec = "NOT RUNNING" plcec = _("NOT RUNNING")
self.var_status.set(plcec) self.var_status.set(plcec)
self.master.after(1000, self.tmr_plcrunning) self.master.after(1000, self.tmr_plcrunning)