VulpesOS/tundra/runtime/hardware-status.py
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

64 lines
2.4 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Publish read-only hardware state. No SSIDs, IP addresses or modem identifiers."""
import argparse
import json
import os
from pathlib import Path
import subprocess
import time
def battery_state(root=Path('/sys/class/power_supply/battery')):
try:
level = int((root/'capacity').read_text().strip())
status = (root/'status').read_text().strip()
if not 0 <= level <= 100 or status not in ('Charging', 'Discharging', 'Full', 'Not charging'):
return None
return {'level': level/100, 'charging': status in ('Charging', 'Full'), 'status': status}
except (OSError, ValueError):
return None
def wifi_state():
try:
result = subprocess.run(['nmcli', '-g', 'GENERAL.STATE', 'device', 'show', 'wlan0'],
capture_output=True, text=True, timeout=3,
env={**os.environ, 'LC_ALL': 'C'})
if result.returncode:
return {'available': False, 'state': 'unavailable'}
state = int(result.stdout.split()[0])
names = {10:'unmanaged', 20:'unavailable', 30:'disconnected', 40:'connecting',
50:'connecting', 60:'authentication', 70:'connecting', 80:'connecting',
90:'connecting', 100:'connected', 110:'disconnecting', 120:'failed'}
return {'available': state >= 30, 'state': names.get(state, 'unknown')}
except (OSError, ValueError, IndexError, subprocess.TimeoutExpired):
return {'available': False, 'state': 'unavailable'}
def snapshot():
# Do not D-Bus-activate NetworkManager from an otherwise display-only boot.
wifi = wifi_state() if Path('/etc/tundra/network-enabled').is_file() else {
'available': False, 'state': 'unavailable'}
return {'schema': 1, 'recordedAt': time.time(), 'battery': battery_state(), 'wifi': wifi}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--once', action='store_true')
args = parser.parse_args()
if args.once:
print(json.dumps(snapshot()))
return
output = Path('/run/tundra-hardware/status.json')
output.parent.mkdir(mode=0o755, exist_ok=True)
while True:
temporary = output.with_suffix('.tmp')
temporary.write_text(json.dumps(snapshot())+'\n')
temporary.chmod(0o644)
temporary.replace(output)
time.sleep(5)
if __name__ == '__main__':
main()