Getting started

WHAD provides dedicated tools to interact with LoRaWAN networks and compatible devices. These tools are based on PHY’s LoRa capabilities.

LoRaWAN Channel Plan

Depending on where you are on the globe, LoRaWAN gateways are using different configurations with a given number of uplink channels with associated frequencies, as well as a given number of downlink channels.

This is why WHAD’s LoRaWAN implementation requires the user to specify a channel plan, an object that specifies the channels, frequencies and data rates to use for uplink and downlink communication.

Defining a custom channel plan

A channel plan can be easily defined as follows:

from whad.lorawan.channel import ChannelPlan, Uplink, Downlink, DataRate

class MyChannelPlan(ChannelPlan):
    """Custom channel plan
    """

    def __init__(self):
        super().__init__(
            channels = [
                # Uplink (1-8, DR5)
                Uplink(1, 868100000, 5),
                Uplink(2, 868300000, 5),
                Uplink(3, 868500000, 5),
                Uplink(4, 867100000, 5),
                Uplink(5, 867300000, 5),
                Uplink(6, 867500000, 5),
                Uplink(7, 867700000, 5),
                Uplink(8, 867900000, 5),
                Downlink(1, 868100000, 5),
                Downlink(2, 868300000, 5),
                Downlink(3, 868500000, 5),
                Downlink(4, 867100000, 5),
                Downlink(5, 867300000, 5),
                Downlink(6, 867500000, 5),
                Downlink(7, 867700000, 5),
                Downlink(8, 867900000, 5),
            ],

            datarates = [
                DataRate(12, 125000),
                DataRate(11, 125000),
                DataRate(10, 125000),
                DataRate(9, 125000),
                DataRate(8, 125000),
                DataRate(7, 125000),
            ],

            # Downlink RX2, DR0
            rx2=Downlink(10, 869525000, 0)
        )

Basically, the channels parameter is used to declare a set of RF channels, used for uplink and downlink, while the datarates parameter defines the supported data rates. An additionnal rx2 parameter allows to set the default second RX window configuration.

Uplink and downlink channels are defined with the following parameters:

  • The first parameter specifies the channel index ;

  • the second parameter its frequency ;

  • and the last one the data rate to use as an index into the datarates array.

Data rates are defined with the following parameters:

  • The first parameter specifies the spreading factor to use, from 7 to 12 ;

  • the second and last parameter specifies the bandwidth to use and must be 125000, 250000 or 500000.

The channel plan will then be used by the whad.lorawan.connector.LoRaWAN connector to use the correct channels for sending and receiving data.

Default channel plans

WHAD implements some default channel plans for some regions:

  • whad.lorawan.channel.EU868 for Europe (default SF7 with 125kHz bandwidth)

Configuring a LoRaWAN end device

Use the whad.lorawan.connector.LoRaWAN connector to create a LoRaWAN end device using a custom channel plan:

from whad.device import WhadDevice
from whad.lorawan.connector import LoRaWAN
from whad.lorawan.channel import ChannelPlan, Uplink, Downlink, DataRate

# Create our freq plan
class MyChannelPlan(ChannelPlan):
    def __init__(self):
        super().__init__(
            channels = [
                Uplink(1, 868100000, 0),
                Downlink(1, 868100000, 0)
            ],
            datarates = [
                DataRate(sf=7, bw=125000),
                DataRate(sf=12, bw=125000)
            ],

            rx2=Downlink(1, 868100000, 1)
        )

lwan = LoRaWAN(WhadDevice.create('uart0'), channel_plan=MyChannelPlan)

Receiving LoRaWAN packets

When a LoRaWAN connector instance is configured, it can be used to receive any LoRaWAN packet. By default, the hardware is put in receive mode with the provided channel plan.

from whad.device import WhadDevice
from whad.lorawan.connector import LoRaWAN
from whad.lorawan.channel import ChannelPlan, Uplink, Downlink, DataRate

# Create our freq plan
class MyChannelPlan(ChannelPlan):
    def __init__(self):
        super().__init__(
            channels = [
                Uplink(1, 868100000, 0),
                Downlink(1, 868100000, 0)
            ],
            datarates = [
                DataRate(sf=7, bw=125000),
                DataRate(sf=12, bw=125000)
            ],

            rx2=Downlink(1, 868100000, 1)
        )
# Create our LoRaWAN connector
lwan = LoRaWAN(WhadDevice.create('uart0'), channel_plan=MyChannelPlan)

# Start receiving by default
lwan.start()

# Listen for any valid packet received
while True:
    packet = lwan.wait_packet()
    packet.show()

Received packets have a timestamp that specifies when the packet has been received by the hardware. It can be later used to schedule a packet to be sent after a specific delay. This feature is used in our gateway implementation to send back some packets after a very precise delay as specified in the LoRaWAN specification.

Sending LoRaWAN packets

LoRaWAN packets can be sent through this connector and it is also possible to specify when a packet must be sent with the use of the timestamp parameter.

The whad.lorawan.connector.LoRaWAN.send() method is used to send a packet:

lwan.send(packet)

And it is possible to tell the WHAD hardware to schedule a packet for a given timestamp:

lwan.send(packet, timestamp=1500.123456)