mirror of
https://github.com/manuelbl/ttn-esp32.git
synced 2025-06-15 12:24:27 +02:00
New event handling
This commit is contained in:
parent
dc0bfefe0e
commit
3ac63d4146
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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)
|
||||||
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
|
||||||
|
|
||||||
if (result == EV_TXCOMPLETE)
|
|
||||||
{
|
{
|
||||||
bool hasRecevied = (LMIC.txrxFlags & (TXRX_DNW1 | TXRX_DNW2)) != 0;
|
TTNResult result;
|
||||||
if (hasRecevied && messageCallback != nullptr)
|
xQueueReceive(resultQueue, &result, portMAX_DELAY);
|
||||||
|
|
||||||
|
switch (result.event)
|
||||||
{
|
{
|
||||||
port_t port = 0;
|
case EvtMessageReceived:
|
||||||
if ((LMIC.txrxFlags & TXRX_PORT))
|
if (messageCallback != nullptr)
|
||||||
port = LMIC.frame[LMIC.dataBeg - 1];
|
messageCallback(result.message, result.messageSize, result.port);
|
||||||
const uint8_t* msg = nullptr;
|
break;
|
||||||
if (LMIC.dataLen > 0)
|
|
||||||
msg = LMIC.frame + LMIC.dataBeg;
|
case EvtTransmissionCompleted:
|
||||||
messageCallback(msg, LMIC.dataLen, port);
|
return kTTNSuccessfulTransmission;
|
||||||
|
|
||||||
|
case EvtTransmissionFailed:
|
||||||
|
return kTTNErrorTransmissionFailed;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return kTTNSuccessfulTransmission;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return kTTNErrorTransmissionFailed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
{
|
||||||
else if (clientAction == eActionJoining)
|
ttnEvent = EvtJoinCompleted;
|
||||||
{
|
}
|
||||||
if (ev != EV_JOINED && ev != EV_REJOIN_FAILED && ev != EV_RESET)
|
else if (event == EV_REJOIN_FAILED || event == EV_RESET)
|
||||||
return;
|
{
|
||||||
}
|
ttnEvent = EvtJoinFailed;
|
||||||
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);
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user