Skip to content

Instantly share code, notes, and snippets.

@andrewwalters
Forked from pfeerick/compressed_ota.py
Last active February 22, 2021 03:20
Show Gist options
  • Save andrewwalters/d4e3539319e55fc980db1ba67254d7ed to your computer and use it in GitHub Desktop.
Save andrewwalters/d4e3539319e55fc980db1ba67254d7ed 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"
SOURCE_BAK = SOURCE_FILE + '.bak'
do_compress = True
if os.path.exists(SOURCE_FILE) and os.path.exists(SOURCE_BAK):
src_mtime = os.stat(SOURCE_FILE).st_mtime
bak_mtime = os.stat(SOURCE_BAK).st_mtime
""" Recompress if .bin file is newer than .bak file """
do_compress = (src_mtime > bak_mtime)
if do_compress:
print("Compressing firmware for upload...")
shutil.move(SOURCE_FILE, SOURCE_BAK)
with open(SOURCE_BAK, 'rb') as f_in:
with gzip.open(SOURCE_FILE, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
""" Set modification time on compressed file so incremental build works """
shutil.copystat(SOURCE_BAK, SOURCE_FILE)
if os.path.exists(SOURCE_BAK):
ORG_FIRMWARE_SIZE = os.stat(SOURCE_BAK).st_size
GZ_FIRMWARE_SIZE = os.stat(SOURCE_FILE).st_size
print("Compression reduced firmware size to {:.0f}% (was {} bytes, now {} bytes)".format((GZ_FIRMWARE_SIZE / ORG_FIRMWARE_SIZE) * 100, ORG_FIRMWARE_SIZE, GZ_FIRMWARE_SIZE))
env.AddPreAction("upload", compressFirmware)
@ozanpalaz
Copy link

How can I use it to compress my own .bin files?

@pfeerick
Copy link

pfeerick commented Feb 22, 2021

@ozanpalaz Do you mean run this script standalone? It's specifically designed to work in conjunction with PlatformIO (to be called automatically during the upload process, hence the AddPreAction hook at the bottom of the file), so that won't be possible without some modification. It would require you to so something like remove Import("env"), change env.subst() calls to point to variables, and then have a main function that runs the function, and ensures the variables are loaded with valid info.

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