New event handling
This commit is contained in:
parent
dc0bfefe0e
commit
3ac63d4146
|
@ -58,6 +58,8 @@
|
|||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define LMIC_ENABLE_onEvent 0
|
||||
|
||||
#define DISABLE_PING
|
||||
|
||||
#define DISABLE_BEACONS
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue