update: Major Overhault to all subsystems
This commit is contained in:
@@ -8,11 +8,11 @@ from fastapi import HTTPException
|
||||
from config import settings
|
||||
from shared.firebase import get_db
|
||||
from shared.exceptions import NotFoundError
|
||||
from firmware.models import FirmwareVersion, FirmwareLatestResponse
|
||||
from firmware.models import FirmwareVersion, FirmwareMetadataResponse, UpdateType
|
||||
|
||||
COLLECTION = "firmware_versions"
|
||||
|
||||
VALID_HW_TYPES = {"vs", "vp", "vx"}
|
||||
VALID_HW_TYPES = {"vesper", "vesper_plus", "vesper_pro", "chronos", "chronos_pro", "agnus", "agnus_mini"}
|
||||
VALID_CHANNELS = {"stable", "beta", "alpha", "testing"}
|
||||
|
||||
|
||||
@@ -36,23 +36,43 @@ def _doc_to_firmware_version(doc) -> FirmwareVersion:
|
||||
filename=data.get("filename", "firmware.bin"),
|
||||
size_bytes=data.get("size_bytes", 0),
|
||||
sha256=data.get("sha256", ""),
|
||||
update_type=data.get("update_type", UpdateType.mandatory),
|
||||
min_fw_version=data.get("min_fw_version"),
|
||||
uploaded_at=uploaded_str,
|
||||
notes=data.get("notes"),
|
||||
is_latest=data.get("is_latest", False),
|
||||
)
|
||||
|
||||
|
||||
def _fw_to_metadata_response(fw: FirmwareVersion) -> FirmwareMetadataResponse:
|
||||
download_url = f"/api/firmware/{fw.hw_type}/{fw.channel}/{fw.version}/firmware.bin"
|
||||
return FirmwareMetadataResponse(
|
||||
hw_type=fw.hw_type,
|
||||
channel=fw.channel,
|
||||
version=fw.version,
|
||||
size_bytes=fw.size_bytes,
|
||||
sha256=fw.sha256,
|
||||
update_type=fw.update_type,
|
||||
min_fw_version=fw.min_fw_version,
|
||||
download_url=download_url,
|
||||
uploaded_at=fw.uploaded_at,
|
||||
notes=fw.notes,
|
||||
)
|
||||
|
||||
|
||||
def upload_firmware(
|
||||
hw_type: str,
|
||||
channel: str,
|
||||
version: str,
|
||||
file_bytes: bytes,
|
||||
update_type: UpdateType = UpdateType.mandatory,
|
||||
min_fw_version: str | None = None,
|
||||
notes: str | None = None,
|
||||
) -> FirmwareVersion:
|
||||
if hw_type not in VALID_HW_TYPES:
|
||||
raise HTTPException(status_code=400, detail=f"Invalid hw_type. Must be one of: {', '.join(VALID_HW_TYPES)}")
|
||||
raise HTTPException(status_code=400, detail=f"Invalid hw_type. Must be one of: {', '.join(sorted(VALID_HW_TYPES))}")
|
||||
if channel not in VALID_CHANNELS:
|
||||
raise HTTPException(status_code=400, detail=f"Invalid channel. Must be one of: {', '.join(VALID_CHANNELS)}")
|
||||
raise HTTPException(status_code=400, detail=f"Invalid channel. Must be one of: {', '.join(sorted(VALID_CHANNELS))}")
|
||||
|
||||
dest = _storage_path(hw_type, channel, version)
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
@@ -83,6 +103,8 @@ def upload_firmware(
|
||||
"filename": "firmware.bin",
|
||||
"size_bytes": len(file_bytes),
|
||||
"sha256": sha256,
|
||||
"update_type": update_type.value,
|
||||
"min_fw_version": min_fw_version,
|
||||
"uploaded_at": now,
|
||||
"notes": notes,
|
||||
"is_latest": True,
|
||||
@@ -108,7 +130,7 @@ def list_firmware(
|
||||
return items
|
||||
|
||||
|
||||
def get_latest(hw_type: str, channel: str) -> FirmwareLatestResponse:
|
||||
def get_latest(hw_type: str, channel: str) -> FirmwareMetadataResponse:
|
||||
if hw_type not in VALID_HW_TYPES:
|
||||
raise HTTPException(status_code=400, detail=f"Invalid hw_type '{hw_type}'")
|
||||
if channel not in VALID_CHANNELS:
|
||||
@@ -126,18 +148,29 @@ def get_latest(hw_type: str, channel: str) -> FirmwareLatestResponse:
|
||||
if not docs:
|
||||
raise NotFoundError("Firmware")
|
||||
|
||||
fw = _doc_to_firmware_version(docs[0])
|
||||
download_url = f"/api/firmware/{hw_type}/{channel}/{fw.version}/firmware.bin"
|
||||
return FirmwareLatestResponse(
|
||||
hw_type=fw.hw_type,
|
||||
channel=fw.channel,
|
||||
version=fw.version,
|
||||
size_bytes=fw.size_bytes,
|
||||
sha256=fw.sha256,
|
||||
download_url=download_url,
|
||||
uploaded_at=fw.uploaded_at,
|
||||
notes=fw.notes,
|
||||
return _fw_to_metadata_response(_doc_to_firmware_version(docs[0]))
|
||||
|
||||
|
||||
def get_version_info(hw_type: str, channel: str, version: str) -> FirmwareMetadataResponse:
|
||||
"""Fetch metadata for a specific version. Used by devices resolving upgrade chains."""
|
||||
if hw_type not in VALID_HW_TYPES:
|
||||
raise HTTPException(status_code=400, detail=f"Invalid hw_type '{hw_type}'")
|
||||
if channel not in VALID_CHANNELS:
|
||||
raise HTTPException(status_code=400, detail=f"Invalid channel '{channel}'")
|
||||
|
||||
db = get_db()
|
||||
docs = list(
|
||||
db.collection(COLLECTION)
|
||||
.where("hw_type", "==", hw_type)
|
||||
.where("channel", "==", channel)
|
||||
.where("version", "==", version)
|
||||
.limit(1)
|
||||
.stream()
|
||||
)
|
||||
if not docs:
|
||||
raise NotFoundError("Firmware version")
|
||||
|
||||
return _fw_to_metadata_response(_doc_to_firmware_version(docs[0]))
|
||||
|
||||
|
||||
def get_firmware_path(hw_type: str, channel: str, version: str) -> Path:
|
||||
|
||||
Reference in New Issue
Block a user