def get_imsi(lte: LTE) -> str: """ Get the international mobile subscriber identity (IMSI) from SIM """ IMSI_LEN = 15 get_imsi_cmd = "AT+CIMI" print("\n>> getting IMSI") modem_suspended = False if lte.isconnected(): lte.pppsuspend() modem_suspended = True result = _send_at_cmd(lte, get_imsi_cmd) if modem_suspended: lte.pppresume() if result[-1] == 'OK' and len(result[0]) == IMSI_LEN: return result[0] raise Exception("getting IMSI failed: {}".format(repr(result)))
def set_modem_func_lvl(lte: LTE, func_lvl: int): """ Sets modem to the desired level of functionality Throws exception if operation fails. :param func_lvl: the functionality level (0: minimum, 1: full, 4: disable modem both transmit and receive RF circuits) """ get_func_cmd = "AT+CFUN?" set_func_cmd = "AT+CFUN={}".format(func_lvl) print("\n>> setting up modem") modem_suspended = False if lte.isconnected(): lte.pppsuspend() modem_suspended = True # check if modem is already set to the correct functionality level result = _send_at_cmd(lte, get_func_cmd) if result[-1] == 'OK' and result[-2] == '+CFUN: {}'.format(func_lvl): if modem_suspended: lte.pppresume() return # set modem functionality level result = _send_at_cmd(lte, set_func_cmd) if result[-1] == 'OK': # check if modem is set and ready result = _send_at_cmd(lte, get_func_cmd) if result[-1] == 'OK' and result[-2] == '+CFUN: {}'.format(func_lvl): if modem_suspended: lte.pppresume() return if modem_suspended: lte.pppresume() raise Exception("setting up modem failed: {}".format(repr(result)))
class NetworkConnector: def __init__(self): self.logger = logging.get_logger(__name__) self.lte = LTE() def _attach(self): """ Attaches to the 1nce network """ self.lte.attach() while not self.lte.isattached(): time.sleep(0.5) print(".", end="") self.logger.info("Sim attached to iot.1nce.net") def connect(self): """ Connects to the 1nce network """ self._attach() self.lte.connect() while not self.lte.isconnected(): time.sleep(0.5) self.logger.info("Sim connected to iot.1nce.net") def disconnect(self): self.lte.disconnect() self.logger.info("Sim disconnected from iot.1nce.net") def _send_at_command(self, command): """ Sends AT command over the modem :rtype: Response string """ self.lte.pppsuspend() resp = self.lte.send_at_cmd(command) self.lte.pppresume() return resp def get_reception(self): """ Gets the current reception to the 1nce network :return: Number Reception to the 1nce network """ return self._send_at_command("AT+CSQ") def get_ip_address(self): """" Gets the Device it's Local IP address :return IP Address """ resp = self._send_at_command("AT+CGPADDR=1") self.logger.info(resp) search = re.search(r"\"([1-2]?\d?\d\.[1-2]?\d?\d\.[1-2]?\d?\d\.[1-2]?\d?\d)\"", resp) if search: return search.group(1) return None
elif line == "ERROR": returnOk = False else: # try: # returnVector += [line.split(" ")[1]] # except: returnVector += [line] if verbose: print(line) return (returnOk, returnVector) lte = LTE() try: print("imei", lte.imei()) except: lte.pppsuspend() print("imei", lte.imei()) send_at_cmd_pretty("AT+CPSMS=?") # +CPSMS: (0-2), , ,("00000000"-"11111111"),("00000000"-"11111111") # modes 0-2 # ^no Periodic-RAU values # ^no GPRS READY timer values # ^Periodic TAU values : 0000 0000 - 1111 1111 # ^Active Time values # +CPSMS: # (list of supported <mode>s), # (list of supported <Requested_Periodic-RAU>s), # (list of supported <Requested_GPRS-READY-timer>s) in GERAN/UTRAN, # (list of supported <Requested_Periodic-TAU>s), in E-UTRAN
print("\nConnected in attempt #"+str(i+1)) break packet = b'$\x1a\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01' s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(20) s.connect(("8.8.8.8", 53)) s.send(packet) resp=s.recv(100) result=False if (len(resp)>34): # very hacky error checking ip=resp[-4:] result=str(ip[0])+'.'+str(ip[1])+'.'+str(ip[2])+'.'+str(ip[3]) print("DNS result: "+str(result)) lte.pppsuspend() # can't send AT commands while in data mode time.sleep_ms(100) csq=lte.send_at_cmd('AT+CSQ').replace('\r\n','').replace('OK','') sgnl=int(csq.split(',')[0].split(' ')[1]) if sgnl!=99: sgnl=-113+(2*sgnl) cesq=lte.send_at_cmd('AT+CESQ').replace('\r\n','').replace('OK','').split(',') rsrq=int(cesq[4]) if rsrq!=255: rsrq=-20+(rsrq*0.5) rsrp=int(cesq[5]) if rsrp!=255: rsrp=-140+rsrp print(sgnl,rsrq,rsrp) lte.pppresume()
class DatacakeGateway: def machine_callback(self, arg): evt = machine.events() if (evt & machine.PYGATE_START_EVT): self.machine_state = config.GATEWAY_STATE_OK pycom.rgbled(config.RGB_GATEWAY_OK) elif (evt & machine.PYGATE_ERROR_EVT): self.machine_state = config.GATEWAY_STATE_ERROR pycom.rgbled(config.RGB_GATEWAY_ERROR) elif (evt & machine.PYGATE_STOP_EVT): self.machine_state = config.GATEWAY_STATE_STOP pycom.rgbled(config.RGB_GATEWAY_STOP) def __init__(self): print("Init: Initialization of Gateway class...") # Machine machine.callback( trigger=(machine.PYGATE_START_EVT | machine.PYGATE_STOP_EVT | machine.PYGATE_ERROR_EVT), handler=self.machine_callback) self.machine_state = 0 # LTE self.lte = LTE() self.lte_connection_state = 0 # RTC self.rtc = RTC() # Gateway # Read the GW config file from Filesystem self.gateway_config_file = None # Timers self.rgb_breathe_timer = Timer.Chrono() # Startup # Should be called outside init # self.start_up() def lte_event_callback(self, arg): #self.blink_rgb_led(5, 0.25, config.RGB_LTE_ERROR) #self.lte.deinit() #machine.reset() print( "\n\n\n#############################################################" ) print("CB LTE Callback Handler") ev = arg.events() # NB: reading the events clears them t = time.ticks_ms() print("CB", t, time.time(), ev, time.gmtime()) self.blink_rgb_led(3, 0.25, config.RGB_LTE_ERROR) if ev & LTE.EVENT_COVERAGE_LOSS: print("CB", t, "coverage loss") if ev & LTE.EVENT_BREAK: print("CB", t, "uart break signal") try: self.lte.pppsuspend() if not self.lte.isattached(): print("not attached ... reattach") self.lte.detach() self.init_lte() else: print("attached ... resume") self.lte.pppresume() except Exception as ex: sys.print_exception(ex) print( "#############################################################\n\n\n" ) def init_gateway(self): print("Init GW: Starting LoRaWAN Concentrator...") try: self.gateway_config_file = open(config.GW_CONFIG_FILE_PATH, 'r').read() except Exception as e: print("Error opening Gateway Config: {}".format(e)) # TODO: Handle Error return False else: machine.pygate_init(self.gateway_config_file) print("Init GW: LoRaWAN Concentrator UP!") return True def init_rtc(self): print("Init RTC: Syncing RTC...") try: self.rtc.ntp_sync(server="pool.ntp.org") while not self.rtc.synced(): self.blink_rgb_led(1, 0.25, config.RGB_RTC_IS_SYNCING, delay_end=False) self.blink_rgb_led(3, 0.1, config.RGB_RTC_IS_SYNCING) except Exception as e: print("Exception syncing RTC: {}".format(e)) return False else: print("Init RTC: Synced!") return True def init_lte(self): self.lte_connection_state = 0 self.lte.init() #self.lte.lte_callback(LTE.EVENT_COVERAGE_LOSS, self.lte_event_callback) self.lte.lte_callback(LTE.EVENT_BREAK, self.lte_event_callback) while True: # attach LTE if self.lte_connection_state == 0: print("Init LTE: Attaching LTE...") self.lte.attach(band=config.LTE_BAND, apn=config.LTE_APN) while not self.lte.isattached(): self.blink_rgb_led(1, 0.25, config.RGB_LTE_IS_ATTACHING, delay_end=False) self.blink_rgb_led(3, 0.1, config.RGB_LTE_IS_ATTACHING) self.lte_connection_state += 1 print("Init LTE: Attached!") # connect LTE if self.lte_connection_state == 1: print("Init LTE: Connecting LTE...") self.lte.connect() while not self.lte.isconnected(): self.blink_rgb_led(1, 0.25, config.RGB_LTE_IS_CONNECTING, delay_end=False) self.blink_rgb_led(3, 0.1, config.RGB_LTE_IS_CONNECTING) self.lte_connection_state += 1 print("Init LTE: Connected!") # done if self.lte_connection_state == 2: return True def blink_rgb_led(self, times, speed, color_on, color_off=config.RGB_OFF, delay_end=True): for index in range(times): pycom.rgbled(config.RGB_OFF) time.sleep(speed) pycom.rgbled(color_on) time.sleep(speed) pycom.rgbled(config.RGB_OFF) if delay_end is True: time.sleep(0.1) def start_up(self): print("Start Up: Now starting up Gateway...") self.init_lte() self.init_rtc() self.init_gateway() #self.main_loop() def main_loop(self): # Start Timers self.rgb_breathe_timer.start() while True: if self.rgb_breathe_timer.read( ) > config.TIMER_RGB_BREATHE_INTERVAL: self.rgb_breathe_timer.reset()
class StartIoT: def __init__(self, network=LTE_M): self._network = network self.lte = LTE() try: self.lte.deinit() self.lte.reset() except: pass sleep(5) self.lte.init() sleep(5) self._assure_modem_fw() def _assure_modem_fw(self): response = self.lte.send_at_cmd('ATI1') if response != None: lines = response.split('\r\n') fw_id = lines[1][0:3] is_nb = fw_id == 'UE6' if is_nb: print('Modem is using NB-IoT firmware (%s/%s).' % (lines[1], lines[2])) else: print('Modem in using LTE-M firmware (%s/%s).' % (lines[1], lines[2])) if not is_nb and self._network == NB_IOT: print( 'You cannot connect using NB-IoT with wrong modem firmware! Please re-flash the modem with the correct firmware.' ) raise WrongNetwork if is_nb and self._network == LTE_M: print( 'You cannot connect using LTE-M with wrong modem firmware! Please re-flash the modem with the correct firmware.' ) raise WrongNetwork else: print('Failed to determine modem firmware. Rebooting device...') reset() # Reboot the device def _get_assigned_ip(self): ip_address = None try: self.lte.pppsuspend() response = self.send_at_cmd_pretty('AT+CGPADDR=1') self.lte.pppresume() lines = response.split('\r\n') sections = lines[1].split('"') ip_address = sections[1] except: print('Failed to retrieve assigned IP from LTE network.') return ip_address def send_at_cmd_pretty(self, cmd): print('>', cmd) response = self.lte.send_at_cmd(cmd) if response != None: lines = response.split('\r\n') for line in lines: if len(line.strip()) != 0: print('>>', line) else: print('>> No response.') return response def connect(self): # NB-IoT if (self._network == NB_IOT): self.send_at_cmd_pretty('AT+CFUN=0') self.send_at_cmd_pretty('AT+CEMODE=0') self.send_at_cmd_pretty('AT+CEMODE?') self.send_at_cmd_pretty('AT!="clearscanconfig"') self.send_at_cmd_pretty('AT!="addscanfreq band=%s dl-earfcn=%s"' % (BAND, EARFCN)) self.send_at_cmd_pretty('AT+CGDCONT=1,"IP","%s"' % APN) self.send_at_cmd_pretty('AT+COPS=1,2,"%s"' % COPS) self.send_at_cmd_pretty('AT+CFUN=1') # LTE-M (Cat M1) else: self.send_at_cmd_pretty('AT+CFUN=0') self.send_at_cmd_pretty('AT!="clearscanconfig"') self.send_at_cmd_pretty('AT!="addscanfreq band=%s dl-earfcn=%s"' % (BAND, EARFCN)) self.send_at_cmd_pretty('AT+CGDCONT=1,"IP","%s"' % APN) self.send_at_cmd_pretty('AT+CFUN=1') self.send_at_cmd_pretty('AT+CSQ') # For a range scan: # AT!="addscanfreqrange band=20 dl-earfcn-min=3450 dl-earfcn-max=6352" print('Attaching...') seconds = 0 while not self.lte.isattached() and seconds < attach_timeout: sleep(0.25) seconds += 0.25 if self.lte.isattached(): print('Attached!') else: print('Failed to attach to LTE (timeout)!') raise AttachTimeout self.lte.connect() print('Connecting...') seconds = 0 while not self.lte.isconnected() and seconds < connect_timeout: sleep(0.25) seconds += 0.25 if self.lte.isconnected(): print('Connected!') else: print('Failed to connect to LTE (timeout)!') raise ConnectTimeout print('Retrieving assigned IP...') ip_address = self._get_assigned_ip() print("Device IP: {}".format(ip_address)) print(ip_address) # Initialise the CoAP module Coap.init(ip_address) # Register the response handler for the requests that the module initiates as a CoAP Client Coap.register_response_handler(self.response_callback) # A CoAP server is needed if CoAP push is used (messages are pushed down from Managed IoT Cloud) # self.setup_coap_server() def setup_coap_server(self): # Add a resource with a default value and a plain text content format r = Coap.add_resource('', media_type=Coap.MEDIATYPE_APP_JSON, value='default_value') # Configure the possible operations on the resource r.callback( Coap.REQUEST_GET | Coap.REQUEST_POST | Coap.REQUEST_PUT | Coap.REQUEST_DELETE, True) # Get the UDP socket created for the CoAP module coap_server_socket = Coap.socket() # Create a new poll object p = uselect.poll() # Register the CoAP module's socket to the poll p.register(coap_server_socket, uselect.POLLIN | uselect.POLLHUP | uselect.POLLERR) # Start a new thread which will handle the sockets of "p" poll _thread.start_new_thread(socket_thread, (p, coap_server_socket)) print('CoAP server running!') # The callback that handles the responses generated from the requests sent to a CoAP Server def response_callback(self, code, id_param, type_param, token, payload): # The ID can be used to pair the requests with the responses print('ID: {}'.format(id_param)) print('Code: {}'.format(code)) print('Type: {}'.format(type_param)) print('Token: {}'.format(token)) print('Payload: {}'.format(payload)) def disconnect(self): if self.lte.isconnected(): self.lte.disconnect() def dettach(self): if self.lte.isattached(): self.lte.dettach() def send(self, data): if not self.lte.isconnected(): raise Exception('Not connected! Unable to send.') id = Coap.send_request(IOTGW_IP, Coap.REQUEST_POST, uri_port=IOTGW_PORT, uri_path=IOTGW_ENDPOINT, payload=data, include_options=True) print('CoAP POST message ID: {}'.format(id)) def pull(self, uri_path='/'): if not self.lte.isconnected(): raise Exception('Not connected! Unable to pull.') id = Coap.send_request(IOTGW_IP, Coap.REQUEST_GET, uri_port=IOTGW_PORT, uri_path=uri_path, include_options=True) Coap.read() print('CoAP GET message ID: {}'.format(id))