mirror of
https://github.com/naruxde/revpipycontrol.git
synced 2025-11-08 15:43:52 +01:00
Compare commits
12 Commits
archivuplo
...
0.2.12
| Author | SHA1 | Date | |
|---|---|---|---|
| 76c45daaf7 | |||
| 6ebf8ccc0a | |||
| 92d73e9c12 | |||
| 3e2b5f66a9 | |||
| 2d04617358 | |||
| b7115ef128 | |||
| 587b7d7acb | |||
| 29249462ca | |||
| cc03ede267 | |||
| 6ef28119ad | |||
| 1adda9912b | |||
| e9648994d0 |
@@ -1,2 +1,8 @@
|
||||
syntax: glob
|
||||
*.pyc
|
||||
deb_dist/*
|
||||
dist/*
|
||||
revpipycontrol.egg-info/*
|
||||
doc/*
|
||||
deb/*
|
||||
.eric6project/*
|
||||
|
||||
5
MANIFEST.in
Normal file
5
MANIFEST.in
Normal file
@@ -0,0 +1,5 @@
|
||||
include MANIFEST.in
|
||||
include stdeb.cfg
|
||||
recursive-include data *
|
||||
recursive-include revpipycontrol *
|
||||
global-exclude *.pyc
|
||||
3
data/revpipycontrol
Normal file
3
data/revpipycontrol
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
exec "/usr/share/revpipycontrol/revpipycontrol.py" "$@"
|
||||
11
data/revpipycontrol.desktop
Normal file
11
data/revpipycontrol.desktop
Normal file
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Name=RevPi PLC Control
|
||||
Comment=Controls the Python PLC program on your RevolutionPI
|
||||
Name[de]=RevPi PLC Steuerung
|
||||
Comment[de]=Kontrolliert das Python PLC Programm auf dem RevolutionPI
|
||||
Exec=/usr/bin/revpipycontrol
|
||||
Icon=revpipycontrol
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Application;
|
||||
#StartupNotify=true
|
||||
BIN
data/revpipycontrol.ico
Normal file
BIN
data/revpipycontrol.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
data/revpipycontrol.png
Normal file
BIN
data/revpipycontrol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
79
revpipycontrol.api
Normal file
79
revpipycontrol.api
Normal file
@@ -0,0 +1,79 @@
|
||||
revpicheckclient.RevPiCheckClient._autorw?5()
|
||||
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.onfrmconf?4(canvas)
|
||||
revpicheckclient.RevPiCheckClient.readvalues?4()
|
||||
revpicheckclient.RevPiCheckClient.root?7
|
||||
revpicheckclient.RevPiCheckClient.toggleauto?4()
|
||||
revpicheckclient.RevPiCheckClient.writevalues?4()
|
||||
revpicheckclient.RevPiCheckClient?1(master, xmlcli)
|
||||
revpilogfile.RevPiLogfile._createwidgets?5()
|
||||
revpilogfile.RevPiLogfile.btn_clearapp?4()
|
||||
revpilogfile.RevPiLogfile.btn_clearplc?4()
|
||||
revpilogfile.RevPiLogfile.get_applines?4()
|
||||
revpilogfile.RevPiLogfile.get_applog?4()
|
||||
revpilogfile.RevPiLogfile.get_plclines?4()
|
||||
revpilogfile.RevPiLogfile.get_plclog?4()
|
||||
revpilogfile.RevPiLogfile?1(master, xmlcli)
|
||||
revpioption.RevPiOption._createwidgets?5()
|
||||
revpioption.RevPiOption._loadappdata?5()
|
||||
revpioption.RevPiOption._setappdata?5()
|
||||
revpioption.RevPiOption.askxmlon?4()
|
||||
revpioption.RevPiOption.xmlmods?4()
|
||||
revpioption.RevPiOption?1(master, xmlcli, xmlmode)
|
||||
revpiplclist.RevPiPlcList._createwidgets?5()
|
||||
revpiplclist.RevPiPlcList._loadappdata?5()
|
||||
revpiplclist.RevPiPlcList._saveappdata?5()
|
||||
revpiplclist.RevPiPlcList.build_listconn?4()
|
||||
revpiplclist.RevPiPlcList.evt_btnadd?4()
|
||||
revpiplclist.RevPiPlcList.evt_btnclose?4()
|
||||
revpiplclist.RevPiPlcList.evt_btnnew?4()
|
||||
revpiplclist.RevPiPlcList.evt_btnremove?4()
|
||||
revpiplclist.RevPiPlcList.evt_btnsave?4()
|
||||
revpiplclist.RevPiPlcList.evt_keypress?4(evt=None)
|
||||
revpiplclist.RevPiPlcList.evt_listconn?4(evt=None)
|
||||
revpiplclist.RevPiPlcList.myapp?7
|
||||
revpiplclist.RevPiPlcList.root?7
|
||||
revpiplclist.RevPiPlcList?1(master)
|
||||
revpiplclist.get_connections?4()
|
||||
revpiplclist.savefile?7
|
||||
revpiprogram.RevPiProgram._createwidgets?5()
|
||||
revpiprogram.RevPiProgram._evt_optdown?5(text="")
|
||||
revpiprogram.RevPiProgram._evt_optup?5(text="")
|
||||
revpiprogram.RevPiProgram._loaddefault?5(full=False)
|
||||
revpiprogram.RevPiProgram._savedefaults?5()
|
||||
revpiprogram.RevPiProgram.check_replacedir?4(rootdir)
|
||||
revpiprogram.RevPiProgram.create_filelist?4(rootdir)
|
||||
revpiprogram.RevPiProgram.getpictoryrsc?4()
|
||||
revpiprogram.RevPiProgram.getprocimg?4()
|
||||
revpiprogram.RevPiProgram.myapp?7
|
||||
revpiprogram.RevPiProgram.picontrolreset?4()
|
||||
revpiprogram.RevPiProgram.plcdownload?4()
|
||||
revpiprogram.RevPiProgram.plcupload?4()
|
||||
revpiprogram.RevPiProgram.root?7
|
||||
revpiprogram.RevPiProgram.setpictoryrsc?4(filename=None)
|
||||
revpiprogram.RevPiProgram?1(master, xmlcli, xmlmode, revpi)
|
||||
revpiprogram.savefile?7
|
||||
revpipycontrol.RevPiPyControl._btnstate?5()
|
||||
revpipycontrol.RevPiPyControl._closeall?5()
|
||||
revpipycontrol.RevPiPyControl._createwidgets?5()
|
||||
revpipycontrol.RevPiPyControl._fillconnbar?5()
|
||||
revpipycontrol.RevPiPyControl._fillmbar?5()
|
||||
revpipycontrol.RevPiPyControl._opt_conn?5(text)
|
||||
revpipycontrol.RevPiPyControl.myapp?7
|
||||
revpipycontrol.RevPiPyControl.plclist?4()
|
||||
revpipycontrol.RevPiPyControl.plclogs?4()
|
||||
revpipycontrol.RevPiPyControl.plcmonitor?4()
|
||||
revpipycontrol.RevPiPyControl.plcoptions?4()
|
||||
revpipycontrol.RevPiPyControl.plcprogram?4()
|
||||
revpipycontrol.RevPiPyControl.plcrestart?4()
|
||||
revpipycontrol.RevPiPyControl.plcstart?4()
|
||||
revpipycontrol.RevPiPyControl.plcstop?4()
|
||||
revpipycontrol.RevPiPyControl.root?7
|
||||
revpipycontrol.RevPiPyControl.servererror?4()
|
||||
revpipycontrol.RevPiPyControl.tmr_plcrunning?4()
|
||||
revpipycontrol.RevPiPyControl?1(master=None)
|
||||
revpipycontrol.addroot?4(filename)
|
||||
6
revpipycontrol.bas
Normal file
6
revpipycontrol.bas
Normal file
@@ -0,0 +1,6 @@
|
||||
RevPiCheckClient tkinter.Frame
|
||||
RevPiLogfile tkinter.Frame
|
||||
RevPiOption tkinter.Frame
|
||||
RevPiPlcList tkinter.Frame
|
||||
RevPiProgram tkinter.Frame
|
||||
RevPiPyControl tkinter.Frame
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
|
||||
<!-- eric project file for project revpipycontrol -->
|
||||
<!-- Saved: 2017-03-09, 20:23:30 -->
|
||||
<!-- Saved: 2017-04-11, 12:38:06 -->
|
||||
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
|
||||
<Project version="5.1">
|
||||
<Language>en_US</Language>
|
||||
@@ -9,12 +9,11 @@
|
||||
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
||||
<ProjectType>Console</ProjectType>
|
||||
<Description></Description>
|
||||
<Version>0.2.1</Version>
|
||||
<Version>0.2.12</Version>
|
||||
<Author>Sven Sager</Author>
|
||||
<Email>akira@narux.de</Email>
|
||||
<Eol index="-1"/>
|
||||
<Sources>
|
||||
<Source>revpipycontrol/__init__.py</Source>
|
||||
<Source>revpipycontrol/revpipycontrol.py</Source>
|
||||
<Source>revpipycontrol/revpicheckclient.py</Source>
|
||||
<Source>setup.py</Source>
|
||||
@@ -27,7 +26,11 @@
|
||||
<Translations/>
|
||||
<Resources/>
|
||||
<Interfaces/>
|
||||
<Others/>
|
||||
<Others>
|
||||
<Other>data</Other>
|
||||
<Other>doc</Other>
|
||||
<Other>revpipycontrol.api</Other>
|
||||
</Others>
|
||||
<MainScript>revpipycontrol/revpipycontrol.py</MainScript>
|
||||
<Vcs>
|
||||
<VcsType>Mercurial</VcsType>
|
||||
@@ -142,6 +145,122 @@
|
||||
<FiletypeAssociation pattern="*.pyw" type="SOURCES"/>
|
||||
<FiletypeAssociation pattern="*.pyw3" type="SOURCES"/>
|
||||
</FiletypeAssociations>
|
||||
<Documentation>
|
||||
<DocumentationParams>
|
||||
<dict>
|
||||
<key>
|
||||
<string>ERIC4API</string>
|
||||
</key>
|
||||
<value>
|
||||
<dict>
|
||||
<key>
|
||||
<string>ignoreDirectories</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>data</string>
|
||||
<string>deb</string>
|
||||
<string>dist</string>
|
||||
<string>doc</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>ignoreFilePatterns</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>setup.py</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>includePrivate</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>True</bool>
|
||||
</value>
|
||||
<key>
|
||||
<string>languages</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>Python3</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>outputFile</string>
|
||||
</key>
|
||||
<value>
|
||||
<string>revpipycontrol.api</string>
|
||||
</value>
|
||||
<key>
|
||||
<string>useRecursion</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>True</bool>
|
||||
</value>
|
||||
</dict>
|
||||
</value>
|
||||
<key>
|
||||
<string>ERIC4DOC</string>
|
||||
</key>
|
||||
<value>
|
||||
<dict>
|
||||
<key>
|
||||
<string>ignoreDirectories</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>data</string>
|
||||
<string>deb</string>
|
||||
<string>dist</string>
|
||||
<string>doc</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>ignoreFilePatterns</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>setup.py</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>noindex</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>True</bool>
|
||||
</value>
|
||||
<key>
|
||||
<string>outputDirectory</string>
|
||||
</key>
|
||||
<value>
|
||||
<string>doc</string>
|
||||
</value>
|
||||
<key>
|
||||
<string>qtHelpEnabled</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>False</bool>
|
||||
</value>
|
||||
<key>
|
||||
<string>sourceExtensions</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string></string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>useRecursion</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>True</bool>
|
||||
</value>
|
||||
</dict>
|
||||
</value>
|
||||
</dict>
|
||||
</DocumentationParams>
|
||||
</Documentation>
|
||||
<Checkers>
|
||||
<CheckersParams>
|
||||
<dict>
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-scrollbar-to-a-group-of-widgets-in-tkinter
|
||||
#
|
||||
# RevPiPyControl
|
||||
#
|
||||
# Webpage: https://revpimodio.org/revpipyplc/
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
# Thranks to: http://stackoverflow.com/questions/3085696/adding-a-
|
||||
# scrollbar-to-a-group-of-widgets-in-tkinter
|
||||
|
||||
import pickle
|
||||
import tkinter
|
||||
@@ -10,28 +17,13 @@ from xmlrpc.client import ServerProxy, Binary, MultiCall
|
||||
|
||||
class RevPiCheckClient(tkinter.Frame):
|
||||
|
||||
def __init__(self, master, xmlcli=None):
|
||||
def __init__(self, master, xmlcli):
|
||||
"""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
|
||||
|
||||
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 = {}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
import pickle
|
||||
import tkinter
|
||||
|
||||
|
||||
@@ -21,21 +22,42 @@ class RevPiLogfile(tkinter.Frame):
|
||||
def _createwidgets(self):
|
||||
self.master.wm_title("RevPi Python PLC Logs")
|
||||
|
||||
self.rowconfigure(0, weight=0)
|
||||
self.rowconfigure(1, weight=1)
|
||||
self.columnconfigure(0, weight=1)
|
||||
self.columnconfigure(1, weight=0)
|
||||
self.columnconfigure(2, weight=0)
|
||||
self.columnconfigure(3, weight=1)
|
||||
self.columnconfigure(4, weight=0)
|
||||
self.columnconfigure(5, weight=0)
|
||||
|
||||
# PLC Log
|
||||
self.lblapplog = tkinter.Label(self)
|
||||
self.lblapplog["text"] = "RevPyPyLoad - Logfile"
|
||||
self.lblapplog.grid(column=0, row=0, sticky="w")
|
||||
self.btnapplog = tkinter.Button(self)
|
||||
self.btnapplog["command"] = self.btn_clearplc
|
||||
self.btnapplog["text"] = "Clear screen"
|
||||
self.btnapplog.grid(column=1, row=0, sticky="e")
|
||||
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["state"] = "disabled"
|
||||
self.plclog.grid(sticky="wnse", columnspan=2, column=0, row=1)
|
||||
self.plcscr.grid(sticky="ns", column=2, row=1)
|
||||
self.plclog["yscrollcommand"] = self.plcscr.set
|
||||
self.plcscr["command"] = self.plclog.yview
|
||||
|
||||
# APP Log
|
||||
self.lblapplog = tkinter.Label(self)
|
||||
self.lblapplog["text"] = "Python PLC program - Logfile"
|
||||
self.lblapplog.grid(column=3, row=0, sticky="w")
|
||||
self.btnapplog = tkinter.Button(self)
|
||||
self.btnapplog["command"] = self.btn_clearapp
|
||||
self.btnapplog["text"] = "Clear screen"
|
||||
self.btnapplog.grid(column=4, row=0, sticky="e")
|
||||
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["state"] = "disabled"
|
||||
self.applog.grid(sticky="nesw", columnspan=2, column=3, row=1)
|
||||
self.appscr.grid(sticky="ns", column=5, row=1)
|
||||
self.applog["yscrollcommand"] = self.appscr.set
|
||||
self.appscr["command"] = self.applog.yview
|
||||
|
||||
@@ -46,28 +68,40 @@ class RevPiLogfile(tkinter.Frame):
|
||||
self.master.after(1000, self.get_applines)
|
||||
self.master.after(1000, self.get_plclines)
|
||||
|
||||
def btn_clearapp(self):
|
||||
self.applog.delete(1.0, tkinter.END)
|
||||
|
||||
def btn_clearplc(self):
|
||||
self.plclog.delete(1.0, tkinter.END)
|
||||
|
||||
def get_applines(self):
|
||||
roll = self.applog.yview()[1] == 1.0
|
||||
for line in self.xmlcli.get_applines():
|
||||
self.applog.insert(tkinter.END, line)
|
||||
try:
|
||||
for line in pickle.loads(self.xmlcli.get_applines().data):
|
||||
self.applog.insert(tkinter.END, line)
|
||||
except:
|
||||
pass
|
||||
if roll:
|
||||
self.applog.see(tkinter.END)
|
||||
self.master.after(1000, self.get_applines)
|
||||
|
||||
def get_applog(self):
|
||||
self.applog.delete(1.0, tkinter.END)
|
||||
self.applog.insert(1.0, self.xmlcli.get_applog())
|
||||
self.applog.insert(1.0, pickle.loads(self.xmlcli.get_applog().data))
|
||||
self.applog.see(tkinter.END)
|
||||
|
||||
def get_plclines(self):
|
||||
roll = self.plclog.yview()[1] == 1.0
|
||||
for line in self.xmlcli.get_plclines():
|
||||
self.plclog.insert(tkinter.END, line)
|
||||
try:
|
||||
for line in pickle.loads(self.xmlcli.get_plclines().data):
|
||||
self.plclog.insert(tkinter.END, line)
|
||||
except:
|
||||
pass
|
||||
if roll:
|
||||
self.plclog.see(tkinter.END)
|
||||
self.master.after(1000, self.get_plclines)
|
||||
|
||||
def get_plclog(self):
|
||||
self.plclog.delete(1.0, tkinter.END)
|
||||
self.plclog.insert(1.0, self.xmlcli.get_plclog())
|
||||
self.plclog.insert(1.0, pickle.loads(self.xmlcli.get_plclog().data))
|
||||
self.plclog.see(tkinter.END)
|
||||
|
||||
@@ -11,18 +11,23 @@ import tkinter.messagebox as tkmsg
|
||||
|
||||
class RevPiOption(tkinter.Frame):
|
||||
|
||||
def __init__(self, master, xmlcli):
|
||||
def __init__(self, master, xmlcli, xmlmode):
|
||||
if xmlmode < 2:
|
||||
return None
|
||||
|
||||
super().__init__(master)
|
||||
self.pack(expand=True, fill="both")
|
||||
|
||||
self.xmlcli = xmlcli
|
||||
self.xmlmode = xmlmode
|
||||
self.xmlstate = "normal" if xmlmode == 3 else "disabled"
|
||||
|
||||
# Fenster bauen
|
||||
self._createwidgets()
|
||||
self._loadappdata()
|
||||
|
||||
def _createwidgets(self):
|
||||
self.master.wm_title("RevPi Python PLC Connections")
|
||||
self.master.wm_title("RevPi Python PLC Options")
|
||||
self.master.wm_resizable(width=False, height=False)
|
||||
|
||||
cpadw = {"padx": 4, "pady": 2, "sticky": "w"}
|
||||
@@ -40,45 +45,85 @@ class RevPiOption(tkinter.Frame):
|
||||
|
||||
ckb_start = tkinter.Checkbutton(stst)
|
||||
ckb_start["text"] = "Programm automatisch starten"
|
||||
ckb_start["state"] = self.xmlstate
|
||||
ckb_start["variable"] = self.var_start
|
||||
ckb_start.grid(**cpadw)
|
||||
|
||||
ckb_reload = tkinter.Checkbutton(stst)
|
||||
ckb_reload["text"] = "Programm nach Absturz neustarten"
|
||||
ckb_reload["text"] = "Programm nach Beenden neu starten"
|
||||
ckb_reload["state"] = self.xmlstate
|
||||
ckb_reload["variable"] = self.var_reload
|
||||
ckb_reload.grid(**cpadw)
|
||||
|
||||
ckb_zexit = tkinter.Checkbutton(stst, justify="left")
|
||||
ckb_zexit["text"] = "Prozessabbild auf NULL setzen, wenn "
|
||||
"Programm\nerfolgreich beendet wird"
|
||||
ckb_zexit["state"] = self.xmlstate
|
||||
ckb_zexit["text"] = "Prozessabbild auf NULL setzen, wenn " \
|
||||
"Programm\nerfolgreich beendet wird"
|
||||
ckb_zexit["variable"] = self.var_zexit
|
||||
ckb_zexit.grid(**cpadw)
|
||||
|
||||
ckb_zerr = tkinter.Checkbutton(stst, justify="left")
|
||||
ckb_zerr["text"] = "Prozessabbild auf NULL setzen, wenn "
|
||||
"Programm\ndurch Absturz beendet wird"
|
||||
ckb_zerr["state"] = self.xmlstate
|
||||
ckb_zerr["text"] = "Prozessabbild auf NULL setzen, wenn " \
|
||||
"Programm\ndurch Absturz beendet wird"
|
||||
ckb_zerr["variable"] = self.var_zerr
|
||||
ckb_zerr.grid(**cpadw)
|
||||
|
||||
# Gruppe Programm
|
||||
prog = tkinter.LabelFrame(self)
|
||||
prog["text"] = "Programm"
|
||||
prog["text"] = "PLC Programm"
|
||||
prog.grid(columnspan=2, pady=2, sticky="we")
|
||||
|
||||
self.var_pythonver = tkinter.IntVar(prog)
|
||||
self.var_startpy = tkinter.StringVar(prog)
|
||||
self.var_startargs = tkinter.StringVar(prog)
|
||||
self.var_slave = tkinter.BooleanVar(prog)
|
||||
|
||||
self.var_pythonver.set(3)
|
||||
|
||||
lbl = tkinter.Label(prog)
|
||||
lbl["text"] = "Python Version"
|
||||
lbl.grid(columnspan=2, row=0, **cpadw)
|
||||
rbn = tkinter.Radiobutton(prog)
|
||||
rbn["state"] = self.xmlstate
|
||||
rbn["text"] = "Python2"
|
||||
rbn["value"] = 2
|
||||
rbn["variable"] = self.var_pythonver
|
||||
rbn.grid(column=0, row=1, **cpadw)
|
||||
|
||||
rbn = tkinter.Radiobutton(prog)
|
||||
rbn["state"] = self.xmlstate
|
||||
rbn["text"] = "Python3"
|
||||
rbn["value"] = 3
|
||||
rbn["variable"] = self.var_pythonver
|
||||
rbn.grid(column=1, row=1, **cpadw)
|
||||
|
||||
lbl = tkinter.Label(prog)
|
||||
lbl["text"] = "Python PLC Programname"
|
||||
lbl.grid(**cpadw)
|
||||
# txt_startpy = tkinter.Entry(prog)
|
||||
# txt_startpy["textvariable"] = self.var_startpy
|
||||
# txt_startpy.grid(**cpadwe)
|
||||
lbl.grid(columnspan=2, **cpadw)
|
||||
|
||||
lst = self.xmlcli.get_filelist()
|
||||
if len(lst) == 0:
|
||||
lst.append("none")
|
||||
opt_startpy = tkinter.OptionMenu(
|
||||
prog, self.var_startpy, *self.xmlcli.get_filelist())
|
||||
opt_startpy.grid(**cpadwe)
|
||||
prog, self.var_startpy, *lst)
|
||||
opt_startpy["state"] = self.xmlstate
|
||||
opt_startpy.grid(columnspan=2, **cpadwe)
|
||||
|
||||
lbl = tkinter.Label(prog)
|
||||
lbl["text"] = "Programm Argumente"
|
||||
lbl.grid(columnspan=2, **cpadw)
|
||||
|
||||
txt = tkinter.Entry(prog)
|
||||
txt["textvariable"] = self.var_startargs
|
||||
txt.grid(columnspan=2, **cpadw)
|
||||
|
||||
ckb_slave = tkinter.Checkbutton(prog, justify="left")
|
||||
ckb_slave["state"] = self.xmlstate
|
||||
ckb_slave["text"] = "RevPi als PLC-Slave verwenden"
|
||||
ckb_slave["state"] = "disabled"
|
||||
ckb_slave["variable"] = self.var_slave
|
||||
ckb_slave.grid(**cpadw)
|
||||
ckb_slave.grid(columnspan=2, **cpadw)
|
||||
|
||||
# Gruppe XMLRPC
|
||||
xmlrpc = tkinter.LabelFrame(self)
|
||||
@@ -86,26 +131,48 @@ class RevPiOption(tkinter.Frame):
|
||||
xmlrpc.grid(columnspan=2, pady=2, sticky="we")
|
||||
|
||||
self.var_xmlon = tkinter.BooleanVar(xmlrpc)
|
||||
self.var_xmlmod2 = tkinter.BooleanVar(xmlrpc)
|
||||
self.var_xmlmod3 = tkinter.BooleanVar(xmlrpc)
|
||||
self.var_xmlport = tkinter.StringVar(xmlrpc)
|
||||
self.var_xmlport.set("55123")
|
||||
|
||||
ckb_xmlon = tkinter.Checkbutton(xmlrpc)
|
||||
ckb_xmlon["command"] = self.askxmlon
|
||||
ckb_xmlon["state"] = self.xmlstate
|
||||
ckb_xmlon["text"] = "XML-RPC Server aktiv auf RevPi"
|
||||
ckb_xmlon["variable"] = self.var_xmlon
|
||||
ckb_xmlon.grid(**cpadw)
|
||||
|
||||
self.ckb_xmlmod2 = tkinter.Checkbutton(xmlrpc, justify="left")
|
||||
self.ckb_xmlmod2["command"] = self.xmlmods
|
||||
self.ckb_xmlmod2["state"] = self.xmlstate
|
||||
self.ckb_xmlmod2["text"] = \
|
||||
"Download von piCtory Konfiguration und\nPLC Programm zulassen"
|
||||
self.ckb_xmlmod2["variable"] = self.var_xmlmod2
|
||||
self.ckb_xmlmod2.grid(**cpadw)
|
||||
|
||||
self.ckb_xmlmod3 = tkinter.Checkbutton(xmlrpc, justify="left")
|
||||
self.ckb_xmlmod3["state"] = self.xmlstate
|
||||
self.ckb_xmlmod3["text"] = \
|
||||
"Upload von piCtory Konfiguration und\nPLC Programm zualssen"
|
||||
self.ckb_xmlmod3["variable"] = self.var_xmlmod3
|
||||
self.ckb_xmlmod3.grid(**cpadw)
|
||||
|
||||
lbl = tkinter.Label(xmlrpc)
|
||||
lbl["text"] = "XML-RPC Serverport"
|
||||
lbl.grid(**cpadw)
|
||||
|
||||
spb_xmlport = tkinter.Spinbox(xmlrpc)
|
||||
spb_xmlport["to"] = 65535
|
||||
spb_xmlport["from"] = 1024
|
||||
spb_xmlport["state"] = self.xmlstate
|
||||
spb_xmlport["textvariable"] = self.var_xmlport
|
||||
spb_xmlport.grid(**cpadwe)
|
||||
|
||||
# Buttons
|
||||
btn_save = tkinter.Button(self)
|
||||
btn_save["command"] = self._setappdata
|
||||
btn_save["state"] = self.xmlstate
|
||||
btn_save["text"] = "Speichern"
|
||||
btn_save.grid(column=0, row=3)
|
||||
|
||||
@@ -117,16 +184,21 @@ class RevPiOption(tkinter.Frame):
|
||||
def _loadappdata(self):
|
||||
dc = self.xmlcli.get_config()
|
||||
|
||||
self.var_start.set(dc["autostart"])
|
||||
self.var_reload.set(dc["autoreload"])
|
||||
self.var_zexit.set(dc["zeroonexit"])
|
||||
self.var_zerr.set(dc["zeroonerror"])
|
||||
self.var_start.set(dc.get("autostart", "1"))
|
||||
self.var_reload.set(dc.get("autoreload", "1"))
|
||||
self.var_zexit.set(dc.get("zeroonexit", "0"))
|
||||
self.var_zerr.set(dc.get("zeroonerror", "0"))
|
||||
|
||||
self.var_startpy.set(dc["plcprogram"])
|
||||
self.var_slave.set(dc["plcslave"])
|
||||
self.var_startpy.set(dc.get("plcprogram", "none.py"))
|
||||
self.var_startargs.set(dc.get("plcarguments", ""))
|
||||
self.var_pythonver.set(dc.get("pythonversion", "3"))
|
||||
self.var_slave.set(dc.get("plcslave", "0"))
|
||||
|
||||
self.var_xmlon.set(dc["xmlrpc"])
|
||||
self.var_xmlport.set(dc["xmlrpcport"])
|
||||
self.var_xmlon.set(dc.get("xmlrpc", 0) >= 1)
|
||||
self.var_xmlmod2.set(dc.get("xmlrpc", 0) >= 2)
|
||||
self.var_xmlmod3.set(dc.get("xmlrpc", 0) >= 3)
|
||||
|
||||
self.var_xmlport.set(dc.get("xmlrpcport", "55123"))
|
||||
|
||||
def _setappdata(self):
|
||||
dc = {}
|
||||
@@ -136,29 +208,54 @@ class RevPiOption(tkinter.Frame):
|
||||
dc["zeroonerror"] = int(self.var_zerr.get())
|
||||
|
||||
dc["plcprogram"] = self.var_startpy.get()
|
||||
dc["plcarguments"] = self.var_startargs.get()
|
||||
dc["pythonversion"] = self.var_pythonver.get()
|
||||
dc["plcslave"] = int(self.var_slave.get())
|
||||
|
||||
dc["xmlrpc"] = int(self.var_xmlon.get())
|
||||
dc["xmlrpc"] = 0
|
||||
if self.var_xmlon.get():
|
||||
dc["xmlrpc"] += 1
|
||||
if self.var_xmlmod2.get():
|
||||
dc["xmlrpc"] += 1
|
||||
if self.var_xmlmod3.get():
|
||||
dc["xmlrpc"] += 1
|
||||
|
||||
dc["xmlrpcport"] = self.var_xmlport.get()
|
||||
self.xmlmode = dc["xmlrpc"]
|
||||
|
||||
ask = tkmsg.askyesnocancel(
|
||||
"Frage", "Die Einstellungen werden jetzt auf den Revolution Pi "
|
||||
"Frage", "Die Einstellungen werden jetzt auf dem Revolution Pi "
|
||||
"gespeichert. \n\nSollen die neuen Einstellungen sofort in Kraft "
|
||||
"treten? \nDies bedeutet einen Neustart des Dienstes und des ggf. "
|
||||
"laufenden PLC-Programms!", parent=self.master
|
||||
)
|
||||
if ask is not None:
|
||||
self.xmlcli.set_config(dc, ask)
|
||||
tkmsg.showinfo(
|
||||
"Information", "Einstellungen gespeichert.", parent=self.master
|
||||
)
|
||||
if self.xmlcli.set_config(dc, ask):
|
||||
tkmsg.showinfo(
|
||||
"Information", "Einstellungen gespeichert.",
|
||||
parent=self.master
|
||||
)
|
||||
else:
|
||||
tkmsg.showerror(
|
||||
"Fehler", "Die Einstellungen konnten nicht gesichert"
|
||||
"werden. Dies kann passieren, wenn Werte falsch sind!",
|
||||
parent=self.master
|
||||
)
|
||||
|
||||
def askxmlon(self):
|
||||
if not self.var_xmlon.get():
|
||||
ask = tkmsg.askyesno(
|
||||
"Frage", "Soll der XML-RPC Server wirklich beendet werden? "
|
||||
"Sie können dann mit diesem Programm NICHT mehr auf den "
|
||||
"Sie können dann NICHT mehr mit diesem Programm auf den "
|
||||
"Revolution Pi zugreifen.", parent=self.master
|
||||
)
|
||||
if not ask:
|
||||
self.var_xmlon.set(True)
|
||||
|
||||
self.xmlmods()
|
||||
|
||||
def xmlmods(self):
|
||||
self.ckb_xmlmod2["state"] = \
|
||||
"normal" if self.var_xmlon.get() else "disabled"
|
||||
self.ckb_xmlmod3["state"] = \
|
||||
"normal" if self.var_xmlmod2.get() else "disabled"
|
||||
|
||||
@@ -21,11 +21,14 @@ else:
|
||||
savefile = os.path.join(homedir, ".revpipyplc", "connections.dat")
|
||||
|
||||
|
||||
# Für andere Module zum Laden der Connections
|
||||
def get_connections():
|
||||
if os.path.exists(savefile):
|
||||
fh = open(savefile, "rb")
|
||||
connections = pickle.load(fh)
|
||||
return connections
|
||||
return connections
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
class RevPiPlcList(tkinter.Frame):
|
||||
@@ -34,6 +37,8 @@ class RevPiPlcList(tkinter.Frame):
|
||||
super().__init__(master)
|
||||
self.pack()
|
||||
|
||||
self.changes = False
|
||||
|
||||
# Daten laden
|
||||
self._connections = {}
|
||||
|
||||
@@ -115,6 +120,7 @@ class RevPiPlcList(tkinter.Frame):
|
||||
makedirs(os.path.dirname(savefile), exist_ok=True)
|
||||
fh = open(savefile, "wb")
|
||||
pickle.dump(self._connections, fh)
|
||||
self.changes = False
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
@@ -131,14 +137,18 @@ class RevPiPlcList(tkinter.Frame):
|
||||
|
||||
self.build_listconn()
|
||||
self.evt_btnnew()
|
||||
self.changes = True
|
||||
|
||||
def evt_btnclose(self):
|
||||
ask = tkmsg.askyesno(
|
||||
"Frage...",
|
||||
"Wollen Sie wirklich beenden?\n"
|
||||
"Nicht gespeicherte Änderungen gehen verloren",
|
||||
parent=self.master
|
||||
)
|
||||
if self.changes:
|
||||
ask = tkmsg.askyesno(
|
||||
parent=self.master, title="Frage...",
|
||||
message="Wollen Sie wirklich beenden?\n"
|
||||
"Nicht gespeicherte Änderungen gehen verloren",
|
||||
)
|
||||
else:
|
||||
ask = True
|
||||
|
||||
if ask:
|
||||
self.master.destroy()
|
||||
|
||||
@@ -166,6 +176,7 @@ class RevPiPlcList(tkinter.Frame):
|
||||
del self._connections[item]
|
||||
self.build_listconn()
|
||||
self.evt_btnnew()
|
||||
self.changes = True
|
||||
|
||||
def evt_btnsave(self):
|
||||
if self._saveappdata():
|
||||
|
||||
@@ -5,19 +5,36 @@
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
import gzip
|
||||
import os
|
||||
import pickle
|
||||
import tarfile
|
||||
import tkinter
|
||||
import tkinter.filedialog as tkfd
|
||||
import tkinter.messagebox as tkmsg
|
||||
import zipfile
|
||||
from tempfile import mktemp
|
||||
from os import environ
|
||||
from os import makedirs
|
||||
from shutil import rmtree
|
||||
from sys import platform
|
||||
from tempfile import mktemp, mkdtemp
|
||||
from xmlrpc.client import Binary
|
||||
|
||||
|
||||
# Systemwerte
|
||||
if platform == "linux":
|
||||
homedir = environ["HOME"]
|
||||
else:
|
||||
homedir = environ["APPDATA"]
|
||||
savefile = os.path.join(homedir, ".revpipyplc", "programpath.dat")
|
||||
|
||||
|
||||
class RevPiProgram(tkinter.Frame):
|
||||
|
||||
def __init__(self, master, xmlcli, revpi):
|
||||
def __init__(self, master, xmlcli, xmlmode, revpi):
|
||||
if xmlmode < 2:
|
||||
return None
|
||||
|
||||
super().__init__(master)
|
||||
# master.protocol("WM_DELETE_WINDOW", self._checkclose)
|
||||
self.pack(expand=True, fill="both")
|
||||
@@ -25,6 +42,11 @@ class RevPiProgram(tkinter.Frame):
|
||||
self.uploaded = False
|
||||
self.revpi = revpi
|
||||
self.xmlcli = xmlcli
|
||||
self.xmlmode = xmlmode
|
||||
self.xmlstate = "normal" if xmlmode == 3 else "disabled"
|
||||
|
||||
# Letzte Einstellungen übernehmen
|
||||
self.opt = self._loaddefault()
|
||||
|
||||
# Fenster bauen
|
||||
self._createwidgets()
|
||||
@@ -54,7 +76,7 @@ class RevPiProgram(tkinter.Frame):
|
||||
# Gruppe Programm
|
||||
prog = tkinter.LabelFrame(self)
|
||||
prog.columnconfigure(0, weight=1)
|
||||
prog["text"] = "PLC Pythonprogramm"
|
||||
prog["text"] = "PLC Python programm"
|
||||
prog.grid(columnspan=2, pady=2, sticky="we")
|
||||
|
||||
# Variablen vorbereiten
|
||||
@@ -66,8 +88,10 @@ class RevPiProgram(tkinter.Frame):
|
||||
|
||||
self.lst_typedown = ["Dateien", "Zip Archiv", "TGZ Archiv"]
|
||||
self.lst_typeup = ["Dateien", "Ordner", "Zip Archiv", "TGZ Archiv"]
|
||||
self.var_typedown.set(self.lst_typedown[0])
|
||||
self.var_typeup.set(self.lst_typeup[0])
|
||||
self.var_picdown.set(self.opt.get("picdown", 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]))
|
||||
|
||||
r = 0
|
||||
lbl = tkinter.Label(prog)
|
||||
@@ -96,22 +120,26 @@ class RevPiProgram(tkinter.Frame):
|
||||
opt = tkinter.OptionMenu(
|
||||
prog, self.var_typeup, *self.lst_typeup,
|
||||
command=self._evt_optup)
|
||||
opt["state"] = self.xmlstate
|
||||
opt["width"] = 10
|
||||
opt.grid(column=1, row=r, **cpad)
|
||||
|
||||
r = 3
|
||||
ckb = tkinter.Checkbutton(prog)
|
||||
ckb["state"] = self.xmlstate
|
||||
ckb["text"] = "vorher alles im Uploadverzeichnis löschen"
|
||||
ckb["variable"] = self.var_cleanup
|
||||
ckb.grid(column=0, row=r, columnspan=2, **cpadw)
|
||||
|
||||
r = 4
|
||||
self.ckb_picup = tkinter.Checkbutton(prog)
|
||||
self.ckb_picup["state"] = self.xmlstate
|
||||
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["state"] = self.xmlstate
|
||||
btn["text"] = "Upload"
|
||||
btn.grid(column=1, row=r, **cpad)
|
||||
|
||||
@@ -133,6 +161,7 @@ class RevPiProgram(tkinter.Frame):
|
||||
lbl.grid(column=0, row=1, **cpadw)
|
||||
btn = tkinter.Button(picto)
|
||||
btn["command"] = self.setpictoryrsc
|
||||
btn["state"] = self.xmlstate
|
||||
btn["text"] = "Upload"
|
||||
btn.grid(column=1, row=1, **cpad)
|
||||
|
||||
@@ -142,13 +171,26 @@ class RevPiProgram(tkinter.Frame):
|
||||
proc["text"] = "piControl0 Prozessabbild"
|
||||
proc.grid(columnspan=2, pady=2, sticky="we")
|
||||
lbl = tkinter.Label(proc)
|
||||
lbl["text"] = "Prozessabbild herunterladen"
|
||||
lbl["text"] = "Prozessabbild-Dump 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)
|
||||
|
||||
# Gruppe piControlReset
|
||||
picon = tkinter.LabelFrame(self)
|
||||
picon.columnconfigure(0, weight=1)
|
||||
picon["text"] = "piControl Reset"
|
||||
picon.grid(columnspan=2, pady=2, sticky="we")
|
||||
lbl = tkinter.Label(picon)
|
||||
lbl["text"] = "piControlReset ausführen"
|
||||
lbl.grid(column=0, row=0, **cpadw)
|
||||
btn = tkinter.Button(picon)
|
||||
btn["command"] = self.picontrolreset
|
||||
btn["text"] = "ausführen"
|
||||
btn.grid(column=1, row=0, **cpad)
|
||||
|
||||
# Beendenbutton
|
||||
btn = tkinter.Button(self)
|
||||
btn["command"] = self.master.destroy
|
||||
@@ -169,19 +211,70 @@ class RevPiProgram(tkinter.Frame):
|
||||
else:
|
||||
self.ckb_picup["state"] = "normal"
|
||||
|
||||
def _loaddefault(self):
|
||||
# TODO: letzte Einstellungen laden
|
||||
pass
|
||||
def _loaddefault(self, full=False):
|
||||
"""Uebernimmt fuer den Pi die letzen Pfade."""
|
||||
if os.path.exists(savefile):
|
||||
fh = open(savefile, "rb")
|
||||
dict_all = pickle.load(fh)
|
||||
if full:
|
||||
return dict_all
|
||||
else:
|
||||
return dict_all.get(self.revpi, {})
|
||||
return {}
|
||||
|
||||
def _savedefaults(self):
|
||||
# TODO: Einstellungen sichern
|
||||
pass
|
||||
"""Schreibt fuer den Pi die letzen Pfade."""
|
||||
try:
|
||||
makedirs(os.path.dirname(savefile), exist_ok=True)
|
||||
dict_all = self._loaddefault(full=True)
|
||||
dict_all[self.revpi] = self.opt
|
||||
fh = open(savefile, "wb")
|
||||
pickle.dump(dict_all, fh)
|
||||
self.changes = False
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def create_filelist(self, rootdir):
|
||||
"""Erstellt eine Dateiliste von einem Verzeichnis.
|
||||
@param rootdir: Verzeichnis fuer das eine Liste erstellt werden soll
|
||||
@returns: Dateiliste"""
|
||||
filelist = []
|
||||
for tup_dir in os.walk(rootdir):
|
||||
for fname in tup_dir[2]:
|
||||
filelist.append(os.path.join(tup_dir[0], fname))
|
||||
return filelist
|
||||
|
||||
def check_replacedir(self, 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.
|
||||
@param rootdir: Verzeichnis fuer Pruefung
|
||||
@returns: Abgeaendertes rootdir
|
||||
|
||||
"""
|
||||
lst_dir = os.listdir(rootdir)
|
||||
if len(lst_dir) == 1 and \
|
||||
os.path.isdir(os.path.join(rootdir, lst_dir[0])):
|
||||
return (os.path.join(rootdir, lst_dir[0]), None)
|
||||
|
||||
if len(lst_dir) == 2:
|
||||
rscfile = None
|
||||
for fname in lst_dir:
|
||||
if fname.find(".rsc"):
|
||||
rscfile = os.path.join(rootdir, fname)
|
||||
return (os.path.join(rootdir, lst_dir[0]), rscfile)
|
||||
|
||||
else:
|
||||
return (rootdir, None)
|
||||
|
||||
def getpictoryrsc(self):
|
||||
fh = tkfd.asksaveasfile(
|
||||
mode="wb", parent=self.master,
|
||||
confirmoverwrite=True,
|
||||
title="Speichern als...",
|
||||
initialdir=self.opt.get("getpictoryrsc_dir", ""),
|
||||
initialfile=self.revpi + ".rsc",
|
||||
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*"))
|
||||
)
|
||||
@@ -200,6 +293,9 @@ class RevPiProgram(tkinter.Frame):
|
||||
message="Datei erfolgreich vom Revolution Pi geladen "
|
||||
"und gespeichert.",
|
||||
)
|
||||
# Einstellungen speichern
|
||||
self.opt["getpictoryrsc_dir"] = os.path.dirname(fh.name)
|
||||
self._savedefaults()
|
||||
finally:
|
||||
fh.close()
|
||||
|
||||
@@ -208,6 +304,7 @@ class RevPiProgram(tkinter.Frame):
|
||||
mode="wb", parent=self.master,
|
||||
confirmoverwrite=True,
|
||||
title="Speichern als...",
|
||||
initialdir=self.opt.get("getprocimg_dir", ""),
|
||||
initialfile=self.revpi + ".img",
|
||||
filetypes=(("Imagefiles", "*.img"), ("All Files", "*.*"))
|
||||
)
|
||||
@@ -226,26 +323,33 @@ class RevPiProgram(tkinter.Frame):
|
||||
message="Datei erfolgreich vom Revolution Pi geladen "
|
||||
"und gespeichert.",
|
||||
)
|
||||
# Einstellungen speichern
|
||||
self.opt["getprocimg_dir"] = os.path.dirname(fh.name)
|
||||
self._savedefaults()
|
||||
finally:
|
||||
fh.close()
|
||||
|
||||
def setpictoryrsc(self, fh=None):
|
||||
if fh is None:
|
||||
def setpictoryrsc(self, filename=None):
|
||||
if filename is None:
|
||||
fh = tkfd.askopenfile(
|
||||
mode="rb", parent=self.master,
|
||||
title="piCtory Datei öffnen...",
|
||||
initialdir=self.opt.get("setpictoryrsc_dir", ""),
|
||||
initialfile=self.revpi + ".rsc",
|
||||
filetypes=(("piCtory Config", "*.rsc"), ("All Files", "*.*"))
|
||||
)
|
||||
else:
|
||||
fh = open(filename, "rb")
|
||||
|
||||
if fh is not None:
|
||||
ask = tkmsg.askyesno(
|
||||
parent=self.master, title="Frage",
|
||||
message="Soll nach dem Hochladen der piCtory Konfiguration "
|
||||
"ein reset am piControl Treiber durchgeführt werden?"
|
||||
"ein Reset am piControl Treiber durchgeführt werden?"
|
||||
)
|
||||
|
||||
ec = self.xmlcli.set_pictoryrsc(Binary(fh.read()), ask)
|
||||
print(ec)
|
||||
if ec == 0:
|
||||
if ask:
|
||||
tkmsg.showinfo(
|
||||
@@ -258,6 +362,10 @@ class RevPiProgram(tkinter.Frame):
|
||||
parent=self.master, title="Erfolgreich",
|
||||
message="Die Übertragung der piCtory Konfiguration "
|
||||
"wurde erfolgreich ausgeführt")
|
||||
|
||||
#Einstellungen speichern
|
||||
self.opt["setpictoryrsc_dir"] = os.path.dirname(fh.name)
|
||||
self._savedefaults()
|
||||
elif ec < 0:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
@@ -272,6 +380,26 @@ class RevPiProgram(tkinter.Frame):
|
||||
|
||||
fh.close()
|
||||
|
||||
def picontrolreset(self):
|
||||
ask = tkmsg.askyesno(
|
||||
parent=self.master, title="Frage...",
|
||||
message="Soll piControlReset wirklich durchgeführt werden? \n"
|
||||
"Das Prozessabbild und die Steuerung werden dann unterbrochen!!!"
|
||||
)
|
||||
if ask:
|
||||
ec = self.xmlcli.resetpicontrol()
|
||||
if ec == 0:
|
||||
tkmsg.showinfo(
|
||||
parent=self.master, title="Erfolgreich",
|
||||
message="piControlReset erfolgreich durchgeführt"
|
||||
)
|
||||
else:
|
||||
tkmsg.showerror(
|
||||
parten=self.master, title="Fehler",
|
||||
message="piControlReset konnte nicht erfolgreich "
|
||||
"durchgeführt werden"
|
||||
)
|
||||
|
||||
def plcdownload(self):
|
||||
tdown = self.lst_typedown.index(self.var_typedown.get())
|
||||
fh = None
|
||||
@@ -280,8 +408,11 @@ class RevPiProgram(tkinter.Frame):
|
||||
if tdown == 0:
|
||||
# Ordner
|
||||
dirselect = tkfd.askdirectory(
|
||||
parent=self.master, title="Verzeichnis zum Ablegen",
|
||||
mustexist=False, initialdir=self.revpi)
|
||||
parent=self.master,
|
||||
title="Verzeichnis zum Ablegen",
|
||||
mustexist=False,
|
||||
initialdir=self.opt.get("plcdownload_dir", self.revpi)
|
||||
)
|
||||
|
||||
if type(dirselect) == str and dirselect != "":
|
||||
fh = open(mktemp(), "wb")
|
||||
@@ -292,6 +423,7 @@ class RevPiProgram(tkinter.Frame):
|
||||
mode="wb", parent=self.master,
|
||||
confirmoverwrite=True,
|
||||
title="Speichern als...",
|
||||
initialdir=self.opt.get("plcdownload_file", ""),
|
||||
initialfile=self.revpi + ".zip",
|
||||
filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*"))
|
||||
)
|
||||
@@ -302,6 +434,7 @@ class RevPiProgram(tkinter.Frame):
|
||||
mode="wb", parent=self.master,
|
||||
confirmoverwrite=True,
|
||||
title="Speichern als...",
|
||||
initialdir=self.opt.get("plcdownload_file", ""),
|
||||
initialfile=self.revpi + ".tar.gz",
|
||||
filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*"))
|
||||
)
|
||||
@@ -327,10 +460,16 @@ class RevPiProgram(tkinter.Frame):
|
||||
for taritem in fh_pack.getmembers():
|
||||
print(rootname)
|
||||
if not taritem.name == "revpipyload":
|
||||
taritem.name = taritem.name.replace("revpipyload/", "")
|
||||
taritem.name = \
|
||||
taritem.name.replace("revpipyload/", "")
|
||||
fh_pack.extract(taritem, dirselect)
|
||||
|
||||
fh_pack.close()
|
||||
self.opt["plcdownload_dir"] = dirselect
|
||||
else:
|
||||
self.opt["plcdownload_file"] = os.path.dirname(fh.name)
|
||||
self.opt["typedown"] = self.var_typedown.get()
|
||||
self.opt["picdown"] = self.var_picdown.get()
|
||||
|
||||
except:
|
||||
raise
|
||||
@@ -345,162 +484,178 @@ class RevPiProgram(tkinter.Frame):
|
||||
message="Datei erfolgreich vom Revolution Pi geladen "
|
||||
"und gespeichert.",
|
||||
)
|
||||
|
||||
# Einstellungen speichern
|
||||
self._savedefaults()
|
||||
finally:
|
||||
fh.close()
|
||||
|
||||
def plcupload(self):
|
||||
tup = self.lst_typeup.index(self.var_typeup.get())
|
||||
fh = None
|
||||
dirselect = ""
|
||||
dirtmp = None
|
||||
filelist = []
|
||||
fileselect = None
|
||||
rscfile = None
|
||||
|
||||
if tup == 0:
|
||||
# Datei
|
||||
fileselect = tkfd.askopenfilenames(
|
||||
parent=self.master, title="Pythonprogramm übertragen...",
|
||||
parent=self.master,
|
||||
title="Python Programm übertragen...",
|
||||
initialdir=self.opt.get("plcupload_dir", ""),
|
||||
filetypes=(("Python", "*.py"), ("All Files", "*.*"))
|
||||
)
|
||||
if type(fileselect) == tuple and len(fileselect) > 0:
|
||||
# Datei als TAR packen
|
||||
tmpfile = mktemp()
|
||||
noerr = True
|
||||
|
||||
try:
|
||||
fh_pack = tarfile.open(
|
||||
name=tmpfile, mode="w:gz", dereference=True)
|
||||
for file in fileselect:
|
||||
fh_pack.add(
|
||||
file, arcname=os.path.basename(file))
|
||||
except:
|
||||
noerr = False
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Die Datei konnte für die Übertragung nicht "
|
||||
"gepackt werden")
|
||||
finally:
|
||||
fh_pack.close()
|
||||
|
||||
if noerr:
|
||||
# fh für Versand öffnen
|
||||
fh = open(tmpfile, "rb")
|
||||
for file in fileselect:
|
||||
filelist.append(file)
|
||||
|
||||
elif tup == 1:
|
||||
# Ordner
|
||||
dirselect = tkfd.askdirectory(
|
||||
parent=self.master, title="Verzeichnis zum Hochladen",
|
||||
mustexist=True, initialdir=self.revpi)
|
||||
|
||||
parent=self.master,
|
||||
title="Verzeichnis zum Hochladen",
|
||||
mustexist=True,
|
||||
initialdir=self.opt.get("plcupload_dir", self.revpi)
|
||||
)
|
||||
if type(dirselect) == str and dirselect != "":
|
||||
# Ordner als TAR packen
|
||||
tmpfile = mktemp()
|
||||
noerr = True
|
||||
|
||||
try:
|
||||
fh_pack = tarfile.open(
|
||||
name=tmpfile, mode="w:gz", dereference=True)
|
||||
fh_pack.add(
|
||||
#dirselect, arcname=os.path.basename(dirselect))
|
||||
dirselect, arcname="")
|
||||
except:
|
||||
noerr = False
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Der Ordner konnte für die Übertragung nicht "
|
||||
"gepackt werden")
|
||||
finally:
|
||||
fh_pack.close()
|
||||
|
||||
if noerr:
|
||||
# fh für Versand öffnen
|
||||
fh = open(tmpfile, "rb")
|
||||
filelist = self.create_filelist(dirselect)
|
||||
|
||||
elif tup == 2:
|
||||
# Zip
|
||||
fh = tkfd.askopenfile(
|
||||
mode="rb", parent=self.master,
|
||||
fileselect = tkfd.askopenfilename(
|
||||
parent=self.master,
|
||||
title="Zip-Archive übertragen...",
|
||||
initialdir=self.opt.get("plcupload_file", ""),
|
||||
initialfile=self.revpi + ".zip",
|
||||
filetypes=(("Zip Archiv", "*.zip"), ("All Files", "*.*"))
|
||||
)
|
||||
if not zipfile.is_zipfile(fh.name):
|
||||
if type(fileselect) == str and fileselect != "":
|
||||
# Zipdatei prüfen
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Die angegebene Datei ist kein ZIP-Archiv.")
|
||||
fh.close()
|
||||
fh = None
|
||||
if zipfile.is_zipfile(fileselect):
|
||||
dirtmp = mkdtemp()
|
||||
fhz = zipfile.ZipFile(fileselect)
|
||||
fhz.extractall(dirtmp)
|
||||
fhz.close()
|
||||
|
||||
filelist = self.create_filelist(dirtmp)
|
||||
dirselect, rscfile = self.check_replacedir(dirtmp)
|
||||
|
||||
else:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Die angegebene Datei ist kein ZIP-Archiv.")
|
||||
return False
|
||||
|
||||
elif tup == 3:
|
||||
# TarGz
|
||||
fh = tkfd.askopenfile(
|
||||
mode="rb", parent=self.master,
|
||||
fileselect = tkfd.askopenfilename(
|
||||
parent=self.master,
|
||||
title="TarGz-Archiv übertragen...",
|
||||
initialdir=self.opt.get("plcupload_file", ""),
|
||||
initialfile=self.revpi + ".tar.gz",
|
||||
filetypes=(("Tar Archiv", "*.tar.gz"), ("All Files", "*.*"))
|
||||
)
|
||||
if not tarfile.is_tarfile(fh.name):
|
||||
# Zipdatei prüfen
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Die angegebene Datei ist kein TAR-Archiv.")
|
||||
fh.close()
|
||||
fh = None
|
||||
if type(fileselect) == str and fileselect != "":
|
||||
|
||||
# Wenn kein fh existiert abbrachen
|
||||
if fh is None:
|
||||
return False
|
||||
# Tar-Datei prüfen
|
||||
if tarfile.is_tarfile(fileselect):
|
||||
dirtmp = mkdtemp()
|
||||
fht = tarfile.open(fileselect)
|
||||
fht.extractall(dirtmp)
|
||||
fht.close()
|
||||
|
||||
filelist = self.create_filelist(dirtmp)
|
||||
dirselect, rscfile = self.check_replacedir(dirtmp)
|
||||
|
||||
else:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Die angegebene Datei ist kein TAR-Archiv.")
|
||||
return False
|
||||
|
||||
# Wenn keine Dateien gewählt
|
||||
if len(filelist) == 0:
|
||||
return True
|
||||
|
||||
# Vor Übertragung aufräumen wenn ausgewählt
|
||||
if self.var_cleanup.get() and not self.xmlcli.plcuploadclean():
|
||||
tkmsg.showerror(
|
||||
parent=self.masger, title="Fehler",
|
||||
parent=self.masger, title="Fehler",
|
||||
message="Beim Löschen der Dateien auf dem Revolution Pi ist "
|
||||
"ein Fehler aufgetreten.")
|
||||
return False
|
||||
|
||||
# Flag setzen, weil ab hier Veränderungen existieren
|
||||
self.uploaded = True
|
||||
ec = 0
|
||||
|
||||
for fname in filelist:
|
||||
|
||||
# Archiv prüfen und umpacken
|
||||
if tup >= 2:
|
||||
# TODO: Archive umpacken
|
||||
pass
|
||||
if fname == rscfile:
|
||||
continue
|
||||
|
||||
# TODO: Fehlerabfang bei Dateilesen
|
||||
with open(fname, "rb") as fh:
|
||||
|
||||
# piControlReset abfragen
|
||||
if self.var_picup.get():
|
||||
pass
|
||||
# Dateinamen ermitteln
|
||||
if dirselect == "":
|
||||
sendname = os.path.basename(fname)
|
||||
else:
|
||||
sendname = fname.replace(dirselect, "")[1:]
|
||||
|
||||
# Datei übertragen
|
||||
try:
|
||||
ustatus = self.xmlcli.plcupload(
|
||||
Binary(gzip.compress(fh.read())), sendname)
|
||||
except:
|
||||
ec = -2
|
||||
break
|
||||
|
||||
if not ustatus:
|
||||
ec = -1
|
||||
break
|
||||
|
||||
# TODO: Fehlerabfang bei Dateilesen
|
||||
xmldata = Binary(fh.read())
|
||||
ec = self.xmlcli.plcupload(xmldata)
|
||||
|
||||
if ec == 0:
|
||||
tkmsg.showinfo(
|
||||
parent=self.master, title="Erfolgreich",
|
||||
message="Die Übertragung war erfolgreich.")
|
||||
elif ec > 0:
|
||||
tkmsg.showwarning(
|
||||
parent=self.master, title="Warnung",
|
||||
message="Die Übertragung war erfolgreich. \n"
|
||||
"Beim piControl Reset trat allerdings ein Fehler auf!")
|
||||
|
||||
if self.var_picup.get():
|
||||
if rscfile is not None:
|
||||
self.setpictoryrsc(rscfile)
|
||||
else:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Es wurde im Archiv keine piCtory "
|
||||
"Konfiguration gefunden")
|
||||
|
||||
# Einstellungen speichern
|
||||
if tup == 0:
|
||||
self.opt["plcupload_dir"] = os.path.dirname(fileselect[0])
|
||||
elif tup == 1:
|
||||
self.opt["plcupload_dir"] = dirselect
|
||||
else:
|
||||
self.opt["plcupload_file"] = os.path.dirname(fileselect)
|
||||
|
||||
self.opt["typeup"] = self.var_typeup.get()
|
||||
self.opt["picup"] = self.var_picup.get()
|
||||
self._savedefaults()
|
||||
|
||||
elif ec == -1:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Der Revoluton Pi konnte die übertragene Datei nicht "
|
||||
message="Der Revoluton Pi konnte Teile der Übertragung nicht "
|
||||
"verarbeiten.")
|
||||
elif ec < -1:
|
||||
tkmsg.showwarning(
|
||||
parent=self.master, title="Warnung",
|
||||
message="Die Übertragung war erfolgreich. \n"
|
||||
"Beim verarbeiten der piCtory Konfiguration trat allerdings "
|
||||
"ein Fehler auf!")
|
||||
|
||||
fh.close()
|
||||
elif ec == -2:
|
||||
tkmsg.showerror(
|
||||
parent=self.master, title="Fehler",
|
||||
message="Bei der Übertragung traten Fehler auf")
|
||||
|
||||
# Temp-File aufräumen
|
||||
if tup <= 1:
|
||||
os.remove(fh.name)
|
||||
# Temp-Dir aufräumen
|
||||
if dirtmp is not None:
|
||||
rmtree(dirtmp)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
BIN
revpipycontrol/revpipycontrol.png
Normal file
BIN
revpipycontrol/revpipycontrol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
122
revpipycontrol/revpipycontrol.py
Normal file → Executable file
122
revpipycontrol/revpipycontrol.py
Normal file → Executable file
@@ -1,24 +1,40 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# RevPiPyControl
|
||||
# Version: 0.2.1
|
||||
# Version: 0.2.12
|
||||
#
|
||||
# Webpage: https://revpimodio.org/revpipyplc/
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
import revpicheckclient
|
||||
import revpilogfile
|
||||
import revpioption
|
||||
import revpiplclist
|
||||
import revpiprogram
|
||||
import socket
|
||||
import sys
|
||||
import tkinter
|
||||
import tkinter.messagebox as tkmsg
|
||||
from functools import partial
|
||||
from os.path import dirname
|
||||
from os.path import join as pathjoin
|
||||
from xmlrpc.client import ServerProxy
|
||||
|
||||
socket.setdefaulttimeout(3)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class RevPiPyControl(tkinter.Frame):
|
||||
@@ -29,7 +45,14 @@ class RevPiPyControl(tkinter.Frame):
|
||||
|
||||
self.cli = None
|
||||
self.dict_conn = revpiplclist.get_connections()
|
||||
self.errcount = 0
|
||||
self.revpiname = None
|
||||
self.xmlmode = 0
|
||||
|
||||
# Globale Fenster
|
||||
self.tklogs = None
|
||||
self.tkoptions = None
|
||||
self.tkprogram = None
|
||||
|
||||
# Fenster aufbauen
|
||||
self._createwidgets()
|
||||
@@ -48,6 +71,9 @@ class RevPiPyControl(tkinter.Frame):
|
||||
"""Erstellt den Fensterinhalt."""
|
||||
# Hauptfenster
|
||||
self.master.wm_title("RevPi Python PLC Loader")
|
||||
self.master.wm_iconphoto(
|
||||
True, tkinter.PhotoImage(file=addroot("revpipycontrol.png"))
|
||||
)
|
||||
self.master.wm_resizable(width=False, height=False)
|
||||
|
||||
# Menü ganz oben
|
||||
@@ -98,7 +124,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")
|
||||
@@ -115,6 +141,7 @@ class RevPiPyControl(tkinter.Frame):
|
||||
)
|
||||
|
||||
def _opt_conn(self, text):
|
||||
socket.setdefaulttimeout(2)
|
||||
sp = ServerProxy(
|
||||
"http://{}:{}".format(
|
||||
self.dict_conn[text][0], int(self.dict_conn[text][1])
|
||||
@@ -122,17 +149,31 @@ class RevPiPyControl(tkinter.Frame):
|
||||
)
|
||||
# Server prüfen
|
||||
try:
|
||||
sp.system.listMethods()
|
||||
self.xmlmode = sp.xmlmodus()
|
||||
except:
|
||||
self.servererror()
|
||||
else:
|
||||
self.cli = sp
|
||||
self._closeall()
|
||||
socket.setdefaulttimeout(15)
|
||||
self.cli = ServerProxy(
|
||||
"http://{}:{}".format(
|
||||
self.dict_conn[text][0], int(self.dict_conn[text][1])
|
||||
)
|
||||
)
|
||||
self.revpiname = text
|
||||
self.var_conn.set("{} - {}:{}".format(
|
||||
text, self.dict_conn[text][0], int(self.dict_conn[text][1])
|
||||
))
|
||||
self.mbar.entryconfig("PLC", state="normal")
|
||||
|
||||
def _closeall(self):
|
||||
if self.tklogs is not None:
|
||||
self.tklogs.master.destroy()
|
||||
if self.tkoptions is not None:
|
||||
self.tkoptions.destroy()
|
||||
if self.tkprogram is not None:
|
||||
self.tkprogram.destroy()
|
||||
|
||||
def plclist(self):
|
||||
win = tkinter.Toplevel(self)
|
||||
revpiplclist.RevPiPlcList(win)
|
||||
@@ -143,29 +184,46 @@ class RevPiPyControl(tkinter.Frame):
|
||||
self._fillconnbar()
|
||||
|
||||
def plclogs(self):
|
||||
# TODO: nicht doppelt starten
|
||||
win = tkinter.Toplevel(self)
|
||||
self.tklogs = revpilogfile.RevPiLogfile(win, self.cli)
|
||||
if self.tklogs is None or len(self.tklogs.children) == 0:
|
||||
win = tkinter.Toplevel(self)
|
||||
self.tklogs = revpilogfile.RevPiLogfile(win, self.cli)
|
||||
else:
|
||||
self.tklogs.focus_set()
|
||||
|
||||
def plcmonitor(self):
|
||||
# TODO: Monitorfenster
|
||||
#self.tkmonitor = revpicheckclient.RevPiCheckClient(self.master, self.cli)
|
||||
pass
|
||||
|
||||
def plcoptions(self):
|
||||
win = tkinter.Toplevel(self)
|
||||
revpioption.RevPiOption(win, self.cli)
|
||||
win.focus_set()
|
||||
win.grab_set()
|
||||
self.wait_window(win)
|
||||
if self.xmlmode < 2:
|
||||
tkmsg.showwarning(
|
||||
parent=self.master, title="Warnung",
|
||||
message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch "
|
||||
"genug eingestellt, um diesen Dialog zu verwenden!"
|
||||
)
|
||||
else:
|
||||
win = tkinter.Toplevel(self)
|
||||
self.tkoptions = \
|
||||
revpioption.RevPiOption(win, self.cli, self.xmlmode)
|
||||
win.focus_set()
|
||||
win.grab_set()
|
||||
self.wait_window(win)
|
||||
self.xmlmode = self.tkoptions.xmlmode
|
||||
|
||||
def plcprogram(self):
|
||||
# TODO: Programfenster
|
||||
win = tkinter.Toplevel(self)
|
||||
revpiprogram.RevPiProgram(win, self.cli, self.revpiname)
|
||||
win.focus_set()
|
||||
win.grab_set()
|
||||
self.wait_window(win)
|
||||
if self.xmlmode < 2:
|
||||
tkmsg.showwarning(
|
||||
parent=self.master, title="Warnung",
|
||||
message="Der XML-RPC Modus ist beim RevPiPyLoad nicht hoch "
|
||||
"genug eingestellt, um diesen Dialog zu verwenden!"
|
||||
)
|
||||
else:
|
||||
win = tkinter.Toplevel(self)
|
||||
self.tkprogram = revpiprogram.RevPiProgram(
|
||||
win, self.cli, self.xmlmode, self.revpiname)
|
||||
win.focus_set()
|
||||
win.grab_set()
|
||||
self.wait_window(win)
|
||||
|
||||
def plcstart(self):
|
||||
self.cli.plcstart()
|
||||
@@ -178,10 +236,13 @@ class RevPiPyControl(tkinter.Frame):
|
||||
self.cli.plcstart()
|
||||
|
||||
def servererror(self):
|
||||
"""Setzt alles auf NULL."""
|
||||
socket.setdefaulttimeout(2)
|
||||
self.cli = None
|
||||
self._btnstate()
|
||||
self.mbar.entryconfig("PLC", state="disabled")
|
||||
self.var_conn.set("")
|
||||
self._closeall()
|
||||
tkmsg.showerror("Fehler", "Server ist nicht erreichbar!")
|
||||
|
||||
def tmr_plcrunning(self):
|
||||
@@ -191,20 +252,25 @@ class RevPiPyControl(tkinter.Frame):
|
||||
self.var_status.set("NOT CONNECTED")
|
||||
else:
|
||||
try:
|
||||
if self.cli.plcrunning():
|
||||
self.txt_status["readonlybackground"] = "green"
|
||||
else:
|
||||
self.txt_status["readonlybackground"] = "red"
|
||||
|
||||
plcec = self.cli.plcexitcode()
|
||||
except:
|
||||
self.var_status.set("SERVER ERROR")
|
||||
self.servererror()
|
||||
self.errcount += 1
|
||||
if self.errcount >= 5:
|
||||
self.var_status.set("SERVER ERROR")
|
||||
self.servererror()
|
||||
else:
|
||||
self.errcount = 0
|
||||
self.txt_status["readonlybackground"] = \
|
||||
"green" if plcec == -1 else "red"
|
||||
|
||||
if plcec == -1:
|
||||
plcec = "RUNNING"
|
||||
elif plcec == -2:
|
||||
plcec = "FILE NOT FOUND"
|
||||
elif plcec == -9:
|
||||
plcec = "PROGRAM KILLED"
|
||||
elif plcec == -15:
|
||||
plcec = "PROGRAMS TERMED"
|
||||
elif plcec == 0:
|
||||
plcec = "NOT RUNNING"
|
||||
self.var_status.set(plcec)
|
||||
|
||||
90
setup.py
Normal file
90
setup.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Setupscript fuer RevPiPyLoad."""
|
||||
import distutils.command.install_egg_info
|
||||
from sys import platform
|
||||
from glob import glob
|
||||
|
||||
|
||||
class MyEggInfo(distutils.command.install_egg_info.install_egg_info):
|
||||
|
||||
u"""Disable egg_info installation, seems pointless for a non-library."""
|
||||
|
||||
def run(self):
|
||||
u"""just pass egg_info."""
|
||||
pass
|
||||
|
||||
|
||||
globsetup = {
|
||||
"author": "Sven Sager",
|
||||
"author_email": "akira@narux.de",
|
||||
"url": "https://revpimodio.org/revpipyplc/",
|
||||
"license": "LGPLv3",
|
||||
"version": "0.2.12",
|
||||
|
||||
"name": "revpipycontrol",
|
||||
|
||||
"description": "PLC Loader für Python-Projekte auf den RevolutionPi",
|
||||
"long_description": ""
|
||||
"Dieses Programm startet beim Systemstart ein angegebenes Python PLC\n"
|
||||
"Programm. Es überwacht das Programm und startet es im Fehlerfall neu.\n"
|
||||
"Bei Abstruz kann das gesamte /dev/piControl0 auf 0x00 gesettz werden.\n"
|
||||
"Außerdem stellt es einen XML-RPC Server bereit, über den die Software\n"
|
||||
"auf den RevPi geladen werden kann. Das Prozessabbild kann über ein Tool\n"
|
||||
"zur Laufzeit überwacht werden.",
|
||||
}
|
||||
|
||||
if platform == "linux":
|
||||
from setuptools import setup
|
||||
setup(
|
||||
maintainer="Sven Sager",
|
||||
maintainer_email="akira@revpimodio.org",
|
||||
|
||||
scripts=["data/revpipycontrol"],
|
||||
|
||||
data_files=[
|
||||
("share/applications", ["data/revpipycontrol.desktop"]),
|
||||
("share/icons/hicolor/32x32/apps", ["data/revpipycontrol.png"]),
|
||||
("share/revpipycontrol", glob("revpipycontrol/*.*")),
|
||||
],
|
||||
|
||||
install_requires=["tkinter"],
|
||||
|
||||
classifiers=[
|
||||
"License :: OSI Approved :: "
|
||||
"GNU Lesser General Public License v3 (LGPLv3)",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
],
|
||||
cmdclass={"install_egg_info": MyEggInfo},
|
||||
**globsetup
|
||||
)
|
||||
|
||||
elif platform == "win32":
|
||||
import sys
|
||||
from cx_Freeze import setup, Executable
|
||||
|
||||
sys.path.append("revpipycontrol")
|
||||
|
||||
exe = Executable(
|
||||
script="revpipycontrol/revpipycontrol.py",
|
||||
base="Win32GUI",
|
||||
compress=False,
|
||||
copyDependentFiles=True,
|
||||
appendScriptToExe=True,
|
||||
appendScriptToLibrary=False,
|
||||
icon="data/revpipycontrol.ico"
|
||||
)
|
||||
|
||||
setup(
|
||||
options={"build_exe": {
|
||||
"include_files": [
|
||||
"revpipycontrol/revpipycontrol.png",
|
||||
# "m4server/locale"
|
||||
]
|
||||
}},
|
||||
executables=[exe],
|
||||
**globsetup
|
||||
)
|
||||
Reference in New Issue
Block a user