feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s

Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
Codex Local
2026-10-08 10:06:44 +08:00
parent 98fb2965d0
commit bf1233d5df
861 changed files with 94614 additions and 3209 deletions
@@ -0,0 +1,80 @@
import importlib.util
import json
from pathlib import Path
import sys
import tempfile
import unittest
TOOLS = Path(__file__).resolve().parents[1] / "tools"
sys.path.insert(0, str(TOOLS))
import device_prepare as prepare
class PrepareTests(unittest.TestCase):
def setUp(self):
self.directory = tempfile.TemporaryDirectory()
self.addCleanup(self.directory.cleanup)
self.root = Path(self.directory.name)
self.credential = self.root / "credential.json"
self.value = {"factory_id": "KP01-0123456789AB", "model": "ECHOEAR-S3",
"origin": "https://example.com", "key_version": 1,
"device_key_hex": "01" * 32}
self.save()
def save(self):
self.credential.write_text(json.dumps(self.value), encoding="utf-8-sig")
def test_accepts_actual_web_download(self):
self.assertEqual(prepare.read_credential(self.credential)["device_id"], self.value["factory_id"])
def test_legacy_id(self):
self.value["device_id"] = self.value.pop("factory_id")
self.save()
self.assertEqual(prepare.read_credential(self.credential)["device_id"], self.value["device_id"])
def test_rejects_conflicting_identity(self):
self.value["device_id"] = "KP01-AAAAAAAAAAAA"
self.save()
with self.assertRaises(ValueError):
prepare.read_credential(self.credential)
def test_rejects_bad_configuration(self):
for field, value in [("model", "different-board"), ("key_version", True),
("key_version", 0), ("device_key_hex", "bad"),
("origin", "http://example.com"),
("origin", "https://user:password@example.com"),
("origin", "https://example.com/path"),
("origin", "https://example.com:invalid")]:
original = self.value[field]
self.value[field] = value
self.save()
with self.subTest(field=field, value=value), self.assertRaises(ValueError):
prepare.read_credential(self.credential)
self.value[field] = original
def test_mac_independent_of_factory_id(self):
self.assertEqual(prepare.normalize_mac("B4-3A-45-16-34-A8"), "b4:3a:45:16:34:a8")
@unittest.skipUnless(importlib.util.find_spec("esp_idf_nvs_partition_gen"), "NVS generator unavailable")
def test_real_nvs_generation_and_no_overwrite(self):
output = self.root / "private"
manifest = prepare.prepare(self.credential, output, "B4:3A:45:16:34:A8")
image = (output / "ble_factory.bin").read_bytes()
self.assertEqual(len(image), 0x6000)
self.assertIn(bytes.fromhex(self.value["device_key_hex"]), image)
self.assertEqual(manifest["expected_mac"], "b4:3a:45:16:34:a8")
self.assertNotIn("device_key_hex", json.dumps(manifest))
self.assertNotIn(self.value["device_key_hex"], (output / "setup-label.json").read_text())
if (TOOLS.parent / "build" / "flasher_args.json").is_file():
import device_flash
plan = device_flash.build_plan(TOOLS.parent / "build", output,
identity_only=True, reset_runtime=True,
expect_mac="B4:3A:45:16:34:A8")
self.assertEqual({item.name for item in plan.images}, {"reset-runtime", "ble_factory"})
self.assertEqual(next(item.data for item in plan.images if item.name == "ble_factory"), image)
with self.assertRaises(FileExistsError):
prepare.prepare(self.credential, output, "B4:3A:45:16:34:A8")
if __name__ == "__main__":
unittest.main()