def _on_write_request(self, request):
        """Callback function called when a write request has been received.
        It is executed in the baBLE working thread: should not be blocking.

        Args:
            request (dict): Information about the request
              - connection_handle (int): The connection handle that sent the request
              - attribute_handle (int): The attribute handle to write
              - value (bytes): The value to write
        """
        if request['connection_handle'] != self._connection_handle:
            return False

        attribute_handle = request['attribute_handle']

        # If write to configure notification
        config_handles = [
            ReceiveHeaderChar.config_handle,
            ReceivePayloadChar.config_handle,
            StreamingChar.config_handle,
            TracingChar.config_handle
        ]
        if attribute_handle in config_handles:
            notification_enabled, _ = struct.unpack('<BB', request['value'])

            # ReceiveHeader or ReceivePayload
            if attribute_handle in [ReceiveHeaderChar.config_handle, ReceivePayloadChar.config_handle] and notification_enabled:
                if attribute_handle == ReceiveHeaderChar.config_handle:
                    self.header_notif = True
                elif attribute_handle == ReceivePayloadChar.config_handle:
                    self.payload_notif = True

                if self.header_notif and self.payload_notif:
                    self.device.open_rpc_interface()
                    self._audit("RPCInterfaceOpened")

            # Streaming
            elif attribute_handle == StreamingChar.config_handle:
                if notification_enabled and not self.streaming:
                    self.streaming = True

                    # If we should send any reports, queue them for sending
                    reports = self.device.open_streaming_interface()
                    if reports is not None:
                        self._queue_reports(*reports)

                    self._audit('StreamingInterfaceOpened')
                elif not notification_enabled and self.streaming:
                    self.streaming = False
                    self.device.close_streaming_interface()
                    self._audit('StreamingInterfaceClosed')

            # Tracing
            elif attribute_handle == TracingChar.config_handle:
                if notification_enabled and not self.tracing:
                    self.tracing = True

                    # If we should send any trace data, queue it immediately
                    traces = self.device.open_tracing_interface()
                    if traces is not None:
                        self._queue_traces(*traces)

                    self._audit('TracingInterfaceOpened')
                elif not notification_enabled and self.tracing:
                    self.tracing = False
                    self.device.close_tracing_interface()
                    self._audit('TracingInterfaceClosed')

            return True
        # If write an RPC
        elif attribute_handle in [SendHeaderChar.value_handle, SendPayloadChar.value_handle]:
            # Payload
            if attribute_handle == SendPayloadChar.value_handle:
                self.rpc_payload = bytearray(request['value'])
                if len(self.rpc_payload) < 20:
                    self.rpc_payload += bytearray(20 - len(self.rpc_payload))
            # Header
            elif attribute_handle == SendHeaderChar.value_handle:
                self._defer(self._call_rpc, [bytearray(request['value'])])

            return True
        else:
            return False