More comments
This commit is contained in:
parent
a8fd68ca5e
commit
43080636bc
|
@ -21,9 +21,15 @@
|
|||
#include "TTNLogging.h"
|
||||
|
||||
|
||||
#define NUM_RINGBUF_MSG 50
|
||||
static const char* const TAG = "lmic";
|
||||
static TTNLogging ttnLog;
|
||||
|
||||
/**
|
||||
* @brief Message structure used in ring buffer
|
||||
*
|
||||
* The structure is sent from the LMIC task to the logging task.
|
||||
*/
|
||||
struct TTNLogMessage {
|
||||
const char* message;
|
||||
uint32_t datum;
|
||||
|
@ -43,6 +49,7 @@ struct TTNLogMessage {
|
|||
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 BW_NAMES[] = { "BW125", "BW250", "BW500", "BWrfu" };
|
||||
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);
|
||||
|
||||
|
||||
// Create singleton instance
|
||||
TTNLogging* TTNLogging::initInstance()
|
||||
{
|
||||
ttnLog.init();
|
||||
return &ttnLog;
|
||||
}
|
||||
|
||||
// Initialize logging
|
||||
void TTNLogging::init()
|
||||
{
|
||||
ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
|
||||
ringBuffer = xRingbufferCreate(NUM_RINGBUF_MSG * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
|
||||
if (ringBuffer == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to create ring buffer");
|
||||
ASSERT(0);
|
||||
|
@ -72,6 +81,7 @@ void TTNLogging::init()
|
|||
hal_set_failure_handler(logFatal);
|
||||
}
|
||||
|
||||
// Record a logging event for later output
|
||||
void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
|
||||
{
|
||||
if (ringBuffer == nullptr)
|
||||
|
@ -100,20 +110,22 @@ void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
|
|||
xRingbufferSend(ringBuffer, &log, sizeof(log), 0);
|
||||
}
|
||||
|
||||
|
||||
// record a fatal event (failed assert) for later output
|
||||
void TTNLogging::logFatal(const char* file, uint16_t 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ttnLog.logEvent(-2, pMessage, datum);
|
||||
|
@ -123,6 +135,7 @@ extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
|
|||
// ---------------------------------------------------------------------------
|
||||
// Log output
|
||||
|
||||
// Tasks that receiveds the recorded messages, formats and outputs them.
|
||||
void TTNLogging::loggingTask(void* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
rps_t rps = log->rps;
|
||||
|
@ -215,6 +231,14 @@ void printEvtJoinFailed(TTNLogMessage* log)
|
|||
|
||||
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)
|
||||
{
|
||||
int tgt = 0;
|
||||
|
|
|
@ -20,6 +20,22 @@
|
|||
#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 {
|
||||
public:
|
||||
static TTNLogging* initInstance();
|
||||
|
|
|
@ -286,7 +286,7 @@ void TTNProvisioning::processLine()
|
|||
ttn_hal.enterCriticalSection();
|
||||
LMIC_reset();
|
||||
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);
|
||||
|
|
|
@ -20,36 +20,45 @@
|
|||
#include "TTNLogging.h"
|
||||
|
||||
|
||||
enum TTNClientAction
|
||||
/**
|
||||
* @brief Reason the user code is waiting
|
||||
*/
|
||||
enum TTNWaitingReason
|
||||
{
|
||||
eActionUnrelated,
|
||||
eActionJoining,
|
||||
eActionTransmission
|
||||
eWaitingNone,
|
||||
eWaitingForJoin,
|
||||
eWaitingForTransmission
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Event type
|
||||
*/
|
||||
enum TTNEvent {
|
||||
EvtNone,
|
||||
EvtJoinCompleted,
|
||||
EvtJoinFailed,
|
||||
EvtMessageReceived,
|
||||
EvtTransmissionCompleted,
|
||||
EvtTransmissionFailed
|
||||
eEvtNone,
|
||||
eEvtJoinCompleted,
|
||||
eEvtJoinFailed,
|
||||
eEvtMessageReceived,
|
||||
eEvtTransmissionCompleted,
|
||||
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;
|
||||
uint8_t port;
|
||||
const uint8_t *message;
|
||||
const uint8_t* message;
|
||||
size_t messageSize;
|
||||
};
|
||||
|
||||
static const char *TAG = "ttn";
|
||||
|
||||
static TheThingsNetwork* ttnInstance;
|
||||
static QueueHandle_t resultQueue;
|
||||
static TTNClientAction clientAction = eActionUnrelated;
|
||||
static QueueHandle_t lmicEventQueue = nullptr;
|
||||
static TTNWaitingReason waitingReason = eWaitingNone;
|
||||
static TTNProvisioning provisioning;
|
||||
#if LMIC_ENABLE_event_logging
|
||||
static TTNLogging* logging;
|
||||
|
@ -66,7 +75,6 @@ TheThingsNetwork::TheThingsNetwork()
|
|||
#if defined(TTN_IS_DISABLED)
|
||||
ESP_LOGE(TAG, "TTN is disabled. Configure a frequency plan using 'make menuconfig'");
|
||||
ASSERT(0);
|
||||
esp_restart();
|
||||
#endif
|
||||
|
||||
ASSERT(ttnInstance == nullptr);
|
||||
|
@ -93,8 +101,8 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
|
|||
os_init_ex(nullptr);
|
||||
reset();
|
||||
|
||||
resultQueue = xQueueCreate(4, sizeof(TTNResult));
|
||||
ASSERT(resultQueue != nullptr);
|
||||
lmicEventQueue = xQueueCreate(4, sizeof(TTNLmicEvent));
|
||||
ASSERT(lmicEventQueue != nullptr);
|
||||
ttn_hal.startBackgroundTask();
|
||||
}
|
||||
|
||||
|
@ -102,6 +110,11 @@ void TheThingsNetwork::reset()
|
|||
{
|
||||
ttn_hal.enterCriticalSection();
|
||||
LMIC_reset();
|
||||
waitingReason = eWaitingNone;
|
||||
if (lmicEventQueue != nullptr)
|
||||
{
|
||||
xQueueReset(lmicEventQueue);
|
||||
}
|
||||
ttn_hal.leaveCriticalSection();
|
||||
}
|
||||
|
||||
|
@ -181,26 +194,26 @@ bool TheThingsNetwork::joinCore()
|
|||
}
|
||||
|
||||
ttn_hal.enterCriticalSection();
|
||||
clientAction = eActionJoining;
|
||||
waitingReason = eWaitingForJoin;
|
||||
LMIC_startJoining();
|
||||
ttn_hal.wakeUp();
|
||||
ttn_hal.leaveCriticalSection();
|
||||
|
||||
TTNResult result;
|
||||
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
||||
return result.event == EvtJoinCompleted;
|
||||
TTNLmicEvent event;
|
||||
xQueueReceive(lmicEventQueue, &event, portMAX_DELAY);
|
||||
return event.event == eEvtJoinCompleted;
|
||||
}
|
||||
|
||||
TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t length, port_t port, bool confirm)
|
||||
{
|
||||
ttn_hal.enterCriticalSection();
|
||||
if (LMIC.opmode & OP_TXRXPEND)
|
||||
if (waitingReason != eWaitingNone || (LMIC.opmode & OP_TXRXPEND) != 0)
|
||||
{
|
||||
ttn_hal.leaveCriticalSection();
|
||||
return kTTNErrorTransmissionFailed;
|
||||
}
|
||||
|
||||
clientAction = eActionTransmission;
|
||||
waitingReason = eWaitingForTransmission;
|
||||
LMIC.client.txMessageCb = messageTransmittedCallback;
|
||||
LMIC.client.txMessageUserData = nullptr;
|
||||
LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm);
|
||||
|
@ -209,20 +222,20 @@ TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t
|
|||
|
||||
while (true)
|
||||
{
|
||||
TTNResult result;
|
||||
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
||||
TTNLmicEvent result;
|
||||
xQueueReceive(lmicEventQueue, &result, portMAX_DELAY);
|
||||
|
||||
switch (result.event)
|
||||
{
|
||||
case EvtMessageReceived:
|
||||
case eEvtMessageReceived:
|
||||
if (messageCallback != nullptr)
|
||||
messageCallback(result.message, result.messageSize, result.port);
|
||||
break;
|
||||
|
||||
case EvtTransmissionCompleted:
|
||||
case eEvtTransmissionCompleted:
|
||||
return kTTNSuccessfulTransmission;
|
||||
|
||||
case EvtTransmissionFailed:
|
||||
case eEvtTransmissionFailed:
|
||||
return kTTNErrorTransmissionFailed;
|
||||
|
||||
default:
|
||||
|
@ -260,7 +273,7 @@ const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT };
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
// Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs
|
||||
void eventCallback(void* userData, ev_t event)
|
||||
{
|
||||
#if LMIC_ENABLE_event_logging
|
||||
|
@ -269,45 +282,42 @@ void eventCallback(void* userData, ev_t event)
|
|||
ESP_LOGI(TAG, "event %s", eventNames[event]);
|
||||
#endif
|
||||
|
||||
if (event == EV_TXCOMPLETE) {
|
||||
if (LMIC.txrxFlags & TXRX_ACK)
|
||||
ESP_LOGI(TAG, "ACK received\n");
|
||||
}
|
||||
TTNEvent ttnEvent = eEvtNone;
|
||||
|
||||
TTNEvent ttnEvent = EvtNone;
|
||||
|
||||
if (clientAction == eActionJoining)
|
||||
if (waitingReason == eWaitingForJoin)
|
||||
{
|
||||
if (event == EV_JOINED)
|
||||
{
|
||||
ttnEvent = EvtJoinCompleted;
|
||||
ttnEvent = eEvtJoinCompleted;
|
||||
}
|
||||
else if (event == EV_REJOIN_FAILED || event == EV_RESET)
|
||||
{
|
||||
ttnEvent = EvtJoinFailed;
|
||||
ttnEvent = eEvtJoinFailed;
|
||||
}
|
||||
}
|
||||
|
||||
if (ttnEvent == EvtNone)
|
||||
if (ttnEvent == eEvtNone)
|
||||
return;
|
||||
|
||||
TTNResult result(ttnEvent);
|
||||
clientAction = eActionUnrelated;
|
||||
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||
TTNLmicEvent result(ttnEvent);
|
||||
waitingReason = eWaitingNone;
|
||||
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)
|
||||
{
|
||||
TTNResult result(EvtMessageReceived);
|
||||
TTNLmicEvent result(eEvtMessageReceived);
|
||||
result.port = port;
|
||||
result.message = message;
|
||||
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)
|
||||
{
|
||||
clientAction = eActionUnrelated;
|
||||
TTNResult result(success ? EvtTransmissionCompleted : EvtTransmissionFailed);
|
||||
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||
waitingReason = eWaitingNone;
|
||||
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
|
||||
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue