OTA PROGRAMMING
Over The Air Device Updates
Over the Air (OTA) Programing is a method that allows to remotely send new firmware to IoT devices over the Internet, no matter where they are as it works with Thinger.io Cloud to deliver the new firrmware binaries.
This feature allow us to keep the devices updated with new security patches and code improvements in a fast and scalable way. It is an essential tool for the maintenance of IoT products that will prevent us from traveling to the location of the devices.
The update process is done over a Visual Studio Code extension that integrates with the Thinger.io cloud to upload new firmware binaries to the target device. So, it integrates with the IDE to streamline the development process, just compile and upload as if the device where connected to the computer.
OTA Programming Example for ESP8266 over Visual Studio Code

IDE Configuration

Before working with this tool it is necessary to install and configure Visual Studio Code and the PlatformIO extension as explained on the SDK SETUP section of the documentation. Then it is required to install Thinger.io VSCode extension directly from the Extension manager. Search for "Thinger.io" or Checkout on Microsoft Marketplace.
Visual Studio Code Thinger.io Extension for MCU OTA
This extension will manage the OTA processes with some interesting features such as:
  • OTA updates directly from the Internet over Thinger.io
  • Device switcher to search & select the target device for the update
  • Real-time device connection status
  • Compatible with multiple PlatformIO configuration environments inside a Project
  • Automatic build and upload over the Internet in a single click
  • OTA with compression support both on ESP8266 and ESP32
  • MD5 Checksum verification for firmware binaries

Extension Configuration

Before running the OTA it is necessary to configure the extension by accessing the VScode Extensions Manager and selecting the Extensions Settings option.
Thinger.io Visual Studio Code Extension for OTA updates
  • Thinger.io Host: Place here the URL of the Thinger.io Instance you are working with (if using a private instance, otherwise by default it will be backend.thinger.io).
  • Thinger.io Port: Specifies the connection port (443 by default).
  • Thinger.io Secure: Enable/disable SSL/TLS connection (enabled by default).
  • Thinger.io Token: Place here a Thinger.io Access Tokenwith the following permissions:
    • ListDevices
    • AccessDeviceResources
    • ReadDeviceStatistics
The following image provides a token configuration example with the required permissions.
Example Thinger.io Token Configuration for Visual Studio Code Extension

Firmware Upload via OTA

The OTA feature is implemented on the default Thinger.io Arduino client libraries required for the connectivity with the Thinger.io cloud.
The boards that supports OTA updates over the Visual Studio Code extension are the following:
  • Espressif ESP8266
  • Espressif ESP32
  • Arduino Nano 33 IOT
  • Arduino MKR WiFi 1010
  • Arduino RPI2040 Connect
  • Arduino MKR NB 1500
The general requirement to start working with OTA updates for a specific device are:
  1. 1.
    Have a PlatformIO project on Visual Studio Code for the target device. More details here.
  2. 2.
    Have a basic Thinger.io firmware for your device, and ensure you it can connect to the cloud.
  3. 3.
    Modify the sketch to include the OTA functionality. More details in each specific device section.
  4. 4.
    Flash the initial firmware over a serial communication port on the computer.
  5. 5.
    Use the Thinger.io Visual Studio Code toolbar buttons to select your device and flash new firmware.
If everything is configured correctly it will be possible to start working with the Thinger.io extension via the new elements added to the bottom toolbar. There are two buttons that allow to select the target device to be flashed, and then compile and upload new firmware binaries.
Thinger.io Buttons on Visual Studio Code Toolbar
Select Target Device πŸš€
This button is a device selector, when you click it, it will prompt to search and select a target device from your Thinger.io account.
Device Selector for OTA Updates over Visual Studio Code
When the target device is disconnected, the target device button background color will be red.
Compile and Update ▢️
This button compiles and uploads the code to the selected device. In the process it will show a window with the OTA progress.
Compile and upload example for ESP8266
To update your device over OTA, the first time it must be flashed from a serial com port.
Clean Target Device πŸ—‘οΈ
It is possible to clean the selected target device accessing the Visual Studio command Palette with Ctrl + Shift + P, and searching for Thinger.io
Clean Target Device

ESP32 OTA

To add OTA functionality for ESP32 it is only required to include the ThingerESP32OTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
ardunio_secrets.h
1
#define THINGER_SERIAL_DEBUG
2
​
3
#include <ThingerESP32.h>
4
#include <ThingerESP32OTA.h>
5
#include "arduino_secrets.h"
6
​
7
ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
8
ThingerESP32OTA ota(thing);
9
​
10
void setup() {
11
// open serial for monitoring
12
Serial.begin(115200);
13
14
pinMode(16, OUTPUT);
15
​
16
thing.add_wifi(SSID, SSID_PASSWORD);
17
​
18
// digital pin control example (i.e. turning on/off a light, a relay, configuring a parameter, etc)
19
thing["GPIO_16"] << digitalPin(16);
20
​
21
// resource output example (i.e. reading a sensor value)
22
thing["millis"] >> outputValue(millis());
23
​
24
// more details at http://docs.thinger.io/arduino/
25
}
26
​
27
void loop() {
28
thing.handle();
29
}
Copied!
1
#define USERNAME "your_user_name"
2
#define DEVICE_ID "your_device_id"
3
#define DEVICE_CREDENTIAL "your_device_credential"
4
​
5
#define SSID "your_wifi_ssid"
6
#define SSID_PASSWORD "your_wifi_ssid_password"
Copied!

ESP8266 OTA

To add OTA functionality for ESP8266 it is only required to include the ThingerESP8266OTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
arduino_secrets.h
1
#define THINGER_SERIAL_DEBUG
2
​
3
#include <ThingerESP8266.h>
4
#include <ThingerESP8266OTA.h>
5
#include "arduino_secrets.h"
6
​
7
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
8
ThingerESP8266OTA ota(thing);
9
​
10
void setup() {
11
// open serial for monitoring
12
Serial.begin(115200);
13
​
14
// set builtin led as output
15
pinMode(LED_BUILTIN, OUTPUT);
16
​
17
// add WiFi credentials
18
thing.add_wifi(SSID, SSID_PASSWORD);
19
​
20
// digital pin control example (i.e. turning on/off a light, a relay, configuring a parameter, etc)
21
thing["led"] << digitalPin(LED_BUILTIN);
22
​
23
// resource output example (i.e. reading a sensor value)
24
thing["millis"] >> outputValue(millis());
25
​
26
// more details at http://docs.thinger.io/arduino/
27
}
28
​
29
void loop() {
30
thing.handle();
31
}
Copied!
1
#define USERNAME "your_user_name"
2
#define DEVICE_ID "your_device_id"
3
#define DEVICE_CREDENTIAL "your_device_credential"
4
​
5
#define SSID "your_wifi_ssid"
6
#define SSID_PASSWORD "your_wifi_ssid_password"
Copied!

Arduino Nano 33 IOT OTA

To add OTA functionality for Arduino Nano 33 IOT it is required to include the ThingerWiFiNINAOTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
arduino_secrets.h
1
#define THINGER_SERIAL_DEBUG
2
​
3
#include <ThingerWiFiNINA.h>
4
#include <ThingerWiFiNINAOTA.h>
5
#include "arduino_secrets.h"
6
​
7
ThingerWiFiNINA thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
8
ThingerWiFiNINAOTA ota(thing);
9
​
10
void setup() {
11
// configure LED_BUILTIN for output
12
pinMode(LED_BUILTIN, OUTPUT);
13
​
14
// open serial for debugging
15
Serial.begin(115200);
16
​
17
// configure wifi network
18
thing.add_wifi(SSID, SSID_PASSWORD);
19
​
20
// pin control example (i.e. turning on/off a light, a relay, etc)
21
thing["led"] << digitalPin(LED_BUILTIN);
22
​
23
// resource output example (i.e. reading a sensor value, a variable, etc)
24
thing["millis"] >> outputValue(millis());
25
26
// more details at http://docs.thinger.io/arduino/
27
}
28
​
29
void loop() {
30
thing.handle();
31
}
Copied!
1
#define USERNAME "your_user_name"
2
#define DEVICE_ID "your_device_id"
3
#define DEVICE_CREDENTIAL "your_device_credential"
4
​
5
#define SSID "your_wifi_ssid"
6
#define SSID_PASSWORD "your_wifi_ssid_password"
Copied!
Note: it is required to include lib_archive = no to platformio.ini configuration file.
platformio.ini
1
[env:nano_33_iot]
2
platform = atmelsam
3
board = nano_33_iot
4
framework = arduino
5
lib_archive = no
6
lib_deps = thinger.io
Copied!

Arduino MKR WiFi 1010 OTA

To add OTA functionality for Arduino MKR WiFi 1010 it is required to include the ThingerWiFiNINAOTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
arduino_secrets.h
1
​
2
#include <ThingerWiFiNINA.h>
3
#include <ThingerWiFiNINAOTA.h>
4
#include "arduino_secrets.h"
5
​
6
ThingerWiFiNINA thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
7
ThingerWiFiNINAOTA ota(thing);
8
​
9
void setup() {
10
// configure LED_BUILTIN for output
11
pinMode(LED_BUILTIN, OUTPUT);
12
​
13
// open serial for debugging
14
Serial.begin(115200);
15
​
16
// configure wifi network
17
thing.add_wifi(SSID, SSID_PASSWORD);
18
​
19
// pin control example (i.e. turning on/off a light, a relay, etc)
20
thing["led"] << digitalPin(LED_BUILTIN);
21
​
22
// resource output example (i.e. reading a sensor value, a variable, etc)
23
thing["millis"] >> outputValue(millis());
24
25
// more details at http://docs.thinger.io/arduino/
26
}
27
​
28
void loop() {
29
thing.handle();
30
}
Copied!
1
#define DEVICE_ID "your_device_id"
2
#define DEVICE_CREDENTIAL "your_device_credential"
3
​
4
#define SSID "your_wifi_ssid"
5
#define SSID_PASSWORD "your_wifi_ssid_password"
Copied!
Note: it is required to include lib_archive = no to platformio.ini configuration file.
platformio.ini
1
[env:mkrwifi1010]
2
platform = atmelsam
3
board = mkrwifi1010
4
framework = arduino
5
lib_archive = no
6
lib_deps = thinger.io
Copied!

Arduino RPI2040 Connect OTA

To add OTA functionality for Arduino RPI2040 Connect it is only required to include the ThingerMbedOTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
arduino_secrets.h
1
​
2
#define THINGER_SERIAL_DEBUG
3
​
4
#include <ThingerMbed.h>
5
#include <ThingerMbedOTA.h>
6
#include "arduino_secrets.h"
7
​
8
ThingerMbed thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
9
ThingerMbedOTA ota(thing);
10
​
11
void setup() {
12
// open serial for debugging
13
Serial.begin(115200);
14
​
15
// configure LED_BUILTIN for output
16
pinMode(LED_BUILTIN, OUTPUT);
17
​
18
// configure wifi network
19
thing.add_wifi(SSID, SSID_PASSWORD);
20
​
21
// pin control example (i.e. turning on/off a light, a relay, etc)
22
thing["led"] << digitalPin(LED_BUILTIN);
23
​
24
// resource output example (i.e. reading a sensor value, a variable, etc)
25
thing["millis"] >> outputValue(millis());
26
​
27
// start thinger task
28
thing.start();
29
​
30
// more details at http://docs.thinger.io/arduino/
31
}
32
​
33
void loop() {
34
// your code here
35
}
Copied!
1
#define DEVICE_ID "your_device_id"
2
#define DEVICE_CREDENTIAL "your_device_credential"
3
​
4
#define SSID "your_wifi_ssid"
5
#define SSID_PASSWORD "your_wifi_ssid_password"
Copied!

Arduino MKR NB 1500 OTA

To add OTA functionality for MKR NB 1500 it is only required to include the ThingerMKRNBOTA.h header and create an instance of it. A complete example for a basic firmware with OTA support can be as the following:
main.cpp
arduino_secrets.h
1
#define THINGER_SERIAL_DEBUG
2
​
3
#include <ThingerMKRNB.h>
4
#include <ThingerMKRNBOTA.h>
5
#include "arduino_secrets.h"
6
​
7
ThingerMKRNB thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
8
// OTA seems to not work if no reset button pressed
9
ThingerMKRNBOTA ota(thing);
10
​
11
void setup() {
12
// enable serial for debugging
13
Serial.begin(115200);
14
​
15
// optional set pin number
16
thing.set_pin(PIN_NUMBER);
17
​
18
// set APN
19
thing.set_apn(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD);
20
​
21
// set builtin led to output
22
pinMode(LED_BUILTIN, OUTPUT);
23
​
24
// pin control example over internet (i.e. turning on/off a light, a relay, etc)
25
thing["led"] << digitalPin(LED_BUILTIN);
26
​
27
// resource output example (i.e. reading a sensor value, a variable, etc)
28
thing["time"] >> [&](pson& out){
29
out = thing.getNB().getTime();
30
};
31
​
32
// more details at http://docs.thinger.io/arduino/
33
}
34
​
35
void loop() {
36
thing.handle();
37
}
38
​
Copied!
1
#define USERNAME "your_user_name"
2
#define DEVICE_ID "your_device_id"
3
#define DEVICE_CREDENTIAL "your_device_credential"
4
​
5
#define PIN_NUMBER ""
6
​
7
#define GPRS_APN "your_apn_name"
8
#define GPRS_LOGIN "your_gprs_login"
9
#define GPRS_PASSWORD "your_gprs_password"
Copied!
Note: it is required to include lib_archive = no to platformio.ini configuration file.
platformio.ini
1
[env:mkrnb1500]
2
platform = atmelsam
3
board = mkrnb1500
4
framework = arduino
5
lib_archive = no
6
lib_deps = thinger.io
Copied!
At this moment, it seems that MKR NB 1500 requires pressing the reset button to apply the OTA update.
Last modified 2mo ago