diff --git a/bellows/zigbee/application.py b/bellows/zigbee/application.py index 1f3c8a42..9dbf499b 100644 --- a/bellows/zigbee/application.py +++ b/bellows/zigbee/application.py @@ -73,6 +73,8 @@ "54:EF:44": 0x115F, # Lumi } +DEFAULT_TX_POWER = 8 # dBm + LIB_VERSION = importlib.metadata.version("bellows") LOGGER = logging.getLogger(__name__) @@ -522,7 +524,11 @@ async def write_network_info( parameters = t.EmberNetworkParameters() parameters.panId = t.EmberPanId(network_info.pan_id) parameters.extendedPanId = t.EUI64(network_info.extended_pan_id) - parameters.radioTxPower = t.uint8_t(network_info.tx_power) + parameters.radioTxPower = ( + t.uint8_t(network_info.tx_power) + if network_info.tx_power is not None + else DEFAULT_TX_POWER + ) parameters.radioChannel = t.uint8_t(network_info.channel) parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION parameters.nwkManagerId = t.EmberNodeId(network_info.nwk_manager_id) diff --git a/tests/test_application.py b/tests/test_application.py index 35e1a2d2..8ce61b45 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -28,7 +28,7 @@ import bellows.types.struct import bellows.uart as uart import bellows.zigbee.application -from bellows.zigbee.application import ControllerApplication +from bellows.zigbee.application import DEFAULT_TX_POWER, ControllerApplication import bellows.zigbee.device from bellows.zigbee.device import EZSPEndpoint, EZSPGroupEndpoint from bellows.zigbee.util import map_rssi_to_energy @@ -104,7 +104,7 @@ def _create_app_for_startup( nwk_params = bellows.types.struct.EmberNetworkParameters( extendedPanId=t.ExtendedPanId.convert("aa:bb:cc:dd:ee:ff:aa:bb"), panId=t.EmberPanId(0x55AA), - radioTxPower=0, + radioTxPower=8, radioChannel=25, joinMethod=t.EmberJoinMethod.USE_MAC_ASSOCIATION, nwkManagerId=t.EmberNodeId(0x0000), @@ -2032,7 +2032,7 @@ def zigpy_backup() -> zigpy.backups.NetworkBackup: channel=t.uint8_t(25), channel_mask=t.Channels.ALL_CHANNELS, security_level=t.uint8_t(1), - tx_power=0, + tx_power=8, network_key=zigpy.state.Key( key=t.KeyData.convert( "41:63:74:75:61:6c:4e:65:74:77:6f:72:6b:4b:65:79" @@ -2251,6 +2251,37 @@ async def test_write_network_info( ] +async def test_write_network_info_with_none_tx_power( + app: ControllerApplication, + ieee: zigpy_t.EUI64, + zigpy_backup: zigpy.backups.NetworkBackup, +) -> None: + """Test that write_network_info uses DEFAULT_TX_POWER when tx_power is None.""" + network_info = zigpy_backup.network_info.replace(tx_power=None) + + with patch.object(app, "_reset"): + await app.write_network_info( + node_info=zigpy_backup.node_info, + network_info=network_info, + ) + + # Verify formNetwork was called with DEFAULT_TX_POWER instead of None + assert app._ezsp._protocol.formNetwork.mock_calls == [ + call( + parameters=t.EmberNetworkParameters( + panId=network_info.pan_id, + extendedPanId=network_info.extended_pan_id, + radioTxPower=DEFAULT_TX_POWER, + radioChannel=network_info.channel, + joinMethod=t.EmberJoinMethod.USE_MAC_ASSOCIATION, + nwkManagerId=t.EmberNodeId(0x0000), + nwkUpdateId=network_info.nwk_update_id, + channels=network_info.channel_mask, + ) + ) + ] + + async def test_write_network_info_restores_route_table( app: ControllerApplication, ieee: zigpy_t.EUI64,