diff --git a/firmware/deploy-firmware.py b/firmware/deploy-firmware.py new file mode 100644 index 0000000..146789f --- /dev/null +++ b/firmware/deploy-firmware.py @@ -0,0 +1,129 @@ +import struct +from collections import namedtuple +from datetime import datetime +import subprocess +from distutils.version import StrictVersion +from esptool import LoadFirmwareImage # required to get hash and checksum right +import os + +# locale.setlocale(locale.LC_ALL, 'en_US') + +APP_DESC_SIZE = 256 # sizeof(esp_app_desc_t) + +APP_DESC_STRUCT = " 0 + + if int(commits_since_tag) == 0: + version_string = latest_release + else: + next_version = increment_version(latest_release) + version_string = version_format.format( + version=next_version, commits=commits_since_tag, sha=sha) + + if is_dirty: + version_string += ".dirty" + return version_string + + +def read_app_description_from_segment(segment): + def process_bytes(b): + if not isinstance(b, bytes): + return b + s = b.decode() + return s[:s.find("\x00")] + + unpacked = struct.unpack(APP_DESC_STRUCT, segment.data[:APP_DESC_SIZE]) + unpacked = tuple(process_bytes(e) for e in unpacked) + magic_word, secure_version, _, _, version, project_name, time, date, idf_ver, app_elf_sha256, *_ = unpacked + assert magic_word == 0xABCD5432 + return AppDesc(secure_version, version, project_name, time, date, idf_ver, app_elf_sha256) + + + +def patch_app_description_in_segment(segment, version, project_name, time, date): + assert len(version) < 32 + assert len(project_name) < 32 + assert len(time) < 16 + assert len(date) < 16 + + def fill_zeros(s, total_length): + s += "\x00" * (total_length - len(s)) + s = s.encode() + assert len(s) == total_length + return s + + raw_app_desc = segment.data[:APP_DESC_SIZE] + unpacked = list(struct.unpack(APP_DESC_STRUCT, raw_app_desc)) + unpacked[4] = fill_zeros(version, 32) + unpacked[5] = fill_zeros(project_name, 32) + unpacked[6] = fill_zeros(time, 16) + unpacked[7] = fill_zeros(date, 16) + packed = struct.pack(APP_DESC_STRUCT, *unpacked) + + original_data = segment.data + segment.data = packed + original_data[APP_DESC_SIZE:] + + +def patch_firmware(input_file, output_file): + img = LoadFirmwareImage("esp32", input_file) + version = version_number_from_git() + + now = datetime.now() + time = now.strftime("%H:%M:%S") + date = now.strftime("%b %d %Y") + patch_app_description_in_segment(img.segments[0], version, "swimtracker.bauer.tech", time, date) + img.save(output_file) + + +if __name__ == "__main__": + firmware_file = ".pio/build/esp32/firmware.bin" + version_file_name = "VERSION" + + patch_firmware(firmware_file, firmware_file) # patch inplace + + version = version_number_from_git() + print("Deploying ", version) + with open(version_file_name, "w") as version_file: + print(version, file=version_file) + + subprocess.run(["scp", firmware_file, "root@server:/volumes/swimtracker-update"]) + subprocess.run(["scp", version_file_name, "root@server:/volumes/swimtracker-update"]) + + os.unlink(firmware_file) + os.unlink(version_file_name) + diff --git a/firmware/esp-idf-install.readme b/firmware/esp-idf-install.readme new file mode 100644 index 0000000..8f356eb --- /dev/null +++ b/firmware/esp-idf-install.readme @@ -0,0 +1,20 @@ +git clone -b v3.3 --recursive https://github.com/espressif/esp-idf.git +set -x IDF_TOOLS_PATH /home/martin/code/swimtracker-firmware/idf-tools +cd esp-idf +./install.fish + +# install arduino +mdir components +cd components +git clone https://github.com/espressif/arduino-esp32.git arduino + +# to get into environment (works only bash?) +export IDF_TOOLS_PATH=/home/martin/code/swimtracker-firmware/idf-tools/ +. /home/martin/code/swimtracker-firmware/esp-idf/export.sh + + ++ use only arduino libraries that are really necessary => smaller firmware + +-> result: new esp-idf version doesn't work together with arduino-esp +-> use 3.3? +-> not yet clear: how to use arduino component libraries \ No newline at end of file