import struct import locale from collections import namedtuple from datetime import datetime import subprocess from distutils.version import StrictVersion import subprocess import os #locale.setlocale(locale.LC_ALL, 'en_US') # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) APP_DESC_OFFSET = 32 # sizeof(esp_app_desc_t) APP_DESC_SIZE = 256 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(file_name): def process_bytes(b): if not isinstance(b, bytes): return b s = b.decode() return s[:s.find("\x00")] with open(file_name, 'rb') as f: f.seek(APP_DESC_OFFSET, 0) raw_app_desc = f.read(APP_DESC_SIZE) unpacked = struct.unpack(APP_DESC_STRUCT, raw_app_desc) 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(file_name, 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 with open(file_name, 'r+b') as f: f.seek(APP_DESC_OFFSET, 0) raw_app_desc = f.read(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) f.seek(APP_DESC_OFFSET, 0) f.write(packed) def add_info_to_firmware(firmware_file, version): now = datetime.now() date = now.strftime("%b %d %Y") time = now.strftime("%H:%M:%S") patch_app_description(firmware_file, version=version, project_name="swimtracker.bauer.tech", time=time, date=date) if __name__ == "__main__": firmware_file = ".pio/build/esp32/firmware.bin" version_file_name = "VERSION" version = version_number_from_git() add_info_to_firmware(firmware_file, version) print(read_app_description(firmware_file)) 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)