Build a topology graph with gateway as center, device types classified, and links inferred.
()
| 5927 | |
| 5928 | # Kiosk install/teardown runs on a background thread and can take many minutes |
| 5929 | # on a slow board — the installer apt-installs chromium. The UI polls |
| 5930 | # /api/kiosk/status while that happens, so the task's progress and any failure |
| 5931 | # have to be visible there. Without it the API reported 'not_installed' for the |
| 5932 | # whole install, which is indistinguishable from "nothing happened", and the UI |
| 5933 | # gave up after ~25s on a job that was running fine. |
| 5934 | _kiosk_task = {'busy': False, 'phase': 'idle', 'error': None, 'started': 0.0} |
| 5935 | _kiosk_task_lock = threading.Lock() |
| 5936 | |
| 5937 | |
| 5938 | def _kiosk_task_set(**kw) -> None: |
| 5939 | with _kiosk_task_lock: |
| 5940 | _kiosk_task.update(kw) |
| 5941 | |
| 5942 | |
| 5943 | def _kiosk_task_get() -> dict: |
| 5944 | with _kiosk_task_lock: |
| 5945 | return dict(_kiosk_task) |
| 5946 | |
| 5947 | |
| 5948 | def _kiosk_mode() -> str: |
| 5949 | """Return 'service', 'autostart', or 'not_installed' based on what's on disk.""" |
| 5950 | if _kiosk_autostart_paths(): |
| 5951 | return 'autostart' |
| 5952 | if os.path.exists(KIOSK_SERVICE_FILE): |
| 5953 | return 'service' |
| 5954 | return 'not_installed' |
| 5955 | |
| 5956 | |
| 5957 | def _kiosk_running() -> bool: |
| 5958 | """Best-effort: is a kiosk chromium process running right now?""" |
| 5959 | try: |
| 5960 | proc = subprocess.run( |
| 5961 | ['pgrep', '-f', 'ragnar-kiosk-chromium'], |
| 5962 | capture_output=True, text=True, timeout=5, check=False |
| 5963 | ) |
| 5964 | return proc.returncode == 0 and bool(proc.stdout.strip()) |
| 5965 | except Exception: |
| 5966 | return False |
| 5967 | |
| 5968 | |
| 5969 | def _x11_display_for(uid: int) -> str: |
| 5970 | """The DISPLAY of this user's X session, via loginctl. '' when there is none. |
| 5971 | |
| 5972 | Pi OS Desktop is Wayland now, but plenty of boxes still run X11 — the user |
| 5973 | switched it in raspi-config, or the image predates labwc. Those sessions have |
| 5974 | no wayland-* socket at all, which is the only thing the spawn used to look |
| 5975 | for, so enabling the kiosk from the web UI appeared to do nothing until the |
| 5976 | person at the screen logged out and back in. |
| 5977 | """ |
| 5978 | try: |
| 5979 | listing = subprocess.run(['loginctl', 'list-sessions', '--no-legend'], |
| 5980 | capture_output=True, text=True, timeout=5, check=False) |
| 5981 | for line in listing.stdout.splitlines(): |
| 5982 | parts = line.split() |
| 5983 | if not parts: |
| 5984 | continue |
| 5985 | sid = parts[0] |
| 5986 | props = subprocess.run( |
nothing calls this directly
no test coverage detected