This script injects a git-based firmware version into PlatformIO ESP32 firmware

This is a Python script that you can use in your PlatformIO build process to inject a firmware version string based on the current Git tag and commit into your ESP32 firmware binary. This is useful for tracking which version of the firmware is running on your device.

An example for a version it could inject is v1.0.0-123-gabc1234@2025-08-27T02:06:15.

#!/usr/bin/env python3
import subprocess
from datetime import datetime
import argparse
import sys


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--environment", help="The build environment to use")
    parser.add_argument("--chip", default="esp32", help="The chip to use (for esptool.py elf2image)")
    parser.add_argument("--flash_freq", default="40m", help="The flash frequency (for esptool.py elf2image)")
    parser.add_argument("--flash_mode", default="dio", help="The flash mode (for esptool.py elf2image)")
    args = parser.parse_args()

    # Determine git version & build date
    version = subprocess.check_output("git describe --long --tags --dirty", shell=True).strip().decode("utf-8")
    date = datetime.utcnow().isoformat()

    # Join version & date
    full_version_string = f"{version}@{date}".encode("utf-8")
    firmware_version_template = b"================================================================================"

    # If no environment is specified, just print the version and exit
    if not args.environment:
        print(f"Version: {version}")
        print("No --environment specified, exiting...")
        sys.exit(1)

    with open(f".pio/build/{args.environment}/firmware.elf", "rb") as infile:
        firmware_binary = infile.read()
        # The replacement strings must have exactly the right length!
        version_replacement = full_version_string.ljust(len(firmware_version_template), b'\0')
        # Replace!
        firmware_binary = firmware_binary.replace(firmware_version_template, version_replacement, 1)
        
    # Write back to file
    with open(f".pio/build/{args.environment}/firmware-versioned.elf", "wb") as outfile:
        outfile.write(firmware_binary)
        
    # Write version to file
    with open(f".pio/build/{args.environment}/version.txt", "w", encoding="utf-8") as outfile:
        outfile.write(version)
        
    # Convert to ELF
    subprocess.check_output(f"esptool.py --chip {args.chip} elf2image --flash_freq {args.flash_freq} --flash_mode {args.flash_mode} .pio/build/{args.environment}/firmware-versioned.elf", shell=True)