"""固件库 + OTA 推送(firmware.py / api.py 的 /api/firmware、/api/boards/{id}/ota)。 断言打在「板子那头真的收到了什么」上(SimBoard.received),和 test_core 同一个口径。""" import hashlib import os import stat import struct import time import pytest from fastapi.testclient import TestClient from prrack.api import create_app from prrack.bus import MemBroker, MemBus from prrack.db import Db, now_ms from prrack.firmware import SLOT_BYTES, FwError, FwStore, parse_image from prrack.hub import Hub from prrack.recovery import RecoveryManager from prrack.simboard import SimBoard B = "b81f3fc9c8bc" BASE = "http://home.example:7765/fw" def image(version="0.1.0-c2", project="phonerail", size=4096, salt=b"", warm=False) -> bytes: """最小的「像 ESP app 镜像」:镜像头 24 B + 段头 8 B + esp_app_desc_t。""" hdr = bytes([0xE9, 3, 2, 0x4F]) + b"\0" * 20 + b"\0" * 8 desc = struct.pack("