Auto-detect RTC device (/dev/rtc0,/dev/rtc1) for hwclock sync

This commit is contained in:
2026-02-13 02:11:46 +01:00
parent f0eaf3dc5f
commit 5f5087c3d6

View File

@@ -1,7 +1,7 @@
import os import os
import subprocess import subprocess
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Tuple from typing import Optional, Tuple
import ntplib import ntplib
@@ -13,21 +13,34 @@ class RTCAndNTPManager:
self.state = state self.state = state
self.rtc_device = rtc_device self.rtc_device = rtc_device
self.ntp_server = ntp_server self.ntp_server = ntp_server
self._resolved_rtc_device: Optional[str] = None
def _run(self, args, timeout: int = 12) -> subprocess.CompletedProcess: def _run(self, args, timeout: int = 12) -> subprocess.CompletedProcess:
return subprocess.run(args, capture_output=True, text=True, timeout=timeout, check=False) return subprocess.run(args, capture_output=True, text=True, timeout=timeout, check=False)
def _resolve_rtc_device(self) -> Optional[str]:
if self._resolved_rtc_device and os.path.exists(self._resolved_rtc_device):
return self._resolved_rtc_device
candidates = [self.rtc_device, "/dev/rtc", "/dev/rtc0", "/dev/rtc1"]
for candidate in candidates:
if os.path.exists(candidate):
self._resolved_rtc_device = candidate
return candidate
return None
def rtc_available(self) -> bool: def rtc_available(self) -> bool:
return os.path.exists(self.rtc_device) return self._resolve_rtc_device() is not None
def sync_from_rtc(self) -> Tuple[bool, str]: def sync_from_rtc(self) -> Tuple[bool, str]:
if not self.rtc_available(): rtc_device = self._resolve_rtc_device()
return False, f"RTC not found at {self.rtc_device}" if rtc_device is None:
return False, f"RTC not found (checked: {self.rtc_device}, /dev/rtc, /dev/rtc0, /dev/rtc1)"
proc = self._run(["hwclock", "-s", "--utc"], timeout=10) proc = self._run(["hwclock", "-s", "--utc", "--rtc", rtc_device], timeout=10)
if proc.returncode == 0: if proc.returncode == 0:
self.state.update_status("System time loaded from RTC", "") self.state.update_status(f"System time loaded from {rtc_device}", "")
return True, "RTC -> system time ok" return True, f"{rtc_device} -> system time ok"
return False, (proc.stderr or proc.stdout or "hwclock -s failed").strip() return False, (proc.stderr or proc.stdout or "hwclock -s failed").strip()
def sync_ntp_to_system(self, timeout: int = 6) -> Tuple[bool, str]: def sync_ntp_to_system(self, timeout: int = 6) -> Tuple[bool, str]:
@@ -48,13 +61,14 @@ class RTCAndNTPManager:
return False, f"NTP sync failed: {exc}" return False, f"NTP sync failed: {exc}"
def write_system_time_to_rtc(self) -> Tuple[bool, str]: def write_system_time_to_rtc(self) -> Tuple[bool, str]:
if not self.rtc_available(): rtc_device = self._resolve_rtc_device()
return False, f"RTC not found at {self.rtc_device}" if rtc_device is None:
return False, f"RTC not found (checked: {self.rtc_device}, /dev/rtc, /dev/rtc0, /dev/rtc1)"
proc = self._run(["hwclock", "-w", "--utc"], timeout=10) proc = self._run(["hwclock", "-w", "--utc", "--rtc", rtc_device], timeout=10)
if proc.returncode == 0: if proc.returncode == 0:
self.state.update_status("RTC updated from system time", "") self.state.update_status(f"{rtc_device} updated from system time", "")
return True, "system -> RTC ok" return True, f"system -> {rtc_device} ok"
return False, (proc.stderr or proc.stdout or "hwclock -w failed").strip() return False, (proc.stderr or proc.stdout or "hwclock -w failed").strip()
def sync_ntp_and_rtc(self) -> Tuple[bool, str]: def sync_ntp_and_rtc(self) -> Tuple[bool, str]: