Skip to main content

BleAccessory

Struct BleAccessory 

Source
pub struct BleAccessory { /* private fields */ }
Expand description

A connected BLE accessory: holds the GATT link, the secure session, the cached attribute database, and a map from (aid, iid) to GATT characteristic UUID for issuing PDUs.

Implementations§

Source§

impl BleAccessory

Source

pub fn accessories(&self) -> &[Accessory]

The cached attribute database.

Source

pub async fn broadcast_state(&self) -> BleBroadcastState

The current persistable broadcast material (key + latest GSN). Persist this so a later connect can resume broadcast decryption.

Source

pub fn find( &self, svc: ServiceType, chr: CharacteristicType, ) -> Result<(u64, u64)>

Find the (aid, iid) of a characteristic by service + characteristic type.

§Errors

BleError::CharacteristicNotFound if no match exists.

Source

pub async fn read(&mut self, aid: u64, iid: u64) -> Result<CharValue>

Read a characteristic value, decoded to its declared format.

§Errors

BleError::CharacteristicNotFound if unknown; otherwise GATT/PDU/crypto.

Source

pub async fn remove_pairing(&mut self, controller_id: &str) -> Result<()>

Remove a pairing by controller pairing id. Pass this controller’s own id to un-pair this controller; pass another controller’s id (this session must hold admin permission) to remove that one.

Runs as an encrypted RemovePairing (State M1, Method 4) write to the accessory’s Pairing-Pairings characteristic; a reconnect-invalidated session is re-verified first.

Removing this controller’s own pairing is a special case: the accessory removes the pairing and tears down the secure session as part of the same operation, so the encrypted M2 response is frequently lost or undecryptable (the link drops, or the reply is no longer sealed under the now-defunct session). Per the HAP self-removal semantics, once the request has been written the removal has taken effect, so a transport/crypto failure reading the response on self-removal is reported as success.

§Errors

BleError::PairingRejected if the accessory rejects the request (PDU status or a kTLVType_Error in the M2 reply); otherwise GATT/PDU/crypto errors (except the tolerated self-removal teardown described above).

Source

pub async fn write( &mut self, aid: u64, iid: u64, value: CharValue, ) -> Result<()>

Write a characteristic value, encoded per its declared format, over the encrypted session (re-verified after a reconnect, like Self::read).

§Errors

BleError::CharacteristicNotFound if unknown; BleError::RequestRejected if the accessory returns a non-zero PDU status; BleError::MalformedPdu if value does not match the characteristic’s format; otherwise GATT/crypto errors.

Source

pub async fn thread_provision(&mut self, dataset: &ThreadDataset) -> Result<()>

Commission this accessory onto the Thread network described by dataset.

HomeKit Thread accessories receive their Thread credentials over HAP-BLE rather than a joiner flow: over the established secure session this writes a query and then the operational dataset to the accessory’s Thread Control Point characteristic (0x0704). After it succeeds the accessory joins that Thread network and becomes reachable over Thread (e.g. via hap-thread).

The accessory typically drops the BLE link as it switches networks, so a transport error on the provision write is expected and treated as success (mirroring aiohomekit); confirm the outcome by the device appearing on the mesh, not by this call’s result. The dataset carries a secret network key — see ThreadDataset, whose Debug redacts it.

§Errors

BleError::CharacteristicNotFound if the accessory exposes no Thread Control Point (not a Thread accessory); otherwise a GATT/PDU/crypto error from the initial query write.

Source

pub fn pairing_id(&self) -> &str

The accessory’s HAP pairing id (as stored in the pairing record).

Source

pub async fn enable_broadcasts(&mut self, iids: &[u64]) -> Result<()>

Enable encrypted broadcast notifications for the given characteristic instance ids (the HAP BLE accessory id is always 1). Each is an encrypted Characteristic-Configuration write (Properties + Broadcast-Interval). Call this while connected, before disconnecting to receive sleepy events — without it the accessory will not emit 0x11 encrypted broadcasts. A characteristic that does not support broadcasts is skipped; per-write failures are tolerated (best-effort).

§Errors

Propagates a session re-verify failure.

Source

pub async fn disconnect(&self)

Release the underlying link (so the sleepy accessory advertises again). A no-op on backends without a live link.

Source

pub async fn subscribe(&mut self, aid: u64, iid: u64) -> Result<()>

Subscribe to value-change events for a characteristic. HAP-BLE connected events use the GATT notification only as a trigger: when it fires we issue an encrypted Characteristic-Read for the new value and publish it on BleAccessory::events.

§Errors

BleError::CharacteristicNotFound if unknown; otherwise GATT errors.

Connected events are best-effort: if the link drops, this GATT subscription ends and is not re-armed (re-arming a sleepy device storms). Durable updates arrive via BleAccessory::events from the broadcast and disconnected-event channels.

Source

pub async fn watch_sleepy_events_with_source( &mut self, advert_source: Arc<dyn AdvertSource>, device_id: [u8; 6], poll_iids: Vec<(u64, u64)>, ) -> Result<()>

Watch advertisements and deliver disconnected-event updates. Two paths:

  • Regular (0x06) advertisements: when the accessory’s GSN bumps, read each polled characteristic and publish its value on BleAccessory::events. Events are deduplicated by (iid, gsn). The poll runs on its own task fed by a watch channel, so bumps coalesce.
  • Encrypted broadcast (0x11) advertisements: decrypt the value directly from the advertisement using the stored hap_crypto::BroadcastKey and publish it — no GATT connection needed.

The advert source is supplied by the caller (the same backend object that provides the GATT connection).

§Errors

BleError if the advert source cannot start.

Source

pub fn set_advert_source(&mut self, src: Arc<dyn AdvertSource>)

Provide the advert source (the connection) so the self-sourcing watch_sleepy_events can use it.

Source

pub async fn watch_sleepy_events( &mut self, poll_iids: Vec<(u64, u64)>, ) -> Result<()>

Watch for sleepy-device events, self-sourcing the advert source (set via set_advert_source) and the device id (from the pairing id). Arms the same machinery as watch_sleepy_events_with_source.

§Errors

BleError::NoAdvertSource if no source was set; BleError::Backend if the stored pairing id cannot be parsed as a device id; otherwise advert/GATT errors.

Source

pub fn events(&self) -> impl Stream<Item = CharacteristicEvent>

An async stream of characteristic events. Each call returns a fresh subscriber to the shared event channel.

Trait Implementations§

Source§

impl Drop for BleAccessory

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more