Maybe this (extended) picture gives a better understanding:
Default setup()
, loop()
(with sleep by waiting for event semaphore), LoRa initialization and handler, BLE initialization and handler, “standard” AT command handler are in the API. (similar to RUI3)
There are “default” events within the API that trigger the loop()
to wake up and then use the callbacks to the application level.
- BLE events are triggering a call off
ble_data_handler()
- LoRa/LoRaWAN events are triggering a call of
lora_data_handler()
- system timer events and custom events are triggering a call of
app_event_handler()
On top of that you can define custom events, e.g. an acceleration sensor with interrupt handler (your code), can define a custom event mask:
/** Define additional events */
#define ACC_TRIGGER 0b1000000000000000
#define N_ACC_TRIGGER 0b0111111111111111
The interrupt handler for the acceleration sensor then calls api_wake(event_mask). With event_mask being ACC_TRIGGER.
This wakes up the loop(), which then calls api_event_handler()
.
There you check the event
// ACC triggered event
if ((g_task_event_type & ACC_TRIGGER) == ACC_TRIGGER)
{
g_task_event_type &= N_ACC_TRIGGER;
.......
}
Then you reset the mask, do whatever you want to do when the event happens. E.g. read the x,y,z values from the sensor, put them into a payload and send them over LoRaWAN.
Another way to use it is to just use the recurring system timer which is setup with ATC+SENDINT=xxxx
or with void api_timer_restart(uint32_t new_time)
.
Then every time the timer has finished, it wakes up the loop(0
with the event STATUS
. This triggers a callback to app_event_handler()
where you check the event_mask and e.g. start reading sensors, put the read values into a payload and send it over LoRaWAN.
Here a code snippet from the examples:
// Timer triggered event
if ((g_task_event_type & STATUS) == STATUS)
{
g_task_event_type &= N_STATUS;
MYLOG("APP", "Timer wakeup");
// Wake up the temperature sensor and start measurements
start_bme();
// Get temperature and humidity data
read_bme();
// Get battery level
batt_level.batt16 = read_batt() / 10;
g_tracker_data.batt_1 = batt_level.batt8[1];
g_tracker_data.batt_2 = batt_level.batt8[0];
lmh_error_status result;
result = send_lora_packet((uint8_t *)&g_tracker_data, TRACKER_DATA_LEN);
switch (result)
{
case LMH_SUCCESS:
MYLOG("APP", "Packet enqueued");
break;
case LMH_BUSY:
MYLOG("APP", "LoRa transceiver is busy");
break;
case LMH_ERROR:
MYLOG("APP", "Packet error, too big to send with current DR");
break;
}
}
}