Understanding WisBlock-API V2 behavior

Please include the following information, in order for us to help you as effectively as possible.

  • What product do you wish to discuss? RAK4631

  • What firmware are you using? RUI3

  • What firmware version? RUI_4.1.0_RAK4631

  • Computer OS? Windows

  • What Computer OS version? Windows 11

Good morning @beegee ,

As you described in the Readme paper (WisBlock-API V2Build Status), " It requires some rethinking about Arduino applications, because you have no setup() or loop() function", I am trying to understand the code logic.

First of all, following the flow in the documentation, for example, where is the function or the call for the function described in the box “sleeping”. I doing this because the “sleeping” is the center of logic, I mean, everything when it finished, it goes to sleep. Then I would like to understand/recognize the flow: wake up in the event and, in the end, go back to sleep.

Do you have a simple example with a code calling the API, any API, in your code to be able to understand the code logic?



sleeping is achieved by stopping all running tasks. The tasks are stopped by FreeRTOS when they are waiting for a semaphore (a signal given from other sources, like an interrupt or a timer).

The loop() is within the API and it is stopped with xSemaphoreTake(g_task_sem, portMAX_DELAY); FreeRTOS will not call the loop() (which is a FreeRTOS task) until the semaphore g_task_sem is released by an event. Such an event can be:
LoRaWAN join success
LoRaWAN join fail
LoRaWAN TX finished
LoRaWAN RX event
LoRa P2P TX finished
LoRa …
BLE device connected
BLE UART data received
or events that you define in your own code, like an external interrupt from a acceleration sensor

The simplest example for WisBlock-API V2 is the Low-Power-PIO

I know that you have examples in the WisBlock-API V2 examples folder (Examples ). What I would like to know it is if you have a simple code where you have the call for WisBlock-API V2. I mean how is the “right way” to call and what do I have to expect as a answer.


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

		// Get temperature and humidity data

		// 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)
				MYLOG("APP", "Packet enqueued");
		case LMH_BUSY:
				MYLOG("APP", "LoRa transceiver is busy");
		case LMH_ERROR:
				MYLOG("APP", "Packet error, too big to send with current DR");
1 Like

Good morning,

I am using the RAK4631-R (RUI3) with VSCODE PlatformIO. What is the best FreeRTOS library that I have to install in my project?

For Nordic nRF52, I found the WrapperFreeRTOS by Alex Cajas

RUI3 and FreeRTOS will most likely not work together.

RUI3 runs its own scheduler to handle its tasks.

Last week I was learning FreeRTOS in a Udemy course, https://www.udemy.com/course/primeiros-passos-com-o-freertos/?kw=primeiros+passos+com+Free&src=sac.

It was a good course that it teach in a easy way how to do task management, queue control, ISR, semaphore, etc…

Do you know a training material in RUI3, I mean I am trying to learn how to do similar things (not necessarily in the same way :slight_smile: ) as I began to learn with FreeRTOS?

Searching RUI3 materials, I found a your paper https://news.rakwireless.com/get-started-with-rui3-api/?utm_source=RUI3&utm_medium=RUI3&utm_campaign=RAKwireless. Do you have more … ?



Not much if it is about tutorials.
We have the How-to-Make-a-Lora-Dongle-for-Your-Computer-with-RUI3/

And I started a collection of example code I started writing since RUI3 came out in the new RUI3-Best-Practice

1 Like


I started a “Tips & Tricks” documents for RUI3. Your feedback if something like that is useful would be very welcome.
RUI3 Tips & Tricks

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.