mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-18 12:33:43 +08:00
25d9d41c90
* esim: MICI eSIM profile management UI * esim: align rename button position regardless of delete button * esim: skip profile UI when SIM is not an eUICC Probe is_euicc() on the first profile poll and cache it; non-eUICC SIMs avoid list_profiles/process_notifications (which hang on a plain SIM) and the eSIM button shows ICCID/MCC-MNC metadata instead of opening the profile management screen. * esim: satisfy ruff E731 in action_pressed helper * esim: get modem info from modem.py state instead of shelling out * esim: simplify switch lifecycle, drop active flag and settle window * esim: only show 'switching...' on the target profile * esim: read cell strength directly from HARDWARE * esim: hide checkmark and dim cell icon during switch; keep rename available * esim: disable active profile button (rename still clickable as overlay) * esim: stop rename/delete buttons and labels from flashing during operations * esim: show 'comma prime' on network button for comma profile * esim: move display_name and is_comma onto Profile dataclass * esim: anchor rename button to rightmost slot to prevent shift * esim: include iccid prefix check in Profile.is_comma * esim: drop process_notifications from cellular manager * esim: disable network button when SIM isn't an eUICC * esim: rename ESim* classes to Esim* * esim: sort imports * esim: default to 'loading...' instead of 'no active profile' * esim: rename PROFILE_POLL_INTERVAL to PROFILE_POLL_INTERVAL_S * esim: slim EsimNetworkButton * esim: use DEFAULT_TEXT_COLOR; load delete dialog texture in __init__ * esim: revert cell-icon index trick, name each NetworkStrength explicitly * esim: tighten delete/rename spacing so 'switch' label fits on one line * esim: shrink delete/rename buttons by 25% * esim: keep rename button at full size, only delete shrinks * Revert "disable modem.py for now" This reverts commit1eeba86ec1. * Revert "modem.py is disabled" This reverts commitd238a1ccc4. * lpa: inline comma iccid prefix * ui/cellular_manager: clear switching state when LPA returns * ui/cellular_manager: lock callback queue, drop poll log noise * esim: sort NetworkStrength/NetworkType imports * esim: drop switching_iccid concept * esim: show 'switching...' on the clicked profile button * esim: optimistic switch, skip post-switch list_profiles to avoid flicker * esim: only style profile button from local op flags, not global busy * esim: remove deleting/switching state, collapse profile button branches * esim: show GSM settings on full prime when non-comma profile is active * esim: expose CellularManager.active_profile, dedup callers * esim: apply comma prime defaults on switch (roaming, metered, no APN) * esim: restore re_sort on show_event to avoid first-frame jank * lpa: apply comma prime defaults inside TiciLPA.switch_profile * lpa: lazy-import Params to break circular import * lpa: treat +CME ERROR 13 (SIM failure) as non-eUICC in is_euicc * esim: show 'obtaining IP...' on non-eUICC path while connecting * Revert "lpa: treat +CME ERROR 13 (SIM failure) as non-eUICC in is_euicc" This reverts commit 475ca448ea914ff8f9892b4cbf4525d961d7618b. * esim: poll profiles every 5s * lpa: tighten Profile.is_comma to require both Webbing provider and comma BIN * lpa: fall back to '<unnamed>' instead of iccid prefix in display_name * esim: re-probe is_euicc each poll for runtime SIM swaps * esim_ui: rename EsimUIMici to EsimUI * esim: simplify cellular manager and profile UI - optimistic profile switch at click time so the active button no longer bounces back - unify LPA worker threads, refresh_profiles resets the poll timer - deterministic profile ordering on show - reuse wifi ForgetButton for delete, drop DeleteButton - construct CellularManager inside NetworkLayoutMici - drop comma prime param defaults from LPA.switch_profile (moved to a separate PR) * esim: drop eUICC state change log * ui: gate cellular settings on prime subscription * ui: disable eSIM management for full prime * ui: keep eSIM management disabled for full prime * ui: unify eSIM profile action buttons * ui: tighten eSIM profile action spacing * ui: place rename before delete in eSIM actions * esim: restrict individual profiles and process switch notifications * esim: defer poll after operations and confirm eUICC loss before clearing profiles * ui: allow cellular settings for unregistered and unpaired devices * ui: disable all profile switching for full prime * ui: simplify cellular access to not full prime * ui: make profile poll interval a CellularManager constant * ui: read modem state on the profile poll cadence * ui: scope eSIM profile colors to their class * ui: inline modem state read in cellular polling * ui: rely on hardware modem state fallback
165 lines
3.8 KiB
Python
165 lines
3.8 KiB
Python
import os
|
|
from abc import abstractmethod, ABC
|
|
from dataclasses import dataclass, fields
|
|
|
|
from openpilot.cereal import log
|
|
from openpilot.common.esim.base import LPABase
|
|
|
|
NetworkType = log.DeviceState.NetworkType
|
|
NetworkStrength = log.DeviceState.NetworkStrength
|
|
|
|
@dataclass
|
|
class ThermalZone:
|
|
# a zone from /sys/class/thermal/thermal_zone*
|
|
name: str # a.k.a type
|
|
scale: float = 1000. # scale to get degrees in C
|
|
zone_number = -1
|
|
|
|
def read(self) -> float:
|
|
if self.zone_number < 0:
|
|
for n in os.listdir("/sys/devices/virtual/thermal"):
|
|
if not n.startswith("thermal_zone"):
|
|
continue
|
|
with open(os.path.join("/sys/devices/virtual/thermal", n, "type")) as f:
|
|
if f.read().strip() == self.name:
|
|
self.zone_number = int(n.removeprefix("thermal_zone"))
|
|
break
|
|
|
|
try:
|
|
with open(f"/sys/devices/virtual/thermal/thermal_zone{self.zone_number}/temp") as f:
|
|
return int(f.read()) / self.scale
|
|
except FileNotFoundError:
|
|
return 0
|
|
|
|
@dataclass
|
|
class ThermalConfig:
|
|
cpu: list[ThermalZone] | None = None
|
|
gpu: list[ThermalZone] | None = None
|
|
dsp: ThermalZone | None = None
|
|
pmic: list[ThermalZone] | None = None
|
|
memory: ThermalZone | None = None
|
|
intake: ThermalZone | None = None
|
|
exhaust: ThermalZone | None = None
|
|
gnss: ThermalZone | None = None
|
|
bottomSoc: ThermalZone | None = None
|
|
|
|
def get_msg(self):
|
|
ret = {}
|
|
for f in fields(ThermalConfig):
|
|
v = getattr(self, f.name)
|
|
if v is not None:
|
|
if isinstance(v, list):
|
|
ret[f.name + "TempC"] = [x.read() for x in v]
|
|
else:
|
|
ret[f.name + "TempC"] = v.read()
|
|
return ret
|
|
|
|
class HardwareBase(ABC):
|
|
@staticmethod
|
|
def get_cmdline() -> dict[str, str]:
|
|
with open('/proc/cmdline') as f:
|
|
cmdline = f.read()
|
|
return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2}
|
|
|
|
@staticmethod
|
|
def read_param_file(path, parser, default=0):
|
|
try:
|
|
with open(path) as f:
|
|
return parser(f.read())
|
|
except Exception:
|
|
return default
|
|
|
|
def booted(self) -> bool:
|
|
return True
|
|
|
|
def reboot(self, reason=None):
|
|
print("REBOOT!")
|
|
|
|
def uninstall(self):
|
|
print("uninstall")
|
|
|
|
def get_os_version(self):
|
|
return None
|
|
|
|
@abstractmethod
|
|
def get_device_type(self):
|
|
pass
|
|
|
|
def get_imei(self) -> str:
|
|
return ""
|
|
|
|
def get_serial(self):
|
|
return ""
|
|
|
|
def get_network_info(self):
|
|
return None
|
|
|
|
def get_network_type(self):
|
|
return NetworkType.none
|
|
|
|
def get_sim_info(self):
|
|
return {
|
|
'sim_id': '',
|
|
'mcc_mnc': None,
|
|
'network_type': ["Unknown"],
|
|
'sim_state': ["ABSENT"],
|
|
'data_connected': False
|
|
}
|
|
|
|
def get_sim_lpa(self) -> LPABase:
|
|
raise NotImplementedError("SIM LPA not available")
|
|
|
|
def get_network_strength(self, network_type):
|
|
return NetworkStrength.unknown
|
|
|
|
def get_network_metered(self, network_type) -> bool:
|
|
return network_type not in (NetworkType.none, NetworkType.wifi, NetworkType.ethernet)
|
|
|
|
def get_current_power_draw(self):
|
|
return 0
|
|
|
|
def get_som_power_draw(self):
|
|
return 0
|
|
|
|
def shutdown(self):
|
|
print("SHUTDOWN!")
|
|
|
|
def get_thermal_config(self):
|
|
return ThermalConfig()
|
|
|
|
def set_display_power(self, on: bool):
|
|
pass
|
|
|
|
def set_screen_brightness(self, percentage):
|
|
pass
|
|
|
|
def get_screen_brightness(self):
|
|
return 0
|
|
|
|
def set_power_save(self, powersave_enabled):
|
|
pass
|
|
|
|
def get_gpu_usage_percent(self):
|
|
return 0
|
|
|
|
def get_modem_temperatures(self):
|
|
return []
|
|
|
|
def get_modem_state(self) -> dict:
|
|
return {}
|
|
|
|
def initialize_hardware(self):
|
|
pass
|
|
|
|
def reset_internal_panda(self):
|
|
pass
|
|
|
|
def recover_internal_panda(self):
|
|
pass
|
|
|
|
def get_modem_data_usage(self):
|
|
return -1, -1
|
|
|
|
def set_ir_power(self, percent: int):
|
|
pass
|