Implementation of the LoRaWAN protocol for communication with LoRaWAN networks.
This file contains the implementation of the LoRaWAN class, which provides methods for initializing the LoRaWAN stack, joining a network, sending and receiving messages, and handling various LoRaWAN protocol features such as ADR (Adaptive Data Rate) and MAC commands.
The implementation uses the RFM95 radio module and supports both CH341SPI and Linux SPI interfaces.
- Note
- This implementation is designed for use with the RFM95 radio module and may require modifications to work with other radio modules.
@dependencies
- OpenSSL (for AES encryption)
- Standard C++ libraries (iostream, thread, chrono, queue, mutex, array, deque, bitset)
- Project-specific headers (LoRaWAN.hpp, RFM95.hpp, AES-CMAC.hpp, SessionManager.hpp)
Usage
To use this implementation, create an instance of the LoRaWAN class and call its methods to initialize the radio, join a network, and send/receive messages. The class provides methods for setting device parameters (DevEUI, AppEUI, AppKey, etc.), configuring the radio, and handling protocol-specific tasks such as calculating MICs and processing MAC commands.
Example:
lorawan.
setAppKey(
"8D7F3B4C5A6B7C8D9E0F1A2B3C4D5E6F");
std::vector<uint8_t> data = {0x01, 0x02, 0x03};
lorawan.
send(data, 1,
false);
}
Class that provides LoRaWAN protocol implementation.
Definition LoRaWAN.hpp:74
@ OTAA
Over-The-Air Activation - dynamic session keys.
Definition LoRaWAN.hpp:100
void setAppEUI(const std::string &appEUI)
Set the Application EUI.
Definition LoRaWAN.cpp:709
bool join(JoinMode mode, unsigned long timeout=10000)
Join a LoRaWAN network.
Definition LoRaWAN.cpp:761
bool send(const std::vector< uint8_t > &data, uint8_t port, bool confirmed=false, bool force_duty_cycle=false)
Send a message.
Definition LoRaWAN.cpp:1196
void setAppKey(const std::string &appKey)
Set the Application Key.
Definition LoRaWAN.cpp:729
void setDevEUI(const std::string &devEUI)
Set the Device EUI.
Definition LoRaWAN.cpp:689
Classes
Methods
- LoRaWAN::LoRaWAN(): Constructor to initialize the LoRaWAN instance.
- LoRaWAN::~LoRaWAN(): Destructor to clean up resources.
- bool LoRaWAN::init(int deviceIndex): Initialize the radio module.
- void LoRaWAN::setDeviceClass(DeviceClass deviceClass): Set the device class (A, B, or C).
- void LoRaWAN::setDevEUI(const std::string& devEUI): Set the device EUI.
- void LoRaWAN::setAppEUI(const std::string& appEUI): Set the application EUI.
- void LoRaWAN::setAppKey(const std::string& appKey): Set the application key.
- void LoRaWAN::setDevAddr(const std::string& devAddr): Set the device address.
- void LoRaWAN::setNwkSKey(const std::string& nwkSKey): Set the network session key.
- void LoRaWAN::setAppSKey(const std::string& appSKey): Set the application session key.
- bool LoRaWAN::join(JoinMode mode, unsigned long timeout): Join a LoRaWAN network.
- std::vector<uint8_t> LoRaWAN::encryptPayload(const std::vector<uint8_t>& payload, uint8_t port): Encrypt the payload.
- std::vector<uint8_t> LoRaWAN::decryptPayload(const std::vector<uint8_t>& payload, uint8_t port): Decrypt the payload.
- float LoRaWAN::calculateTimeOnAir(size_t payload_size): Calculate the time on air for a given payload size.
- bool LoRaWAN::checkDutyCycle(float frequency, size_t payload_size): Check if the duty cycle allows transmission.
- float LoRaWAN::getDutyCycleUsage(int channel): Get the duty cycle usage for a specific channel.
- void LoRaWAN::resetDutyCycle(): Reset the duty cycle usage.
- bool LoRaWAN::send(const std::vector<uint8_t>& data, uint8_t port, bool confirmed, bool force_duty_cycle): Send a message.
- void LoRaWAN::update(): Update the LoRaWAN state and handle received messages.
- bool LoRaWAN::receive(Message& message, unsigned long timeout): Receive a message.
- void LoRaWAN::onReceive(std::function<void(const Message&)> callback): Set a callback for received messages.
- void LoRaWAN::onJoin(std::function<void(bool)> callback): Set a callback for join events.
- void LoRaWAN::setRegion(int region): Set the LoRaWAN region.
- int LoRaWAN::getRegion() const: Get the current LoRaWAN region.
- float LoRaWAN::getFrequency() const: Get the current frequency.
- void LoRaWAN::setFrequency(float freq_mhz): Set the frequency.
- int LoRaWAN::getChannelFromFrequency(float freq_mhz) const: Get the channel index from a frequency.
- float LoRaWAN::getFrequencyFromChannel(int channel) const: Get the frequency from a channel index.
- void LoRaWAN::setChannel(uint8_t channel): Set the current channel.
- uint8_t LoRaWAN::getChannel() const: Get the current channel.
- void LoRaWAN::setSingleChannel(bool enable, float freq_mhz, int sf, int bw, int cr, int power, int preamble): Enable or disable single channel mode.
- bool LoRaWAN::getSingleChannel() const: Check if single channel mode is enabled.
- float LoRaWAN::getSingleChannelFrequency() const: Get the frequency for single channel mode.
- void LoRaWAN::setTxPower(int8_t power): Set the transmission power.
- int LoRaWAN::getRSSI() const: Get the RSSI (Received Signal Strength Indicator).
- int LoRaWAN::getSNR() const: Get the SNR (Signal-to-Noise Ratio).
- uint32_t LoRaWAN::getFrameCounter() const: Get the frame counter.
- void LoRaWAN::setFrameCounter(uint32_t counter): Set the frame counter.
- void LoRaWAN::wake(): Wake up the radio module.
- void LoRaWAN::sleep(): Put the radio module to sleep.
- bool LoRaWAN::validateKeys() const: Validate the session keys.
- void LoRaWAN::enableADR(bool enable): Enable or disable ADR (Adaptive Data Rate).
- bool LoRaWAN::isADREnabled() const: Check if ADR is enabled.
- void LoRaWAN::resetSession(): Reset the LoRaWAN session.
- void LoRaWAN::applyADRSettings(uint8_t dataRate, uint8_t txPower, const std::vector<uint8_t>& channelMask): Apply ADR settings.
- void LoRaWAN::processMACCommands(const std::vector<uint8_t>& commands, std::vector<uint8_t>& response): Process MAC commands.
- void LoRaWAN::processLinkADRReq(const std::vector<uint8_t>& cmd, size_t index, std::vector<uint8_t>& response): Process LinkADRReq command.
Debugging
The implementation includes several debug macros for conditional printing:
- DEBUG_PRINT(x): Print a message if verbose mode is enabled.
- DEBUG_PRINTLN(x): Print a message with a newline if verbose mode is enabled.
- DEBUG_HEX(x): Print a value in hexadecimal format if verbose mode is enabled.
Structures
- struct LoRaWAN::Impl: Internal implementation details, including radio configuration, session keys, counters, and state management.
Constants
- BASE_FREQ: Base frequencies for different regions.
- CHANNEL_STEP: Channel step sizes for different regions.
- MAX_POWER: Maximum transmission power for different regions.
- RX2_FREQ: RX2 frequencies for different regions.
- RX2_SF: RX2 spreading factors for different regions.
- RX2_BW: RX2 bandwidths for different regions.
- RX2_CR: RX2 coding rates for different regions.
- RX2_PREAMBLE: RX2 preamble lengths for different regions.
- ADR_ACK_LIMIT: ADR acknowledgment limit.
- ADR_ACK_DELAY: ADR acknowledgment delay.
- MAX_CHANNELS: Maximum number of channels.
- REGIONS: Number of supported regions.
Enums
- enum DeviceClass: Device classes (A, B, C).
- enum JoinMode: Join modes (OTAA, ABP).
- enum ConfirmationState: Confirmation states (NONE, WAITING_ACK, ACK_PENDING).
- enum RxWindowState: RX window states (RX_IDLE, RX_WINDOW_1, RX_WINDOW_2, RX_CONTINUOUS).
Typedefs
- typedef std::function<void(const Message&)> ReceiveCallback: Callback type for received messages.
- typedef std::function<void(bool)> JoinCallback: Callback type for join events.
Structs
- struct Message: Structure representing a LoRaWAN message.
Authors
- Sergio Pérez (Original Author)
- Date
- 2025/03/08
License
This code is provided under the MIT License.