New event handling

This commit is contained in:
Manuel Bl 2019-10-09 23:06:18 +02:00
parent dc0bfefe0e
commit 3ac63d4146
5 changed files with 190 additions and 69 deletions

View File

@ -58,6 +58,8 @@
#include <stdio.h> #include <stdio.h>
#endif #endif
#define LMIC_ENABLE_onEvent 0
#define DISABLE_PING #define DISABLE_PING
#define DISABLE_BEACONS #define DISABLE_BEACONS

View File

@ -21,14 +21,26 @@
#include "TTNLogging.h" #include "TTNLogging.h"
#define NO_DATUM 0x7cabcde3
static const char* const TAG = "lmic"; static const char* const TAG = "lmic";
static TTNLogging ttnLog; static TTNLogging ttnLog;
struct TTNLogMessage { struct TTNLogMessage {
const char* message; 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() void TTNLogging::init()
{ {
ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT); ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
if (ringBuffer == NULL) { if (ringBuffer == nullptr) {
ESP_LOGE(TAG, "Failed to create ring buffer"); ESP_LOGE(TAG, "Failed to create ring buffer");
ASSERT(0); 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; return;
TTNLogMessage log; TTNLogMessage log;
log.message = message; log.message = message;
log.datum = datum; 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); 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) void TTNLogging::loggingTask(void* param)
{ {
RingbufHandle_t ringBuffer = (RingbufHandle_t)param; RingbufHandle_t ringBuffer = (RingbufHandle_t)param;
@ -69,28 +119,28 @@ void TTNLogging::loggingTask(void* param)
while (true) { while (true) {
size_t size; size_t size;
TTNLogMessage* log = (TTNLogMessage*) xRingbufferReceive(ringBuffer, &size, portMAX_DELAY); TTNLogMessage* log = (TTNLogMessage*) xRingbufferReceive(ringBuffer, &size, portMAX_DELAY);
if (log == NULL) if (log == nullptr)
continue; continue;
if (log->datum == NO_DATUM) if (log->event == -1)
ESP_LOGI(TAG, "%s", log->message); {
else ESP_LOGI(TAG, "%s: opmode=0x%x", log->message, log->opmode);
ESP_LOGI(TAG, "%s (0x%x)", log->message, log->datum); }
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); 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 #endif

View File

@ -25,10 +25,11 @@ public:
static void initInstance(); static void initInstance();
void init(); void init();
void logEvent(const char* message, uint32_t datum); void logEvent(int event, const char* message, uint32_t datum);
private: private:
static void loggingTask(void* param); static void loggingTask(void* param);
static void logFatal(const char* file, uint16_t line);
RingbufHandle_t ringBuffer; RingbufHandle_t ringBuffer;
}; };

View File

@ -20,20 +20,42 @@
#include "TTNLogging.h" #include "TTNLogging.h"
enum ClientAction enum TTNClientAction
{ {
eActionUnrelated, eActionUnrelated,
eActionJoining, 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 const char *TAG = "ttn";
static TheThingsNetwork* ttnInstance; static TheThingsNetwork* ttnInstance;
static QueueHandle_t resultQueue; static QueueHandle_t resultQueue;
static ClientAction clientAction = eActionUnrelated; static TTNClientAction clientAction = eActionUnrelated;
static TTNProvisioning provisioning; 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() TheThingsNetwork::TheThingsNetwork()
: messageCallback(nullptr) : messageCallback(nullptr)
@ -62,10 +84,13 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
TTNLogging::initInstance(); TTNLogging::initInstance();
#endif #endif
os_init_ex(NULL); LMIC_registerEventCb(eventCallback, nullptr);
LMIC_registerRxMessageCb(messageReceivedCallback, nullptr);
os_init_ex(nullptr);
reset(); reset();
resultQueue = xQueueCreate(12, sizeof(int)); resultQueue = xQueueCreate(4, sizeof(TTNResult));
ASSERT(resultQueue != nullptr); ASSERT(resultQueue != nullptr);
ttn_hal.startBackgroundTask(); ttn_hal.startBackgroundTask();
} }
@ -158,9 +183,9 @@ bool TheThingsNetwork::joinCore()
ttn_hal.wakeUp(); ttn_hal.wakeUp();
ttn_hal.leaveCriticalSection(); ttn_hal.leaveCriticalSection();
int result = 0; TTNResult result;
xQueueReceive(resultQueue, &result, portMAX_DELAY); 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) 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; return kTTNErrorTransmissionFailed;
} }
clientAction = eActionSending; clientAction = eActionTransmission;
LMIC.client.txMessageCb = messageTransmittedCallback;
LMIC.client.txMessageUserData = nullptr;
LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm); LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm);
ttn_hal.wakeUp(); ttn_hal.wakeUp();
ttn_hal.leaveCriticalSection(); ttn_hal.leaveCriticalSection();
int result = 0; while (true)
{
TTNResult result;
xQueueReceive(resultQueue, &result, portMAX_DELAY); xQueueReceive(resultQueue, &result, portMAX_DELAY);
if (result == EV_TXCOMPLETE) switch (result.event)
{ {
bool hasRecevied = (LMIC.txrxFlags & (TXRX_DNW1 | TXRX_DNW2)) != 0; case EvtMessageReceived:
if (hasRecevied && messageCallback != nullptr) if (messageCallback != nullptr)
{ messageCallback(result.message, result.messageSize, result.port);
port_t port = 0; break;
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 EvtTransmissionCompleted:
return kTTNSuccessfulTransmission; return kTTNSuccessfulTransmission;
}
case EvtTransmissionFailed:
return kTTNErrorTransmissionFailed; return kTTNErrorTransmissionFailed;
default:
ASSERT(0);
}
}
} }
void TheThingsNetwork::onMessage(TTNMessageCallback callback) void TheThingsNetwork::onMessage(TTNMessageCallback callback)
@ -222,38 +250,59 @@ void TheThingsNetwork::setRSSICal(int8_t rssiCal)
} }
// --- LMIC functions --- // --- Callbacks ---
#if CONFIG_LOG_DEFAULT_LEVEL >= 3 #if CONFIG_LOG_DEFAULT_LEVEL >= 3
static const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT }; static const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT };
#endif #endif
void onEvent (ev_t ev) {
void eventCallback(void* userData, ev_t event)
{
#if CONFIG_LOG_DEFAULT_LEVEL >= 3 #if CONFIG_LOG_DEFAULT_LEVEL >= 3
ESP_LOGI(TAG, "event %s", eventNames[ev]); ESP_LOGI(TAG, "event %s", eventNames[event]);
#endif #endif
if (ev == EV_TXCOMPLETE) { if (event == EV_TXCOMPLETE) {
if (LMIC.txrxFlags & TXRX_ACK) if (LMIC.txrxFlags & TXRX_ACK)
ESP_LOGI(TAG, "ACK received\n"); ESP_LOGI(TAG, "ACK received\n");
} }
if (clientAction == eActionUnrelated) TTNEvent ttnEvent = EvtNone;
if (clientAction == eActionJoining)
{ {
return; if (event == EV_JOINED)
{
ttnEvent = EvtJoinCompleted;
} }
else if (clientAction == eActionJoining) else if (event == EV_REJOIN_FAILED || event == EV_RESET)
{ {
if (ev != EV_JOINED && ev != EV_REJOIN_FAILED && ev != EV_RESET) ttnEvent = EvtJoinFailed;
return;
} }
else
{
if (ev != EV_TXCOMPLETE && ev != EV_LINK_DEAD && ev != EV_RESET)
return;
} }
int result = ev; if (ttnEvent == EvtNone)
return;
TTNResult result(ttnEvent);
clientAction = eActionUnrelated; clientAction = eActionUnrelated;
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS); 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);
}

View File

@ -464,8 +464,27 @@ void HAL_ESP32::startBackgroundTask() {
xTaskCreate(backgroundTask, "ttn_lora_task", 1024 * 4, NULL, CONFIG_TTN_BG_TASK_PRIO, NULL); 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) void hal_failed(const char *file, u2_t line)
{ {
ESP_LOGE(TAG, "%s:%d", file, line); if (custom_hal_failure_handler != NULL)
ASSERT(0); (*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);
}
} }