Ejemplo n.º 1
0
def test_rx_device_annce(app, addr_ieee, addr_nwk):
    dst_ep = 0
    cluster_id = zdo_t.ZDOCmd.Device_annce
    device = MagicMock()
    device.status = zigpy.device.Status.NEW
    app.get_device = MagicMock(return_value=device)

    app.handle_join = MagicMock()
    app._handle_reply = MagicMock()
    app.handle_message = MagicMock()

    data = t.uint8_t(0xAA).serialize()
    data += addr_nwk.address.serialize()
    data += addr_ieee.address.serialize()
    data += t.uint8_t(0x8E).serialize()

    app.handle_rx(
        addr_nwk,
        sentinel.src_ep,
        dst_ep,
        sentinel.profile_id,
        cluster_id,
        data,
        sentinel.lqi,
        sentinel.rssi,
    )

    assert app.handle_message.call_count == 1
    assert app.handle_join.call_count == 1
    assert app.handle_join.call_args[0][0] == addr_nwk.address
    assert app.handle_join.call_args[0][1] == addr_ieee.address
    assert app.handle_join.call_args[0][2] == 0
Ejemplo n.º 2
0
 def _api_frame(self, cmd, *args):
     schema = TX_COMMANDS[cmd]
     d = t.serialize(args, schema)
     data = t.uint8_t(cmd).serialize()
     self._seq = (self._seq % 255) + 1
     data += t.uint8_t(self._seq).serialize()
     data += t.uint8_t(0).serialize()
     data += t.uint16_t(len(d) + 5).serialize()
     data += d
     return data, self._seq
Ejemplo n.º 3
0
def _fake_args(arg_type):
    if isinstance(arg_type(), t.DeconzAddressEndpoint):
        addr = t.DeconzAddressEndpoint()
        addr.address_mode = t.ADDRESS_MODE.NWK
        addr.address = t.uint8_t(0)
        addr.endpoint = t.uint8_t(0)
        return addr
    if isinstance(arg_type(), t.EUI64):
        return t.EUI64([0x01] * 8)

    return arg_type()
Ejemplo n.º 4
0
    async def request(
        self,
        device,
        profile,
        cluster,
        src_ep,
        dst_ep,
        sequence,
        data,
        expect_reply=True,
        use_ieee=False,
    ):
        req_id = self.get_sequence()
        LOGGER.debug(
            "Sending Zigbee request with tsn %s under %s request id, data: %s",
            sequence,
            req_id,
            binascii.hexlify(data),
        )
        dst_addr_ep = t.DeconzAddressEndpoint()
        dst_addr_ep.endpoint = t.uint8_t(dst_ep)
        if use_ieee:
            dst_addr_ep.address_mode = t.uint8_t(t.ADDRESS_MODE.IEEE)
            dst_addr_ep.address = device.ieee
        else:
            dst_addr_ep.address_mode = t.uint8_t(t.ADDRESS_MODE.NWK)
            dst_addr_ep.address = device.nwk

        tx_options = t.DeconzTransmitOptions.USE_NWK_KEY_SECURITY

        async with self._limit_concurrency():
            with self._pending.new(req_id) as req:
                try:
                    await self._api.aps_data_request(
                        req_id,
                        dst_addr_ep,
                        profile,
                        cluster,
                        min(1, src_ep),
                        data,
                        tx_options=tx_options,
                    )
                except zigpy_deconz.exception.CommandError as ex:
                    return ex.status, f"Couldn't enqueue send data request: {ex!r}"

                r = await asyncio.wait_for(req.result, SEND_CONFIRM_TIMEOUT)

                if r:
                    LOGGER.debug("Error while sending %s req id frame: %s",
                                 req_id, r)
                    return r, "message send failure"

                return r, "message send success"
Ejemplo n.º 5
0
def _fake_args(arg_type):
    if issubclass(arg_type, enum.Enum):
        return list(arg_type)[0]  # Pick the first enum value
    elif issubclass(arg_type, t.DeconzAddressEndpoint):
        addr = t.DeconzAddressEndpoint()
        addr.address_mode = t.ADDRESS_MODE.NWK
        addr.address = t.uint8_t(0)
        addr.endpoint = t.uint8_t(0)
        return addr
    elif issubclass(arg_type, t.EUI64):
        return t.EUI64([0x01] * 8)

    return arg_type()
Ejemplo n.º 6
0
def test_api_frame(api):
    addr = t.DeconzAddressEndpoint()
    addr.address_mode = t.ADDRESS_MODE.NWK
    addr.address = t.uint8_t(0)
    addr.endpoint = t.uint8_t(0)
    for cmd, schema in deconz_api.TX_COMMANDS.items():
        if schema:
            args = [
                addr if isinstance(a(), t.DeconzAddressEndpoint) else a()
                for a in schema
            ]
            api._api_frame(cmd, *args)
        else:
            api._api_frame(cmd)
Ejemplo n.º 7
0
    async def broadcast(
            self,
            profile,
            cluster,
            src_ep,
            dst_ep,
            grpid,
            radius,
            sequence,
            data,
            broadcast_address=zigpy.types.BroadcastAddress.RX_ON_WHEN_IDLE):
        req_id = self.get_sequence()
        LOGGER.debug(
            "Sending Zigbee broadcast with tsn %s under %s request id, data: %s",
            sequence, req_id, binascii.hexlify(data))
        dst_addr_ep = t.DeconzAddressEndpoint()
        dst_addr_ep.address_mode = t.uint8_t(t.ADDRESS_MODE.GROUP.value)
        dst_addr_ep.address = t.uint16_t(broadcast_address)

        with self._pending.new(req_id) as req:
            try:
                await self._api.aps_data_request(req_id, dst_addr_ep, profile,
                                                 cluster, min(1, src_ep), data)
            except zigpy_deconz.exception.CommandError as ex:
                return ex.status, "Couldn't enqueue send data request for broadcast: {}".format(
                    ex)

            r = await asyncio.wait_for(req.result, SEND_CONFIRM_TIMEOUT)

            if r:
                LOGGER.warning(
                    "Error while sending %s req id broadcast: 0x%02x", req_id,
                    r)
                return r, "broadcast send failure"
            return r, "broadcast send success"
Ejemplo n.º 8
0
def test_device_state_network_state(data, network_state):
    """Test device state flag."""
    extra = b"the rest of the data\xaa\x55"

    for other_fields in (0x04, 0x08, 0x0C, 0x10, 0x24, 0x28, 0x30, 0x2C):
        new_data = t.uint8_t(data | other_fields).serialize()
        state, rest = deconz_api.DeviceState.deserialize(new_data + extra)
        assert rest == extra
        assert state.network_state == deconz_api.NetworkState[network_state]
        assert state.serialize() == new_data
Ejemplo n.º 9
0
def test_struct():
    class TestStruct(t.Struct):
        _fields = [("a", t.uint8_t), ("b", t.uint8_t)]

    ts = TestStruct()
    ts.a = t.uint8_t(0xAA)
    ts.b = t.uint8_t(0xBB)
    ts2 = TestStruct(ts)
    assert ts2.a == ts.a
    assert ts2.b == ts.b

    r = repr(ts)
    assert "TestStruct" in r
    assert r.startswith("<") and r.endswith(">")

    s = ts2.serialize()
    assert s == b"\xaa\xbb"

    extra = b"\x00extra data\xff"
    d, rest = TestStruct.deserialize(s + extra)
    assert rest == extra
    assert d.a == ts.a
    assert d.b == ts.b
Ejemplo n.º 10
0
def test_api_frame(api):
    addr = t.DeconzAddress()
    addr.address_mode = t.ADDRESS_MODE.NWK
    addr.address = t.uint8_t(0)
    for cmd_name, cmd_opts in deconz_api.TX_COMMANDS.items():
        _, schema, _ = cmd_opts
        if schema:
            args = [
                addr if isinstance(a(), t.DeconzAddress) else a()
                for a in schema
            ]
            api._api_frame(cmd_name, *args)
        else:
            api._api_frame(cmd_name)
Ejemplo n.º 11
0
def test_data_received_unk_cmd(api, monkeypatch):
    monkeypatch.setattr(
        t, 'deserialize',
        mock.MagicMock(return_value=(mock.sentinel.deserialize_data, b'')))

    for cmd_id in range(253, 255):
        payload = b'\x01\x02\x03\x04'
        status = t.uint8_t(0x00).serialize()
        data = cmd_id.to_bytes(1, 'big') + b'\x00' + \
            status + b'\x00\x00' + payload
        api._awaiting[0] = (mock.MagicMock(), )
        api.data_received(data)
        assert t.deserialize.call_count == 0
        t.deserialize.reset_mock()
Ejemplo n.º 12
0
def test_tx_status(value, name):
    """Test tx status undefined values."""
    i = deconz_api.TXStatus(value)
    assert i == value
    assert i.value == value
    assert i.name == name

    extra = b"\xaa\55"
    data = t.uint8_t(value).serialize()
    status, rest = deconz_api.TXStatus.deserialize(data + extra)
    assert rest == extra
    assert isinstance(status, deconz_api.TXStatus)
    assert status == value
    assert status.value == value
    assert status.name == name
Ejemplo n.º 13
0
def test_data_received_unk_cmd(api, monkeypatch):
    monkeypatch.setattr(
        t,
        "deserialize",
        MagicMock(return_value=(sentinel.deserialize_data, b"")),
    )

    for cmd_id in range(253, 255):
        payload = b"\x01\x02\x03\x04"
        status = t.uint8_t(0x00).serialize()
        data = cmd_id.to_bytes(
            1, "big") + b"\x00" + status + b"\x00\x00" + payload
        api._awaiting[0] = (MagicMock(), )
        api.data_received(data)
        assert t.deserialize.call_count == 0
        t.deserialize.reset_mock()
Ejemplo n.º 14
0
    async def request(self,
                      nwk,
                      profile,
                      cluster,
                      src_ep,
                      dst_ep,
                      sequence,
                      data,
                      expect_reply=True,
                      timeout=10):
        LOGGER.debug("Zigbee request with id %s, data: %s", sequence,
                     binascii.hexlify(data))
        assert sequence not in self._pending
        send_fut = asyncio.Future()
        reply_fut = None
        if expect_reply:
            reply_fut = asyncio.Future()
        self._pending[sequence] = (send_fut, reply_fut)
        dst_addr = t.DeconzAddress()
        dst_addr.address_mode = t.uint8_t(t.ADDRESS_MODE.NWK.value)
        dst_addr.address = t.uint16_t(nwk)

        await self._api.aps_data_request(sequence, dst_addr, dst_ep, profile,
                                         cluster, min(1, src_ep), data)

        try:
            r = await asyncio.wait_for(send_fut, SEND_CONFIRM_TIMEOUT)
        except asyncio.TimeoutError:
            self._pending.pop(sequence, None)
            LOGGER.warning(
                "Failed to receive transmit confirm for request id: %s",
                sequence)
            raise

        if r:
            LOGGER.warning("Error while sending frame: 0x%02x", r)

        if not expect_reply:
            self._pending.pop(sequence, None)
            return

        try:
            return await asyncio.wait_for(reply_fut, timeout)
        except asyncio.TimeoutError:
            self._pending.pop(sequence, None)
            raise
Ejemplo n.º 15
0
def test_data_received_unk_status(api, monkeypatch):
    monkeypatch.setattr(
        t, 'deserialize',
        mock.MagicMock(return_value=(mock.sentinel.deserialize_data, b'')))
    my_handler = mock.MagicMock()

    for cmd, cmd_opts in deconz_api.RX_COMMANDS.items():
        _, unsolicited = cmd_opts
        payload = b'\x01\x02\x03\x04'
        status = t.uint8_t(0xfe).serialize()
        data = cmd.serialize() + b'\x00' + status + b'\x00\x00' + payload
        setattr(api, '_handle_{}'.format(cmd.name), my_handler)
        api._awaiting[0] = mock.MagicMock()
        api.data_received(data)
        assert t.deserialize.call_count == 1
        assert t.deserialize.call_args[0][0] == payload
        if unsolicited:
            assert my_handler.call_count == 0
        else:
            assert my_handler.call_count == 1
        t.deserialize.reset_mock()
        my_handler.reset_mock()
Ejemplo n.º 16
0
def test_data_received_unk_status(api, monkeypatch):
    monkeypatch.setattr(
        t,
        "deserialize",
        MagicMock(return_value=(sentinel.deserialize_data, b"")),
    )
    my_handler = MagicMock()

    for cmd, cmd_opts in deconz_api.RX_COMMANDS.items():
        _, solicited = cmd_opts
        payload = b"\x01\x02\x03\x04"
        status = t.uint8_t(0xFE).serialize()
        data = cmd.serialize() + b"\x00" + status + b"\x00\x00" + payload
        setattr(api, "_handle_{}".format(cmd.name), my_handler)
        api._awaiting[0] = MagicMock()
        api.data_received(data)
        if solicited:
            assert my_handler.call_count == 0
            assert t.deserialize.call_count == 0
        else:
            assert t.deserialize.call_count == 1
            assert my_handler.call_count == 1
        t.deserialize.reset_mock()
        my_handler.reset_mock()
Ejemplo n.º 17
0
 def serialize(self) -> bytes:
     """Serialize data."""
     return t.uint8_t(self).serialize()