From 8c716ae11e6cff45bb3dcca6a1898fc71a512677 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Mon, 24 May 2021 10:59:00 +0200 Subject: [PATCH 1/5] [skip changelog] Create generator script to create boards.json --- generator/generator.py | 144 +++++++++++ generator/raw_boards.json | 528 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 672 insertions(+) create mode 100644 generator/generator.py create mode 100644 generator/raw_boards.json diff --git a/generator/generator.py b/generator/generator.py new file mode 100644 index 00000000..32dd1a30 --- /dev/null +++ b/generator/generator.py @@ -0,0 +1,144 @@ +import json +import hashlib +import shutil +from pathlib import Path + +DOWNLOAD_URL = "https://downloads.arduino.cc" +FQBNS = { + "mkr1000": "arduino:samd:mkr1000", + "mkrwifi1010": "arduino:samd:mkrwifi1010", + "nano_33_iot": "arduino:samd:nano_33_iot", + "mkrvidor4000": "arduino:samd:mkrvidor4000", + "uno2018": "arduino:megaavr:uno2018", + "mkrnb1500": "arduino:samd:mkrnb1500", + "nanorp2040connect": "arduino:mbed_nano:nanorp2040connect", +} + + +# Generates file SHA256 +def sha2(file_path): + with open(file_path, "rb") as f: + return hashlib.sha256(f.read()).hexdigest() + + +# Generate and copy loader Sketch binary data for specified board +def create_loader_data(simple_fqbn, binary): + loader_path = f"firmwares/loader/{simple_fqbn}/loader.bin" + loader = Path(__file__).parent / loader_path + loader.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(binary, loader) + + file_hash = sha2(loader) + + return { + "url": f"{DOWNLOAD_URL}/{loader_path}", + "checksum": f"SHA-256:{file_hash}", + "size": f"{loader.stat().st_size}", + } + + +# Generate and copy all firmware binary data for specified board +def create_firmware_data(simple_fqbn, binary, module, version): + binary_name = binary.name + firmware_path = f"firmwares/{module}/{version}/{binary_name}" + firmware = Path(__file__).parent / firmware_path + firmware.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(binary, firmware) + + file_hash = sha2(firmware) + + return { + "version": version, + "url": f"{DOWNLOAD_URL}/{firmware_path}", + "checksum": f"SHA-256:{file_hash}", + "size": f"{firmware.stat().st_size}", + } + + +def generate_boards_json(input_data): + boards = { + "arduino:samd:mkr1000": {"fqbn": "arduino:samd:mkr1000", "firmware": []}, + "arduino:samd:mkrwifi1010": { + "fqbn": "arduino:samd:mkrwifi1010", + "firmware": [], + }, + "arduino:samd:nano_33_iot": { + "fqbn": "arduino:samd:nano_33_iot", + "firmware": [], + }, + "arduino:samd:mkrvidor4000": { + "fqbn": "arduino:samd:mkrvidor4000", + "firmware": [], + }, + "arduino:megaavr:uno2018": {"fqbn": "arduino:megaavr:uno2018", "firmware": []}, + "arduino:samd:mkrnb1500": {"fqbn": "arduino:samd:mkrnb1500", "firmware": []}, + "arduino:mbed_nano:nanorp2040connect": { + "fqbn": "arduino:mbed_nano:nanorp2040connect", + "firmware": [], + }, + } + + for pseudo_fqbn, data in input_data.items(): + fqbn = FQBNS[pseudo_fqbn] + simple_fqbn = fqbn.replace(":", ".") + + for _, v in data.items(): + item = v[0] + binary = Path(item["Path"]) + + if item["IsLoader"]: + boards[fqbn]["loader_sketch"] = create_loader_data(simple_fqbn, binary) + else: + module, version = item["version"].split("/") + boards[fqbn]["firmware"].append( + create_firmware_data(simple_fqbn, binary, module, version) + ) + + # TODO: Run arduino-cli to get board names and other things? + + boards_json = [] + for _, b in boards.items(): + boards_json.append(b) + + +if __name__ == "__main__": + # raw_boards.json has been generated using --get_available_for FirmwareUploader flag. + # It has been edited a bit to better handle parsing. + with open("raw_boards.json", "r") as f: + raw_boards = json.load(f) + + boards_json = generate_boards_json(raw_boards) + + with open("boards.json", "w") as f: + json.dump(boards_json, f, indent=2) + +# boards.json must be formatted like so: +# +# { +# "name": "MKR 1000", +# "fqbn": "arduino:samd:mkr1000", +# "module": "WINC_1500", +# "firmware": [ +# { +# "version": "19.6.1", +# "url": "https://downloads.arduino.cc/firmwares/WINC_1500/19.6.1/m2m_aio_3a0.bin", +# "checksum": "SHA-256:de0c6b1621aa15996432559efb5d8a29885f62bde145937eee99883bfa129f97", +# "size": "359356", +# }, +# { +# "version": "19.5.4", +# "url": "https://downloads.arduino.cc/firmwares/WINC_1500/19.5.4/m2m_aio_3a0.bin", +# "checksum": "SHA-256:71e5a805e60f96e6968414670d8a414a03cb610fd4b020f47ab53f5e1ff82a13", +# "size": "413604", +# }, +# ], +# "loader_sketch": { +# "url": "https://downloads.arduino.cc/firmwares/loader/arduino.samd.mkr1000/loader.bin", +# "checksum": "SHA-256:71e5a805e60f96e6968414670d8a414a03cb610fd4b020f47ab53f5e1ff82a13", +# "size": "39287", +# }, +# "uploader": "arduino:bossac@1.7.0", +# "uploader.command": "{uploader} --port={upload.port} -U true -i -e -w -v {loader.sketch} -R", +# "uploader.requires_1200_bps_touch": "true", +# "uploader.requires_port_change": "true", +# } diff --git a/generator/raw_boards.json b/generator/raw_boards.json new file mode 100644 index 00000000..e43617b9 --- /dev/null +++ b/generator/raw_boards.json @@ -0,0 +1,528 @@ +{ + "mkr1000": { + "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500": [ + { + "version": "WINC1500", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/FirmwareUpdater.mkr1000.ino.bin", + "Name": "firmwares WINC1500", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.4.4": [ + { + "version": "WINC1500/19.4.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.4.4/m2m_aio_3a0.bin", + "Name": "WINC1500 19.4.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.5.2": [ + { + "version": "WINC1500/19.5.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.5.2/m2m_aio_3a0.bin", + "Name": "WINC1500 19.5.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.5.4": [ + { + "version": "WINC1500/19.5.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.5.4/m2m_aio_3a0.bin", + "Name": "WINC1500 19.5.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.6.1": [ + { + "version": "WINC1500/19.6.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/WINC1500/19.6.1/m2m_aio_3a0.bin", + "Name": "WINC1500 19.6.1", + "IsLoader": false + } + ] + }, + "mkrwifi1010": { + "/home/alien/workspace/FirmwareUploader/firmwares/NINA": [ + { + "version": "NINA", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/FirmwareUpdater.mkrwifi1010.ino.bin", + "Name": "firmwares NINA", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0": [ + { + "version": "NINA/1.0.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0/NINA_W102.bin", + "Name": "NINA 1.0.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0": [ + { + "version": "NINA/1.1.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0/NINA_W102.bin", + "Name": "NINA 1.1.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1": [ + { + "version": "NINA/1.2.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1/NINA_W102.bin", + "Name": "NINA 1.2.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2": [ + { + "version": "NINA/1.2.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2/NINA_W102.bin", + "Name": "NINA 1.2.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3": [ + { + "version": "NINA/1.2.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3/NINA_W102.bin", + "Name": "NINA 1.2.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4": [ + { + "version": "NINA/1.2.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4/NINA_W102.bin", + "Name": "NINA 1.2.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0": [ + { + "version": "NINA/1.3.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0/NINA_W102.bin", + "Name": "NINA 1.3.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0": [ + { + "version": "NINA/1.4.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0/NINA_W102.bin", + "Name": "NINA 1.4.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1": [ + { + "version": "NINA/1.4.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1/NINA_W102.bin", + "Name": "NINA 1.4.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2": [ + { + "version": "NINA/1.4.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2/NINA_W102.bin", + "Name": "NINA 1.4.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3": [ + { + "version": "NINA/1.4.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3/NINA_W102.bin", + "Name": "NINA 1.4.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4": [ + { + "version": "NINA/1.4.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4/NINA_W102.bin", + "Name": "NINA 1.4.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5": [ + { + "version": "NINA/1.4.5", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5/NINA_W102.bin", + "Name": "NINA 1.4.5", + "IsLoader": false + } + ] + }, + "nano_33_iot": { + "/home/alien/workspace/FirmwareUploader/firmwares/NINA": [ + { + "version": "NINA", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/FirmwareUpdater.nano_33_iot.ino.bin", + "Name": "firmwares NINA", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0": [ + { + "version": "NINA/1.0.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0/NINA_W102.bin", + "Name": "NINA 1.0.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0": [ + { + "version": "NINA/1.1.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0/NINA_W102.bin", + "Name": "NINA 1.1.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1": [ + { + "version": "NINA/1.2.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1/NINA_W102.bin", + "Name": "NINA 1.2.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2": [ + { + "version": "NINA/1.2.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2/NINA_W102.bin", + "Name": "NINA 1.2.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3": [ + { + "version": "NINA/1.2.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3/NINA_W102.bin", + "Name": "NINA 1.2.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4": [ + { + "version": "NINA/1.2.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4/NINA_W102.bin", + "Name": "NINA 1.2.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0": [ + { + "version": "NINA/1.3.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0/NINA_W102.bin", + "Name": "NINA 1.3.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0": [ + { + "version": "NINA/1.4.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0/NINA_W102.bin", + "Name": "NINA 1.4.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1": [ + { + "version": "NINA/1.4.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1/NINA_W102.bin", + "Name": "NINA 1.4.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2": [ + { + "version": "NINA/1.4.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2/NINA_W102.bin", + "Name": "NINA 1.4.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3": [ + { + "version": "NINA/1.4.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3/NINA_W102.bin", + "Name": "NINA 1.4.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4": [ + { + "version": "NINA/1.4.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4/NINA_W102.bin", + "Name": "NINA 1.4.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5": [ + { + "version": "NINA/1.4.5", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5/NINA_W102.bin", + "Name": "NINA 1.4.5", + "IsLoader": false + } + ] + }, + "mkrvidor4000": { + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0": [ + { + "version": "NINA/1.0.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.0.0/NINA_W102.bin", + "Name": "NINA 1.0.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0": [ + { + "version": "NINA/1.1.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.1.0/NINA_W102.bin", + "Name": "NINA 1.1.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1": [ + { + "version": "NINA/1.2.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1/NINA_W102.bin", + "Name": "NINA 1.2.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2": [ + { + "version": "NINA/1.2.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2/NINA_W102.bin", + "Name": "NINA 1.2.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3": [ + { + "version": "NINA/1.2.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3/NINA_W102.bin", + "Name": "NINA 1.2.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4": [ + { + "version": "NINA/1.2.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4/NINA_W102.bin", + "Name": "NINA 1.2.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0": [ + { + "version": "NINA/1.3.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0/NINA_W102.bin", + "Name": "NINA 1.3.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0": [ + { + "version": "NINA/1.4.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0/NINA_W102.bin", + "Name": "NINA 1.4.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1": [ + { + "version": "NINA/1.4.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1/NINA_W102.bin", + "Name": "NINA 1.4.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2": [ + { + "version": "NINA/1.4.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2/NINA_W102.bin", + "Name": "NINA 1.4.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3": [ + { + "version": "NINA/1.4.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3/NINA_W102.bin", + "Name": "NINA 1.4.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4": [ + { + "version": "NINA/1.4.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4/NINA_W102.bin", + "Name": "NINA 1.4.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5": [ + { + "version": "NINA/1.4.5", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5/NINA_W102.bin", + "Name": "NINA 1.4.5", + "IsLoader": false + } + ] + }, + "uno2018": { + "/home/alien/workspace/FirmwareUploader/firmwares/NINA": [ + { + "version": "NINA", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/FirmwareUpdater.unowifirev2.without_bl.ino.hex", + "Name": "firmwares NINA", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1": [ + { + "version": "NINA/1.2.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.1/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.2.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2": [ + { + "version": "NINA/1.2.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.2/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.2.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3": [ + { + "version": "NINA/1.2.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.3/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.2.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4": [ + { + "version": "NINA/1.2.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.2.4/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.2.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0": [ + { + "version": "NINA/1.3.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.3.0/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.3.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0": [ + { + "version": "NINA/1.4.0", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.0/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.0", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1": [ + { + "version": "NINA/1.4.1", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.1/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.1", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2": [ + { + "version": "NINA/1.4.2", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.2/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.2", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3": [ + { + "version": "NINA/1.4.3", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.3/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.3", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4": [ + { + "version": "NINA/1.4.4", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.4/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.4", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5": [ + { + "version": "NINA/1.4.5", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5/NINA_W102-Uno_WiFi_Rev2.bin", + "Name": "NINA 1.4.5", + "IsLoader": false + } + ] + }, + "mkrnb1500": { + "/home/alien/workspace/FirmwareUploader/firmwares/SARA": [ + { + "version": "SARA", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/SARA/SerialSARAPassthrough.ino.bin", + "Name": "firmwares SARA", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/SARA/5.6A2.00-to-5.6A2.01": [ + { + "version": "SARA/5.6A2.00-to-5.6A2.01", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/SARA/5.6A2_01/5.6A2.00-to-5.6A2.01.pkg", + "Name": "SARA 5.6A2_01 (5.6A2.00-to-5.6A2.01.pkg)", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/SARA/5.6A2_01_to_99": [ + { + "version": "SARA/5.6A2_01_to_99", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/SARA/5.6A2_01/5.6A2_01_to_99.pkg", + "Name": "SARA 5.6A2_01 (5.6A2_01_to_99.pkg)", + "IsLoader": false + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/SARA/99_to_5.6A2_01": [ + { + "version": "SARA/99_to_5.6A2_01", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/SARA/5.6A2_01/99_to_5.6A2_01.pkg", + "Name": "SARA 5.6A2_01 (99_to_5.6A2_01.pkg)", + "IsLoader": false + } + ] + }, + "nanorp2040connect": { + "/home/alien/workspace/FirmwareUploader/firmwares/NINA": [ + { + "version": "NINA", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/FirmwareUpdater.nanorp2040connect.ino.elf", + "Name": "firmwares NINA", + "IsLoader": true + } + ], + "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5": [ + { + "version": "NINA/1.4.5", + "Path": "/home/alien/workspace/FirmwareUploader/firmwares/NINA/1.4.5/NINA_W102-Nano_RP2040_Connect.bin", + "Name": "NINA 1.4.5", + "IsLoader": false + } + ] + } +} From 8eb71fc89506610486c1d97912ff41249bb60b7d Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Tue, 25 May 2021 11:19:53 +0200 Subject: [PATCH 2/5] [skip changelog] Update generator script to gather upload info --- generator/generator.py | 137 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/generator/generator.py b/generator/generator.py index 32dd1a30..0d6edfb0 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -1,3 +1,6 @@ +import argparse +import subprocess +import sys import json import hashlib import shutil @@ -15,6 +18,12 @@ } +# Runs arduino-cli, doesn't handle errors at all because am lazy +def arduino_cli(cli_path, args=[]): + res = subprocess.run([cli_path, *args], capture_output=True, text=True) + return res.stdout + + # Generates file SHA256 def sha2(file_path): with open(file_path, "rb") as f: @@ -55,7 +64,92 @@ def create_firmware_data(simple_fqbn, binary, module, version): } -def generate_boards_json(input_data): +def create_upload_data(fqbn, installed_cores): + upload_data = {} + # Assume we're on Linux + arduino15 = Path.home() / ".arduino15" + + core_id = ":".join(fqbn.split(":")[:2]) + + # Get the core install dir + core = installed_cores[core_id] + (maintainer, arch) = core_id.split(":") + core_install_dir = ( + arduino15 / "packages" / maintainer / "hardware" / arch / core["installed"] + ) + + with open(core_install_dir / "boards.txt") as f: + boards_txt = f.readlines() + + board_upload_data = {} + for l in boards_txt: + board_id = fqbn.split(":")[2] + if l.startswith(f"{board_id}.upload"): + (k, v) = l.strip().split("=", maxsplit=1) + k = ".".join(k.split(".", maxsplit=1)[1:]) + board_upload_data[k] = v + + tool = board_upload_data["upload.tool"] + + with open(core_install_dir / "platform.txt") as f: + platform_txt = f.readlines() + + platform_upload_data = {} + for l in platform_txt: + if l.startswith(f"tools.{tool}"): + (k, v) = l.strip().split("=", maxsplit=1) + k = ".".join(k.split(".", maxsplit=1)[1:]) + platform_upload_data[k] = v + + # We assume the installed.json exist + with open(core_install_dir / "installed.json") as f: + installed_json_data = json.load(f) + + if f"{tool}.cmd" in platform_upload_data: + tool_executable = platform_upload_data[f"{tool}.cmd"] + elif f"{tool}.cmd.path" in platform_upload_data: + tool_executable = platform_upload_data[f"{tool}.cmd.path"].split("/")[-1] + + tools = installed_json_data["packages"][0]["platforms"][0]["toolsDependencies"] + for t in tools: + if tool_executable == "rp2040load": + # rp2040tools includes the rp2040load tool + if t["name"] == "rp2040tools": + packager = t["packager"] + name = t["name"] + version = t["version"] + upload_data["uploader"] = f"{packager}:{name}@{version}" + continue + + if t["name"] == tool_executable: + packager = t["packager"] + name = t["name"] + version = t["version"] + upload_data["uploader"] = f"{packager}:{name}@{version}" + break + + # We already store the tool name in a different manner + del board_upload_data["upload.tool"] + # Save also all the upload properties + for k, v in board_upload_data.items(): + if v: + upload_data[k] = v + + # Get the command used to upload and modifies it a bit + command = ( + platform_upload_data[f"{tool}.upload.pattern"] + .replace("{path}/{cmd}", "{uploader}") + .replace("{cmd.path}", "{uploader}") + .replace("{build.path}/{build.project_name}", "{loader.sketch}") + .replace('\\"', "") + ) + + upload_data["uploader.command"] = command + + return upload_data + + +def generate_boards_json(input_data, arduino_cli_path): boards = { "arduino:samd:mkr1000": {"fqbn": "arduino:samd:mkr1000", "firmware": []}, "arduino:samd:mkrwifi1010": { @@ -78,6 +172,20 @@ def generate_boards_json(input_data): }, } + # Gets the installed cores + res = arduino_cli( + cli_path=arduino_cli_path, args=["core", "list", "--format", "json"] + ) + installed_cores = {c["id"]: c for c in json.loads(res)} + + # Verify all necessary cores are installed + # TODO: Should we check that the latest version is installed too? + for fqbn in boards.keys(): + core_id = ":".join(fqbn.split(":")[:2]) + if core_id not in installed_cores: + print(f"Board {fqbn} is not installed, install its core {core_id}") + sys.exit(1) + for pseudo_fqbn, data in input_data.items(): fqbn = FQBNS[pseudo_fqbn] simple_fqbn = fqbn.replace(":", ".") @@ -93,21 +201,44 @@ def generate_boards_json(input_data): boards[fqbn]["firmware"].append( create_firmware_data(simple_fqbn, binary, module, version) ) + boards[fqbn]["module"] = module - # TODO: Run arduino-cli to get board names and other things? + res = arduino_cli( + cli_path=arduino_cli_path, + args=["board", "search", fqbn, "--format", "json"], + ) + # Gets the board name + for board in json.loads(res): + if board["fqbn"] == fqbn: + boards[fqbn]["name"] = board["name"] + break + + boards[fqbn].update(create_upload_data(fqbn, installed_cores)) boards_json = [] for _, b in boards.items(): boards_json.append(b) + return boards_json + if __name__ == "__main__": + parser = argparse.ArgumentParser(prog="generator.py") + parser.add_argument( + "-a", + "--arduino-cli", + default="arduino-cli", + help="Path to arduino-cli executable", + required=True, + ) + args = parser.parse_args(sys.argv[1:]) + # raw_boards.json has been generated using --get_available_for FirmwareUploader flag. # It has been edited a bit to better handle parsing. with open("raw_boards.json", "r") as f: raw_boards = json.load(f) - boards_json = generate_boards_json(raw_boards) + boards_json = generate_boards_json(raw_boards, args.arduino_cli) with open("boards.json", "w") as f: json.dump(boards_json, f, indent=2) From 3658fc588c23e35f9766416f5d58b984cb839533 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Tue, 25 May 2021 12:09:11 +0200 Subject: [PATCH 3/5] [skip changelog] Change download url and generated json name --- generator/generator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/generator/generator.py b/generator/generator.py index 0d6edfb0..dee23b93 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -6,7 +6,7 @@ import shutil from pathlib import Path -DOWNLOAD_URL = "https://downloads.arduino.cc" +DOWNLOAD_URL = "https://downloads.arduino.cc/arduino-fwuploader" FQBNS = { "mkr1000": "arduino:samd:mkr1000", "mkrwifi1010": "arduino:samd:mkrwifi1010", @@ -240,10 +240,12 @@ def generate_boards_json(input_data, arduino_cli_path): boards_json = generate_boards_json(raw_boards, args.arduino_cli) - with open("boards.json", "w") as f: + Path("boards").mkdir() + + with open("boards/board_index.json", "w") as f: json.dump(boards_json, f, indent=2) -# boards.json must be formatted like so: +# board_index.json must be formatted like so: # # { # "name": "MKR 1000", From 601dcb0d675f0a2cb42d4013209f57d27d90f76a Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Wed, 26 May 2021 11:28:49 +0200 Subject: [PATCH 4/5] [skip changelog] Small enhancements in generator script --- generator/generator.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/generator/generator.py b/generator/generator.py index dee23b93..8843d863 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -30,6 +30,12 @@ def sha2(file_path): return hashlib.sha256(f.read()).hexdigest() +def split_property_and_drop_first_level(s): + (k, v) = s.strip().split("=", maxsplit=1) + k = ".".join(k.split(".", maxsplit=1)[1:]) + return (k, v) + + # Generate and copy loader Sketch binary data for specified board def create_loader_data(simple_fqbn, binary): loader_path = f"firmwares/loader/{simple_fqbn}/loader.bin" @@ -47,7 +53,7 @@ def create_loader_data(simple_fqbn, binary): # Generate and copy all firmware binary data for specified board -def create_firmware_data(simple_fqbn, binary, module, version): +def create_firmware_data(binary, module, version): binary_name = binary.name firmware_path = f"firmwares/{module}/{version}/{binary_name}" firmware = Path(__file__).parent / firmware_path @@ -85,8 +91,7 @@ def create_upload_data(fqbn, installed_cores): for l in boards_txt: board_id = fqbn.split(":")[2] if l.startswith(f"{board_id}.upload"): - (k, v) = l.strip().split("=", maxsplit=1) - k = ".".join(k.split(".", maxsplit=1)[1:]) + (k, v) = split_property_and_drop_first_level(l) board_upload_data[k] = v tool = board_upload_data["upload.tool"] @@ -97,8 +102,7 @@ def create_upload_data(fqbn, installed_cores): platform_upload_data = {} for l in platform_txt: if l.startswith(f"tools.{tool}"): - (k, v) = l.strip().split("=", maxsplit=1) - k = ".".join(k.split(".", maxsplit=1)[1:]) + (k, v) = split_property_and_drop_first_level(l) platform_upload_data[k] = v # We assume the installed.json exist @@ -199,7 +203,7 @@ def generate_boards_json(input_data, arduino_cli_path): else: module, version = item["version"].split("/") boards[fqbn]["firmware"].append( - create_firmware_data(simple_fqbn, binary, module, version) + create_firmware_data(binary, module, version) ) boards[fqbn]["module"] = module From 3eaf2a85d275159ee19f9810afeb18c02125640d Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Wed, 26 May 2021 11:59:44 +0200 Subject: [PATCH 5/5] [skip changelog] Reduce function complexity --- generator/generator.py | 43 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/generator/generator.py b/generator/generator.py index 8843d863..281c4e65 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -70,11 +70,21 @@ def create_firmware_data(binary, module, version): } +def get_uploader_id(tools, tool_executable): + for t in tools: + if t["name"] == tool_executable: + packager = t["packager"] + name = t["name"] + version = t["version"] + return f"{packager}:{name}@{version}" + + def create_upload_data(fqbn, installed_cores): upload_data = {} # Assume we're on Linux arduino15 = Path.home() / ".arduino15" + board_id = fqbn.split(":")[2] core_id = ":".join(fqbn.split(":")[:2]) # Get the core install dir @@ -88,10 +98,9 @@ def create_upload_data(fqbn, installed_cores): boards_txt = f.readlines() board_upload_data = {} - for l in boards_txt: - board_id = fqbn.split(":")[2] - if l.startswith(f"{board_id}.upload"): - (k, v) = split_property_and_drop_first_level(l) + for line in boards_txt: + if line.startswith(f"{board_id}.upload"): + (k, v) = split_property_and_drop_first_level(line) board_upload_data[k] = v tool = board_upload_data["upload.tool"] @@ -100,9 +109,9 @@ def create_upload_data(fqbn, installed_cores): platform_txt = f.readlines() platform_upload_data = {} - for l in platform_txt: - if l.startswith(f"tools.{tool}"): - (k, v) = split_property_and_drop_first_level(l) + for line in platform_txt: + if line.startswith(f"tools.{tool}"): + (k, v) = split_property_and_drop_first_level(line) platform_upload_data[k] = v # We assume the installed.json exist @@ -114,23 +123,11 @@ def create_upload_data(fqbn, installed_cores): elif f"{tool}.cmd.path" in platform_upload_data: tool_executable = platform_upload_data[f"{tool}.cmd.path"].split("/")[-1] - tools = installed_json_data["packages"][0]["platforms"][0]["toolsDependencies"] - for t in tools: - if tool_executable == "rp2040load": - # rp2040tools includes the rp2040load tool - if t["name"] == "rp2040tools": - packager = t["packager"] - name = t["name"] - version = t["version"] - upload_data["uploader"] = f"{packager}:{name}@{version}" - continue + if tool_executable == "rp2040load": + tool_executable = "rp2040tools" - if t["name"] == tool_executable: - packager = t["packager"] - name = t["name"] - version = t["version"] - upload_data["uploader"] = f"{packager}:{name}@{version}" - break + tools = installed_json_data["packages"][0]["platforms"][0]["toolsDependencies"] + upload_data["uploader"] = get_uploader_id(tools, tool_executable) # We already store the tool name in a different manner del board_upload_data["upload.tool"]