mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-10 02:03:57 +08:00
Merge branch commaai/openpilot:master into branch sunnypilot/sunnypilot:master-new
This commit is contained in:
@@ -6,6 +6,19 @@ from cereal import log
|
||||
|
||||
NetworkType = log.DeviceState.NetworkType
|
||||
|
||||
class LPAError(RuntimeError):
|
||||
pass
|
||||
|
||||
class LPAProfileNotFoundError(LPAError):
|
||||
pass
|
||||
|
||||
@dataclass
|
||||
class Profile:
|
||||
iccid: str
|
||||
nickname: str
|
||||
enabled: bool
|
||||
provider: str
|
||||
|
||||
@dataclass
|
||||
class ThermalZone:
|
||||
# a zone from /sys/class/thermal/thermal_zone*
|
||||
@@ -33,6 +46,7 @@ class ThermalZone:
|
||||
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
|
||||
@@ -50,6 +64,31 @@ class ThermalConfig:
|
||||
ret[f.name + "TempC"] = v.read()
|
||||
return ret
|
||||
|
||||
class LPABase(ABC):
|
||||
@abstractmethod
|
||||
def list_profiles(self) -> list[Profile]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_active_profile(self) -> Profile | None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_profile(self, iccid: str) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def download_profile(self, qr: str, nickname: str | None = None) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def nickname_profile(self, iccid: str, nickname: str) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def switch_profile(self, iccid: str) -> None:
|
||||
pass
|
||||
|
||||
class HardwareBase(ABC):
|
||||
@staticmethod
|
||||
def get_cmdline() -> dict[str, str]:
|
||||
@@ -104,6 +143,10 @@ class HardwareBase(ABC):
|
||||
def get_sim_info(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_sim_lpa(self) -> LPABase:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_network_strength(self, network_type):
|
||||
pass
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
from openpilot.system.hardware import HARDWARE
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(prog='esim.py', description='manage eSIM profiles on your comma device', epilog='comma.ai')
|
||||
parser.add_argument('--backend', choices=['qmi', 'at'], default='qmi', help='use the specified backend, defaults to qmi')
|
||||
parser.add_argument('--switch', metavar='iccid', help='switch to profile')
|
||||
parser.add_argument('--delete', metavar='iccid', help='delete profile (warning: this cannot be undone)')
|
||||
parser.add_argument('--download', nargs=2, metavar=('qr', 'name'), help='download a profile using QR code (format: LPA:1$rsp.truphone.com$QRF-SPEEDTEST)')
|
||||
parser.add_argument('--nickname', nargs=2, metavar=('iccid', 'name'), help='update the nickname for a profile')
|
||||
args = parser.parse_args()
|
||||
|
||||
lpa = HARDWARE.get_sim_lpa()
|
||||
if args.switch:
|
||||
lpa.switch_profile(args.switch)
|
||||
elif args.delete:
|
||||
confirm = input('are you sure you want to delete this profile? (y/N) ')
|
||||
if confirm == 'y':
|
||||
lpa.delete_profile(args.delete)
|
||||
print('deleted profile, please restart device to apply changes')
|
||||
else:
|
||||
print('cancelled')
|
||||
exit(0)
|
||||
elif args.download:
|
||||
lpa.download_profile(args.download[0], args.download[1])
|
||||
elif args.nickname:
|
||||
lpa.nickname_profile(args.nickname[0], args.nickname[1])
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
profiles = lpa.list_profiles()
|
||||
print(f'\n{len(profiles)} profile{"s" if len(profiles) > 1 else ""}:')
|
||||
for p in profiles:
|
||||
print(f'- {p.iccid} (nickname: {p.nickname or "<none provided>"}) (provider: {p.provider}) - {"enabled" if p.enabled else "disabled"}')
|
||||
@@ -1,12 +1,11 @@
|
||||
import random
|
||||
|
||||
from cereal import log
|
||||
from openpilot.system.hardware.base import HardwareBase
|
||||
from openpilot.system.hardware.base import HardwareBase, LPABase
|
||||
|
||||
NetworkType = log.DeviceState.NetworkType
|
||||
NetworkStrength = log.DeviceState.NetworkStrength
|
||||
|
||||
|
||||
class Pc(HardwareBase):
|
||||
def get_os_version(self):
|
||||
return None
|
||||
@@ -41,6 +40,9 @@ class Pc(HardwareBase):
|
||||
'data_connected': False
|
||||
}
|
||||
|
||||
def get_sim_lpa(self) -> LPABase:
|
||||
raise NotImplementedError("SIM LPA not implemented for PC")
|
||||
|
||||
def get_network_strength(self, network_type):
|
||||
return NetworkStrength.unknown
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
[
|
||||
{
|
||||
"name": "xbl",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl-468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c.img.xz",
|
||||
"hash": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
|
||||
"hash_raw": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl-6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1.img.xz",
|
||||
"hash": "6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1",
|
||||
"hash_raw": "6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1",
|
||||
"size": 3282256,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "d35a86e7b8ddd9279b513a6f27da1521aa0f89fb93987ea74d57d0f0bbbbd247"
|
||||
"ondevice_hash": "003a17ab1be68a696f7efe4c9938e8be511d4aacfc2f3211fc896bdc1681d089"
|
||||
},
|
||||
{
|
||||
"name": "xbl_config",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b.img.xz",
|
||||
"hash": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
|
||||
"hash_raw": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535.img.xz",
|
||||
"hash": "63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535",
|
||||
"hash_raw": "63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535",
|
||||
"size": 98124,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "623f1568072ee2d687ba8449a3d894c1c83dc4131b2e79eff35696885f70a419"
|
||||
"ondevice_hash": "2a855dd636cc94718b64bea83a44d0a31741ecaa8f72a63613ff348ec7404091"
|
||||
},
|
||||
{
|
||||
"name": "abl",
|
||||
@@ -34,50 +34,50 @@
|
||||
},
|
||||
{
|
||||
"name": "aop",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/aop-f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5.img.xz",
|
||||
"hash": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
|
||||
"hash_raw": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/aop-21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9.img.xz",
|
||||
"hash": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9",
|
||||
"hash_raw": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9",
|
||||
"size": 184364,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "bf74feca486f650589f6b7c90eab73274e35a68b5e00bfc1de0ed5f5484d4b3d"
|
||||
"ondevice_hash": "c1be2f4aac5b3af49b904b027faec418d05efd7bd5144eb4fdfcba602bcf2180"
|
||||
},
|
||||
{
|
||||
"name": "devcfg",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180.img.xz",
|
||||
"hash": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
|
||||
"hash_raw": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620.img.xz",
|
||||
"hash": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620",
|
||||
"hash_raw": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620",
|
||||
"size": 40336,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "70f682b59ca0fe2f197d1486bd8be7b9b7e560798ad40ddef83b9f0a2f497938"
|
||||
"ondevice_hash": "17b229668b20305ff8fa3cd5f94716a3aaa1e5bf9d1c24117eff7f2f81ae719f"
|
||||
},
|
||||
{
|
||||
"name": "boot",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425.img.xz",
|
||||
"hash": "3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425",
|
||||
"hash_raw": "3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968.img.xz",
|
||||
"hash": "eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968",
|
||||
"hash_raw": "eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968",
|
||||
"size": 18479104,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "2075104847d1c96a06f07e85efb9f48d0e792d75a059047eae7ba4b463ffeadf"
|
||||
"ondevice_hash": "800868bd9d340f1fdf8340924caca374409624658324607621663fc5c7d10d4f"
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7.img.xz",
|
||||
"hash": "cb9bfde1e995b97f728f5d5ad8d7a0f7a01544db5d138ead9b2350f222640939",
|
||||
"hash_raw": "b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1.img.xz",
|
||||
"hash": "226794914e9d157b34cc86f1fbe1f2827a9a9919dbe560021b61573a7e5d3101",
|
||||
"hash_raw": "4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1",
|
||||
"size": 5368709120,
|
||||
"sparse": true,
|
||||
"full_check": false,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "e92a1f34158c60364c8d47b8ebbb6e59edf8d4865cd5edfeb2355d6f54f617fc",
|
||||
"ondevice_hash": "236890f04ee21b7eb92a59bc47971bd96cad5a4381ed8935eb4be0cb5a4cf48b",
|
||||
"alt": {
|
||||
"hash": "b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7.img",
|
||||
"hash": "4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1.img",
|
||||
"size": 5368709120
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,25 +130,25 @@
|
||||
},
|
||||
{
|
||||
"name": "xbl",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl-468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c.img.xz",
|
||||
"hash": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
|
||||
"hash_raw": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl-6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1.img.xz",
|
||||
"hash": "6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1",
|
||||
"hash_raw": "6710967ca9701f205d7ab19c3a9b0dd2f547e65b3d96048b7c2b03755aafa0f1",
|
||||
"size": 3282256,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "d35a86e7b8ddd9279b513a6f27da1521aa0f89fb93987ea74d57d0f0bbbbd247"
|
||||
"ondevice_hash": "003a17ab1be68a696f7efe4c9938e8be511d4aacfc2f3211fc896bdc1681d089"
|
||||
},
|
||||
{
|
||||
"name": "xbl_config",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b.img.xz",
|
||||
"hash": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
|
||||
"hash_raw": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535.img.xz",
|
||||
"hash": "63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535",
|
||||
"hash_raw": "63922cfbfdf4ab87986c4ba8f3a4df5bf28414b3f71a29ec5947336722215535",
|
||||
"size": 98124,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "623f1568072ee2d687ba8449a3d894c1c83dc4131b2e79eff35696885f70a419"
|
||||
"ondevice_hash": "2a855dd636cc94718b64bea83a44d0a31741ecaa8f72a63613ff348ec7404091"
|
||||
},
|
||||
{
|
||||
"name": "abl",
|
||||
@@ -163,14 +163,14 @@
|
||||
},
|
||||
{
|
||||
"name": "aop",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/aop-f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5.img.xz",
|
||||
"hash": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
|
||||
"hash_raw": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/aop-21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9.img.xz",
|
||||
"hash": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9",
|
||||
"hash_raw": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9",
|
||||
"size": 184364,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "bf74feca486f650589f6b7c90eab73274e35a68b5e00bfc1de0ed5f5484d4b3d"
|
||||
"ondevice_hash": "c1be2f4aac5b3af49b904b027faec418d05efd7bd5144eb4fdfcba602bcf2180"
|
||||
},
|
||||
{
|
||||
"name": "bluetooth",
|
||||
@@ -207,14 +207,14 @@
|
||||
},
|
||||
{
|
||||
"name": "devcfg",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180.img.xz",
|
||||
"hash": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
|
||||
"hash_raw": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620.img.xz",
|
||||
"hash": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620",
|
||||
"hash_raw": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620",
|
||||
"size": 40336,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "70f682b59ca0fe2f197d1486bd8be7b9b7e560798ad40ddef83b9f0a2f497938"
|
||||
"ondevice_hash": "17b229668b20305ff8fa3cd5f94716a3aaa1e5bf9d1c24117eff7f2f81ae719f"
|
||||
},
|
||||
{
|
||||
"name": "devinfo",
|
||||
@@ -339,62 +339,62 @@
|
||||
},
|
||||
{
|
||||
"name": "boot",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425.img.xz",
|
||||
"hash": "3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425",
|
||||
"hash_raw": "3d8e848796924081f5a6b3d745808b1117ae2ec41c03f2d41ee2e75633bd6425",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/boot-eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968.img.xz",
|
||||
"hash": "eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968",
|
||||
"hash_raw": "eb0dd0a8ffdc1c03aa28d055788d70be885a00f523b552d7acf79b954838e968",
|
||||
"size": 18479104,
|
||||
"sparse": false,
|
||||
"full_check": true,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "2075104847d1c96a06f07e85efb9f48d0e792d75a059047eae7ba4b463ffeadf"
|
||||
"ondevice_hash": "800868bd9d340f1fdf8340924caca374409624658324607621663fc5c7d10d4f"
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7.img.xz",
|
||||
"hash": "cb9bfde1e995b97f728f5d5ad8d7a0f7a01544db5d138ead9b2350f222640939",
|
||||
"hash_raw": "b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1.img.xz",
|
||||
"hash": "226794914e9d157b34cc86f1fbe1f2827a9a9919dbe560021b61573a7e5d3101",
|
||||
"hash_raw": "4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1",
|
||||
"size": 5368709120,
|
||||
"sparse": true,
|
||||
"full_check": false,
|
||||
"has_ab": true,
|
||||
"ondevice_hash": "e92a1f34158c60364c8d47b8ebbb6e59edf8d4865cd5edfeb2355d6f54f617fc",
|
||||
"ondevice_hash": "236890f04ee21b7eb92a59bc47971bd96cad5a4381ed8935eb4be0cb5a4cf48b",
|
||||
"alt": {
|
||||
"hash": "b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-b22bd239c6f9527596fd49b98b7d521a563f99b90953ce021ee36567498e99c7.img",
|
||||
"hash": "4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/system-4c3fa88833a8a3876653fa53a658769ecc64be8fc6f6a28ce520ef79bf3061c1.img",
|
||||
"size": 5368709120
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "userdata_90",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_90-4bb7239f7e82c846e4d2584c0c433f03c582a80950de4094e6c190563d6d84ac.img.xz",
|
||||
"hash": "b18001a2a87caa070fabf6321f8215ac353d6444564e3f86329b4dccc039ce54",
|
||||
"hash_raw": "4bb7239f7e82c846e4d2584c0c433f03c582a80950de4094e6c190563d6d84ac",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_90-f6d24876234f6bea9cc753892eea99ac4b0c8646e93b93d76fc5dddce67347f1.img.xz",
|
||||
"hash": "2485459e9fbfc0d88a59a017bfa193d97b80afed30d6f59db711e53f62a21c72",
|
||||
"hash_raw": "f6d24876234f6bea9cc753892eea99ac4b0c8646e93b93d76fc5dddce67347f1",
|
||||
"size": 96636764160,
|
||||
"sparse": true,
|
||||
"full_check": true,
|
||||
"has_ab": false,
|
||||
"ondevice_hash": "15ce16f2349d5b4d5fec6ad1e36222b1ae744ed10b8930bc9af75bd244dccb3c"
|
||||
"ondevice_hash": "893cfb3e95d6025b9fa6a5c8c3b97bf2abc4ff036c3da846a07536653dbb3a1d"
|
||||
},
|
||||
{
|
||||
"name": "userdata_89",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_89-e36b59bf9ff755b6ca488df2ba1e20da8f7dab6b8843129f3fdcccd7ff2ff7d8.img.xz",
|
||||
"hash": "12682cf54596ab1bd1c2464c4ca85888e4e06b47af5ff7d0432399e9907e2f64",
|
||||
"hash_raw": "e36b59bf9ff755b6ca488df2ba1e20da8f7dab6b8843129f3fdcccd7ff2ff7d8",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_89-14f0f02e53ce62a79b337d7b3174dcaffebaa4130264bb5ed9105d942338230b.img.xz",
|
||||
"hash": "9222aebb280531b7015ee9bab3848dd195567d075b6f37f74d4cd0186685a11f",
|
||||
"hash_raw": "14f0f02e53ce62a79b337d7b3174dcaffebaa4130264bb5ed9105d942338230b",
|
||||
"size": 95563022336,
|
||||
"sparse": true,
|
||||
"full_check": true,
|
||||
"has_ab": false,
|
||||
"ondevice_hash": "e4df9dea47ff04967d971263d50c17460ef240457e8d814e7c4f409f7493eb8a"
|
||||
"ondevice_hash": "a5459ec858d39e3d0709a09af430cb644fe640f92e0cd216b138f01401e4e17e"
|
||||
},
|
||||
{
|
||||
"name": "userdata_30",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_30-fe1d86f5322c675c58b3ae9753a4670abf44a25746bf6ac822aed108bb577282.img.xz",
|
||||
"hash": "fa471703be0f0647617d183312d5209d23407f1628e4ab0934e6ec54b1a6b263",
|
||||
"hash_raw": "fe1d86f5322c675c58b3ae9753a4670abf44a25746bf6ac822aed108bb577282",
|
||||
"url": "https://commadist.azureedge.net/agnosupdate/userdata_30-180ad331538f20c00218d41591afed3a25bb0f76fa30b1a665cad102cf6c9f7d.img.xz",
|
||||
"hash": "7fc09317f005676150bfcced43ebb1aa919d854c2511d547a588a35c1122bfe3",
|
||||
"hash_raw": "180ad331538f20c00218d41591afed3a25bb0f76fa30b1a665cad102cf6c9f7d",
|
||||
"size": 32212254720,
|
||||
"sparse": true,
|
||||
"full_check": true,
|
||||
"has_ab": false,
|
||||
"ondevice_hash": "0b5b2402c9caa1ed7b832818e66580c974251e735bda91f2f226c41499d5616e"
|
||||
"ondevice_hash": "1a2f2d14c922bd2895073446460a0bd680711a7b14318a4402631635e6d133b3"
|
||||
}
|
||||
]
|
||||
Executable → Regular
+88
-92
@@ -1,115 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import math
|
||||
import time
|
||||
import binascii
|
||||
import requests
|
||||
import serial
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import Literal
|
||||
|
||||
from openpilot.system.hardware.base import LPABase, LPAError, LPAProfileNotFoundError, Profile
|
||||
|
||||
def post(url, payload):
|
||||
print()
|
||||
print("POST to", url)
|
||||
r = requests.post(
|
||||
url,
|
||||
data=payload,
|
||||
verify=False,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"X-Admin-Protocol": "gsma/rsp/v2.2.0",
|
||||
"charset": "utf-8",
|
||||
"User-Agent": "gsma-rsp-lpad",
|
||||
},
|
||||
)
|
||||
print("resp", r)
|
||||
print("resp text", repr(r.text))
|
||||
print()
|
||||
r.raise_for_status()
|
||||
class TiciLPA(LPABase):
|
||||
def __init__(self, interface: Literal['qmi', 'at'] = 'qmi'):
|
||||
self.env = os.environ.copy()
|
||||
self.env['LPAC_APDU'] = interface
|
||||
self.env['QMI_DEVICE'] = '/dev/cdc-wdm0'
|
||||
self.env['AT_DEVICE'] = '/dev/ttyUSB2'
|
||||
|
||||
ret = f"HTTP/1.1 {r.status_code}"
|
||||
ret += ''.join(f"{k}: {v}" for k, v in r.headers.items() if k != 'Connection')
|
||||
return ret.encode() + r.content
|
||||
self.timeout_sec = 45
|
||||
|
||||
if shutil.which('lpac') is None:
|
||||
raise LPAError('lpac not found, must be installed!')
|
||||
|
||||
class LPA:
|
||||
def __init__(self):
|
||||
self.dev = serial.Serial('/dev/ttyUSB2', baudrate=57600, timeout=1, bytesize=8)
|
||||
self.dev.reset_input_buffer()
|
||||
self.dev.reset_output_buffer()
|
||||
assert "OK" in self.at("AT")
|
||||
def list_profiles(self) -> list[Profile]:
|
||||
msgs = self._invoke('profile', 'list')
|
||||
self._validate_successful(msgs)
|
||||
return [Profile(
|
||||
iccid=p['iccid'],
|
||||
nickname=p['profileNickname'],
|
||||
enabled=p['profileState'] == 'enabled',
|
||||
provider=p['serviceProviderName']
|
||||
) for p in msgs[-1]['payload']['data']]
|
||||
|
||||
def at(self, cmd):
|
||||
print(f"==> {cmd}")
|
||||
self.dev.write(cmd.encode() + b'\r\n')
|
||||
def get_active_profile(self) -> Profile | None:
|
||||
return next((p for p in self.list_profiles() if p.enabled), None)
|
||||
|
||||
r = b""
|
||||
cnt = 0
|
||||
while b"OK" not in r and b"ERROR" not in r and cnt < 20:
|
||||
r += self.dev.read(8192).strip()
|
||||
cnt += 1
|
||||
r = r.decode()
|
||||
print(f"<== {repr(r)}")
|
||||
return r
|
||||
def delete_profile(self, iccid: str) -> None:
|
||||
self._validate_profile_exists(iccid)
|
||||
latest = self.get_active_profile()
|
||||
if latest is not None and latest.iccid == iccid:
|
||||
raise LPAError('cannot delete active profile, switch to another profile first')
|
||||
self._validate_successful(self._invoke('profile', 'delete', iccid))
|
||||
self._process_notifications()
|
||||
|
||||
def download_ota(self, qr):
|
||||
return self.at(f'AT+QESIM="ota","{qr}"')
|
||||
def download_profile(self, qr: str, nickname: str | None = None) -> None:
|
||||
msgs = self._invoke('profile', 'download', '-a', qr)
|
||||
self._validate_successful(msgs)
|
||||
new_profile = next((m for m in msgs if m['payload']['message'] == 'es8p_meatadata_parse'), None)
|
||||
if new_profile is None:
|
||||
raise LPAError('no new profile found')
|
||||
if nickname:
|
||||
self.nickname_profile(new_profile['payload']['data']['iccid'], nickname)
|
||||
self._process_notifications()
|
||||
|
||||
def download(self, qr):
|
||||
smdp = qr.split('$')[1]
|
||||
out = self.at(f'AT+QESIM="download","{qr}"')
|
||||
for _ in range(5):
|
||||
line = out.split("+QESIM: ")[1].split("\r\n\r\nOK")[0]
|
||||
def nickname_profile(self, iccid: str, nickname: str) -> None:
|
||||
self._validate_profile_exists(iccid)
|
||||
self._validate_successful(self._invoke('profile', 'nickname', iccid, nickname))
|
||||
|
||||
parts = [x.strip().strip('"') for x in line.split(',', maxsplit=4)]
|
||||
print(repr(parts))
|
||||
trans, ret, url, payloadlen, payload = parts
|
||||
assert trans == "trans" and ret == "0"
|
||||
assert len(payload) == int(payloadlen)
|
||||
def switch_profile(self, iccid: str) -> None:
|
||||
self._enable_profile(iccid)
|
||||
|
||||
r = post(f"https://{smdp}/{url}", payload)
|
||||
to_send = binascii.hexlify(r).decode()
|
||||
def _enable_profile(self, iccid: str) -> None:
|
||||
self._validate_profile_exists(iccid)
|
||||
latest = self.get_active_profile()
|
||||
if latest:
|
||||
if latest.iccid == iccid:
|
||||
return
|
||||
self._validate_successful(self._invoke('profile', 'disable', latest.iccid))
|
||||
self._validate_successful(self._invoke('profile', 'enable', iccid))
|
||||
self._process_notifications()
|
||||
|
||||
chunk_len = 1400
|
||||
for i in range(math.ceil(len(to_send) / chunk_len)):
|
||||
state = 1 if (i+1)*chunk_len < len(to_send) else 0
|
||||
data = to_send[i * chunk_len : (i+1)*chunk_len]
|
||||
out = self.at(f'AT+QESIM="trans",{len(to_send)},{state},{i},{len(data)},"{data}"')
|
||||
assert "OK" in out
|
||||
def _invoke(self, *cmd: str):
|
||||
proc = subprocess.Popen(['sudo', '-E', 'lpac'] + list(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self.env)
|
||||
try:
|
||||
out, err = proc.communicate(timeout=self.timeout_sec)
|
||||
except subprocess.TimeoutExpired as e:
|
||||
proc.kill()
|
||||
raise LPAError(f"lpac {cmd} timed out after {self.timeout_sec} seconds") from e
|
||||
|
||||
if '+QESIM:"download",1' in out:
|
||||
raise Exception("profile install failed")
|
||||
elif '+QESIM:"download",0' in out:
|
||||
print("done, successfully loaded")
|
||||
break
|
||||
messages = []
|
||||
for line in out.decode().strip().splitlines():
|
||||
if line.startswith('{'):
|
||||
message = json.loads(line)
|
||||
|
||||
def enable(self, iccid):
|
||||
self.at(f'AT+QESIM="enable","{iccid}"')
|
||||
# lpac response format validations
|
||||
assert 'type' in message, 'expected type in message'
|
||||
assert message['type'] == 'lpa' or message['type'] == 'progress', 'expected lpa or progress message type'
|
||||
assert 'payload' in message, 'expected payload in message'
|
||||
assert 'code' in message['payload'], 'expected code in message payload'
|
||||
assert 'data' in message['payload'], 'expected data in message payload'
|
||||
|
||||
def disable(self, iccid):
|
||||
self.at(f'AT+QESIM="disable","{iccid}"')
|
||||
msg_ret_code = message['payload']['code']
|
||||
if msg_ret_code != 0:
|
||||
raise LPAError(f"lpac {' '.join(cmd)} failed with code {msg_ret_code}: <{message['payload']['message']}> {message['payload']['data']}")
|
||||
|
||||
def delete(self, iccid):
|
||||
self.at(f'AT+QESIM="delete","{iccid}"')
|
||||
messages.append(message)
|
||||
|
||||
def list_profiles(self):
|
||||
out = self.at('AT+QESIM="list"')
|
||||
return out.strip().splitlines()[1:]
|
||||
if len(messages) == 0:
|
||||
raise LPAError(f"lpac {cmd} returned no messages")
|
||||
|
||||
return messages
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
def _process_notifications(self) -> None:
|
||||
"""
|
||||
Process notifications stored on the eUICC, typically to activate/deactivate the profile with the carrier.
|
||||
"""
|
||||
self._validate_successful(self._invoke('notification', 'process', '-a', '-r'))
|
||||
|
||||
if "RESTART" in os.environ:
|
||||
subprocess.check_call("sudo systemctl stop ModemManager", shell=True)
|
||||
subprocess.check_call("/usr/comma/lte/lte.sh stop_blocking", shell=True)
|
||||
subprocess.check_call("/usr/comma/lte/lte.sh start", shell=True)
|
||||
while not os.path.exists('/dev/ttyUSB2'):
|
||||
time.sleep(1)
|
||||
time.sleep(3)
|
||||
def _validate_profile_exists(self, iccid: str) -> None:
|
||||
if not any(p.iccid == iccid for p in self.list_profiles()):
|
||||
raise LPAProfileNotFoundError(f'profile {iccid} does not exist')
|
||||
|
||||
lpa = LPA()
|
||||
print(lpa.list_profiles())
|
||||
if len(sys.argv) > 1:
|
||||
lpa.download(sys.argv[1])
|
||||
print(lpa.list_profiles())
|
||||
def _validate_successful(self, msgs: list[dict]) -> None:
|
||||
assert msgs[-1]['payload']['message'] == 'success', 'expected success notification'
|
||||
|
||||
@@ -10,8 +10,9 @@ from pathlib import Path
|
||||
|
||||
from cereal import log
|
||||
from openpilot.common.gpio import gpio_set, gpio_init, get_irqs_for_action
|
||||
from openpilot.system.hardware.base import HardwareBase, ThermalConfig, ThermalZone
|
||||
from openpilot.system.hardware.base import HardwareBase, LPABase, ThermalConfig, ThermalZone
|
||||
from openpilot.system.hardware.tici import iwlist
|
||||
from openpilot.system.hardware.tici.esim import TiciLPA
|
||||
from openpilot.system.hardware.tici.pins import GPIO
|
||||
from openpilot.system.hardware.tici.amplifier import Amplifier
|
||||
|
||||
@@ -198,6 +199,9 @@ class Tici(HardwareBase):
|
||||
'data_connected': modem.Get(MM_MODEM, 'State', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) == MM_MODEM_STATE.CONNECTED,
|
||||
}
|
||||
|
||||
def get_sim_lpa(self) -> LPABase:
|
||||
return TiciLPA()
|
||||
|
||||
def get_imei(self, slot):
|
||||
if slot != 0:
|
||||
return ""
|
||||
@@ -297,13 +301,11 @@ class Tici(HardwareBase):
|
||||
return None
|
||||
|
||||
def get_modem_temperatures(self):
|
||||
if self.get_device_type() == "mici":
|
||||
return []
|
||||
timeout = 0.2 # Default timeout is too short
|
||||
try:
|
||||
modem = self.get_modem()
|
||||
temps = modem.Command("AT+QTEMP", math.ceil(timeout), dbus_interface=MM_MODEM, timeout=timeout)
|
||||
return list(map(int, temps.split(' ')[1].split(',')))
|
||||
return list(filter(lambda t: t != 255, map(int, temps.split(' ')[1].split(','))))
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
@@ -335,6 +337,7 @@ class Tici(HardwareBase):
|
||||
return ThermalConfig(cpu=[ThermalZone(f"cpu{i}-silver-usr") for i in range(4)] +
|
||||
[ThermalZone(f"cpu{i}-gold-usr") for i in range(4)],
|
||||
gpu=[ThermalZone("gpu0-usr"), ThermalZone("gpu1-usr")],
|
||||
dsp=ThermalZone("compute-hvx-usr"),
|
||||
memory=ThermalZone("ddr-usr"),
|
||||
pmic=[ThermalZone("pm8998_tz"), ThermalZone("pm8005_tz")],
|
||||
intake=intake,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import pytest
|
||||
|
||||
from openpilot.system.hardware import HARDWARE, TICI
|
||||
from openpilot.system.hardware.base import LPAProfileNotFoundError
|
||||
|
||||
# https://euicc-manual.osmocom.org/docs/rsp/known-test-profile
|
||||
# iccid is always the same for the given activation code
|
||||
TEST_ACTIVATION_CODE = 'LPA:1$rsp.truphone.com$QRF-BETTERROAMING-PMRDGIR2EARDEIT5'
|
||||
TEST_ICCID = '8944476500001944011'
|
||||
|
||||
TEST_NICKNAME = 'test_profile'
|
||||
|
||||
def cleanup():
|
||||
lpa = HARDWARE.get_sim_lpa()
|
||||
try:
|
||||
lpa.delete_profile(TEST_ICCID)
|
||||
except LPAProfileNotFoundError:
|
||||
pass
|
||||
lpa.process_notifications()
|
||||
|
||||
class TestEsim:
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
if not TICI:
|
||||
pytest.skip()
|
||||
cleanup()
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
cleanup()
|
||||
|
||||
def test_provision_enable_disable(self):
|
||||
lpa = HARDWARE.get_sim_lpa()
|
||||
current_active = lpa.get_active_profile()
|
||||
|
||||
lpa.download_profile(TEST_ACTIVATION_CODE, TEST_NICKNAME)
|
||||
assert any(p.iccid == TEST_ICCID and p.nickname == TEST_NICKNAME for p in lpa.list_profiles())
|
||||
|
||||
lpa.enable_profile(TEST_ICCID)
|
||||
new_active = lpa.get_active_profile()
|
||||
assert new_active is not None
|
||||
assert new_active.iccid == TEST_ICCID
|
||||
assert new_active.nickname == TEST_NICKNAME
|
||||
|
||||
lpa.disable_profile(TEST_ICCID)
|
||||
new_active = lpa.get_active_profile()
|
||||
assert new_active is None
|
||||
|
||||
if current_active:
|
||||
lpa.enable_profile(current_active.iccid)
|
||||
@@ -33,7 +33,7 @@ class Proc:
|
||||
PROCS = [
|
||||
Proc(['camerad'], 1.75, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']),
|
||||
Proc(['modeld'], 1.12, atol=0.2, msgs=['modelV2']),
|
||||
Proc(['dmonitoringmodeld'], 1.4, msgs=['driverStateV2']),
|
||||
Proc(['dmonitoringmodeld'], 0.6, msgs=['driverStateV2']),
|
||||
Proc(['encoderd'], 0.23, msgs=[]),
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user