Beispiel #1
0
    async def send_app(
        self, destination: int, app_index: int, opcode: int, params: MessageDescription
    ):
        """
        Send a message using an application key.

        :param destination: Destination address
        :param app_index: Index of the application key
        :param opcode: Message opcode.
        :param params: Message parameters.
        """

        data = AccessMessage.build(dict(opcode=opcode, params=params))

        message = AccessMessage.parse(data)
        self.logger.debug(
            "Sending: %s -> %04x [app_index %d] %s %r",
            self.element.path,
            destination,
            app_index,
            message["opcode"],
            message["params"],
        )

        await self._send_app(destination, app_index, data)
Beispiel #2
0
    async def send_dev(self, destination: int, net_index: int, opcode: int,
                       params: MessageDescription):
        """
        Send a message using a device key.

        `destination` determines which device key is going to be used. For
        local destinations, the key is always known, but if `destination` is a
        remote node, the caller must first import its device key using
        :func:`~bluetooth_mesh.application.Application.import_remote_node`.

        Unlike application keys, device keys are bound to all subnets, so
        you need to explicitly provide `net_index`.

        See :py:func:`send_app`

        :param destination: Destination address
        :param net_index: Index of the network key
        :param opcode: Message opcode.
        :param params: Message parameters.
        """

        remote = True
        data = AccessMessage.build(dict(opcode=opcode, params=params))

        message = AccessMessage.parse(data)
        self.logger.debug(
            "Sending: %s -> %04x [remote %s, net_index %d] %r",
            self.element.path,
            destination,
            remote,
            net_index,
            message,
        )

        await self._send_dev(destination, remote, net_index, data)
    def dev_key_message_received(self, source: int, remote: bool,
                                 net_index: int, data: bytes):
        """
        Called by :py:class:`bluetooth_mesh.interfaces.ElementInterface` when
        receiving a message encrypted with device key.

        The message is parsed using :py:class:`bluetooth_mesh.messages.AccessMessage`
        and (depending on the opcode) passed to relevant models'
        :py:func:`bluetooth_mesh.models.Model.dev_key_message_received`.
        """

        try:
            message = AccessMessage.parse(data)
        except construct.ConstructError as ex:
            self.logger.warning(
                "Dev message parse error [source %04x, net_index %d, data %s]: %s",
                source,
                net_index,
                data.hex(),
                ex,
            )
            return

        for model in self._models.values():
            if message["opcode"] in model.OPCODES:
                model.dev_key_message_received(source, remote, net_index,
                                               message)
                return
    def message_received(self, source: int, app_index: int,
                         destination: Union[int, UUID], data: bytes):
        """
        Called by :py:class:`bluetooth_mesh.interfaces.ElementInterface` when
        receiving a message encrypted with application key.

        The message is parsed using :py:class:`bluetooth_mesh.messages.AccessMessage`
        and (depending on the opcode) passed to relevant models'
        :func:`~bluetooth_mesh.models.Model.message_received`.

        """
        try:
            message = AccessMessage.parse(data)
        except construct.ConstructError as ex:
            self.logger.warning(
                "App message parse error [source %04x, app_index %d, destination %04x, data %s]: %s",
                source,
                app_index,
                destination,
                data.hex(),
                ex,
            )
            return

        for model in self._models.values():
            if message["opcode"] in model.OPCODES:
                model.message_received(source, app_index, destination, message)
                return
def test_parse_capnproto(encoded, capnproto):
    logging.info("MESH[%i] %s", len(encoded), encoded.hex())

    decoded = AccessMessage.parse(encoded)
    logging.info("CONSTRUCT %r", decoded)

    params = CaseConverter.to_camelcase(decoded)
    logging.info("CAPNP INPUT[%i] %s", len(json.dumps(params)), json.dumps(params))

    message = capnproto.AccessMessage.new_message(**params)
    logging.info("CAPNP %r", message)

    packed = message.to_bytes_packed()
    logging.info("PACKED[%i] %s", len(packed), packed.hex())

    unpacked = capnproto.AccessMessage.from_bytes_packed(packed)
    logging.info("UNPACKED %r", unpacked)

    params = CaseConverter.to_snakecase(unpacked.to_dict())
    logging.info("CONSTRUCT INPUT %s", params)

    assert AccessMessage.build(params) == encoded
Beispiel #6
0
def test_dev_message_received(element, source, net_index, status_encoded):
    status_parsed = AccessMessage.parse(status_encoded)
    element.dev_key_message_received(source, True, net_index, status_encoded)
    MockModel.INSTANCES[0].dev_key_message_received.assert_called_once_with(
        source, True, net_index, status_parsed)
Beispiel #7
0
def test_message_received(element, source, app_index, status_encoded):
    status_parsed = AccessMessage.parse(status_encoded)
    element.message_received(source, app_index, False, status_encoded)
    MockModel.INSTANCES[0].message_received.assert_called_once_with(
        source, app_index, False, status_parsed)
def test_parse(encoded, decoded):
    result = AccessMessage.parse(data=encoded)
    # print(result)
    assert result == decoded
def test_build(encoded, decoded):
    result = AccessMessage.build(obj=decoded)
    # print(result)
    assert result == encoded