Files
revpi-middleware/src/revpi_middleware/daemon.py
Sven Sager bde3920fc1 feat: Add session bus option for local testing and development
Introduced a `--use-session-bus` flag to optionally use the D-Bus
session bus instead of the system bus. This allows better flexibility
for local testing and development scenarios without requiring
system-level changes. Updated related classes and functions to respect
the new flag.
2025-04-19 09:33:54 +02:00

122 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""Main daemon of revpi-middleware."""
from logging import getLogger
from threading import Event
from time import perf_counter
from . import proginit as pi
from .dbus_middleware1.bus_provider import BusProvider
log = getLogger(__name__)
class MiddlewareDaemon:
"""Main program of MiddlewareDaemon class."""
def __init__(self):
"""Init MiddlewareDaemon class."""
log.debug("enter MiddlewareDaemon.__init__")
self._cycle_time = 1.0
self.do_cycle = Event()
self._reconfigure = False
self._running = True
self.bus_provider = None
self._configure()
log.debug("leave MiddlewareDaemon.__init__")
def _configure(self) -> None:
"""Load the configuration file and set values."""
log.debug("enter MiddlewareDaemon._configure")
pi.reload_conf()
log.debug("leave MiddlewareDaemon._configure")
def dbus_start(self):
log.debug("enter MiddlewareDaemon.dbus_start")
if self.bus_provider and self.bus_provider.is_alive():
return
self.bus_provider = BusProvider(use_system_bus=not pi.pargs.use_session_bus)
self.bus_provider.start()
log.debug("leave MiddlewareDaemon.dbus_start")
def dbus_stop(self):
log.debug("enter MiddlewareDaemon.dbus_stop")
if self.bus_provider:
self.bus_provider.stop()
self.bus_provider.join(timeout=10.0)
if self.bus_provider.is_alive():
log.warning("dbus provider thread is still alive")
log.debug("leave MiddlewareDaemon.dbus_stop")
def reload_config(self) -> None:
"""Reload configuration file."""
log.debug("enter MiddlewareDaemon.reload_config")
self._reconfigure = True
self.do_cycle.set()
log.debug("leave MiddlewareDaemon.reload_config")
@staticmethod
def rotate_logfile() -> None:
"""Start a new logfile."""
log.debug("enter MiddlewareDaemon.rotate_logfile")
pi.reconfigure_logger()
log.warning("start new logfile")
log.debug("leave MiddlewareDaemon.rotate_logfile")
def start(self) -> int:
"""Blocking mainloop of program."""
log.debug("enter MiddlewareDaemon.start")
error_code = 0
# Startup tasks
self.dbus_start()
pi.startup_complete()
# Go into mainloop of daemon
while self._running:
ot = perf_counter()
self.do_cycle.clear()
# Early tasks of the cycle loop
if self._reconfigure:
self._configure()
self._reconfigure = False
pi.startup_complete()
# Cycle time calculation
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.
if dm[0] == -1.0: # Cycle time isn't exceeded
self.do_cycle.wait(dm[1])
else:
log.debug("Cycle time exceeded about {0:.0f} times".format(abs(dm[0])))
# Cleanup tasks
self.dbus_stop()
log.debug("leave MiddlewareDaemon.start")
return error_code
def stop(self) -> None:
"""Set stop request for mainloop."""
log.debug("enter MiddlewareDaemon.stop")
self._running = False
self.do_cycle.set()
log.debug("leave MiddlewareDaemon.stop")