reboot_RPi.RebootManager¶
- class reboot_RPi.RebootManager¶
Coordinates Raspberry Pi reboots with cooldown protection.
Persists a record of each successful reboot to
LOG_FILEand enforces a minimum interval (COOLDOWN_SECONDS) between consecutive reboots. This prevents cascading reboot loops when a persistent hardware or configuration error triggers repeated reboot requests from upstream components such as the watchdog or sensor error handlers.- Variables:
LOG_FILE (
str) – Path to the persistent reboot history file. Each line is a pipe-delimited record produced bywrite_reboot_log().COOLDOWN_SECONDS (
int) – Minimum number of seconds that must elapse between two reboots; defaults to 4 hours.
Example
Attempt a reboot for an operator-initiated event:
manager = RebootManager() manager.reboot_raspberry_pi({ "type": "events", "t": int(time.time() * 1000), "msg": {"type": "manual", "value": "ops"}, }) # doctest: +SKIP
- read_last_reboot() int | None¶
Read the timestamp of the most recent reboot from the log file.
Opens
LOG_FILE, examines the last line, and extracts the epoch-millisecond value stored in thet=<epoch_ms>field of a record written bywrite_reboot_log(). Any parsing or I/O error is logged throughOizomLoggerand reduced to aNonereturn so the caller treats the device as never having rebooted.- Parameters:
None.
- Returns:
Epoch timestamp in milliseconds of the last reboot, or
Noneif no previous reboot is recorded, the file is missing, empty, or cannot be parsed.
:raises None. All
Exceptioninstances are caught and: :raises converted:Example
>>> manager = RebootManager() >>> manager.read_last_reboot()
Note
The function intentionally swallows exceptions so that a corrupt log file cannot block future reboots; integrity of the log is not security-critical.
- reboot_raspberry_pi(payload: dict) None¶
Trigger a SysRq reboot if outside the cooldown window.
Reads the last reboot timestamp via
read_last_reboot()and compares it withpayload['t']. When the elapsed time is less thanCOOLDOWN_SECONDS, the reboot is suppressed and a context-tagged informational message is emitted via the module-levelOizomLogger. Otherwise the event is appended toLOG_FILEand an immediate Magic SysRq reboot is issued by writing"b"to/proc/sysrq-trigger.- Parameters:
payload –
Reboot event dictionary with the structure:
{ "type": "events", "t": <epoch_ms>, "msg": {"type": "...", "value": "..."} }
- Returns:
None.
:raises None directly. Any
OSErrorfrom the write to: :raises /proc/sysrq-trigger` (or the preceding sleep) is caugh: :raises and logged; the process then returns` to :py:class:`the caller instead: :raises of propagating the failure.:Example
>>> manager = RebootManager() >>> manager.reboot_raspberry_pi({ ... "type": "events", ... "t": 1700000000000, ... "msg": {"type": "manual", "value": "ops"}, ... })
Note
Requires root privileges (or
CAP_SYS_ADMIN) because writes to/proc/sysrq-triggerare restricted; a kernel withCONFIG_MAGIC_SYSRQis also required.
- write_reboot_log(payload: dict) bool¶
Append a reboot event record to
LOG_FILE.Serializes
payloadinto a single pipe-delimited line of the formt=<epoch_ms> | type=<...> | msg_type=<...> | msg_value=<...>, appends it to the log file, flushes the userspace buffer, and attemptsos.fsync()to make the write durable before the impending hardware reboot. A short sleep keeps the kernel a moment to commit the write on slow storage.- Parameters:
payload –
Reboot event dictionary with the following keys:
"t"(int): epoch timestamp in milliseconds."type"(str): event category, e.g."events"."msg"(dict): nested dictionary with"type"and"value"string fields describing the cause.
- Returns:
Trueafter successfully writing and flushing the entry.- Raises:
Example
>>> manager = RebootManager() >>> manager.write_reboot_log({ ... "t": 1700000000000, ... "type": "events", ... "msg": {"type": "manual", "value": "test"}, ... })
Note
os.fsync()may fail on some filesystems (e.g. those backed by/proc); failures are swallowed to keep the reboot path moving.
- COOLDOWN_SECONDS = 14400¶
- LOG_FILE = 'reboot_log.txt'¶