Compare commits
6 Commits
f3ffdd8eaa
...
c3417c38a3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3417c38a3 | ||
|
|
1415055483 | ||
|
|
fbfda04d7c | ||
|
|
9e5a9e0141 | ||
|
|
f6f83e236e | ||
|
|
8db3af9ca1 |
8
data/etc/default/revpi-ios
Normal file
8
data/etc/default/revpi-ios
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Additional options that are passed to revpi-ios.
|
||||||
|
# add '-f /var/log/revpi-ios.log' to write logs to own log file
|
||||||
|
# add '-v' or '-vv' for verbose logging
|
||||||
|
|
||||||
|
DAEMON_OPTS=""
|
||||||
|
|
||||||
|
# In addition to journalctl, use your own additional log file
|
||||||
|
# DAEMON_OPTS="-f /var/log/revpi-ios.log"
|
||||||
14
data/etc/logrotate/revpi-ios
Normal file
14
data/etc/logrotate/revpi-ios
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/var/log/revpi-ios.log
|
||||||
|
{
|
||||||
|
rotate 6
|
||||||
|
weekly
|
||||||
|
maxsize 1M
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
systemctl kill --signal=SIGUSR1 revpi-ios > /dev/null 2>&1 || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
12
data/systemd/before_253/revpi-ios.service
Normal file
12
data/systemd/before_253/revpi-ios.service
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=D-Bus interface for Inputs/Outputs of Revolution Pi
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/default/revpi-ios
|
||||||
|
Type=notify
|
||||||
|
NotifyAccess=all
|
||||||
|
ExecStart=/usr/sbin/revpi-middleware ios $DAEMON_OPTS
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
11
data/systemd/from_253/revpi-ios.service
Normal file
11
data/systemd/from_253/revpi-ios.service
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=D-Bus interface for Inputs/Outputs of Revolution Pi
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/default/revpi-ios
|
||||||
|
Type=notify-reload
|
||||||
|
NotifyAccess=all
|
||||||
|
ExecStart=/usr/sbin/revpi-middleware ios $DAEMON_OPTS
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -3,35 +3,43 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
"""Main daemon of revpi-middleware."""
|
"""Main daemon of revpi-middleware."""
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from os import getuid, environ
|
from os import environ
|
||||||
from threading import Event
|
from threading import Event
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
|
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
from .dbus_ios1 import BusProviderIos1
|
from .dbus_ios1 import BusProviderIos1
|
||||||
from .dbus_middleware1 import BusProviderMiddleware1
|
from .dbus_middleware1 import BusProviderMiddleware1
|
||||||
|
from .dbus_middleware1.process_image.process_image_helper import ResetDriverWatchdog
|
||||||
|
|
||||||
log = getLogger(__name__)
|
log = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BusProvider(Enum):
|
||||||
|
middleware = "middleware"
|
||||||
|
ios = "ios"
|
||||||
|
|
||||||
|
|
||||||
class MiddlewareDaemon:
|
class MiddlewareDaemon:
|
||||||
"""Main program of MiddlewareDaemon class."""
|
"""Main program of MiddlewareDaemon class."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, bus_provider: BusProvider):
|
||||||
"""Init MiddlewareDaemon class."""
|
"""Init MiddlewareDaemon class."""
|
||||||
log.debug("enter MiddlewareDaemon.__init__")
|
log.debug("enter MiddlewareDaemon.__init__")
|
||||||
|
|
||||||
self._cycle_time = 1.0
|
self._cycle_time = 1.0
|
||||||
self.do_cycle = Event()
|
self.do_cycle = Event()
|
||||||
|
self._force_dbus_restart = False
|
||||||
self._reconfigure = False
|
self._reconfigure = False
|
||||||
self._running = True
|
self._running = True
|
||||||
|
|
||||||
self.bp_middleware1 = None
|
self.bus_provider = None
|
||||||
self.bp_ios1 = None
|
self.bus_provider_selected = bus_provider
|
||||||
|
self.wd_reset = ResetDriverWatchdog("")
|
||||||
|
|
||||||
self._configure()
|
self._configure()
|
||||||
log.debug("leave MiddlewareDaemon.__init__")
|
log.debug("leave MiddlewareDaemon.__init__")
|
||||||
@@ -41,6 +49,17 @@ class MiddlewareDaemon:
|
|||||||
log.debug("enter MiddlewareDaemon._configure")
|
log.debug("enter MiddlewareDaemon._configure")
|
||||||
pi.reload_conf()
|
pi.reload_conf()
|
||||||
|
|
||||||
|
if self._force_dbus_restart:
|
||||||
|
self.dbus_stop()
|
||||||
|
self._force_dbus_restart = False
|
||||||
|
|
||||||
|
if pi.pargs.procimg != self.wd_reset.procimg:
|
||||||
|
self.dbus_stop()
|
||||||
|
|
||||||
|
self.wd_reset.stop()
|
||||||
|
self.wd_reset = ResetDriverWatchdog(pi.pargs.procimg)
|
||||||
|
self.wd_reset.register_call(self._reset_driver_callack)
|
||||||
|
|
||||||
log.debug("leave MiddlewareDaemon._configure")
|
log.debug("leave MiddlewareDaemon._configure")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -54,44 +73,44 @@ class MiddlewareDaemon:
|
|||||||
|
|
||||||
return environ.get(environ_name, bus_address)
|
return environ.get(environ_name, bus_address)
|
||||||
|
|
||||||
|
def _reset_driver_callack(self, *args) -> None:
|
||||||
|
log.debug("enter MiddlewareDaemon._reset_driver_callack")
|
||||||
|
|
||||||
|
if self.bus_provider_selected is BusProvider.ios:
|
||||||
|
self._force_dbus_restart = True
|
||||||
|
self.reload_config()
|
||||||
|
|
||||||
|
log.debug("leave MiddlewareDaemon._reset_driver_callack")
|
||||||
|
|
||||||
def dbus_start(self):
|
def dbus_start(self):
|
||||||
log.debug("enter MiddlewareDaemon.dbus_start")
|
log.debug("enter MiddlewareDaemon.dbus_start")
|
||||||
|
|
||||||
dbus_middleware1_running = self.bp_middleware1 and self.bp_middleware1.is_alive()
|
dbus_running = self.bus_provider and self.bus_provider.is_alive()
|
||||||
if not dbus_middleware1_running:
|
if not dbus_running:
|
||||||
self.bp_middleware1 = BusProviderMiddleware1(self._get_bus_address())
|
if self.bus_provider_selected is BusProvider.middleware:
|
||||||
self.bp_middleware1.start()
|
self.bus_provider = BusProviderMiddleware1(
|
||||||
|
dbus_address=self._get_bus_address(),
|
||||||
dbus_ios1_running = self.bp_ios1 and self.bp_ios1.is_alive()
|
picontrol_device=pi.pargs.procimg,
|
||||||
if not dbus_ios1_running:
|
)
|
||||||
if self.bp_middleware1.published.wait(timeout=10.0):
|
elif self.bus_provider_selected is BusProvider.ios:
|
||||||
self.bp_ios1 = BusProviderIos1(self._get_bus_address())
|
self.bus_provider = BusProviderIos1(
|
||||||
self.bp_ios1.start()
|
dbus_address=self._get_bus_address(),
|
||||||
|
picontrol_device=pi.pargs.procimg,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
log.error("dbus middleware1 provider thread is not alive - can not start ios1 bus")
|
raise ValueError("Unknown bus provider")
|
||||||
|
self.bus_provider.start()
|
||||||
|
|
||||||
log.debug("leave MiddlewareDaemon.dbus_start")
|
log.debug("leave MiddlewareDaemon.dbus_start")
|
||||||
|
|
||||||
def dbus_stop(self, bus_filter: List[object] = None):
|
def dbus_stop(self):
|
||||||
log.debug("enter MiddlewareDaemon.dbus_stop")
|
log.debug("enter MiddlewareDaemon.dbus_stop")
|
||||||
|
|
||||||
if bus_filter is None:
|
if self.bus_provider:
|
||||||
bus_filter = [
|
self.bus_provider.stop()
|
||||||
self.bp_middleware1,
|
self.bus_provider.join(timeout=10.0)
|
||||||
self.bp_ios1,
|
if self.bus_provider.is_alive():
|
||||||
]
|
log.warning(f"dbus {self.bus_provider.name} thread is still alive")
|
||||||
|
|
||||||
if self.bp_middleware1 and self.bp_middleware1 in bus_filter:
|
|
||||||
self.bp_middleware1.stop()
|
|
||||||
self.bp_middleware1.join(timeout=10.0)
|
|
||||||
if self.bp_middleware1.is_alive():
|
|
||||||
log.warning("dbus middleware1 provider thread is still alive")
|
|
||||||
|
|
||||||
if self.bp_ios1 and self.bp_ios1 in bus_filter:
|
|
||||||
self.bp_ios1.stop()
|
|
||||||
self.bp_ios1.join(timeout=10.0)
|
|
||||||
if self.bp_ios1.is_alive():
|
|
||||||
log.warning("dbus ios1 provider thread is still alive")
|
|
||||||
|
|
||||||
log.debug("leave MiddlewareDaemon.dbus_stop")
|
log.debug("leave MiddlewareDaemon.dbus_stop")
|
||||||
|
|
||||||
@@ -122,7 +141,6 @@ class MiddlewareDaemon:
|
|||||||
# Startup tasks
|
# Startup tasks
|
||||||
self.dbus_start()
|
self.dbus_start()
|
||||||
|
|
||||||
pi.startup_complete()
|
|
||||||
# Go into mainloop of daemon
|
# Go into mainloop of daemon
|
||||||
while self._running:
|
while self._running:
|
||||||
ot = perf_counter()
|
ot = perf_counter()
|
||||||
@@ -132,19 +150,15 @@ class MiddlewareDaemon:
|
|||||||
if self._reconfigure:
|
if self._reconfigure:
|
||||||
self._configure()
|
self._configure()
|
||||||
self._reconfigure = False
|
self._reconfigure = False
|
||||||
pi.startup_complete()
|
|
||||||
|
|
||||||
# Monitor bus providers for errors and restart them
|
# Monitor bus providers for errors and restart them
|
||||||
restart = False
|
if not (self.bus_provider and self.bus_provider.is_alive()):
|
||||||
if not (self.bp_middleware1 and self.bp_middleware1.is_alive()):
|
log.warning(f"dbus {self.bus_provider.name} thread is not alive - restarting")
|
||||||
log.warning("dbus middleware1 provider thread is not alive - restarting")
|
|
||||||
restart = True
|
|
||||||
if not (self.bp_ios1 and self.bp_ios1.is_alive()):
|
|
||||||
log.warning("dbus ios1 provider thread is not alive - restarting")
|
|
||||||
restart = True
|
|
||||||
if restart:
|
|
||||||
self.dbus_start()
|
self.dbus_start()
|
||||||
|
|
||||||
|
if self.bus_provider and self.bus_provider.published.is_set():
|
||||||
|
pi.startup_complete()
|
||||||
|
|
||||||
# Cycle time calculation
|
# Cycle time calculation
|
||||||
dm = divmod(ot - perf_counter(), self._cycle_time)
|
dm = divmod(ot - perf_counter(), self._cycle_time)
|
||||||
# For float the result is (q, a % b), where q is usually math.floor(a / b) but may be 1 less than that.
|
# For float the result is (q, a % b), where q is usually math.floor(a / b) but may be 1 less than that.
|
||||||
|
|||||||
@@ -92,16 +92,10 @@ class BusProviderIos1(Thread):
|
|||||||
*lst_interfaces,
|
*lst_interfaces,
|
||||||
)
|
)
|
||||||
self.published.set()
|
self.published.set()
|
||||||
|
log.info(f"published {REVPI_DBUS_NAME} on {self._bus_address}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"can not publish dbus {REVPI_DBUS_NAME}: {e}")
|
log.error(f"can not publish dbus {REVPI_DBUS_NAME}: {e}")
|
||||||
|
|
||||||
# Subscribe to NotifyDriverReset on middleware1 dbus
|
|
||||||
iface_pi_control = bus.get(
|
|
||||||
"com.revolutionpi.middleware1",
|
|
||||||
"/com/revolutionpi/middleware1",
|
|
||||||
)["com.revolutionpi.middleware1.PiControl"]
|
|
||||||
iface_pi_control.onNotifyDriverReset = self.stop
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._loop.run()
|
self._loop.run()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -109,6 +103,7 @@ class BusProviderIos1(Thread):
|
|||||||
|
|
||||||
bus.con.close()
|
bus.con.close()
|
||||||
self._modio.cleanup()
|
self._modio.cleanup()
|
||||||
|
log.info(f"closed {REVPI_DBUS_NAME} connection to {self._bus_address}")
|
||||||
|
|
||||||
log.debug("leave BusProviderIos1.run")
|
log.debug("leave BusProviderIos1.run")
|
||||||
|
|
||||||
@@ -117,6 +112,10 @@ class BusProviderIos1(Thread):
|
|||||||
self._loop.quit()
|
self._loop.quit()
|
||||||
log.debug("leave BusProviderIos1.stop")
|
log.debug("leave BusProviderIos1.stop")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return REVPI_DBUS_NAME
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def running(self):
|
def running(self):
|
||||||
return self._loop.is_running()
|
return self._loop.is_running()
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class BusProviderMiddleware1(Thread):
|
|||||||
*lst_interfaces,
|
*lst_interfaces,
|
||||||
)
|
)
|
||||||
self.published.set()
|
self.published.set()
|
||||||
|
log.info(f"published {REVPI_DBUS_NAME} on {self._bus_address}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"can not publish dbus {REVPI_DBUS_NAME}: {e}")
|
log.error(f"can not publish dbus {REVPI_DBUS_NAME}: {e}")
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ class BusProviderMiddleware1(Thread):
|
|||||||
log.error(f"can not run dbus mainloop: {e}")
|
log.error(f"can not run dbus mainloop: {e}")
|
||||||
|
|
||||||
bus.con.close()
|
bus.con.close()
|
||||||
|
log.info(f"closed {REVPI_DBUS_NAME} connection to {self._bus_address}")
|
||||||
|
|
||||||
# Clean up all interfaces
|
# Clean up all interfaces
|
||||||
for interface in lst_interfaces:
|
for interface in lst_interfaces:
|
||||||
@@ -78,6 +80,10 @@ class BusProviderMiddleware1(Thread):
|
|||||||
self._loop.quit()
|
self._loop.quit()
|
||||||
log.debug("leave BusProviderMiddleware1.stop")
|
log.debug("leave BusProviderMiddleware1.stop")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return REVPI_DBUS_NAME
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def running(self):
|
def running(self):
|
||||||
return self._loop.is_running()
|
return self._loop.is_running()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .daemon import MiddlewareDaemon
|
from .daemon import MiddlewareDaemon, BusProvider
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
|
|
||||||
log = getLogger(__name__)
|
log = getLogger(__name__)
|
||||||
@@ -27,6 +27,19 @@ pi.parser.add_argument(
|
|||||||
default="/etc/{0}/{0}.conf".format(pi.programname),
|
default="/etc/{0}/{0}.conf".format(pi.programname),
|
||||||
help="application configuration file",
|
help="application configuration file",
|
||||||
)
|
)
|
||||||
|
pi.parser.add_argument(
|
||||||
|
"--procimg",
|
||||||
|
dest="procimg",
|
||||||
|
default="/dev/piControl0",
|
||||||
|
help="Path to process image",
|
||||||
|
)
|
||||||
|
pi.parser.add_argument(
|
||||||
|
"bus_provider",
|
||||||
|
default="middleware",
|
||||||
|
nargs="?",
|
||||||
|
choices=["middleware", "ios"],
|
||||||
|
help="bus provider to use",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
@@ -35,7 +48,7 @@ def main() -> int:
|
|||||||
# Parse command line arguments
|
# Parse command line arguments
|
||||||
pi.init_app()
|
pi.init_app()
|
||||||
|
|
||||||
root = MiddlewareDaemon()
|
root = MiddlewareDaemon(BusProvider(pi.pargs.bus_provider))
|
||||||
|
|
||||||
# Set signals
|
# Set signals
|
||||||
signal.signal(signal.SIGHUP, lambda n, f: root.reload_config())
|
signal.signal(signal.SIGHUP, lambda n, f: root.reload_config())
|
||||||
|
|||||||
Reference in New Issue
Block a user