Skip to content

Commit 54d003b

Browse files
authored
EZSP v18 support (#704)
* EZSP v18 * Remove unused `_handle_no_such_device` * Move packet reception logic into the protocol handler * Add to EZSP config * Add a new test for v18 * Properly handle event lifecycle * Migrate to events * Revert unit test changes * Remove unnecessary unit tests * Fix tests * Revert EmberApsFrameV18 addition * Use dicts for tests * Migrate the rest to events * Use named callbacks to avoid duplication * Remove unnecessary proxy methods * Bring coverage up * Reduce diff size * Fix new unit test
1 parent 9e31738 commit 54d003b

File tree

7 files changed

+93
-7
lines changed

7 files changed

+93
-7
lines changed

bellows/ezsp/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
import bellows.types as t
3030
import bellows.uart
3131

32-
from . import v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v16, v17
32+
from . import v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v16, v17, v18
3333

3434
RESET_ATTEMPTS = 3
3535

36-
EZSP_LATEST = v17.EZSPv17.VERSION
36+
EZSP_LATEST = v18.EZSPv18.VERSION
3737
LOGGER = logging.getLogger(__name__)
3838
MTOR_MIN_INTERVAL = 60
3939
MTOR_MAX_INTERVAL = 3600
@@ -61,6 +61,7 @@ class EZSP:
6161
v14.EZSPv14.VERSION: v14.EZSPv14,
6262
v16.EZSPv16.VERSION: v16.EZSPv16,
6363
v17.EZSPv17.VERSION: v17.EZSPv17,
64+
v18.EZSPv18.VERSION: v18.EZSPv18,
6465
}
6566

6667
def __init__(self, device_config: dict, application: Any | None = None):

bellows/ezsp/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,5 @@ class ValueConfig:
129129
14: DEFAULT_CONFIG_NEW,
130130
16: DEFAULT_CONFIG_NEW,
131131
17: DEFAULT_CONFIG_NEW,
132+
18: DEFAULT_CONFIG_NEW,
132133
}

bellows/ezsp/v18/__init__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
""""EZSP Protocol version 18 protocol handler."""
2+
from __future__ import annotations
3+
4+
import voluptuous as vol
5+
6+
import bellows.config
7+
8+
from . import commands, config
9+
from ..v17 import EZSPv17
10+
11+
12+
class EZSPv18(EZSPv17):
13+
"""EZSP Version 18 Protocol version handler."""
14+
15+
VERSION = 18
16+
COMMANDS = commands.COMMANDS
17+
SCHEMAS = {
18+
bellows.config.CONF_EZSP_CONFIG: vol.Schema(config.EZSP_SCHEMA),
19+
bellows.config.CONF_EZSP_POLICIES: vol.Schema(config.EZSP_POLICIES_SCH),
20+
}

bellows/ezsp/v18/commands.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import bellows.types as t
2+
3+
from ..v17.commands import COMMANDS as COMMANDS_v17
4+
5+
COMMANDS = {
6+
**COMMANDS_v17,
7+
"macFilterMatchMessageHandler": (
8+
0x46,
9+
{},
10+
{
11+
"filterValueMatch": t.uint16_t, # Was `filterIndexMatch: uint8_t`
12+
"legacyPassthroughType": t.EmberMacPassthroughType,
13+
"lastHopLqi": t.uint8_t,
14+
"lastHopRssi": t.int8s,
15+
"messageContents": t.LVBytes,
16+
},
17+
),
18+
}

bellows/ezsp/v18/config.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import voluptuous as vol
2+
3+
from bellows.config import cv_uint16
4+
from bellows.types import EzspPolicyId
5+
6+
from ..v4.config import EZSP_POLICIES_SHARED
7+
from ..v17 import config as v17_config
8+
9+
EZSP_SCHEMA = {
10+
**v17_config.EZSP_SCHEMA,
11+
}
12+
13+
EZSP_POLICIES_SCH = {
14+
**EZSP_POLICIES_SHARED,
15+
**{vol.Optional(policy.name): cv_uint16 for policy in EzspPolicyId},
16+
}

tests/test_ezsp.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -951,21 +951,20 @@ async def test_cfg_initialize_skip():
951951
)
952952

953953

954-
@pytest.mark.parametrize("unsupported_version", [15, 18, 99])
955-
async def test_unsupported_ezsp_version_startup(unsupported_version: int, caplog):
954+
async def test_unsupported_ezsp_version_startup(caplog):
956955
"""Test that startup works with an unsupported EZSP version."""
957-
ezsp = make_ezsp(version=unsupported_version)
956+
ezsp = make_ezsp(version=99)
958957

959958
with patch("bellows.uart.connect"):
960959
await ezsp.connect()
961960

962961
# The EZSP version should be stored as the unsupported version
963-
assert ezsp._ezsp_version == unsupported_version
962+
assert ezsp._ezsp_version == 99
964963

965964
# But the protocol should fall back to the latest
966965
assert ezsp._protocol.VERSION == EZSP_LATEST
967966

968-
assert f"Protocol version {unsupported_version} is not supported" in caplog.text
967+
assert "Protocol version 99 is not supported" in caplog.text
969968

970969
ezsp.getConfigurationValue = AsyncMock(return_value=(t.EzspStatus.SUCCESS, 0))
971970
ezsp.setConfigurationValue = AsyncMock(return_value=(t.EzspStatus.SUCCESS,))

tests/test_ezsp_v18.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from unittest.mock import MagicMock
2+
3+
import pytest
4+
5+
import bellows.ezsp.v18
6+
import bellows.types as t
7+
8+
from tests.common import mock_ezsp_commands
9+
10+
11+
@pytest.fixture
12+
def ezsp_f():
13+
"""EZSP v18 protocol handler."""
14+
ezsp = bellows.ezsp.v18.EZSPv18(MagicMock(), MagicMock())
15+
mock_ezsp_commands(ezsp)
16+
17+
return ezsp
18+
19+
20+
def test_ezsp_frame(ezsp_f):
21+
ezsp_f._seq = 0x22
22+
data = ezsp_f._ezsp_frame("version", 18)
23+
assert data == b"\x22\x00\x01\x00\x00\x12"
24+
25+
26+
def test_ezsp_frame_rx(ezsp_f):
27+
"""Test receiving a version frame."""
28+
ezsp_f(b"\x01\x01\x80\x00\x00\x01\x02\x34\x12")
29+
assert ezsp_f._handle_callback.call_count == 1
30+
assert ezsp_f._handle_callback.call_args[0][0] == "version"
31+
assert ezsp_f._handle_callback.call_args[0][1] == [0x01, 0x02, 0x1234]

0 commit comments

Comments
 (0)