mirror of
				https://github.com/manuelbl/ttn-esp32.git
				synced 2025-10-31 18:50:33 +01:00 
			
		
		
		
	More comments
This commit is contained in:
		| @ -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); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user