""" PlatformIO post-build script: generates a Nordic DFU package (.zip) from the built firmware .hex using adafruit-nrfutil. The resulting firmware_dfu.zip can be uploaded to the device via: - nRF Connect mobile app (iOS / Android) after triggering OTA mode - nRF Connect for Desktop - adafruit-nrfutil over BLE (advanced) Trigger OTA mode on the device: - Send BLE command 0x02 to cfgCommand (0x1236), OR - Type 'o' in the serial monitor Usage: referenced from platformio.ini as: extra_scripts = pre:scripts/git_hash.py, post:scripts/generate_dfu.py """ import subprocess, os Import("env") # noqa: F821 - PlatformIO injects this def generate_dfu_package(source, target, env): build_dir = env.subst("$BUILD_DIR") project_dir = env.subst("$PROJECT_DIR") hex_path = os.path.join(build_dir, "firmware.hex") if not os.path.exists(hex_path): print(f"[generate_dfu] firmware.hex not found at {hex_path}, skipping") return out_path = os.path.join(project_dir, "firmware_dfu.zip") try: result = subprocess.run( [ "adafruit-nrfutil", "dfu", "genpkg", "--dev-type", "0x0052", # nRF52840 "--application", hex_path, out_path, ], capture_output=True, text=True, ) if result.returncode == 0: size_kb = os.path.getsize(out_path) / 1024 print(f"[generate_dfu] DFU package ready: firmware_dfu.zip ({size_kb:.1f} KB)") print(f"[generate_dfu] Upload with nRF Connect after sending OTA command (0x02) via BLE") else: print(f"[generate_dfu] adafruit-nrfutil error: {result.stderr.strip()}") except FileNotFoundError: print("[generate_dfu] adafruit-nrfutil not found - skipping DFU package generation") print("[generate_dfu] Install with: pip install adafruit-nrfutil") env.AddPostAction("$BUILD_DIR/firmware.hex", generate_dfu_package) # noqa: F821