these days I have been working with new boards to include its support in the client libraries (for the upcoming 2.2.0 release), like the Arduino Nano RP2040 connect. This board includes mbed RTOS which allows, for example, creating multiple tasks. I have adapted the client library so Thinger client starts on its own Thread, leaving the loop completely free for the user. For example, a working sketch for this device is the following:
#define THINGER_SERIAL_DEBUG
#include <ThingerMbed.h>
#include <ThingerMbedOTA.h>
#include "arduino_secrets.h"
ThingerMbed thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
ThingerMbedOTA ota(thing);
void setup() {
// configure LED_BUILTIN for output
pinMode(LED_BUILTIN, OUTPUT);
// open serial for debugging
Serial.begin(115200);
// configure wifi network
thing.add_wifi(SSID, SSID_PASSWORD);
// pin control example (i.e. turning on/off a light, a relay, etc)
thing["led"] << digitalPin(LED_BUILTIN);
// resource output example (i.e. reading a sensor value, a variable, etc)
thing["millis"] >> outputValue(millis());
// start thinger.io on its own thread
thing.start();
}
void loop() {
Serial.println("user can work freely here");
delay(1000);
}
It even allows to start/stop thinger on demand. Since ESP32 on arduino runs using FreeRTOS, do you think it is worth to include the same approach shown here!?
Very interesting. Visually, it is simpler for the user to understand.
Also, are there any expectations to update the library so that it is possible to configure ESP32 with “WebConfig”/WiFiManager? And that the OTA update works with “WebConfig/WiFiManager”?
Apparently, WiFiManager version 2.0.4-Beta already works with ESP32.
This multitasking is just in one core or involves both? I ask this because it could be dangerous at the moment that two processes (running simultaneously, at both cores) access at the very same moment the very same memory, for example thinger’s task uploading (or writing) variables and another task writing them, at the same time, yes maybe the probabilities are soooo low, but it is something to keep in mind.
Hi @George_Santiago, I will take a look to WifiManager for ESP32.
And yes, @ega, with mulltitasking there is a chance of multiple task using the same memory. Thinger client library already had semaphores for ESP32 (started whit the ESP32Core project) and now included Mutex for Mbed platform, so, at least, the use of the thinger client instance is ok with multiple task, i.e., the loop calling endpoints, writing buckets, etc., and the background task handling incoming messages, streams, etc.
Moreover, if the loop updates or uses variables that are used someway inside a resource definition, it is possible to acquire the lock before using them. Here it is a working example for the upcoming library version.
We have a new library with RTOS support for ESP32:
Example for creating a background task for Thinger.io (notice the THINGER_FREE_RTOS define to enable RTOS functionality).
#define THINGER_SERIAL_DEBUG
#define THINGER_FREE_RTOS
#include <ThingerESP32.h>
#include "arduino_secrets.h"
ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
void setup() {
// open serial for debugging
Serial.begin(115200);
pinMode(16, OUTPUT);
thing.add_wifi(SSID, SSID_PASSWORD);
// digital pin control example (i.e. turning on/off a light, a relay, configuring a parameter, etc)
thing["GPIO_16"] << digitalPin(16);
// resource output example (i.e. reading a sensor value)
thing["millis"] >> outputValue(millis());
// start thinger in its own task
thing.start();
// more details at http://docs.thinger.io/arduino/
}
void loop() {
// use loop as in normal Arduino Sketch
// use thing.lock() thing.unlock() if using variables exposed on thinger resources
}
When trying to compile <ThingerTinyGSM.h> with the FreeRTOS option ( #define THINGER_FREE_RTOS ) an error is generated:
error: 'class ThingerTinyGSM' has no member named 'start'
thing.start();
Everything works fine when trying to compile <ThingerESP32WebConfig.h>, but with <ThingerTinyGSM.h> an error occurs.
Is it a bug? If so, is it easy to fix? Would it be possible to make the fix available before Friday (8/4/2023)?
I need to make a prototype before Friday. I tried to fix the problem in the <ThingerTinyGSM.h> code, but I couldn’t.
Tried to perform OTA with FreeRTOS via WiFi and GSM.
Via WiFi, the first attempt gave an error (the serial port was enabled on Termite). So I closed the serial port and tried again. I had success with OTA via WiFi for the next three attempts.
Image of the Error generated on the first attempt:
However, all OTA attempts via GSM gave an error. nem starts streaming the data in the VS Code notification bar. The <ThingerTinyGSM.h> library needs fixing in the FreeRTOS implementation. I made some adaptations and managed to make the <ThingerTinyGSM.h> library work with FreeRTOS, but it may need new corrections to work with OTA.
In the serial monitor, the following messages were captured:
I tried to perform the OTA via GSM, but I couldn’t yet. All attempts failed.
See the information below:
RAM: [= ] 7.6% (used 25052 bytes from 327680 bytes)
Flash: [=== ] 27.8% (used 364741 bytes from 1310720 bytes)
16:28:50: [THINGER] Available bytes: 24
[THINGER] Writing bytes: 83 [OK]
16:28:51: [THINGER] Available bytes: 117
[OTA] Received OTA request...
[OTA] Firmware: esp32
[OTA] Firmware Size: 365104
[OTA] Chunk Size: 32768
[OTA] Initializing update...
[OTA] Set MD5 verification:8baf228966c041c0bc66167967d518a7
[OTA] Init OK: 1
[THINGER] Writing bytes: 20 [OK]
[OTA] Stopping streams...
[OTA] Waiting for firmware...
........
16:28:57: [THINGER] Available bytes: 2920
........
16:29:34: [OTA] Received OTA part (bytes): 32768
[OTA] Wrote OK: 1
[OTA] Elapsed time ms: 122
[THINGER] Writing bytes: 20 [OK]
[THINGER] Writing bytes: 2 [OK]
........
16:29:35: [THINGER] Available bytes: 2
........
16:30:04: [OTA] OTA update timed out after (ms): 30000
[OTA] OTA update failed... Restarting device
[THINGER] Client was requested to stop.
Thinger State Listener: THINGER_STOP_REQUEST
[_SOCKET] Is now closed!
Thinger State Listener: SOCKET_DISCONNECTED
........
16:30:06: [THINGER] Rebooting device...
I have some questions about how to use thing.lock(); and thing.unlock();
1) If there is a shared resource in the thing object ( eg: ‘Serial.println’ in thing[“print_alert”], executed in CORE_0 ) and a function (CORE_1), we must also use thing.lock(); and thing.unlock(); in the thing[“print_alert”] object? See the example below:
2) If there are multiple shared resources, the recommended thing would be to create a mutex semaphore for each resource, correct? But with thing.lock(); and thing.unlock(); we just use one mutex semaphary for all resources, correct? See the fictional example below:
3) The thing object does not execute xSemaphoreTake(semaphore_, portMAX_DELAY);, nor xSemaphoreGive(semaphore_); when it is running in CORE_0, correct? So, what happens if thing (CORE_0) executes the same feature that is in a function in CORE_1 (which uses thing.lock(); and thing.unlock(); ) ? Does the thing object (which has no internal mutex) take the function’s resource? Or is it blocked, waiting for the function (CORE_1) to release the resource?
4) If thing(CORE_0) is waiting for the WiFi or GSM connection, can it block/lock a function (CORE_1) that shares the same resource, example: Serial.print?