Hi guys,
i’m newbie in LoRaWAN network configuration.
I need to transmit data from a lopy4 board to a backend through the use of a second lopy4 board acting as a nanogateway.
The chirpstack LoRaWAN network stack has been implemented on a dedicated server.
The nanogateway is configured and visible on the chirpstack server grapgical interface, i created a profile for the device associated to the second board, but it transmits continuous join requests without ever being accepted. As authentication method I tried both ABP and OTAA, I also tried to reverse the order of credentials (MSB to LSB) but on the board I always read “Not yet joined” and on the nanogatewy I read the following log :
“[ 11644.731] Received packet: {“rxpk”: [{“data”: “AAAAAAAAAA/iKYkNnVs3DqV+8M2mA=”, “time”: “2022-05-03T12:38:26. 263245Z”, “chan”: 0, “tmst”: 196355297, “stat”: 1, “modu”: “LORA”, “lsnr”: 6.0, “rssi”: -28, “rfch”: 0, “codr”: “4/5”, “freq”: 868.1, “datr”: “SF7BW125”, “size”: 23}]}”
On the second board I’m using the following codes:
config.py
#configuration
from network import LoRa
#application-level device identifier
DEVICE_ID = '4'
# authentication credentials (specific for each device, generated by LoRa backend)
# LORA_CRED_ABP = ('01e1a5f3', 'f71c36d3499d4962f8966b4d7abe271f', '7f9d74a6966264fbf6e7d13ec0e70509')
#LORA_CRED_ABP = ('00750889', 'f56e40b52f0162a9b9a68fc131a07a34', '5d015e33eaf54140ca1b69f238da1fdd')
# initialized (hard-coded) sampling/sending interval (will be modified and adapted by the synchronization mechanism)
INTERVAL_PRE = 120000 # (milliseconds)
# led activation (for testing only)
LED_ON = True
### It is suggested to not modify the following configurations
# authentication method
# ABP (Authentication By Personalization) suggested.
# ABP = False enables OTA (Over The Air authentication)
ABP = False
# For OTA specific OTA-credentials must be used
LORA_CRED_OTAA = ubinascii.unhexlify('70b3d5d9909822fe','0000000000000000', '6ac1f02766915f0cc4ad8e2d04042303')
# LoRa payload format
# (2 Bytes for device ID, 8 float numbers: temp humid ph1 ph2 ph3 volt1 volt2 volt3)
LORA_PKG_FORMAT = "!Hffffffff"
# waiting time (for receive windows to expire)
WAITING_SLEEP = 8 #seconds
# LoRa PHY settings
LORA_FREQUENCY = 868100000
LORA_NODE_DR = 0 # LoRa datarate DR=0 sets SF = 12, DR=5 sets SF = 7 (DR=0 suggested for maximum range)
LORA_DEVICE_CLASS = LoRa.CLASS_C
LORA_REGION = LoRa.EU868 # LORAWAN region (Europe)
# alternatives:
# Asia = LoRa.AS923
# Australia = LoRa.AU915
# United States = LoRa.US915
loranet.py
#!/usr/bin/env python
import config
from network import LoRa
import socket
import binascii
import struct
import time
import _thread
import pycom
import time
class LoraNet:
def __init__(self, sleep_time, check_rx, frequency, dr, region, activation, device_class=LoRa.CLASS_C, auth = None):
self.sleep_time = sleep_time
self.check_rx = check_rx
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._process_ota_msg = None
def stop(self):
self._exit = True
def init(self, process_msg_callback):
self._process_ota_msg = process_msg_callback
def read_sleep_time(self):
return self.sleep_time
def read_check_rx(self):
return self.check_rx
def receive_callback(self, lora):
#callback on reception ack-sync
events = lora.events()
if events & LoRa.RX_PACKET_EVENT:
rx, port = self.sock.recvfrom(256)
#decode received meassage and extract sleep time
rx_data = rx.decode()
rx_sleep_time = int(rx_data.split(',')[1].split('.')[0])
print('Ack/sync received. Decoded received sleep time', rx_sleep_time)
self.sleep_time = rx_sleep_time
self.check_rx = True
if config.LED_ON:
#toggle blue led, message received
pycom.rgbled(0x0000FF) #blue
print('Received, blue led on')
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)
if self.activation == LoRa.OTAA:
# 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)
else:
# set the 3 default channels as per LoRaWAN specification
self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5)
self.lora.add_channel(1, frequency=868300000, dr_min=0, dr_max=5)
self.lora.add_channel(2, frequency=868500000, 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 has_joined(self):
return self.lora.has_joined()
main.py
from network import LoRa
import socket
import time
import ubinascii
# 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.EU868)
# create an OTAA authentication parameters, change them to the provided credentials
app_eui = ubinascii.unhexlify('0000000000000000')
app_key = ubinascii.unhexlify('6ac1f02766915f0cc4ad8e2d04042303')
#uncomment to use LoRaWAN application provided dev_eui
dev_eui = ubinascii.unhexlify('70b3d5d9909822fe')
# Uncomment for US915 / AU915 & Pygate
# for i in range(0,8):
# lora.remove_channel(i)
# for i in range(16,65):
# lora.remove_channel(i)
# for i in range(66,72):
# lora.remove_channel(i)
# join a network using OTAA (Over the Air Activation)
#uncomment below to use LoRaWAN application provided dev_eui
lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=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():
time.sleep(2.5)
print('Not yet joined...')
print('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, 5)
# 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(bytes([0x01, 0x02, 0x03]))
# make the socket non-blocking
# (because if there's no data received it will block forever...)
s.setblocking(False)
# get any data received (if any...)
data = s.recv(64)
print(data)
otaa_node.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.EU868)
# create an OTA authentication params
dev_eui = binascii.unhexlify('70b3d5d9909822fe')
app_eui = binascii.unhexlify('0000000000000000')
app_key = binascii.unhexlify('6ac1f02766915f0cc4ad8e2d04042303')
# 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...')
# 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)
I attach an image of the join frame
Can someone help me ?