Exemple #1
0
def send_LORA(value):
    # Initialize LoRa in LORAWAN mode.
    lora = LoRa(mode=LoRa.LORAWAN)

    # create an ABP authentication params
    dev_addr = struct.unpack(">l", binascii.unhexlify(config.DEV_ADDR.replace(' ','')))[0]
    nwk_swkey = binascii.unhexlify(config.NWK_SWKEY.replace(' ',''))
    app_swkey = binascii.unhexlify(config.APP_SWKEY.replace(' ',''))

    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

    # remove all the non-default channels
    for i in range(3, 16):
        lora.remove_channel(i)

    # set the 3 default channels to the same frequency
    lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
    lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5)
    lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5)

    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

    # make the socket blocking
    s.setblocking(False)        

    s.send(bytes(value))
Exemple #2
0
def lora():
    lora = LoRa(mode=LoRa.LORAWAN)

    dev_addr = struct.unpack(">l",
                             binascii.unhexlify('26011DA5'.replace(
                                 ' ', '')))[0]  #Device Address
    nwk_swkey = binascii.unhexlify('9E8262DC2B9787CA600C5CF46F25CC55'.replace(
        ' ', ''))  # Network Session Key
    app_swkey = binascii.unhexlify('77F84AF9B49326ACE2E1F0CB18A79FB0'.replace(
        ' ', ''))  # App Session Key

    for channel in range(3, 16):
        lora.remove_channel(channel)

    # set the  channels  frequency
    lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
    lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5)
    lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5)

    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

    for i in range(3, 16):
        lora.remove_channel(i)

    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
    s.setblocking(False)

    return s
Exemple #3
0
    def initialize_lorawan_link(self):
        #print(ubinascii.hexlify(network.LoRa().mac()))

        # Initialise LoRa in LORAWAN mode.
        # Please pick the region that matches where you are using the device:
        # Asia = LoRa.AS923
        # Australia = LoRa.AU915
        # Europe = LoRa.EU868
        # United States = LoRa.US915
        lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915, adr=False)
        self.myLora = lora

        # create an ABP authentication params
        dev_addr = struct.unpack(">l", ubinascii.unhexlify('260211EE'))[0]
        nwk_swkey = ubinascii.unhexlify('AB189EFE29DCF9F9830F3A564DC1844E')
        app_swkey = ubinascii.unhexlify('A55931ACC412DE51171CEDA45BE6B319')

        #for channel in range(0, 72):
        #    lora.add_channel(channel, frequency=916800000, dr_min=0, dr_max=5)
        #lora.add_channel(0, frequency=923300000, dr_min=0, dr_max=5)

        for i in range(8, 72):
            lora.remove_channel(i)

        start = 916800000
        f_inc = 200000
        curr  = start

        for i in range(8):
            #print(curr)
            lora.add_channel(index=i, frequency=curr, dr_min=0, dr_max=5)
            curr += f_inc

        #lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self.lora_cb)

        # join a network using ABP (Activation By Personalization)
        lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

        #print(lora.has_joined())

        # wait until the module has joined the network
        while not lora.has_joined():
            time.sleep(2.5)
            print('Not yet joined...')

        #print("Has joined!!!!!")

        # create a LoRa socket
        s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # set the LoRaWAN data rate
        s.setsockopt(socket.SOL_LORA, socket.SO_DR, self.data_rate)
        s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False)

        return s
Exemple #4
0
def init():
    global s
    # initialize LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

    # create an OTA authentication params
    # dev_eui = binascii.unhexlify('30AEA4FFFE505654')
    dev_eui = binascii.unhexlify('3AAEA4FFFE505654')
    app_eui = binascii.unhexlify('70B3D57ED000BDA0')
    # app_key = binascii.unhexlify('6D08E6C2C4237B3A1D223404713DF335')
    app_key = binascii.unhexlify('705DFC1AF37D90FB858F510EAFAAAE14')

    # set the 3 default channels to the same frequency (must be before sending the OTAA join request)
    lora.add_channel(0, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5)
    lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5)
    lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5)

    # join a network using OTAA
    lora.join(activation=LoRa.OTAA,
              auth=(dev_eui, app_eui, app_key),
              timeout=0,
              dr=config.LORA_NODE_DR)

    # wait until the module has joined the network
    while not lora.has_joined():
        time.sleep(2.5)
        print('Not joined yet...')

    print('Joined')

    # remove all the non-default channels
    for i in range(3, 16):
        lora.remove_channel(i)

    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.LORA_NODE_DR)

    # make the socket blocking
    s.setblocking(False)
Exemple #5
0
    def send(self):
        t0 = time.time()
        print("LoRaWAN start")
        lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

        # set the 3 default channels to the same frequency (must be before sending the OTAA join request)
        lora.add_channel(0,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=5)
        lora.add_channel(1,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=5)
        lora.add_channel(2,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=5)

        # join a network using OTAA
        lora.join(activation=LoRa.OTAA,
                  auth=(self.dev_eui, self.app_eui, self.app_key),
                  timeout=0,
                  dr=config.LORA_NODE_DR)

        # wait until the module has joined the network
        while not lora.has_joined():
            time.sleep(2.5)
            print('Not joined yet...', time.localtime())

        # remove all the non-default channels
        for i in range(3, 16):
            lora.remove_channel(i)

        # create a LoRa socket
        s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # set the LoRaWAN data rate
        s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.LORA_NODE_DR)

        # make the socket non-blocking
        s.setblocking(False)

        pkt = b'PKT #' + bytes([i])
        print('Sending:', pkt)
        s.send(pkt)
        print("LoRaWAN done in ", time.time() - t0, " seconds")
Exemple #6
0
def connect():
    global _lora

    pycom.rgbled(0x7f0000)  #red

    _lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

    # Remove all the non-default channels
    for i in range(3, 16):
        _lora.remove_channel(i)
    print('Removed default channels')
    time.sleep(1)

    # Set EU ISM 868 channel plan for TTN Europe
    _lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
    _lora.add_channel(1, frequency=868300000, dr_min=0, dr_max=5)
    _lora.add_channel(2, frequency=868500000, dr_min=0, dr_max=5)
    _lora.add_channel(3, frequency=867100000, dr_min=0, dr_max=5)
    _lora.add_channel(4, frequency=867300000, dr_min=0, dr_max=5)
    _lora.add_channel(5, frequency=867500000, dr_min=0, dr_max=5)
    _lora.add_channel(6, frequency=867700000, dr_min=0, dr_max=5)
    _lora.add_channel(7, frequency=867900000, dr_min=0, dr_max=5)

    print('EU channels set')
    time.sleep(1)

    #Join TTN Network via OTAA
    _lora.join(activation=LoRa.OTAA,
               auth=(dev_eui, app_eui, app_key),
               timeout=0,
               dr=0)

    # wait until the module has joined the network
    print('Trying to join TTN Network...')
    while not _lora.has_joined():
        pycom.rgbled(0x7f7f00)  #yellow
        time.sleep(5)
        print('...')
        pass

    print('Network joined')
    pycom.rgbled(0x009999)  #teal
Exemple #7
0
    def setupLora():
        utime.sleep_ms(5)

        #thethingsnetwork parameters
        dev_addr = struct.unpack(">l", binascii.unhexlify(config.dev_addr))[0]
        nwk_swkey = binascii.unhexlify(config.nwk_swkey)
        app_swkey = binascii.unhexlify(config.app_swkey)

        #initialize LoRa in LORAWAN mode for Australia AU915
        lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915)

        # remove all the non-default channels and leave channels 8-15 and 65
        for index in range(0, 8):
            lora.remove_channel(index)  # remove 0-7
        for index in range(16, 65):
            lora.remove_channel(index)  # remove 16-64
        for index in range(66, 72):
            lora.remove_channel(index)  # remove 66-71

        # join a network using ABP (Activation By Personalization)
        lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

        # create a LoRa socke
        s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # make the socket non-blocking
        s.setblocking(False)

        #print("LoRa connexion set up")
        utime.sleep_ms(5)
        return s
def setup_node():
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915)

    # create an ABP authentication params
    dev_addr = struct.unpack(">l",
                             binascii.unhexlify('260210B3'.replace(' ',
                                                                   '')))[0]
    nwk_swkey = binascii.unhexlify('EC6368A1D013E22B7B4BAF96645DCF48'.replace(
        ' ', ''))
    app_swkey = binascii.unhexlify('5A60972B94850CA94141ED76FAC0DEDD'.replace(
        ' ', ''))

    # remove all the channels
    for channel in range(0, 72):
        lora.remove_channel(channel)

    # set all channels to the same frequency (must be before sending the OTAA join request)
    for channel in range(0, 72):
        lora.add_channel(channel,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=4)

    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.LORA_NODE_DR)

    # make the socket blocking
    s.setblocking(False)

    return s
Exemple #9
0
class Comunication:
    def __init__(self):
        self.key = b'encriptaincendis'
        self.node_list = ""
        pass

    # Initialize LoRa in LORAWAN mode.
    def JoinLoraWan(self):
        self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

        # create an OTA authentication params
        app_eui = ubinascii.unhexlify('70B3D57ED001C55E')
        dev_eui = ubinascii.unhexlify(
            '006D2D7767E7BAFE')  # these settings can be found from TTN
        #app_eui = ubinascii.unhexlify('70B3D57ED0019255') # these settings can be found from TTN
        app_key = ubinascii.unhexlify('0A05862CEA15FC56C047FC03FBDF34DB'
                                      )  # these settings can be found from TTN

        # set the 3 default channels to the same frequency (must be before sending the OTAA join request)
        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)

        # join a network using OTAA
        self.lora.join(activation=LoRa.OTAA,
                       auth=(dev_eui, app_eui, app_key),
                       timeout=0)

        # wait until the module has joined the network
        while not self.lora.has_joined():
            time.sleep(2.5)
            print('Not joined yet...')

        # remove all the non-default channels
        for i in range(3, 16):
            self.lora.remove_channel(i)

        # create a LoRa socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # set the LoRaWAN data rate. DR5 means 5470 bits/s ans max payload=230
        self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

        # make the socket non-blocking
        self.s.setblocking(False)

        time.sleep(5)

    def start_LoraRaw(self):
        self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868)
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setblocking(False)  #Aquesta instrucció igual sobra
        time.sleep(5)
        lora = self.lora
        #return(lora)

    def change_txpower(self, power):
        self.lora.tx_power(power)

    def savestate(self):
        self.lora.nvram_save()

    def Switch_to_LoraRaw(self):
        self.lora.nvram_save()
        self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868)
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setblocking(False)  #Aquesta instrucció igual sobra
        time.sleep(5)

    def Switch_to_LoraWan(self):
        self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
        self.lora.nvram_restore()
        time.sleep(2.5)
        #Si no es reinicia el socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
        self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False)

    def EnviarGateway(self, data):
        self.s.bind(2)
        self.s.send(data)
        time.sleep(10)

    def sendData(self, msg, rtc, f):
        if "Hay" not in msg:
            f = open('msg_sent_final.txt', 'a')
            f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format(
                rtc.now()[2],
                rtc.now()[1],
                rtc.now()[0],
                rtc.now()[3],
                rtc.now()[4],
                rtc.now()[5], msg, self.lora.stats()))
            f.close()
        self.s.setblocking(True)
        iv = crypto.getrandbits(
            128)  # hardware generated random IV (never reuse it)
        cipher = AES(self.key, AES.MODE_CFB, iv)
        misg_crc = msg + " " + str(self.calculate_crc(msg))
        msg = iv + cipher.encrypt(misg_crc)
        self.s.send(msg)
        #print("missatge amb crc", msg)
        self.s.setblocking(False)
        #print(msg)
        #print(len(msg))
        #time.sleep(5)

    def reciveData(self, rtc, f):
        self.s.setblocking(False)
        msg = self.s.recv(128)  #Get any data recieved
        #If there's any data, decrypt
        if (len(msg) > 0):
            try:
                #print("encriptat: ",msg)
                cipher = AES(self.key, AES.MODE_CFB,
                             msg[:16])  # on the decryption side
                original = cipher.decrypt(msg[16:])
                print("original ", original)
                if "Config" in original or "stop" in original or "Discover" in original or "Hello" in original or "Info" in original or "Token" in original or "Alarm" in original or "Hay" in original:
                    crc_OK, msg = self.check_crc(original)
                    if crc_OK:
                        if "Hay" not in msg:
                            f = open('msg_received_final.txt', 'a')
                            f.write(
                                "{}/{}/{} {}:{}:{} msg {} stats {}\n".format(
                                    rtc.now()[2],
                                    rtc.now()[1],
                                    rtc.now()[0],
                                    rtc.now()[3],
                                    rtc.now()[4],
                                    rtc.now()[5], msg, self.lora.stats()))
                            f.close()
                        return (msg)
                    else:
                        print("CRC not OK")
                        return ("error")
                else:
                    return ("error")
                    print("Keyword not in msg")
            except:
                return ("error")
                print("Exception")
        else:
            return ("error")
            print("Empty msg")

    def update_neighbours(self, pow, id_n, neighbours):
        if id_n in neighbours[0]:
            if pow < neighbours[1][neighbours[0].index(id_n)]:
                neighbours[1][neighbours[0].index(id_n)] = pow
        else:
            neighbours[0].append(id_n)
            neighbours[1].append(pow)
            #print("I have a friend ")
        print(neighbours)
        return neighbours

    def neighbours_min(self, neighbours, neighbours_aux, id):
        for id in neighbours[0]:
            if id in neighbours_aux[0]:
                neighbours[1][neighbours[0].index(id)] = min(
                    neighbours[1][neighbours[0].index(id)],
                    neighbours_aux[1][neighbours_aux[0].index(id)])
        print(neighbours)
        return (neighbours)

    def ApplyFormat(self, splitmsg):
        packet_dust = ustruct.pack('H',
                                   int(splitmsg[3]))  #Unsigned short 2 bytes
        packet_tempC = ustruct.pack('H', int(splitmsg[4]))
        packet_Tht = ustruct.pack('H', int(splitmsg[5]))
        packet_Hht = ustruct.pack(
            'B', round(int(splitmsg[6]) *
                       100))  #Form 0 to 1 -> 0% to 100% #Unsigned char 1 byte
        packet_tbmp = ustruct.pack('H', int(splitmsg[7]))
        packet_val = ustruct.pack('H', int(splitmsg[8]))
        packet_dhi = ustruct.pack('B', int(splitmsg[9]))
        #+packet_TCam=ustruct.pack('f',int(splitmsg[10]))
        #id=splitmsg[1].encode('utf-8')
        id_aux = ustruct.pack('>Q', int(splitmsg[1], 16))  #long long: 8 bytes
        return (packet_dust + packet_tempC + packet_Tht + packet_Hht +
                packet_tbmp + packet_val + packet_dhi + id_aux)  #+packet_TCam)

    def calculate_crc(self, msg):
        """
        Compute CRC
        """
        if type(msg) == bytes:
            msg = bytes.decode(msg)
        crc = 0
        data = bin(int(binascii.hexlify(msg), 16))
        data = str.encode(data)
        for i in range(len(data)):
            byte = data[i]
            for b in range(8):
                fb_bit = (crc ^ byte) & 0x01
                if fb_bit == 0x01:
                    crc = crc ^ 0x18
                crc = (crc >> 1) & 0x7f
                if fb_bit == 0x01:
                    crc = crc | 0x80
                byte = byte >> 1
        return crc

    def check_crc(self, msg):
        """
            Check if CRC received is correct
            """
        if type(msg) == bytes:
            msg = bytes.decode(msg)
        splitmsg = msg.split()
        crc_rcv = int(splitmsg[-1])
        aux = " ".join(splitmsg[:-1])  #Not including the CRC received
        crc_new = self.calculate_crc(aux)
        return (crc_new == crc_rcv, aux)

    def get_node_list(self, list):
        self.node_list = list
def initialize_lora(name):
    print("first connection")
    lora = LoRa(mode=LoRa.LORAWAN,
                region=LoRa.US915,
                tx_power=20,
                bandwidth=LoRa.BW_500KHZ,
                sf=7,
                frequency=903900000)
    #remove all channels gateway doesn't use
    for channel in range(16, 72):
        lora.remove_channel(channel)
    for channel in range(0, 7):
        lora.remove_channel(channel)
    #create an OTAA authentication parameters for no ring lopy
    if name == 1:
        dev_eui = ubinascii.unhexlify(
            '70B3D549952757BF')  # these settings can be found from TTN
        app_eui = ubinascii.unhexlify('70B3D57ED0028A4F')
        app_key = ubinascii.unhexlify('88397B010F71D34BEDF77DA003C3A54C')
    elif name == NO_RING:
        dev_eui = ubinascii.unhexlify(
            '70B3D54990435DFE')  # these settings can be found from TTN
        app_eui = ubinascii.unhexlify('70B3D57ED0028A4F')
        app_key = ubinascii.unhexlify('CE46C01958A612D102F0D106AB415862')
    else:
        dev_eui = ubinascii.unhexlify(
            '70B3D54990435DFE')  # these settings can be found from TTN
        app_eui = ubinascii.unhexlify('70B3D57ED0028A4F')
        app_key = ubinascii.unhexlify('CE46C01958A612D102F0D106AB415862')

    if not lora.has_joined():
        lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0)
        pycom.rgbled(green)
        time.sleep(2.5)
    handshk_time = Timer.Chrono()
    handshk_time.start()
    # wait until the module has joined the network
    while not lora.has_joined():
        pycom.rgbled(off)
        time.sleep(0.1)
        pycom.rgbled(red)
        time.sleep(2.4)
        print('Not yet joined...')
    lora.nvram_save()
    handshk_time.stop()
    print("Total handshake time: {0}".format(handshk_time.read()))
    print('Joined!')
    pycom.rgbled(blue)
    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    #set to confirmed type of messages
    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)
    # make the socket blocking
    # (waits for the data to be sent and for the 2 receive windows to expire)
    s.setblocking(True)
    # send some data
    s.send(make_payload())
    # make the socket non-blocking
    s.setblocking(False)
    # get any data received (if any...)
    data = s.recvfrom(128)
    print("received message: {0}".format(data))

    return
class Node:
    def __init__(self, data_rate, py):
        self.lora = None  # Instancia de Lora (sin inicializar)
        self.s = None  # Instancia Socket (sin inicializar)
        self.dr = data_rate  # Data Rate (defecto 5)
        self.py = py  # Instancia de Pysense
        self.acc = LIS2HH12(self.py)  # Instancia del Acelerometro
        self.last = [0, 0, 0]  # Último valor leído de aceleracion
        self.raw = [0, 0, 0]  # Valor leído actual de aceleracion
        self.busy = 0  # Value has passed limit
        self.interval = 10  # Intervalo de toma de datos
        self.battery = None  # Valor de la tensión de batería
        self.s_lock = _thread.allocate_lock()  # Semaforo para envío
#------------------------------------------------------------------------------#

    def connect(self, dev_eui, app_eui, app_key):
        """
        Connect device to LoRa.
        Set the socket and lora instances.
        """
        # Initialize LoRa in LORAWAN mode
        self.lora = LoRa(mode=LoRa.LORAWAN, device_class=LoRa.CLASS_A)
        # Set the 3 default channels to the same frequency (must be before
        # sending the OTAA join request)
        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)
        # Join a network using OTAA (Over the Air Activation)
        self.lora.join(activation=LoRa.OTAA,
                       auth=(dev_eui, app_eui, app_key),
                       timeout=0,
                       dr=5)  #login for TheThingsNetwork see here:
        #https://www.thethingsnetwork.org/forum/t/lopy-otaa-example/4471
        # Wait until the module has joined the network
        while not self.lora.has_joined():
            print("Trying to join LoraWAN with OTAA")
            time.sleep(2.5)
        print("LoraWAN joined! ")
        #Handler de Recepción
        #self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT),handler=self.lora_cb)
        # save the LoRaWAN connection state
        self.lora.nvram_save()
#------------------------------------------------------------------------------#

    def send(self, data):
        """
        Send data over the network.
        """

        self.s_lock.acquire(
        )  # Espera a que el semáforo esté disponible (tiempo indefinido)

        if py.get_wake_reason(
        ) == WAKE_REASON_ACCELEROMETER:  #Si despierta tras deepsleep
            # Initialize LoRa in LORAWAN mode
            self.lora = LoRa(mode=LoRa.LORAWAN,
                             adr=True,
                             device_class=LoRa.CLASS_A)
            # restore the LoRaWAN connection state
            try:
                self.lora.nvram_restore()
            except OSError:
                print("Error: LoRa Configuration could not be restored")
                self.connect(
                    binascii.unhexlify('006A76B0778AEDA7'),
                    binascii.unhexlify('70B3D57ED0009ABB'),
                    binascii.unhexlify('08D62712D816F1C28B7E6EA39E711209'))
                print("LoRa Connection Parameters Recovered")
        for i in range(3, 16):
            self.lora.remove_channel(i)
        # Set the 3 default channels to the same frequency
        # (must be before sending the OTAA join request)
        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)
        # Create a LoRa socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        print("Created LoRaWAN socket")
        # Make the socket non-blocking
        self.s.setblocking(True)

        try:
            self.s.send(data)
            self.s.setblocking(False)  #Espera para posible recepción
            rx = bytes(self.s.recv(128))  #Recepción de datos
            self.receive(rx=rx)
            self.lora.nvram_save()
        except OSError as e:
            if e.errno == 11:
                print("Caught exception while sending")
                print("errno: ", e.errno)

        self.s_lock.release()  #Libera el semáforo
        _thread.exit()  #Cierra el hilo

#------------------------------------------------------------------------------#
#Función de recpeción de datos.Es activada tras la ventana de recepción
#posterior al envío.

    def receive(self, rx=None):
        if len(rx) == 0:  #No hay mensaje de recepción
            pass
        else:
            if rx[0] == 82:  #Orden de Cambio Data Rate (ASCII hex R=0x52 dec 87)
                print("Cambiando Data Rate %d" %
                      (int.from_bytes(rx[1:], 'big')))
                self.dr = int.from_bytes(
                    rx[1:], 'big')  #Decodifica el valor del nuevo data Rate
                pycom.nvs_set('data_rate', self.data_rate)  #Lo guarda en NVRAM
            else:
                pass
#------------------------------------------------------------------------------#
#Función de lectura de medidas. Los sensores ya han sido inicializados al
#crear la instancia de la clase Node

    def readsens(self):
        self.raw = self.acc.acceleration(
        )  # Devuelve tuple con aceleracion en tres ejes (G)
        print("Aceleracion-> X:%fG Y:%fG Z:%fG" %
              (self.raw[0], self.raw[1], self.raw[2]))
        #Cálculos
        #if (self.raw[0] > 2.1) or (self.raw[1] > 2.1) or (self.raw[2] > 2.1):
        #        print("Enviando datos")
        #        XR=int(self.raw[0]*10000).to_bytes(2,'little')
        #        YR=int(self.raw[1]*10000).to_bytes(2,'little')
        #        ZR=int(self.raw[2]*10000).to_bytes(2,'little')
        #        XL=int(self.last[0]*10000).to_bytes(2,'little')
        #        YL=int(self.last[1]*10000).to_bytes(2,'little')
        #        ZL=int(self.last[2]*10000).to_bytes(2,'little')
        #        data = XR+YR+ZR+XL+YL+ZL
        #        _thread.start_new_thread(self.send,data)                        # Se crea un hilo para el envío de valores
        self._compare_update()
        alarmaPub = Timer.Alarm(self.readsens(), 10, periodic=False)
        #if (self.raw[0] < 1.5) and (self.raw[1] < 1.5) and (self.raw[2] < 1.5):
        #    alarmaPub.cancel();
        #    n.py.setup_int_wake_up(rising=True,falling=False)                   #Activa la interrupcion para el boton DEBUG
        #    print('Activada Interrupccion de Actividad')
        #    n.acc.enable_activity_interrupt(1500,100)                           #Threshold= 1,5G, Min Time = 100ms
        #    print("Going to Sleep")
        #    n.py.setup_sleep(300)
        #    n.py.go_to_sleep()

        #self.battery = round(self.py.read_battery_voltage(),2)
        #print("Battery: %f",%(self.battery))
        #if (self.battery < 3.4):
        #    print("Batería Crítica")
        #    _thread.start_new_thread(self.send,("Batería"," Crítica"))          # Se crea un hilo para el envío de alarma de batería

#------------------------------------------------------------------------------#

    def _compare_update(self):
        if self.raw is not self.last:
            self.last = self.raw
        else:
            pass
Exemple #12
0
class Comunication:
    def __init__(self):
        self.key = b'encriptaincendis'
        pass

    # Initialize LoRa in LORAWAN mode.
    def JoinLoraWan(self):
        self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)

        # create an OTA authentication params
        app_eui = ubinascii.unhexlify('70B3D57ED001C55E')
        dev_eui = ubinascii.unhexlify(
            '006D2D7767E7BAFE')  # these settings can be found from TTN
        #app_eui = ubinascii.unhexlify('70B3D57ED0019255') # these settings can be found from TTN
        app_key = ubinascii.unhexlify('0A05862CEA15FC56C047FC03FBDF34DB'
                                      )  # these settings can be found from TTN

        # set the 3 default channels to the same frequency (must be before sending the OTAA join request)
        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)

        # join a network using OTAA
        self.lora.join(activation=LoRa.OTAA,
                       auth=(dev_eui, app_eui, app_key),
                       timeout=0)

        # wait until the module has joined the network
        while not self.lora.has_joined():
            time.sleep(5)
            print('Not joined yet...')

        # remove all the non-default channels
        for i in range(3, 16):
            self.lora.remove_channel(i)

        # create a LoRa socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # set the LoRaWAN data rate
        self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

        # make the socket non-blocking
        self.s.setblocking(False)

        time.sleep(5)

    """ Your own code can be written below! """

    def start_LoraRaw(self):
        self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868)
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setblocking(False)  #Aquesta instrucció igual sobra
        #time.sleep(5)
        lora = self.lora
        #return(lora)
    def savestate(self):
        self.lora.nvram_save()

        # def restorestate(self):
        #     self.lora.nvram_restore()

    def Switch_to_LoraRaw(self):
        self.lora.nvram_save()
        self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868)
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setblocking(False)  #Aquesta instrucció igual sobra
        time.sleep(5)

    def Switch_to_LoraWan(self):
        self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
        self.lora.nvram_restore()
        time.sleep(5)
        #Si no es reinicia el socket el missatge 3 no s'envia
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

    def EnviarGateway(self, data):
        self.s.send(data)
        time.sleep(5)

    def RebreGateway(self):
        data, port = self.s.recvfrom(256)
        print(data)

    def sendData(self, misg):
        self.s.setblocking(True)
        iv = crypto.getrandbits(
            128)  # hardware generated random IV (never reuse it)
        cipher = AES(self.key, AES.MODE_CFB, iv)
        msg = iv + cipher.encrypt(misg)
        self.s.send(msg)
        self.s.setblocking(False)
        #print(msg)
        #print(len(msg))
        time.sleep(5)

    def reciveData(self):
        self.s.setblocking(False)
        msg = self.s.recv(128)  #Get any data recieved
        #If there's any data, decrypt
        if len(msg) > 0:
            print("encriptat: ", msg)
            cipher = AES(self.key, AES.MODE_CFB,
                         msg[:16])  # on the decryption side
            original = cipher.decrypt(msg[16:])
            print("original ", original)
            return (original)
        else:
            return
class PybytesConnection:
    def __init__(self, config, message_callback):
        if config is not None:
            self.__conf = config
            try:
                self.__host = pycom.nvs_get('pybytes_server')
            except:
                self.__host = config.get('server')
            self.__ssl = config.get('ssl', False)
            self.__ssl_params = config.get('ssl_params', {})
            self.__user_name = config.get('username')
            self.__device_id = config.get('device_id')
            self.__mqtt_download_topic = "d" + self.__device_id
            self.__mqtt_upload_topic = "u" + self.__device_id
            self.__pybytes_protocol = PybytesProtocol(
                config, message_callback, pybytes_connection=self
            )
        self.__connection = None
        self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED
        self.__lora_socket = None
        self.lora = None
        self.lora_lock = _thread.allocate_lock()
        self.__sigfox_socket = None
        self.lte = None
        self.wlan = None
        self.__network_type = None
        self.__wifi_lte_watchdog = None

    def lte_ping_routine(self, delay):
        while True:
            self.send_ping_message()
            time.sleep(delay)

    def print_pretty_response(self, rsp):
        lines = rsp.split('\r\n')
        for line in lines:
            if line:
                if line not in ['OK']:
                    print(line)

    def __initialise_watchdog(self):
        if self.__conf.get('connection_watchdog', True):
            self.__wifi_lte_watchdog = WDT(
                timeout=constants.__WDT_TIMEOUT_MILLISECONDS
            )
            print('Initialized watchdog for WiFi and LTE connection with timeout {} ms'.format(constants.__WDT_TIMEOUT_MILLISECONDS)) # noqa
        else:
            print('Watchdog for WiFi and LTE was disabled, enable with "connection_watchdog": true in pybytes_config.json') # noqa

    # Establish a connection through WIFI before connecting to mqtt server
    def connect_wifi(self, reconnect=True, check_interval=0.5, timeout=120):
        self.__initialise_watchdog()

        if self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED: # noqa
            print("Error connect_wifi: Connection already exists. Disconnect First") # noqa
            return False
        try:
            from network import WLAN
            antenna = self.__conf.get('wlan_antenna', WLAN.INT_ANT)
            known_nets = [((self.__conf['wifi']['ssid'], self.__conf['wifi']['password']))] # noqa
            if antenna == WLAN.EXT_ANT:
                print("WARNING! Using external WiFi antenna.")

            '''to connect it to an existing network,
            the WiFi class must be configured as a station'''

            self.wlan = WLAN(mode=WLAN.STA, antenna=antenna)

            attempt = 0

            print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected()))

            while not self.wlan.isconnected() and attempt < 3:
                attempt += 1
                print_debug(3, "Wifi connection attempt: {}".format(attempt))
                print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected()))
                available_nets = None
                while available_nets is None:
                    try:
                        available_nets = self.wlan.scan()
                        for x in available_nets:
                            print_debug(5, x)
                        time.sleep(1)
                    except:
                        pass

                nets = frozenset([e.ssid for e in available_nets])
                known_nets_names = frozenset([e[0]for e in known_nets])
                net_to_use = list(nets & known_nets_names)
                try:
                    net_to_use = net_to_use[0]
                    pwd = dict(known_nets)[net_to_use]
                    sec = [e.sec for e in available_nets if e.ssid == net_to_use][0] # noqa
                    print_debug(99, "Connecting with {} and {}".format(net_to_use, pwd))
                    if  sec == 0:
                        self.wlan.connect(net_to_use, timeout=10000)
                    else:
                        self.wlan.connect(net_to_use, (sec, pwd), timeout=10000)
                    start_time = time.time()
                    while not self.wlan.isconnected():
                        if time.time() - start_time > timeout:
                            raise TimeoutError('Timeout trying to connect via WiFi')
                        time.sleep(0.1)
                except Exception as e:
                    if str(e) == "list index out of range" and attempt == 3:
                        print("Please review Wifi SSID and password inside config")
                        self.wlan.deinit()
                        return False
                    elif attempt == 3:
                        print("Error connecting using WIFI: %s" % e)
                        return False

            self.__network_type = constants.__NETWORK_TYPE_WIFI
            print("WiFi connection established")
            try:
                self.__connection = MQTTClient(
                    self.__device_id,
                    self.__host,
                    self.__mqtt_download_topic,
                    self.__pybytes_protocol,
                    user=self.__user_name,
                    password=self.__device_id
                )
                self.__connection.connect()
                self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI # noqa
                self.__pybytes_protocol.start_MQTT(
                    self,
                    constants.__NETWORK_TYPE_WIFI
                )
                return True
            except Exception as ex:
                if '{}'.format(ex) == '4':
                    print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa
                else:
                    print("MQTT ERROR! {}".format(ex))
                return False
        except Exception as ex:
            print("Exception connect_wifi: {}".format(ex))
            return False

    # Establish a connection through LTE before connecting to mqtt server
    def connect_lte(self, activation_info=False, start_mqtt=True):
        if activation_info:
            lte_cfg = activation_info
        else:
            lte_cfg = self.__conf.get('lte')
            self.__initialise_watchdog()

        if lte_cfg is not None:
            if (os.uname()[0] not in ['FiPy', 'GPy']):
                print("You need a device with FiPy or GPy firmware to connect via LTE") # noqa
                return False
            try:
                from network import LTE
                time.sleep(3)
                if lte_cfg.get('carrier', 'standard') == 'standard':
                    carrier = None
                else:
                    carrier = lte_cfg.get('carrier')
                print_debug(1, 'LTE init(carrier={}, cid={})'.format(carrier, lte_cfg.get('cid', 1))) # noqa
                # instantiate the LTE object
                self.lte = LTE(carrier=carrier, cid=lte_cfg.get('cid', 1))
                try:
                    lte_type = lte_cfg.get('type') if len(lte_cfg.get('type')) > 0 else None
                except:
                    lte_type = None
                try:
                    lte_apn = lte_cfg.get('apn') if len(lte_cfg.get('type')) > 0 else None
                except:
                    lte_apn = None
                try:
                    lte_band = int(lte_cfg.get('band'))
                except:
                    lte_band = None
                print_debug(
                    1,
                    'LTE attach(band={}, apn={}, type={})'.format(
                        lte_band,
                        lte_apn,
                        lte_type
                    )
                )

                self.lte.attach(band=lte_band, apn=lte_apn, type=lte_type)  # noqa   # attach the cellular modem to a base station
                while not self.lte.isattached():
                    time.sleep(0.25)
                time.sleep(1)
                print_debug(1, 'LTE connect()')
                # start a data session and obtain an IP address
                self.lte.connect()
                print_debug(1, 'LTE is_connected()')
                while not self.lte.isconnected():
                    time.sleep(0.25)
                print("LTE connection established")
                self.__network_type = constants.__NETWORK_TYPE_LTE

                if start_mqtt:
                    try:
                        self.__connection = MQTTClient(
                            self.__device_id,
                            self.__host,
                            self.__mqtt_download_topic,
                            self.__pybytes_protocol,
                            user=self.__user_name,
                            password=self.__device_id
                        )
                        self.__connection.connect()
                        self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE # noqa
                        self.__pybytes_protocol.start_MQTT(
                            self,
                            constants.__NETWORK_TYPE_LTE
                        )
                        print("Connected to MQTT {}".format(self.__host))
                        return True
                    except Exception as ex:
                        if '{}'.format(ex) == '4':
                            print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa
                        else:
                            print("MQTT ERROR! {}".format(ex))
                        return False
            except Exception as ex:
                print("Exception connect_lte: {}".format(ex))
                sys.print_exception(ex)
            return False
        else:
            print("Error... missing configuration!")
            return False

    # LORA
    def connect_lora_abp(self, lora_timeout, nanogateway):
        print_debug(1,'Attempting to connect via LoRa')
        if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa
            print("Error connect_lora_abp: Connection already exists. Disconnect First") # noqa
            return False
        try:
            from network import LoRa
        except Exception as ex:
            print("This device does not support LoRa connections: %s" % ex)
            return False

        lora_class = self.__conf.get('lora', {}).get('class', 0)
        if self.__conf.get('lora', {}).get('region') is not None:
            self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora').get('region'), device_class=lora_class)
        else:
            self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class)
        self.lora.nvram_restore()

        try:
            dev_addr = self.__conf['lora']['abp']['dev_addr']
            nwk_swkey = self.__conf['lora']['abp']['nwk_skey']
            app_swkey = self.__conf['lora']['abp']['app_skey']
        except Exception as ex:
            print("Invalid LoRaWAN ABP configuration!")
            print_debug(1, ex)
            return False
        timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000

        dev_addr = struct.unpack(">l", binascii.unhexlify(dev_addr.replace(' ', '')))[0] # noqa
        nwk_swkey = binascii.unhexlify(nwk_swkey.replace(' ', ''))
        app_swkey = binascii.unhexlify(app_swkey.replace(' ', ''))

        try:
            print("Trying to join LoRa.ABP for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout))
            self.lora.join(
                activation=LoRa.ABP,
                auth=(dev_addr, nwk_swkey, app_swkey),
                timeout=timeout_ms
            )

            # if you want, uncomment this code, but timeout must be 0
            # while not self.lora.has_joined():
            #     print("Joining...")
            #     time.sleep(5)

            self.__open_lora_socket(nanogateway)
#            print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size))
#            _thread.stack_size(self.__thread_stack_size)
#            _thread.start_new_thread(self.__check_lora_messages, ())
            return True
        except Exception as e:
            message = str(e)
            if message == 'timed out':
                print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout))
            else:
                print_debug(3, 'Exception in LoRa connect: {}'.format(e))
            return False

    def connect_lora_otaa(self, lora_timeout, nanogateway):
        print_debug(1,'Attempting to connect via LoRa')
        if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa
            print("Error connect_lora_otaa: Connection already exists. Disconnect First") # noqa
            return False
        try:
            from network import LoRa
        except Exception as ex:
            print("This device does not support LoRa connections: %s" % ex)
            return False

        try:
            dev_eui = self.__conf['lora']['otaa']['app_device_eui']
            app_eui = self.__conf['lora']['otaa']['app_eui']
            app_key = self.__conf['lora']['otaa']['app_key']
        except Exception as ex:
            print("Invalid LoRaWAN OTAA configuration!")
            print_debug(1, ex)
            return False

        timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000

        lora_class = self.__conf.get('lora', {}).get('class', 0)
        if self.__conf.get('lora', {}).get('region') is not None:
            self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora', {}).get('region'), device_class=lora_class)
        else:
            self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class)
        self.lora.nvram_restore()

        dev_eui = binascii.unhexlify(dev_eui.replace(' ', ''))
        app_eui = binascii.unhexlify(app_eui.replace(' ', ''))
        app_key = binascii.unhexlify(app_key.replace(' ', ''))
        try:
            if not self.lora.has_joined():
                print("Trying to join LoRa.OTAA for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout))
                self.lora.join(
                    activation=LoRa.OTAA,
                    auth=(dev_eui, app_eui, app_key),
                    timeout=timeout_ms
                )

            # if you want, uncomment this code, but timeout must be 0
            # while not self.lora.has_joined():
            #     print("Joining...")
            #     time.sleep(5)

            self.__open_lora_socket(nanogateway)
#            print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size))
#            _thread.stack_size(self.__thread_stack_size)
#            _thread.start_new_thread(self.__check_lora_messages, ())
            return True
        except Exception as e:
            message = str(e)
            if message == 'timed out':
                print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout))
            else:
                print_debug(3, 'Exception in LoRa connect: {}'.format(e))
            return False

    def __open_lora_socket(self, nanogateway):
        if (nanogateway):
            for i in range(3, 16):
                self.lora.remove_channel(i)

            self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
            self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5)
            self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5)

        print("Setting up LoRa socket...")
        self.__lora_socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        self.__lora_socket.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

        self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_LORA

        self.__pybytes_protocol.start_Lora(self)

        print("Connected using LoRa")

    # SIGFOX
    def connect_sigfox(self):
        if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa
            print("Error: Connection already exists. Disconnect First")
            pass
        try:
            from network import Sigfox
        except Exception:
            print("This device does not support Sigfox connections")
            return
        sigfox_config = self.__conf.get('sigfox', {})
        if sigfox_config is None or sigfox_config.get('RCZ') is None:
            print(constants.__SIGFOX_WARNING)
        try:
            sf_rcz = int(sigfox_config.get('RCZ', 1)) - 1
            if sf_rcz >= 0 and sf_rcz <= 3:
                Sigfox(mode=Sigfox.SIGFOX, rcz=sf_rcz)
                self.__sigfox_socket = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW) # noqa
                self.__sigfox_socket.setblocking(True)
                self.__sigfox_socket.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, False) # noqa
                self.__network_type = constants.__NETWORK_TYPE_SIGFOX
                self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_SIGFOX # noqa
                self.__pybytes_protocol.start_Sigfox(self)
                print(
                    "Connected using Sigfox. Only upload stream is supported"
                )
                return True
            else:
                print('Invalid Sigfox RCZ specified in config!')
                return False
        except Exception as e:
            print('Exception in connect_sigfox: {}'.format(e))
            return False

    # COMMON
    def disconnect(self, keep_wifi=False, force=False):

        if self.__wifi_lte_watchdog is not None:
            self.__wifi_lte_watchdog = WDT(timeout=constants.__WDT_MAX_TIMEOUT_MILLISECONDS)
            print('Watchdog timeout has been increased to {} ms'.format(constants.__WDT_MAX_TIMEOUT_MILLISECONDS)) # noqa

        print_debug(
            1,
            'self.__connection_status={} | self.__network_type={}'.format(
                self.__connection_status, self.__network_type
            )
        )

        if (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED): # noqa
            print_debug(3, "Already disconnected")

        if (constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI <= self.__connection_status <= constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): # noqa
            print_debug(1, 'MQTT over WIFI||LTE... disconnecting MQTT')
            try:
                self.__connection.disconnect(force=force)
                self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED # noqa
            except Exception as e:
                print("Error disconnecting: {}".format(e))

        if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_LORA): # noqa
            print_debug(1, 'Connected over LORA... closing socket and saving nvram') # noqa
            try:
                self.__lora_socket.close()
                self.lora.nvram_save()
            except Exception as e:
                print("Error disconnecting: {}".format(e))

        if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_SIGFOX): # noqa
            print_debug(1, 'Connected over SIGFOX... closing socket')
            try:
                self.__sigfox_socket.close()
            except Exception as e:
                print("Error disconnecting: {}".format(e))

        if (self.__network_type == constants.__NETWORK_TYPE_WIFI and not keep_wifi):
            print_debug(1, 'Connected over WIFI... disconnecting')
            try:
                self.wlan.deinit()
            except Exception as e:
                print("Error disconnecting: {}".format(e))

        if (self.__network_type == constants.__NETWORK_TYPE_LTE):
            print_debug(1, 'Connected over LTE... disconnecting')
            try:
                lte_cfg = self.__conf.get('lte')
                print_debug(1, 'lte.deinit(reset={})'.format(lte_cfg.get('reset', False))) # noqa
                self.lte.deinit(reset=lte_cfg.get('reset', False))
            except Exception as e:
                print("Error disconnecting: {}".format(e))

        self.__network_type = None
        self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED

    def is_connected(self):
        return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa

    # Added for convention with other connectivity classes
    def isconnected(self):
        return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa
class Node:
    def __init__(self,sleep_time,data_rate,pysense):
        self.lora = None                                                        # Instancia de Lora (sin inicializar)
        self.s = None                                                           # Instancia Socket (sin inicializar)
        self.sleep_time = sleep_time                                            # Intervalo de inactividad
        self.dr = data_rate                                                     # Data Rate (defecto 5)
        self.py = pysense                                                       # Instancia de Pysense
        self.lt = LTR329ALS01(self.py)                                          # Instancia Sensor de Luminosidad
        self.mp = MPL3115A2(self.py,mode=PRESSURE)                              # Instancia Sensor de Presión
        self.si = SI7006A20(self.py)                                            # Instancia Sensor de Humedad y tempertura

#------------------------------------------------------------------------------#
    def connect(self,dev_eui,app_eui, app_key):
        """
        Connect device to LoRa.
        Set the socket and lora instances.
        """
        # Initialize LoRa in LORAWAN mode
        self.lora = LoRa(mode = LoRa.LORAWAN,device_class=LoRa.CLASS_A,region=LoRa.EU868)
        # Set the 3 default channels to the same frequency (must be before
        # sending the OTAA join request)
        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)
        # Join a network using OTAA (Over the Air Activation)
        self.lora.join(activation = LoRa.OTAA, auth = (dev_eui,app_eui, app_key),
                    timeout = 0, dr=self.dr)                                                #login for TheThingsNetwork see here:
                                                                                #https://www.thethingsnetwork.org/forum/t/lopy-otaa-example/4471
        # Wait until the module has joined the network
        while not self.lora.has_joined():
            print("Trying to join LoraWAN with OTAA")
            time.sleep(2.5)
        print ("LoraWAN joined! ")
        # save the LoRaWAN connection state
        self.lora.nvram_save()
#------------------------------------------------------------------------------#
    def send(self,data):
        """
        Send data over the network.
        """
        if py.get_wake_reason() == WAKE_REASON_TIMER:                           #Si despierta tras deepsleep
            # Initialize LoRa in LORAWAN mode
            self.lora = LoRa(mode = LoRa.LORAWAN,adr=True,device_class=LoRa.CLASS_A,region=LoRa.EU868)
            # restore the LoRaWAN connection state
            try:
                self.lora.nvram_restore()
            except OSError:
                print("Error: LoRa Configuration could not be restored")
                self.connect(dev_eui,app_eui,app_key)
                print("LoRa Connection Parameters Recovered")
        # remove all the non-default channels
        for i in range(3, 16):
            self.lora.remove_channel(i)
        # Set the 3 default channels to the same frequency
        # (must be before sending the OTAA join request)
        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)
        # Create a LoRa socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        print("Created LoRaWAN socket")
        # Make the socket blocking
        self.s.setblocking(True)                                                #Necesario para gurdar el contador de mensajes

        try:
            self.s.send(data)                                                   #Envio de datos
            self.s.setblocking(False)                                           # make the socket non-blocking (necesario para no dejar colgado el dispositivo)
            rx = bytes(self.s.recv(128))                                        # (because if there's no data received it will block forever...)
            self.receive(rx=rx)
            self.lora.nvram_save()
            print('Lora Config Saved!')
        except OSError as e:
            if e.errno == 11:
                print("Caught exception while sending")
                print("errno: ", e.errno)
                pass

#------------------------------------------------------------------------------#
#Función de recepción de datos.Es activada tras la ventana de recepción
#posterior al envío.
    def receive(self,rx=None):
        if len(rx) == 0:                                                        #No hay mensaje de recepción
            print('No incoming message')
            pass
        else:
            if rx[0] == 73:                                                     #Orden de Cambio de intervalo (ASCII hex I=0x49 dec 73)
                print("Recibido cambio de intervalo %d"
                           %(int.from_bytes(rx[1:],'big')))
                self.sleep_time = int.from_bytes(rx[1:],'big')                  #Decodifica el valor del nuevo intervalo
                pycom.nvs_set('sleep_time',self.sleep_time)                     #Lo guarda en NVRAM
            elif rx[0] == 82:                                                   #Orden de Cambio Data Rate (ASCII hex R=0x52 dec 87)
                print("Cambiando Data Rate %d" %(int.from_bytes(rx[1:],'big')))
                self.dr = int.from_bytes(rx[1:],'big')                          #Decodifica el valor del nuevo data Rate
                pycom.nvs_set('data_rate',self.data_rate)                       #Lo guarda en NVRAM
            elif rx[0] == 79:                                                   #4Fh
                ota = WiFiOTA('MBP_JuanMa','MBP_JuanMa',"54.154.225.138",8000)      #Amazon Web Services Server
                print("Updating via OTA...")
                print('- ' * 20)
                ota.connect()
                ota.update()
            else:
                pass
#------------------------------------------------------------------------------#
#Función de lectura de medidas. Los sensores ya han sido inicializados al
#crear la instancia de la clase Node
    def readsens(self):
        pressure = (int(self.mp.pressure())-90000).to_bytes(2,'little')                     #Segundo Elemento Lista: Presión (entero)
        humidity = int(round(self.si.humidity(),2)*100).to_bytes(2,'little')                #Tercer Elemento Lista: Humedad (dos decimales)
        temperature = int(round(self.si.temperature(),2)*100).to_bytes(2,'little')          #Cuarto Elemento Lista: Temperatura (dos decimales)
        battery = int(round(self.py.read_battery_voltage(),4)*10000-33000).to_bytes(2,'little') #Quinto Elemento Lista: Voltaje (cuatro decimales)
        light = int(self.lt.light()[0]).to_bytes(2,'little')                                #Primer Elemento Lista: Luminosidad (entero)
        reading = light+pressure+humidity+temperature+battery                   #Union de tipos bytes
        return reading
Exemple #15
0
def BLEAndLoRaFun():
    ###### First, initialize as one LoRa node device ######
    # initialize LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    # Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915)

    # create an ABP authentication params
    dev_addr = struct.unpack(">l", binascii.unhexlify('26021A14'))[0]
    nwk_swkey = binascii.unhexlify('BB515D851353D2AB5ACCD112F0F2C597')
    app_swkey = binascii.unhexlify('B74092CB7C5A79CAD681C384ABF925D2')

    # remove all the channels
    for channel in range(0, 72):
        lora.remove_channel(channel)

    # set all channels to the same frequency (must be before sending the OTAA join request)
    for channel in range(0, 72):
        lora.add_channel(channel,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=3)

    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)  # last parameter is 3

    # make the socket non-blocking
    s.setblocking(False)
    '''
	###### Second, set up BLE server service ######
    pycom.heartbeat(False)
    bluetooth = Bluetooth() #create a bluetooth object
    bluetooth.set_advertisement(name='LoPyServer'+str(globalvar.device_id), service_uuid=b'3333333333333333')
    
    #using callback conn_cb to check client's connection
    ##Function:   conn_cb(callback for bluetooth object events checking)
    ##Description:check there is any client connected to the service
    def conn_cb (bt_o):
        events = bt_o.events()#using events to check if there is any client connected to the service
        if  events & Bluetooth.CLIENT_CONNECTED:
            print("Client connected")
            pycom.rgbled(0x007f00) # green
        elif events & Bluetooth.CLIENT_DISCONNECTED:
            bt_o.disconnect_client()
            print("Client disconnected")
            pycom.rgbled(0x7f0000) # red    
            time.sleep(3)       
    bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED | Bluetooth.CLIENT_DISCONNECTED, handler=conn_cb)
    bluetooth.advertise(True)
    #set up BLE service
    srv1 = bluetooth.service(uuid=b'3333333333333333', isprimary=True)
    #set up service character
    chr1 = srv1.characteristic(uuid=b'3333333333333333', value=5)
    #char1_read_counter = 0
    def char1_cb_handler(chr):
        #global char1_read_counter
        #char1_read_counter += 1
        global BLEConnectionCounter
        events = chr.events()
        if  events & Bluetooth.CHAR_WRITE_EVENT:
            print("Write request with value = {}".format(chr.value()))
        else:
            #modify here to send its device_id to other clients
            BLEConnectionCounter += 1
            return str(globalvar.device_id)+' '+str(BLEConnectionCounter)
    #using the callback to send the data to other clients
    char1_cb = chr1.callback(trigger=Bluetooth.CHAR_WRITE_EVENT | Bluetooth.CHAR_READ_EVENT, handler=char1_cb_handler)
	'''
    ###### Third, set up BLE client service ######
    bluetooth_client = Bluetooth()
    #bluetooth_client.init(id=0, mode=Bluetooth.BLE, antenna=None)
    bluetooth_client.start_scan(10)
    #server_name1 = bluetooth_client.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL)

    counter = 50
    #while True:
    while counter > 0:
        print(counter)
        counter -= 1
        #Gets an named tuple with the advertisement data received during the scanning.
        #The structure is (mac, addr_type, adv_type, rssi, data)
        adv = bluetooth_client.get_adv()
        #servermac = ''#save the serer mac
        #use resolve_adv_data to resolve the 31 bytes of the advertisement message
        #Here is problem: when disconnect from server, then adv will always be null...

        #if get a valid advertisement from one server
        if adv:
            server_name = bluetooth_client.resolve_adv_data(
                adv.data, Bluetooth.ADV_NAME_CMPL)
            #print(server_name)
            if checkValidServer(server_name):
                try:
                    #Opens a BLE connection with the device specified by the mac_addr argument
                    #This function blocks until the connection succeeds or fails.
                    #print(adv.mac)
                    #global servermac#change servermac to global
                    #servermac = adv.mac
                    #counter += 1
                    conn = bluetooth_client.connect(adv.mac)
                    #print('connected?',conn.isconnected())
                    services = conn.services()
                    #print('This is service',services)
                    #print(services)
                    #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server
                    for service in services:
                        time.sleep(0.050)
                        if type(service.uuid()) == bytes:
                            chars = service.characteristics()
                            for char in chars:
                                #check if the character properties is PROP_READ
                                properties = char.properties()
                                print('char properties is ' + str(properties))
                                if (properties & Bluetooth.PROP_READ):
                                    print('char {} value = {}'.format(
                                        char.uuid(), char.read()))
                                    #Use LoRa to send the data out
                                    #s.send(char.read())
                                    time.sleep(2)
                                #10 & Bluetooth.PROP_WRITE
                                #10&Bluetooth.PROP_READ
                                if (properties & Bluetooth.PROP_WRITE):
                                    print('write to server!')
                                    char.write(b'x02')
                                    time.sleep(2)
                    #Yunwei
                    conn.disconnect()
                    #bluetooth_client.deinit()
                    bluetooth_client.stop_scan()
                    time.sleep(3)
                    bluetooth_client.deinit()
                    print('deinit')
                    time.sleep(3)
                    bluetooth_client.init()
                    #if(bluetooth_client.isscanning()):
                    #    bluetooth_client.stop_scan()
                    #bluetooth_client.deinit()
                    bluetooth_client.start_scan(10)
                    print('connected?', conn.isconnected())
                    #break
                    time.sleep(3)
                    gc.collect()
                    #if it's still scan, then need to stop scan first
                    #bluetooth_client.start_scan(-1)
                    '''
                    if(bluetooth_client.isscanning()):
                        bluetooth_client.stop_scan()
                        #then scan again
                        bluetooth_client.start_scan(-1)
                    '''
                except:
                    print(
                        "Error while connecting or reading from the BLE device"
                    )
                    #break
                    time.sleep(1)
                    if (bluetooth_client.isscanning()):
                        bluetooth_client.stop_scan()
                        bluetooth_client.deinit()
                        time.sleep(1)
                        bluetooth_client.deinit()
                        time.sleep(1)
                        #init again
                        bluetooth_client.init(id=0,
                                              mode=Bluetooth.BLE,
                                              antenna=None)
                        bluetooth_client.start_scan(10)
                    else:
                        bluetooth_client.deinit()
                        time.sleep(1)
                        bluetooth_client.init()
                        time.sleep(1)
                        bluetooth_client.start_scan(10)
                    print('Scan again')
        else:
            print('adv is None!')
            time.sleep(3)
            '''
            time.sleep(3)
            #if it's still scan, then need to stop scan first
            if(bluetooth_client.isscanning()):
                bluetooth_client.stop_scan()
                #then scan again
                bluetooth_client.start_scan(-1)
            '''
    #bluetooth_client.stop_scan()
    bluetooth_client.stop_scan()
    bluetooth_client.deinit()
    print('out of loop!')
Exemple #16
0
class LoraNet:
    def __init__(self,
                 frequency,
                 dr,
                 region,
                 device_class=LoRa.CLASS_C,
                 activation=LoRa.OTAA,
                 auth=None):
        self.frequency = frequency
        self.dr = dr
        self.region = region
        self.device_class = device_class
        self.activation = activation
        self.auth = auth
        self.sock = None
        self._exit = False
        self.s_lock = _thread.allocate_lock()
        self.lora = LoRa(mode=LoRa.LORAWAN,
                         region=self.region,
                         device_class=self.device_class)

        self._msg_queue = []
        self.q_lock = _thread.allocate_lock()
        self._process_ota_msg = None

    def stop(self):
        self._exit = True

    def init(self, process_msg_callback):
        self._process_ota_msg = process_msg_callback

    def receive_callback(self, lora):
        events = lora.events()
        if events & LoRa.RX_PACKET_EVENT:
            rx, port = self.sock.recvfrom(256)
            if rx:
                if '$OTA' in rx:
                    print("OTA msg received: {}".format(rx))
                    self._process_ota_msg(rx.decode())
                else:
                    self.q_lock.acquire()
                    self._msg_queue.append(rx)
                    self.q_lock.release()

    def connect(self):
        if self.activation != LoRa.OTAA and self.activation != LoRa.ABP:
            raise ValueError("Invalid Lora activation method")
        if len(self.auth) < 3:
            raise ValueError("Invalid authentication parameters")

        self.lora.callback(trigger=LoRa.RX_PACKET_EVENT,
                           handler=self.receive_callback)

        # set the 3 default channels to the same frequency
        self.lora.add_channel(0, frequency=self.frequency, dr_min=0, dr_max=5)
        self.lora.add_channel(1, frequency=self.frequency, dr_min=0, dr_max=5)
        self.lora.add_channel(2, frequency=self.frequency, dr_min=0, dr_max=5)

        # remove all the non-default channels
        for i in range(3, 16):
            self.lora.remove_channel(i)

        # authenticate with abp or ota
        if self.activation == LoRa.OTAA:
            self._authenticate_otaa(self.auth)
        else:
            self._authenticate_abp(self.auth)

        # create socket to server
        self._create_socket()

    def _authenticate_otaa(self, auth_params):

        # create an OTAA authentication params
        self.dev_eui = binascii.unhexlify(auth_params[0])
        self.app_eui = binascii.unhexlify(auth_params[1])
        self.app_key = binascii.unhexlify(auth_params[2])

        self.lora.join(activation=LoRa.OTAA,
                       auth=(self.dev_eui, self.app_eui, self.app_key),
                       timeout=0,
                       dr=self.dr)

        while not self.lora.has_joined():
            time.sleep(2.5)
            print('Not joined yet...')

    def has_joined(self):
        return self.lora.has_joined()

    def _authenticate_abp(self, auth_params):
        # create an ABP authentication params
        self.dev_addr = struct.unpack(">l",
                                      binascii.unhexlify(auth_params[0]))[0]
        self.nwk_swkey = binascii.unhexlify(auth_params[1])
        self.app_swkey = binascii.unhexlify(auth_params[2])

        self.lora.join(activation=LoRa.ABP,
                       auth=(self.dev_addr, self.nwk_swkey, self.app_swkey))

    def _create_socket(self):

        # create a LoRa socket
        self.sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

        # set the LoRaWAN data rate
        self.sock.setsockopt(socket.SOL_LORA, socket.SO_DR, self.dr)

        # make the socket non blocking
        self.sock.setblocking(False)

        time.sleep(2)

    def send(self, packet):
        with self.s_lock:
            self.sock.send(packet)

    def receive(self, bufsize):
        with self.q_lock:
            if len(self._msg_queue) > 0:
                return self._msg_queue.pop(0)
        return ''

    def get_dev_eui(self):
        return binascii.hexlify(self.lora.mac()).decode('ascii')

    def change_to_multicast_mode(self, mcAuth):
        print('Start listening for firmware updates ...........')

        if self.device_class != LoRa.CLASS_C:
            self.lora = LoRa(mode=LoRa.LORAWAN,
                             region=self.region,
                             device_class=LoRa.CLASS_C)
            self.connect()

        mcAddr = struct.unpack(">l", binascii.unhexlify(mcAuth[0]))[0]
        mcNwkKey = binascii.unhexlify(mcAuth[1])
        mcAppKey = binascii.unhexlify(mcAuth[2])

        self.lora.join_multicast_group(mcAddr, mcNwkKey, mcAppKey)
Exemple #17
0
import struct
import ujson

# Colors
off = 0x000000
red = 0xff0000
green = 0x00ff00
blue = 0x0000ff
yellow = 0xffff00

# Initialize LoRa in LORAWAN mode.
lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915, public=True)
# Set up KotahiNet channels
# leave channels 8-15 and 65
for index in range(0, 8):
    lora.remove_channel(index)  # remove 0-7
for index in range(16, 65):
    lora.remove_channel(index)  # remove 16-64
for index in range(66, 72):
    lora.remove_channel(index)  # remove 66-71
# Turn off hearbeat LED
pycom.heartbeat(False)

# create an ABP authentication params
dev_addr = struct.unpack(">l",
                         binascii.unhexlify('26 00 2C 58'.replace(' ', '')))[0]
nwk_swkey = binascii.unhexlify(
    '37 70 5E 6D F5 04 8F 2F 42 87 E5 3F 09 78 A9 11'.replace(' ', ''))
app_swkey = binascii.unhexlify(
    'A1 13 D6 0F 1A 9C 08 9F E6 94 D6 83 76 9F 8B DE'.replace(' ', ''))
Exemple #18
0
class LoRaMQ:
    def __init__(self, config):
        self.lora = LoRa(mode=LoRa.LORAWAN)
        # set the 3 default channels to the same frequency (must be before sending the OTAA join request)
        self.lora.add_channel(0,
                              frequency=config.LORA_FREQUENCY,
                              dr_min=0,
                              dr_max=5)
        self.lora.add_channel(1,
                              frequency=config.LORA_FREQUENCY,
                              dr_min=0,
                              dr_max=5)
        self.lora.add_channel(2,
                              frequency=config.LORA_FREQUENCY,
                              dr_min=0,
                              dr_max=5)
        # join a network using OTAA
        self.lora.join(activation=LoRa.OTAA,
                       auth=(binascii.unhexlify(config.DEV_EUI),
                             binascii.unhexlify(config.APP_EUI),
                             binascii.unhexlify(config.APP_KEY)),
                       timeout=0,
                       dr=config.LORA_NODE_DR)
        # wait until the module has joined the network
        while not self.lora.has_joined():
            time.sleep(2.5)
            print('Not joined yet...')
        # remove all the non-default channels
        for i in range(3, 16):
            self.lora.remove_channel(i)
        # create a LoRa socket
        self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        # set the LoRaWAN data rate
        self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.LORA_NODE_DR)
        # make the socket non-blocking
        self.s.setblocking(False)
        time.sleep(5.0)
        self.send_mutex = _thread.allocate_lock()
        self.send_queue = []
        self.recv_mutex = _thread.allocate_lock()
        self.recv_queue = []
        self.callback = None
        self.lora.callback(LoRa.RX_PACKET_EVENT, self._recv)

    def _recv(self, data):
        rx, port = s.recvfrom(256)
        self.recv_mutex.acquire()
        self.recv_queue.append((port, rx))
        self.recv_mutex.release()
        if self.callback:
            _thread.start_new_thread(self.callback, tuple())

    def send(self, data):
        self.send_mutex.acquire()
        self.send_queue.append(data)
        self.send_mutex.release()

    def receive(self):
        self.recv_mutex.acquire()
        if not len(self.recv_queue):
            return False
        data = self.recv_queue.pop(0)
        self.recv_mutex.release()
        return data

    def rq_length(self):
        self.recv_mutex.acquire()
        size = len(self.recv_queue)
        self.recv_mutex.release()
        return size

    def attach_callback(self, callback):
        self.callback = callback

    def _loop(self):
        while True:
            #acquire a lock on the send message queue
            self.send_mutex.acquire()
            #get the message from the front of the queue
            if len(self.send_queue):
                data = self.send_queue.pop(0)
            else:
                data = None
            self.send_mutex.release()
            if data:
                #acquire a lock on the channel
                self.recv_mutex.acquire()
                #send the data
                self.s.send(data)
                #release the channel lock
                self.recv_mutex.release()
                #LoRa protocol only allows sending and recieving every 5 seconds
                #so to avoid protocol errors from the transciever sleep the thread
                #for 5 seconds
            time.sleep(5)

    def start(self):
        _thread.start_new_thread(self._loop, tuple())
import binascii
import struct
import time
import config

# initialize LoRa in LORAWAN mode.
lora = LoRa(mode=LoRa.LORAWAN)

# create an OTA authentication params
dev_eui = binascii.unhexlify('AA BB CC DD EE FF 77 78'.replace(' ',''))
app_eui = binascii.unhexlify('70 B3 D5 7E F0 00 3B FD'.replace(' ',''))
app_key = binascii.unhexlify('36 AB 76 25 FE 77 0B 68 81 68 3B 49 53 00 FF D6'.replace(' ',''))

# remove all the channels
for channel in range(0, 72):
    lora.remove_channel(channel)

# set all channels to the same frequency (must be before sending the OTAA join request)
for channel in range(0, 72):
    lora.add_channel(channel, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=3)

# join a network using OTAA
lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=config.LORA_NODE_DR)

# wait until the module has joined the network
join_wait = 0
while True: 
    time.sleep(2.5)
    if not lora.has_joined():
        print('Not joined yet...')
        join_wait += 1
Exemple #20
0
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, ssid, password, 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.wlan = 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.
        """

        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()

        # 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,
            region=LoRa.AU915,
            frequency=self.frequency,
            bandwidth=self.bw,
            sf=self.sf,
            preamble=8,
            coding_rate=LoRa.CODING_4_5,
            tx_iq=True
        )

        # remove all the channels
        for channel in range(0, 72):
            self.lora.remove_channel(channel)

        self.lora.add_channel(8, frequency=self.frequency, dr_min=0, dr_max=3)

        # 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 WLAN
        self.wlan.disconnect()
        self.wlan.deinit()

    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 _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 BLEAndLoRaFun():
    #First, initialize as one LoRa node device
    # initialize LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    # Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915)

    # create an ABP authentication params
    dev_addr = struct.unpack(">l", binascii.unhexlify('260214B3'))[0]
    nwk_swkey = binascii.unhexlify('2C2139EEC68B264BF1F0EDCE183CE33F')
    app_swkey = binascii.unhexlify('C25FB9A263307BF86B659298D86D4A45')

    # remove all the channels
    for channel in range(0, 72):
        lora.remove_channel(channel)

    # set all channels to the same frequency (must be before sending the OTAA join request)
    for channel in range(0, 72):
        lora.add_channel(channel,
                         frequency=config.LORA_FREQUENCY,
                         dr_min=0,
                         dr_max=3)

    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)  # last parameter is 3

    # make the socket non-blocking
    s.setblocking(False)

    #Second, act as BLE client
    bt = Bluetooth()
    bt.start_scan(-1)
    counter = 0
    while True:
        #Gets an named tuple with the advertisement data received during the scanning.
        #The structure is (mac, addr_type, adv_type, rssi, data)
        adv = bt.get_adv()
        #servermac = ''#save the serer mac
        #use resolve_adv_data to resolve the 31 bytes of the advertisement message
        #Here is problem: when disconnect from server, then adv will always be null...
        if adv and bt.resolve_adv_data(
                adv.data, Bluetooth.ADV_NAME_CMPL) == 'LoPyServer1':
            try:
                #Opens a BLE connection with the device specified by the mac_addr argument
                #This function blocks until the connection succeeds or fails.
                #print(adv.mac)
                #global servermac#change servermac to global
                #servermac = adv.mac
                counter += 1
                conn = bt.connect(adv.mac)
                #print('connected?',conn.isconnected())
                services = conn.services()
                #print('This is service',services)
                #print(services)
                '''
                for service in services:
                    print('This is service uuid',service.uuid())
                    time.sleep(0.050)
                    if type(service.uuid()) == bytes:
                        print('if bytes:Reading chars from service = {}'.format(service.uuid()))
                    else:
                        print('if not bytes:Reading chars from service = %x' % service.uuid())
                    chars = service.characteristics()
                    for char in chars:
                        if (char.properties() & Bluetooth.PROP_READ):
                            print('char {} value = {}'.format(char.uuid(), char.read()))
                '''
                #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server
                for service in services:
                    time.sleep(0.050)
                    if type(service.uuid()) == bytes:
                        chars = service.characteristics()
                        for char in chars:
                            #check if the character properties is PROP_READ
                            if (char.properties() & Bluetooth.PROP_READ):
                                print('char {} value = {}'.format(
                                    char.uuid(), char.read()) + str(counter))
                                #Use LoRa to send the data out
                                s.send(char.read())
                                time.sleep(4)
                #Yunwei
                conn.disconnect()
                print('connected?', conn.isconnected())
                #break
                time.sleep(6)
                bt.start_scan(-1)
            except:
                print("Error while connecting or reading from the BLE device")
                #break
                time.sleep(1)
                bt.start_scan(-1)
                print('Scan again')
Exemple #22
0
# set the 3 default channels to the same frequency (must be before sending the OTAA join request)
lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5)

# join a network using OTAA
lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0)

# wait until the module has joined the network
while not lora.has_joined():
    time.sleep(2.5)
    print('Not joined yet...')

# remove all the non-default channels
for i in range(3, 16):
    lora.remove_channel(i)

# create a LoRa socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate
s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

# make the socket blocking
s.setblocking(False)

time.sleep(5.0)

for i in range (200):
    s.send(b'PKT #' + bytes([i]))
    print('STA node sending packet ...')
Exemple #23
0
# initialize LoRa in LORAWAN mode.
# Please pick the region that matches where you are using the device:
# Asia = LoRa.AS923
# Australia = LoRa.AU915
# Europe = LoRa.EU868
# United States = LoRa.US915
lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915)

# create an ABP authentication params
dev_addr = struct.unpack(">l", binascii.unhexlify('2601147D'))[0]
nwk_swkey = binascii.unhexlify('3C74F4F40CAEA021303BC24284FCF3AF')
app_swkey = binascii.unhexlify('0FFA7072CC6FF69A102A0F39BEB0880F')

# remove all the channels
for channel in range(0, 72):
    lora.remove_channel(channel)

# set all channels to the same frequency (must be before sending the OTAA join request)
for channel in range(0, 72):
    lora.add_channel(channel,
                     frequency=config.LORA_FREQUENCY,
                     dr_min=0,
                     dr_max=3)

# join a network using ABP (Activation By Personalization)
lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

# create a LoRa socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate
Exemple #24
0
lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0)

# wait until the module has joined the network
while not lora.has_joined():
    pycom.rgbled(0x140000)
    time.sleep(2.5)
    pycom.rgbled(0x000000)
    time.sleep(1.0)
    print('Not yet joined...')

print('OTAA joined')
pycom.rgbled(0x001400)

# to have only one channel:
for index in range(0, 16):
    lora.remove_channel(index)

lora.add_channel(index=0, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(index=1, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(index=2, frequency=868100000, dr_min=0, dr_max=5)

# create a LoRa socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate:
# DR | SF
# 5  | 7
# 4  | 8
# 3  | 9
# 2  | 10
# 1  | 11
Exemple #25
0
import config

# Initialize LoRa in LORAWAN mode.
lora = LoRa(mode=LoRa.LORAWAN)

# create an ABP authentication params
dev_addr = struct.unpack(">l", binascii.unhexlify(config.DEV_ADDR.replace(' ','')))[0]
nwk_swkey = binascii.unhexlify(config.NWK_SWKEY.replace(' ',''))
app_swkey = binascii.unhexlify(config.APP_SWKEY.replace(' ',''))

# join a network using ABP (Activation By Personalization)
lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))

# remove all the non-default channels
for i in range(3, 16):
    lora.remove_channel(i)

# set the 3 default channels to the same frequency
lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5)
lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5)

# create a LoRa socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)

# set the LoRaWAN data rate
s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)

# make the socket blocking
s.setblocking(False)
Exemple #26
0
class LoRaWANNode:

    def __init__(self, app_eui, app_key, frequency=868100000, dr=5):
        '''setup LoRaWAN for the European 868 MHz region with OTAA'''
        self.dr = dr
        self.frequency = frequency
        self.app_eui = ubinascii.unhexlify(app_eui)
        self.app_key = ubinascii.unhexlify(app_key)
        self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
        self.socket = None
        self.setup()

    @property
    def has_joined(self):
        return self.lora.has_joined()

    def default_channels(self):
        '''
        Remove all non-default channels and set the 3 default channels to the
        same frequency (must be before ending the OTAA join request)
        '''
        for i in range(3, 16):
            self.lora.remove_channel(i)

        self.lora.add_channel(0, frequency=self.frequency,
                              dr_min=0, dr_max=self.dr)
        self.lora.add_channel(1, frequency=self.frequency,
                              dr_min=0, dr_max=self.dr)
        self.lora.add_channel(2, frequency=self.frequency,
                              dr_min=0, dr_max=self.dr)

    def setup(self):
        '''Try to restore from nvram or join the network with otaa'''
        self.default_channels()
        self.lora.nvram_restore()
        if not self.has_joined:
            self.join()
        else:
            self.open_socket()

    def join(self, timeout=10):
        try:
            timeout = timeout * 1000
            self.lora.join(activation=LoRa.OTAA,
                           auth=(self.app_eui, self.app_key),
                           timeout=timeout, dr=self.dr)
            if self.has_joined:
                self.lora.nvram_save()
                self.open_socket()
        except TimeoutError:
            pass

    def open_socket(self, timeout=6):
        self.socket = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
        self.socket.setsockopt(usocket.SOL_LORA, usocket.SO_DR,
                               self.dr)
        self.socket.settimeout(timeout)

    def reset(self):
        self.socket.close()
        self.lora.nvram_erase()
        self.join()

    def send(self, data):
        '''Send out data as bytes'''
        if self.has_joined:
            if isinstance(data, (float, str, int)):
                data = bytes([data])
            self.socket.send(data)
            utime.sleep(2)
            self.lora.nvram_save()