#!/bin/bash # # Date: 12/2024 # Author: Industrial Shields® # Hardware: UPSafePI and SARA R412M # Description: # This script prompts the user for the ISP's APN, username, password, and the desired RAT as parameters. # It then configures the modem by passing AT commands and connects to the network using CHAP authentication. # Finally, it creates a service named pppd so that the desired RAT (LTE Cat M1, NB-IoT, or GPRS/eGPRS) # is automatically configured with a network interface called ppp0 every time the Raspberry PI is started. set -euo pipefail PHONE="*99***1#" LTE="LTE Cat M1 or Long Term Evolution (4G) category M1" NB="Narrow Band IoT (NB-IoT)" GPRS="GPRS/eGPRS" echo "Please enter your APN" read APN echo -e "\r\nPlease enter your ISP username" read USERNAME echo -e "\r\nPlease enter your ISP password" read PASSWORD echo -e "\r\nPlease select the desired Radio Access Technology (1, 2 or 3):" echo "--> 1: ${LTE}" echo "--> 2: ${NB}" echo "--> 3: ${GPRS}" read VALUE if [[ $VALUE =~ ^[1-3]$ ]]; then case $VALUE in 1) RAT="lte-m" ;; 2) RAT="nb-iot" ;; 3) RAT="gprs" ;; esac else echo "Invalid value. Please enter a value between 1 and 3." exit 1 fi SERVICE="pppd" ###################################################################### cat > /lib/systemd/system/${SERVICE}.service <> /etc/systemd/system.conf fi ###################################################################### cat > /etc/ppp/options < /etc/ppp/chap-secrets < /usr/local/bin/network-setup.py <= min_value and csq_value != 99.99: return True time.sleep(0.2) return False ###################################################################### def open_port(baud_rate): print(f'opening serial port {serial_port} with baud rate {baud_rate} ...') port = serial.Serial(serial_port, baud_rate, timeout=1) print('ok') port.flushInput() time.sleep(1) print('ok') return port ###################################################################### def write_cmd(ser, cmd): if cmd != '+++': cmd = f'AT{cmd}\r\n' print(f">> Sending {cmd}") ser.write(cmd.encode('utf-8')) ###################################################################### def read_response(ser, timeout=0.2): start_time = time.time() rx = b'' count = 0 while (time.time() - start_time) < timeout: rx_bytes = ser.inWaiting() if rx_bytes: rx += ser.read(rx_bytes) if rx.endswith(b'OK\r\n') or rx.endswith(b'150000000\r\n'): return rx.decode('utf-8', errors='ignore') return None ###################################################################### def manage_fails(ser, cmd_fails): print(f"{cmd_fails} commands failed") if cmd_fails >= 4: close_port(ser) main() sys.exit(0) ###################################################################### def send_at_until_ok(ser): while True: write_cmd(ser, '') time.sleep(0.1) response = read_response(ser, 1) if response is not None and 'OK' in response: ser.flush() print("Ready") break ###################################################################### def send_at(ser, cmd, tries=5, timeout=1): write_cmd(ser, cmd) for i in range(tries): response = read_response(ser, timeout) print(f'{response}') if response is not None: return response print(f"No response for {cmd} command") return None ###################################################################### def clear_pppd(): try: output = subprocess.check_output(['pgrep', 'pppd'], stderr=subprocess.STDOUT) if output: subprocess.call(['sudo', 'killall', 'pppd']) subprocess.call(['sudo', 'poff', '-a']) output = subprocess.check_output(['ifconfig', 'ppp0'], stderr=subprocess.STDOUT) if b'ppp0:' in output: subprocess.call(['sudo', 'ifconfig', 'ppp0', 'down']) subprocess.call(['sudo', 'killall', 'pppd']) subprocess.call(['sudo', 'poff', '-a']) except subprocess.CalledProcessError as e: output = e.output pass ###################################################################### def trigger_reset(): print('triggering reset...') subprocess.call(['pinctrl', 'set', '26', 'op', 'dh']) time.sleep(11) subprocess.call(['pinctrl', 'set', '26', 'op', 'dl']) time.sleep(2) print("OK trigger reset") ###################################################################### def close_port(ser): if ser.isOpen(): print("closing port...") ser.flushInput() ser.flushOutput() ser.close() ###################################################################### def main(): timeSpent = time.time() now = datetime.datetime.now() print(now) try: ser = None clear_pppd() trigger_reset() for baud_rate in baud_rates: ser = open_port(baud_rate) if ser.isOpen(): print(f'Serial port {serial_port} opened with baud rate {baud_rate}') response = send_at(ser, '', tries=3) # Send AT command to check if modem responds if response and 'OK' in response: rx = send_at(ser, '+IPR=115200', tries=1) # Send AT command to check if modem responds break # Break the loop if modem responds else: ser.close() if baud_rate: ser = open_port(115200) # Open port at baud rate 115200 if ser.isOpen(): print(f'Serial port {serial_port} opened with baud rate 115200') configure_modem(gprs_cmds, ser) else: print('Failed to open serial port with baud rate 115200') else: print(f'Unable to open serial port {serial_port} with any baud rate') except Exception as e: print("Exception: ", e) finally: close_port(ser) timeSpent = time.time() - timeSpent print("-------- TIME SPENT ", timeSpent) ###################################################################### # Start if __name__ == "__main__": if arg == 'clear': print("Clearing configurations...") sys.exit(0) if arg not in ['gprs', 'nb-iot', 'lte-m']: print(usage) sys.exit(1) modem_commands = { 'gprs': gprs_cmds, 'nb-iot': nb_iot_cmds, 'lte-m': lte_m_cmds } ser = open_port(baud_rate) commands = modem_commands[arg] configure_modem(commands, ser) ser.close() EOF ###################################################################### chmod 755 /usr/local/bin/network-setup.py systemctl enable ${SERVICE} if systemctl is-active ${SERVICE} >/dev/null 2>&1; then systemctl restart ${SERVICE} else systemctl start ${SERVICE} fi systemctl daemon-reload ###################################################################### sync exit 0