def get_LTE(): global lte if lte == None: lte = LTE() if lte.isconnected(): return True # lte.reset() # lte.send_at_cmd('AT+CGDCONT=1,"IP","nbiot.iot"') if (not lte.isattached()): lte.attach(band=20, apn="nbiot.iot") while not lte.isattached(): debugprint('Attaching...') time.sleep(1) debugprint('LTE is attached') return True
def nb_iot_attach(lte: LTE, apn: str): sys.stdout.write(">> attaching to LTE network ({})".format(apn)) # since we disable unsolicited CEREG messages in reset_modem(), as they interfere with AT communication with the SIM via CSIM commands, # we are required to use an attach method that does not require cereg messages, for pycom that is legacyattach=false lte.attach(band=8, apn=apn, legacyattach=False) i = 0 while not lte.isattached() and i < 60: machine.idle() # save power while waiting time.sleep(1.0) sys.stdout.write(".") i += 1 print("") if not lte.isattached(): raise Exception("unable to attach to LTE network") print("-- attached: " + str(i) + "s")
def lte_connect(): lte = LTE() lte.init() #some carriers have special requirements, check print(lte.send_at_cmd("AT+SQNCTM=?")) to see if your carrier is listed. #when using verizon, use #lte.init(carrier=verizon) #when usint AT&T use, #lte.init(carrier=at&t) #some carriers do not require an APN #also, check the band settings with your carrier lte.attach(band=2, apn="vzwinternet") print("attaching..", end='') while not lte.isattached(): time.delay(0.25) print('.', end='') print(lte.send_at_cmd('AT!="fsm"')) # get the System FSM print("attached!") lte.connect() print("connecting [##", end='') while not lte.isconnected(): time.sleep(0.25) print('#', end='') #print(lte.send_at_cmd('AT!="showphy"')) print(lte.send_at_cmd('AT!="fsm"')) print("] connected!") print(socket.getaddrinfo('pycom.io', 80)) lte.deinit()
def lte_setup(lte: LTE, connect: bool, apn: str or None): print(">> initializing LTE") lte.init() if connect: if not lte.isattached(): nb_iot_attach(lte, apn) if not lte.isconnected(): nb_iot_connect(lte)
def lte_shutdown(lte: LTE, detach=True): if lte.isconnected(): print(">> disconnecting LTE") lte.disconnect() if detach and lte.isattached(): print(">> detaching LTE") lte.detach() print(">> de-initializing LTE") lte.deinit(detach=False, reset=False)
def attachLte(): global lte lte = LTE() lte.init() lte.attach(band=12, apn="soracom.io") while not lte.isattached(): time.sleep(0.25) print('.',end='') print("attached!")
def sendData(dataList, deviceKey): # ******************** Hologram endpoint Definition HOST = "cloudsocket.hologram.io" PORT = 9999 TOPIC = "SENSOR_DATA" blink(1, 0xffffff) # blink white # Set up LTE connection lte = LTE() lte.init() print("Resetting LTE modem ... ", end="") lte.send_at_cmd('AT^RESET') print("Reset OK") time.sleep(1) # While the configuration of the CGDCONT register survives resets, # the other configurations don't. So just set them all up every time. print("Configuring LTE ", end='') # Changed this from origninal lte.send_at_cmd('AT+CGDCONT=1,"IP","hologram"') print(".", end='') # changed band from 28 to 4. I dont know what earfcn=9410 is; lte.send_at_cmd('AT!="RRC::addscanfreq band=4 dl-earfcn=9410"') print(".", end='') # lte.send_at_cmd # Do the attach (Enable radio functionality and attach to the LTE network authorized by the inserted SIM card) lte.attach() print("attaching..", end='') while not lte.isattached(): blink(1, 0x0000ff) # blue print('.', end='') # print(lte.send_at_cmd('AT!="fsm"')) # get the System FSM print("attached!") # Do the connect (Start a data session and obtain and IP address) lte.connect() print("connecting [##", end='') while not lte.isconnected(): time.sleep(1) print('#', end='') print("] connected!") blink(1, 0x00ff00) # Green # **** Send data to hologram bodyData = buildData(dataList) lteSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) lteSocket.connect(socket.getaddrinfo(HOST, PORT)[0][-1]) data = '{"k": "%s", "d": "{%s}", "t": "%s"}' % (deviceKey, bodyData, TOPIC) print("Send Data:", data) lteSocket.send(data) # Clean up and close connection lteSocket.close() lte.deinit() print("Disconnected") blink(1, 0xff0000) # red
class LteController: def __init__(self): self._lte = LTE() self._lte.attach() while not self._lte.isattached(): time.sleep(1) self._lte.connect() while not self._lte.isconnected(): time.sleep(1) print(self._lte.isattached()) print(self._lte.isconnected()) def canSend(self): """return true if interface can send data, false otherwise""" return self._lte.isconnected() def send(self, data): """attempts to send via interface, returns success status""" return False
class Connection: def __init__(self): self.lte = LTE() def nb_connect(self, band=20, apn="nb.inetd.gdsp"): counter1 = 0 counter2 = 0 if not self.lte.isattached(): print("Attaching to LTE...") self.lte.attach(band=band, apn=apn) while not self.lte.isattached(): counter1 += 1 print(str(counter1) + ' seconds elapsed') if counter1 >= 50: import machine machine.reset() time.sleep(1) if not self.lte.isconnected(): print("Obtaining IP address...") self.lte.connect() while not self.lte.isconnected(): counter2 += 1 print(str(counter2) + ' seconds elapsed') time.sleep(0.25) print("Network ready ...") def nb_disconnect(self): if self.lte.isconnected(): self.lte.disconnect() while self.lte.isattached(): try: self.lte.dettach() except OSError as e: print(e, type(e)) else: print("Network is now disconnected")
def connect(): global lte lte = LTE() # instantiate the LTE object # Change this if you are using the M1 network (comment out the next 6 lines) lte.send_at_cmd('AT+CFUN=0') lte.send_at_cmd('AT+CEMODE=0') lte.send_at_cmd('AT+CEMODE?') lte.send_at_cmd('AT!="clearscanconfig"') lte.send_at_cmd('AT!="addscanfreq band=20 dl-earfcn=6352"') lte.send_at_cmd('AT+CFUN=1') # End change this .... lte.attach() # attach the cellular modem to a base station while not lte.isattached(): time.sleep(0.25) print("attatched") lte.connect() # start a data session and obtain an IP address while not lte.isconnected(): time.sleep(0.25) print("connected")
def connect(timeout=30, lte=None): if lte is None: lte = LTE() # instantiate the LTE object lte.attach() # attach the cellular modem to a base station cycles = 0 while not lte.isattached(): sleep(1) cycles += 1 if cycles > timeout: raise Exception("Failed to attach cellular modem to base station") lte.connect() # start a data session and obtain an IP address cycles = 0 while not lte.isconnected(): sleep(1) cycles += 1 if cycles > timeout: raise Exception("Failed to obtain cellular data session") return lte
for line in response: print(line) lte = LTE() send_at_cmd_pretty('AT+CPIN?') send_at_cmd_pretty('AT+CGDCONT=1,"IP","swisscom-test.m2m.ch"') send_at_cmd_pretty('AT+CFUN=0') send_at_cmd_pretty('AT+CEREG=2') send_at_cmd_pretty('AT!="clearscanconfig"') send_at_cmd_pretty('AT!="RRC::addscanfreq band=20 dl-earfcn=6300"') send_at_cmd_pretty('AT+CFUN=1') pycom.heartbeat(False) while not lte.isattached(): pycom.rgbled(0x7f0000) time.sleep(0.1) pycom.rgbled(0x000000) time.sleep(0.5) send_at_cmd_pretty('AT!="showphy"') send_at_cmd_pretty('AT!="fsm"') send_at_cmd_pretty('AT+CEREG?') lte.connect() while not lte.isconnected(): pycom.rgbled(0x7f7f00) time.sleep(0.1) pycom.rgbled(0x000000) time.sleep(0.5) print("waiting")
lte.send_at_cmd('AT^RESET')\ print("OK")\ time.sleep(1)\ \ # While the configuration of the CGDCONT register survives resets,\ # the other configurations don't. So just set them all up every time.\ print("Configuring LTE ", end='')\ lte.send_at_cmd('AT+CGDCONT=1,"IP","vodafone.internet"')\ print(".", end='')\ lte.send_at_cmd('AT!="RRC::addscanfreq band=20 dl-earfcn=6300"')\ print(".", end='')\ lte.send_at_cmd('AT+CFUN=1')\ print(" OK")\ \ # If correctly configured for carrier network, attach() should succeed.\ if not lte.isattached():\ print("Attaching to LTE network ", end='')\ lte.attach()\ while True:\ if lte.isattached():\ print(" OK")\ break\ print('.', end='')\ time.sleep(1)\ \ # Once attached, connect() should succeed.\ if not lte.isconnected():\ print("Connecting on LTE network ", end='')\ lte.connect()\ while(True):\ if lte.isconnected():\
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 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 def disconnect(self): if self.lte.isconnected(): self.lte.disconnect() def dettach(self): if self.lte.isattached(): self.lte.dettach()
class LteComms: def __init__(self): self.message_storage = 'AT+CPMS="SM", "SM", "SM"' gc.collect() try: self.lte = LTE() time.sleep(4) except: print("initialize LTE object?") self.lte.reset() time.sleep(4) print("delay 4 secs") def at(self, cmd): print("modem command: {}".format(cmd)) r = self.lte.send_at_cmd(cmd).split('\r\n') r = list(filter(None, r)) print("response={}".format(r)) return r def attach_LTE(self): gc.collect() time.sleep(10.0) if self.lte.isattached(): try: print("LTE was already attached, disconnecting...") if self.lte.isconnected(): print("disconnect") self.lte.disconnect() except: print("Exception during disconnect") try: if self.lte.isattached(): print("detach") self.lte.dettach() except: print("Exception during dettach") try: print("resetting modem...") self.lte.reset() except: print("Exception during reset") print("delay 5 secs") time.sleep(5.0) # enable network registration and location information, unsolicited result code self.at('AT+CEREG=2') # print("full functionality level") self.at('AT+CFUN=1') time.sleep(1.0) # using Hologram SIM self.at('AT+CGDCONT=1,"IP","hologram"') print("attempt to attach cell modem to base station...") # lte.attach() # do not use attach with custom init for Hologram SIM self.at("ATI") time.sleep(2.0) i = 0 while self.lte.isattached() == False: # get EPS Network Registration Status: # +CEREG: <stat>[,[<tac>],[<ci>],[<AcT>]] # <tac> values: # 0 - not registered # 1 - registered, home network # 2 - not registered, but searching... # 3 - registration denied # 4 - unknown (out of E-UTRAN coverage) # 5 - registered, roaming r = self.at('AT+CEREG?') try: r0 = r[0] # +CREG: 2,<tac> r0x = r0.split(',') # ['+CREG: 2',<tac>] tac = int(r0x[1]) # 0..5 print("tac={}".format(tac)) except IndexError: tac = 0 print("Index Error!!!") # get signal strength # +CSQ: <rssi>,<ber> # <rssi>: 0..31, 99-unknown r = self.at('AT+CSQ') # extended error report # r =self.at('AT+CEER') # if lte.isattached(): # print("Modem attached (isattached() function worked)!!!") # break # if (tac==1) or (tac==5): # print("Modem attached!!!") # break i = i + 5 print("not attached: {} secs".format(i)) # while self.lte.isattached(): # # self.receive_and_forward_to_chat() # continue # print("Modem not attached") print("set to check messages on sim") self.at(self.message_storage) def connect_lte_data(self): self.at('AT+CEREG?') print("Attempt to connect") if self.lte.isattached() == False: print("Not attached, try again, will fail") else: print("Attached and continue") self.lte.connect() i = 0 while not self.lte.isconnected(): i = i + 1 print("not connected: {}".format(i)) time.sleep(1.0) print("LTE connected for data!!!") # also send this to chat # so just pymesh this to all nodes in leader_mesh_list while self.lte.isconnected(): continue def scrape_webpage(self, url): s = socket.socket() s = ssl.wrap_socket(s) s.connect(socket.getaddrinfo(url, 443)[0][-1]) s.send(b"GET / HTTP/1.0\r\n\r\n") print(s.recv(4096)) s.close() def send_sms(self, number, msg): # this will somehow have to be connected to the chat with a JM msg1 print("set mode to text") self.at('AT+CMGF=1') time.sleep(.5) # msg = ('AT+CMGS="%s"\r%s\0x1a' % (number, msg)) # print(('ATTB+SQNSMSSEND="%s", "%s"' % (number, msg))) print('sendin an sms', end=' ') ans = self.lte.send_at_cmd( ('AT+SQNSMSSEND="%s", "%s"' % (number, msg))).split('\r\n') print(ans) # self.at(msg) time.sleep(4) print("sent!") def receive_and_forward_to_chat(self): # this will somehow have to be connected to the chat with a JM msg1 print("set mode to text") self.at('AT+CMGF=1') msg_list = [] msg_list = self.at('AT+CMGL="ALL"') number_of_messages = 0 if len(msg_list) > 1: print("This'll print if there a msg") if len(msg_list) > 20: print("More then 10 messages, loop") i = 1 while len(msg_list) > 20: print("This is the inner loop running %s times" % i) msg_list = self.at('AT+CMGL="ALL"') number_of_messages += len(msg_list) self.write_msg_to_file_and_delete(msg_list) time.sleep(15) i += 1 print("This is to get the last group of messages") # you don't scan for messages while it sleep, almost Need # to run this in a thread in the background. time.sleep(10) msg_list = self.at('AT+CMGL="ALL"') number_of_messages += len(msg_list) self.write_msg_to_file_and_delete(msg_list) else: print("The list is less than 10, so straight to file") number_of_messages += len(msg_list) self.write_msg_to_file_and_delete(msg_list) else: print("This prints when no messages") self.at('AT+CMGD=1,4') # Cuz apparently you need to clean out the sim card, it only holds 10 msgs # at('AT+CMGD=1,4') time.sleep(5) actual_messages = (number_of_messages / 2) - 1 print(actual_messages) def msg_parse(self, msg_list): parsed_msg_list = [] msg_list_string = "".join(msg_list) split_msg_list = msg_list_string.split('+CMGL:') for i in range(len(split_msg_list)): temp_string = str(split_msg_list[i]) if temp_string[-2:] == 'OK': parsed_msg_list.append(temp_string[:-2]) else: parsed_msg_list.append(temp_string) return parsed_msg_list def disconnect_LTE(self): self.lte.disconnect() print("LTE Data disconnected") # send to chat def unattach_lte(self): self.lte.detach(reset=True) print("LTE modem deattached") def signal_strength(self): self.at('AT+CSQ') def check_read_sms(self): self.at('AT+CMGF=1') msg_list = self.at('AT+CMGL="ALL"') print(msg_list) def write_msg_to_file_and_delete(self, msg_list): parsed_msg_list = self.msg_parse(msg_list) print("Writing to SMS log") f = open('/sd/www/sms.txt', 'a+') for i in range(len(parsed_msg_list)): if parsed_msg_list[i] != '\r\n': f.write(str(parsed_msg_list[i])) f.write('\r\n') f.close() self.at('AT+CMGD=1,4')
class StartIot(): def __init__(self): self.lte = LTE() self.initModem() # METHOD FOR PRETTY PRINTING AT COMMANDS def send_at_cmd_pretty(self, cmd): response = self.lte.send_at_cmd(cmd) if response != None: lines=response.split('\r\n') print("Response is:< ") for line in lines: if len(line.strip()) != 0: print(line) print(">") else: print("Response is None...") return response # SETUP AND START THE MODEM - ATTACH TO THE NETWORK def initModem(self): print ("Starting modem...") self.send_at_cmd_pretty('AT+CFUN=0') # Change this if you are using the NB1 network (uncomment the next 4 lines) #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=20 dl-earfcn=6352"') # End change this .... self.send_at_cmd_pretty('AT+CGDCONT=1,"IP","mda.ee"') self.send_at_cmd_pretty('AT+CFUN=1') self.send_at_cmd_pretty('AT+CSQ') print ("Waiting for attachement (To Radio Access Network)...") while not self.lte.isattached(): time.sleep(0.25) else: print ("Attached (To Radio Access Network)...") # CONNECT TO THE NETWORK def connect(self): if not self.lte.isattached(): raise Exception('NOT ATTACHED... call initModem() first') print ("Waiting for connection (To IP network)...") self.lte.connect() # Wait until we get connected to network while not self.lte.isconnected(): machine.idle() print ("Connected (To IP network)!") # OPEN SOCKET AND SEND DATA def send(self, data): if not self.lte.isconnected(): raise Exception('NOT CONNECTED') s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) IP_address = socket.getaddrinfo('172.16.15.14', 1234)[0][-1] s.connect(IP_address) s.send(data) s.close() def disconnect(self): if self.lte.isconnected(): self.lte.disconnect() def dettach(self): if self.lte.isattached(): self.lte.dettach() self.lte.send_at_cmd('AT+CFUN=0') print("Modem offline")
def test_lte_ntp(hw, max_drift_secs=4): _logger.info("Starting LTE test...") pycom_util.reset_rgbled() global failures _logger.info("Testing LTE connectivity...") chrono = machine.Timer.Chrono() chrono.start() with CheckStep(FLAG_SD_CARD, suppress_exception=True): hw.mount_sd_card() ou_id = None cc = None cs = None with CheckStep(FLAG_COMM_CONFIG, suppress_exception=True): import os import co2unit_comm os.chdir(hw.SDCARD_MOUNT_POINT) ou_id, cc, cs = co2unit_comm.read_comm_config(hw) with CheckStep(FLAG_TIME_SOURCE, suppress_exception=True): hw.sync_to_most_reliable_rtc() lte = None signal_quality = None try: with CheckStep(FLAG_LTE_FW_API): from network import LTE with CheckStep(FLAG_LTE_INIT): # _logger.info("Give LTE a moment to boot") # LTE init seems to be successful more often if we give it time first # time.sleep_ms(1000) # wdt.feed() _logger.info("Init LTE...") chrono.reset() pycom.nvs_set("lte_on", True) lte = LTE() _logger.info("LTE init ok (%d ms)", chrono.read_ms()) except: return failures try: with CheckStep(FLAG_LTE_ATTACH): _logger.info("LTE attaching... (up to 2 minutes)") chrono.reset() lte.attach() try: while True: wdt.feed() if lte.isattached(): break if chrono.read_ms() > 150 * 1000: raise TimeoutError("Timeout during LTE attach") time.sleep_ms(50) finally: signal_quality = pycom_util.lte_signal_quality(lte) _logger.info("Signal quality: %s", signal_quality) import co2unit_errors co2unit_errors.info( hw, "Self-test. LTE attached: {}. Signal quality {}".format( lte.isattached(), signal_quality)) _logger.info("LTE attach ok (%d ms). Connecting...", chrono.read_ms()) if signal_quality["rssi_raw"] in range(0, 31): led_show_scalar(signal_quality["rssi_raw"], [0, 31]) with CheckStep(FLAG_LTE_CONNECT): chrono.reset() lte.connect() while True: wdt.feed() if lte.isconnected(): break if chrono.read_ms() > 120 * 1000: raise TimeoutError("Timeout during LTE connect") time.sleep_ms(50) _logger.info("LTE connect ok (%d ms)", chrono.read_ms()) with CheckStep(FLAG_COMM_PING, suppress_exception=True): import co2unit_comm for sync_dest in cc.sync_dest: co2unit_comm.send_alive_ping(sync_dest, ou_id, cc, cs) wdt.feed() with CheckStep(FLAG_NTP_FETCH, suppress_exception=True): from machine import RTC import timeutil chrono.reset() irtc = RTC() ts = timeutil.fetch_ntp_time(cc.ntp_host if cc else None) idrift = ts - time.mktime(irtc.now()) if abs(idrift) < max_drift_secs: _logger.info("Drift from NTP: %s s; within threshold (%d s)", idrift, max_drift_secs) else: ntp_tuple = time.gmtime(ts) irtc = RTC() irtc.init(ntp_tuple) hw.ertc.save_time() _logger.info("RTC set from NTP %s; drift was %d s", ntp_tuple, idrift) failures &= ~FLAG_TIME_SOURCE # Clear FLAG_TIME_SOURCE if previously set _logger.info("Got time with NTP (%d ms). Shutting down...", chrono.read_ms()) wdt.feed() with CheckStep(FLAG_LTE_SHUTDOWN): if lte: try: if lte.isconnected(): chrono.reset() lte.disconnect() _logger.info("LTE disconnected (%d ms)", chrono.read_ms()) wdt.feed() if lte.isattached(): chrono.reset() lte.dettach() _logger.info("LTE detached (%d ms)", chrono.read_ms()) wdt.feed() finally: chrono.reset() lte.deinit() pycom.nvs_set("lte_on", False) _logger.info("LTE deinit-ed (%d ms)", chrono.read_ms()) wdt.feed() except: pass show_boot_flags() _logger.info("Failures after LTE test: 0x%04x", failures) display_errors_led() if signal_quality and signal_quality["rssi_raw"] in range(0, 32): led_show_scalar(signal_quality["rssi_raw"], [0, 31]) pycom.rgbled(0x0)
class SequansLTE: """ Synopsis:: sq = SequansLTE() sq.info() sq.firmware_info() sq.at('showphy') See also: - https://git.cicer.de/autonome-zelle/fipy-nbiot-rtd/blob/master/main.py """ def __init__(self, network_manager, settings): self.network_manager = network_manager self.settings = settings from network import LTE self.lte = LTE() import machine self.chrono = machine.Timer.Chrono() self.chrono.start() def start(self): self.lte.init() self.attach() self.connect() def stop(self): self.lte.disconnect() time.sleep(0.25) self.lte.deinit() time.sleep(0.25) def attach(self): log.info('Attaching to LTE') self.lte.attach(band=self.settings.get('networking.lte.band'), apn=self.settings.get('networking.lte.apn')) self.chrono.reset() while True: log.info('Signal strength: {}'.format(self.get_signal_strength())) if self.lte.isattached(): break if self.chrono.read() > self.settings.get( 'networking.lte.attach_timeout'): raise Exception('Attaching to LTE timed out') time.sleep(0.25) def connect(self): log.info('Connecting to LTE') self.lte.connect() self.chrono.reset() while True: if self.lte.isconnected(): break if self.chrono.read() > self.settings.get( 'networking.lte.connect_timeout'): raise Exception('Connecting to LTE timed out') time.sleep(0.25) def imei(self): """ Return IMEI. """ return self.at('AT+CGSN=1') def info(self): """ Get infos from Modem. """ log.info('Signal strength: {}'.format(self.get_signal_strength())) self.at('RRC:setDbgPerm full') self.at('RRC:showcaps') self.at('showver') # https://forum.pycom.io/topic/4022/unable-to-update-gpy-modem-firmware/8 #self.at('AT') #self.at('ATI') #self.at('ATZ') def get_signal_strength(self): csq_at = self.lte.send_at_cmd("AT+CSQ") csq_line_regex = ure.compile("\n") csq_line = csq_line_regex.split(csq_at) csq_string_regex = ure.compile(" ") csq_string = csq_string_regex.split(csq_line[1]) csq_comma = csq_string[1] csq_num_regex = ure.compile(",") csq_num = csq_num_regex.split(csq_comma) csq = csq_num[0] return csq def at(self, command): """ :param command: """ return self.raw('AT!="{}"'.format(command)) def raw(self, command): """ :param command: """ log.info('Sending: {}'.format(command)) answer = self.lte.send_at_cmd(command) log.info('Answer: {}'.format(answer)) return answer def firmware_info(self): """ """ import sqnsupgrade sqnsupgrade.info(verbose=True, debug=True) def unbrick(self): """ """ raise NotImplementedError( 'https://forum.pycom.io/topic/4022/unable-to-update-gpy-modem-firmware/21' )
class NanoGateway: """ Nano gateway class, set up by default for use with TTN, but can be configured for any other network supporting the Semtech Packet Forwarder. Only required configuration is wifi_ssid and wifi_password which are used for connecting to the Internet. """ def __init__(self, id, frequency, datarate, server, port, ntp_server='pool.ntp.org', ntp_period=3600): self.id = id self.server = server self.port = port self.frequency = frequency self.datarate = datarate # self.ssid = ssid # self.password = password self.ntp_server = ntp_server self.ntp_period = ntp_period self.server_ip = None self.rxnb = 0 self.rxok = 0 self.rxfw = 0 self.dwnb = 0 self.txnb = 0 self.sf = self._dr_to_sf(self.datarate) self.bw = self._dr_to_bw(self.datarate) self.stat_alarm = None self.pull_alarm = None self.uplink_alarm = None self.lte = None self.sock = None self.udp_stop = False self.udp_lock = _thread.allocate_lock() self.lora = None self.lora_sock = None self.rtc = machine.RTC() def start(self): """ Starts the LoRaWAN nano gateway. """ pycom.heartbeat(False) self._log('Starting LoRaWAN nano gateway with id: {}', self.id) # # setup WiFi as a station and connect # self.wlan = WLAN(mode=WLAN.STA) # self._connect_to_wifi() # setup LTE CATM1 connection self.lte = LTE(carrier="verizon") self._connect_to_LTE() # get a time sync self._log('Syncing time with {} ...', self.ntp_server) self.rtc.ntp_sync(self.ntp_server, update_period=self.ntp_period) while not self.rtc.synced(): utime.sleep_ms(50) self._log("RTC NTP sync complete") # get the server IP and create an UDP socket self.server_ip = usocket.getaddrinfo(self.server, self.port)[0][-1] self._log('Opening UDP socket to {} ({}) port {}...', self.server, self.server_ip[0], self.server_ip[1]) self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.IPPROTO_UDP) self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) self.sock.setblocking(False) # push the first time immediatelly self._push_data(self._make_stat_packet()) # create the alarms self.stat_alarm = Timer.Alarm( handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # start the UDP receive thread self.udp_stop = False _thread.start_new_thread(self._udp_thread, ()) # initialize the LoRa radio in LORA mode self._log('Setting up the LoRa radio at {} Mhz using {}', self._freq_to_float(self.frequency), self.datarate) self.lora = LoRa(mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) # create a raw LoRa socket self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb) self._log('LoRaWAN nano gateway online') def stop(self): """ Stops the LoRaWAN nano gateway. """ self._log('Stopping...') # send the LoRa radio to sleep self.lora.callback(trigger=None, handler=None) self.lora.power_mode(LoRa.SLEEP) # stop the NTP sync self.rtc.ntp_sync(None) # cancel all the alarms self.stat_alarm.cancel() self.pull_alarm.cancel() # signal the UDP thread to stop self.udp_stop = True while self.udp_stop: utime.sleep_ms(50) # disable LTE self.lte.disconnect() self.lte.dettach() def _connect_to_wifi(self): self.wlan.connect(self.ssid, auth=(None, self.password)) while not self.wlan.isconnected(): utime.sleep_ms(50) self._log('WiFi connected to: {}', self.ssid) def _connect_to_LTE(self): print("reset modem") try: self.lte.reset() except: print("Exception during reset") print("delay 5 secs") utime.sleep(5.0) if self.lte.isattached(): try: print("LTE was already attached, disconnecting...") if self.lte.isconnected(): print("disconnect") self.lte.disconnect() except: print("Exception during disconnect") try: if self.lte.isattached(): print("detach") self.lte.dettach() except: print("Exception during dettach") try: print("resetting modem...") self.lte.reset() except: print("Exception during reset") print("delay 5 secs") utime.sleep(5.0) # enable network registration and location information, unsolicited result code self.at('AT+CEREG=2') # print("full functionality level") self.at('AT+CFUN=1') utime.sleep(1.0) # using Hologram SIM self.at('AT+CGDCONT=1,"IP","hologram"') print("attempt to attach cell modem to base station...") # lte.attach() # do not use attach with custom init for Hologram SIM self.at("ATI") utime.sleep(2.0) i = 0 while self.lte.isattached() == False: # get EPS Network Registration Status: # +CEREG: <stat>[,[<tac>],[<ci>],[<AcT>]] # <tac> values: # 0 - not registered # 1 - registered, home network # 2 - not registered, but searching... # 3 - registration denied # 4 - unknown (out of E-UTRAN coverage) # 5 - registered, roaming r = self.at('AT+CEREG?') try: r0 = r[0] # +CREG: 2,<tac> r0x = r0.split(',') # ['+CREG: 2',<tac>] tac = int(r0x[1]) # 0..5 print("tac={}".format(tac)) except IndexError: tac = 0 print("Index Error!!!") # get signal strength # +CSQ: <rssi>,<ber> # <rssi>: 0..31, 99-unknown r = self.at('AT+CSQ') # extended error report # r = at('AT+CEER') if self.lte.isattached(): print("Modem attached (isattached() function worked)!!!") break if (tac == 1) or (tac == 5): print("Modem attached!!!") break i = i + 5 print("not attached: {} secs".format(i)) if (tac != 0): self.blink(BLUE, tac) else: self.blink(RED, 5) utime.sleep(2) self.at('AT+CEREG?') print("connect: start a data session and obtain an IP address") self.lte.connect(cid=3) i = 0 while not self.lte.isconnected(): i = i + 1 print("not connected: {}".format(i)) self.blink(YELLOW, 1) utime.sleep(1.0) print("connected!!!") pycom.rgbled(GREEN) def _dr_to_sf(self, dr): sf = dr[2:4] if sf[1] not in '0123456789': sf = sf[:1] return int(sf) def _dr_to_bw(self, dr): bw = dr[-5:] if bw == 'BW125': return LoRa.BW_125KHZ elif bw == 'BW250': return LoRa.BW_250KHZ else: return LoRa.BW_500KHZ def _sf_bw_to_dr(self, sf, bw): dr = 'SF' + str(sf) if bw == LoRa.BW_125KHZ: return dr + 'BW125' elif bw == LoRa.BW_250KHZ: return dr + 'BW250' else: return dr + 'BW500' def _lora_cb(self, lora): """ LoRa radio events callback handler. """ events = lora.events() if events & LoRa.RX_PACKET_EVENT: self.rxnb += 1 self.rxok += 1 rx_data = self.lora_sock.recv(256) stats = lora.stats() packet = self._make_node_packet(rx_data, self.rtc.now(), stats.rx_timestamp, stats.sfrx, self.bw, stats.rssi, stats.snr) self._push_data(packet) self._log('Received packet: {}', packet) self.rxfw += 1 if events & LoRa.TX_PACKET_EVENT: self.txnb += 1 lora.init(mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) def _freq_to_float(self, frequency): """ MicroPython has some inprecision when doing large float division. To counter this, this method first does integer division until we reach the decimal breaking point. This doesn't completely elimate the issue in all cases, but it does help for a number of commonly used frequencies. """ divider = 6 while divider > 0 and frequency % 10 == 0: frequency = frequency // 10 divider -= 1 if divider > 0: frequency = frequency / (10**divider) return frequency def _make_stat_packet(self): now = self.rtc.now() STAT_PK["stat"]["time"] = "%d-%02d-%02d %02d:%02d:%02d GMT" % ( now[0], now[1], now[2], now[3], now[4], now[5]) STAT_PK["stat"]["rxnb"] = self.rxnb STAT_PK["stat"]["rxok"] = self.rxok STAT_PK["stat"]["rxfw"] = self.rxfw STAT_PK["stat"]["dwnb"] = self.dwnb STAT_PK["stat"]["txnb"] = self.txnb return ujson.dumps(STAT_PK) def _make_node_packet(self, rx_data, rx_time, tmst, sf, bw, rssi, snr): RX_PK["rxpk"][0]["time"] = "%d-%02d-%02dT%02d:%02d:%02d.%dZ" % ( rx_time[0], rx_time[1], rx_time[2], rx_time[3], rx_time[4], rx_time[5], rx_time[6]) RX_PK["rxpk"][0]["tmst"] = tmst RX_PK["rxpk"][0]["freq"] = self._freq_to_float(self.frequency) RX_PK["rxpk"][0]["datr"] = self._sf_bw_to_dr(sf, bw) RX_PK["rxpk"][0]["rssi"] = rssi RX_PK["rxpk"][0]["lsnr"] = snr RX_PK["rxpk"][0]["data"] = ubinascii.b2a_base64(rx_data)[:-1] RX_PK["rxpk"][0]["size"] = len(rx_data) return ujson.dumps(RX_PK) def _push_data(self, data): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes( [PUSH_DATA]) + ubinascii.unhexlify(self.id) + data with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to push uplink packet to server: {}', ex) def _pull_data(self): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes( [PULL_DATA]) + ubinascii.unhexlify(self.id) with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to pull downlink packets from server: {}', ex) def _ack_pull_rsp(self, token, error): TX_ACK_PK["txpk_ack"]["error"] = error resp = ujson.dumps(TX_ACK_PK) packet = bytes([PROTOCOL_VERSION]) + token + bytes( [PULL_ACK]) + ubinascii.unhexlify(self.id) + resp with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('PULL RSP ACK exception: {}', ex) def _send_down_link(self, data, tmst, datarate, frequency): """ Transmits a downlink message over LoRa. """ self.lora.init(mode=LoRa.LORA, frequency=frequency, bandwidth=self._dr_to_bw(datarate), sf=self._dr_to_sf(datarate), preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) while utime.ticks_cpu() < tmst: pass self.lora_sock.send(data) self._log( 'Sent downlink packet scheduled on {:.3f}, at {:.3f} Mhz using {}: {}', tmst / 1000000, self._freq_to_float(frequency), datarate, data) def _udp_thread(self): """ UDP thread, reads data from the server and handles it. """ while not self.udp_stop: try: data, src = self.sock.recvfrom(1024) _token = data[1:3] _type = data[3] if _type == PUSH_ACK: self._log("Push ack") elif _type == PULL_ACK: self._log("Pull ack") elif _type == PULL_RESP: self.dwnb += 1 ack_error = TX_ERR_NONE tx_pk = ujson.loads(data[4:]) tmst = tx_pk["txpk"]["tmst"] t_us = tmst - utime.ticks_cpu() - 15000 if t_us < 0: t_us += 0xFFFFFFFF if t_us < 20000000: self.uplink_alarm = Timer.Alarm( handler=lambda x: self._send_down_link( ubinascii.a2b_base64(tx_pk["txpk"]["data"]), tx_pk["txpk"]["tmst"] - 50, tx_pk["txpk"][ "datr"], int(tx_pk["txpk"]["freq"] * 1000) * 1000), us=t_us) else: ack_error = TX_ERR_TOO_LATE self._log('Downlink timestamp error!, t_us: {}', t_us) self._ack_pull_rsp(_token, ack_error) self._log("Pull rsp") except usocket.timeout: pass except OSError as ex: if ex.errno != errno.EAGAIN: self._log('UDP recv OSError Exception: {}', ex) except Exception as ex: self._log('UDP recv Exception: {}', ex) # wait before trying to receive again utime.sleep_ms(UDP_THREAD_CYCLE_MS) # we are to close the socket self.sock.close() self.udp_stop = False self._log('UDP thread stopped') def _log(self, message, *args): """ Outputs a log message to stdout. """ print('[{:>10.3f}] {}'.format(utime.ticks_ms() / 1000, str(message).format(*args))) def at(self, cmd): print("modem command: {}".format(cmd)) r = self.lte.send_at_cmd(cmd).split('\r\n') r = list(filter(None, r)) print("response={}".format(r)) return r def blink(self, rgb, n): for i in range(n): pycom.rgbled(rgb) utime.sleep(0.25) pycom.rgbled(BLACK) utime.sleep(0.1)
from network import LTE import time import socket lte = LTE() #Vodafone UK apn=nb.inetd.gdsp print("Attempting to attach...", end="") lte.attach(band=20, apn="ep.inetd.gdsp") for j in range(10): print(".", end="") time.sleep(1) if lte.isattached(): print("\nAttached in attempt #" + str(j + 1)) break lte.connect() print("Attempting to connect..", end="") for i in range(10): print(".", end="") if lte.isconnected(): print("\nConnected in attempt #" + str(i + 1)) break s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(20) s.connect(("3.9.21.110", 6789)) result = s.send(b'helloworld') print("Sent bytes: " + str(result)) lte.disconnect() lte.dettach()
print("instantiate LTE object") lte = LTE(carrier="verizon") print("delay 4 secs") time.sleep(4.0) print("reset modem") try: lte.reset() except: print("Exception during reset") print("delay 5 secs") time.sleep(5.0) if lte.isattached(): try: print("LTE was already attached, disconnecting...") if lte.isconnected(): print("disconnect") lte.disconnect() except: print("Exception during disconnect") try: if lte.isattached(): print("detach") lte.dettach() except: print("Exception during dettach")
import machine # NOTE: test the code. Changed prints during loops pycom.heartbeat(False) # disable the heartbeat LED #sqnsupgrade.info(verbose=False, debug=False) print("#####################") print("#####################") print("NB-IoT Hello World v0.1") wdt=WDT(timeout=660000) lte = LTE() #lte.init() wdt.feed() #Vodafone UK apn=nb.inetd.gdsp if not lte.isattached(): for i in range(4): ccid=lte.iccid() print (" ccid = " + str(ccid)) if ccid: break time.sleep(3) print("Attempting to attach...", end="") #vodafone uk: lte.attach(band=20,apn="ep.inetd.gdsp") #comms365: #lte.attach(band=20, apn="nb.iot.com") for j in range(10): print(".", end ="") time.sleep(1) if lte.isattached():
class PybytesConnection: def __init__(self, config, message_callback): if config is not None: self.__conf = config try: self.__host = pycom.nvs_get('pybytes_server') except: self.__host = config.get('server') self.__ssl = config.get('ssl', False) self.__ssl_params = config.get('ssl_params', {}) self.__user_name = config.get('username') self.__device_id = config.get('device_id') self.__mqtt_download_topic = "d" + self.__device_id self.__mqtt_upload_topic = "u" + self.__device_id self.__pybytes_protocol = PybytesProtocol( config, message_callback, pybytes_connection=self ) self.__connection = None self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED self.__lora_socket = None self.lora = None self.lora_lock = _thread.allocate_lock() self.__sigfox_socket = None self.lte = None self.wlan = None self.__network_type = None self.__wifi_lte_watchdog = None def lte_ping_routine(self, delay): while True: self.send_ping_message() time.sleep(delay) def print_pretty_response(self, rsp): lines = rsp.split('\r\n') for line in lines: if line: if line not in ['OK']: print(line) def __initialise_watchdog(self): if self.__conf.get('connection_watchdog', True): self.__wifi_lte_watchdog = WDT( timeout=constants.__WDT_TIMEOUT_MILLISECONDS ) print('Initialized watchdog for WiFi and LTE connection with timeout {} ms'.format(constants.__WDT_TIMEOUT_MILLISECONDS)) # noqa else: print('Watchdog for WiFi and LTE was disabled, enable with "connection_watchdog": true in pybytes_config.json') # noqa # Establish a connection through WIFI before connecting to mqtt server def connect_wifi(self, reconnect=True, check_interval=0.5, timeout=120): self.__initialise_watchdog() if self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED: # noqa print("Error connect_wifi: Connection already exists. Disconnect First") # noqa return False try: from network import WLAN antenna = self.__conf.get('wlan_antenna', WLAN.INT_ANT) known_nets = [((self.__conf['wifi']['ssid'], self.__conf['wifi']['password']))] # noqa if antenna == WLAN.EXT_ANT: print("WARNING! Using external WiFi antenna.") '''to connect it to an existing network, the WiFi class must be configured as a station''' self.wlan = WLAN(mode=WLAN.STA, antenna=antenna) attempt = 0 print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected())) while not self.wlan.isconnected() and attempt < 3: attempt += 1 print_debug(3, "Wifi connection attempt: {}".format(attempt)) print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected())) available_nets = None while available_nets is None: try: available_nets = self.wlan.scan() for x in available_nets: print_debug(5, x) time.sleep(1) except: pass nets = frozenset([e.ssid for e in available_nets]) known_nets_names = frozenset([e[0]for e in known_nets]) net_to_use = list(nets & known_nets_names) try: net_to_use = net_to_use[0] pwd = dict(known_nets)[net_to_use] sec = [e.sec for e in available_nets if e.ssid == net_to_use][0] # noqa print_debug(99, "Connecting with {} and {}".format(net_to_use, pwd)) if sec == 0: self.wlan.connect(net_to_use, timeout=10000) else: self.wlan.connect(net_to_use, (sec, pwd), timeout=10000) start_time = time.time() while not self.wlan.isconnected(): if time.time() - start_time > timeout: raise TimeoutError('Timeout trying to connect via WiFi') time.sleep(0.1) except Exception as e: if str(e) == "list index out of range" and attempt == 3: print("Please review Wifi SSID and password inside config") self.wlan.deinit() return False elif attempt == 3: print("Error connecting using WIFI: %s" % e) return False self.__network_type = constants.__NETWORK_TYPE_WIFI print("WiFi connection established") try: self.__connection = MQTTClient( self.__device_id, self.__host, self.__mqtt_download_topic, self.__pybytes_protocol, user=self.__user_name, password=self.__device_id ) self.__connection.connect() self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI # noqa self.__pybytes_protocol.start_MQTT( self, constants.__NETWORK_TYPE_WIFI ) return True except Exception as ex: if '{}'.format(ex) == '4': print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa else: print("MQTT ERROR! {}".format(ex)) return False except Exception as ex: print("Exception connect_wifi: {}".format(ex)) return False # Establish a connection through LTE before connecting to mqtt server def connect_lte(self, activation_info=False, start_mqtt=True): if activation_info: lte_cfg = activation_info else: lte_cfg = self.__conf.get('lte') self.__initialise_watchdog() if lte_cfg is not None: if (os.uname()[0] not in ['FiPy', 'GPy']): print("You need a device with FiPy or GPy firmware to connect via LTE") # noqa return False try: from network import LTE time.sleep(3) if lte_cfg.get('carrier', 'standard') == 'standard': carrier = None else: carrier = lte_cfg.get('carrier') print_debug(1, 'LTE init(carrier={}, cid={})'.format(carrier, lte_cfg.get('cid', 1))) # noqa # instantiate the LTE object self.lte = LTE(carrier=carrier, cid=lte_cfg.get('cid', 1)) try: lte_type = lte_cfg.get('type') if len(lte_cfg.get('type')) > 0 else None except: lte_type = None try: lte_apn = lte_cfg.get('apn') if len(lte_cfg.get('type')) > 0 else None except: lte_apn = None try: lte_band = int(lte_cfg.get('band')) except: lte_band = None print_debug( 1, 'LTE attach(band={}, apn={}, type={})'.format( lte_band, lte_apn, lte_type ) ) self.lte.attach(band=lte_band, apn=lte_apn, type=lte_type) # noqa # attach the cellular modem to a base station while not self.lte.isattached(): time.sleep(0.25) time.sleep(1) print_debug(1, 'LTE connect()') # start a data session and obtain an IP address self.lte.connect() print_debug(1, 'LTE is_connected()') while not self.lte.isconnected(): time.sleep(0.25) print("LTE connection established") self.__network_type = constants.__NETWORK_TYPE_LTE if start_mqtt: try: self.__connection = MQTTClient( self.__device_id, self.__host, self.__mqtt_download_topic, self.__pybytes_protocol, user=self.__user_name, password=self.__device_id ) self.__connection.connect() self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE # noqa self.__pybytes_protocol.start_MQTT( self, constants.__NETWORK_TYPE_LTE ) print("Connected to MQTT {}".format(self.__host)) return True except Exception as ex: if '{}'.format(ex) == '4': print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa else: print("MQTT ERROR! {}".format(ex)) return False except Exception as ex: print("Exception connect_lte: {}".format(ex)) sys.print_exception(ex) return False else: print("Error... missing configuration!") return False # LORA def connect_lora_abp(self, lora_timeout, nanogateway): print_debug(1,'Attempting to connect via LoRa') if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error connect_lora_abp: Connection already exists. Disconnect First") # noqa return False try: from network import LoRa except Exception as ex: print("This device does not support LoRa connections: %s" % ex) return False lora_class = self.__conf.get('lora', {}).get('class', 0) if self.__conf.get('lora', {}).get('region') is not None: self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora').get('region'), device_class=lora_class) else: self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class) self.lora.nvram_restore() try: dev_addr = self.__conf['lora']['abp']['dev_addr'] nwk_swkey = self.__conf['lora']['abp']['nwk_skey'] app_swkey = self.__conf['lora']['abp']['app_skey'] except Exception as ex: print("Invalid LoRaWAN ABP configuration!") print_debug(1, ex) return False timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000 dev_addr = struct.unpack(">l", binascii.unhexlify(dev_addr.replace(' ', '')))[0] # noqa nwk_swkey = binascii.unhexlify(nwk_swkey.replace(' ', '')) app_swkey = binascii.unhexlify(app_swkey.replace(' ', '')) try: print("Trying to join LoRa.ABP for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout)) self.lora.join( activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey), timeout=timeout_ms ) # if you want, uncomment this code, but timeout must be 0 # while not self.lora.has_joined(): # print("Joining...") # time.sleep(5) self.__open_lora_socket(nanogateway) # print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size)) # _thread.stack_size(self.__thread_stack_size) # _thread.start_new_thread(self.__check_lora_messages, ()) return True except Exception as e: message = str(e) if message == 'timed out': print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout)) else: print_debug(3, 'Exception in LoRa connect: {}'.format(e)) return False def connect_lora_otaa(self, lora_timeout, nanogateway): print_debug(1,'Attempting to connect via LoRa') if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error connect_lora_otaa: Connection already exists. Disconnect First") # noqa return False try: from network import LoRa except Exception as ex: print("This device does not support LoRa connections: %s" % ex) return False try: dev_eui = self.__conf['lora']['otaa']['app_device_eui'] app_eui = self.__conf['lora']['otaa']['app_eui'] app_key = self.__conf['lora']['otaa']['app_key'] except Exception as ex: print("Invalid LoRaWAN OTAA configuration!") print_debug(1, ex) return False timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000 lora_class = self.__conf.get('lora', {}).get('class', 0) if self.__conf.get('lora', {}).get('region') is not None: self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora', {}).get('region'), device_class=lora_class) else: self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class) self.lora.nvram_restore() dev_eui = binascii.unhexlify(dev_eui.replace(' ', '')) app_eui = binascii.unhexlify(app_eui.replace(' ', '')) app_key = binascii.unhexlify(app_key.replace(' ', '')) try: if not self.lora.has_joined(): print("Trying to join LoRa.OTAA for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout)) self.lora.join( activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=timeout_ms ) # if you want, uncomment this code, but timeout must be 0 # while not self.lora.has_joined(): # print("Joining...") # time.sleep(5) self.__open_lora_socket(nanogateway) # print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size)) # _thread.stack_size(self.__thread_stack_size) # _thread.start_new_thread(self.__check_lora_messages, ()) return True except Exception as e: message = str(e) if message == 'timed out': print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout)) else: print_debug(3, 'Exception in LoRa connect: {}'.format(e)) return False def __open_lora_socket(self, nanogateway): if (nanogateway): for i in range(3, 16): self.lora.remove_channel(i) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) print("Setting up LoRa socket...") self.__lora_socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.__lora_socket.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_LORA self.__pybytes_protocol.start_Lora(self) print("Connected using LoRa") # SIGFOX def connect_sigfox(self): if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error: Connection already exists. Disconnect First") pass try: from network import Sigfox except Exception: print("This device does not support Sigfox connections") return sigfox_config = self.__conf.get('sigfox', {}) if sigfox_config is None or sigfox_config.get('RCZ') is None: print(constants.__SIGFOX_WARNING) try: sf_rcz = int(sigfox_config.get('RCZ', 1)) - 1 if sf_rcz >= 0 and sf_rcz <= 3: Sigfox(mode=Sigfox.SIGFOX, rcz=sf_rcz) self.__sigfox_socket = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW) # noqa self.__sigfox_socket.setblocking(True) self.__sigfox_socket.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, False) # noqa self.__network_type = constants.__NETWORK_TYPE_SIGFOX self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_SIGFOX # noqa self.__pybytes_protocol.start_Sigfox(self) print( "Connected using Sigfox. Only upload stream is supported" ) return True else: print('Invalid Sigfox RCZ specified in config!') return False except Exception as e: print('Exception in connect_sigfox: {}'.format(e)) return False # COMMON def disconnect(self, keep_wifi=False, force=False): if self.__wifi_lte_watchdog is not None: self.__wifi_lte_watchdog = WDT(timeout=constants.__WDT_MAX_TIMEOUT_MILLISECONDS) print('Watchdog timeout has been increased to {} ms'.format(constants.__WDT_MAX_TIMEOUT_MILLISECONDS)) # noqa print_debug( 1, 'self.__connection_status={} | self.__network_type={}'.format( self.__connection_status, self.__network_type ) ) if (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print_debug(3, "Already disconnected") if (constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI <= self.__connection_status <= constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): # noqa print_debug(1, 'MQTT over WIFI||LTE... disconnecting MQTT') try: self.__connection.disconnect(force=force) self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED # noqa except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_LORA): # noqa print_debug(1, 'Connected over LORA... closing socket and saving nvram') # noqa try: self.__lora_socket.close() self.lora.nvram_save() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_SIGFOX): # noqa print_debug(1, 'Connected over SIGFOX... closing socket') try: self.__sigfox_socket.close() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__network_type == constants.__NETWORK_TYPE_WIFI and not keep_wifi): print_debug(1, 'Connected over WIFI... disconnecting') try: self.wlan.deinit() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__network_type == constants.__NETWORK_TYPE_LTE): print_debug(1, 'Connected over LTE... disconnecting') try: lte_cfg = self.__conf.get('lte') print_debug(1, 'lte.deinit(reset={})'.format(lte_cfg.get('reset', False))) # noqa self.lte.deinit(reset=lte_cfg.get('reset', False)) except Exception as e: print("Error disconnecting: {}".format(e)) self.__network_type = None self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED def is_connected(self): return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa # Added for convention with other connectivity classes def isconnected(self): return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa
class SQNS: """ Synopsis:: sq = SQNS() sq.info() sq.firmware_info() sq.at('showphy') See also: - https://git.cicer.de/autonome-zelle/fipy-nbiot-rtd/blob/master/main.py """ def __init__(self): from network import LTE self.lte = LTE() self.at('RRC:setDbgPerm full') def connect(self): self.lte.init() def attach(self): self.lte.attach(band=8, apn="iot.1nce.net") while not self.lte.isattached(): # do we have a timeout? time.sleep(1) try: csq_at = self.lte.send_at_cmd("AT+CSQ") csq_line_regex = ure.compile("\n") csq_line = csq_line_regex.split(csq_at) csq_string_regex = ure.compile(" ") csq_string = csq_string_regex.split(csq_line[1]) csq_comma = csq_string[1] csq_num_regex = ure.compile(",") csq_num = csq_num_regex.split(csq_comma) csq = csq_num[0] print("[LTE ] ... still attaching ... (CSQ: " + csq + ")") except: csq = "-999.0" print( "[LTE ] ... no CSQ recevied, let us hope I am still attaching " + csq) def at(self, command): """ :param command: """ self.raw('AT!="{}"'.format(command)) def raw(self, command): """ :param command: """ print('Sending command {}'.format(command)) print(self.lte.send_at_cmd(command)) def imei(self): """ """ self.at('AT+CGSN=1') def info(self): """ """ # https://forum.pycom.io/topic/4022/unable-to-update-gpy-modem-firmware/8 self.at('AT') self.at('ATI') self.at('ATZ') def firmware_info(self): """ """ import sqnsupgrade sqnsupgrade.info(verbose=True, debug=True) def unbrick(self): """ """ raise NotImplementedError( 'https://forum.pycom.io/topic/4022/unable-to-update-gpy-modem-firmware/21' )
from network import Bluetootht import time # import ujson import pycom # from pysense import Pysense # from machine import I2C # from machine import ADC # from network import Bluetooth # from SHT35 import SHT35 # from LIS2HH12 import LIS2HH12 from network import LTE lte = LTE() print("Intializing...") lte.init([carrier='standard’, psm_period_value=0, psm_period_unit=LTE.PSM_PERIOD_DISABLED, psm_active_value=0, psm_active_unit=LTE.PSM_ACTIVE_DISABLED]) print("Attaching...") lte.attach([band=None, apn=None, cid=None, type=LTE.IP, legacyattach=True]) print("Network attached: " + lte.isattached())
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))
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
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()