From 3ac63d4146a11a6c3d789107762b82438ec856c3 Mon Sep 17 00:00:00 2001 From: Manuel Bl <10954524+manuelbl@users.noreply.github.com> Date: Wed, 9 Oct 2019 23:06:18 +0200 Subject: [PATCH] New event handling --- esp_idf_lmic_config.h | 2 + src/TTNLogging.cpp | 98 ++++++++++++++++++++++------- src/TTNLogging.h | 3 +- src/TheThingsNetwork.cpp | 133 ++++++++++++++++++++++++++------------- src/hal/hal_esp32.cpp | 23 ++++++- 5 files changed, 190 insertions(+), 69 deletions(-) diff --git a/esp_idf_lmic_config.h b/esp_idf_lmic_config.h index e613b78..d4798c8 100755 --- a/esp_idf_lmic_config.h +++ b/esp_idf_lmic_config.h @@ -58,6 +58,8 @@ #include #endif +#define LMIC_ENABLE_onEvent 0 + #define DISABLE_PING #define DISABLE_BEACONS diff --git a/src/TTNLogging.cpp b/src/TTNLogging.cpp index 3232b3f..550002d 100644 --- a/src/TTNLogging.cpp +++ b/src/TTNLogging.cpp @@ -21,14 +21,26 @@ #include "TTNLogging.h" -#define NO_DATUM 0x7cabcde3 - static const char* const TAG = "lmic"; static TTNLogging ttnLog; struct TTNLogMessage { const char* message; - uint32_t datum; + 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; }; @@ -40,28 +52,66 @@ void TTNLogging::initInstance() void TTNLogging::init() { ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT); - if (ringBuffer == NULL) { + if (ringBuffer == nullptr) { ESP_LOGE(TAG, "Failed to create ring buffer"); ASSERT(0); } - xTaskCreate(loggingTask, "ttn_log", 1024 * 4, ringBuffer, 4, NULL); + xTaskCreate(loggingTask, "ttn_log", 1024 * 4, ringBuffer, 4, nullptr); + hal_set_failure_handler(logFatal); } -void TTNLogging::logEvent(const char* message, uint32_t datum) +void TTNLogging::logEvent(int event, const char* message, uint32_t datum) { - if (ringBuffer == NULL) + if (ringBuffer == nullptr) return; TTNLogMessage log; - log.message = message; log.datum = datum; + + // capture state + log.time = os_getTime(); + log.txend = LMIC.txend; + log.globalDutyAvail = LMIC.globalDutyAvail; + log.event = (ev_t)event; + log.freq = LMIC.freq; + log.opmode = LMIC.opmode; + log.fcntDn = (u2_t) LMIC.seqnoDn; + log.fcntUp = (u2_t) LMIC.seqnoUp; + log.rxsyms = LMIC.rxsyms; + log.rps = LMIC.rps; + log.txChnl = LMIC.txChnl; + log.datarate = LMIC.datarate; + log.txrxFlags = LMIC.txrxFlags; + log.saveIrqFlags = LMIC.saveIrqFlags; xRingbufferSend(ringBuffer, &log, sizeof(log), 0); } +void TTNLogging::logFatal(const char* file, uint16_t line) +{ + ttnLog.logEvent(-3, file, line); +} + + + +extern "C" void LMICOS_logEvent(const char *pMessage) +{ + ttnLog.logEvent(-1, pMessage, 0); + +} + +extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum) +{ + ttnLog.logEvent(-2, pMessage, datum); +} + + +// --------------------------------------------------------------------------- +// Log output + void TTNLogging::loggingTask(void* param) { RingbufHandle_t ringBuffer = (RingbufHandle_t)param; @@ -69,28 +119,28 @@ void TTNLogging::loggingTask(void* param) while (true) { size_t size; TTNLogMessage* log = (TTNLogMessage*) xRingbufferReceive(ringBuffer, &size, portMAX_DELAY); - if (log == NULL) + if (log == nullptr) continue; - if (log->datum == NO_DATUM) - ESP_LOGI(TAG, "%s", log->message); - else - ESP_LOGI(TAG, "%s (0x%x)", log->message, log->datum); + if (log->event == -1) + { + ESP_LOGI(TAG, "%s: opmode=0x%x", log->message, log->opmode); + } + else if (log->event == -2) + { + ESP_LOGI(TAG, "%s: datum=0x%x, opmode=0x%x)", log->message, log->datum, log->opmode); + } + else if (log->event == -3) + { + ESP_LOGE(TAG, "%s, %d: freq=%d.%d", + log->message, log->datum, + log->freq / 1000000, (log->freq % 1000000) / 100000 + ); + } vRingbufferReturnItem(ringBuffer, log); } } -extern "C" void LMICOS_logEvent(const char *pMessage) -{ - ttnLog.logEvent(pMessage, NO_DATUM); - -} - -extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum) -{ - ttnLog.logEvent(pMessage, datum); -} - #endif diff --git a/src/TTNLogging.h b/src/TTNLogging.h index ff5b2a4..003cac8 100644 --- a/src/TTNLogging.h +++ b/src/TTNLogging.h @@ -25,10 +25,11 @@ public: static void initInstance(); void init(); - void logEvent(const char* message, uint32_t datum); + void logEvent(int event, const char* message, uint32_t datum); private: static void loggingTask(void* param); + static void logFatal(const char* file, uint16_t line); RingbufHandle_t ringBuffer; }; diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index 0bba0b9..6ffea96 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -20,20 +20,42 @@ #include "TTNLogging.h" -enum ClientAction +enum TTNClientAction { eActionUnrelated, eActionJoining, - eActionSending + eActionTransmission +}; + +enum TTNEvent { + EvtNone, + EvtJoinCompleted, + EvtJoinFailed, + EvtMessageReceived, + EvtTransmissionCompleted, + EvtTransmissionFailed +}; + +struct TTNResult { + TTNResult(TTNEvent ev = EvtNone): event(ev) { } + + TTNEvent event; + uint8_t port; + const uint8_t *message; + size_t messageSize; }; static const char *TAG = "ttn"; static TheThingsNetwork* ttnInstance; static QueueHandle_t resultQueue; -static ClientAction clientAction = eActionUnrelated; +static TTNClientAction clientAction = eActionUnrelated; static TTNProvisioning provisioning; +static void eventCallback(void* userData, ev_t event); +static void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t messageSize); +static void messageTransmittedCallback(void *userData, int success); + TheThingsNetwork::TheThingsNetwork() : messageCallback(nullptr) @@ -62,10 +84,13 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui TTNLogging::initInstance(); #endif - os_init_ex(NULL); + LMIC_registerEventCb(eventCallback, nullptr); + LMIC_registerRxMessageCb(messageReceivedCallback, nullptr); + + os_init_ex(nullptr); reset(); - resultQueue = xQueueCreate(12, sizeof(int)); + resultQueue = xQueueCreate(4, sizeof(TTNResult)); ASSERT(resultQueue != nullptr); ttn_hal.startBackgroundTask(); } @@ -158,9 +183,9 @@ bool TheThingsNetwork::joinCore() ttn_hal.wakeUp(); ttn_hal.leaveCriticalSection(); - int result = 0; + TTNResult result; xQueueReceive(resultQueue, &result, portMAX_DELAY); - return result == EV_JOINED; + return result.event == EvtJoinCompleted; } TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t length, port_t port, bool confirm) @@ -172,32 +197,35 @@ TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t return kTTNErrorTransmissionFailed; } - clientAction = eActionSending; + clientAction = eActionTransmission; + LMIC.client.txMessageCb = messageTransmittedCallback; + LMIC.client.txMessageUserData = nullptr; LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm); ttn_hal.wakeUp(); ttn_hal.leaveCriticalSection(); - int result = 0; - xQueueReceive(resultQueue, &result, portMAX_DELAY); - - if (result == EV_TXCOMPLETE) + while (true) { - bool hasRecevied = (LMIC.txrxFlags & (TXRX_DNW1 | TXRX_DNW2)) != 0; - if (hasRecevied && messageCallback != nullptr) + TTNResult result; + xQueueReceive(resultQueue, &result, portMAX_DELAY); + + switch (result.event) { - port_t port = 0; - if ((LMIC.txrxFlags & TXRX_PORT)) - port = LMIC.frame[LMIC.dataBeg - 1]; - const uint8_t* msg = nullptr; - if (LMIC.dataLen > 0) - msg = LMIC.frame + LMIC.dataBeg; - messageCallback(msg, LMIC.dataLen, port); + case EvtMessageReceived: + if (messageCallback != nullptr) + messageCallback(result.message, result.messageSize, result.port); + break; + + case EvtTransmissionCompleted: + return kTTNSuccessfulTransmission; + + case EvtTransmissionFailed: + return kTTNErrorTransmissionFailed; + + default: + ASSERT(0); } - - return kTTNSuccessfulTransmission; } - - return kTTNErrorTransmissionFailed; } void TheThingsNetwork::onMessage(TTNMessageCallback callback) @@ -222,38 +250,59 @@ void TheThingsNetwork::setRSSICal(int8_t rssiCal) } -// --- LMIC functions --- +// --- Callbacks --- #if CONFIG_LOG_DEFAULT_LEVEL >= 3 static const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT }; #endif -void onEvent (ev_t ev) { + + +void eventCallback(void* userData, ev_t event) +{ #if CONFIG_LOG_DEFAULT_LEVEL >= 3 - ESP_LOGI(TAG, "event %s", eventNames[ev]); + ESP_LOGI(TAG, "event %s", eventNames[event]); #endif - if (ev == EV_TXCOMPLETE) { + if (event == EV_TXCOMPLETE) { if (LMIC.txrxFlags & TXRX_ACK) ESP_LOGI(TAG, "ACK received\n"); } - if (clientAction == eActionUnrelated) + TTNEvent ttnEvent = EvtNone; + + if (clientAction == eActionJoining) { - return; - } - else if (clientAction == eActionJoining) - { - if (ev != EV_JOINED && ev != EV_REJOIN_FAILED && ev != EV_RESET) - return; - } - else - { - if (ev != EV_TXCOMPLETE && ev != EV_LINK_DEAD && ev != EV_RESET) - return; + if (event == EV_JOINED) + { + ttnEvent = EvtJoinCompleted; + } + else if (event == EV_REJOIN_FAILED || event == EV_RESET) + { + ttnEvent = EvtJoinFailed; + } } - int result = ev; + if (ttnEvent == EvtNone) + return; + + TTNResult result(ttnEvent); clientAction = eActionUnrelated; xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS); } + +void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t nMessage) +{ + TTNResult result(EvtMessageReceived); + result.port = port; + result.message = message; + result.messageSize = nMessage; + xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS); +} + +void messageTransmittedCallback(void *userData, int success) +{ + clientAction = eActionUnrelated; + TTNResult result(success ? EvtTransmissionCompleted : EvtTransmissionFailed); + xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS); +} diff --git a/src/hal/hal_esp32.cpp b/src/hal/hal_esp32.cpp index af0d32f..205b4ff 100755 --- a/src/hal/hal_esp32.cpp +++ b/src/hal/hal_esp32.cpp @@ -464,8 +464,27 @@ void HAL_ESP32::startBackgroundTask() { xTaskCreate(backgroundTask, "ttn_lora_task", 1024 * 4, NULL, CONFIG_TTN_BG_TASK_PRIO, NULL); } + +// ----------------------------------------------------------------------------- +// Fatal failure + +static hal_failure_handler_t* custom_hal_failure_handler = NULL; + +void hal_set_failure_handler(const hal_failure_handler_t* const handler) +{ + custom_hal_failure_handler = handler; +} + void hal_failed(const char *file, u2_t line) { - ESP_LOGE(TAG, "%s:%d", file, line); - ASSERT(0); + if (custom_hal_failure_handler != NULL) + (*custom_hal_failure_handler)(file, line); + + ESP_LOGE(TAG, "LMIC failed and stopped: %s:%d", file, line); + + // go to sleep forever + while (true) + { + vTaskDelay(portMAX_DELAY); + } }