Skip to content

Commit b7f3ef9

Browse files
authored
Do not read XNCP flow control on older radios (#659)
* Only request XNCP flow control type if the feature is supported * Ignore XNCP for older gateways * Add a unit test
1 parent acd2aa5 commit b7f3ef9

File tree

5 files changed

+38
-15
lines changed

5 files changed

+38
-15
lines changed

bellows/ezsp/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ async def version(self):
180180
)
181181

182182
async def get_xncp_features(self) -> xncp.FirmwareFeatures:
183+
# Some older gateways seem to have their own XNCP protocol. Ignore them.
184+
if self._ezsp_version < 13:
185+
return FirmwareFeatures.NONE
186+
183187
try:
184188
self._xncp_features = await self.xncp_get_supported_firmware_features()
185189
except InvalidCommandError:

bellows/ezsp/xncp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ class XncpCommandPayload(t.Struct):
112112

113113

114114
class FlowControlType(t.enum8):
115-
Software = 0x00
116-
Hardware = 0x01
115+
SOFTWARE = 0x00
116+
HARDWARE = 0x01
117117

118118

119119
@register_command(XncpCommandId.GET_SUPPORTED_FEATURES_REQ)

bellows/zigbee/application.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,7 @@
3232
CONF_USE_THREAD,
3333
CONFIG_SCHEMA,
3434
)
35-
from bellows.exception import (
36-
ControllerError,
37-
EzspError,
38-
InvalidCommandError,
39-
StackAlreadyRunning,
40-
)
35+
from bellows.exception import ControllerError, EzspError, StackAlreadyRunning
4136
import bellows.ezsp
4237
from bellows.ezsp.xncp import FirmwareFeatures
4338
import bellows.multicast
@@ -299,9 +294,9 @@ async def load_network_info(self, *, load_devices=False) -> None:
299294
can_burn_userdata_custom_eui64 = await ezsp.can_burn_userdata_custom_eui64()
300295
can_rewrite_custom_eui64 = await ezsp.can_rewrite_custom_eui64()
301296

302-
try:
303-
flow_control = await self._ezsp.xncp_get_flow_control_type()
304-
except InvalidCommandError:
297+
if FirmwareFeatures.FLOW_CONTROL_TYPE in ezsp._xncp_features:
298+
flow_control = await ezsp.xncp_get_flow_control_type()
299+
else:
305300
flow_control = None
306301

307302
self.state.network_info = zigpy.state.NetworkInfo(

tests/test_application.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from bellows.exception import ControllerError, EzspError
1818
import bellows.ezsp as ezsp
1919
from bellows.ezsp.v9.commands import GetTokenDataRsp
20-
from bellows.ezsp.xncp import FirmwareFeatures
20+
from bellows.ezsp.xncp import FirmwareFeatures, FlowControlType
2121
import bellows.types
2222
import bellows.types as t
2323
import bellows.types.struct
@@ -1874,7 +1874,7 @@ def zigpy_backup() -> zigpy.backups.NetworkBackup:
18741874
metadata={
18751875
"ezsp": {
18761876
"stack_version": 8,
1877-
"flow_control": None,
1877+
"flow_control": "hardware",
18781878
"can_burn_userdata_custom_eui64": True,
18791879
"can_rewrite_custom_eui64": True,
18801880
}
@@ -1890,6 +1890,24 @@ async def test_load_network_info(
18901890
) -> None:
18911891
await app.load_network_info(load_devices=True)
18921892

1893+
zigpy_backup.network_info.metadata["ezsp"]["flow_control"] = None
1894+
1895+
assert app.state.node_info == zigpy_backup.node_info
1896+
assert app.state.network_info == zigpy_backup.network_info
1897+
1898+
1899+
async def test_load_network_info_xncp_flow_control(
1900+
app: ControllerApplication,
1901+
ieee: zigpy_t.EUI64,
1902+
zigpy_backup: zigpy.backups.NetworkBackup,
1903+
) -> None:
1904+
app._ezsp._xncp_features |= FirmwareFeatures.FLOW_CONTROL_TYPE
1905+
app._ezsp.xncp_get_flow_control_type = AsyncMock(
1906+
return_value=FlowControlType.HARDWARE
1907+
)
1908+
1909+
await app.load_network_info(load_devices=True)
1910+
18931911
assert app.state.node_info == zigpy_backup.node_info
18941912
assert app.state.network_info == zigpy_backup.network_info
18951913

tests/test_xncp.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,22 @@ async def test_xncp_get_flow_control_type(ezsp_f: EZSP) -> None:
171171
t.EmberStatus.SUCCESS,
172172
xncp.XncpCommand.from_payload(
173173
xncp.GetFlowControlTypeRsp(
174-
flow_control_type=xncp.FlowControlType.Hardware
174+
flow_control_type=xncp.FlowControlType.HARDWARE
175175
)
176176
).serialize(),
177177
]
178178
)
179179

180-
assert await ezsp_f.xncp_get_flow_control_type() == xncp.FlowControlType.Hardware
180+
assert await ezsp_f.xncp_get_flow_control_type() == xncp.FlowControlType.HARDWARE
181181
assert customFrame.mock_calls == [
182182
call(xncp.XncpCommand.from_payload(xncp.GetFlowControlTypeReq()).serialize())
183183
]
184184

185185

186186
async def test_xncp_get_xncp_features_fixes(ezsp_f: EZSP) -> None:
187187
"""Test XNCP `get_xncp_features`, with fixes."""
188+
ezsp_f._ezsp_version = 13
189+
188190
ezsp_f._mock_commands["customFrame"] = customFrame = AsyncMock(
189191
return_value=[
190192
t.EmberStatus.SUCCESS,
@@ -220,6 +222,10 @@ async def test_xncp_get_xncp_features_fixes(ezsp_f: EZSP) -> None:
220222
| xncp.FirmwareFeatures.MEMBER_OF_ALL_GROUPS
221223
)
222224

225+
# XNCP is ignored for older EmberZNet
226+
ezsp_f._ezsp_version = 8
227+
assert (await ezsp_f.get_xncp_features()) == xncp.FirmwareFeatures.NONE
228+
223229
assert customFrame.mock_calls == [
224230
call(xncp.XncpCommand.from_payload(xncp.GetSupportedFeaturesReq()).serialize()),
225231
call(xncp.XncpCommand.from_payload(xncp.GetSupportedFeaturesReq()).serialize()),

0 commit comments

Comments
 (0)