async def request( self, device, profile, cluster, src_ep, dst_ep, sequence, data, expect_reply=True, use_ieee=False, ): tx_options = c.af.TransmitOptions.RouteDiscovery # if expect_reply: # tx_options |= c.af.TransmitOptions.APSAck if use_ieee: destination = t.AddrModeAddress(mode=t.AddrMode.IEEE, address=device.ieee) else: destination = t.AddrModeAddress(mode=t.AddrMode.NWK, address=device.nwk) return await self._send_request( dst_addr=destination, dst_ep=dst_ep, src_ep=src_ep, cluster=cluster, sequence=sequence, options=tx_options, radius=30, data=data, )
async def broadcast( self, profile, cluster, src_ep, dst_ep, grpid, radius, sequence, data, broadcast_address=zigpy.types.BroadcastAddress.RX_ON_WHEN_IDLE, ): assert grpid == 0 return await self._send_request( dst_addr=t.AddrModeAddress(mode=t.AddrMode.Broadcast, address=broadcast_address), dst_ep=dst_ep, src_ep=src_ep, cluster=cluster, sequence=sequence, options=c.af.TransmitOptions.NONE, radius=radius, data=data, )
def test_command_str_repr(): command = c.UtilCommands.BindAddEntry.Req( DstAddrModeAddr=t.AddrModeAddress(mode=t.AddrMode.NWK, address=0x1234), DstEndpoint=0x56, ClusterIdList=[0x12, 0x34], ) assert repr(command) == str(command) assert str([command]) == f"[{str(command)}]"
async def test_zigpy_request(application, mocker): app, znp_server = application await app.startup(auto_form=False) TSN = 1 device = app.add_device(ieee=t.EUI64(range(8)), nwk=0xAABB) device.status = zigpy.device.Status.ENDPOINTS_INIT device.initializing = False device.add_endpoint(1).add_input_cluster(6) # Respond to a light turn on request data_req = znp_server.reply_once_to( request=c.AF.DataRequestExt.Req( DstAddrModeAddress=t.AddrModeAddress(mode=t.AddrMode.NWK, address=device.nwk), DstEndpoint=1, SrcEndpoint=1, ClusterId=6, TSN=TSN, Data=bytes([0x01, TSN, 0x01]), partial=True, ), responses=[ c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS), c.AF.DataConfirm.Callback( Status=t.Status.SUCCESS, Endpoint=1, TSN=TSN, ), c.ZDO.SrcRtgInd.Callback(DstAddr=device.nwk, Relays=[]), c.AF.IncomingMsg.Callback( GroupId=0x0000, ClusterId=6, SrcAddr=device.nwk, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=False, LQI=63, SecurityUse=False, TimeStamp=1198515, TSN=0, Data=bytes([0x08, TSN, 0x0B, 0x00, 0x00]), MacSrcAddr=device.nwk, MsgResultRadius=29, ), ], ) # Turn on the light await device.endpoints[1].on_off.on() await data_req
async def test_zigpy_request_failure(application, mocker): app, znp_server = application await app.startup(auto_form=False) TSN = 1 device = app.add_device(ieee=t.EUI64(range(8)), nwk=0xAABB) device.status = zigpy.device.Status.ENDPOINTS_INIT device.initializing = False device.add_endpoint(1).add_input_cluster(6) # Fail to respond to a light turn on request znp_server.reply_to( request=c.AF.DataRequestExt.Req( DstAddrModeAddress=t.AddrModeAddress(mode=t.AddrMode.NWK, address=device.nwk), DstEndpoint=1, SrcEndpoint=1, ClusterId=6, TSN=TSN, Data=bytes([0x01, TSN, 0x01]), partial=True, ), responses=[ c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS), c.AF.DataConfirm.Callback( Status=t.Status.FAILURE, Endpoint=1, TSN=TSN, ), ], ) mocker.patch.object(app, "_send_request", new=CoroutineMock(wraps=app._send_request)) # Fail to turn on the light with pytest.raises(zigpy.exceptions.DeliveryError): await device.endpoints[1].on_off.on() assert app._send_request.call_count == 1
"_send_request", new=CoroutineMock(wraps=app._send_request)) # Fail to turn on the light with pytest.raises(zigpy.exceptions.DeliveryError): await device.endpoints[1].on_off.on() assert app._send_request.call_count == 1 @pytest_mark_asyncio_timeout(seconds=3) @pytest.mark.parametrize( "use_ieee,dev_addr", [ (True, t.AddrModeAddress(mode=t.AddrMode.IEEE, address=t.EUI64(range(8)))), (False, t.AddrModeAddress(mode=t.AddrMode.NWK, address=t.NWK(0xAABB))), ], ) async def test_request_use_ieee(application, mocker, use_ieee, dev_addr): app, znp_server = application device = app.add_device(ieee=t.EUI64(range(8)), nwk=0xAABB) send_req = mocker.patch.object(app, "_send_request", new=CoroutineMock()) await app.request( device, use_ieee=use_ieee, profile=None, cluster=None, src_ep=None,
def test_command_param_binding(): # No params c.SysCommands.Ping.Req() # Invalid param name with pytest.raises(KeyError): c.SysCommands.Ping.Rsp(asd=123) # Valid param name c.SysCommands.Ping.Rsp(Capabilities=t.MTCapabilities.CAP_SYS) # Too many params, one valid with pytest.raises(KeyError): c.SysCommands.Ping.Rsp(foo="asd", Capabilities=t.MTCapabilities.CAP_SYS) # Not enough params with pytest.raises(KeyError): c.SysCommands.Ping.Rsp() # Invalid type with pytest.raises(ValueError): c.UtilCommands.TimeAlive.Rsp(Seconds=b"asd") # Coerced numerical type a = c.UtilCommands.TimeAlive.Rsp(Seconds=12) b = c.UtilCommands.TimeAlive.Rsp(Seconds=t.uint32_t(12)) assert a == b assert a.Seconds == b.Seconds assert type(a.Seconds) == type(b.Seconds) == t.uint32_t # noqa: E721 # Overflowing integer types with pytest.raises(ValueError): c.UtilCommands.TimeAlive.Rsp(Seconds=10**20) # Integers will not be coerced to enums assert t.MTCapabilities.CAP_SYS == 0x0001 with pytest.raises(ValueError): c.SysCommands.Ping.Rsp(Capabilities=0x0001) # Parameters can be looked up by name ping_rsp = c.SysCommands.Ping.Rsp(Capabilities=t.MTCapabilities.CAP_SYS) assert ping_rsp.Capabilities == t.MTCapabilities.CAP_SYS # Invalid ones cannot with pytest.raises(AttributeError): ping_rsp.Oops # bytes are converted into t.ShortBytes cmd = c.SysCommands.NVWrite.Req(SysId=0x12, ItemId=0x3456, SubId=0x7890, Offset=0x0000, Value=b"asdfoo") assert isinstance(cmd.Value, t.ShortBytes) # Lists are converted to typed LVLists c.UtilCommands.BindAddEntry.Req( DstAddrModeAddr=t.AddrModeAddress(mode=t.AddrMode.NWK, address=0x1234), DstEndpoint=0x56, ClusterIdList=[0x12, 0x45], ) # Type errors within containers are also caught with pytest.raises(ValueError): c.UtilCommands.BindAddEntry.Req( DstAddrModeAddr=t.AddrModeAddress(mode=t.AddrMode.NWK, address=0x1234), DstEndpoint=0x56, ClusterIdList=[0x12, 0x457890], # 0x457890 doesn't fit into a uint8_t )