#!/usr/bin/env python3 """ PlatformIO extra script: generate DFU .zip after build. Add to platformio.ini: extra_scripts = post:flasher/pio_create_dfu_zip.py """ import sys import os import json import struct import zipfile # Add flasher dir to path for importing the main module sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: from create_dfu_zip import hex_to_bin, uf2_to_bin, create_dfu_zip except ImportError: # Fallback: define minimal conversion inline def hex_to_bin(hex_path): from intelhex import IntelHex ih = IntelHex(hex_path) min_addr = ih.minaddr() or 0 max_addr = ih.maxaddr() or 0 size = max_addr - min_addr + 1 page_size = 0x1000 aligned = ((size + page_size - 1) // page_size) * page_size return bytes(ih.tobinarray(start=min_addr, size=aligned)), min_addr def create_dfu_zip(bin_data, base_addr, fw_version=1, hw_version=52): init_packet = bytearray() init_packet.append(0x01) init_packet.append(0x04) init_packet += struct.pack(' Heltec_T114_Beacon_BLE parts = env_name.split("_") if "beacon" in parts: fw_name = "Heltec_T114_Beacon" elif "companion" in parts: fw_name = "Heltec_T114_Companion_Radio" elif "repeater" in parts: fw_name = "Heltec_T114_Repeater" elif "room" in parts: fw_name = "Heltec_T114_Room_Server" else: fw_name = "firmware" if "ble" in parts: fw_name += "_BLE" elif "usb" in parts: fw_name += "_USB" zip_name = f"{fw_name}.dfu.zip" zip_path = os.path.join(build_dir, zip_name) with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf: zf.writestr("manifest.json", json.dumps(manifest, indent=2)) zf.writestr("firmware.bin", fw_bin) zf.writestr("firmware.dat", fw_dat) size = os.path.getsize(zip_path) print(f" [DFU] Created: {zip_path} ({size / 1024:.0f} KB)") # Register hook Import("env") env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex", create_dfu_zip_from_build) # Also trigger after .uf2 creation if that action exists try: env.AddPostAction("$BUILD_DIR/${PROGNAME}.uf2", create_dfu_zip_from_build) except: pass