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>
#endif
#define LMIC_ENABLE_onEvent 0
#define DISABLE_PING
#define DISABLE_BEACONS

View File

@ -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

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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);
}
}