API Reference
February 4, 2022 · View on GitHub
The TheThingsNetwork class enables Arduino devices with supported LoRaWAN modules to communicate via The Things Network. Currently supported LoRaWAN modules are the Microchip RN2483 and the RN2903.
Class: TheThingsNetwork
Include and instantiate the TheThingsNetwork class. The constructor initializes the library with the Streams it should communicate with. It also sets the value of the spreading factor, the frequency plan, and the frequency sub-band.
#include <TheThingsNetwork.h>
TheThingsNetwork ttn(Stream& modemStream, Stream& debugStream, fp_ttn_t fp, uint8_t sf = 7, uint8_t fsb = 2);
Stream& modemStream: Stream for the LoRa modem (see notes).Stream& debugStream: Stream to write debug logs to (see notes).fp_ttn_fp fp: The frequency plan:TTN_FP_EU868,TTN_FP_US915,TTN_FP_AS920_923,TTN_FP_AS923_925orTTN_FP_KR920_923depending on the region you deploy in. See the wiki.uint8_t sf = 7: Optional custom spreading factor. Can be7to10forTTN_FP_US915and7to12for other frequency plans. Defaults to7.uint8_t fsb = 2: Optional custom frequency subband. Can be1to8. Defaults to2(for US915).
Method: reset
Performs a software reset of the RN module. This does not clear saved state, e.g. provisioned keys.
void reset(bool adr);
bool adr: Enable/disable Adaptive Data Rate.
Method: hardReset
Performs a hardware reset of the RN module. Input parameter is the pin to which the reset pin from the module is connected. This does clear saved state, e.g., provisioned keys.
void hardReset(uint8_t resetPin);
uint8_t resetPin: The output pin that is connected to the module's reset pin. The output pin should be configured as output and set to high by the user.
Method: getHardwareEui
Gets the unique hardware EUI, often used as the DevEUI.
size_t getHardwareEui(char *buffer, size_t size);
Method: getAppEui
Gets the provisioned AppEUI. The AppEUI is set using provision() or join().
size_t getAppEui(char *buffer, size_t size);
Method: getVersion
Gets the response from a sys get ver command (i.e. the hardware model, the the software version, etc.).
size_t getVersion(char *buffer, size_t size);
Method: showStatus
Writes information about the device and LoRa module to debugStream.
void showStatus();
Will write something like:
EUI: 0004A30B001B7AD2
Battery: 3223
AppEUI: 70B3D57EF000001C
DevEUI: 0004A30B001B7AD2
Data Rate: 5
RX Delay 1: 1000
RX Delay 2: 2000
See the DeviceInfo example.
Method: onMessage
Sets a function that will be called to process incoming messages. You'll want to do this in your setup() function and then define a void (*cb)(const byte* payload, size_t length, port_t port) function somewhere else in your sketch.
void onMessage(void (*cb)(const byte* payload, size_t length, port_t port));
const byte* payload: Bytes received.size_t length: Number of bytes.port_t port: The port addressed.
See the Receive example.
Method: join
Activate the device via OTAA (default).
bool join(const char *appEui, const char *appKey, int8_t retries = -1, uint32_t retryDelay = 10000, lorawan_class = CLASS_A);
bool join(int8_t retries = -1, uint32_t retryDelay = 10000);
const char *appEui: Application EUI the device is registered to.const char *appKey: Application Key assigned to the device.int8_t retries = -1: Number of times to retry after failed or unconfirmed join. Defaults to-1, which means infinite.uint32_t retryDelay = 10000: Delay in ms between attempts. Defaults to 10 seconds.lorawan_class = CLASS_A: The LoRaWAN class to use for downlink message reception.
Returns true or false depending on whether it received confirmation that the activation was successful before the maximum number of attempts.
Call the method without the first two arguments if the device's LoRa module comes with pre-flashed values.
Method: personalize
Activate the device via ABP.
bool personalize(const char *devAddr, const char *nwkSKey, const char *appSKey, bool reset_first);
bool personalize();
const char *devAddr: Device Address assigned to the device.const char *nwkSKey: Network Session Key assigned to the device for identification.const char *appSKey: Application Session Key assigned to the device for encryption.bool reset_first: Soft reset the module before performing any other action. Default istrue.
Returns true or false depending on whether the activation was successful.
Call the method with no arguments if the device's LoRa module comes with pre-flashed values.
See the SendABP example.
Method: setClass
Change the downlink receive LoRaWAN Class. Class C is only supported in firmware version 1.0.5 and up. For other firmware versions, this method will have no effect.
bool setClass(lorawan_class p_lw_class);
lorawan_class p_lw_class: The LoRaWAN class. EitherCLASS_AorCLASS_C.
Returns true if the change was successful, or false if not successful.
The receive window only opens after a transmit. Therefore Class C receive will only start after calling sendBytes().
See the ReceiveClassC example.
Method: sendBytes
Send a message to the application using raw bytes.
ttn_response_t sendBytes(const byte* payload, size_t length, port_t port = 1, bool confirm = false, uint8_t sf = 0);
const byte* payload: Bytes to send.size_t length: The number of bytes. Usesizeof(payload)to get it.port_t port = 1: The port to address. Defaults to1.bool confirm = false: Whether to ask for confirmation—defaults tofalse. If confirmation fails, the method will return the error codeTTN_ERROR_UNEXPECTED_RESPONSE.uint8_t sf = 0: Override the spreading factor (SF). If the default value0is passed, the SF is not changed from the constructor or previous value.
Returns a success or error code and logs the related error message:
TTN_ERROR_SEND_COMMAND_FAILED: Send command failed.TTN_SUCCESSFUL_TRANSMISSION: Successful transmission.TTN_SUCCESSFUL_RECEIVE: Successful transmission. Received <N> bytesTTN_UNSUCCESSFUL_RECEIVE: if we sent a confirmed message but did not get an acknowledgmentTTN_ERROR_UNEXPECTED_RESPONSE: Unexpected response: <Response>
See the SendOTAA example.
Method: poll
Calls sendBytes() with { 0x00 } as payload to poll for incoming messages.
int8_t poll(port_t port = 1, bool confirm = false);
port_t port = 1: The port to address. Defaults to1.bool confirm = false: Whether to ask for confirmation.bool modem_only = false: (only class A) Whether to avoid sending an empty frame and only listen to the modem's incoming message.
Returns the result of sendBytes(), with one difference:
TTN_UNSUCCESSFUL_RECEIVE: In class C or class Amodem_onlypoll, we only listened, and there was no incoming message.
The modem_only option for poll may be useful if the sending procedure did not terminate yet, e.g., we sent a confirmed message and did not get a response. In such a case, the modem will independently retry. With modem_only we thus just listen to the modem output to verify the status of the further attempts.
See the Receive example.
Method: provision
Sets the information needed to activate the device via OTAA, without actually activating. Call join() without the first 2 arguments to activate.
bool provision(const char *appEui, const char *appKey, bool reset_first);
const char *appEui: Application Identifier for the device.const char *appKey: Application Key assigned to the device.bool reset_first: Soft reset the module before performing any other action. Default istrue.
Method: sleep
Sleep the LoRa module for a specified number of milliseconds.
void sleep(unsigned long mseconds);
unsigned long mseconds: number of milliseconds to sleep.
Method: wake
Wake up the LoRa module from sleep before the expiration of the defined time.
void wake();
Method: linkCheck
Sets the time interval for the link check process to be triggered. The next uplink will include a Link Check Request MAC command when the interval expires. This method should be called after joining has been completed.
void linkCheck(uint16_t seconds);
uint16_t seconds: the time interval in seconds. A value of 0 will disable the link check process.
Method: getLinkCheckGateways
Gets the number of gateways that successfully received the last Link Check Request frame.
uint8_t getLinkCheckGateways();
Method: getLinkCheckMargin
Gets the demodulation margin as received in the last Link Check Answer frame.
uint8_t getLinkCheckMargin();
Additional for operation
Method: getVDD
Returns the voltage in millivolt (mV) measured by the RN2xxx LoRa module. It's for information only since we don't know how it's calculated but looks accurate.
uint16_t getVDD();
Method: getStatus
Returns the status of the RN2xxx modem's state machine in one of the nine possible states of ttn_modem_status_t. Unfortunately, due to a firmware bug, this does not work for RN2493 modems with firmware < 1.05. If unsuccessful, the method returns TTN_MODEM_READ_ERROR.
enum ttn_modem_status_t getStatus()
Possible return codes are:
TTN_MODEM_READ_ERRcould not read out the statusTTN_MODEM_IDLEmodem idle, ready for next txTTN_MODEM_TXmodem transmittingTTN_MODEM_BEFORE_RXwaiting time between tx and rx1 windowsTTN_MODEM_RX1RX1 window openTTN_MODEM_BEFORE_RX2waiting time between the two rx windowsTTN_MODEM_RETRY_DELAYwaiting before retry againTTN_MODEM_APB_DELAYAPB join delayTTN_MODEM_C_RX1RX1 window open in class CTTN_MODEM_C_RX2RX2 window open in class C
Method: getLastError
Returns the last error code encountered by the RN2xxx modem. The error code may be one of the twelve possible errors of ttn_response_code_t. Call this method after an unsuccessful execution.
ttn_response_code_t getLastError();
For example, suppose you perform a send via sendbytes and get a TTN_ERROR_SEND_COMMAND_FAILED. In that case, you can call this method and get a TTN_ERR_BUSY, which means the modem already has a message to send in the buffer.
Possible error codes are:
TTN_OKnothing actually went wrong.TTN_ERROR_BUSYbusy sending a messageTTN_ERROR_FRAME_COUNTER_ERRORif the frame counter rolled overTTN_ERROR_INVALID_CLASSselected LoRaWan class is invalidTTN_ERROR_INVALID_LENGTHdata length is not available for the current configurationTTN_ERROR_INVALID_PARAMETERinvalid parameter specifiedTTN_ERROR_NO_KEY_INTITIALIZEDnetwork keys not initializedTTN_ERROR_MAC_PAUSEmac level has been pausedTTN_ERROR_NO_KEY_MULTICASTmulticast keys not setTTN_ERROR_NO_FREE_CHANNELall channels exhausted their duty cycle, so we can not sendTTN_ERROR_NOT_JOINEDmodem did not join a networkTTN_ERROR_SILENTif the module is in a Silent Immediately stateTTN_ERROR_ERRother unspecified error
Method: getFCU
Returns the next used uplink frame counter. In LoRaWan, this counter must match on both sides, server, and end-node, for a transmission to be successful. Please note that although the counter is 32bit, the frame itself contains only the lowest 16bits of the message. Nonetheless, the message is encrypted using all 32bits of the FCU in the key. Therefore, it must be up to date and in sync. If the readout is unsuccessful, the method returns 0. However, the first frame after a reset is also set to 0.
uint32_t getFCU();
Method: setFCU
Sets the FCU as of above. The method returns true if successful.
bool setFCU(uint32_t fcu);
Method: getFCD
Returns the next expected downlink frame counter. In LoRaWan, this counter must match on both sides, server, and end-node, for a transmission to be successful. Please note that although the counter is 32bit, the frame itself contains only the lowest 16bits of the message. Nonetheless, the message is encrypted using all 32bits of the FCD in the key. Therefore, it must be up to date and in sync. If the readout is unsuccessful, the method returns 0. However, the first frame after a reset is also sent with frame number 0.
uint32_t getFCD();
Method: setFCD
Sets the FCD as of above. The method returns true if successful.
bool setFCD(uint32_t fcd);
Method: getDR
Returns the data rate that the modem will use for the next uplink frame. If the readout is unsuccessful, the method returns -1.
int8_t getDR();
Method: setDR
Sets the data rate to use for the next uplink frame; see getDR. This is mainly useful for operating with adaptive data rate (ADR) in off; see setADR. If ADR is on, it will set the DR for the next uplink, but the value for the successive transmissions may change according to the ADR protocol. The range of valid DR values depends on the frequency plan. The method returns true if successful.
bool setDR(uint8_t dr);
Method: getPowerIndex
Returns the power index that the LoRa modem will use for the next uplink frame. If the readout is unsuccessful, the method returns -1.
int8_t getPowerIndex();
Method: setPowerIndex
Sets the power index to use for the next uplink frame; see getPowerIndex. This is mainly useful for operating with adaptive data rate (ADR) in off; see setADR. If ADR is on, it will set the power index for the next uplink. Still, the value for the following transmissions may change according to the ADR protocol. The range of valid values depends on modem hardware and the frequency plan. The method returns true if successful.
bool setPowerIndex(uint8_t index);
Method: setChannel
The TTN module can store multiple channel configurations. With this method, you can configure a logical channel of the modem by defining frequency in Hz, minimum and maximum usable data rates for the channel. Data rates depend on the used frequency plan and must be between 0 and 15. The method returns true if a configuration is successful.
bool setChannel(uint8_t channel, uint32_t frequency = 0l, uint8_t dr_min = 255, uint8_t dr_max = 255);
Alternatively, you can only re-set the data rates for the channel by leaving (omitting) frequency to 0.
setChannel(2, dr_min = 0, dr_max = 4);
Or, you can only re-set the frequency for the channel by leaving (omitting) dr_* to 255.
setChannel(2, 863500000);
However, the whole configuration must have been set at least once to be successful in both cases.
Method: setRX2Channel
In some plans, the TTN module stores a common RX2 downlink channel, which is used for RX2 window communication. With this method, you can configure this channel by defining frequency in Hz and its data rates. The valid data rates depend on the used frequency plan. The method returns true if a configuration is successful.
bool setRx2Channel(uint32_t frequency, uint8_t dr);
Method: getChannelStatus
The TTN module can store multiple channel configurations. This method returns true if the channel is enabled for transmission and/or receiving.
bool getChannelStatus (uint8_t channel);
Method: setChannelStatus
Sets the channel status of the selected channel number; see getChannelStatus. If set to true and the channel is configured, the modem may use the channel for transmission. The method returns true if successful.
bool setChannelStatus (uint8_t channel, bool status);
Method: setChannelDCycle
Sets the channel maximum allowed duty cycle of a selected channel number in %. Depending on regional regulations, the duty cycle may limit the maximum frequency use to a percentage in time. With this method, we set the ratio of transmission time for the selected channel, e.g., 1% with 1 second transmission time means the radio has to pause for 99 seconds on this channel before retransmitting. The method returns true if successful.
bool setChannelDCycle (uint8_t channel, float duty_cycle);
Method: setADR
We can manually disable or enable the adaptive data rate (ADR) algorithm on the device with this method. It independently adapts the transmission data rate (and power) in runtime if active. If disabled, we must select power index and data rate manually, see setDR and setPowerIndex. The method returns true if successful.
bool setADR(bool adr);
Method: setRX1Delay
When transmitting in LoRaWan, we usually operate on a TX window and two RX windows. This setting defines how long the modem has to wait before opening the channel for listening for RX window 1. RX window two is hardcoded to be one second after RX1. This parameter is configurable between 1 and 15 seconds in ms. By default, we have a delay of 1000 ms, and you should not change this if you do not change the network server accordingly. Longer window delays may be helpful with slow, unresponsive Internet connectivity. The method returns true if successful.
bool setRX1Delay(uint16_t delay);
Method: checkValidModuleConnected
Checks if a valid module is connected to the configured serial port. Useful to check for connectivity with a supported module before performing any other actions.
bool checkValidModuleConnected(bool autobaud_first);
bool autobaud_first: Perform a call toautoBaud()before checking connection. Default isfalse.
Returns:
falseif no response was received (i.e.needsHardResetistrue)falseif the module is invalid (unsupported), i.e. not one of the following:RN2483RN2483ARN2903RN2903AS
trueif the module responded (i.e.needsHardResetisfalse) and is valid (supported).
See the CheckModule example.
Additional for statistics
Method: getRSSI
Returns the relative signal strength of the last received frame in dBm. Typical values are between -70dBm (very strong) and -136dBm (weak/sensitivity threshold). If the readout is unsuccessful, the method returns -255.
int16_t getRSSI();
Method: getSNR
Returns the signal to noise ratio of the last received frame in dB. Note that LoRa also allows negative values for SNR. Typical values are between +20dB (very clear) and -20dB (weak/sensitivity threshold). If the readout is unsuccessful, the method returns -128.
int8_t getSNR();
Method: getFrequency
Returns the channel frequency of the last received frame in Hz. If the readout is unsuccessful, the method returns 0.
uint32_t getFrequency();
Method: getWatchDogTimer
Returns the LoRa modem's internal watch-dog timer in ms. If this time is exceeded, the modem resets. If instead, the readout is unsuccessful, the method returns 0.
uint32_t getWatchDogTimer();
Method: getBW
Returns the used channel bandwidth of the last received frame in kHz. If the readout is unsuccessful, the method returns 0.
uint8_t getBW();
Method: getCR
Returns the used code rate of the last received frame in 4/x. If the readout is unsuccessful, the method returns 0.
uint8_t getCR();
Method: getPower
Returns the power of the last incoming transmission in dBm. If the readout is unsuccessful, the method returns -128.
int8_t getPower();