def nb_iot_connect(lte: LTE):
    sys.stdout.write(">> connecting to LTE network")
    lte.connect()  # start a data session and obtain an IP address
    i = 0
    while not lte.isconnected() and i < 30:
        machine.idle()  # save power while waiting
        time.sleep(1.0)
        sys.stdout.write(".")
        i += 1
    print("")
    if not lte.isconnected():
        raise Exception("unable to connect to LTE network")
    print("-- connected ({}s)".format(i))
Exemple #2
0
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)
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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")
Exemple #8
0
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 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)))
Exemple #10
0
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
Exemple #12
0
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 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
Exemple #14
0
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")

client = MQTTClient("client",
                    "domain",
                    user="******",
                    password="******",
                    port=port,
                    ssl=True)

i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('G9', 'G10'))
scanner = i2c.scan()
 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():\
             print(" OK")\
             break\
             print('.', end='')\
         time.sleep(1)\
\
 # Once connect() succeeds, any call requiring Internet access will\
 # use the active LTE connection.\
 return lte\
\
# Clean disconnection of the LTE network is required for future\
# successful connections without a complete power cycle between.\
Exemple #16
0
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()
Exemple #17
0
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 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)
from network import WLAN
wlan = WLAN()
print("wlan.isconnected", wlan.isconnected())
if wlan.isconnected():
    print('IP:', wlan.ifconfig()[0])

try:
    from network import LTE
    lte = LTE()
    print("imei", lte.imei())
    print("lte.isconnected", lte.isconnected())
    # print("ue_coverage", lte.ue_coverage())
except:
    print("no LTE")
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 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)
Exemple #24
0
from network import LTE


def send_at_cmd_pretty(cmd):
    response = lte.send_at_cmd(cmd).split('\r\n')
    for line in response:
        if (len(line) > 0):
            print(line)


lte = LTE()
print("imei", lte.imei())
print("is_connected", lte.isconnected())
print("ue_coverage", lte.ue_coverage())
print("iccid", lte.iccid())
print("time", lte.time())

send_at_cmd_pretty('AT+CGMI')
# PYCOM
send_at_cmd_pretty('AT+CGMM')
# FiPy
send_at_cmd_pretty('AT+CGMR')
# UE5.0.0.0d
send_at_cmd_pretty('AT+CGSN=0')

send_at_cmd_pretty('AT+CGSN=1')

send_at_cmd_pretty('AT+CGSN=2')

send_at_cmd_pretty('AT+CGSN=3')
# +CGSN: "00"
Exemple #25
0
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))
Exemple #26
0
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()
Exemple #27
0
    #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():
            print("\nAttached in attempt #"+str(j+1))
            break
        lte.send_at_cmd('AT+CEREG?').replace('\r\n','')
        #NOTE: for Vodafone UK: AT+COPS=1,2,"23415"
        lte.send_at_cmd('AT+COPS=1,2,"23415"').replace('\r\n','')
        #NOTE: for Comms365 on vodafone
        #lte.send_at_cmd('AT+COPS=1,2,"90128"').replace('\r\n','')
if not lte.isconnected():
    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

#packet = b'$\x1a\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01'
packet = b'hello nbiot world'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(20)
s.connect(("3.9.21.110", 8088))
s.send(packet)
#lte.disconnect()
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
Exemple #29
0
class Tracker:
    def __init__(self, pytrack=None, debug=False):
        if pytrack is not None:
            self.pytrack = pytrack
        else:
            self.pytrack = Pytrack()

        self.debug = debug
        # Instantiate and hold state for sensors (accelerometer, lte, gps, etc)
        self.accel = LIS2HH12()
        self.lte = LTE()
        self.gps = None
        # Holds the mqtt client to send messages to
        self.mqttClient = None
        # If after wakeup, we are in continuous GPS logging state
        self.continueGPSRead = False
        # Flag for handling wakeup and logging logic differently if owner is nearby
        self.checkOwnerNearby = True
        self.wlan = WLAN()  #TODO remove

    def init(self, bInitLTE=False):
        '''
        Initialize local variables used within the script. Checks for network connectivity. If not able to connect after
        a timeout, resets the machine in order to try and conenct again. 
        Initializes MQTTClient and checks if we are in a continuous GPS read state after wakeup (saved to self instance variables)
        '''
        # Check if network is connected. If not, attempt to connect
        if bInitLTE:
            self.initLTE()
        else:
            #TODO remove
            # Check if network is connected. If not, attempt to connect
            counter = 0
            while not self.wlan.isconnected():
                # If we surpass some counter timeout and network is still not connected, reset and attempt to connect again
                if counter > 100000:
                    machine.reset()
                machine.idle()
                counter += 1

        # Initialize mqttClient
        self.mqttClient = self._getMqttClient(self.debug)

        # Check to see if we are in continued gps read (went to sleep and want to continue reading GPS data)
        if self._getNVS(ConfigGPS.NVS_SLEEP_CONTINUE_GPS_READ) is not None:
            self.continueGPSRead = True
            # Erase this key from NVS
            pycom.nvs_erase(ConfigGPS.NVS_SLEEP_CONTINUE_GPS_READ)

    @staticmethod
    def _getRTC():
        '''
        Syncs the real time clock with latest time and returns RTC instance
        '''
        rtc = machine.RTC()
        if not rtc.synced():
            # Sync real time clock
            rtc.ntp_sync("pool.ntp.org")
        return rtc

    @staticmethod
    def _getNVS(key):
        '''
        Looks up at the non volatile storage for a specified key. If it exists, returns the value stored
        for that key. Otherwise, returns None
        '''
        try:
            if pycom.nvs_get(key) is not None:
                return pycom.nvs_get(key)
        except Exception:
            # Do nothing, key doesnt exist
            pass
        return None

    @staticmethod
    def _decodeBytes(data):
        '''
        Attempts to decode a byte array to string format. If not a byte type,
        just returns the original data
        '''
        try:
            return data.decode()
        except (UnicodeDecodeError, AttributeError):
            pass
        return data

    def _getMqttClient(self, debug):
        # Initialize mqttClient
        state = False
        count = 0
        mqttClient = None

        while not state and count < 5:
            try:
                count += 1
                mqttClient = MQTTClient(ConfigMqtt.CLIENT_ID,
                                        ConfigMqtt.SERVER,
                                        port=ConfigMqtt.PORT,
                                        user=ConfigMqtt.USER,
                                        password=ConfigMqtt.PASSWORD)
                # Set the callback method that will be invoked on subscription to topics
                mqttClient.set_callback(self.mqttCallback)
                mqttClient.connect()
                state = True
            except Exception as e:
                if debug:
                    print("Exception on initialize mqtt client: {}".format(e))
                time.sleep(0.5)

        #Subscribe to the disable tracking topic
        mqttClient.subscribe(topic=ConfigMqtt.TOPIC_TRACKING_STATE)
        time.sleep(0.5)
        if self.debug:
            print("Checking MQTT messages")

        mqttClient.check_msg()

        if self.debug:
            print("Messages checked. Returning MQTT client")

        return mqttClient

    def initLTE(self):
        #TODO remove
        return
        '''
        If already used, the lte device will have an active connection.
        If not, need to set up a new connection.
        '''
        lte = self.lte
        debug = self.debug

        if lte.isconnected():
            return

        # Modem does not connect successfully without first being reset.
        if debug:
            print("Resetting LTE modem ... ", end='')
        lte.send_at_cmd('AT^RESET')
        if debug:
            print("OK")
        time.sleep(5)
        lte.send_at_cmd('AT+CFUN=0')
        time.sleep(5)

        #send_at_cmd_pretty('AT!="fsm"')
        # While the configuration of the CGDCONT register survives resets,
        # the other configurations don't. So just set them all up every time.
        if debug:
            print("Configuring LTE ", end='')
        lte.send_at_cmd('AT!="clearscanconfig"')

        if debug:
            print(".", end='')
        lte.send_at_cmd('AT!="RRC::addScanBand band=26"')

        if debug:
            print(".", end='')
        lte.send_at_cmd('AT!="RRC::addScanBand band=18"')

        if debug:
            print(".", end='')
        lte.send_at_cmd('AT+CGDCONT=1,"IP","soracom.io"')

        if debug:
            print(".", end='')
        lte.send_at_cmd('AT+CGAUTH=1,1,"sora","sora"')
        print(".", end='')

        if debug:
            lte.send_at_cmd('AT+CFUN=1')
        print(" OK")

        # If correctly configured for carrier network, attach() should succeed.
        if not lte.isattached():
            if debug:
                print("Attaching to LTE network ", end='')
            lte.attach()

            while True:
                if lte.isattached():
                    #send_at_cmd_pretty('AT+COPS?')
                    time.sleep(5)
                    break

                if debug:
                    print('.', end='')
                    pycom.rgbled(0x0f0000)
                time.sleep(0.5)
                if debug:
                    pycom.rgbled(0x000000)
                time.sleep(1.5)

        # Once attached, connect() should succeed.
        if not lte.isconnected():
            if debug:
                print("Connecting on LTE network ", end='')
            lte.connect()
            while True:
                if lte.isconnected():
                    break
                if debug:
                    print('.', end='')
                time.sleep(1)

        # Once connect() succeeds, any call requiring Internet access will
        # use the active LTE connection.
        self.lte = lte

    def isContinueGPSRead(self):
        '''
        Returns true or false - whether or not we are in a continued gps read state after power cycle / deep sleep.
        If true, we should jump right to gps read. False if we should execute normal wakeup flow
        '''
        return self.continueGPSRead

    def getWakeReason(self):
        '''
        Returns the reason why the device was woken up.
        Return values are from the ConfigWakeup scope
        '''
        if self.continueGPSRead:
            return ConfigWakeup.WAKE_CONTINUE_GPS
        elif self.pytrack.get_wake_reason() == WAKE_REASON_ACCELEROMETER:
            return ConfigWakeup.WAKE_REASON_ACCELEROMATER
        else:
            return ConfigWakeup.WAKE_REASON_TIMEOUT

    def setCheckOwnerNearby(self, bOwnerNearby=True):
        '''
        If bOnwerNearby is set to true (defaults to true here and constructor instantiation), we handle
        logic for wakup and actively logging location and pushing mqtt messages differently.
        If checkowner flag is true and owner is detected nearby on device wakeup, we are much less active
        in wakeups and monitoring
        '''
        self.checkOwnerNearby = bOwnerNearby

    def isOwnerNearby(self):
        '''
        Logic here checks if a known BLE device is broadcasting nearby.
        If they are, return true. Else, return false
        '''
        # TODO remove
        return False
        bt = Bluetooth()
        bt.start_scan(ConfigBluetooth.SCAN_ALLOW_TIME)  # Scans for 10 seconds

        while bt.isscanning():
            adv = bt.get_adv()
            if adv and binascii.hexlify(adv.mac) == ConfigBluetooth.MAC_ADDR:
                try:
                    if self.debug:
                        print("Owner device found: {} Mac addr {}".format(
                            bt.resolve_adv_data(adv.data,
                                                Bluetooth.ADV_NAME_CMPL),
                            ConfigBluetooth.MAC_ADDR))
                    conn = bt.connect(adv.mac)
                    time.sleep(0.05)
                    conn.disconnect()
                    bt.stop_scan()
                except Exception:
                    bt.stop_scan()

                return True

            time.sleep(0.050)

        return False

    def handleOwnerNearby(self):
        '''
        If owner is determined to be nearby, puts device in deep sleep for specified amount
        of time without acceleration wakeup
        '''
        # Current time and last time we wokeup with owner nearby was less than 2 minutes apart.
        # Go to deep sleep for specified amount of time without accelerometer wakeup
        self.pytrack.setup_sleep(ConfigWakeup.SLEEP_TIME_OWNER_NEARBY)
        self.pytrack.go_to_sleep()

    def mqttCallback(self, topic, msg):
        '''
        Method to handle callbacks of any mqtt topics that we subscribe to.
        For now, only subscribes to bypass topic which is used to disable gps monitoring and accelerometer wakeup detection.
        topic - MQTT topic that we are subscribing to and processing the request for 
        msg - Message received from the topic
        '''
        if self.debug:
            print("In MQTT subscription callback")

        # Attempt to decode the topic and msg if in byte format
        topic = self._decodeBytes(topic)
        msg = self._decodeBytes(msg)

        # Handle mqtt topic for disabiling the monitoring
        if topic == ConfigMqtt.TOPIC_TRACKING_STATE:
            try:
                bSleep = False
                sleepTime = ConfigMqtt.SLEEP_TIME_MQTT_DISABLE

                # First check if this is a plaintext msg (not json format)
                if msg == ConfigMqtt.ENABLE_TRACKING_MSG:
                    # Tracking is enabled, continue
                    bSleep = False

                elif msg == ConfigMqtt.DISABLE_TRACKING_MSG:
                    # If tracking is disabled, go to sleep with configured sleep time
                    bSleep = True

                else:
                    # Structure of the message will be in json format:
                    # { msg: "XXX", "time": 123} where msg value is ON/OFF for disable (OFF) or enable(ON)
                    # and time value is time to disable tracking (will automatically be re-enabled after
                    # time surpasses if this value is present)
                    jMsg = ujson.loads(msg)
                    # Check if the msg is Y. If so, need to stop tracking
                    if jMsg['msg'] == ConfigMqtt.DISABLE_TRACKING_MSG:
                        # Requested to go to sleep, so set the flags
                        bSleep = True
                        # If theres a time with the disable flag, go to sleep for that amount of time
                        if jMsg['time'] and jMsg['time'] is not None:
                            sleepTime = jMsg['time']

                # If the flag was set, go to sleep
                if bSleep:
                    if self.debug:
                        print("Disable tracking from mqtt. Sleeping for {}".
                              format(sleepTime))
                    self.goToSleep(sleepTime=sleepTime)

            except ValueError:
                if self.debug:
                    print('Exception parsing disable tracking mqtt msg')

    def sendMQTTMessage(self, topic, msg, retain=False):
        '''
        Sends an MQTT message to the specified topic
        topic - Topic to send to
        msg - Message to send to topic
        mqttClient - MQTT Client used to send the message. If not defined, sends to default configured mqtt client in configuration
        '''
        debug = self.debug

        # If LTE is not setup, initialize it so we can send messages
        #self.initLTE()

        if self.mqttClient is None:
            try:
                # Instantiate a new MQTTClient
                self.mqttClient = self._getMqttClient(debug)
            except:
                self.mqttClient = None

        try:
            if self.mqttClient is not None:
                # Send the message topic
                self.mqttClient.publish(topic=topic, msg=msg, retain=retain)
        except:
            if debug:
                print(
                    "Exception occurred attempting to connect to MQTT server")

    def goToSleep(self, sleepTime=60, bWithInterrupt=False, bSleepGps=True):
        '''
        Puts the py to deepsleep, turning off lte in order to reduce battery consumption.
        By default, sleeps for 60 seconds and powers down gps.
        sleepTime - specifies the time (in seconds) to put the device in deep sleep before waking up
        bWithInterrupt - if True, will wakeup for both timer timeout as well as acceleration interrupt
        bSleepGps - If True, puts the gps in deepsleep state as well (will take longer to reinitialize and refix gps signal)
        '''
        # Enable wakeup source from INT pin
        self.pytrack.setup_int_pin_wake_up(False)

        # Enable activity and inactivity interrupts with acceleration threshold and min duration
        if bWithInterrupt:
            self.pytrack.setup_int_wake_up(True, True)
            self.accel.enable_activity_interrupt(
                ConfigAccelerometer.INTERRUPT_THRESHOLD,
                ConfigAccelerometer.INTERRUPT_DURATION)

        # If mqttClient is defined, disconnect
        if self.mqttClient is not None:
            try:
                self.mqttClient.disconnect()
            except:
                if self.debug:
                    print("Exception occurred disconnecting from mqtt client")

        # Disconnect lte
        if self.lte is not None and self.lte.isconnected():
            try:
                self.lte.disconnect()
                time.sleep(1)
                self.lte.dettach()
            except:
                if self.debug:
                    print("Exception disconnecting from lte")

        # Go to sleep for specified amount of time if no accelerometer wakeup
        if self.debug:
            print("Sleeping for {} seconds with accel interrupt? {}".format(
                sleepTime, bWithInterrupt))
            time.sleep(0.5)

        time.sleep(0.1)
        self.pytrack.setup_sleep(sleepTime)
        self.pytrack.go_to_sleep(gps=bSleepGps)

    def _getGpsFix(self):
        '''
        Attempts to lock on a signal to the gps.
        Returns true if signal is found, false otherwise
        '''
        # Attempt to get the gps lock for X number of attempts (defined in config)
        maxTries = max(ConfigGPS.LOCK_FAIL_ATTEMPTS, 1)
        signalFixTries = maxTries
        while signalFixTries > 0:
            signalFixTries -= 1
            if self.debug:
                print("On GPS fix try number {} of {}".format(
                    maxTries - signalFixTries, maxTries))
            self.gps.get_fix(debug=False)
            pycom.heartbeat(False)
            bIsFixed = False

            if self.gps.fixed():
                # Got the GPS fix, exit out of this while condition
                if self.debug:
                    pycom.rgbled(0x000f00)
                bIsFixed = True
            else:
                # If couldnt get a signal fix, try again
                if self.debug:
                    pycom.rgbled(0x0f0000)

        return bIsFixed

    def monitorLocation(self, bWithMotion=True):
        '''
        Sends GPS location to Mqtt topic. Continues sending data as long as motion is detected
        bWithMotion - If true, continues to monitor and send GPS location to topic as long as accelerometer activity is
            detected. If false, only publishes location once
        '''
        if self.debug:
            print("Monitoring Location")
        self.gps = L76GNSS(self.pytrack,
                           timeout=ConfigGPS.LOCK_TIMEOUT,
                           debug=False)
        self.gps.setAlwaysOn()

        if not self._getGpsFix():
            # Couldnt get a signal so send message to topic for gps not available and exit (go back to sleep)
            if self.debug:
                print("Couldnt get a GPS signal after {} attempts".format(
                    ConfigGPS.LOCK_FAIL_ATTEMPTS))
            self.sendMQTTMessage(ConfigMqtt.TOPIC_GPS_NOT_AVAILABLE, "-1")
            return

        # Otherwise we have a gps signal, so get the coordinates and send to topic
        coordinates = self.gps.coordinates()
        self.sendMQTTMessage(ConfigMqtt.TOPIC_GPS, coordinates)

        # Save current timestamp of log time
        self._getRTC()  # Syncs rtc
        pycom.nvs_set(ConfigGPS.NVS_LAST_LOCATION_LOG_TIME, utime.time())

        # If we want to monitor with motion (send multiple gps coordinates as long as there is motion), start monitoring
        if bWithMotion & self.accelInMotion():
            # Go to sleep for a specified amount of time (keeping GPS alive) to conserve some battery
            # TODO - check if this is better than setPeriodicMode
            if self.debug:
                print("Putting gps in low power and going to sleep")
            #Save state to nvs (non volatile storage)
            pycom.nvs_set(ConfigGPS.NVS_SLEEP_CONTINUE_GPS_READ, 1)
            self.goToSleep(sleepTime=ConfigGPS.SLEEP_BETWEEN_READS,
                           bWithInterrupt=False,
                           bSleepGps=False)

    def accelInMotion(self, numReads=10):
        '''
        Takes numReads measurements of accelerometer data to detect if there is motion.
        numReads - Number of measurements to take to detect motion
        Returns true if delta sensor data is above a threshold (meaning there is active motion), false otherwise
        '''
        accel = self.accel
        xyzList = list()
        xyzList.append(accel.acceleration())
        for index in range(0, numReads):
            # Print change from last reading
            time.sleep(0.5)
            xyzList.append(accel.acceleration())
            deltas = list(
                map(lambda b, a: abs(b - a), xyzList[-1], xyzList[-2])
            )  # Get last element (with -1) and subtract previous element (-2)
            # If max delta is greater than threshold, return true
            if max(deltas) >= ConfigAccelerometer.MOTION_CHECK_MIN_THRESHOLD:
                return True

        # Get the largest change in x, y, and z and see if that surpasses the threshold
        minVals = list()
        maxVals = list()
        for i in range(3):
            minVals.append(min(map(lambda a, i=i: a[i], xyzList)))
            maxVals.append(max(map(lambda a, i=i: a[i], xyzList)))

        # Get the maximum delta for x, y, z for all logged points
        deltas = list(map(lambda b, a: b - a, maxVals, minVals))
        if self.debug:
            print("Deltas accel motion {}".format(deltas))
        # If any x, y, or z axis in deltas array have a total delta change past the allowed threshold, return true. Otherwise return false
        return max(deltas) >= ConfigAccelerometer.MOTION_CHECK_MIN_THRESHOLD

    def logRegularCoordinates(self):
        '''
        On regular timed wakeups, we still log our location every so often. Check the last time the location was
        logged and if the time is greater than the surpassed time defined in config, log coordinates again
        '''
        lastLogTime = self._getNVS(ConfigGPS.NVS_LAST_LOCATION_LOG_TIME)
        self._getRTC()  # Updates RTC

        # Compare the last log time with current rtc to see if threshold has passed
        if (lastLogTime is None or
            (utime.time() - lastLogTime > ConfigGPS.LOCATION_LOG_INTERVAL)):
            # Need to update gps as time has elapsed since last log
            self.monitorLocation(bWithMotion=False)  # Only log once

    def accelWakeup(self):
        '''
        Logic to handle board wakeup interruption due to accelerometer.
        Sends mqtt messages for wakeup if client is defined.
        '''
        debug = self.debug
        if debug:
            print("Accelerometer wakeup")

        # Check if the owner is nearby (owner moving device). If so, handle differently
        if self.checkOwnerNearby and self.isOwnerNearby():
            # Owner is nearby. If last wake is with 2 minutes, we are most likely riding
            # so go to sleep for longer time without wakeup
            self.handleOwnerNearby()

        # Check the accelerometer is still active (preventing false negatives for alerting of theft)
        # If we dont ready any new accelerometer motion, exit this function and dont send any accelerometer wakeup or gps msgs
        if not self.accelInMotion():
            if debug:
                print("Not currently in motion, going back to sleep")
            return
        else:
            if debug:
                print("Motion detected after wakeup...")

        # Not a false wakeup, so send a message to the initial accelerometer wakeup topic
        self.sendMQTTMessage(ConfigMqtt.TOPIC_ACCEL_WAKEUP, "1")

        # Send GPS updates while there has been continued motion for some time
        self.monitorLocation(bWithMotion=True)