#!/usr/bin/env python3 import serial import sys import time import os import configparser import gpiod config_dump = __import__("modem-config-dump") SERIAL_DEV = '/dev/ttyACM0' WWAN_DEV = '/sys/class/net/wwan0' SIM_CONFIG = '/etc/sim.conf' APN_CONFIG = '/etc/apn.conf' def execute_and_check(ser, cmd): tries = 0 MAX_TRY = 5 ser.flushInput() ser.write(cmd) ser.write(b'\r') s = ser.read_until(b'OK') if b'OK' not in s: print("Failed cmd : " + str(cmd)) print("Output: " + str(s)) tries += 1 if tries < MAX_TRY: time.sleep(1) execute_and_check(ser, cmd) else: sys.exit(-1) tries = 0 def switch_sim(): line = gpiod.find_line('SIM_SW') line.request(consumer='ublox-config', type=gpiod.LINE_REQ_DIR_OUT) line.set_value(0) def sim_present(ser): cmd = b'AT+CCID?' while True: try: ser.flushInput() ser.write(cmd) ser.write(b'\r') s = ser.read_until(b'OK') if b'ERROR' in s: return False elif b'OK' in s: return True except Exception as e: print("Exception : " + str(e)) time.sleep(1) return s def check_sim_presence(ser): if sim_present(ser): print("sim present") return False else: print("no sim, switching to esim") switch_sim() return True def sim_config(ser): config = configparser.ConfigParser() config.read(SIM_CONFIG) sim = config.get('default', 'SIM') print(sim) if sim == 'auto': return check_sim_presence(ser) elif sim == 'esim' or sim == 'ui-top': switch_sim() return True # ui-btm and main are default return False def apn_setup(ser): if not os.path.exists(APN_CONFIG): print('No APN configured') return config = configparser.ConfigParser() config.read(APN_CONFIG) try: apn = config.get('default', 'apn') except: print('apn.conf malformed : no apn found\n') return try: user = '"' + config.get('default', 'user') + '"' try: password = '"' + config.get('default', 'password') + '"' except: print("No password for APN") password = 'NULL' except: print("No user for APN") user = 'NULL' password = 'NULL' if not apn: return auth = '1' if user is not 'NULL' else '0' print("Switching to airplane mode") execute_and_check(ser, b'AT+CFUN=4\r') print("Configuring default ctx") cmd = 'AT+UCGDFLT=0,"IP","' + str(apn) + '",0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,' + auth + ',' + str(user) + ',' + str(password) + ',""\r' execute_and_check(ser, bytes(cmd, 'utf8')) print("Full functionality mode") execute_and_check(ser, b'AT+CFUN=1\r') def poweroff(gpio): print('poweroff') if not os.path.exists(SERIAL_DEV): print('serial interface is not available') gpio.set_value(0) return -1 ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5) ser.write(b'AT+CPWROFF\r') ser.close() time.sleep(2) gpio.set_value(0) def main(): line = gpiod.find_line('GSM_SUP_EN') line.request(consumer='ublox-config', type=gpiod.LINE_REQ_DIR_OUT) if len(sys.argv) == 2 and sys.argv[1] == 'stop': return poweroff(line) # Power on line.set_value(1) # Wait on device while not os.path.exists(SERIAL_DEV): time.sleep(1) ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5) rst = False if not os.path.exists(WWAN_DEV): print("Setting up bridge mode") execute_and_check(ser, b'AT+UBMCONF=2') print("Setting up USB mode to ECM") execute_and_check(ser, b'AT+UUSBCONF=2,"ECM",0') rst = True rst = sim_config(ser) or rst if rst: print("Resetting modem") ser.write(b'AT+CFUN=16\r') ser.close() while os.path.exists(SERIAL_DEV): time.sleep(1) while not os.path.exists(SERIAL_DEV): time.sleep(1) ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5) apn_setup(ser) config_dump.dump_modem_config(ser) ser.close() if __name__ == '__main__': main()