MicroPython is a lean and efficient software implementation of the Python 3 programming language, written in C, that is optimized to run on a microcontrollers (like the pyBoard or an ESP8266, ESP32…). MicroPython is a full Python compiler and runtime that runs on the microcontroller itself. As a user you are presented with an interactive prompt (the REPL) to execute supported commands immediately. Included are a selection of core Python libraries and some extra libraries like machine which allows you to easily access low-level hardware.
As a developer, I am much more productive with MicroPython than plain old Arduino C++. Proper support for classes, easy access to the low level hardware results in readable and maintainable code which I find really important. But that’s enough of smalltalk about MicroPython.
For the moment, I’m working on a complex microcontroller project where I just feel that I will need updates to all the microcontrollers running in the wild. I do not want to bother people with asking them to flash their microcontroller again and again, each time I do an update/bugfix to the code. Since in my day-to-day workflow I already use github as a source control repository, I was thinking about using it to manage updates to all the devices.
So, I created a new MicroPython library (https://github.com/rdehuyss/micropython-ota-updater) which allows you to automatically update your MicroPython project using github releases. The workflow is as follows:
- whenever you feel fit, you ask the OTAUpdater (on my project this is after a hardware interrupt which starts up the WLAN for MQTT messaging) to check for a new version using
ota_updater.check_for_update_to_install_during_next_reboot()
if a new version is present, the OTAUpdater will download the new version on the next reboot (usemachine.reset()
to reboot your microcontroller) and use it
- You have a github repo where you host your micropython project
- In this project, you include all your source code in a folder called ‘main’
- You also include the ota_updater.py (https://github.com/rdehuyss/micropython-ota-updater)
- Use the following code in your `main.py`:
- Eh voila!
The important thing to note is that o.download_and_install_update_if_available(‘wifi-ssid’, ‘wifi-password’)
will only start the WLAN if a new version is available (see below for more info). If not, it will just start your main code as usual.
What happens behind the scene? Once you finish a new feature/bug fix, you create a new release in GitHub (thus tagging it). The ota_updater queries GitHub for the latest release/tag (you should use semantic versioning). If a new version is available, it creates a .version_on_reboot
file which contains the new version number and puts it in a sibling folder of your main
module, called next
. Once you reset your microcontroller and ask the OTAUpdater to download_and_install_update_if_available()
the pending version, it will:
- see which version it must download from the
.version_on_reboot
file in thenext
folder
- download all the new .py files in the
next
folder
- delete the
main
folder
- rename the
next
folder tomain
- rename the
.version_on_reboot
to.version
- and do a
machine.reset()
.
In your main.py file you then continue as normal, importing and bootstrapping your code from your main
module.
The .version
file is used to compare it against the latest release on your GitHub account. If a new version is found, the cycle starts over and that’s it!
You may ask yourself: why this workflow? Well, my project is quite complex and large and I was hitting memory issues. By having the download and update part in a separate boot cycle, I’m sure that everything is garbage collected.
For the moment, the ota_updater works with for sure with an ESP32 microcontroller running MicroPython 1.9.4.
Comments