diff --git a/bellows/ezsp/__init__.py b/bellows/ezsp/__init__.py index e4441486..b5bd087f 100644 --- a/bellows/ezsp/__init__.py +++ b/bellows/ezsp/__init__.py @@ -29,11 +29,11 @@ import bellows.types as t import bellows.uart -from . import v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v16, v17 +from . import v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v16, v17, v18 RESET_ATTEMPTS = 3 -EZSP_LATEST = v17.EZSPv17.VERSION +EZSP_LATEST = v18.EZSPv18.VERSION LOGGER = logging.getLogger(__name__) MTOR_MIN_INTERVAL = 60 MTOR_MAX_INTERVAL = 3600 @@ -61,6 +61,7 @@ class EZSP: v14.EZSPv14.VERSION: v14.EZSPv14, v16.EZSPv16.VERSION: v16.EZSPv16, v17.EZSPv17.VERSION: v17.EZSPv17, + v18.EZSPv18.VERSION: v18.EZSPv18, } def __init__(self, device_config: dict, application: Any | None = None): diff --git a/bellows/ezsp/config.py b/bellows/ezsp/config.py index 1045da0f..61e485ce 100644 --- a/bellows/ezsp/config.py +++ b/bellows/ezsp/config.py @@ -129,4 +129,5 @@ class ValueConfig: 14: DEFAULT_CONFIG_NEW, 16: DEFAULT_CONFIG_NEW, 17: DEFAULT_CONFIG_NEW, + 18: DEFAULT_CONFIG_NEW, } diff --git a/bellows/ezsp/v18/__init__.py b/bellows/ezsp/v18/__init__.py new file mode 100644 index 00000000..f087a8d1 --- /dev/null +++ b/bellows/ezsp/v18/__init__.py @@ -0,0 +1,20 @@ +""""EZSP Protocol version 18 protocol handler.""" +from __future__ import annotations + +import voluptuous as vol + +import bellows.config + +from . import commands, config +from ..v17 import EZSPv17 + + +class EZSPv18(EZSPv17): + """EZSP Version 18 Protocol version handler.""" + + VERSION = 18 + COMMANDS = commands.COMMANDS + SCHEMAS = { + bellows.config.CONF_EZSP_CONFIG: vol.Schema(config.EZSP_SCHEMA), + bellows.config.CONF_EZSP_POLICIES: vol.Schema(config.EZSP_POLICIES_SCH), + } diff --git a/bellows/ezsp/v18/commands.py b/bellows/ezsp/v18/commands.py new file mode 100644 index 00000000..ff458c4c --- /dev/null +++ b/bellows/ezsp/v18/commands.py @@ -0,0 +1,18 @@ +import bellows.types as t + +from ..v17.commands import COMMANDS as COMMANDS_v17 + +COMMANDS = { + **COMMANDS_v17, + "macFilterMatchMessageHandler": ( + 0x46, + {}, + { + "filterValueMatch": t.uint16_t, # Was `filterIndexMatch: uint8_t` + "legacyPassthroughType": t.EmberMacPassthroughType, + "lastHopLqi": t.uint8_t, + "lastHopRssi": t.int8s, + "messageContents": t.LVBytes, + }, + ), +} diff --git a/bellows/ezsp/v18/config.py b/bellows/ezsp/v18/config.py new file mode 100644 index 00000000..167fa57a --- /dev/null +++ b/bellows/ezsp/v18/config.py @@ -0,0 +1,16 @@ +import voluptuous as vol + +from bellows.config import cv_uint16 +from bellows.types import EzspPolicyId + +from ..v4.config import EZSP_POLICIES_SHARED +from ..v17 import config as v17_config + +EZSP_SCHEMA = { + **v17_config.EZSP_SCHEMA, +} + +EZSP_POLICIES_SCH = { + **EZSP_POLICIES_SHARED, + **{vol.Optional(policy.name): cv_uint16 for policy in EzspPolicyId}, +} diff --git a/tests/test_ezsp.py b/tests/test_ezsp.py index b3e24821..d548309a 100644 --- a/tests/test_ezsp.py +++ b/tests/test_ezsp.py @@ -951,21 +951,20 @@ async def test_cfg_initialize_skip(): ) -@pytest.mark.parametrize("unsupported_version", [15, 18, 99]) -async def test_unsupported_ezsp_version_startup(unsupported_version: int, caplog): +async def test_unsupported_ezsp_version_startup(caplog): """Test that startup works with an unsupported EZSP version.""" - ezsp = make_ezsp(version=unsupported_version) + ezsp = make_ezsp(version=99) with patch("bellows.uart.connect"): await ezsp.connect() # The EZSP version should be stored as the unsupported version - assert ezsp._ezsp_version == unsupported_version + assert ezsp._ezsp_version == 99 # But the protocol should fall back to the latest assert ezsp._protocol.VERSION == EZSP_LATEST - assert f"Protocol version {unsupported_version} is not supported" in caplog.text + assert "Protocol version 99 is not supported" in caplog.text ezsp.getConfigurationValue = AsyncMock(return_value=(t.EzspStatus.SUCCESS, 0)) ezsp.setConfigurationValue = AsyncMock(return_value=(t.EzspStatus.SUCCESS,)) diff --git a/tests/test_ezsp_v18.py b/tests/test_ezsp_v18.py new file mode 100644 index 00000000..b0c8c90e --- /dev/null +++ b/tests/test_ezsp_v18.py @@ -0,0 +1,31 @@ +from unittest.mock import MagicMock + +import pytest + +import bellows.ezsp.v18 +import bellows.types as t + +from tests.common import mock_ezsp_commands + + +@pytest.fixture +def ezsp_f(): + """EZSP v18 protocol handler.""" + ezsp = bellows.ezsp.v18.EZSPv18(MagicMock(), MagicMock()) + mock_ezsp_commands(ezsp) + + return ezsp + + +def test_ezsp_frame(ezsp_f): + ezsp_f._seq = 0x22 + data = ezsp_f._ezsp_frame("version", 18) + assert data == b"\x22\x00\x01\x00\x00\x12" + + +def test_ezsp_frame_rx(ezsp_f): + """Test receiving a version frame.""" + ezsp_f(b"\x01\x01\x80\x00\x00\x01\x02\x34\x12") + assert ezsp_f._handle_callback.call_count == 1 + assert ezsp_f._handle_callback.call_args[0][0] == "version" + assert ezsp_f._handle_callback.call_args[0][1] == [0x01, 0x02, 0x1234]