def notify( self, data ) -> IdBasedEventWaitable[GattsCharacteristic, NotificationCompleteEventArgs]: """ Notifies the client with the data provided without setting the data into the characteristic value. If data is not provided (None), will notify with the currently-set value of the characteristic :param data: Optional data to notify the client with. If supplied, must be an iterable type such as a str, bytes, or list of uint8 values, or a BleDataStream object. Length must be less than or equal to the characteristic's max length. If a string is given, it will be encoded using the string_encoding property of the characteristic. :raises: InvalidStateException if the client is not subscribed to the characteristic :raises: InvalidOperationException if the characteristic is not configured for notifications/indications :return: An EventWaitable that will trigger when the notification is successfully sent to the client. The waitable also contains the ID of the sent notification which is used in the on_notify_complete event """ if isinstance(data, BleDataStream): value = data.value if isinstance(data, str): value = data.encode(self.string_encoding) if not self.notifiable: raise InvalidOperationException( "Cannot notify client. " "{} not set up for notifications or indications".format( self.uuid)) if not self.client_subscribed: raise InvalidStateException( "Client is not subscribed, cannot notify client") notification_id = self._notification_manager.notify( self, self._value_attr.handle, self._on_notify_complete, data) return IdBasedEventWaitable(self._on_notify_complete, notification_id)
def subscribe(self, on_notification_handler, prefer_indications=False): """ Subscribes to the characteristic's indications or notifications, depending on what's available and the prefer_indications setting. Returns a Waitable that executes when the subscription on the peripheral finishes. The Waitable returns two parameters: (GattcCharacteristic this, SubscriptionWriteCompleteEventArgs event args) :param on_notification_handler: The handler to be called when an indication or notification is received from the peripheral. Must take three parameters: (GattcCharacteristic this, gatt.GattNotificationType, bytearray data) :param prefer_indications: If the peripheral supports both indications and notifications, will subscribe to indications instead of notifications :return: A Waitable that will fire when the subscription finishes :rtype: blatann.waitables.EventWaitable :raises: InvalidOperationException if the characteristic cannot be subscribed to (characteristic does not support indications or notifications) """ if not self.subscribable: raise InvalidOperationException( "Cannot subscribe to Characteristic {}".format(self.uuid)) if prefer_indications and self._properties.indicate or not self._properties.notify: value = gatt.SubscriptionState.INDICATION else: value = gatt.SubscriptionState.NOTIFY self._on_notification_event.register(on_notification_handler) write_id = self._manager.write(self.cccd_handle, gatt.SubscriptionState.to_buffer(value)) return IdBasedEventWaitable(self._on_cccd_write_complete_event, write_id)
def notify( self, data ) -> EventWaitable[GattsCharacteristic, NotificationCompleteEventArgs]: """ Notifies the client with the data provided without setting the data into the characteristic value. If data is not provided (None), will notify with the currently-set value of the characteristic :param data: The data to notify the client with :return: An EventWaitable that will fire when the notification is successfully sent to the client. The waitable also contains the ID of the sent notification which is used in the on_notify_complete event :rtype: NotificationCompleteEventWaitable """ if isinstance(data, BleDataStream): value = data.value if isinstance(data, str): value = data.encode(self.string_encoding) if not self.notifiable: raise InvalidOperationException( "Cannot notify client. " "{} not set up for notifications or indications".format( self.uuid)) if not self.client_subscribed: raise InvalidStateException( "Client is not subscribed, cannot notify client") notification_id = self._notification_manager.notify( self, self.value_handle, self._on_notify_complete, data) return IdBasedEventWaitable(self._on_notify_complete, notification_id)
def subscribe( self, on_notification_handler: Callable[ [GattcCharacteristic, NotificationReceivedEventArgs], None], prefer_indications=False ) -> EventWaitable[GattcCharacteristic, SubscriptionWriteCompleteEventArgs]: """ Subscribes to the characteristic's indications or notifications, depending on what's available and the prefer_indications setting. Returns a Waitable that triggers when the subscription on the peripheral finishes. :param on_notification_handler: The handler to be called when an indication or notification is received from the peripheral. Must take two parameters: (GattcCharacteristic this, NotificationReceivedEventArgs event args) :param prefer_indications: If the peripheral supports both indications and notifications, will subscribe to indications instead of notifications :return: A Waitable that will trigger when the subscription finishes :raises: InvalidOperationException if the characteristic cannot be subscribed to (characteristic does not support indications or notifications) """ if not self.subscribable: raise InvalidOperationException( "Cannot subscribe to Characteristic {}".format(self.uuid)) if prefer_indications and self._properties.indicate or not self._properties.notify: value = gatt.SubscriptionState.INDICATION else: value = gatt.SubscriptionState.NOTIFY self._on_notification_event.register(on_notification_handler) waitable = self._cccd_attr.write( gatt.SubscriptionState.to_buffer(value)) return IdBasedEventWaitable(self._on_cccd_write_complete_event, waitable.id)
def read(self) -> IdBasedEventWaitable[GattcAttribute, ReadCompleteEventArgs]: """ Performs a read of the attribute and returns a Waitable that executes when the read finishes with the data read. :return: A waitable that will trigger when the read finishes """ read_id = self._manager.read(self._handle, self._read_complete) return IdBasedEventWaitable(self._on_read_complete_event, read_id)
def read(self) -> EventWaitable[GattcCharacteristic, ReadCompleteEventArgs]: """ Initiates a read of the characteristic and returns a Waitable that executes when the read finishes with the data read. The Waitable returns two parameters: (GattcCharacteristic this, ReadCompleteEventArgs event args) :return: A waitable that will fire when the read finishes :raises: InvalidOperationException if characteristic not readable """ if not self.readable: raise InvalidOperationException("Characteristic {} is not readable".format(self.uuid)) read_id = self._manager.read(self.value_handle) return IdBasedEventWaitable(self._on_read_complete_event, read_id)
def read( self) -> EventWaitable[GattcCharacteristic, ReadCompleteEventArgs]: """ Initiates a read of the characteristic and returns a Waitable that triggers when the read finishes with the data read. :return: A waitable that will trigger when the read finishes :raises: InvalidOperationException if characteristic not readable """ if not self.readable: raise InvalidOperationException( "Characteristic {} is not readable".format(self.uuid)) waitable = self._value_attr.read() return IdBasedEventWaitable(self._on_read_complete_event, waitable.id)
def write(self, data, with_response=True) -> IdBasedEventWaitable[GattcAttribute, WriteCompleteEventArgs]: """ Initiates a write of the data provided to the attribute and returns a Waitable that executes when the write completes and the confirmation response is received from the other device. :param data: The data to write. Can be a string, bytes, or anything that can be converted to bytes :type data: str or bytes or bytearray :param with_response: Used internally for characteristics that support write without responses. Should always be true for any other case (descriptors, etc.). :return: A waitable that returns when the write finishes """ if isinstance(data, str): data = data.encode(self._string_encoding) write_id = self._manager.write(self._handle, bytes(data), self._write_complete, with_response) return IdBasedEventWaitable(self._on_write_complete_event, write_id)
def write(self, data): """ Initiates a write of the data provided to the characteristic and returns a Waitable that executes when the write completes. The Waitable returns two parameters: (GattcCharacteristic this, WriteCompleteEventArgs event args) :param data: The data to write. Can be a string, bytearray, or anything that can be converted to a bytearray :return: A waitable that returns when the write finishes :rtype: blatann.waitables.EventWaitable :raises: InvalidOperationException if characteristic is not writable """ if not self.writable: raise InvalidOperationException( "Characteristic {} is not writable".format(self.uuid)) write_id = self._manager.write(self.value_handle, bytearray(data)) return IdBasedEventWaitable(self._on_write_complete_event, write_id)
def unsubscribe(self) -> EventWaitable[GattcCharacteristic, SubscriptionWriteCompleteEventArgs]: """ Unsubscribes from indications and notifications from the characteristic and clears out all handlers for the characteristic's on_notification event handler. Returns a Waitable that executes when the unsubscription finishes. The Waitable returns two parameters: (GattcCharacteristic this, SubscriptionWriteCompleteEventArgs event args) :return: A Waitable that will fire when the unsubscription finishes """ if not self.subscribable: raise InvalidOperationException("Cannot subscribe to Characteristic {}".format(self.uuid)) value = gatt.SubscriptionState.NOT_SUBSCRIBED write_id = self._manager.write(self.cccd_handle, gatt.SubscriptionState.to_buffer(value)) self._on_notification_event.clear_handlers() return IdBasedEventWaitable(self._on_cccd_write_complete_event, write_id)
def write( self, data ) -> EventWaitable[GattcCharacteristic, WriteCompleteEventArgs]: """ Performs a write request of the data provided to the characteristic and returns a Waitable that triggers when the write completes and the confirmation response is received from the other device. :param data: The data to write. Can be a string, bytes, or anything that can be converted to bytes :type data: str or bytes or bytearray :return: A waitable that returns when the write finishes :raises: InvalidOperationException if characteristic is not writable """ if not self.writable: raise InvalidOperationException( "Characteristic {} is not writable".format(self.uuid)) if isinstance(data, str): data = data.encode(self.string_encoding) waitable = self._value_attr.write(bytes(data), True) return IdBasedEventWaitable(self._on_write_complete_event, waitable.id)
def write_without_response( self, data ) -> EventWaitable[GattcCharacteristic, WriteCompleteEventArgs]: """ Performs a write command, which does not require the peripheral to send a confirmation response packet. This is a faster but lossy operation in the case that the packet is dropped/never received by the peer. This returns a waitable that triggers when the write is transmitted to the peripheral device. .. note:: Data sent without responses must fit within a single MTU minus 3 bytes for the operation overhead. :param data: The data to write. Can be a string, bytes, or anything that can be converted to bytes :type data: str or bytes or bytearray :return: A waitable that returns when the write finishes :raises: InvalidOperationException if characteristic is not writable without responses """ if not self.writable_without_response: raise InvalidOperationException( "Characteristic {} does not accept " "writes without responses".format(self.uuid)) if isinstance(data, str): data = data.encode(self.string_encoding) waitable = self._value_attr.write(bytes(data), False) return IdBasedEventWaitable(self._on_write_complete_event, waitable.id)
def unsubscribe( self ) -> EventWaitable[GattcCharacteristic, SubscriptionWriteCompleteEventArgs]: """ Unsubscribes from indications and notifications from the characteristic and clears out all handlers for the characteristic's on_notification event handler. Returns a Waitable that triggers when the unsubscription finishes. :return: A Waitable that will trigger when the unsubscription operation finishes :raises: InvalidOperationException if characteristic cannot be subscribed to (characteristic does not support indications or notifications) """ if not self.subscribable: raise InvalidOperationException( "Cannot subscribe to Characteristic {}".format(self.uuid)) value = gatt.SubscriptionState.NOT_SUBSCRIBED waitable = self._cccd_attr.write( gatt.SubscriptionState.to_buffer(value)) self._on_notification_event.clear_handlers() return IdBasedEventWaitable(self._on_cccd_write_complete_event, waitable.id)
def read_time(self) -> EventWaitable[CurrentTimeClient, DecodedReadCompleteEventArgs[CurrentTime]]: """ Reads the time from the server """ event = self._current_time_char.read().then(self._current_time_dispatcher) return IdBasedEventWaitable(self._on_current_time_updated_event, event.id)
def read_time(self): event = self._current_time_char.read().then(self._current_time_dispatcher) return IdBasedEventWaitable(self._on_current_time_updated_event, event.id)