I’m working with FreeRTOS and AWS IoT and exploring the OTA (Over-the-Air) library that FreeRTOS provides. I know it’s designed to work with AWS IoT for managing firmware updates, but I was wondering:
Can we use this library for a custom OTA job within AWS IoT?
For example, if we want more control over update handling, scheduling, or validation, is there a way to customize the OTA process while still leveraging AWS IoT?
My goal is to create a simple OTA process—without any code signing—and stream the update directly through MQTT.
Has anyone tried modifying the OTA workflow while staying within AWS IoT? Any best practices or potential pitfalls?
You absolutely can use a custom OTA job! We introduced the Modular OTA library (or more the set of libraries) for this exact purpose. These libraries make working with an OTA process simper by providing clean APIs for things such parsing job documents. You can find more on this here.
But now I think I might be looking at the wrong demo, right? Since this one is based on the FreeRTOS OTA job, it seems tightly integrated with AWS IoT’s standard OTA process.
Do you have a demo or example of a custom OTA job that still uses the FreeRTOS OTA library but allows more flexibility (e.g., no code signing, MQTT streaming, etc.)?
That demo is supposed to more closely resemble our older OTA Agent library. I don’t recommend using that library or pattern as it can make extensibility tricky. Instead I’d probably start from the simple orchestrator demo and build up from there.
You would still use the same component libraries as the simple or OTA agent orchestrator demos.
I tested out the simple orchestrator with a custom document - it won’t handle it out of the gate (not a shocker) but it was able to get the job doc and decline it. Try that demo subbing in your custom job document and modify it as needed. This should be the quickest way to get started.
The demo jobHandlerChain fails because the otaParser_parseJobDocFile function is specifically checking for a FreeRTOS OTA job (see this line). What you’ll need to do is replace the OTA parser in the job handler chain with your own your custom document parser.
I created a rough example you can find under my fork here which parses a custom job document. Further work would be required to actually process the document but that isn’t important for this example because you know best how to process your own job.
The job document below was generated by selecting the “Create custom job” option and using the “AWS-Download-File” template. I only used this template because I did not want to create my own. The Job Document shown in the console is…
I am using the Modular OTA library.
After setting the OTA PAL interfaces and OTA_Init(), everything looks fine before running the OTA_EventProcessingTask.
However, when this task runs, I’m getting a hard fault, and I see function pointers pointing to invalid addresses.
Looks like the link to the demo on the announcement page is broken. The demo you’ve referenced uses the old OTA agent library. The new, modular OTA demos can be found here.
The old OTA agent demo will not support your use case. Switching to the modular demo will allow you to modify the code more easily to handle you custom job.
@Jhon sorry to say but you’re still using the old OTA agent based off the link you’ve provided. The ota-for-aws-iot-embedded-sdk Github library is the old OTA agent, not the modular OTA library.
Please see this page for the new modular OTA library demos.
The simple-ota demo will be the best guide here. It’s important to remember that both the jobs and mqtt-streams libraries assemble the requests for you but don’t send the requests. To send the requests your code will need to call some sort of MQTT (or whatever messaging protocol you’re using) library which will send the assembled payloads. In the simple-ota demo the MQTT library used is CoreMQTT.
To get started you’ll need to:
Register a callback to handle an incoming MQTT message. In the simple demo this is done by creating the otaDemo_handleIncomingMQTTMessage function and registering it as part of the MQTT_Init function.
From here you can create whatever request/response handlers that you’d like. Your application will probably send the first message to as part of fetching the job through a stream. Your MQTT callback handler will then process the response (coming as an MQTT message) and orchestrate further requests for additional ‘blocks’ as needed.
No code signing is required since you’ll be creating a custom AWS IoT Job. Going without is probably fine for a short lived POC however it is strongly recommended to use code signing for longer term/production solutions.
Choosing an S3 file in the AWS IoT Jobs ‘Custom Job’ console workflow should show that code signing would be disabled for the custom job. An example of this is shown in the screenshot below.
The firmware is downloading now.
But I have one more doubt:
The .bin file size before uploading to the S3 bucket was around 10 KB, but when I check it in S3, it’s somehow only 6 KB. Even when I download it back from S3, it’s still 6 KB.