Table of Contents

Class LorawanEndDevice

Namespace
Pamoja.Lorawan
Assembly
Pamoja.Lorawan.dll

A LoRaWAN Class A end device, without a radio.

public sealed class LorawanEndDevice : IDisposable
Inheritance
LorawanEndDevice
Implements
Inherited Members

Remarks

It joins, chooses a channel and data rate for each uplink, says when and where to listen for the answer, reads what comes back, and does what the network's MAC commands ask. It owns no radio and no clock: every call takes the time in microseconds and hands back what to put on the air, so the same device runs over any radio, or in a test with none.

One exchange runs like this: Join(ushort, ulong) or Send(byte, ReadOnlySpan<byte>, ulong, bool) returns a transmission and two receive windows timed from its end. A frame heard in either window goes to Heard(ReadOnlySpan<byte>, sbyte, LorawanReceiveWindow?). If neither held one, NothingHeard(ulong) says whether to Repeat(ulong) the frame, or move on.

Properties

DataRate

The data rate the next uplink goes out at, before any back-off step.

public byte DataRate { get; }

Property Value

byte

DevAddr

The address the device is on the network by, or null before joining.

public uint? DevAddr { get; }

Property Value

uint?

FcntDown

The last downlink frame counter accepted, or null before any downlink.

public uint? FcntDown { get; }

Property Value

uint?

FcntUp

The next uplink frame counter, which a device stores to carry over a restart.

public uint FcntUp { get; }

Property Value

uint

FrequencySpan

The lowest and highest frequency the device transmits or listens on, in hertz.

public (uint LowestHz, uint HighestHz) FrequencySpan { get; }

Property Value

(uint LowestHz, uint HighestHz)

IsJoined

Whether the device is on a network: once joined, or from the start when personalized.

public bool IsJoined { get; }

Property Value

bool

ReceiveDelayMicros

The delay from the end of an uplink to the first receive window, in microseconds.

public uint ReceiveDelayMicros { get; }

Property Value

uint

RelayActivation

How the device decides whether to use a relay.

public LorawanRelayActivation RelayActivation { get; }

Property Value

LorawanRelayActivation

RelayStatus

What the relay's last acknowledgment said, or null before one arrived.

public LorawanRelayStatus? RelayStatus { get; }

Property Value

LorawanRelayStatus?

RelaySync

What the device knows of when its relay listens, TS011-1.0.1 section 3.9.

public LorawanRelaySync RelaySync { get; }

Property Value

LorawanRelaySync

Relaying

Whether the next uplink goes through a relay.

public bool Relaying { get; }

Property Value

bool

Rx2

Where the second receive window listens.

public LoraRx2 Rx2 { get; }

Property Value

LoraRx2

Transmissions

How many times each uplink goes out, as the network last set it.

public byte Transmissions { get; }

Property Value

byte

WorCounter

The wake-on-radio frame counter the next frame will use, section 5.3.2.

public uint WorCounter { get; }

Property Value

uint

Methods

Channels()

Lists the channels the device may send on.

public IReadOnlyList<LorawanChannel> Channels()

Returns

IReadOnlyList<LorawanChannel>

Each enabled channel, with its index.

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

public void Dispose()

Heard(ReadOnlySpan<byte>, sbyte, LorawanReceiveWindow?)

Reads a frame heard in one of the receive windows of the last transmission.

public LorawanHeard Heard(ReadOnlySpan<byte> frame, sbyte snrDb, LorawanReceiveWindow? window = null)

Parameters

frame ReadOnlySpan<byte>

The bytes the radio received.

snrDb sbyte

The frame's signal-to-noise ratio, which a DevStatusAns reports.

window LorawanReceiveWindow?

The window the radio heard it in, when known. TS001-1.0.4 section 4.1 has a device discard a frame whose MACPayload is longer than the data rate it was received at carries, so a named window holds the frame to its own limit; without one, the frame may be as long as the faster window allows.

Returns

LorawanHeard

The join, or the downlink read and acted on.

Exceptions

LorawanDeviceException

Nothing pending, another device's frame, a replayed or far-ahead counter, a refused join accept, or a frame that did not decode or is longer than the window carries. The windows stay open, so the second still listens.

ArgumentOutOfRangeException

The window is not one of the two.

HeardWorAck(ReadOnlySpan<byte>)

Reads the acknowledgment a relay answered the last wake-on-radio frame with.

public LorawanRelayStatus HeardWorAck(ReadOnlySpan<byte> frame)

Parameters

frame ReadOnlySpan<byte>

The seven bytes the radio received in the acknowledgment window.

Returns

LorawanRelayStatus

What the relay said about itself.

Remarks

The device is now synchronized: it knows when the relay scans, so its next frames carry only as much preamble as the two clocks could have drifted apart.

Exceptions

LorawanDeviceException

No exchange is waiting, or the acknowledgment does not verify.

Join(ushort, ulong)

Builds a join request.

public LorawanTransmission Join(ushort devNonce, ulong nowMicros)

Parameters

devNonce ushort

A nonce this device has never used with its join EUI.

nowMicros ulong

The time, in microseconds.

Returns

LorawanTransmission

What to transmit, with the join accept windows.

Exceptions

LorawanDeviceException

No credentials, busy, or a wait for the air.

NoWorAck(ulong)

Says what to do once the acknowledgment window closed with nothing in it.

public LorawanWorNext NoWorAck(ulong nowMicros)

Parameters

nowMicros ulong

The time the window closed, in microseconds.

Returns

LorawanWorNext

Whether to send the uplink at the time the exchange named anyway, or wake the relay again first, as the network's back-off asks.

Exceptions

LorawanDeviceException

No wake-on-radio frame waits on an answer.

NothingHeard(ulong)

Says what comes next once both receive windows closed with nothing for the device.

public LorawanNext NothingHeard(ulong nowMicros)

Parameters

nowMicros ulong

The time the second window closed, in microseconds.

Returns

LorawanNext

Whether to repeat the frame, join again, or move on.

Exceptions

LorawanDeviceException

No transmission waits on its windows.

OverTheAir(LoraChannelPlan, LorawanDevice, LorawanDeviceSettings, uint, uint?)

Makes a device that joins over the air.

public static LorawanEndDevice OverTheAir(LoraChannelPlan plan, LorawanDevice credentials, LorawanDeviceSettings settings, uint fcntUp = 0, uint? fcntDown = null)

Parameters

plan LoraChannelPlan

A published channel plan, from ForRegion(LoraRegion) or ForCn470(LoraCn470Plan).

credentials LorawanDevice

The device's identifiers and root key, which the device copies.

settings LorawanDeviceSettings

What its radio can do.

fcntUp uint

The next uplink frame counter carried over a restart; a join starts it over.

fcntDown uint?

The last downlink frame counter accepted, if any was.

Returns

LorawanEndDevice

The device, not yet joined.

Exceptions

PamojaException

The plan was built rather than published, or the settings run backward.

Personalized(LoraChannelPlan, LorawanSession, LorawanDeviceSettings, uint, uint?)

Makes a device activated by personalization, with its session provisioned.

public static LorawanEndDevice Personalized(LoraChannelPlan plan, LorawanSession session, LorawanDeviceSettings settings, uint fcntUp = 0, uint? fcntDown = null)

Parameters

plan LoraChannelPlan

A published channel plan.

session LorawanSession

The address and session keys it was provisioned with, which the device copies.

settings LorawanDeviceSettings

What its radio can do.

fcntUp uint

The next uplink frame counter.

fcntDown uint?

The last downlink frame counter accepted, if any was.

Returns

LorawanEndDevice

The device, ready to send at its slowest data rate.

Remarks

Such a device never resets its frame counters, TS001-1.0.4 section 4.3.1.5, so one that lost power passes the counters it kept.

Exceptions

PamojaException

The plan was built rather than published.

Repeat(ulong)

Sends the last uplink again, the same frame on a channel chosen afresh.

public LorawanTransmission Repeat(ulong nowMicros)

Parameters

nowMicros ulong

The time, in microseconds.

Returns

LorawanTransmission

What to transmit, with its receive windows.

Exceptions

LorawanDeviceException

Nothing due to repeat, or a wait.

RequestDeviceTime()

Asks the network, with the next uplink, for the time.

public void RequestDeviceTime()

RequestLinkCheck()

Asks the network, with the next uplink, how well it hears the device.

public void RequestLinkCheck()

Resume(ReadOnlySpan<byte>, ulong)

Puts a saved state back on a device made the same way.

public void Resume(ReadOnlySpan<byte> saved, ulong nowMicros)

Parameters

saved ReadOnlySpan<byte>

The state Save(ulong) returned.

nowMicros ulong

The time on the clock the device woke to, in microseconds.

Exceptions

LorawanDeviceException

A state of the wrong length, a corrupt one, one in another format, one from another plan, or a busy device.

Save(ulong)

Saves a joined device's state, to keep across a loss of power.

public byte[] Save(ulong nowMicros)

Parameters

nowMicros ulong

The time, in microseconds.

Returns

byte[]

The state, which holds the session keys: keep it wherever the keys would be safe.

Exceptions

LorawanDeviceException

Not joined, or busy.

Send(byte, ReadOnlySpan<byte>, ulong, bool)

Builds an uplink carrying a payload.

public LorawanTransmission Send(byte port, ReadOnlySpan<byte> payload, ulong nowMicros, bool confirmed = false)

Parameters

port byte

The application port, 1 to 223, or 224 for the certification test port.

payload ReadOnlySpan<byte>

The application payload.

nowMicros ulong

The time, in microseconds.

confirmed bool

Whether to ask the network to acknowledge it.

Returns

LorawanTransmission

What to transmit, with its receive windows.

Exceptions

LorawanDeviceException

Not joined, busy, a wait for the air, a payload too long, or port 0.

SendEmpty(ulong)

Builds an uplink with no payload, carrying the answers the device owes, an acknowledgment, or an ADR acknowledgment request.

public LorawanTransmission SendEmpty(ulong nowMicros)

Parameters

nowMicros ulong

The time, in microseconds.

Returns

LorawanTransmission

What to transmit, with its receive windows.

Exceptions

LorawanDeviceException

As Send(byte, ReadOnlySpan<byte>, ulong, bool).

SetBattery(LorawanBattery)

Sets what the device reports its battery as, when a network asks.

public void SetBattery(LorawanBattery battery)

Parameters

battery LorawanBattery

The battery.

UseRelay(bool)

Turns relay mode on or off, TS011-1.0.1 section 10.2 and appendix 5.

public bool UseRelay(bool on)

Parameters

on bool

Whether the next uplinks go through a relay.

Returns

bool

false when the network holds the decision, leaving the mode as it was.

Remarks

From here on the decision is the caller's rather than the device's own policy, until the network takes it over with an EndDeviceConfReq or hands it back.