Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename firmware types and support variant metadata #81

Merged
merged 7 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ jobs:
with:
CODE_FOLDER: universal_silabs_flasher
CACHE_VERSION: 2
PYTHON_VERSION_DEFAULT: 3.8.14
PRE_COMMIT_CACHE_PATH: ~/.cache/pre-commit
MINIMUM_COVERAGE_PERCENTAGE: 40
secrets:
Expand Down
Binary file not shown.
43 changes: 35 additions & 8 deletions tests/test_firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ def test_firmware_ebl_valid():
fw.get_nabucasa_metadata()


def test_firmware_gbl_valid_no_metadata():
data = (
FIRMWARES_DIR / "NabuCasa_EZSP_v6.10.3.0_PB32_ncp-uart-hw_115200.gbl"
).read_bytes()
fw = firmware.parse_firmware_image(data)

assert isinstance(fw, firmware.GBLImage)
assert fw.serialize() == data

with pytest.raises(KeyError):
fw.get_nabucasa_metadata()


def test_firmware_gbl_valid_with_metadata():
data = (
FIRMWARES_DIR / "NabuCasa_SkyConnect_RCP_v4.1.3_rcp-uart-hw-802154_115200.gbl"
Expand All @@ -32,7 +45,8 @@ def test_firmware_gbl_valid_with_metadata():
sdk_version=Version("4.1.3"),
ezsp_version=None,
cpc_version=None,
fw_type=firmware.FirmwareImageType.RCP_UART_802154,
fw_type=firmware.FirmwareImageType.MULTIPAN,
fw_variant=None,
ot_rcp_version=None,
baudrate=None,
original_json={
Expand All @@ -43,14 +57,27 @@ def test_firmware_gbl_valid_with_metadata():
)


def test_firmware_gbl_valid_no_metadata():
data = (
FIRMWARES_DIR / "NabuCasa_EZSP_v6.10.3.0_PB32_ncp-uart-hw_115200.gbl"
).read_bytes()
def test_firmware_gbl_valid_with_metadata_v2():
data = (FIRMWARES_DIR / "skyconnect_zigbee_ncp_7.4.4.0.gbl").read_bytes()
fw = firmware.parse_firmware_image(data)

assert isinstance(fw, firmware.GBLImage)
assert fw.serialize() == data

with pytest.raises(KeyError):
fw.get_nabucasa_metadata()
assert fw.get_nabucasa_metadata() == firmware.NabuCasaMetadata(
metadata_version=2,
sdk_version=Version("4.4.4"),
ezsp_version=Version("7.4.4.0"),
cpc_version=None,
fw_type=firmware.FirmwareImageType.ZIGBEE_NCP,
fw_variant=None,
ot_rcp_version=None,
baudrate=115200,
original_json={
"baudrate": 115200,
"ezsp_version": "7.4.4.0",
"fw_type": "zigbee_ncp",
"fw_variant": None,
"metadata_version": 2,
"sdk_version": "4.4.4",
},
)
43 changes: 21 additions & 22 deletions universal_silabs_flasher/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@


class FirmwareImageType(enum.Enum):
# EmberZNet Zigbee firmware
NCP_UART_HW = "ncp-uart-hw"

# Multi-PAN RCP Multiprotocol (via zigbeed)
RCP_UART_802154 = "rcp-uart-802154"

# Zigbee NCP + OpenThread RCP
ZIGBEE_NCP_RCP_UART_802154 = "zigbee-ncp-rcp-uart-802154"

# OpenThread RCP
OT_RCP = "ot-rcp"

# Z-Wave
Z_WAVE = "z-wave"

# Gecko Bootloader
GECKO_BOOTLOADER = "gecko-bootloader"
ZIGBEE_NCP = "zigbee_ncp"
OPENTHREAD_RCP = "openthread_rcp"
ZWAVE_NCP = "zwave_ncp"
BOOTLOADER = "bootloader"
MULTIPAN = "multipan"

UNKNOWN = "unknown"


LEGACY_FIRMWARE_TYPE_REMAPPING = {
"ncp-uart-hw": FirmwareImageType.ZIGBEE_NCP,
"ncp-uart-sw": FirmwareImageType.ZIGBEE_NCP,
"rcp-uart-802154": FirmwareImageType.MULTIPAN,
"ot-rcp": FirmwareImageType.OPENTHREAD_RCP,
"z-wave": FirmwareImageType.ZWAVE_NCP,
"gecko-bootloader": FirmwareImageType.BOOTLOADER,
}


class ApplicationType(enum.Enum):
Expand All @@ -29,11 +29,10 @@ class ApplicationType(enum.Enum):


FW_IMAGE_TYPE_TO_APPLICATION_TYPE = {
FirmwareImageType.NCP_UART_HW: ApplicationType.EZSP,
FirmwareImageType.RCP_UART_802154: ApplicationType.CPC,
FirmwareImageType.ZIGBEE_NCP_RCP_UART_802154: ApplicationType.CPC,
FirmwareImageType.OT_RCP: ApplicationType.SPINEL,
FirmwareImageType.GECKO_BOOTLOADER: ApplicationType.GECKO_BOOTLOADER,
FirmwareImageType.ZIGBEE_NCP: ApplicationType.EZSP,
FirmwareImageType.MULTIPAN: ApplicationType.CPC,
FirmwareImageType.OPENTHREAD_RCP: ApplicationType.SPINEL,
FirmwareImageType.BOOTLOADER: ApplicationType.GECKO_BOOTLOADER,
}


Expand Down
18 changes: 15 additions & 3 deletions universal_silabs_flasher/firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import zigpy.types as zigpy_t

from .common import Version, pad_to_multiple
from .const import FirmwareImageType
from .const import LEGACY_FIRMWARE_TYPE_REMAPPING, FirmwareImageType

_LOGGER = logging.getLogger(__name__)

NABUCASA_METADATA_VERSION = 1
NABUCASA_METADATA_VERSION = 2


class GBLTagId(zigpy_t.enum32):
Expand Down Expand Up @@ -72,6 +72,7 @@ class NabuCasaMetadata:
cpc_version: Version | None

fw_type: FirmwareImageType | None
fw_variant: str | None
baudrate: int | None

original_json: dict[str, typing.Any] = dataclasses.field(repr=False)
Expand Down Expand Up @@ -108,7 +109,17 @@ def from_json(cls, obj: dict[str, typing.Any]) -> NabuCasaMetadata:
cpc_version = Version(cpc_version)

if fw_type := obj.pop("fw_type", None):
fw_type = FirmwareImageType(fw_type)
if fw_type in LEGACY_FIRMWARE_TYPE_REMAPPING:
fw_type = LEGACY_FIRMWARE_TYPE_REMAPPING[fw_type]

try:
fw_type = FirmwareImageType(fw_type)
except ValueError:
_LOGGER.warning("Unknown firmware type: %r", fw_type)
fw_type = None

if fw_variant := obj.pop("fw_variant", None):
fw_variant = fw_variant

baudrate = obj.pop("baudrate", None)

Expand All @@ -122,6 +133,7 @@ def from_json(cls, obj: dict[str, typing.Any]) -> NabuCasaMetadata:
ot_rcp_version=ot_rcp_version,
cpc_version=cpc_version,
fw_type=fw_type,
fw_variant=fw_variant,
baudrate=baudrate,
original_json=original_json,
)
Expand Down
9 changes: 5 additions & 4 deletions universal_silabs_flasher/flash.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ async def flash(

try:
metadata = fw_image.get_nabucasa_metadata()
except KeyError:
except Exception:
_LOGGER.info("Failed to read firmware metadata: {exc!r}")
metadata = None
else:
_LOGGER.info("Extracted GBL metadata: %s", metadata)
Expand Down Expand Up @@ -343,12 +344,12 @@ async def flash(
raise click.ClickException(str(e)) from e

if flasher.app_type == ApplicationType.EZSP:
running_image_type = FirmwareImageType.NCP_UART_HW
running_image_type = FirmwareImageType.ZIGBEE_NCP
elif flasher.app_type == ApplicationType.SPINEL:
running_image_type = FirmwareImageType.OT_RCP
running_image_type = FirmwareImageType.OPENTHREAD_RCP
elif flasher.app_type == ApplicationType.CPC:
# TODO: how do you distinguish RCP_UART_802154 from ZIGBEE_NCP_RCP_UART_802154?
running_image_type = FirmwareImageType.RCP_UART_802154
running_image_type = FirmwareImageType.MULTIPAN
elif flasher.app_type == ApplicationType.GECKO_BOOTLOADER:
running_image_type = None
else:
Expand Down