diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..7a4b90f --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: Microsoft +IndentWidth: 4 +ColumnLimit: 120 diff --git a/include/TheThingsNetwork.h b/include/TheThingsNetwork.h index 69756ae..be18f1b 100644 --- a/include/TheThingsNetwork.h +++ b/include/TheThingsNetwork.h @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -21,7 +21,7 @@ /** * @brief Integer data type for specified the port of an uplink or downlink message. - * + * * @deprecated Use @ref ttn_port_t instead. */ typedef ttn_port_t port_t; @@ -41,7 +41,6 @@ enum TTNResponseCode kTTNSuccessfulReceive = TTN_SUCCESSFUL_RECEIVE }; - /** * @brief RX/TX window */ @@ -65,7 +64,6 @@ enum TTNRxTxWindow kTTNRx2Window = TTN_WINDOW_RX2 }; - /** * @brief Spreading Factor */ @@ -105,7 +103,6 @@ enum TTNSpreadingFactor kTTNSF12 = TTN_SF12 }; - /** * @brief Bandwidth */ @@ -129,10 +126,9 @@ enum TTNBandwidth kTTNBW500 = TTN_BW_500 }; - /** * @brief Data Rate - * + * * Note that the spreading factor, bandwidth, bit rate and maximum message * size associated with each data rate depends on the region. */ @@ -201,37 +197,37 @@ enum TTNDataRate kTTNDataRate_AU915_SF8_BW500 = 6, /** * @brief Data rate for region AU915 using SF12 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF12_BW500 = 8, /** * @brief Data rate for region AU915 using SF11 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF11_BW500 = 9, /** * @brief Data rate for region AU915 using SF10 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF10_BW500 = 10, /** * @brief Data rate for region AU915 using SF9 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF9_BW500 = 11, /** * @brief Data rate for region AU915 using SF8 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF8_BW500_DR12 = 12, /** * @brief Data rate for region AU915 using SF7 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_AU915_SF7_BW500 = 13, @@ -345,37 +341,37 @@ enum TTNDataRate kTTNDataRate_US915_SF8_BW500 = 4, /** * @brief Data rate for region US915 using SF12 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF12_BW500 = 8, /** * @brief Data rate for region US915 using SF11 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF11_BW500 = 9, /** * @brief Data rate for region US915 using SF10 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF10_BW500 = 10, /** * @brief Data rate for region US915 using SF9 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF9_BW500 = 11, /** * @brief Data rate for region US915 using SF8 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF8_BW500_DR12 = 12, /** * @brief Data rate for region US915 using SF7 and 500 kHz bandwidth. - * + * * Reserved for future applications. */ kTTNDataRate_US915_SF7_BW500 = 13, @@ -386,7 +382,6 @@ enum TTNDataRate kTTNDRJoinDdefault }; - /** * @brief RF settings for TX or RX */ @@ -406,55 +401,64 @@ struct TTNRFSettings uint32_t frequency; }; - /** * @brief Callback for recieved messages - * + * * @param payload pointer to the received bytes * @param length number of received bytes * @param port port the message was received on */ -typedef void (*TTNMessageCallback)(const uint8_t* payload, size_t length, ttn_port_t port); +typedef void (*TTNMessageCallback)(const uint8_t *payload, size_t length, ttn_port_t port); /** * @brief TTN device - * + * * This class enables ESP32 devices with SX1272/73/76/77/78/79 LoRaWAN chips * to communicate via The Things Network. - * + * * Only one instance of this class may be created. */ class TheThingsNetwork { -public: + public: /** * @brief Constructs a new The Things Network device instance. */ - TheThingsNetwork() { ttn_init(); } + TheThingsNetwork() + { + ttn_init(); + } /** * @brief Destroys the The Things Network device instance. */ - ~TheThingsNetwork() { } + ~TheThingsNetwork() + { + } /** * @brief Resets the LoRaWAN radio. - * + * * To restart communication, @ref join() must be called. * Clears neither the provisioned keys nor the configured pins. */ - void reset() { ttn_reset(); } + void reset() + { + ttn_reset(); + } /** * @brief Configures the pins used to communicate with the LoRaWAN radio chip. - * - * Before calling this member function, the SPI bus needs to be configured using `spi_bus_initialize()`. + * + * Before calling this member function, the SPI bus needs to be configured using `spi_bus_initialize()`. * Additionally, `gpio_install_isr_service()` must have been called to initialize the GPIO ISR handler service. - * + * * @param spi_host The SPI bus/peripherial to use (`SPI_HOST`, `HSPI_HOST` or `VSPI_HOST`). * @param nss The GPIO pin number connected to the radio chip's NSS pin (serving as the SPI chip select) - * @param rxtx The GPIO pin number connected to the radio chip's RXTX pin (@ref TTN_NOT_CONNECTED if not connected) - * @param rst The GPIO pin number connected to the radio chip's RST pin (@ref TTN_NOT_CONNECTED if not connected) + * @param rxtx The GPIO pin number connected to the radio chip's RXTX pin (@ref TTN_NOT_CONNECTED if not + * connected) + * @param rst The GPIO pin number connected to the radio chip's RST pin (@ref TTN_NOT_CONNECTED if not + * connected) * @param dio0 The GPIO pin number connected to the radio chip's DIO0 pin * @param dio1 The GPIO pin number connected to the radio chip's DIO1 pin */ @@ -465,112 +469,134 @@ public: /** * @brief Sets the frequency sub-band to be used. - * + * * For regions with sub-bands (USA, Australia), sets the sub-band to be used for uplink communication. * For other regions, this function has no effect. - * + * * The sub-band must be set before joining or sending the first message. - * + * * If not set, it defaults to sub-band 2 as defined by TTN. - * + * * @param band band (0 for all bands, or value between 1 and 8) */ - void setSubband(int band) { ttn_set_subband(band); } + void setSubband(int band) + { + ttn_set_subband(band); + } /** * @brief Sets the credentials needed to activate the device via OTAA, without activating it. - * + * * The provided DevEUI, AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before * this function is called, `nvs_flash_init()` must have been called once. - * + * * Call @ref join() to activate the device. - * + * * @param devEui DevEUI (16 character string with hexadecimal data) * @param appEui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) * @param appKey AppKey of the device (32 character string with hexadecimal data) * @return `true` if the provisioning was successful, `false` if the provisioning failed */ - bool provision(const char *devEui, const char *appEui, const char *appKey) { return ttn_provision(devEui, appEui, appKey); } + bool provision(const char *devEui, const char *appEui, const char *appKey) + { + return ttn_provision(devEui, appEui, appKey); + } /** * @brief Sets the information needed to activate the device via OTAA, using the MAC to generate the DevEUI * and without activating it. - * + * * The generated DevEUI and the provided AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before * this function is called, `nvs_flash_init` must have been called once. - * + * * The DevEUI is generated by retrieving the ESP32's WiFi MAC address and expanding it into a DevEUI * by adding FFFE in the middle. So the MAC address A0:B1:C2:01:02:03 becomes the EUI A0B1C2FFFE010203. * This hexadecimal data can be entered into the DevEUI field in the TTN console. - * + * * Generating the DevEUI from the MAC address allows to flash the same AppEUI/JoinEUI and AppKey to a batch of * devices. However, using the same AppKey for multiple devices is insecure. Only use this approach if * it is okay for that the LoRa communication of your application can easily be intercepted and that * forged data can be injected. - * + * * Call @ref join() to activate. - * + * * @param appEui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) * @param appKey AppKey of the device (32 character string with hexadecimal data) * @return `true` if the provisioning was successful, `false` if the provisioning failed */ - bool provisionWithMAC(const char *appEui, const char *appKey) { return ttn_provision_with_mac(appEui, appKey); } + bool provisionWithMAC(const char *appEui, const char *appKey) + { + return ttn_provision_with_mac(appEui, appKey); + } /** * @brief Starts task listening on configured UART for AT commands. - * + * * Run `make menuconfig` to configure it. */ - void startProvisioningTask() { ttn_start_provisioning_task(); } + void startProvisioningTask() + { + ttn_start_provisioning_task(); + } /** * @brief Waits until the DevEUI, AppEUI/JoinEUI and AppKey have been provisioned * by the provisioning task. - * + * * If the device has already been provisioned (stored data in NVS, call of provision() * or call of @ref join(const char*, const char*, const char*), this function * immediately returns. */ - void waitForProvisioning() { ttn_wait_for_provisioning(); } + void waitForProvisioning() + { + ttn_wait_for_provisioning(); + } - /** + /** * @brief Activates the device via OTAA. - * + * * The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call to provision(). * Before this function is called, `nvs_flash_init()` must have been called once. - * + * * The function blocks until the activation has completed or failed. - * + * * @return `true` if the activation was succesful, `false` if the activation failed */ - bool join() { return ttn_join_provisioned(); } + bool join() + { + return ttn_join_provisioned(); + } - /** + /** * @brief Sets the DevEUI, AppEUI/JoinEUI and AppKey and activate the device via OTAA. - * + * * The DevEUI, AppEUI/JoinEUI and AppKey are NOT saved in non-volatile memory. - * + * * The function blocks until the activation has completed or failed. - * + * * @param devEui DevEUI (16 character string with hexadecimal data) * @param appEui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) * @param appKey AppKey of the device (32 character string with hexadecimal data) * @return `true` if the activation was succesful, `false` if the activation failed */ - bool join(const char *devEui, const char *appEui, const char *appKey) { return ttn_join(devEui, appEui, appKey); } + bool join(const char *devEui, const char *appEui, const char *appKey) + { + return ttn_join(devEui, appEui, appKey); + } /** * @brief Transmits a message - * + * * The function blocks until the message could be transmitted and a message has been received * in the subsequent receive window (or the window expires). Additionally, the function will * first wait until the duty cycle allows a transmission (enforcing the duty cycle limits). - * + * * @param payload bytes to be transmitted * @param length number of bytes to be transmitted * @param port port (defaults to 1) * @param confirm flag indicating if a confirmation should be requested. Defaults to `false` - * @return @ref kTTNSuccessfulTransmission for successful transmission, @ref kTTNErrorTransmissionFailed for failed transmission, @ref kTTNErrorUnexpected for unexpected error + * @return @ref kTTNSuccessfulTransmission for successful transmission, @ref kTTNErrorTransmissionFailed for failed + * transmission, @ref kTTNErrorUnexpected for unexpected error */ TTNResponseCode transmitMessage(const uint8_t *payload, size_t length, ttn_port_t port = 1, bool confirm = false) { @@ -579,97 +605,127 @@ public: /** * @brief Sets the function to be called when a message is received - * + * * When a message is received, the specified function is called. The * message, its length and the port number are provided as * parameters. The values are only valid during the duration of the * callback. So they must be immediately processed or copied. - * + * * Messages are received as a result of a call to @ref transmitMessage(). The callback is called * in the task that called this function and it occurs before this function * returns control to the caller. - * + * * @param callback the callback function */ - void onMessage(TTNMessageCallback callback) { ttn_on_message(callback); } + void onMessage(TTNMessageCallback callback) + { + ttn_on_message(callback); + } /** * @brief Checks if DevEUI, AppEUI/JoinEUI and AppKey have been stored in non-volatile storage * or have been provided as by a call to @ref join(const char*, const char*, const char*). - * + * * @return `true` if they are stored, complete and of the correct size, `false` otherwise */ - bool isProvisioned() { return ttn_is_provisioned(); } + bool isProvisioned() + { + return ttn_is_provisioned(); + } /** * @brief Sets the RSSI calibration value for LBT (Listen Before Talk). - * + * * This value is added to RSSI measured prior to decision. It must include the guardband. * Ignored in US, EU, IN and other countries where LBT is not required. * Defaults to 10 dB. - * + * * @param rssiCal RSSI calibration value, in dB */ - void setRSSICal(int8_t rssiCal) { ttn_set_rssi_cal(rssiCal); } + void setRSSICal(int8_t rssiCal) + { + ttn_set_rssi_cal(rssiCal); + } /** * Returns whether Adaptive Data Rate (ADR) is enabled. - * + * * @return `true` if enabled, `false` if disabled */ - bool adrEnabled() { return ttn_adr_enabled(); } + bool adrEnabled() + { + return ttn_adr_enabled(); + } /** * @brief Enables or disabled Adaptive Data Rate (ADR). - * + * * ADR is enabled by default. It optimizes data rate, airtime and energy consumption * for devices with stable RF conditions. It should be turned off for mobile devices. - * + * * @param enabled `true` to enable, `false` to disable - */ - void setAdrEnabled(bool enabled) { ttn_set_adr_enabled(enabled); } + */ + void setAdrEnabled(bool enabled) + { + ttn_set_adr_enabled(enabled); + } /** * @brief Sets the transmission data rate (i.e. the data rate for uplink messages). - * + * * If ADR is enabled, it's is used as the initial data rate and later adjusted depending * on the RF conditions. If ADR is disabled, it is used for all uplink messages. - * + * * @param data_rate data rate (use constants of enum @ref TTNDataRate) */ - void setDataRate(TTNDataRate data_rate) { ttn_set_data_rate(static_cast(data_rate)); } + void setDataRate(TTNDataRate data_rate) + { + ttn_set_data_rate(static_cast(data_rate)); + } /** * @brief Sets the maximum power for transmission - * + * * The power is specified in dBm and sets the power emitted by the radio. * If the antenna has a gain, it must be substracted from the specified value to * achieve the correct transmission power. - * + * * @param tx_pow power, in dBm */ - void setMaxTxPower(int tx_pow) { ttn_set_max_tx_pow(tx_pow); } + void setMaxTxPower(int tx_pow) + { + ttn_set_max_tx_pow(tx_pow); + } /** * @brief Stops all activies and shuts down the RF module and the background tasks. - * + * * To restart communication, @ref startup() and @ref join() must be called. * it neither clears the provisioned keys nor the configured pins. */ - void shutdown() { ttn_shutdown(); } + void shutdown() + { + ttn_shutdown(); + } /** * @brief Restarts the background tasks and RF module. - * + * * This member function must only be called after a call to shutdowna(). */ - void startup() { ttn_startup(); } + void startup() + { + ttn_startup(); + } /** * @brief Gets current RX/TX window * @return window */ - TTNRxTxWindow rxTxWindow() { return static_cast(ttn_rx_tx_window()); } + TTNRxTxWindow rxTxWindow() + { + return static_cast(ttn_rx_tx_window()); + } /** * @brief Gets the RF settings for the specified window @@ -681,28 +737,40 @@ public: * @brief Gets the RF settings of the last (or ongoing) transmission. * @return RF settings */ - TTNRFSettings txSettings() { return getRFSettings(kTTNTxWindow); } + TTNRFSettings txSettings() + { + return getRFSettings(kTTNTxWindow); + } /** * @brief Gets the RF settings of the last (or ongoing) reception of RX window 1. * @return RF settings */ - TTNRFSettings rx1Settings() { return getRFSettings(kTTNRx1Window); } + TTNRFSettings rx1Settings() + { + return getRFSettings(kTTNRx1Window); + } /** * @brief Gets the RF settings of the last (or ongoing) reception of RX window 2. * @return RF settings */ - TTNRFSettings rx2Settings() { return getRFSettings(kTTNRx2Window); } + TTNRFSettings rx2Settings() + { + return getRFSettings(kTTNRx2Window); + } /** * @brief Gets the received signal strength indicator (RSSI). - * + * * RSSI is the measured signal strength of the last recevied message (incl. join responses). - * + * * @return RSSI, in dBm */ - int rssi() { return ttn_rssi(); } + int rssi() + { + return ttn_rssi(); + } }; #endif diff --git a/include/ttn.h b/include/ttn.h index 7536ad3..bdf83fc 100644 --- a/include/ttn.h +++ b/include/ttn.h @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -17,699 +17,691 @@ #ifndef TTN_C_H #define TTN_C_H -#include #include "driver/spi_master.h" - +#include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /** * @addtogroup c_api - * + * * @{ */ - /** * @brief Constant for indicating that a pin is not connected */ #define TTN_NOT_CONNECTED 0xff - -/** - * @brief Integer data type for specifiying the port of an uplink or downlink message. - */ -typedef uint8_t ttn_port_t; - -/** - * @brief Response codes - */ -typedef enum -{ - /** @brief Transmission failed error */ - TTN_ERROR_TRANSMISSION_FAILED = -1, - /** @brief Unexpected or internal error */ - TTN_ERROR_UNEXPECTED = -10, - /** @brief Successful transmission of an uplink message */ - TTN_SUCCESSFUL_TRANSMISSION = 1, - /** @brief Successful receipt of a downlink message */ - TTN_SUCCESSFUL_RECEIVE = 2 -} ttn_response_code_t; - - -/** - * @brief RX/TX window - */ -typedef enum -{ /** - * @brief Outside RX/TX window + * @brief Integer data type for specifiying the port of an uplink or downlink message. */ - TTN_WINDOW_IDLE = 0, - /** - * @brief Transmission window (up to RX1 window) - */ - TTN_WINDOW_TX = 1, - /** - * @brief Reception window 1 (up to RX2 window) - */ - TTN_WINDOW_RX1 = 2, - /** - * @brief Reception window 2 - */ - TTN_WINDOW_RX2 = 3 -} ttn_rx_tx_window_t; - - -/** - * @brief Spreading Factor - */ -typedef enum -{ - /** - * @brief Unused / undefined spreading factor - */ - TTN_SF_NONE = 0, - /** - * @brief Frequency Shift Keying (FSK) - */ - TTN_FSK = 1, - /** - * @brief Spreading Factor 7 (SF7) - */ - TTN_SF7 = 2, - /** - * @brief Spreading Factor 8 (SF8) - */ - TTN_SF8 = 3, - /** - * @brief Spreading Factor 9 (SF9) - */ - TTN_SF9 = 4, - /** - * @brief Spreading Factor 10 (SF10) - */ - TTN_SF10 = 5, - /** - * @brief Spreading Factor 11 (SF11) - */ - TTN_SF11 = 6, - /** - * @brief Spreading Factor 12 (SF12) - */ - TTN_SF12 = 7 -} ttn_spreading_factor_t; - - -/** - * @brief Bandwidth - */ -typedef enum -{ - /** - * @brief Undefined/unused bandwidth - */ - TTN_BW_NONE = 0, - /** - * @brief Bandwidth of 125 kHz - */ - TTN_BW_125 = 1, - /** - * @brief Bandwidth of 250 kHz - */ - TTN_BW_250 = 2, - /** - * @brief Bandwidth of 500 kHz - */ - TTN_BW_500 = 3 -} ttn_bandwidth_t; - - -/** - * @brief Data Rate - * - * Note that the spreading factor, bandwidth, bit rate and maximum message - * size associated with each data rate depends on the region. - */ -typedef enum -{ - /** - * @brief Data rate for region AS923 using SF12 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF12 = 0, - /** - * @brief Data rate for region AS923 using SF11 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF11 = 1, - /** - * @brief Data rate for region AS923 using SF10 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF10 = 2, - /** - * @brief Data rate for region AS923 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF9 = 3, - /** - * @brief Data rate for region AS923 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF8 = 4, - /** - * @brief Data rate for region AS923 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_AS923_SF7_BW125 = 5, - /** - * @brief Data rate for region AS923 using SF7 and 250 kHz bandwidth. - */ - TTN_DR_AS923_SF7_BW250 = 6, - /** - * @brief Data rate for region AS923 using FSK and 50 kpbs. - */ - TTN_DR_AS923_FSK = 7, + typedef uint8_t ttn_port_t; /** - * @brief Data rate for region AU915 using SF12 and 125 kHz bandwidth. + * @brief Response codes */ - TTN_DR_AU915_SF12 = 0, - /** - * @brief Data rate for region AU915 using SF11 and 125 kHz bandwidth. - */ - TTN_DR_AU915_SF11 = 1, - /** - * @brief Data rate for region AU915 using SF10 and 125 kHz bandwidth. - */ - TTN_DR_AU915_SF10 = 2, - /** - * @brief Data rate for region AU915 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_AU915_SF9 = 3, - /** - * @brief Data rate for region AU915 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_AU915_SF8 = 4, - /** - * @brief Data rate for region AU915 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_AU915_SF7 = 5, - /** - * @brief Data rate for region AU915 using SF8 and 500 kHz bandwidth. - */ - TTN_DR_AU915_SF8_BW500 = 6, - /** - * @brief Data rate for region AU915 using SF12 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF12_BW500 = 8, - /** - * @brief Data rate for region AU915 using SF11 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF11_BW500 = 9, - /** - * @brief Data rate for region AU915 using SF10 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF10_BW500 = 10, - /** - * @brief Data rate for region AU915 using SF9 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF9_BW500 = 11, - /** - * @brief Data rate for region AU915 using SF8 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF8_BW500_DR12 = 12, - /** - * @brief Data rate for region AU915 using SF7 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_AU915_SF7_BW500 = 13, + typedef enum + { + /** @brief Transmission failed error */ + TTN_ERROR_TRANSMISSION_FAILED = -1, + /** @brief Unexpected or internal error */ + TTN_ERROR_UNEXPECTED = -10, + /** @brief Successful transmission of an uplink message */ + TTN_SUCCESSFUL_TRANSMISSION = 1, + /** @brief Successful receipt of a downlink message */ + TTN_SUCCESSFUL_RECEIVE = 2 + } ttn_response_code_t; /** - * @brief Data rate for region EU868 using SF12 and 125 kHz bandwidth. + * @brief RX/TX window */ - TTN_DR_EU868_SF12 = 0, - /** - * @brief Data rate for region EU868 using SF11 and 125 kHz bandwidth. - */ - TTN_DR_EU868_SF11 = 1, - /** - * @brief Data rate for region EU868 using SF10 and 125 kHz bandwidth. - */ - TTN_DR_EU868_SF10 = 2, - /** - * @brief Data rate for region EU868 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_EU868_SF9 = 3, - /** - * @brief Data rate for region EU868 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_EU868_SF8 = 4, - /** - * @brief Data rate for region EU868 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_EU868_SF7_BW125 = 5, - /** - * @brief Data rate for region EU868 using SF7 and 250 kHz bandwidth. - */ - TTN_DR_EU868_SF7_BW250 = 6, - /** - * @brief Data rate for region EU868 using FSK and 50 kpbs. - */ - TTN_DR_EU868_FSK = 7, + typedef enum + { + /** + * @brief Outside RX/TX window + */ + TTN_WINDOW_IDLE = 0, + /** + * @brief Transmission window (up to RX1 window) + */ + TTN_WINDOW_TX = 1, + /** + * @brief Reception window 1 (up to RX2 window) + */ + TTN_WINDOW_RX1 = 2, + /** + * @brief Reception window 2 + */ + TTN_WINDOW_RX2 = 3 + } ttn_rx_tx_window_t; /** - * @brief Data rate for region IN866 using SF12 and 125 kHz bandwidth. + * @brief Spreading Factor */ - TTN_DR_IN866_SF12 = 0, - /** - * @brief Data rate for region IN866 using SF11 and 125 kHz bandwidth. - */ - TTN_DR_IN866_SF11 = 1, - /** - * @brief Data rate for region IN866 using SF10 and 125 kHz bandwidth. - */ - TTN_DR_IN866_SF10 = 2, - /** - * @brief Data rate for region IN866 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_IN866_SF9 = 3, - /** - * @brief Data rate for region IN866 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_IN866_SF8 = 4, - /** - * @brief Data rate for region IN866 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_IN866_SF7 = 5, - /** - * @brief Data rate for region IN866 using FSK and 50 kpbs. - */ - TTN_DR_IN866_FSK = 7, + typedef enum + { + /** + * @brief Unused / undefined spreading factor + */ + TTN_SF_NONE = 0, + /** + * @brief Frequency Shift Keying (FSK) + */ + TTN_FSK = 1, + /** + * @brief Spreading Factor 7 (SF7) + */ + TTN_SF7 = 2, + /** + * @brief Spreading Factor 8 (SF8) + */ + TTN_SF8 = 3, + /** + * @brief Spreading Factor 9 (SF9) + */ + TTN_SF9 = 4, + /** + * @brief Spreading Factor 10 (SF10) + */ + TTN_SF10 = 5, + /** + * @brief Spreading Factor 11 (SF11) + */ + TTN_SF11 = 6, + /** + * @brief Spreading Factor 12 (SF12) + */ + TTN_SF12 = 7 + } ttn_spreading_factor_t; /** - * @brief Data rate for region KR920 using SF12 and 125 kHz bandwidth. + * @brief Bandwidth */ - TTN_DR_KR920_SF12 = 0, - /** - * @brief Data rate for region KR920 using SF11 and 125 kHz bandwidth. - */ - TTN_DR_KR920_SF11 = 1, - /** - * @brief Data rate for region KR920 using SF10 and 125 kHz bandwidth. - */ - TTN_DR_KR920_SF10 = 2, - /** - * @brief Data rate for region KR920 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_KR920_SF9 = 3, - /** - * @brief Data rate for region KR920 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_KR920_SF8 = 4, - /** - * @brief Data rate for region KR920 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_KR920_SF7 = 5, + typedef enum + { + /** + * @brief Undefined/unused bandwidth + */ + TTN_BW_NONE = 0, + /** + * @brief Bandwidth of 125 kHz + */ + TTN_BW_125 = 1, + /** + * @brief Bandwidth of 250 kHz + */ + TTN_BW_250 = 2, + /** + * @brief Bandwidth of 500 kHz + */ + TTN_BW_500 = 3 + } ttn_bandwidth_t; /** - * @brief Data rate for region US915 using SF10 and 125 kHz bandwidth. + * @brief Data Rate + * + * Note that the spreading factor, bandwidth, bit rate and maximum message + * size associated with each data rate depends on the region. */ - TTN_DR_US915_SF10 = 0, - /** - * @brief Data rate for region US915 using SF9 and 125 kHz bandwidth. - */ - TTN_DR_US915_SF9 = 1, - /** - * @brief Data rate for region US915 using SF8 and 125 kHz bandwidth. - */ - TTN_DR_US915_SF8 = 2, - /** - * @brief Data rate for region US915 using SF7 and 125 kHz bandwidth. - */ - TTN_DR_US915_SF7 = 3, - /** - * @brief Data rate for region US915 using SF8 and 500 kHz bandwidth. - */ - TTN_DR_US915_SF8_BW500 = 4, - /** - * @brief Data rate for region US915 using SF12 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF12_BW500 = 8, - /** - * @brief Data rate for region US915 using SF11 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF11_BW500 = 9, - /** - * @brief Data rate for region US915 using SF10 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF10_BW500 = 10, - /** - * @brief Data rate for region US915 using SF9 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF9_BW500 = 11, - /** - * @brief Data rate for region US915 using SF8 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF8_BW500_DR12 = 12, - /** - * @brief Data rate for region US915 using SF7 and 500 kHz bandwidth. - * - * Reserved for future applications. - */ - TTN_DR_US915_SF7_BW500 = 13, + typedef enum + { + /** + * @brief Data rate for region AS923 using SF12 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF12 = 0, + /** + * @brief Data rate for region AS923 using SF11 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF11 = 1, + /** + * @brief Data rate for region AS923 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF10 = 2, + /** + * @brief Data rate for region AS923 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF9 = 3, + /** + * @brief Data rate for region AS923 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF8 = 4, + /** + * @brief Data rate for region AS923 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_AS923_SF7_BW125 = 5, + /** + * @brief Data rate for region AS923 using SF7 and 250 kHz bandwidth. + */ + TTN_DR_AS923_SF7_BW250 = 6, + /** + * @brief Data rate for region AS923 using FSK and 50 kpbs. + */ + TTN_DR_AS923_FSK = 7, + + /** + * @brief Data rate for region AU915 using SF12 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF12 = 0, + /** + * @brief Data rate for region AU915 using SF11 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF11 = 1, + /** + * @brief Data rate for region AU915 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF10 = 2, + /** + * @brief Data rate for region AU915 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF9 = 3, + /** + * @brief Data rate for region AU915 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF8 = 4, + /** + * @brief Data rate for region AU915 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_AU915_SF7 = 5, + /** + * @brief Data rate for region AU915 using SF8 and 500 kHz bandwidth. + */ + TTN_DR_AU915_SF8_BW500 = 6, + /** + * @brief Data rate for region AU915 using SF12 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF12_BW500 = 8, + /** + * @brief Data rate for region AU915 using SF11 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF11_BW500 = 9, + /** + * @brief Data rate for region AU915 using SF10 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF10_BW500 = 10, + /** + * @brief Data rate for region AU915 using SF9 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF9_BW500 = 11, + /** + * @brief Data rate for region AU915 using SF8 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF8_BW500_DR12 = 12, + /** + * @brief Data rate for region AU915 using SF7 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_AU915_SF7_BW500 = 13, + + /** + * @brief Data rate for region EU868 using SF12 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF12 = 0, + /** + * @brief Data rate for region EU868 using SF11 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF11 = 1, + /** + * @brief Data rate for region EU868 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF10 = 2, + /** + * @brief Data rate for region EU868 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF9 = 3, + /** + * @brief Data rate for region EU868 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF8 = 4, + /** + * @brief Data rate for region EU868 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_EU868_SF7_BW125 = 5, + /** + * @brief Data rate for region EU868 using SF7 and 250 kHz bandwidth. + */ + TTN_DR_EU868_SF7_BW250 = 6, + /** + * @brief Data rate for region EU868 using FSK and 50 kpbs. + */ + TTN_DR_EU868_FSK = 7, + + /** + * @brief Data rate for region IN866 using SF12 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF12 = 0, + /** + * @brief Data rate for region IN866 using SF11 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF11 = 1, + /** + * @brief Data rate for region IN866 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF10 = 2, + /** + * @brief Data rate for region IN866 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF9 = 3, + /** + * @brief Data rate for region IN866 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF8 = 4, + /** + * @brief Data rate for region IN866 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_IN866_SF7 = 5, + /** + * @brief Data rate for region IN866 using FSK and 50 kpbs. + */ + TTN_DR_IN866_FSK = 7, + + /** + * @brief Data rate for region KR920 using SF12 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF12 = 0, + /** + * @brief Data rate for region KR920 using SF11 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF11 = 1, + /** + * @brief Data rate for region KR920 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF10 = 2, + /** + * @brief Data rate for region KR920 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF9 = 3, + /** + * @brief Data rate for region KR920 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF8 = 4, + /** + * @brief Data rate for region KR920 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_KR920_SF7 = 5, + + /** + * @brief Data rate for region US915 using SF10 and 125 kHz bandwidth. + */ + TTN_DR_US915_SF10 = 0, + /** + * @brief Data rate for region US915 using SF9 and 125 kHz bandwidth. + */ + TTN_DR_US915_SF9 = 1, + /** + * @brief Data rate for region US915 using SF8 and 125 kHz bandwidth. + */ + TTN_DR_US915_SF8 = 2, + /** + * @brief Data rate for region US915 using SF7 and 125 kHz bandwidth. + */ + TTN_DR_US915_SF7 = 3, + /** + * @brief Data rate for region US915 using SF8 and 500 kHz bandwidth. + */ + TTN_DR_US915_SF8_BW500 = 4, + /** + * @brief Data rate for region US915 using SF12 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF12_BW500 = 8, + /** + * @brief Data rate for region US915 using SF11 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF11_BW500 = 9, + /** + * @brief Data rate for region US915 using SF10 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF10_BW500 = 10, + /** + * @brief Data rate for region US915 using SF9 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF9_BW500 = 11, + /** + * @brief Data rate for region US915 using SF8 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF8_BW500_DR12 = 12, + /** + * @brief Data rate for region US915 using SF7 and 500 kHz bandwidth. + * + * Reserved for future applications. + */ + TTN_DR_US915_SF7_BW500 = 13, + + /** + * @brief Default data rate for joining. + */ + TTN_DR_JOIN_DEFAULT = 255 + } ttn_data_rate_t; /** - * @brief Default data rate for joining. + * @brief RF settings for TX or RX */ - TTN_DR_JOIN_DEFAULT = 255 -} ttn_data_rate_t; + typedef struct + { + /** + * @brief Spreading Factor (SF) + */ + ttn_spreading_factor_t spreading_factor; + /** + * @brief Bandwidth (BW) + */ + ttn_bandwidth_t bandwidth; + /** + * @brief Frequency, in Hz + */ + uint32_t frequency; + } ttn_rf_settings_t; - -/** - * @brief RF settings for TX or RX - */ -typedef struct -{ /** - * @brief Spreading Factor (SF) + * @brief Callback for recieved messages + * + * @param payload pointer to the received bytes + * @param length number of received bytes + * @param port port the message was received on */ - ttn_spreading_factor_t spreading_factor; + typedef void (*ttn_message_cb)(const uint8_t *payload, size_t length, ttn_port_t port); + /** - * @brief Bandwidth (BW) + * @brief Initializes The Things Network device instance. + * + * Call this function once at the start of the program and before all other TTN functions. */ - ttn_bandwidth_t bandwidth; + void ttn_init(void); + /** - * @brief Frequency, in Hz + * @brief Resets the LoRaWAN radio. + * + * To restart communication, @ref ttn_join() or @ref ttn_join_provisioned() must be called. + * It neither clears the provisioned keys nor the configured pins. */ - uint32_t frequency; -} ttn_rf_settings_t; + void ttn_reset(void); + /** + * @brief Configures the pins used to communicate with the LoRaWAN radio chip. + * + * Before calling this member function, the SPI bus needs to be configured using `spi_bus_initialize()`. + * Additionally, `gpio_install_isr_service()` must have been called to initialize the GPIO ISR handler service. + * + * @param spi_host The SPI bus/peripherial to use (`SPI_HOST`, `HSPI_HOST` or `VSPI_HOST`). + * @param nss The GPIO pin number connected to the radio chip's NSS pin (serving as the SPI chip select) + * @param rxtx The GPIO pin number connected to the radio chip's RXTX pin (@ref TTN_NOT_CONNECTED if not + * connected) + * @param rst The GPIO pin number connected to the radio chip's RST pin (@ref TTN_NOT_CONNECTED if not + * connected) + * @param dio0 The GPIO pin number connected to the radio chip's DIO0 pin + * @param dio1 The GPIO pin number connected to the radio chip's DIO1 pin + */ + void ttn_configure_pins(spi_host_device_t spi_host, uint8_t nss, uint8_t rxtx, uint8_t rst, uint8_t dio0, + uint8_t dio1); -/** - * @brief Callback for recieved messages - * - * @param payload pointer to the received bytes - * @param length number of received bytes - * @param port port the message was received on - */ -typedef void (*ttn_message_cb)(const uint8_t* payload, size_t length, ttn_port_t port); + /** + * @brief Sets the frequency sub-band to be used. + * + * For regions with sub-bands (USA, Australia), sets the sub-band to be used for uplink communication. + * For other regions, this function has no effect. + * + * The sub-band must be set before joining or sending the first message. + * + * If not set, it defaults to sub-band 2 as defined by TTN. + * + * @param band band (0 for all bands, or value between 1 and 8) + */ + void ttn_set_subband(int band); + /** + * @brief Sets the credentials needed to activate the device via OTAA, without activating it. + * + * The provided DevEUI, AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before + * this function is called, `nvs_flash_init()` must have been called once. + * + * Call @ref ttn_join_provisioned() to activate the device. + * + * @param dev_eui DevEUI (16 character string with hexadecimal data) + * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) + * @param app_key AppKey of the device (32 character string with hexadecimal data) + * @return `true` if the provisioning was successful, `false` if the provisioning failed + */ + bool ttn_provision(const char *dev_eui, const char *app_eui, const char *app_key); -/** - * @brief Initializes The Things Network device instance. - * - * Call this function once at the start of the program and before all other TTN functions. - */ -void ttn_init(void); + /** + * @brief Sets the information needed to activate the device via OTAA, using the MAC to generate the DevEUI + * and without activating it. + * + * The generated DevEUI and the provided AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before + * this function is called, `nvs_flash_init` must have been called once. + * + * The DevEUI is generated by retrieving the ESP32's WiFi MAC address and expanding it into a DevEUI + * by adding FFFE in the middle. So the MAC address A0:B1:C2:01:02:03 becomes the EUI A0B1C2FFFE010203. + * This hexadecimal data can be entered into the DevEUI field in the TTN console. + * + * Generating the DevEUI from the MAC address allows to flash the same AppEUI/JoinEUI and AppKey to a batch of + * devices. However, using the same AppKey for multiple devices is insecure. Only use this approach if + * it is okay for that the LoRa communication of your application can easily be intercepted and that + * forged data can be injected. + * + * Call @ref ttn_join_provisioned() to activate. + * + * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) + * @param app_key AppKey of the device (32 character string with hexadecimal data) + * @return `true` if the provisioning was successful, `false` if the provisioning failed + */ + bool ttn_provision_with_mac(const char *app_eui, const char *app_key); -/** - * @brief Resets the LoRaWAN radio. - * - * To restart communication, @ref ttn_join() or @ref ttn_join_provisioned() must be called. - * It neither clears the provisioned keys nor the configured pins. - */ -void ttn_reset(void); + /** + * @brief Starts task listening on configured UART for AT commands. + * + * Run `make menuconfig` to configure it. + */ + void ttn_start_provisioning_task(void); -/** - * @brief Configures the pins used to communicate with the LoRaWAN radio chip. - * - * Before calling this member function, the SPI bus needs to be configured using `spi_bus_initialize()`. - * Additionally, `gpio_install_isr_service()` must have been called to initialize the GPIO ISR handler service. - * - * @param spi_host The SPI bus/peripherial to use (`SPI_HOST`, `HSPI_HOST` or `VSPI_HOST`). - * @param nss The GPIO pin number connected to the radio chip's NSS pin (serving as the SPI chip select) - * @param rxtx The GPIO pin number connected to the radio chip's RXTX pin (@ref TTN_NOT_CONNECTED if not connected) - * @param rst The GPIO pin number connected to the radio chip's RST pin (@ref TTN_NOT_CONNECTED if not connected) - * @param dio0 The GPIO pin number connected to the radio chip's DIO0 pin - * @param dio1 The GPIO pin number connected to the radio chip's DIO1 pin - */ -void ttn_configure_pins(spi_host_device_t spi_host, uint8_t nss, uint8_t rxtx, uint8_t rst, uint8_t dio0, uint8_t dio1); + /** + * @brief Waits until the DevEUI, AppEUI/JoinEUI and AppKey have been provisioned + * by the provisioning task. + * + * If the device has already been provisioned (stored data in NVS, call of provision() + * or call of @ref ttn_join(), this function immediately returns. + */ + void ttn_wait_for_provisioning(void); -/** - * @brief Sets the frequency sub-band to be used. - * - * For regions with sub-bands (USA, Australia), sets the sub-band to be used for uplink communication. - * For other regions, this function has no effect. - * - * The sub-band must be set before joining or sending the first message. - * - * If not set, it defaults to sub-band 2 as defined by TTN. - * - * @param band band (0 for all bands, or value between 1 and 8) - */ -void ttn_set_subband(int band); + /** + * @brief Activates the device via OTAA. + * + * The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call to provision(). + * Before this function is called, `nvs_flash_init()` must have been called once. + * + * The function blocks until the activation has completed or failed. + * + * @return `true` if the activation was succesful, `false` if the activation failed + */ + bool ttn_join_provisioned(void); -/** - * @brief Sets the credentials needed to activate the device via OTAA, without activating it. - * - * The provided DevEUI, AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before - * this function is called, `nvs_flash_init()` must have been called once. - * - * Call @ref ttn_join_provisioned() to activate the device. - * - * @param dev_eui DevEUI (16 character string with hexadecimal data) - * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) - * @param app_key AppKey of the device (32 character string with hexadecimal data) - * @return `true` if the provisioning was successful, `false` if the provisioning failed - */ -bool ttn_provision(const char *dev_eui, const char *app_eui, const char *app_key); + /** + * @brief Sets the DevEUI, AppEUI/JoinEUI and AppKey and activate the device via OTAA. + * + * The DevEUI, AppEUI/JoinEUI and AppKey are NOT saved in non-volatile memory. + * + * The function blocks until the activation has completed or failed. + * + * @param dev_eui DevEUI (16 character string with hexadecimal data) + * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) + * @param app_key AppKey of the device (32 character string with hexadecimal data) + * @return `true` if the activation was succesful, `false` if the activation failed + */ + bool ttn_join(const char *dev_eui, const char *app_eui, const char *app_key); -/** - * @brief Sets the information needed to activate the device via OTAA, using the MAC to generate the DevEUI - * and without activating it. - * - * The generated DevEUI and the provided AppEUI/JoinEUI and AppKey are saved in non-volatile memory. Before - * this function is called, `nvs_flash_init` must have been called once. - * - * The DevEUI is generated by retrieving the ESP32's WiFi MAC address and expanding it into a DevEUI - * by adding FFFE in the middle. So the MAC address A0:B1:C2:01:02:03 becomes the EUI A0B1C2FFFE010203. - * This hexadecimal data can be entered into the DevEUI field in the TTN console. - * - * Generating the DevEUI from the MAC address allows to flash the same AppEUI/JoinEUI and AppKey to a batch of - * devices. However, using the same AppKey for multiple devices is insecure. Only use this approach if - * it is okay for that the LoRa communication of your application can easily be intercepted and that - * forged data can be injected. - * - * Call @ref ttn_join_provisioned() to activate. - * - * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) - * @param app_key AppKey of the device (32 character string with hexadecimal data) - * @return `true` if the provisioning was successful, `false` if the provisioning failed - */ -bool ttn_provision_with_mac(const char *app_eui, const char *app_key); + /** + * @brief Transmits a message + * + * The function blocks until the message could be transmitted and a message has been received + * in the subsequent receive window (or the window expires). Additionally, the function will + * first wait until the duty cycle allows a transmission (enforcing the duty cycle limits). + * + * @param payload bytes to be transmitted + * @param length number of bytes to be transmitted + * @param port port (use 1 as default) + * @param confirm flag indicating if a confirmation should be requested (use `false` as default) + * @return @ref TTN_SUCCESSFUL_TRANSMISSION for successful transmission, @ref TTN_ERROR_TRANSMISSION_FAILED for + * failed transmission, @ref TTN_ERROR_UNEXPECTED for unexpected error + */ + ttn_response_code_t ttn_transmit_message(const uint8_t *payload, size_t length, ttn_port_t port, bool confirm); -/** - * @brief Starts task listening on configured UART for AT commands. - * - * Run `make menuconfig` to configure it. - */ -void ttn_start_provisioning_task(void); + /** + * @brief Sets the function to be called when a message is received + * + * When a message is received, the specified function is called. The + * message, its length and the port number are provided as + * parameters. The values are only valid during the duration of the + * callback. So they must be immediately processed or copied. + * + * Messages are received as a result of @ref ttn_transmit_message(). The callback is called + * in the task that called this function and it occurs before this function + * returns control to the caller. + * + * @param callback the callback function + */ + void ttn_on_message(ttn_message_cb callback); -/** - * @brief Waits until the DevEUI, AppEUI/JoinEUI and AppKey have been provisioned - * by the provisioning task. - * - * If the device has already been provisioned (stored data in NVS, call of provision() - * or call of @ref ttn_join(), this function immediately returns. - */ -void ttn_wait_for_provisioning(void); + /** + * @brief Checks if DevEUI, AppEUI/JoinEUI and AppKey have been stored in non-volatile storage + * or have been provided as by a call to @ref ttn_join(). + * + * @return `true` if they are stored, complete and of the correct size, `false` otherwise + */ + bool ttn_is_provisioned(void); -/** - * @brief Activates the device via OTAA. - * - * The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call to provision(). - * Before this function is called, `nvs_flash_init()` must have been called once. - * - * The function blocks until the activation has completed or failed. - * - * @return `true` if the activation was succesful, `false` if the activation failed - */ -bool ttn_join_provisioned(void); + /** + * @brief Sets the RSSI calibration value for LBT (Listen Before Talk). + * + * This value is added to RSSI measured prior to decision. It must include the guardband. + * Ignored in US, EU, IN and other countries where LBT is not required. + * Defaults to 10 dB. + * + * @param rssi_cal RSSI calibration value, in dB + */ + void ttn_set_rssi_cal(int8_t rssi_cal); -/** - * @brief Sets the DevEUI, AppEUI/JoinEUI and AppKey and activate the device via OTAA. - * - * The DevEUI, AppEUI/JoinEUI and AppKey are NOT saved in non-volatile memory. - * - * The function blocks until the activation has completed or failed. - * - * @param dev_eui DevEUI (16 character string with hexadecimal data) - * @param app_eui AppEUI/JoinEUI of the device (16 character string with hexadecimal data) - * @param app_key AppKey of the device (32 character string with hexadecimal data) - * @return `true` if the activation was succesful, `false` if the activation failed - */ -bool ttn_join(const char *dev_eui, const char *app_eui, const char *app_key); + /** + * Returns whether Adaptive Data Rate (ADR) is enabled. + * + * @return `true` if enabled, `false` if disabled + */ + bool ttn_adr_enabled(void); -/** - * @brief Transmits a message - * - * The function blocks until the message could be transmitted and a message has been received - * in the subsequent receive window (or the window expires). Additionally, the function will - * first wait until the duty cycle allows a transmission (enforcing the duty cycle limits). - * - * @param payload bytes to be transmitted - * @param length number of bytes to be transmitted - * @param port port (use 1 as default) - * @param confirm flag indicating if a confirmation should be requested (use `false` as default) - * @return @ref TTN_SUCCESSFUL_TRANSMISSION for successful transmission, @ref TTN_ERROR_TRANSMISSION_FAILED for failed transmission, @ref TTN_ERROR_UNEXPECTED for unexpected error - */ -ttn_response_code_t ttn_transmit_message(const uint8_t *payload, size_t length, ttn_port_t port, bool confirm); + /** + * @brief Enables or disabled Adaptive Data Rate (ADR). + * + * ADR is enabled by default. It optimizes data rate, airtime and energy consumption + * for devices with stable RF conditions. It should be turned off for mobile devices. + * + * @param enabled `true` to enable, `false` to disable + */ + void ttn_set_adr_enabled(bool enabled); -/** - * @brief Sets the function to be called when a message is received - * - * When a message is received, the specified function is called. The - * message, its length and the port number are provided as - * parameters. The values are only valid during the duration of the - * callback. So they must be immediately processed or copied. - * - * Messages are received as a result of @ref ttn_transmit_message(). The callback is called - * in the task that called this function and it occurs before this function - * returns control to the caller. - * - * @param callback the callback function - */ -void ttn_on_message(ttn_message_cb callback); + /** + * @brief Sets the transmission data rate (i.e. the data rate for uplink messages). + * + * If ADR is enabled, it's is used as the initial data rate and later adjusted depending + * on the RF conditions. If ADR is disabled, it is used for all uplink messages. + * + * @param data_rate data rate (use constants of enum @ref ttn_data_rate_t) + */ + void ttn_set_data_rate(ttn_data_rate_t data_rate); -/** - * @brief Checks if DevEUI, AppEUI/JoinEUI and AppKey have been stored in non-volatile storage - * or have been provided as by a call to @ref ttn_join(). - * - * @return `true` if they are stored, complete and of the correct size, `false` otherwise - */ -bool ttn_is_provisioned(void); + /** + * @brief Sets the maximum power for transmission + * + * The power is specified in dBm and sets the power emitted by the radio. + * If the antenna has a gain, it must be substracted from the specified value to + * achieve the correct transmission power. + * + * @param tx_pow power, in dBm + */ + void ttn_set_max_tx_pow(int tx_pow); -/** - * @brief Sets the RSSI calibration value for LBT (Listen Before Talk). - * - * This value is added to RSSI measured prior to decision. It must include the guardband. - * Ignored in US, EU, IN and other countries where LBT is not required. - * Defaults to 10 dB. - * - * @param rssi_cal RSSI calibration value, in dB - */ -void ttn_set_rssi_cal(int8_t rssi_cal); + /** + * @brief Stops all activies and shuts down the RF module and the background tasks. + * + * To restart communication, @ref ttn_startup() and @ref ttn_join() must be called. + * it neither clears the provisioned keys nor the configured pins. + */ + void ttn_shutdown(void); -/** - * Returns whether Adaptive Data Rate (ADR) is enabled. - * - * @return `true` if enabled, `false` if disabled - */ -bool ttn_adr_enabled(void); + /** + * @brief Restarts the background tasks and RF module. + * + * This member function must only be called after a call to shutdowna(). + */ + void ttn_startup(void); -/** - * @brief Enables or disabled Adaptive Data Rate (ADR). - * - * ADR is enabled by default. It optimizes data rate, airtime and energy consumption - * for devices with stable RF conditions. It should be turned off for mobile devices. - * - * @param enabled `true` to enable, `false` to disable - */ -void ttn_set_adr_enabled(bool enabled); + /** + * @brief Gets current RX/TX window + * @return window + */ + ttn_rx_tx_window_t ttn_rx_tx_window(void); -/** - * @brief Sets the transmission data rate (i.e. the data rate for uplink messages). - * - * If ADR is enabled, it's is used as the initial data rate and later adjusted depending - * on the RF conditions. If ADR is disabled, it is used for all uplink messages. - * - * @param data_rate data rate (use constants of enum @ref ttn_data_rate_t) - */ -void ttn_set_data_rate(ttn_data_rate_t data_rate); + /** + * @brief Gets the RF settings for the specified window + * @param window RX/TX window (valid values are @ref TTN_WINDOW_TX, @ref TTN_WINDOW_RX1 and @ref TTN_WINDOW_RX2 + */ + ttn_rf_settings_t ttn_get_rf_settings(ttn_rx_tx_window_t window); -/** - * @brief Sets the maximum power for transmission - * - * The power is specified in dBm and sets the power emitted by the radio. - * If the antenna has a gain, it must be substracted from the specified value to - * achieve the correct transmission power. - * - * @param tx_pow power, in dBm - */ -void ttn_set_max_tx_pow(int tx_pow); + /** + * @brief Gets the RF settings of the last (or ongoing) transmission. + * @return RF settings + */ + ttn_rf_settings_t ttn_tx_settings(void); -/** - * @brief Stops all activies and shuts down the RF module and the background tasks. - * - * To restart communication, @ref ttn_startup() and @ref ttn_join() must be called. - * it neither clears the provisioned keys nor the configured pins. - */ -void ttn_shutdown(void); + /** + * @brief Gets the RF settings of the last (or ongoing) reception of RX window 1. + * @return RF settings + */ + ttn_rf_settings_t ttn_rx1_settings(void); -/** - * @brief Restarts the background tasks and RF module. - * - * This member function must only be called after a call to shutdowna(). - */ -void ttn_startup(void); + /** + * @brief Gets the RF settings of the last (or ongoing) reception of RX window 2. + * @return RF settings + */ + ttn_rf_settings_t ttn_rx2_settings(void); -/** - * @brief Gets current RX/TX window - * @return window - */ -ttn_rx_tx_window_t ttn_rx_tx_window(void); - -/** - * @brief Gets the RF settings for the specified window - * @param window RX/TX window (valid values are @ref TTN_WINDOW_TX, @ref TTN_WINDOW_RX1 and @ref TTN_WINDOW_RX2 - */ -ttn_rf_settings_t ttn_get_rf_settings(ttn_rx_tx_window_t window); - -/** - * @brief Gets the RF settings of the last (or ongoing) transmission. - * @return RF settings - */ -ttn_rf_settings_t ttn_tx_settings(void); - -/** - * @brief Gets the RF settings of the last (or ongoing) reception of RX window 1. - * @return RF settings - */ -ttn_rf_settings_t ttn_rx1_settings(void); - -/** - * @brief Gets the RF settings of the last (or ongoing) reception of RX window 2. - * @return RF settings - */ -ttn_rf_settings_t ttn_rx2_settings(void); - -/** - * @brief Gets the received signal strength indicator (RSSI). - * - * RSSI is the measured signal strength of the last recevied message (incl. join responses). - * - * @return RSSI, in dBm - */ -int ttn_rssi(); - - -/** - * @} - */ + /** + * @brief Gets the received signal strength indicator (RSSI). + * + * RSSI is the measured signal strength of the last recevied message (incl. join responses). + * + * @return RSSI, in dBm + */ + int ttn_rssi(); + /** + * @} + */ #ifdef __cplusplus } #endif - #endif diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index bfdfe61..1796a56 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -12,7 +12,6 @@ #include "TheThingsNetwork.h" - TTNRFSettings TheThingsNetwork::getRFSettings(TTNRxTxWindow window) { ttn_rf_settings_t settings = ttn_get_rf_settings(static_cast(window)); diff --git a/src/esp_idf_lmic_config.h b/src/esp_idf_lmic_config.h index d21a5fb..ee65f1f 100755 --- a/src/esp_idf_lmic_config.h +++ b/src/esp_idf_lmic_config.h @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -17,7 +17,8 @@ #elif defined(CONFIG_TTN_LORA_FREQ_US_915) #define CFG_us915 1 #elif defined(CONFIG_TTN_LORA_FREQ_AU_921) -# warning "CONFIG_TTN_LORA_FREQ_AU_921 was deprecated in favour of CONFIG_TTN_LORA_FREQ_AU_921. Support for CONFIG_TTN_LORA_FREQ_AU_921 will be removed in the future." +#warning \ + "CONFIG_TTN_LORA_FREQ_AU_921 was deprecated in favour of CONFIG_TTN_LORA_FREQ_AU_921. Support for CONFIG_TTN_LORA_FREQ_AU_921 will be removed in the future." #define CFG_au915 1 #elif defined(CONFIG_TTN_LORA_FREQ_AU_915) #define CFG_au915 1 @@ -50,7 +51,6 @@ #endif #endif - // 16 μs per tick // LMIC requires ticks to be 15.5μs - 100 μs long #define US_PER_OSTICK 16 diff --git a/src/ttn.c b/src/ttn.c index 02ed365..eecfa12 100644 --- a/src/ttn.c +++ b/src/ttn.c @@ -1,24 +1,23 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * * High-level C API for ttn-esp32. *******************************************************************************/ -#include "lmic/lmic.h" #include "ttn.h" -#include "ttn_provisioning.h" -#include "ttn_logging.h" -#include "hal/hal_esp32.h" -#include "freertos/FreeRTOS.h" #include "esp_event.h" #include "esp_log.h" - +#include "freertos/FreeRTOS.h" +#include "hal/hal_esp32.h" +#include "lmic/lmic.h" +#include "ttn_logging.h" +#include "ttn_provisioning.h" #define TAG "ttn" @@ -37,7 +36,8 @@ typedef enum /** * @brief Event type */ -typedef enum { +typedef enum +{ TTN_EVENT_NONE, TTN_EVNT_JOIN_COMPLETED, TTN_EVENT_JOIN_FAILED, @@ -49,10 +49,11 @@ typedef enum { /** * @brief Event message sent from LMIC task to waiting client task */ -typedef struct { +typedef struct +{ ttn_event_t event; uint8_t port; - const uint8_t* message; + const uint8_t *message; size_t message_size; } ttn_lmic_event_t; @@ -68,12 +69,11 @@ static int max_tx_power = DEFAULT_MAX_TX_POWER; static bool join_core(void); static void config_rf_params(void); -static void event_callback(void* user_data, ev_t event); +static void event_callback(void *user_data, ev_t event); static void message_received_callback(void *user_data, uint8_t port, const uint8_t *message, size_t message_size); static void message_transmitted_callback(void *user_data, int success); -static void save_rf_settings(ttn_rf_settings_t* rf_settings); -static void clear_rf_settings(ttn_rf_settings_t* rf_settings); - +static void save_rf_settings(ttn_rf_settings_t *rf_settings); +static void clear_rf_settings(ttn_rf_settings_t *rf_settings); void ttn_init(void) { @@ -140,7 +140,7 @@ bool ttn_provision(const char *dev_eui, const char *app_eui, const char *app_key { if (!ttn_provisioning_decode_keys(dev_eui, app_eui, app_key)) return false; - + return ttn_provisioning_save_keys(); } @@ -148,11 +148,10 @@ bool ttn_provision_with_mac(const char *app_eui, const char *app_key) { if (!ttn_provisioning_from_mac(app_eui, app_key)) return false; - + return ttn_provisioning_save_keys(); } - void ttn_start_provisioning_task(void) { #if defined(TTN_HAS_AT_COMMANDS) @@ -188,7 +187,7 @@ bool ttn_join(const char *dev_eui, const char *app_eui, const char *app_key) { if (!ttn_provisioning_decode_keys(dev_eui, app_eui, app_key)) return false; - + return join_core(); } @@ -267,19 +266,19 @@ ttn_response_code_t ttn_transmit_message(const uint8_t *payload, size_t length, switch (result.event) { - case TTN_EVENT_MESSAGE_RECEIVED: - if (message_callback != NULL) - message_callback(result.message, result.message_size, result.port); - break; + case TTN_EVENT_MESSAGE_RECEIVED: + if (message_callback != NULL) + message_callback(result.message, result.message_size, result.port); + break; - case TTN_EVENT_TRANSMISSION_COMPLETED: - return TTN_SUCCESSFUL_TRANSMISSION; + case TTN_EVENT_TRANSMISSION_COMPLETED: + return TTN_SUCCESSFUL_TRANSMISSION; - case TTN_EVENT_TRANSMISSION_FAILED: - return TTN_ERROR_TRANSMISSION_FAILED; + case TTN_EVENT_TRANSMISSION_FAILED: + return TTN_ERROR_TRANSMISSION_FAILED; - default: - ASSERT(0); + default: + ASSERT(0); } } } @@ -289,12 +288,11 @@ void ttn_on_message(ttn_message_cb callback) message_callback = callback; } - bool ttn_is_provisioned(void) { if (ttn_provisioning_have_keys()) return true; - + ttn_provisioning_restore_keys(true); return ttn_provisioning_have_keys(); @@ -376,43 +374,41 @@ int ttn_rssi(void) return LMIC.rssi; } - // --- Callbacks --- #if CONFIG_LOG_DEFAULT_LEVEL >= 3 || LMIC_ENABLE_event_logging -static const char *event_names[] = { LMIC_EVENT_NAME_TABLE__INIT }; +static const char *event_names[] = {LMIC_EVENT_NAME_TABLE__INIT}; #endif - // Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs -void event_callback(void* user_data, ev_t event) +void event_callback(void *user_data, ev_t event) { // update monitoring information - switch(event) + switch (event) { - case EV_TXSTART: - current_rx_tx_window = TTN_WINDOW_TX; - save_rf_settings(&last_rf_settings[TTN_WINDOW_TX]); - clear_rf_settings(&last_rf_settings[TTN_WINDOW_RX1]); - clear_rf_settings(&last_rf_settings[TTN_WINDOW_RX2]); - break; + case EV_TXSTART: + current_rx_tx_window = TTN_WINDOW_TX; + save_rf_settings(&last_rf_settings[TTN_WINDOW_TX]); + clear_rf_settings(&last_rf_settings[TTN_WINDOW_RX1]); + clear_rf_settings(&last_rf_settings[TTN_WINDOW_RX2]); + break; - case EV_RXSTART: - if (current_rx_tx_window != TTN_WINDOW_RX1) - { - current_rx_tx_window = TTN_WINDOW_RX1; - save_rf_settings(&last_rf_settings[TTN_WINDOW_RX1]); - } - else - { - current_rx_tx_window = TTN_WINDOW_RX2; - save_rf_settings(&last_rf_settings[TTN_WINDOW_RX2]); - } - break; + case EV_RXSTART: + if (current_rx_tx_window != TTN_WINDOW_RX1) + { + current_rx_tx_window = TTN_WINDOW_RX1; + save_rf_settings(&last_rf_settings[TTN_WINDOW_RX1]); + } + else + { + current_rx_tx_window = TTN_WINDOW_RX2; + save_rf_settings(&last_rf_settings[TTN_WINDOW_RX2]); + } + break; - default: - current_rx_tx_window = TTN_WINDOW_IDLE; - break; + default: + current_rx_tx_window = TTN_WINDOW_IDLE; + break; }; #if LMIC_ENABLE_event_logging @@ -438,9 +434,7 @@ void event_callback(void* user_data, ev_t event) if (ttn_event == TTN_EVENT_NONE) return; - ttn_lmic_event_t result = { - .event = ttn_event - }; + ttn_lmic_event_t result = {.event = ttn_event}; waiting_reason = TTN_WAITING_NONE; xQueueSend(lmic_event_queue, &result, pdMS_TO_TICKS(100)); } @@ -449,11 +443,7 @@ void event_callback(void* user_data, ev_t event) void message_received_callback(void *user_data, uint8_t port, const uint8_t *message, size_t message_size) { ttn_lmic_event_t result = { - .event = TTN_EVENT_MESSAGE_RECEIVED, - .port = port, - .message = message, - .message_size = message_size - }; + .event = TTN_EVENT_MESSAGE_RECEIVED, .port = port, .message = message, .message_size = message_size}; xQueueSend(lmic_event_queue, &result, pdMS_TO_TICKS(100)); } @@ -461,24 +451,20 @@ void message_received_callback(void *user_data, uint8_t port, const uint8_t *mes void message_transmitted_callback(void *user_data, int success) { waiting_reason = TTN_WAITING_NONE; - ttn_lmic_event_t result = { - .event = success ? TTN_EVENT_TRANSMISSION_COMPLETED : TTN_EVENT_TRANSMISSION_FAILED - }; + ttn_lmic_event_t result = {.event = success ? TTN_EVENT_TRANSMISSION_COMPLETED : TTN_EVENT_TRANSMISSION_FAILED}; xQueueSend(lmic_event_queue, &result, pdMS_TO_TICKS(100)); } - // --- Helpers - -void save_rf_settings(ttn_rf_settings_t* rf_settings) +void save_rf_settings(ttn_rf_settings_t *rf_settings) { rf_settings->spreading_factor = (ttn_spreading_factor_t)(getSf(LMIC.rps) + 1); rf_settings->bandwidth = (ttn_bandwidth_t)(getBw(LMIC.rps) + 1); rf_settings->frequency = LMIC.freq; } -void clear_rf_settings(ttn_rf_settings_t* rf_settings) +void clear_rf_settings(ttn_rf_settings_t *rf_settings) { memset(rf_settings, 0, sizeof(*rf_settings)); } diff --git a/src/ttn_logging.c b/src/ttn_logging.c index b6cec5e..d6070fa 100644 --- a/src/ttn_logging.c +++ b/src/ttn_logging.c @@ -1,82 +1,80 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * * Circular buffer for detailed logging without affecting LMIC timing. *******************************************************************************/ - #if LMIC_ENABLE_event_logging #include "ttn_logging.h" +#include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_log.h" #include "lmic/lmic.h" #include - #define NUM_RINGBUF_MSG 50 #define TAG "lmic" - /** * @brief Message structure used in ring buffer - * + * * The structure is sent from the LMIC task to the logging task. */ -typedef struct { - const char* message; - uint32_t datum; - ev_t event; - ostime_t time; - ostime_t txend; - ostime_t globalDutyAvail; - u4_t freq; - u2_t opmode; - u2_t fcntDn; - u2_t fcntUp; - u2_t rxsyms; - rps_t rps; - u1_t txChnl; - u1_t datarate; - u1_t txrxFlags; - u1_t saveIrqFlags; +typedef struct +{ + const char *message; + uint32_t datum; + ev_t event; + ostime_t time; + ostime_t txend; + ostime_t globalDutyAvail; + u4_t freq; + u2_t opmode; + u2_t fcntDn; + u2_t fcntUp; + u2_t rxsyms; + rps_t rps; + u1_t txChnl; + u1_t datarate; + u1_t txrxFlags; + u1_t saveIrqFlags; } TTNLogMessage; -static void loggingTask(void* param); -static void logFatal(const char* const file, const uint16_t line); +static void loggingTask(void *param); +static void logFatal(const char *const file, const uint16_t line); -static void printMessage(TTNLogMessage* log); -static void printFatalError(TTNLogMessage* log); -static void printEvent(TTNLogMessage* log); -static void printEvtJoined(TTNLogMessage* log); -static void printEvtJoinFailed(TTNLogMessage* log); -static void printEvtTxComplete(TTNLogMessage* log); -static void printEvtTxStart(TTNLogMessage* log); -static void printEvtRxStart(TTNLogMessage* log); -static void printEvtJoinTxComplete(TTNLogMessage* log); -static void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep); +static void printMessage(TTNLogMessage *log); +static void printFatalError(TTNLogMessage *log); +static void printEvent(TTNLogMessage *log); +static void printEvtJoined(TTNLogMessage *log); +static void printEvtJoinFailed(TTNLogMessage *log); +static void printEvtTxComplete(TTNLogMessage *log); +static void printEvtTxStart(TTNLogMessage *log); +static void printEvtRxStart(TTNLogMessage *log); +static void printEvtJoinTxComplete(TTNLogMessage *log); +static void bin2hex(const uint8_t *bin, unsigned len, char *buf, char sep); // Constants for formatting LORA values -static const char* const SF_NAMES[] = { "FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SFrfu" }; -static const char* const BW_NAMES[] = { "BW125", "BW250", "BW500", "BWrfu" }; -static const char* const CR_NAMES[] = { "CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8" }; -static const char* const CRC_NAMES[] = { "NoCrc", "Crc" }; +static const char *const SF_NAMES[] = {"FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SFrfu"}; +static const char *const BW_NAMES[] = {"BW125", "BW250", "BW500", "BWrfu"}; +static const char *const CR_NAMES[] = {"CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8"}; +static const char *const CRC_NAMES[] = {"NoCrc", "Crc"}; static RingbufHandle_t ringBuffer; - // Initialize logging void ttn_log_init(void) { ringBuffer = xRingbufferCreate(NUM_RINGBUF_MSG * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT); - if (ringBuffer == NULL) { + if (ringBuffer == NULL) + { ESP_LOGE(TAG, "Failed to create ring buffer"); ASSERT(0); } @@ -86,7 +84,7 @@ void ttn_log_init(void) } // Record a logging event for later output -void ttn_log_event(int event, const char* message, uint32_t datum) +void ttn_log_event(int event, const char *message, uint32_t datum) { if (ringBuffer == NULL) return; @@ -101,8 +99,8 @@ void ttn_log_event(int event, const char* message, uint32_t datum) .event = (ev_t)event, .freq = LMIC.freq, .opmode = LMIC.opmode, - .fcntDn = (u2_t) LMIC.seqnoDn, - .fcntUp = (u2_t) LMIC.seqnoUp, + .fcntDn = (u2_t)LMIC.seqnoDn, + .fcntUp = (u2_t)LMIC.seqnoUp, .rxsyms = LMIC.rxsyms, .rps = LMIC.rps, .txChnl = LMIC.txChnl, @@ -115,7 +113,7 @@ void ttn_log_event(int event, const char* message, uint32_t datum) } // record a fatal event (failed assert) for later output -void logFatal(const char* const file, const uint16_t line) +void logFatal(const char *const file, const uint16_t line) { ttn_log_event(-3, file, line); } @@ -125,7 +123,6 @@ void logFatal(const char* const file, const uint16_t line) void LMICOS_logEvent(const char *pMessage) { ttn_log_event(-1, pMessage, 0); - } // Record an information message with an integer value for later output @@ -135,18 +132,18 @@ void LMICOS_logEventUint32(const char *pMessage, uint32_t datum) ttn_log_event(-2, pMessage, datum); } - // --------------------------------------------------------------------------- // Log output // Tasks that receiveds the recorded messages, formats and outputs them. -void loggingTask(void* param) +void loggingTask(void *param) { RingbufHandle_t ringBuffer = (RingbufHandle_t)param; - while (true) { + while (true) + { size_t size; - TTNLogMessage* log = (TTNLogMessage*) xRingbufferReceive(ringBuffer, &size, portMAX_DELAY); + TTNLogMessage *log = (TTNLogMessage *)xRingbufferReceive(ringBuffer, &size, portMAX_DELAY); if (log == NULL) continue; @@ -156,107 +153,79 @@ void loggingTask(void* param) } } - // Format and output a log message -void printMessage(TTNLogMessage* log) +void printMessage(TTNLogMessage *log) { - switch((int)log->event) + switch ((int)log->event) { - case -1: - ESP_LOGI(TAG, "%u (%d ms) - %s: opmode=%x", - log->time, osticks2ms(log->time), - log->message, log->opmode - ); - break; + case -1: + ESP_LOGI(TAG, "%u (%d ms) - %s: opmode=%x", log->time, osticks2ms(log->time), log->message, log->opmode); + break; - case -2: - ESP_LOGI(TAG, "%u (%d ms) - %s: datum=0x%x, opmode=%x)", - log->time, osticks2ms(log->time), - log->message, log->datum, log->opmode - ); - break; + case -2: + ESP_LOGI(TAG, "%u (%d ms) - %s: datum=0x%x, opmode=%x)", log->time, osticks2ms(log->time), log->message, + log->datum, log->opmode); + break; - case -3: - printFatalError(log); - break; + case -3: + printFatalError(log); + break; - default: - printEvent(log); - break; + default: + printEvent(log); + break; } } - -void printFatalError(TTNLogMessage* log) +void printFatalError(TTNLogMessage *log) { - ESP_LOGE(TAG, "%u (%d ms) - %s, %d", - log->time, osticks2ms(log->time), - log->message, log->datum - ); - ESP_LOGE(TAG, "- freq=%d.%d, txend=%u, avail=%u, ch=%u", - log->freq / 1000000, (log->freq % 1000000) / 100000, - log->txend, log->globalDutyAvail, - (unsigned)log->txChnl - ); + ESP_LOGE(TAG, "%u (%d ms) - %s, %d", log->time, osticks2ms(log->time), log->message, log->datum); + ESP_LOGE(TAG, "- freq=%d.%d, txend=%u, avail=%u, ch=%u", log->freq / 1000000, (log->freq % 1000000) / 100000, + log->txend, log->globalDutyAvail, (unsigned)log->txChnl); rps_t rps = log->rps; - ESP_LOGE(TAG, "- rps=0x%02x (%s, %s, %s, %s, IH=%d)", - rps, - SF_NAMES[getSf(rps)], - BW_NAMES[getBw(rps)], - CR_NAMES[getCr(rps)], - CRC_NAMES[getNocrc(rps)], - getIh(rps) - ); - ESP_LOGE(TAG, "- opmode=%x, txrxFlags=0x%02x%s, saveIrqFlags=0x%02x", - log->opmode, - log->txrxFlags, - (log->txrxFlags & TXRX_ACK) != 0 ? "; received ack" : "", - log->saveIrqFlags - ); + ESP_LOGE(TAG, "- rps=0x%02x (%s, %s, %s, %s, IH=%d)", rps, SF_NAMES[getSf(rps)], BW_NAMES[getBw(rps)], + CR_NAMES[getCr(rps)], CRC_NAMES[getNocrc(rps)], getIh(rps)); + ESP_LOGE(TAG, "- opmode=%x, txrxFlags=0x%02x%s, saveIrqFlags=0x%02x", log->opmode, log->txrxFlags, + (log->txrxFlags & TXRX_ACK) != 0 ? "; received ack" : "", log->saveIrqFlags); } - -void printEvent(TTNLogMessage* log) +void printEvent(TTNLogMessage *log) { - ESP_LOGI(TAG, "%u (%d ms) - %s", - log->time, osticks2ms(log->time), - log->message - ); + ESP_LOGI(TAG, "%u (%d ms) - %s", log->time, osticks2ms(log->time), log->message); - switch((int)log->event) + switch ((int)log->event) { - case EV_JOINED: - printEvtJoined(log); - break; + case EV_JOINED: + printEvtJoined(log); + break; - case EV_JOIN_FAILED: - printEvtJoinFailed(log); - break; + case EV_JOIN_FAILED: + printEvtJoinFailed(log); + break; - case EV_TXCOMPLETE: - printEvtTxComplete(log); - break; + case EV_TXCOMPLETE: + printEvtTxComplete(log); + break; - case EV_TXSTART: - printEvtTxStart(log); - break; + case EV_TXSTART: + printEvtTxStart(log); + break; - case EV_RXSTART: - printEvtRxStart(log); - break; + case EV_RXSTART: + printEvtRxStart(log); + break; - case EV_JOIN_TXCOMPLETE: - printEvtJoinTxComplete(log); - break; + case EV_JOIN_TXCOMPLETE: + printEvtJoinTxComplete(log); + break; - default: - break; + default: + break; }; } - // Format and output the detail of a successful network join -void printEvtJoined(TTNLogMessage* log) +void printEvtJoined(TTNLogMessage *log) { ESP_LOGI(TAG, "- ch=%d", (unsigned)log->txChnl); @@ -271,111 +240,68 @@ void printEvtJoined(TTNLogMessage* log) ESP_LOGI(TAG, "- devaddr: %08x", devaddr); char hexBuf[48]; - bin2hex((uint8_t*)&artKey, sizeof(artKey), hexBuf, '-'); + bin2hex((uint8_t *)&artKey, sizeof(artKey), hexBuf, '-'); ESP_LOGI(TAG, "- artKey: %s", hexBuf); - bin2hex((uint8_t*)&nwkKey, sizeof(nwkKey), hexBuf, '-'); + bin2hex((uint8_t *)&nwkKey, sizeof(nwkKey), hexBuf, '-'); ESP_LOGI(TAG, "- nwkKey: %s", hexBuf); } - // Format and output the detail of a failed network join -void printEvtJoinFailed(TTNLogMessage* log) +void printEvtJoinFailed(TTNLogMessage *log) { rps_t rps = log->rps; - ESP_LOGE(TAG, "- freq=%d.%d, opmode=%x, rps=0x%02x (%s, %s, %s, %s, IH=%d)", - log->freq / 1000000, (log->freq % 1000000) / 100000, - log->opmode, - rps, - SF_NAMES[getSf(rps)], - BW_NAMES[getBw(rps)], - CR_NAMES[getCr(rps)], - CRC_NAMES[getNocrc(rps)], - getIh(rps) - ); + ESP_LOGE(TAG, "- freq=%d.%d, opmode=%x, rps=0x%02x (%s, %s, %s, %s, IH=%d)", log->freq / 1000000, + (log->freq % 1000000) / 100000, log->opmode, rps, SF_NAMES[getSf(rps)], BW_NAMES[getBw(rps)], + CR_NAMES[getCr(rps)], CRC_NAMES[getNocrc(rps)], getIh(rps)); } -void printEvtTxComplete(TTNLogMessage* log) +void printEvtTxComplete(TTNLogMessage *log) { rps_t rps = log->rps; - ESP_LOGI(TAG, "- ch=%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", - (unsigned)log->txChnl, - rps, - SF_NAMES[getSf(rps)], - BW_NAMES[getBw(rps)], - CR_NAMES[getCr(rps)], - CRC_NAMES[getNocrc(rps)], - getIh(rps) - ); - ESP_LOGI(TAG, "- txrxFlags=0x%02x%s, FcntUp=%04x, FcntDn=%04x, txend=%u", - log->txrxFlags, - (log->txrxFlags & TXRX_ACK) != 0 ? "; received ack" : "", - log->fcntUp, log->fcntDn, - log->txend - ); + ESP_LOGI(TAG, "- ch=%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", (unsigned)log->txChnl, rps, SF_NAMES[getSf(rps)], + BW_NAMES[getBw(rps)], CR_NAMES[getCr(rps)], CRC_NAMES[getNocrc(rps)], getIh(rps)); + ESP_LOGI(TAG, "- txrxFlags=0x%02x%s, FcntUp=%04x, FcntDn=%04x, txend=%u", log->txrxFlags, + (log->txrxFlags & TXRX_ACK) != 0 ? "; received ack" : "", log->fcntUp, log->fcntDn, log->txend); } -void printEvtTxStart(TTNLogMessage* log) +void printEvtTxStart(TTNLogMessage *log) { rps_t rps = log->rps; - ESP_LOGI(TAG, "- ch=%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", - (unsigned)log->txChnl, - rps, - SF_NAMES[getSf(rps)], - BW_NAMES[getBw(rps)], - CR_NAMES[getCr(rps)], - CRC_NAMES[getNocrc(rps)], - getIh(rps) - ); - ESP_LOGI(TAG, "- datarate=%u, opmode=%x, txend=%u", - log->datarate, - log->opmode, - log->txend - ); + ESP_LOGI(TAG, "- ch=%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", (unsigned)log->txChnl, rps, SF_NAMES[getSf(rps)], + BW_NAMES[getBw(rps)], CR_NAMES[getCr(rps)], CRC_NAMES[getNocrc(rps)], getIh(rps)); + ESP_LOGI(TAG, "- datarate=%u, opmode=%x, txend=%u", log->datarate, log->opmode, log->txend); } -void printEvtRxStart(TTNLogMessage* log) +void printEvtRxStart(TTNLogMessage *log) { rps_t rps = log->rps; - ESP_LOGI(TAG, "- freq=%d.%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", - log->freq / 1000000, (log->freq % 1000000) / 100000, - rps, - SF_NAMES[getSf(rps)], - BW_NAMES[getBw(rps)], - CR_NAMES[getCr(rps)], - CRC_NAMES[getNocrc(rps)], - getIh(rps) - ); - ESP_LOGI(TAG, "- delta=%dms, rxsysm=%u", - osticks2ms(log->time - log->txend), - log->rxsyms - ); + ESP_LOGI(TAG, "- freq=%d.%d, rps=0x%02x (%s, %s, %s, %s, IH=%d)", log->freq / 1000000, + (log->freq % 1000000) / 100000, rps, SF_NAMES[getSf(rps)], BW_NAMES[getBw(rps)], CR_NAMES[getCr(rps)], + CRC_NAMES[getNocrc(rps)], getIh(rps)); + ESP_LOGI(TAG, "- delta=%dms, rxsysm=%u", osticks2ms(log->time - log->txend), log->rxsyms); } -void printEvtJoinTxComplete(TTNLogMessage* log) +void printEvtJoinTxComplete(TTNLogMessage *log) { - ESP_LOGI(TAG, "- saveIrqFlags=0x%02x", - log->saveIrqFlags - ); + ESP_LOGI(TAG, "- saveIrqFlags=0x%02x", log->saveIrqFlags); } - - - -static const char* HEX_DIGITS = "0123456789ABCDEF"; +static const char *HEX_DIGITS = "0123456789ABCDEF"; /** * @brief Convert binary data to hexadecimal representation. - * + * * @param bin start of binary data * @param len length of binary data (in bytes) * @param buf buffer for hexadecimal result * @param sep separator used between bytes (or 0 for none) */ -void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep) +void bin2hex(const uint8_t *bin, unsigned len, char *buf, char sep) { int tgt = 0; - for (int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) + { if (sep != 0 && i != 0) buf[tgt++] = sep; buf[tgt++] = HEX_DIGITS[bin[i] >> 4]; @@ -384,5 +310,4 @@ void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep) buf[tgt] = 0; } - #endif diff --git a/src/ttn_logging.h b/src/ttn_logging.h index 681323a..14f03a3 100644 --- a/src/ttn_logging.h +++ b/src/ttn_logging.h @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -13,42 +13,38 @@ #ifndef TTN_LOGGING_H #define TTN_LOGGING_H - #if LMIC_ENABLE_event_logging #include #include - #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif + /** + * @brief Logging functions. + * + * Logs internal information from LMIC in an asynchrnous fashion in order + * not to distrub the sensitive LORA timing. + * + * A ring buffer and a separate logging task is ued. The LMIC core records + * relevant values from the current LORA settings and writes them to a ring + * buffer. The logging tasks receives the message and the values, formats + * them and outputs them via the regular ESP-IDF logging mechanism. + * + * In order to activate the detailed logging, set the macro + * `LMIC_ENABLE_event_logging` to 1. + */ -/** - * @brief Logging functions. - * - * Logs internal information from LMIC in an asynchrnous fashion in order - * not to distrub the sensitive LORA timing. - * - * A ring buffer and a separate logging task is ued. The LMIC core records - * relevant values from the current LORA settings and writes them to a ring - * buffer. The logging tasks receives the message and the values, formats - * them and outputs them via the regular ESP-IDF logging mechanism. - * - * In order to activate the detailed logging, set the macro - * `LMIC_ENABLE_event_logging` to 1. - */ - -void ttn_log_init(void); -void ttn_log_event(int event, const char* message, uint32_t datum); - + void ttn_log_init(void); + void ttn_log_event(int event, const char *message, uint32_t datum); #ifdef __cplusplus } #endif - #endif #endif diff --git a/src/ttn_provisioning.c b/src/ttn_provisioning.c index 7139b5b..a851ec4 100644 --- a/src/ttn_provisioning.c +++ b/src/ttn_provisioning.c @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -11,14 +11,14 @@ *******************************************************************************/ #include "ttn_provisioning.h" -#include "freertos/FreeRTOS.h" #include "driver/uart.h" #include "esp_event.h" #include "esp_log.h" #include "esp_system.h" -#include "nvs_flash.h" -#include "lmic/lmic.h" +#include "freertos/FreeRTOS.h" #include "hal/hal_esp32.h" +#include "lmic/lmic.h" +#include "nvs_flash.h" #if defined(TTN_HAS_AT_COMMANDS) #define UART_NUM CONFIG_TTN_PROVISION_UART_NUM @@ -32,7 +32,7 @@ #define NVS_FLASH_KEY_APP_KEY "appKey" #if defined(TTN_HAS_AT_COMMANDS) -static void provisioning_task(void* pvParameter); +static void provisioning_task(void *pvParameter); static void add_line_data(int num_bytes); static void detect_line_end(int start_at); static void process_line(void); @@ -43,16 +43,16 @@ static void config_uart(void); #endif static bool decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key); -static bool read_nvs_value(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent); -static bool write_nvs_value(nvs_handle handle, const char* key, const uint8_t* data, size_t len); +static bool read_nvs_value(nvs_handle handle, const char *key, uint8_t *data, size_t expected_length, bool silent); +static bool write_nvs_value(nvs_handle handle, const char *key, const uint8_t *data, size_t len); static bool hex_str_to_bin(const char *hex, uint8_t *buf, int len); static int hex_tuple_to_byte(const char *hex); static int hex_digit_to_val(char ch); -static void bin_to_hex_str(const uint8_t* buf, int len, char* hex); +static void bin_to_hex_str(const uint8_t *buf, int len, char *hex); static char val_to_hex_digit(int val); -static void swap_bytes(uint8_t* buf, int len); -static bool is_all_zeros(const uint8_t* buf, int len); +static void swap_bytes(uint8_t *buf, int len); +static bool is_all_zeros(const uint8_t *buf, int len); static uint8_t global_dev_eui[8]; static uint8_t global_app_eui[8]; @@ -62,26 +62,25 @@ static bool have_keys = false; #if defined(TTN_HAS_AT_COMMANDS) static QueueHandle_t uart_queue; -static char* line_buf; +static char *line_buf; static int line_length; static uint8_t last_line_end_char; static bool quit_task; #endif - // --- LMIC callbacks // This EUI must be in little-endian format, so least-significant-byte first. // When copying an EUI from ttnctl output, this means to reverse the bytes. // For TTN issued EUIs the last bytes should be 0xD5, 0xB3, 0x70. // The order is swapped in provisioning_decode_keys(). -void os_getArtEui (u1_t* buf) +void os_getArtEui(u1_t *buf) { memcpy(buf, global_app_eui, 8); } // This should also be in little endian format, see above. -void os_getDevEui (u1_t* buf) +void os_getDevEui(u1_t *buf) { memcpy(buf, global_dev_eui, 8); } @@ -89,7 +88,7 @@ void os_getDevEui (u1_t* buf) // This key should be in big endian format (or, since it is not really a number // but a block of memory, endianness does not really apply). In practice, a key // taken from ttnctl can be copied as-is. -void os_getDevKey (u1_t* buf) +void os_getDevKey(u1_t *buf) { memcpy(buf, global_app_key, 16); } @@ -100,7 +99,6 @@ void ttn_provisioning_init(void) { } - // --- Provisioning task #if defined(TTN_HAS_AT_COMMANDS) @@ -117,9 +115,9 @@ void ttn_provisioning_start_task(void) xTaskCreate(provisioning_task, "ttn_provision", 2048, NULL, 1, NULL); } -void provisioning_task(void* pvParameter) +void provisioning_task(void *pvParameter) { - line_buf = (char*)malloc(MAX_LINE_LENGTH + 1); + line_buf = (char *)malloc(MAX_LINE_LENGTH + 1); line_length = 0; uart_event_t event; @@ -133,18 +131,18 @@ void provisioning_task(void* pvParameter) switch (event.type) { - case UART_DATA: - add_line_data(event.size); - break; + case UART_DATA: + add_line_data(event.size); + break; - case UART_FIFO_OVF: - case UART_BUFFER_FULL: - uart_flush_input(UART_NUM); - xQueueReset(uart_queue); - break; + case UART_FIFO_OVF: + case UART_BUFFER_FULL: + uart_flush_input(UART_NUM); + xQueueReset(uart_queue); + break; - default: - break; + default: + break; } } @@ -160,8 +158,8 @@ top: n = num_bytes; if (line_length + n > MAX_LINE_LENGTH) n = MAX_LINE_LENGTH - line_length; - - uart_read_bytes(UART_NUM, (uint8_t*)line_buf + line_length, n, portMAX_DELAY); + + uart_read_bytes(UART_NUM, (uint8_t *)line_buf + line_length, n, portMAX_DELAY); int start_at = line_length; line_length += n; @@ -239,7 +237,7 @@ void process_line(void) } else if (strncmp(line_buf, "AT+PROV=", 8) == 0) { - is_ok = strlen(line_buf) == 74 && line_buf[24] == '-' && line_buf[41] == '-'; + is_ok = strlen(line_buf) == 74 && line_buf[24] == '-' && line_buf[41] == '-'; if (is_ok) { line_buf[24] = 0; @@ -271,7 +269,8 @@ void process_line(void) ESP_ERROR_CHECK(err); bin_to_hex_str(mac, 6, hexbuf); - for (int i = 0; i < 12; i += 2) { + for (int i = 0; i < 12; i += 2) + { if (i > 0) uart_write_bytes(UART_NUM, ":", 1); uart_write_bytes(UART_NUM, hexbuf + i, 2); @@ -287,10 +286,11 @@ void process_line(void) ESP_ERROR_CHECK(err); bin_to_hex_str(mac, 6, hexbuf); - for (int i = 0; i < 12; i += 2) { + for (int i = 0; i < 12; i += 2) + { uart_write_bytes(UART_NUM, hexbuf + i, 2); if (i == 4) - uart_write_bytes(UART_NUM, "FFFE", 4); + uart_write_bytes(UART_NUM, "FFFE", 4); } uart_write_bytes(UART_NUM, "\r\n", 2); } @@ -316,30 +316,27 @@ void process_line(void) #endif - #if defined(TTN_CONFIG_UART) void config_uart(void) { esp_err_t err; - uart_config_t uart_config = { - .baud_rate = CONFIG_TTN_PROVISION_UART_BAUDRATE, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE - }; + uart_config_t uart_config = {.baud_rate = CONFIG_TTN_PROVISION_UART_BAUDRATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE}; err = uart_param_config(UART_NUM, &uart_config); ESP_ERROR_CHECK(err); - err = uart_set_pin(UART_NUM, CONFIG_TTN_PROVISION_UART_TX_GPIO, CONFIG_TTN_PROVISION_UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + err = uart_set_pin(UART_NUM, CONFIG_TTN_PROVISION_UART_TX_GPIO, CONFIG_TTN_PROVISION_UART_RX_GPIO, + UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); ESP_ERROR_CHECK(err); } #endif - // --- Key handling bool ttn_provisioning_have_keys(void) @@ -357,7 +354,7 @@ bool ttn_provisioning_from_mac(const char *app_eui, const char *app_key) uint8_t mac[6]; esp_err_t err = esp_efuse_mac_get_default(mac); ESP_ERROR_CHECK(err); - + global_dev_eui[7] = mac[0]; global_dev_eui[6] = mac[1]; global_dev_eui[5] = mac[2]; @@ -404,13 +401,12 @@ bool decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const c memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui)); memcpy(global_app_key, buf_app_key, sizeof(global_app_key)); - have_keys = !is_all_zeros(global_dev_eui, sizeof(global_dev_eui)) - && !is_all_zeros(global_app_key, sizeof(global_app_key)); + have_keys = + !is_all_zeros(global_dev_eui, sizeof(global_dev_eui)) && !is_all_zeros(global_app_key, sizeof(global_app_key)); return true; } - // --- Non-volatile storage bool ttn_provisioning_save_keys() @@ -430,16 +426,16 @@ bool ttn_provisioning_save_keys() if (!write_nvs_value(handle, NVS_FLASH_KEY_DEV_EUI, global_dev_eui, sizeof(global_dev_eui))) goto done; - + if (!write_nvs_value(handle, NVS_FLASH_KEY_APP_EUI, global_app_eui, sizeof(global_app_eui))) goto done; - + if (!write_nvs_value(handle, NVS_FLASH_KEY_APP_KEY, global_app_key, sizeof(global_app_key))) goto done; res = nvs_commit(handle); ESP_ERROR_CHECK(res); - + result = true; ESP_LOGI(TAG, "DevEUI, AppEUI/JoinEUI and AppKey saved in NVS storage"); @@ -453,7 +449,7 @@ bool ttn_provisioning_restore_keys(bool silent) uint8_t buf_dev_eui[8]; uint8_t buf_app_eui[8]; uint8_t buf_app_key[16]; - + nvs_handle handle = 0; esp_err_t res = nvs_open(NVS_FLASH_PARTITION, NVS_READONLY, &handle); if (res == ESP_ERR_NVS_NOT_FOUND) @@ -480,12 +476,12 @@ bool ttn_provisioning_restore_keys(bool silent) memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui)); memcpy(global_app_key, buf_app_key, sizeof(global_app_key)); - have_keys = !is_all_zeros(global_dev_eui, sizeof(global_dev_eui)) - && !is_all_zeros(global_app_key, sizeof(global_app_key)); + have_keys = + !is_all_zeros(global_dev_eui, sizeof(global_dev_eui)) && !is_all_zeros(global_app_key, sizeof(global_app_key)); if (have_keys) { - ESP_LOGI(TAG, "DevEUI, AppEUI/JoinEUI and AppKey have been restored from NVS storage"); + ESP_LOGI(TAG, "DevEUI, AppEUI/JoinEUI and AppKey have been restored from NVS storage"); } else { @@ -497,7 +493,7 @@ done: return true; } -bool read_nvs_value(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent) +bool read_nvs_value(nvs_handle handle, const char *key, uint8_t *data, size_t expected_length, bool silent) { size_t size = expected_length; esp_err_t res = nvs_get_blob(handle, key, data, &size); @@ -517,29 +513,28 @@ bool read_nvs_value(nvs_handle handle, const char* key, uint8_t* data, size_t ex ESP_LOGW(TAG, "No NVS data found for %s", key); return false; } - + ESP_ERROR_CHECK(res); return false; } -bool write_nvs_value(nvs_handle handle, const char* key, const uint8_t* data, size_t len) +bool write_nvs_value(nvs_handle handle, const char *key, const uint8_t *data, size_t len) { uint8_t buf[16]; if (read_nvs_value(handle, key, buf, len, true) && memcmp(buf, data, len) == 0) return true; // unchanged - + esp_err_t res = nvs_set_blob(handle, key, data, len); ESP_ERROR_CHECK(res); return res == ESP_OK; } - // --- Helper functions --- bool hex_str_to_bin(const char *hex, uint8_t *buf, int len) { - const char* ptr = hex; + const char *ptr = hex; for (int i = 0; i < len; i++) { int val = hex_tuple_to_byte(ptr); @@ -573,7 +568,7 @@ int hex_digit_to_val(char ch) return -1; } -void bin_to_hex_str(const uint8_t* buf, int len, char* hex) +void bin_to_hex_str(const uint8_t *buf, int len, char *hex) { for (int i = 0; i < len; i++) { @@ -590,10 +585,10 @@ char val_to_hex_digit(int val) return "0123456789ABCDEF"[val]; } -void swap_bytes(uint8_t* buf, int len) +void swap_bytes(uint8_t *buf, int len) { - uint8_t* p1 = buf; - uint8_t* p2 = buf + len - 1; + uint8_t *p1 = buf; + uint8_t *p2 = buf + len - 1; while (p1 < p2) { uint8_t t = *p1; @@ -604,7 +599,7 @@ void swap_bytes(uint8_t* buf, int len) } } -bool is_all_zeros(const uint8_t* buf, int len) +bool is_all_zeros(const uint8_t *buf, int len) { for (int i = 0; i < len; i++) if (buf[i] != 0) diff --git a/src/ttn_provisioning.h b/src/ttn_provisioning.h index 41e7de6..5188621 100644 --- a/src/ttn_provisioning.h +++ b/src/ttn_provisioning.h @@ -1,9 +1,9 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * + * * Copyright (c) 2018-2021 Manuel Bleichenbacher - * + * * Licensed under MIT License * https://opensource.org/licenses/MIT * @@ -16,20 +16,20 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -void ttn_provisioning_init(void); + void ttn_provisioning_init(void); - -bool ttn_provisioning_have_keys(void); -bool ttn_provisioning_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key); -bool ttn_provisioning_from_mac(const char *app_eui, const char *app_key); -bool ttn_provisioning_save_keys(void); -bool ttn_provisioning_restore_keys(bool silent); + bool ttn_provisioning_have_keys(void); + bool ttn_provisioning_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key); + bool ttn_provisioning_from_mac(const char *app_eui, const char *app_key); + bool ttn_provisioning_save_keys(void); + bool ttn_provisioning_restore_keys(bool silent); #if defined(TTN_HAS_AT_COMMANDS) -void ttn_provisioning_start_task(void); + void ttn_provisioning_start_task(void); #endif #ifdef __cplusplus