mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-08 15:13:52 +01:00
Dateikontrolle für pictory und replace_ios per timestamp und hash Wert
Hashwerte der Dateien über RevPiNetIO abrufbar b'PH' b'RH' Alte Testfunktion für replace_ios aus helper entfernt
This commit is contained in:
@@ -31,9 +31,6 @@ Functions</h3>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#refullmatch">refullmatch</a></td>
|
||||
<td>re.fullmatch wegen alter python version aus wheezy nachgebaut.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#revpimodio_replaceio">revpimodio_replaceio</a></td>
|
||||
<td>Importiert und ersetzt IOs in RevPiModIO.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr /><hr />
|
||||
@@ -83,26 +80,5 @@ True, wenn komplett passt sonst False
|
||||
</dd>
|
||||
</dl>
|
||||
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
||||
<hr /><hr />
|
||||
<a NAME="revpimodio_replaceio" ID="revpimodio_replaceio"></a>
|
||||
<h2 style="background-color:#FFFFFF;color:#0000FF">revpimodio_replaceio</h2>
|
||||
<b>revpimodio_replaceio</b>(<i>revpi, filename</i>)
|
||||
<p>
|
||||
Importiert und ersetzt IOs in RevPiModIO.
|
||||
</p><dl>
|
||||
<dt><i>revpi</i></dt>
|
||||
<dd>
|
||||
RevPiModIO Instanz
|
||||
</dd><dt><i>filename</i></dt>
|
||||
<dd>
|
||||
Dateiname der Ersetzungsdatei
|
||||
</dd>
|
||||
</dl><dl>
|
||||
<dt>Returns:</dt>
|
||||
<dd>
|
||||
True, wenn alle IOs ersetzt werden konnten
|
||||
</dd>
|
||||
</dl>
|
||||
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
||||
<hr />
|
||||
</body></html>
|
||||
@@ -110,6 +110,12 @@ Methods</h3>
|
||||
<td><a style="color:#0000FF" href="#RevPiPyLoad._signewlogfile">_signewlogfile</a></td>
|
||||
<td>Signal handler to start new logfile.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#RevPiPyLoad.check_pictory_changed">check_pictory_changed</a></td>
|
||||
<td>Prueft ob sich die piCtory Datei veraendert hat.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#RevPiPyLoad.check_replace_ios_changed">check_replace_ios_changed</a></td>
|
||||
<td>Prueft ob sich die replace_ios.conf Datei veraendert hat (oder del).</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#RevPiPyLoad.packapp">packapp</a></td>
|
||||
<td>Erzeugt aus dem PLC-Programm ein TAR/Zip-File.</td>
|
||||
</tr><tr>
|
||||
@@ -299,7 +305,29 @@ RevPiPyLoad._signewlogfile</h3>
|
||||
<b>_signewlogfile</b>(<i>signum, frame</i>)
|
||||
<p>
|
||||
Signal handler to start new logfile.
|
||||
</p><a NAME="RevPiPyLoad.packapp" ID="RevPiPyLoad.packapp"></a>
|
||||
</p><a NAME="RevPiPyLoad.check_pictory_changed" ID="RevPiPyLoad.check_pictory_changed"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
RevPiPyLoad.check_pictory_changed</h3>
|
||||
<b>check_pictory_changed</b>(<i></i>)
|
||||
<p>
|
||||
Prueft ob sich die piCtory Datei veraendert hat.
|
||||
</p><dl>
|
||||
<dt>Returns:</dt>
|
||||
<dd>
|
||||
True, wenn veraendert wurde
|
||||
</dd>
|
||||
</dl><a NAME="RevPiPyLoad.check_replace_ios_changed" ID="RevPiPyLoad.check_replace_ios_changed"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
RevPiPyLoad.check_replace_ios_changed</h3>
|
||||
<b>check_replace_ios_changed</b>(<i></i>)
|
||||
<p>
|
||||
Prueft ob sich die replace_ios.conf Datei veraendert hat (oder del).
|
||||
</p><dl>
|
||||
<dt>Returns:</dt>
|
||||
<dd>
|
||||
True, wenn veraendert wurde
|
||||
</dd>
|
||||
</dl><a NAME="RevPiPyLoad.packapp" ID="RevPiPyLoad.packapp"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
RevPiPyLoad.packapp</h3>
|
||||
<b>packapp</b>(<i>mode="tar", pictory=False</i>)
|
||||
|
||||
@@ -4,7 +4,6 @@ helper.__license__?9
|
||||
helper._setuprt?5(pid, evt_exit)
|
||||
helper._zeroprocimg?5()
|
||||
helper.refullmatch?4(regex, string)
|
||||
helper.revpimodio_replaceio?4(revpi, filename)
|
||||
logsystem.LogReader.closeall?4()
|
||||
logsystem.LogReader.load_applog?4(start, count)
|
||||
logsystem.LogReader.load_plclog?4(start, count)
|
||||
@@ -93,6 +92,8 @@ revpipyload.RevPiPyLoad._plcthread?5()
|
||||
revpipyload.RevPiPyLoad._sigexit?5(signum, frame)
|
||||
revpipyload.RevPiPyLoad._sigloadconfig?5(signum, frame)
|
||||
revpipyload.RevPiPyLoad._signewlogfile?5(signum, frame)
|
||||
revpipyload.RevPiPyLoad.check_pictory_changed?4()
|
||||
revpipyload.RevPiPyLoad.check_replace_ios_changed?4()
|
||||
revpipyload.RevPiPyLoad.packapp?4(mode="tar", pictory=False)
|
||||
revpipyload.RevPiPyLoad.start?4()
|
||||
revpipyload.RevPiPyLoad.stop?4()
|
||||
|
||||
@@ -5,7 +5,6 @@ __copyright__ = "Copyright (C) 2018 Sven Sager"
|
||||
__license__ = "GPLv3"
|
||||
import os
|
||||
import proginit
|
||||
from configparser import ConfigParser
|
||||
from re import match as rematch
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
@@ -118,115 +117,6 @@ def _zeroprocimg():
|
||||
)
|
||||
|
||||
|
||||
def revpimodio_replaceio(revpi, filename):
|
||||
"""Importiert und ersetzt IOs in RevPiModIO.
|
||||
|
||||
@param revpi RevPiModIO Instanz
|
||||
@param filename Dateiname der Ersetzungsdatei
|
||||
@return True, wenn alle IOs ersetzt werden konnten
|
||||
|
||||
"""
|
||||
cp = ConfigParser()
|
||||
try:
|
||||
with open(filename, "r") as fh:
|
||||
cp.read_file(fh)
|
||||
except Exception as e:
|
||||
proginit.logger.error(
|
||||
"could not read replace_io file '{0}' | {1}".format(filename, e)
|
||||
)
|
||||
return False
|
||||
|
||||
# Pre-check
|
||||
lst_replace = []
|
||||
rc = True
|
||||
for io in cp:
|
||||
if io == "DEFAULT":
|
||||
continue
|
||||
|
||||
dict_replace = {
|
||||
"replace": cp[io].get("replace", ""),
|
||||
"frm": cp[io].get("frm"),
|
||||
"bmk": cp[io].get("bmk", ""),
|
||||
"byteorder": cp[io].get("byteorder", "little"),
|
||||
}
|
||||
|
||||
if dict_replace["replace"] in revpi.io:
|
||||
|
||||
# Byteorder prüfen
|
||||
if not (dict_replace["byteorder"] == "little" or
|
||||
dict_replace["byteorder"] == "big"):
|
||||
proginit.logger.error(
|
||||
"byteorder of '{0}' must be 'little' or 'big'".format(io)
|
||||
)
|
||||
rc = False
|
||||
continue
|
||||
|
||||
if dict_replace["frm"] == "?":
|
||||
|
||||
# Convert defaultvalue from config file
|
||||
try:
|
||||
dict_replace["default"] = cp[io].getboolean("defaultvalue")
|
||||
except Exception:
|
||||
proginit.logger.error(
|
||||
"could not convert '{0}' defaultvalue '{1}' to boolean"
|
||||
"".format(io, cp[io].get("defaultvalue"))
|
||||
)
|
||||
rc = False
|
||||
continue
|
||||
|
||||
# Get bitaddress
|
||||
try:
|
||||
dict_replace["bitaddress"] = cp[io].getint("bitaddress", 0)
|
||||
except Exception:
|
||||
proginit.logger.error(
|
||||
"could not convert '{0}' bitaddress '{1}' to integer"
|
||||
"".format(io, cp[io].get("bitaddress"))
|
||||
)
|
||||
rc = False
|
||||
continue
|
||||
|
||||
else:
|
||||
# Convert defaultvalue from config file
|
||||
try:
|
||||
dict_replace["default"] = cp[io].getint("defaultvalue")
|
||||
except Exception:
|
||||
proginit.logger.error(
|
||||
"could not convert '{0}' defaultvalue '{1}' to integer"
|
||||
"".format(io, cp[io].get("defaultvalue"))
|
||||
)
|
||||
rc = False
|
||||
continue
|
||||
|
||||
else:
|
||||
proginit.logger.error(
|
||||
"can not find io '{0}' to replace with '{1}'"
|
||||
"".format(dict_replace["replace"], io)
|
||||
)
|
||||
rc = False
|
||||
continue
|
||||
|
||||
# Replace_IO übernehmen
|
||||
lst_replace.append(dict_replace)
|
||||
|
||||
if not rc:
|
||||
# Abbrechen, wenn IO-Verarbeitung einen Fehler hatte
|
||||
return False
|
||||
|
||||
# Replace IOs
|
||||
for dict_replace in lst_replace:
|
||||
|
||||
# FIXME: Hier können Fehler auftreten !!!
|
||||
|
||||
revpi.io[dict_replace["replace"]].replace_io(
|
||||
io,
|
||||
frm=dict_replace["frm"],
|
||||
bmk=dict_replace["bmk"],
|
||||
bit=dict_replace["bitaddress"],
|
||||
byteorder=dict_replace["byteorder"],
|
||||
defaultvalue=dict_replace["default"]
|
||||
)
|
||||
|
||||
|
||||
def refullmatch(regex, string):
|
||||
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ __license__ = "GPLv3"
|
||||
import proginit
|
||||
import socket
|
||||
from fcntl import ioctl
|
||||
from hashlib import md5
|
||||
from shared.ipaclmanager import IpAclManager
|
||||
from threading import Event, Thread
|
||||
from timeit import default_timer
|
||||
@@ -385,6 +386,25 @@ class RevPiSlaveDev(Thread):
|
||||
# End-of-Transmission character immer senden
|
||||
self._devcon.send(b'\x04')
|
||||
|
||||
elif cmd == b'PH':
|
||||
# piCtory md5 Hashwert senden (32 Byte)
|
||||
try:
|
||||
with open(proginit.pargs.configrsc, "rb") as fh_pic:
|
||||
# Hashwert erzeugen und senden
|
||||
file_hash = md5(fh_pic.read())
|
||||
proginit.logger.debug(
|
||||
"send pictory hashvalue: {0}"
|
||||
"".format(file_hash)
|
||||
)
|
||||
self._devcon.sendall(file_hash)
|
||||
except Exception as e:
|
||||
proginit.logger.error(
|
||||
"error on pictory hash value transfair: {0}".format(e)
|
||||
)
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
elif cmd == b'RP':
|
||||
# piCtory Konfiguration senden
|
||||
proginit.logger.debug(
|
||||
@@ -408,6 +428,27 @@ class RevPiSlaveDev(Thread):
|
||||
# End-of-Transmission character immer senden
|
||||
self._devcon.send(b'\x04')
|
||||
|
||||
elif cmd == b'RH':
|
||||
# Replace_IOs md5 Hashwert senden (32 Byte)
|
||||
replace_ios = proginit.conf["DEFAULT"].get("replace_ios", None)
|
||||
try:
|
||||
with open(replace_ios, "rb") as fh:
|
||||
# Hashwert erzeugen und senden
|
||||
file_hash = md5(fh.read())
|
||||
proginit.logger.debug(
|
||||
"send replace_ios hashvalue: {0}"
|
||||
"".format(file_hash)
|
||||
)
|
||||
self._devcon.sendall(file_hash)
|
||||
except Exception as e:
|
||||
proginit.logger.error(
|
||||
"error on replace_ios hash value transfair: {0}"
|
||||
"".format(e)
|
||||
)
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
elif cmd == b'EX':
|
||||
# Sauber Verbindung verlassen
|
||||
dirty = False
|
||||
@@ -429,7 +470,6 @@ class RevPiSlaveDev(Thread):
|
||||
break
|
||||
|
||||
try:
|
||||
# FIXME: IOCTL für Dateien implementieren
|
||||
if proginit.pargs.procimg == "/dev/piControl0":
|
||||
# Läuft auf RevPi
|
||||
ioctl(fh_proc, request, arg)
|
||||
@@ -439,6 +479,7 @@ class RevPiSlaveDev(Thread):
|
||||
)
|
||||
else:
|
||||
# Simulation
|
||||
# TODO: IOCTL für Dateien implementieren
|
||||
proginit.logger.warning(
|
||||
"ioctl {0} with {1} simulated".format(request, arg)
|
||||
)
|
||||
|
||||
@@ -39,6 +39,7 @@ import signal
|
||||
import tarfile
|
||||
import zipfile
|
||||
from configparser import ConfigParser
|
||||
from hashlib import md5
|
||||
from helper import refullmatch
|
||||
from json import loads as jloads
|
||||
from shared.ipaclmanager import IpAclManager
|
||||
@@ -49,7 +50,7 @@ from time import asctime
|
||||
from xmlrpc.client import Binary
|
||||
from xrpcserver import SaveXMLRPCServer
|
||||
|
||||
min_revpimodio = "2.3.3"
|
||||
min_revpimodio = "2.4.1"
|
||||
|
||||
|
||||
class RevPiPyLoad():
|
||||
@@ -67,8 +68,6 @@ class RevPiPyLoad():
|
||||
|
||||
# Klassenattribute
|
||||
self._exit = True
|
||||
self.pictorymtime = os.path.getmtime(proginit.pargs.configrsc)
|
||||
self.replaceiosmtime = 0
|
||||
self.evt_loadconfig = Event()
|
||||
self.globalconfig = ConfigParser()
|
||||
proginit.conf = self.globalconfig
|
||||
@@ -76,6 +75,12 @@ class RevPiPyLoad():
|
||||
self.xsrv = None
|
||||
self.xml_ps = None
|
||||
|
||||
# Dateimerker
|
||||
self.pictorymtime = 0
|
||||
self.pictoryhash = b''
|
||||
self.replaceiosmtime = 0
|
||||
self.replaceiohash = b''
|
||||
|
||||
# Berechtigungsmanger
|
||||
if proginit.pargs.developermode:
|
||||
self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=9)
|
||||
@@ -233,23 +238,17 @@ class RevPiPyLoad():
|
||||
self.zeroonexit = \
|
||||
self.globalconfig["DEFAULT"].getboolean("zeroonexit", True)
|
||||
|
||||
# MTime für replace io übernehmen
|
||||
mtime = 0
|
||||
if self.replace_ios_config:
|
||||
if os.access(self.replace_ios_config, os.R_OK | os.W_OK):
|
||||
mtime = os.path.getmtime(self.replace_ios_config)
|
||||
else:
|
||||
proginit.logger.error(
|
||||
"can not access (r/w) the replace_ios file '{0}' "
|
||||
"using defaults".format(self.replace_ios_config)
|
||||
)
|
||||
self.replace_ios_config = ""
|
||||
|
||||
if self.replaceiosmtime != mtime:
|
||||
# MQTT reload erforderlich
|
||||
# Dateiveränderungen prüfen
|
||||
file_changed = False
|
||||
# Beide Funktionen müssen einmal aufgerufen werden
|
||||
if self.check_pictory_changed():
|
||||
file_changed = True
|
||||
if self.check_replace_ios_changed():
|
||||
file_changed = True
|
||||
if file_changed:
|
||||
restart_plcmqtt = True
|
||||
|
||||
self.replaceiosmtime = mtime
|
||||
restart_plcslave = True
|
||||
restart_plcprogram = True
|
||||
|
||||
# Konfiguration verarbeiten [MQTT]
|
||||
self.mqtt = 0
|
||||
@@ -597,6 +596,56 @@ class RevPiPyLoad():
|
||||
|
||||
proginit.logger.debug("leave RevPiPyLoad._signewlogfile()")
|
||||
|
||||
def check_pictory_changed(self):
|
||||
"""Prueft ob sich die piCtory Datei veraendert hat.
|
||||
@return True, wenn veraendert wurde"""
|
||||
mtime = os.path.getmtime(proginit.pargs.configrsc)
|
||||
if self.pictorymtime == mtime:
|
||||
return False
|
||||
self.pictorymtime = mtime
|
||||
|
||||
with open(proginit.pargs.configrsc, "rb") as fh:
|
||||
file_hash = md5(fh.read())
|
||||
if self.pictoryhash == file_hash:
|
||||
return False
|
||||
self.pictoryhash = file_hash
|
||||
|
||||
return True
|
||||
|
||||
def check_replace_ios_changed(self):
|
||||
"""Prueft ob sich die replace_ios.conf Datei veraendert hat (oder del).
|
||||
@return True, wenn veraendert wurde"""
|
||||
|
||||
# Zugriffsrechte prüfen (pre-check für unten)
|
||||
if self.replace_ios_config \
|
||||
and not os.access(self.replace_ios_config, os.R_OK | os.W_OK):
|
||||
proginit.logger.error(
|
||||
"can not access (r/w) the replace_ios file '{0}' "
|
||||
"using defaults".format(self.replace_ios_config)
|
||||
)
|
||||
self.replace_ios_config = ""
|
||||
|
||||
if not self.replace_ios_config:
|
||||
# Dateipfad leer, prüfen ob es vorher einen gab
|
||||
if self.replaceiosmtime > 0 or self.replaceiohash:
|
||||
self.replaceiosmtime = 0
|
||||
self.replaceiohash = b''
|
||||
return True
|
||||
|
||||
else:
|
||||
mtime = os.path.getmtime(self.replace_ios_config)
|
||||
if self.replaceiosmtime == mtime:
|
||||
return False
|
||||
self.replaceiosmtime = mtime
|
||||
|
||||
with open(self.replace_ios_config, "rb") as fh:
|
||||
file_hash = md5(fh.read())
|
||||
if self.replaceiohash == file_hash:
|
||||
return False
|
||||
self.replaceiohash = file_hash
|
||||
|
||||
return True
|
||||
|
||||
def packapp(self, mode="tar", pictory=False):
|
||||
"""Erzeugt aus dem PLC-Programm ein TAR/Zip-File.
|
||||
|
||||
@@ -672,6 +721,7 @@ class RevPiPyLoad():
|
||||
self.plc.start()
|
||||
|
||||
# mainloop
|
||||
file_changed = False
|
||||
while not self._exit:
|
||||
|
||||
# Neue Konfiguration laden
|
||||
@@ -699,21 +749,30 @@ class RevPiPyLoad():
|
||||
if self.th_plcslave is not None:
|
||||
self.th_plcslave.start()
|
||||
|
||||
# piCtory auf Veränderung prüfen
|
||||
if self.pictorymtime != os.path.getmtime(proginit.pargs.configrsc):
|
||||
# Dateiveränderungen prüfen mit beiden Funktionen!
|
||||
if self.check_pictory_changed():
|
||||
file_changed = True
|
||||
proginit.logger.warning("piCtory configuration was changed")
|
||||
self.pictorymtime = os.path.getmtime(proginit.pargs.configrsc)
|
||||
if self.check_replace_ios_changed():
|
||||
file_changed = True
|
||||
proginit.logger.warning("replace ios file was changed")
|
||||
if file_changed:
|
||||
file_changed = False
|
||||
|
||||
# Auf Dateiveränderung reagieren
|
||||
|
||||
# MQTT Publisher neu laden
|
||||
if self.mqtt and self.th_plcmqtt is not None:
|
||||
self.th_plcmqtt.reload_revpimodio()
|
||||
|
||||
# FIXME: ProcImgServer muss alle Verbindungen vernichten
|
||||
# NOTE: RevPiNetIO müsste bei Neuverbindung Hashs abfragen
|
||||
|
||||
# XML Prozessabbildserver neu laden
|
||||
if self.xml_ps is not None:
|
||||
self.xml_psstop()
|
||||
self.xml_ps.loadrevpimodio()
|
||||
# Kein psstart um Reload im Client zu erzeugen
|
||||
|
||||
self.evt_loadconfig.wait(1)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class TestSystem:
|
||||
rpi = revpimodio2.RevPiModIO(
|
||||
configrsc=proginit.pargs.configrsc,
|
||||
procimg=proginit.pargs.procimg,
|
||||
monitoring=False,
|
||||
monitoring=True,
|
||||
debug=True,
|
||||
replace_io_file=file,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user