mirror of
				https://github.com/manuelbl/ttn-esp32.git
				synced 2025-10-31 10:40:35 +01:00 
			
		
		
		
	Adapted code formatting
This commit is contained in:
		
							
								
								
									
										3
									
								
								.clang-format
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.clang-format
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| BasedOnStyle: Microsoft | ||||
| IndentWidth: 4 | ||||
| ColumnLimit: 120 | ||||
| @ -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<ttn_data_rate_t>(data_rate)); } | ||||
|     void setDataRate(TTNDataRate data_rate) | ||||
|     { | ||||
|         ttn_set_data_rate(static_cast<ttn_data_rate_t>(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<TTNRxTxWindow>(ttn_rx_tx_window()); } | ||||
|     TTNRxTxWindow rxTxWindow() | ||||
|     { | ||||
|         return static_cast<TTNRxTxWindow>(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 | ||||
|  | ||||
							
								
								
									
										1244
									
								
								include/ttn.h
									
									
									
									
									
								
							
							
						
						
									
										1244
									
								
								include/ttn.h
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -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<ttn_rx_tx_window_t>(window)); | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										132
									
								
								src/ttn.c
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								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)); | ||||
| } | ||||
|  | ||||
| @ -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 <string.h> | ||||
|  | ||||
|  | ||||
| #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 | ||||
|  | ||||
| @ -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 <freertos/FreeRTOS.h> | ||||
| #include <freertos/ringbuf.h> | ||||
|  | ||||
|  | ||||
| #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 | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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 <stdbool.h> | ||||
|  | ||||
| #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 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user