Uploading Firmware
Uploading Firmware via Platform IO (VSCode)
You can find an example project here: https://github.com/TechdroidInc
To upload directly from platform IO we use a pre- and post-script in the platform.ini
file. The two scripts can be found here (post_extra_script.py, pre_extra_script.py) and should be places in your root folder. Configuration is done via specific variables in the platform.ini
file.
There following variables are required:
- api_token - an api token with access to the project on otabin
- upload_server_url - otabin upload server URL without trailing slash (should almost always be ‘https://app.otabin.com ’)
- ota_url - otabin server URL without trailing slash (should almost always be ‘https://app.otabin.com ’)
- custom_prog_version - firmware version
- custom_prog_board - hardware name
- custom_hw_uuid - hardware unqiueID from the otabin platform
Step-by-step setup:
- Download the two scripts and place them in your project root.
- Create a
private_config.ini
in the root folder. Add a ‘otabin’ sectionAlso add [otabin] section and pre- and post-scripts to your env section in your[otabin] api_token = otabin_api_key upload_server_url = https://app.otabin.com
platform.ini
[otabin] ota_url = https://app.otabin.com [env:esp32-s3-rev-a-release] ... custom_prog_version = 1.0.2 custom_prog_board = esp32-s3-rev-a custom_hw_uuid = 7d2e5970-a8de-4c69-bd3d-6c8eb78fd3f9 upload_protocol = custom extra_scripts = pre:pre_extra_script.py post:post_extra_script.py
- In platform IO the firmware will now be uploaded upon running this particular env. We recommend setting separate envs for local development and release. There is a complete project example available here:
Configure Hardware for OTA
Arduino - esp32FOTA
Similar to the upload configuration in order to have your hardware do OTAs you need to additionally add the following to your env in platform.ini
[env:esp32-s3-rev-a-release]
...
build_flags =
-D VERSION=\"${this.custom_prog_version}\"
-D BOARD=\"${this.custom_prog_board}\"
-D OTA_HW_UUID=\"${this.custom_hw_uuid}\"
-D OTA_URL=\"${otabin.server_url}/fw/l\"
This will inject 4 constants into your project which esp32FOTA will use to perform the OTA.
In your main.cpp
do something similar to this:
...
#include <esp32FOTA.hpp>
esp32FOTA FOTA(BOARD, VERSION, false, true); // init esp32FOTA
int32_t updateCounter = 86401; // Do update on boot
int32_t updateInterval = 86400; // Check for update every 24 hours if loop delay is 1 second
void setup()
{
//...
FOTA.setManifestURL(OTA_URL); // OTA without trailing slash
FOTA.useDeviceId(true); // Unique HW identifier
FOTA.setExtraHTTPHeader("x-hardware", BOARD); // env name of the build, will be sent as 'type' in json response
FOTA.setExtraHTTPHeader("x-current-version", VERSION); // this is the current version
FOTA.setExtraHTTPHeader("x-hardware-uuid", OTA_HW_UUID); // the hardware Unique ID
// Other options such as reboot after update
FOTA.setUpdateFinishedCb([](int partition, bool restart_after) {
if (restart_after)
{
ESP.restart();
}
});
//...
}
void loop()
{
//...
if (updateCounter > updateInterval)
{
updateCounter = 0;
bool updatedNeeded = FOTA.execHTTPcheck();
if (updatedNeeded)
{
FOTA.execOTA();
}
}
updateCounter++;
delay(1000);
//...
}
Example pre_extra_script.py
Import("env")
try:
import configparser
except ImportError:
import ConfigParser as configparser
project_config = configparser.ConfigParser()
project_config.read("platformio.ini")
env.Replace(PROGNAME=env.GetProjectOption("custom_prog_board") + "_" + env.GetProjectOption("custom_prog_version"))
Example post_extra_script.py
import requests
import sys
from os.path import basename
Import('env')
try:
import configparser
except ImportError:
import ConfigParser as configparser
project_config = configparser.ConfigParser(inline_comment_prefixes="#")
private_config = configparser.ConfigParser(inline_comment_prefixes="#")
project_config.read("platformio.ini")
private_config.read("private_config.ini")
ota_config = {k: v for k, v in project_config.items("otabin")}
otaupload_config = {k: v for k, v in private_config.items("otabin")}
def publish_firmware(source, target, env):
hardware = env.GetProjectOption("custom_prog_board")
uuid = env.GetProjectOption("custom_hw_uuid")
version = env.GetProjectOption("custom_prog_version")
firmware_path = str(source[0])
firmware_name = basename(firmware_path)
print("Uploading {0} to otabin.com. Version: {1}".format(firmware_path, version))
url = "/".join([
otaupload_config.get("upload_server_url"), "fw/upload"
])
headers = {
"X-Firmware-Version": version,
"X-Hardware": hardware,
"X-Hardware-Uuid": uuid,
"Authorization": "Bearer " + otaupload_config['api_token']
}
r = None
try:
files = {'firmware': open(firmware_path, "rb")}
r = requests.post(url,
files = files,
headers = headers)
r.raise_for_status()
except requests.exceptions.RequestException as e:
if r.status_code >= 400:
sys.stderr.write("Failed to submit package: %s\n" % r.text)
else:
sys.stderr.write("Failed to submit package: %s\n" %
("%s\n%s" % (r.status_code, r.text) if r else str(e)))
env.Exit(1)
print("The firmware has been successfuly uploaded to otabin.com")
env.Replace(UPLOADCMD=publish_firmware)