Files
ESPEasy/lib/RN2483-Arduino-Library/src/rn2xx3.h
T

378 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* A library for controlling a Microchip RN2xx3 LoRa radio.
*
* Original:
* @Author JP Meijers
* @Author Nicolas Schteinschraber
* @Date 18/12/2015
*
* Rewrite to make it async (non blocking) in handling commands:
* @Author Gijs Noorlander
* @Date 16/02/2020
*
*/
#ifndef rn2xx3_h
#define rn2xx3_h
#include "Arduino.h"
#include "rn2xx3_status.h"
#include "rn2xx3_handler.h"
#include "rn2xx3_helper.h"
#include "rn2xx3_datatypes.h"
class rn2xx3 {
public:
/*
* A simplified constructor taking only a Stream ({Software/Hardware}Serial) object.
* The serial port should already be initialised when initialising this library.
*/
rn2xx3(Stream& serial);
/*
* Set the mode to work in async mode.
* This requires the user of this library to call async_loop()
* When set in async mode, the calls to commands which may take a while (e.g. join or "mac tx")
* will not be blocking anymore.
*/
void setAsyncMode(bool enabled);
bool getAsyncMode() const;
/*
* Transmit the correct sequence to the rn2xx3 to trigger its autobauding feature.
* After this operation the rn2xx3 should communicate at the same baud rate than us.
*/
bool autobaud();
/*
* Get the hardware EUI of the radio, so that we can register it on The Things Network
* and obtain the correct AppKey.
* You have to have a working serial connection to the radio before calling this function.
* In other words you have to at least call autobaud() some time before this function.
*/
String hweui();
/*
* Returns the OTAA AppKey used when initializing the radio.
*/
String appkey() const;
/*
* Returns the ABP AppSKey used when initializing the radio.
*/
String appskey() const;
/*
* In the case of OTAA this function will return the Application EUI used
* to initialize the radio.
*/
String appeui();
/*
* In the case of OTAA this function will return the Device EUI used to
* initialize the radio. This is not necessarily the same as the Hardware EUI.
* To obtain the Hardware EUI, use the hweui() function.
*/
String deveui();
/*
* Get the RN2xx3's hardware and firmware version number. This is also used
* to detect if the module is either an RN2483 or an RN2903.
*/
String sysver();
bool setSF(uint8_t sf);
bool setAdaptiveDataRate(bool enabled);
/*
* Initialise the RN2xx3 and join the LoRa network (if applicable).
* This function can only be called after calling initABP() or initOTAA().
* The sole purpose of this function is to re-initialise the radio if it
* is in an unknown state.
*/
bool init();
/*
* Initialise the RN2xx3 and join a network using personalization.
*
* addr: The device address as a HEX string.
* Example "0203FFEE"
* AppSKey: Application Session Key as a HEX string.
* Example "8D7FFEF938589D95AAD928C2E2E7E48F"
* NwkSKey: Network Session Key as a HEX string.
* Example "AE17E567AECC8787F749A62F5541D522"
*/
bool initABP(const String& addr,
const String& AppSKey,
const String& NwkSKey);
// TODO: initABP(uint8_t * addr, uint8_t * AppSKey, uint8_t * NwkSKey)
/*
* Initialise the RN2xx3 and join a network using over the air activation.
*
* AppEUI: Application EUI as a HEX string.
* Example "70B3D57ED00001A6"
* AppKey: Application key as a HEX string.
* Example "A23C96EE13804963F8C2BD6285448198"
* DevEUI: Device EUI as a HEX string.
* Example "0011223344556677"
* If the DevEUI parameter is omitted, the Hardware EUI from module will be used
* If no keys, or invalid length keys, are provided, no keys
* will be configured. If the module is already configured with some keys
* they will be used. Otherwise the join will fail and this function
* will return false.
*/
bool initOTAA(const String& AppEUI = "",
const String& AppKey = "",
const String& DevEUI = "");
/*
* Initialise the RN2xx3 and join a network using over the air activation,
* using byte arrays. This is useful when storing the keys in eeprom or flash
* and reading them out in runtime.
*
* AppEUI: Application EUI as a uint8_t buffer
* AppKey: Application key as a uint8_t buffer
* DevEui: Device EUI as a uint8_t buffer (optional - set to 0 to use Hardware EUI)
*/
bool initOTAA(uint8_t *AppEUI,
uint8_t *AppKey,
uint8_t *DevEui);
/*
* Transmit the provided data. The data is hex-encoded by this library,
* so plain text can be provided.
* This function is an alias for txUncnf().
*
* Parameter is an ascii text string.
*/
RN2xx3_datatypes::TX_return_type tx(const String&,
uint8_t port = 1);
/*
* Transmit raw byte encoded data via LoRa WAN.
* This method expects a raw byte array as first parameter.
* The second parameter is the count of the bytes to send.
*/
RN2xx3_datatypes::TX_return_type txBytes(const uint8_t *,
uint8_t size,
uint8_t port = 1);
RN2xx3_datatypes::TX_return_type txHexBytes(const String&,
uint8_t port = 1);
/*
* Do a confirmed transmission via LoRa WAN.
*
* Parameter is an ascii text string.
*/
RN2xx3_datatypes::TX_return_type txCnf(const String&,
uint8_t port = 1);
/*
* Do an unconfirmed transmission via LoRa WAN.
*
* Parameter is an ascii text string.
*/
RN2xx3_datatypes::TX_return_type txUncnf(const String&,
uint8_t port = 1);
/*
* Transmit the provided data using the provided command.
* Will return after the command has been processed and replies were received
*
* String - the tx command to send
can only be one of "mac tx cnf 1 " or "mac tx uncnf 1 "
* String - an ascii text string if bool is true. A HEX string if bool is false.
* bool - should the data string be hex encoded or not
*/
RN2xx3_datatypes::TX_return_type txCommand(const String&,
const String&,
bool,
uint8_t port = 1);
/*
* Call this frequently to process TX commmands when running
* txCommand with async set
* This is also called from txCommand, so no need to call it when not in async mode.
*
* Return value is the internal state of the TX processing.
*/
rn2xx3_handler::RN_state async_loop();
uint8_t get_busy_count() const;
rn2xx3_handler::RN_state wait_command_finished(unsigned long timeout = 10000);
rn2xx3_handler::RN_state wait_command_accepted(unsigned long timeout = 10000);
bool command_finished() const;
/*
* Change the datarate at which the RN2xx3 transmits.
* A value of between 0 and 5 can be specified,
* as is defined in the LoRaWan specs.
* This can be overwritten by the network when using OTAA.
* So to force a datarate, call this function after initOTAA().
*/
/*
EU / CN
Frequencies:
EU 863-870 MHz (LoRaWAN Specification (2015), Page 35, Table 14)
CN 779-787 MHz (LoRaWAN Specification (2015), Page 44, Table 25)
EU 433 MHz (LoRaWAN Specification (2015), Page 48, Table 31)
DataRate Modulation SF BW bit/s
0 LoRa 12 125 250
1 LoRa 11 125 440
2 LoRa 10 125 980
3 LoRa 9 125 1'760
4 LoRa 8 125 3'125
5 LoRa 7 125 5'470
6 LoRa 7 250 11'000
7 FSK 50 kbps 50'000
Data rates 8-15 are reserved.
US
Frequencies:
US 902-928 MHz (LoRaWAN Specification (2015), Page 40, Table 18)
DataRate Modulation SF BW bit/s
0 LoRa 10 125 980
1 LoRa 9 125 1'760
2 LoRa 8 125 3'125
3 LoRa 7 125 5'470
4 LoRa 8 500 12'500
8 LoRa 12 500 980
9 LoRa 11 500 1'760
10 LoRa 10 500 3'900
11 LoRa 9 500 7'000
12 LoRa 8 500 12'500
13 LoRa 7 500 21'900
Data rates 5-7 and 14-15 are reserved.
*/
bool setDR(int dr);
/*
* Put the RN2xx3 to sleep for a specified timeframe.
* The RN2xx3 accepts values from 100 to 4294967296.
* Rumour has it that you need to do a autobaud() after the module wakes up again.
*/
void sleep(long msec);
/*
* Send a raw command to the RN2xx3 module.
* Returns the raw string as received back from the RN2xx3.
* If the RN2xx3 replies with multiple line, only the first line will be returned.
*/
String sendRawCommand(const String& command);
/*
* Returns the module type either RN2903 or RN2483, or NA.
*/
RN2xx3_datatypes::Model moduleType();
/*
* Set the active channels to use.
* Optional rx2_freq to set/override the default frequency for RX2
*
* Returns true if setting the channels is possible.
* Returns false if you are trying to use the wrong channels on the wrong module type.
*/
bool setFrequencyPlan(RN2xx3_datatypes::Freq_plan, uint32_t rx2_freq = 0);
/*
* Set version of TTN stack to use.
*/
bool setTTNstack(RN2xx3_datatypes::TTN_stack_version version);
/*
* Returns the last downlink message HEX string.
*/
String getRx();
/*
* Get the RN2xx3's SNR of the last received packet. Helpful to debug link quality.
*/
int getSNR();
/*
* Get the RN2xx3's voltage measurement on the Vdd in mVolt
* 03600 (decimal value from 0 to 3600)
*/
int getVbat();
/*
* Return the current data rate formatted like sf7bw125
* Firmware 1.0.1 returns always "sf9"
*/
String getDataRate();
/*
* Return radio Received Signal Strength Indication (rssi) value
* for the last received frame.
* Supported since firmware 1.0.5
*/
int getRSSI();
/*
* Almost all commands can return "invalid_param"
* The last command resulting in such an error can be retrieved.
* Reading this will clear the error.
*/
String getLastError();
String peekLastError() const;
// Compute the air time for a packet in msec.
// Formula used from https://www.loratools.nl/#/airtime
// @param pl Payload length in bytes
float getLoRaAirTime(uint8_t pl) const;
bool hasJoined() const {
return _rn2xx3_handler.Status.Joined;
}
bool useOTAA() const {
return _rn2xx3_handler.useOTAA();
}
// Get the current frame counter values for downlink and uplink
bool getFrameCounters(uint32_t& dnctr,
uint32_t& upctr);
// Set frame counter values for downlink and uplink
// E.g. to restore them after a reboot or reset of the module.
bool setFrameCounters(uint32_t dnctr,
uint32_t upctr);
// delay from last moment of sending to receive RX1 and RX2 window
bool getRxDelayValues(uint32_t& rxdelay1,
uint32_t& rxdelay2);
// At init() the module is assumed to be joined, which is also checked against the
// _otaa flag.
// Allow to set the last used join mode to help prevent unneeded join requests.
void setLastUsedJoinMode(bool isOTAA) {
_rn2xx3_handler.setLastUsedJoinMode(isOTAA);
}
const RN2xx3_status& getStatus() const;
private:
// The actual interface to the module, handling the internal states.
rn2xx3_handler _rn2xx3_handler;
};
#endif // ifndef rn2xx3_h