#!/usr/bin/env python3
import argparse
import time
from openpilot . system . hardware import HARDWARE
from openpilot . system . hardware . base import LPABase
def bootstrap ( lpa : LPABase ) - > None :
print ( ' ┌──────────────────────────────────────────────────────────────────────────────┐ ' )
print ( ' │ WARNING, PLEASE READ BEFORE PROCEEDING │ ' )
print ( ' │ │ ' )
print ( ' │ this is an irreversible operation that will remove the comma-provisioned │ ' )
print ( ' │ profile. │ ' )
print ( ' │ │ ' )
print ( ' │ after this operation, you must purchase a new eSIM from comma in order to │ ' )
print ( ' │ use the comma prime subscription again. │ ' )
print ( ' └──────────────────────────────────────────────────────────────────────────────┘ ' )
print ( )
for severity in ( ' sure ' , ' 100 % s ure ' ) :
print ( f ' are you { severity } you want to proceed? (y/N) ' , end = ' ' )
confirm = input ( )
if confirm != ' y ' :
print ( ' aborting ' )
exit ( 0 )
lpa . bootstrap ( )
if __name__ == ' __main__ ' :
parser = argparse . ArgumentParser ( prog = ' esim.py ' , description = ' manage eSIM profiles on your comma device ' , epilog = ' comma.ai ' )
parser . add_argument ( ' --bootstrap ' , action = ' store_true ' , help = ' bootstrap the eUICC (required before downloading profiles) ' )
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 ( )
mutated = False
lpa = HARDWARE . get_sim_lpa ( )
if args . bootstrap :
bootstrap ( lpa )
mutated = True
elif args . switch :
lpa . switch_profile ( args . switch )
mutated = True
elif args . delete :
confirm = input ( ' are you sure you want to delete this profile? (y/N) ' )
if confirm == ' y ' :
lpa . delete_profile ( args . delete )
mutated = True
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 ( )
if mutated :
HARDWARE . reboot_modem ( )
# eUICC needs a small delay post-reboot before querying profiles
time . sleep ( .5 )
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 " } ' )