mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-08 23:23:52 +01:00
Helpermodul angelegt und Funktionen darauf umgestellt
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
<?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 revpipyload -->
|
<!-- eric project file for project revpipyload -->
|
||||||
<!-- Saved: 2017-12-03, 15:22:22 -->
|
<!-- Saved: 2018-03-08, 10:30:46 -->
|
||||||
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
|
<!-- Copyright (C) 2018 Sven Sager, akira@narux.de -->
|
||||||
<Project version="5.1">
|
<Project version="5.1">
|
||||||
<Language>en_US</Language>
|
<Language>en_US</Language>
|
||||||
<Hash>89ddb4e70b339f832ee277085202b38acc6a125c</Hash>
|
<Hash>89ddb4e70b339f832ee277085202b38acc6a125c</Hash>
|
||||||
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
||||||
<ProjectType>Console</ProjectType>
|
<ProjectType>Console</ProjectType>
|
||||||
<Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description>
|
<Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description>
|
||||||
<Version>0.5.3</Version>
|
<Version>0.6.0</Version>
|
||||||
<Author>Sven Sager</Author>
|
<Author>Sven Sager</Author>
|
||||||
<Email>akira@narux.de</Email>
|
<Email>akira@narux.de</Email>
|
||||||
<Eol index="1"/>
|
<Eol index="1"/>
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
<Source>revpipyload/logsystem.py</Source>
|
<Source>revpipyload/logsystem.py</Source>
|
||||||
<Source>revpipyload/plcsystem.py</Source>
|
<Source>revpipyload/plcsystem.py</Source>
|
||||||
<Source>revpipyload/picontrolserver.py</Source>
|
<Source>revpipyload/picontrolserver.py</Source>
|
||||||
|
<Source>revpipyload/xmlinterface.py</Source>
|
||||||
|
<Source>revpipyload/helper.py</Source>
|
||||||
</Sources>
|
</Sources>
|
||||||
<Forms/>
|
<Forms/>
|
||||||
<Translations/>
|
<Translations/>
|
||||||
|
|||||||
147
revpipyload/helper.py
Normal file
147
revpipyload/helper.py
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# RevPiPyLoad
|
||||||
|
#
|
||||||
|
# Webpage: https://revpimodio.org/revpipyplc/
|
||||||
|
# (c) Sven Sager, License: LGPLv3
|
||||||
|
#
|
||||||
|
"""Helperfunktionen fuer das gesamte RevPiPyLoad-System."""
|
||||||
|
import os
|
||||||
|
import proginit
|
||||||
|
from re import match as rematch
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
|
||||||
|
def _ipmatch(ipaddress, dict_acl):
|
||||||
|
"""Prueft IP gegen ACL List und gibt ACL aus.
|
||||||
|
|
||||||
|
@param ipaddress zum pruefen
|
||||||
|
@param dict_acl ACL Dict gegen die IP zu pruefen ist
|
||||||
|
@return int() ACL Wert oder -1 wenn nicht gefunden
|
||||||
|
|
||||||
|
"""
|
||||||
|
for aclip in sorted(dict_acl, reverse=True):
|
||||||
|
regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}")
|
||||||
|
if refullmatch(regex, ipaddress):
|
||||||
|
return dict_acl[aclip]
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
def _setuprt(pid, evt_exit):
|
||||||
|
"""Konfiguriert Programm fuer den RT-Scheduler.
|
||||||
|
@param pid PID, der angehoben werden soll
|
||||||
|
@return None"""
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.debug("enter _setuprt()")
|
||||||
|
|
||||||
|
dict_change = {
|
||||||
|
"ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10,
|
||||||
|
"ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20
|
||||||
|
}
|
||||||
|
|
||||||
|
for ps_change in dict_change:
|
||||||
|
# pid und prio ermitteln
|
||||||
|
kpidps = Popen([
|
||||||
|
"/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change
|
||||||
|
], bufsize=1, stdout=PIPE)
|
||||||
|
|
||||||
|
# Timeout nachbilden da in Python 3.2 nicht vorhanden
|
||||||
|
count = 10
|
||||||
|
while kpidps.poll() is None:
|
||||||
|
count -= 1
|
||||||
|
if count == 0:
|
||||||
|
kpidps.kill()
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"ps timeout to get rt prio info - no rt active"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
evt_exit.wait(0.5)
|
||||||
|
if evt_exit.is_set():
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
kpiddat = kpidps.communicate()[0]
|
||||||
|
lst_kpids = kpiddat.split()
|
||||||
|
except:
|
||||||
|
kpidps.kill()
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"can not get pid and prio - no rt active"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
while len(lst_kpids) > 0:
|
||||||
|
# Elemente paarweise übernehmen
|
||||||
|
kpid = lst_kpids.pop(0)
|
||||||
|
kprio = lst_kpids.pop(0)
|
||||||
|
|
||||||
|
# Daten prüfen
|
||||||
|
if not kpid.isdigit():
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"pid={} and prio={} are not valid - no rt active"
|
||||||
|
"".format(kpid, kprio)
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
kpid = int(kpid)
|
||||||
|
|
||||||
|
# RTPrio ermitteln
|
||||||
|
if kprio.isdigit():
|
||||||
|
kprio = int(kprio)
|
||||||
|
else:
|
||||||
|
kprio = 0
|
||||||
|
|
||||||
|
if kprio < 10:
|
||||||
|
# Profile anpassen
|
||||||
|
ec = os.system("/usr/bin/env chrt -fp {} {}".format(
|
||||||
|
dict_change[ps_change], kpid
|
||||||
|
))
|
||||||
|
if ec != 0:
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"could not adjust scheduler - no rt active"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# SCHED_RR für pid setzen
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.info("set scheduler profile of pid {}".format(pid))
|
||||||
|
|
||||||
|
ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid))
|
||||||
|
if ec != 0 and proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"could not set scheduler profile of pid {}"
|
||||||
|
"".format(pid)
|
||||||
|
)
|
||||||
|
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.debug("leave _setuprt()")
|
||||||
|
|
||||||
|
|
||||||
|
def _zeroprocimg():
|
||||||
|
"""Setzt Prozessabbild auf NULL."""
|
||||||
|
procimg = "/dev/piControl0" if proginit.pargs is None \
|
||||||
|
else proginit.pargs.procimg
|
||||||
|
|
||||||
|
if os.access(procimg, os.W_OK):
|
||||||
|
with open(procimg, "w+b", 0) as f:
|
||||||
|
f.write(bytes(4096))
|
||||||
|
else:
|
||||||
|
if proginit.logger is not None:
|
||||||
|
proginit.logger.error(
|
||||||
|
"zeroprocimg can not write to piControl device"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def refullmatch(regex, string):
|
||||||
|
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
|
||||||
|
|
||||||
|
@param regex RegEx Statement
|
||||||
|
@param string Zeichenfolge gegen die getestet wird
|
||||||
|
@return True, wenn komplett passt sonst False
|
||||||
|
|
||||||
|
"""
|
||||||
|
m = rematch(regex, string)
|
||||||
|
return m is not None and m.end() == len(string)
|
||||||
@@ -8,9 +8,9 @@
|
|||||||
"""Modul fuer die Verwaltung der PLC-Slave Funktionen."""
|
"""Modul fuer die Verwaltung der PLC-Slave Funktionen."""
|
||||||
import proginit
|
import proginit
|
||||||
import socket
|
import socket
|
||||||
|
from helper import _ipmatch
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from timeit import default_timer
|
from timeit import default_timer
|
||||||
from revpipyload import _ipmatch
|
|
||||||
|
|
||||||
|
|
||||||
class RevPiSlave(Thread):
|
class RevPiSlave(Thread):
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import proginit
|
|||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
from logsystem import PipeLogwriter
|
from logsystem import PipeLogwriter
|
||||||
from proginit import _setuprt
|
from helper import _setuprt, _zeroprocimg
|
||||||
from sys import stdout as sysstdout
|
from sys import stdout as sysstdout
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from time import sleep, asctime
|
from time import sleep, asctime
|
||||||
@@ -145,7 +145,7 @@ class RevPiPlc(Thread):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
if self.zeroonerror:
|
if self.zeroonerror:
|
||||||
proginit._zeroprocimg()
|
_zeroprocimg()
|
||||||
proginit.logger.warning(
|
proginit.logger.warning(
|
||||||
"set piControl0 to ZERO after PLC program error")
|
"set piControl0 to ZERO after PLC program error")
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ class RevPiPlc(Thread):
|
|||||||
# PLC Python Programm sauber beendet
|
# PLC Python Programm sauber beendet
|
||||||
proginit.logger.info("plc program did a clean exit")
|
proginit.logger.info("plc program did a clean exit")
|
||||||
if self.zeroonexit:
|
if self.zeroonexit:
|
||||||
proginit._zeroprocimg()
|
_zeroprocimg()
|
||||||
proginit.logger.info(
|
proginit.logger.info(
|
||||||
"set piControl0 to ZERO after PLC program returns "
|
"set piControl0 to ZERO after PLC program returns "
|
||||||
"clean exitcode")
|
"clean exitcode")
|
||||||
@@ -221,7 +221,7 @@ class RevPiPlc(Thread):
|
|||||||
self.exitcode = self._procplc.poll()
|
self.exitcode = self._procplc.poll()
|
||||||
if self.zeroonexit and self.exitcode == 0 \
|
if self.zeroonexit and self.exitcode == 0 \
|
||||||
or self.zeroonerror and self.exitcode != 0:
|
or self.zeroonerror and self.exitcode != 0:
|
||||||
proginit._zeroprocimg()
|
_zeroprocimg()
|
||||||
|
|
||||||
if self._plw is not None:
|
if self._plw is not None:
|
||||||
self._plw.stop()
|
self._plw.stop()
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
|
|
||||||
forked = False
|
forked = False
|
||||||
globalconffile = None
|
globalconffile = None
|
||||||
@@ -23,110 +22,6 @@ rapcatalog = None
|
|||||||
startdir = None
|
startdir = None
|
||||||
|
|
||||||
|
|
||||||
def _setuprt(pid, evt_exit):
|
|
||||||
"""Konfiguriert Programm fuer den RT-Scheduler.
|
|
||||||
@param pid PID, der angehoben werden soll
|
|
||||||
@return None"""
|
|
||||||
if logger is not None:
|
|
||||||
logger.debug("enter _setuprt()")
|
|
||||||
|
|
||||||
dict_change = {
|
|
||||||
"ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10,
|
|
||||||
"ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20
|
|
||||||
}
|
|
||||||
|
|
||||||
for ps_change in dict_change:
|
|
||||||
# pid und prio ermitteln
|
|
||||||
kpidps = Popen([
|
|
||||||
"/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change
|
|
||||||
], bufsize=1, stdout=PIPE)
|
|
||||||
|
|
||||||
# Timeout nachbilden da in Python 3.2 nicht vorhanden
|
|
||||||
count = 10
|
|
||||||
while kpidps.poll() is None:
|
|
||||||
count -= 1
|
|
||||||
if count == 0:
|
|
||||||
kpidps.kill()
|
|
||||||
if logger is not None:
|
|
||||||
logger.error(
|
|
||||||
"ps timeout to get rt prio info - no rt active"
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
evt_exit.wait(0.5)
|
|
||||||
if evt_exit.is_set():
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
kpiddat = kpidps.communicate()[0]
|
|
||||||
lst_kpids = kpiddat.split()
|
|
||||||
except:
|
|
||||||
kpidps.kill()
|
|
||||||
if logger is not None:
|
|
||||||
logger.error(
|
|
||||||
"can not get pid and prio - no rt active"
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
while len(lst_kpids) > 0:
|
|
||||||
# Elemente paarweise übernehmen
|
|
||||||
kpid = lst_kpids.pop(0)
|
|
||||||
kprio = lst_kpids.pop(0)
|
|
||||||
|
|
||||||
# Daten prüfen
|
|
||||||
if not kpid.isdigit():
|
|
||||||
if logger is not None:
|
|
||||||
logger.error(
|
|
||||||
"pid={} and prio={} are not valid - no rt active"
|
|
||||||
"".format(kpid, kprio)
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
kpid = int(kpid)
|
|
||||||
|
|
||||||
# RTPrio ermitteln
|
|
||||||
if kprio.isdigit():
|
|
||||||
kprio = int(kprio)
|
|
||||||
else:
|
|
||||||
kprio = 0
|
|
||||||
|
|
||||||
if kprio < 10:
|
|
||||||
# Profile anpassen
|
|
||||||
ec = os.system("/usr/bin/env chrt -fp {} {}".format(
|
|
||||||
dict_change[ps_change], kpid
|
|
||||||
))
|
|
||||||
if ec != 0:
|
|
||||||
if logger is not None:
|
|
||||||
logger.error(
|
|
||||||
"could not adjust scheduler - no rt active"
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
# SCHED_RR für pid setzen
|
|
||||||
if logger is not None:
|
|
||||||
logger.info("set scheduler profile of pid {}".format(pid))
|
|
||||||
|
|
||||||
ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid))
|
|
||||||
if ec != 0 and logger is not None:
|
|
||||||
logger.error(
|
|
||||||
"could not set scheduler profile of pid {}"
|
|
||||||
"".format(pid)
|
|
||||||
)
|
|
||||||
|
|
||||||
if logger is not None:
|
|
||||||
logger.debug("leave _setuprt()")
|
|
||||||
|
|
||||||
|
|
||||||
def _zeroprocimg():
|
|
||||||
"""Setzt Prozessabbild auf NULL."""
|
|
||||||
procimg = "/dev/piControl0" if pargs is None else pargs.procimg
|
|
||||||
if os.access(procimg, os.W_OK):
|
|
||||||
with open(procimg, "w+b", 0) as f:
|
|
||||||
f.write(bytes(4096))
|
|
||||||
else:
|
|
||||||
if logger is not None:
|
|
||||||
logger.error("zeroprocimg can not write to piControl device")
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup():
|
def cleanup():
|
||||||
"""Clean up program."""
|
"""Clean up program."""
|
||||||
# NOTE: Pidfile wirklich löschen?
|
# NOTE: Pidfile wirklich löschen?
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ import tarfile
|
|||||||
import zipfile
|
import zipfile
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
from helper import refullmatch
|
||||||
from json import loads as jloads
|
from json import loads as jloads
|
||||||
from re import match as rematch
|
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
from threading import Event
|
from threading import Event
|
||||||
@@ -50,37 +50,10 @@ from time import asctime
|
|||||||
from xmlrpc.client import Binary
|
from xmlrpc.client import Binary
|
||||||
from xmlrpc.server import SimpleXMLRPCServer
|
from xmlrpc.server import SimpleXMLRPCServer
|
||||||
|
|
||||||
pyloadversion = "0.5.3"
|
pyloadversion = "0.6.0"
|
||||||
re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*"
|
re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*"
|
||||||
|
|
||||||
|
|
||||||
def _ipmatch(ipaddress, dict_acl):
|
|
||||||
"""Prueft IP gegen ACL List und gibt ACL aus.
|
|
||||||
|
|
||||||
@param ipaddress zum pruefen
|
|
||||||
@param dict_acl ACL Dict gegen die IP zu pruefen ist
|
|
||||||
@return int() ACL Wert oder -1 wenn nicht gefunden
|
|
||||||
|
|
||||||
"""
|
|
||||||
for aclip in sorted(dict_acl, reverse=True):
|
|
||||||
regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}")
|
|
||||||
if refullmatch(regex, ipaddress):
|
|
||||||
return dict_acl[aclip]
|
|
||||||
return -1
|
|
||||||
|
|
||||||
|
|
||||||
def refullmatch(regex, string):
|
|
||||||
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
|
|
||||||
|
|
||||||
@param regex RegEx Statement
|
|
||||||
@param string Zeichenfolge gegen die getestet wird
|
|
||||||
@return True, wenn komplett passt sonst False
|
|
||||||
|
|
||||||
"""
|
|
||||||
m = rematch(regex, string)
|
|
||||||
return m is not None and m.end() == len(string)
|
|
||||||
|
|
||||||
|
|
||||||
class RevPiPyLoad():
|
class RevPiPyLoad():
|
||||||
|
|
||||||
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt.
|
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt.
|
||||||
|
|||||||
Reference in New Issue
Block a user