OTAA Node to Nano Gateway AU915



  • Hi,
    I just recently got a couple of Lopy 4's to act as nodes, but while I wait for my gateway, I was trying to set the pair up in a LoraWan nano gateway and OTAA node test.

    I’m using the GitHub code for a base https://github.com/pycom/pycom-libraries/tree/master/examples/lorawan-nano-gateway and trying to modify it for use in Australia AU915.

    I think I got the gateway working but it never shows connected in the TNN console.

    config.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway configuration options """
    
    import machine
    import ubinascii
    
    WIFI_MAC = ubinascii.hexlify(machine.unique_id()).upper()
    # Set  the Gateway ID to be the first 3 bytes of MAC address + 'FFFE' + last 3 bytes of MAC address
    GATEWAY_ID = WIFI_MAC[:6] + "FFFE" + WIFI_MAC[6:12]
    
    SERVER = 'router.thethings.meshed.com.au'
    PORT = 1700
    
    NTP = "pool.ntp.org"
    NTP_PERIOD_S = 3600
    
    WIFI_SSID = 'ssid'
    WIFI_PASS = 'password'
    WIFI_ADDRESS = '192.168.1.50'
    WIFI_MASK = '255.255.255.0'
    WIFI_GATEWAY = '192.168.1.1'
    
    # for EU868
    # LORA_FREQUENCY = 868100000
    # LORA_GW_DR = "SF7BW125" # DR_5
    # LORA_NODE_DR = 5
    
    # for US915
    # LORA_FREQUENCY = 903900000
    # LORA_GW_DR = "SF7BW125" # DR_3
    # LORA_NODE_DR = 3
    
    # for AU915
    LORA_FREQUENCY = 916800000
    LORA_GW_DR = "SF7BW125"
    LORA_NODE_DR = 4
    

    nanogateway.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway. Can be used for both EU868 and US915. """
    
    import errno
    import machine
    import ubinascii
    import ujson
    import uos
    import usocket
    import utime
    import _thread
    from micropython import const
    from network import LoRa
    from network import WLAN
    from machine import Timer
    
    
    PROTOCOL_VERSION = const(2)
    
    PUSH_DATA = const(0)
    PUSH_ACK = const(1)
    PULL_DATA = const(2)
    PULL_ACK = const(4)
    PULL_RESP = const(3)
    
    TX_ERR_NONE = 'NONE'
    TX_ERR_TOO_LATE = 'TOO_LATE'
    TX_ERR_TOO_EARLY = 'TOO_EARLY'
    TX_ERR_COLLISION_PACKET = 'COLLISION_PACKET'
    TX_ERR_COLLISION_BEACON = 'COLLISION_BEACON'
    TX_ERR_TX_FREQ = 'TX_FREQ'
    TX_ERR_TX_POWER = 'TX_POWER'
    TX_ERR_GPS_UNLOCKED = 'GPS_UNLOCKED'
    
    UDP_THREAD_CYCLE_MS = const(20)
    
    STAT_PK = {
        'stat': {
            'time': '',
            'lati': 0,
            'long': 0,
            'alti': 0,
            'rxnb': 0,
            'rxok': 0,
            'rxfw': 0,
            'ackr': 100.0,
            'dwnb': 0,
            'txnb': 0
        }
    }
    
    RX_PK = {
        'rxpk': [{
            'time': '',
            'tmst': 0,
            'chan': 0,
            'rfch': 0,
            'freq': 0,
            'stat': 1,
            'modu': 'LORA',
            'datr': '',
            'codr': '4/5',
            'rssi': 0,
            'lsnr': 0,
            'size': 0,
            'data': ''
        }]
    }
    
    TX_ACK_PK = {
        'txpk_ack': {
            'error': ''
        }
    }
    
    
    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, address, mask, gateway, 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.address = address
            self.mask = mask
            self.gateway = gateway
    
            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.wlan.ifconfig(config=(self.address, self.mask, self.gateway, self.gateway))
            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.LORAWAN,
                frequency=self.frequency,
                bandwidth=self.bw,
                sf=self.sf,
                preamble=8,
                coding_rate=LoRa.CODING_4_5,
                tx_iq=True
            )
    
            # create a raw LoRa socket
            self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
            self.lora_sock.setblocking(False)
            self.lora_tx_done = False
    
            self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb)
            self._log('LoRaWAN nano gateway online')
    
        def stop(self):
            """
            Stops the LoRaWAN nano gateway.
            """
    
            self._log('Stopping...')
    
            # send the LoRa radio to sleep
            self.lora.callback(trigger=None, handler=None)
            self.lora.power_mode(LoRa.SLEEP)
    
            # stop the NTP sync
            self.rtc.ntp_sync(None)
    
            # cancel all the alarms
            self.stat_alarm.cancel()
            self.pull_alarm.cancel()
    
            # signal the UDP thread to stop
            self.udp_stop = True
            while self.udp_stop:
                utime.sleep_ms(50)
    
            # disable 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)
                packet = self.frequency_rounding_fix(packet, self.frequency)
                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 frequency_rounding_fix(self, packet, frequency):
            freq = str(frequency)[0:3] + '.' + str(frequency)[3]
    
            start = packet.find("freq\":")
            end = packet.find(",", start)
    
            packet = packet[:start + 7] + freq + packet[end:]
    
            return packet
    
        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 _send_down_link_class_c(self, data, datarate, frequency):
            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,
                device_class=LoRa.CLASS_C
                )
    
            self.lora_sock.send(data)
            self._log(
                'Sent downlink packet scheduled on {:.3f}, at {:.3f} Mhz using {}: {}',
                utime.time(),
                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:])
                        if "tmst" in data:
                            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)
                        else:
                            self.uplink_alarm = Timer.Alarm(
                                handler=lambda x: self._send_down_link_class_c(
                                    ubinascii.a2b_base64(tx_pk["txpk"]["data"]),
                                    tx_pk["txpk"]["datr"],
                                    int(tx_pk["txpk"]["freq"] * 1000) * 1000
                                ),
                                us=50
                            )
                        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)
                ))
    

    main.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway example usage """
    
    import config
    from nanogateway import NanoGateway
    
    if __name__ == '__main__':
        nanogw = NanoGateway(
            id=config.GATEWAY_ID,
            frequency=config.LORA_FREQUENCY,
            datarate=config.LORA_GW_DR,
            ssid=config.WIFI_SSID,
            password=config.WIFI_PASS,
            address=config.WIFI_ADDRESS,
            mask=config.WIFI_MASK,
            gateway=config.WIFI_GATEWAY,
            server=config.SERVER,
            port=config.PORT,
            ntp_server=config.NTP,
            ntp_period=config.NTP_PERIOD_S
            )
    
        nanogw.start()
        nanogw._log('You may now press ENTER to enter the REPL')
        input()
    

    Start up log

    rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1688
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    WMAC: 3C71BF8750F0
    Firmware: 1.18.2.r6
    Pybytes: 0.9.12
    Pybytes configuration read from /flash/pybytes_config.json
    Initialized watchdog for WiFi and LTE connection with timeout 660000 ms
    WiFi connection established
    WARNING: consider enabling certificate validation
    Using MQTT over TLS
    Connected to MQTT mqtt.pybytes.pycom.io
    Pybytes connected successfully (using the built-in pybytes library)
    Now starting user code in main.py
    [    31.212] Starting LoRaWAN nano gateway with id: b'3C71BFFFFE8750F0'
    [    31.238] WiFi connected to: ssid
    [    31.245] Syncing time with pool.ntp.org ...
    [    35.502] RTC NTP sync complete
    [    42.098] Opening UDP socket to router.thethings.meshed.com.au (224.94.149.63) port 1700...
    [    42.116] Setting up the LoRa radio at 916.7999 Mhz using SF7BW125
    [    42.160] LoRaWAN nano gateway online
    [    42.167] You may now press ENTER to enter the REPL
    

    As for the OTAA client I can not get it to connect
    config.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy Node configuration options """
    
    import machine
    import ubinascii
    
    WIFI_MAC = ubinascii.hexlify(machine.unique_id()).upper()
    # Set  the Node ID to be the first 3 bytes of MAC address + 'FFFE' + last 3 bytes of MAC address
    NODE_ID = WIFI_MAC[:6] + "FFFE" + WIFI_MAC[6:12]
    
    # for EU868
    # LORA_FREQUENCY = 868100000
    # LORA_GW_DR = "SF7BW125" # DR_5
    # LORA_NODE_DR = 5
    
    # for US915
    # LORA_FREQUENCY = 903900000
    # LORA_GW_DR = "SF7BW125" # DR_3
    # LORA_NODE_DR = 3
    
    # for AU915
    LORA_FREQUENCY = 916800000
    LORA_GW_DR = "SF7BW125"
    LORA_NODE_DR = 4
    

    main.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ OTAA Node example compatible with the LoPy Nano Gateway """
    
    from network import LoRa
    import socket
    import binascii
    import struct
    import time
    import config
    
    # 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.AU915)
    
    # create an OTA authentication params
    dev_eui = config.NODE_ID
    app_eui = binascii.unhexlify('3C71BFFFFE8750F0')
    app_key = binascii.unhexlify('36AB7625FE770B6881683B495300FFD6')
    
    for channel in range(0, 16):
        lora.remove_channel(channel)
    # 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=config.LORA_NODE_DR)
    lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=config.LORA_NODE_DR)
    lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=config.LORA_NODE_DR)
    
    # 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...')
    
    # 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)
    
    time.sleep(5.0)
    
    for i in range (200):
        pkt = b'PKT #' + bytes([i])
        print('Sending:', pkt)
        s.send(pkt)
        time.sleep(4)
        rx, port = s.recvfrom(256)
        if rx:
            print('Received: {}, on port: {}'.format(rx, port))
        time.sleep(6)
    
    

    Startup Log

    rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1688
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    WMAC: 807D3A934E9C
    Firmware: 1.18.2.r6
    Pybytes: 0.9.12
    Pybytes configuration read from /flash/pybytes_config.json
    Initialized watchdog for WiFi and LTE connection with timeout 660000 ms
    WiFi connection established
    WARNING: consider enabling certificate validation
    Using MQTT over TLS
    Connected to MQTT mqtt.pybytes.pycom.io
    Pybytes connected successfully (using the built-in pybytes library)
    Now starting user code in main.py
    Not joined yet...
    Not joined yet...
    Not joined yet...
    Not joined yet...
    Not joined yet...
    Not joined yet...
    Not joined yet...
    Not joined yet...
    

    Most likely I’ve don’t something wrong been new to Lora and the Lopy’s

    Any help would be appreciated, thanks.



  • Thanks @jcaron ,
    Got it working using ABP and a few change to the TNN config, but would still like to get it working with OTAA this was all done with the Pybytes firmware, I have now removed it on your suggestion and I'll see how it goes.

    Current configuration
    Gateway config.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway configuration options """
    
    import machine
    import ubinascii
    
    WIFI_MAC = ubinascii.hexlify(machine.unique_id()).upper()
    # Set  the Gateway ID to be the first 3 bytes of MAC address + 'FFFE' + last 3 bytes of MAC address
    GATEWAY_ID = WIFI_MAC[:6] + "FFFE" + WIFI_MAC[6:12]
    
    SERVER = 'router.au.thethings.network'
    PORT = 1700
    
    NTP = "au.pool.ntp.org"
    NTP_PERIOD_S = 3600
    
    WIFI_SSID = 'ssid'
    WIFI_PASS = 'password'
    WIFI_ADDRESS = '192.168.1.50'
    WIFI_MASK = '255.255.255.0'
    WIFI_GATEWAY = '192.168.1.1'
    
    # for EU868
    # LORA_FREQUENCY = 868100000
    # LORA_GW_DR = "SF7BW125" # DR_5
    # LORA_NODE_DR = 5
    
    # for US915
    # LORA_FREQUENCY = 903900000
    # LORA_GW_DR = "SF7BW125" # DR_3
    # LORA_NODE_DR = 3
    
    # for AU915
    LORA_FREQUENCY = 916800000
    LORA_GW_DR = "SF7BW125"
    LORA_NODE_DR = 5
    

    nanogateway.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway. Can be used for both EU868 and US915. """
    
    import errno
    import machine
    import ubinascii
    import ujson
    import uos
    import usocket
    import utime
    import _thread
    from micropython import const
    from network import LoRa
    from network import WLAN
    from machine import Timer
    
    
    PROTOCOL_VERSION = const(2)
    
    PUSH_DATA = const(0)
    PUSH_ACK = const(1)
    PULL_DATA = const(2)
    PULL_ACK = const(4)
    PULL_RESP = const(3)
    
    TX_ERR_NONE = 'NONE'
    TX_ERR_TOO_LATE = 'TOO_LATE'
    TX_ERR_TOO_EARLY = 'TOO_EARLY'
    TX_ERR_COLLISION_PACKET = 'COLLISION_PACKET'
    TX_ERR_COLLISION_BEACON = 'COLLISION_BEACON'
    TX_ERR_TX_FREQ = 'TX_FREQ'
    TX_ERR_TX_POWER = 'TX_POWER'
    TX_ERR_GPS_UNLOCKED = 'GPS_UNLOCKED'
    
    UDP_THREAD_CYCLE_MS = const(20)
    
    STAT_PK = {
        'stat': {
            'time': '',
            'lati': 0,
            'long': 0,
            'alti': 0,
            'rxnb': 0,
            'rxok': 0,
            'rxfw': 0,
            'ackr': 100.0,
            'dwnb': 0,
            'txnb': 0
        }
    }
    
    RX_PK = {
        'rxpk': [{
            'time': '',
            'tmst': 0,
            'chan': 0,
            'rfch': 0,
            'freq': 0,
            'stat': 1,
            'modu': 'LORA',
            'datr': '',
            'codr': '4/5',
            'rssi': 0,
            'lsnr': 0,
            'size': 0,
            'data': ''
        }]
    }
    
    TX_ACK_PK = {
        'txpk_ack': {
            'error': ''
        }
    }
    
    
    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, address, mask, gateway, server, port, ntp_server='au.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.address = address
            self.mask = mask
            self.gateway = gateway
    
            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.wlan.ifconfig(config=(self.address, self.mask, self.gateway, self.gateway))
            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,
                frequency=self.frequency,
                bandwidth=self.bw,
                sf=self.sf,
                preamble=8,
                coding_rate=LoRa.CODING_4_5,
                tx_iq=True
            )
    
            # create a raw LoRa socket
            self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
            self.lora_sock.setblocking(False)
            self.lora_tx_done = False
    
            self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb)
            self._log('LoRaWAN nano gateway online')
    
        def stop(self):
            """
            Stops the LoRaWAN nano gateway.
            """
    
            self._log('Stopping...')
    
            # send the LoRa radio to sleep
            self.lora.callback(trigger=None, handler=None)
            self.lora.power_mode(LoRa.SLEEP)
    
            # stop the NTP sync
            self.rtc.ntp_sync(None)
    
            # cancel all the alarms
            self.stat_alarm.cancel()
            self.pull_alarm.cancel()
    
            # signal the UDP thread to stop
            self.udp_stop = True
            while self.udp_stop:
                utime.sleep_ms(50)
    
            # disable 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)
                packet = self.frequency_rounding_fix(packet, self.frequency)
                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 frequency_rounding_fix(self, packet, frequency):
            freq = str(frequency)[0:3] + '.' + str(frequency)[3]
    
            start = packet.find("freq\":")
            end = packet.find(",", start)
    
            packet = packet[:start + 7] + freq + packet[end:]
    
            return packet
    
        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 _send_down_link_class_c(self, data, datarate, frequency):
            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,
                device_class=LoRa.CLASS_C
                )
    
            self.lora_sock.send(data)
            self._log(
                'Sent downlink packet scheduled on {:.3f}, at {:.3f} Mhz using {}: {}',
                utime.time(),
                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:])
                        if "tmst" in data:
                            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)
                        else:
                            self.uplink_alarm = Timer.Alarm(
                                handler=lambda x: self._send_down_link_class_c(
                                    ubinascii.a2b_base64(tx_pk["txpk"]["data"]),
                                    tx_pk["txpk"]["datr"],
                                    int(tx_pk["txpk"]["freq"] * 1000) * 1000
                                ),
                                us=50
                            )
                        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)
                ))
    

    main.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy LoRaWAN Nano Gateway example usage """
    
    import config
    from nanogateway import NanoGateway
    
    if __name__ == '__main__':
        nanogw = NanoGateway(
            id=config.GATEWAY_ID,
            frequency=config.LORA_FREQUENCY,
            datarate=config.LORA_GW_DR,
            ssid=config.WIFI_SSID,
            password=config.WIFI_PASS,
            address=config.WIFI_ADDRESS,
            mask=config.WIFI_MASK,
            gateway=config.WIFI_GATEWAY,
            server=config.SERVER,
            port=config.PORT,
            ntp_server=config.NTP,
            ntp_period=config.NTP_PERIOD_S
            )
    
        nanogw.start()
        nanogw._log('You may now press ENTER to enter the REPL')
        input()
    
    Connecting to COM11...
    [     2.595] Starting LoRaWAN nano gateway with id: b'3C71BFFFFE8750F0'
    [     6.118] WiFi connected to: ssid
    [     6.123] Syncing time with au.pool.ntp.org ...
    [     6.179] RTC NTP sync complete
    [     6.189] Opening UDP socket to router.au.thethings.network (52.62.83.250) port 1700...
    [     6.204] Setting up the LoRa radio at 916.7999 Mhz using SF7BW125
    [     6.213] LoRaWAN nano gateway online
    [     6.218] You may now press ENTER to enter the REPL
    
    Pycom MicroPython 1.18.2.r7 [v1.8.6-849-df9f237] on 2019-05-14; LoPy4 with ESP32
    Type "help()" for more information.
    >>> [     6.249] Push ack
    [    21.068] Received packet: {"rxpk": [{"data": "QLIXAiYAAAACQ9+WpQPqPkmVOg==", "time": "2019-05-31T19:49:52.173381Z", "chan": 0, "tmst": 21050429, "stat": 1, "modu": "LORA", "lsnr": 6.0, "rssi": 0, "rfch": 0, "codr": "4/5", "freq": 916.8, "datr": "SF7BW125", "size": 19}]}
    [    21.129] Push ack
    [    31.066] Received packet: {"rxpk": [{"data": "QLIXAiYAAQAC1T4VWxMKlrC8Aw==", "time": "2019-05-31T19:50:02.172292Z", "chan": 0, "tmst": 31049439, "stat": 1, "modu": "LORA", "lsnr": 6.0, "rssi": -1, "rfch": 0, "codr": "4/5", "freq": 916.8, "datr": "SF7BW125", "size": 19}]}
    [    31.208] Push ack
    [    31.252] Pull ack
    

    ABP Node config.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ LoPy Node configuration options """
    
    import machine
    import binascii
    import struct
    
    WIFI_MAC = binascii.hexlify(machine.unique_id()).upper()
    # Set  the Node ID to be the first 3 bytes of MAC address + 'FFFE' + last 3 bytes of MAC address
    NODE_ID = WIFI_MAC[:6] + "FFFE" + WIFI_MAC[6:12]
    
    # create an OTA authentication params
    DEV_EUI = binascii.unhexlify('0x')
    APP_EUI = binascii.unhexlify('0x')
    APP_KEY = binascii.unhexlify('0x')
    DEV_ADDR = struct.unpack(">l", binascii.unhexlify('0x'))[0]
    NWK_SWKEY = binascii.unhexlify('0x')
    APP_SWKEY = binascii.unhexlify('0x')
    
    # for EU868
    # LORA_FREQUENCY = 868100000
    # LORA_GW_DR = "SF7BW125" # DR_5
    # LORA_NODE_DR = 5
    
    # for US915
    # LORA_FREQUENCY = 903900000
    # LORA_GW_DR = "SF7BW125" # DR_3
    # LORA_NODE_DR = 3
    
    # for AU915
    LORA_FREQUENCY = 916800000
    LORA_GATEWAY_DR = "SF7BW125"
    LORA_NODE_DR = 5
    

    main.py

    #!/usr/bin/env python
    #
    # Copyright (c) 2019, Pycom Limited.
    #
    # This software is licensed under the GNU GPL version 3 or any
    # later version, with permitted additional terms. For more information
    # see the Pycom Licence v1.0 document supplied with this file, or
    # available at https://www.pycom.io/opensource/licensing
    #
    
    """ ABP Node example compatible with the LoPy Nano Gateway """
    
    from network import LoRa
    import socket
    import binascii
    import struct
    import time
    import config
    
    # 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.AU915)
    
    # 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=config.LORA_NODE_DR)
    
    # set the 3 default channels to the same frequency
    lora.add_channel(0, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=config.LORA_NODE_DR)
    lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=config.LORA_NODE_DR)
    lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=config.LORA_NODE_DR)
    
    # join a network using ABP
    lora.join(activation=LoRa.ABP, auth=(config.DEV_ADDR, config.NWK_SWKEY, config.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 non-blocking
    s.setblocking(False)
    
    for i in range (200):
        pkt = b'PKT #' + bytes([i])
        print('Sending:', pkt)
        s.send(pkt)
        time.sleep(4)
        rx, port = s.recvfrom(256)
        if rx:
            print('Received: {}, on port: {}'.format(rx, port))
        time.sleep(6)
    
    Connecting to COM11...
    Sending: b'PKT #\x00'
    Sending: b'PKT #\x01'
    Sending: b'PKT #\x02'
    


  • @Yendor I think you have the Pybytes firmware loaded, you probably want the version without Pybytes in this case.


Log in to reply
 

Pycom on Twitter