Adapted code formatting

pull/47/head
Manuel Bleichenbacher 2021-07-31 17:03:00 +02:00
parent e34dbcb467
commit 8fa345a5d4
10 changed files with 1076 additions and 1112 deletions

3
.clang-format Normal file
View File

@ -0,0 +1,3 @@
BasedOnStyle: Microsoft
IndentWidth: 4
ColumnLimit: 120

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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));

View File

@ -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
View File

@ -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));
}

View File

@ -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";