Skip to content

Instantly share code, notes, and snippets.

@pfeerick
Last active January 5, 2024 09:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pfeerick/9607fba1bfae45726187ab53add40027 to your computer and use it in GitHub Desktop.
Save pfeerick/9607fba1bfae45726187ab53add40027 to your computer and use it in GitHub Desktop.
Extra script to make PlatformIO do compressed OTA updates for the ESP8266
import gzip
import shutil
import os
Import("env")
def compressFirmware(source, target, env):
""" Compress ESP8266 firmware using gzip for 'compressed OTA upload' """
SOURCE_FILE = env.subst("$BUILD_DIR") + os.sep + env.subst("$PROGNAME") + ".bin"
if not os.path.exists(SOURCE_FILE+'.bak'):
print("Compressing firmware for upload...")
shutil.move(SOURCE_FILE, SOURCE_FILE + '.bak')
with open(SOURCE_FILE + '.bak', 'rb') as f_in:
with gzip.open(SOURCE_FILE, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
if os.path.exists(SOURCE_FILE+'.bak'):
ORG_FIRMWARE_SIZE = os.stat(SOURCE_FILE + '.bak').st_size
GZ_FIRMWARE_SIZE = os.stat(SOURCE_FILE).st_size
print("Compression reduced firmware size to {:.0f}% of original (was {} bytes, now {} bytes)".format((GZ_FIRMWARE_SIZE / ORG_FIRMWARE_SIZE) * 100, ORG_FIRMWARE_SIZE, GZ_FIRMWARE_SIZE))
env.AddPreAction("upload", compressFirmware)
@andrewwalters
Copy link

Thanks for showing how to get compressed OTA updates to work in PlatformIO! I made a fork with a couple changes to improve handling of incremental builds: (1) If the .bin file is newer than the .bak file, then go ahead and do the compression (assumes that .bin is freshly generated and not compressed), (2) After compressing, set the modification time of the compressed image to the same as the original so it doesn't break #1 and so incremental builds see the original timestamp.

@pfeerick
Copy link
Author

No problem! And thanks for taking it further! :)

@Mazo
Copy link

Mazo commented Feb 21, 2021

Thanks for the script, seems to work pretty well.

One thing worth changing though, on line 21 where it prints the % it should be 100 - (GZ_FIRMWARE_SIZE / ORG_FIRMWARE_SIZE) * 100, otherwise you're getting the final compressed % size, not the % size it was reduced by

@pfeerick
Copy link
Author

lol... so it does... I obviously had a brain fart moment there, there, as that was the percentage I wanted to see, but the message should have been something like Compression reduced firmware size to {:.0f}% of original size. I see andrewwalters spotted that also when he made the other tweaks.

Thanks for the suggestion!

@petter-b
Copy link

petter-b commented Jan 5, 2024

Thx for this script.

One suggested improvement:
SOURCE_FILE = source[0].get_abspath()

Then I prefer to use this as part of the build rather than upload. This is achieved by replacing last row with:
env.AddPostAction("buildprog", compressFirmware)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment