mirror of
https://github.com/manuelbl/ttn-esp32.git
synced 2025-06-15 04:14:28 +02:00
More comments
This commit is contained in:
parent
a8fd68ca5e
commit
43080636bc
@ -21,9 +21,15 @@
|
|||||||
#include "TTNLogging.h"
|
#include "TTNLogging.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define NUM_RINGBUF_MSG 50
|
||||||
static const char* const TAG = "lmic";
|
static const char* const TAG = "lmic";
|
||||||
static TTNLogging ttnLog;
|
static TTNLogging ttnLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Message structure used in ring buffer
|
||||||
|
*
|
||||||
|
* The structure is sent from the LMIC task to the logging task.
|
||||||
|
*/
|
||||||
struct TTNLogMessage {
|
struct TTNLogMessage {
|
||||||
const char* message;
|
const char* message;
|
||||||
uint32_t datum;
|
uint32_t datum;
|
||||||
@ -43,6 +49,7 @@ struct TTNLogMessage {
|
|||||||
u1_t saveIrqFlags;
|
u1_t saveIrqFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Constants for formatting LORA values
|
||||||
static const char* const SF_NAMES[] = { "FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SFrfu" };
|
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 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 CR_NAMES[] = { "CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8" };
|
||||||
@ -54,15 +61,17 @@ static void printEvtJoinFailed(TTNLogMessage* log);
|
|||||||
static void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep = 0);
|
static void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep = 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Create singleton instance
|
||||||
TTNLogging* TTNLogging::initInstance()
|
TTNLogging* TTNLogging::initInstance()
|
||||||
{
|
{
|
||||||
ttnLog.init();
|
ttnLog.init();
|
||||||
return &ttnLog;
|
return &ttnLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize logging
|
||||||
void TTNLogging::init()
|
void TTNLogging::init()
|
||||||
{
|
{
|
||||||
ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
|
ringBuffer = xRingbufferCreate(NUM_RINGBUF_MSG * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
|
||||||
if (ringBuffer == nullptr) {
|
if (ringBuffer == nullptr) {
|
||||||
ESP_LOGE(TAG, "Failed to create ring buffer");
|
ESP_LOGE(TAG, "Failed to create ring buffer");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
@ -72,6 +81,7 @@ void TTNLogging::init()
|
|||||||
hal_set_failure_handler(logFatal);
|
hal_set_failure_handler(logFatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record a logging event for later output
|
||||||
void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
|
void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
|
||||||
{
|
{
|
||||||
if (ringBuffer == nullptr)
|
if (ringBuffer == nullptr)
|
||||||
@ -100,20 +110,22 @@ void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
|
|||||||
xRingbufferSend(ringBuffer, &log, sizeof(log), 0);
|
xRingbufferSend(ringBuffer, &log, sizeof(log), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// record a fatal event (failed assert) for later output
|
||||||
void TTNLogging::logFatal(const char* file, uint16_t line)
|
void TTNLogging::logFatal(const char* file, uint16_t line)
|
||||||
{
|
{
|
||||||
ttnLog.logEvent(-3, file, line);
|
ttnLog.logEvent(-3, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record an informational message for later output
|
||||||
|
// The message must not be freed.
|
||||||
extern "C" void LMICOS_logEvent(const char *pMessage)
|
extern "C" void LMICOS_logEvent(const char *pMessage)
|
||||||
{
|
{
|
||||||
ttnLog.logEvent(-1, pMessage, 0);
|
ttnLog.logEvent(-1, pMessage, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record an information message with an integer value for later output
|
||||||
|
// The message must not be freed.
|
||||||
extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
|
extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
|
||||||
{
|
{
|
||||||
ttnLog.logEvent(-2, pMessage, datum);
|
ttnLog.logEvent(-2, pMessage, datum);
|
||||||
@ -123,6 +135,7 @@ extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Log output
|
// Log output
|
||||||
|
|
||||||
|
// Tasks that receiveds the recorded messages, formats and outputs them.
|
||||||
void TTNLogging::loggingTask(void* param)
|
void TTNLogging::loggingTask(void* param)
|
||||||
{
|
{
|
||||||
RingbufHandle_t ringBuffer = (RingbufHandle_t)param;
|
RingbufHandle_t ringBuffer = (RingbufHandle_t)param;
|
||||||
@ -140,6 +153,7 @@ void TTNLogging::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)
|
||||||
@ -173,6 +187,7 @@ void printMessage(TTNLogMessage* log)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Format and output the detail of a successful network join
|
||||||
void printEvtJoined(TTNLogMessage* log)
|
void printEvtJoined(TTNLogMessage* log)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "%s: ch=%d", log->message, (unsigned)log->txChnl);
|
ESP_LOGI(TAG, "%s: ch=%d", log->message, (unsigned)log->txChnl);
|
||||||
@ -196,6 +211,7 @@ void printEvtJoined(TTNLogMessage* log)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Format and output the detail of a failed network join
|
||||||
void printEvtJoinFailed(TTNLogMessage* log)
|
void printEvtJoinFailed(TTNLogMessage* log)
|
||||||
{
|
{
|
||||||
rps_t rps = log->rps;
|
rps_t rps = log->rps;
|
||||||
@ -215,6 +231,14 @@ void printEvtJoinFailed(TTNLogMessage* log)
|
|||||||
|
|
||||||
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;
|
int tgt = 0;
|
||||||
|
@ -20,6 +20,22 @@
|
|||||||
#include <freertos/ringbuf.h>
|
#include <freertos/ringbuf.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Logging class.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This class is not to be used directly.
|
||||||
|
*/
|
||||||
class TTNLogging {
|
class TTNLogging {
|
||||||
public:
|
public:
|
||||||
static TTNLogging* initInstance();
|
static TTNLogging* initInstance();
|
||||||
|
@ -286,7 +286,7 @@ void TTNProvisioning::processLine()
|
|||||||
ttn_hal.enterCriticalSection();
|
ttn_hal.enterCriticalSection();
|
||||||
LMIC_reset();
|
LMIC_reset();
|
||||||
ttn_hal.leaveCriticalSection();
|
ttn_hal.leaveCriticalSection();
|
||||||
onEvent(EV_RESET);
|
LMIC.client.eventCb(LMIC.client.eventUserData, EV_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
uart_write_bytes(UART_NUM, is_ok ? "OK\r\n" : "ERROR\r\n", is_ok ? 4 : 7);
|
uart_write_bytes(UART_NUM, is_ok ? "OK\r\n" : "ERROR\r\n", is_ok ? 4 : 7);
|
||||||
|
@ -20,36 +20,45 @@
|
|||||||
#include "TTNLogging.h"
|
#include "TTNLogging.h"
|
||||||
|
|
||||||
|
|
||||||
enum TTNClientAction
|
/**
|
||||||
|
* @brief Reason the user code is waiting
|
||||||
|
*/
|
||||||
|
enum TTNWaitingReason
|
||||||
{
|
{
|
||||||
eActionUnrelated,
|
eWaitingNone,
|
||||||
eActionJoining,
|
eWaitingForJoin,
|
||||||
eActionTransmission
|
eWaitingForTransmission
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event type
|
||||||
|
*/
|
||||||
enum TTNEvent {
|
enum TTNEvent {
|
||||||
EvtNone,
|
eEvtNone,
|
||||||
EvtJoinCompleted,
|
eEvtJoinCompleted,
|
||||||
EvtJoinFailed,
|
eEvtJoinFailed,
|
||||||
EvtMessageReceived,
|
eEvtMessageReceived,
|
||||||
EvtTransmissionCompleted,
|
eEvtTransmissionCompleted,
|
||||||
EvtTransmissionFailed
|
eEvtTransmissionFailed
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TTNResult {
|
/**
|
||||||
TTNResult(TTNEvent ev = EvtNone): event(ev) { }
|
* @brief Event message sent from LMIC task to waiting client task
|
||||||
|
*/
|
||||||
|
struct TTNLmicEvent {
|
||||||
|
TTNLmicEvent(TTNEvent ev = eEvtNone): event(ev) { }
|
||||||
|
|
||||||
TTNEvent event;
|
TTNEvent event;
|
||||||
uint8_t port;
|
uint8_t port;
|
||||||
const uint8_t *message;
|
const uint8_t* message;
|
||||||
size_t messageSize;
|
size_t messageSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *TAG = "ttn";
|
static const char *TAG = "ttn";
|
||||||
|
|
||||||
static TheThingsNetwork* ttnInstance;
|
static TheThingsNetwork* ttnInstance;
|
||||||
static QueueHandle_t resultQueue;
|
static QueueHandle_t lmicEventQueue = nullptr;
|
||||||
static TTNClientAction clientAction = eActionUnrelated;
|
static TTNWaitingReason waitingReason = eWaitingNone;
|
||||||
static TTNProvisioning provisioning;
|
static TTNProvisioning provisioning;
|
||||||
#if LMIC_ENABLE_event_logging
|
#if LMIC_ENABLE_event_logging
|
||||||
static TTNLogging* logging;
|
static TTNLogging* logging;
|
||||||
@ -66,7 +75,6 @@ TheThingsNetwork::TheThingsNetwork()
|
|||||||
#if defined(TTN_IS_DISABLED)
|
#if defined(TTN_IS_DISABLED)
|
||||||
ESP_LOGE(TAG, "TTN is disabled. Configure a frequency plan using 'make menuconfig'");
|
ESP_LOGE(TAG, "TTN is disabled. Configure a frequency plan using 'make menuconfig'");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
esp_restart();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASSERT(ttnInstance == nullptr);
|
ASSERT(ttnInstance == nullptr);
|
||||||
@ -93,8 +101,8 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
|
|||||||
os_init_ex(nullptr);
|
os_init_ex(nullptr);
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
resultQueue = xQueueCreate(4, sizeof(TTNResult));
|
lmicEventQueue = xQueueCreate(4, sizeof(TTNLmicEvent));
|
||||||
ASSERT(resultQueue != nullptr);
|
ASSERT(lmicEventQueue != nullptr);
|
||||||
ttn_hal.startBackgroundTask();
|
ttn_hal.startBackgroundTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +110,11 @@ void TheThingsNetwork::reset()
|
|||||||
{
|
{
|
||||||
ttn_hal.enterCriticalSection();
|
ttn_hal.enterCriticalSection();
|
||||||
LMIC_reset();
|
LMIC_reset();
|
||||||
|
waitingReason = eWaitingNone;
|
||||||
|
if (lmicEventQueue != nullptr)
|
||||||
|
{
|
||||||
|
xQueueReset(lmicEventQueue);
|
||||||
|
}
|
||||||
ttn_hal.leaveCriticalSection();
|
ttn_hal.leaveCriticalSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,26 +194,26 @@ bool TheThingsNetwork::joinCore()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ttn_hal.enterCriticalSection();
|
ttn_hal.enterCriticalSection();
|
||||||
clientAction = eActionJoining;
|
waitingReason = eWaitingForJoin;
|
||||||
LMIC_startJoining();
|
LMIC_startJoining();
|
||||||
ttn_hal.wakeUp();
|
ttn_hal.wakeUp();
|
||||||
ttn_hal.leaveCriticalSection();
|
ttn_hal.leaveCriticalSection();
|
||||||
|
|
||||||
TTNResult result;
|
TTNLmicEvent event;
|
||||||
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
xQueueReceive(lmicEventQueue, &event, portMAX_DELAY);
|
||||||
return result.event == EvtJoinCompleted;
|
return event.event == eEvtJoinCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t length, port_t port, bool confirm)
|
TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t length, port_t port, bool confirm)
|
||||||
{
|
{
|
||||||
ttn_hal.enterCriticalSection();
|
ttn_hal.enterCriticalSection();
|
||||||
if (LMIC.opmode & OP_TXRXPEND)
|
if (waitingReason != eWaitingNone || (LMIC.opmode & OP_TXRXPEND) != 0)
|
||||||
{
|
{
|
||||||
ttn_hal.leaveCriticalSection();
|
ttn_hal.leaveCriticalSection();
|
||||||
return kTTNErrorTransmissionFailed;
|
return kTTNErrorTransmissionFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
clientAction = eActionTransmission;
|
waitingReason = eWaitingForTransmission;
|
||||||
LMIC.client.txMessageCb = messageTransmittedCallback;
|
LMIC.client.txMessageCb = messageTransmittedCallback;
|
||||||
LMIC.client.txMessageUserData = nullptr;
|
LMIC.client.txMessageUserData = nullptr;
|
||||||
LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm);
|
LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm);
|
||||||
@ -209,20 +222,20 @@ TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
TTNResult result;
|
TTNLmicEvent result;
|
||||||
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
xQueueReceive(lmicEventQueue, &result, portMAX_DELAY);
|
||||||
|
|
||||||
switch (result.event)
|
switch (result.event)
|
||||||
{
|
{
|
||||||
case EvtMessageReceived:
|
case eEvtMessageReceived:
|
||||||
if (messageCallback != nullptr)
|
if (messageCallback != nullptr)
|
||||||
messageCallback(result.message, result.messageSize, result.port);
|
messageCallback(result.message, result.messageSize, result.port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EvtTransmissionCompleted:
|
case eEvtTransmissionCompleted:
|
||||||
return kTTNSuccessfulTransmission;
|
return kTTNSuccessfulTransmission;
|
||||||
|
|
||||||
case EvtTransmissionFailed:
|
case eEvtTransmissionFailed:
|
||||||
return kTTNErrorTransmissionFailed;
|
return kTTNErrorTransmissionFailed;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -260,7 +273,7 @@ const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT };
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs
|
||||||
void eventCallback(void* userData, ev_t event)
|
void eventCallback(void* userData, ev_t event)
|
||||||
{
|
{
|
||||||
#if LMIC_ENABLE_event_logging
|
#if LMIC_ENABLE_event_logging
|
||||||
@ -269,45 +282,42 @@ void eventCallback(void* userData, ev_t event)
|
|||||||
ESP_LOGI(TAG, "event %s", eventNames[event]);
|
ESP_LOGI(TAG, "event %s", eventNames[event]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (event == EV_TXCOMPLETE) {
|
TTNEvent ttnEvent = eEvtNone;
|
||||||
if (LMIC.txrxFlags & TXRX_ACK)
|
|
||||||
ESP_LOGI(TAG, "ACK received\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
TTNEvent ttnEvent = EvtNone;
|
if (waitingReason == eWaitingForJoin)
|
||||||
|
|
||||||
if (clientAction == eActionJoining)
|
|
||||||
{
|
{
|
||||||
if (event == EV_JOINED)
|
if (event == EV_JOINED)
|
||||||
{
|
{
|
||||||
ttnEvent = EvtJoinCompleted;
|
ttnEvent = eEvtJoinCompleted;
|
||||||
}
|
}
|
||||||
else if (event == EV_REJOIN_FAILED || event == EV_RESET)
|
else if (event == EV_REJOIN_FAILED || event == EV_RESET)
|
||||||
{
|
{
|
||||||
ttnEvent = EvtJoinFailed;
|
ttnEvent = eEvtJoinFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ttnEvent == EvtNone)
|
if (ttnEvent == eEvtNone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TTNResult result(ttnEvent);
|
TTNLmicEvent result(ttnEvent);
|
||||||
clientAction = eActionUnrelated;
|
waitingReason = eWaitingNone;
|
||||||
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
|
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by LMIC when a message has been received
|
||||||
void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t nMessage)
|
void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t nMessage)
|
||||||
{
|
{
|
||||||
TTNResult result(EvtMessageReceived);
|
TTNLmicEvent result(eEvtMessageReceived);
|
||||||
result.port = port;
|
result.port = port;
|
||||||
result.message = message;
|
result.message = message;
|
||||||
result.messageSize = nMessage;
|
result.messageSize = nMessage;
|
||||||
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
|
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by LMIC when a message has been transmitted (or the transmission failed)
|
||||||
void messageTransmittedCallback(void *userData, int success)
|
void messageTransmittedCallback(void *userData, int success)
|
||||||
{
|
{
|
||||||
clientAction = eActionUnrelated;
|
waitingReason = eWaitingNone;
|
||||||
TTNResult result(success ? EvtTransmissionCompleted : EvtTransmissionFailed);
|
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
|
||||||
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
|
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user