1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! `blew` is a cross-platform BLE central + peripheral library.
//!
//! Supports iOS, macOS, Linux, and Android. Each role is initialised
//! independently, and in its simplest form:
//!
//! ```rust
//! # async fn example() -> blew::error::BlewResult<()> {
//! use blew::central::{Central, ScanFilter};
//! use blew::peripheral::Peripheral;
//!
//! let central: Central = Central::new().await?;
//! central.start_scan(ScanFilter::default()).await?;
//!
//! let peripheral: Peripheral = Peripheral::new().await?;
//! # Ok(())
//! # }
//! ```
//!
//! # Getting started
//!
//! Construct [`Central`] or [`Peripheral`] with an explicit type annotation:
//!
//! ```no_run
//! # async fn example() -> blew::error::BlewResult<()> {
//! use blew::central::Central;
//! let central: Central = Central::new().await?;
//! # Ok(()) }
//! ```
//!
//! The annotation is required because Rust's default type-parameter inference does not fire on
//! method calls. If you see compiler error E0283 ("type annotations needed"), you forgot the
//! `: Central`.
//!
//! # State restoration
//!
//! **iOS only.** On macOS, Linux, and Android the restoration configuration is inert —
//! `Central::with_config` / `Peripheral::with_config` accept the same types but behave
//! identically to `new()` there, so applications can call them unconditionally. The
//! `take_restored()` drain methods are only exposed on Apple targets; non-Apple code
//! does not need to call them.
//!
//! State restoration lets iOS relaunch your app in the background when BLE events arrive
//! after it has been suspended or jetsam-killed. When it works, the system hands back the
//! previously-connected peripherals (central) or published services (peripheral), along
//! with the subscriber list and any in-flight advertising state — no re-scan, no
//! re-advertise, no re-discover-services. Used correctly it can keep a BLE session alive
//! across hours or days of background time. Used incorrectly it silently does nothing, or
//! worse, diverges from what the OS expects and causes connection drops. The rules below
//! are non-negotiable.
//!
//! ## Prerequisites
//!
//! 1. **Info.plist `UIBackgroundModes`** must include `bluetooth-central` (for [`Central`])
//! and/or `bluetooth-peripheral` (for [`Peripheral`]). Without these the OS will not
//! preserve or restore state and `with_config` behaves like `new()`.
//! 2. **The restore identifier must be stable across launches.** Hard-code it or load it
//! from a place that is available before the BLE stack comes up (e.g. a build-time
//! constant). If the identifier differs from the previous launch, the OS discards the
//! preserved state.
//! 3. **Construct the role in `application:didFinishLaunchingWithOptions:`** — that is, at
//! the earliest possible point in app startup, *synchronously* from the launch
//! callback. If you construct it later, the delegate misses the `willRestoreState:`
//! callback and preserved state is dropped.
//!
//! ## Runtime contract
//!
//! The `willRestoreState:` callback fires *during* manager construction, before
//! [`Central::with_config`] / [`Peripheral::with_config`] returns, so subscribers attached
//! afterwards would miss it. Instead, the payload is buffered and handed out once via
//! [`Central::take_restored`] / [`Peripheral::take_restored`]. Call it immediately after
//! `with_config`, before issuing any new work (scanning, connecting, adding services,
//! advertising) — otherwise the app's state can diverge from the OS's in ways that look
//! like random disconnects.
//!
//! Typical shape (iOS):
//!
//! ```ignore
//! use blew::central::{Central, CentralConfig};
//!
//! let central: Central = Central::with_config(CentralConfig {
//! restore_identifier: Some("com.example.app.central".into()),
//! ..Default::default()
//! }).await?;
//!
//! if let Some(devices) = central.take_restored() {
//! // Re-hydrate app-level state from the restored peripherals before
//! // kicking off any new scans or connects.
//! for _dev in devices { /* ... */ }
//! }
//! ```
//!
//! ## What is *not* restored
//!
//! - **L2CAP CoC channels.** The OS does not persist L2CAP sockets across termination.
//! Any side that had a channel open must re-establish it — the central via
//! [`Central::open_l2cap_channel`], the peripheral via
//! [`Peripheral::l2cap_listener`]. The restored-state callbacks do not carry PSM info.
//! - **Subscribers.** Peripheral subscribers are not carried across restoration; the
//! `SubscriptionChanged` events replay as clients re-subscribe.
//! - **GATT service discovery cache** (central side) is preserved, but discovered
//! characteristics will be re-emitted by your own `discover_services` flow if you call
//! it again. Skip redundant discovery by using the restored peripherals directly.
//!
//! ## Background runtime caveats
//!
//! - Background scanning is degraded: you must pass a non-empty service-UUID filter, the
//! OS forces duplicate suppression on, and the scan duty cycle is coalesced with other
//! apps. Scans with no filter are silently ignored in the background.
//! - Background advertising strips `local_name` from the advertisement and moves service
//! UUIDs into the overflow area. Peers that are not explicitly scanning for your
//! service UUID will not see you.
//! - Repeated crashes during a background relaunch cause iOS to *disable* background BLE
//! for your app until the user relaunches it from the foreground. Treat
//! `willRestoreState:` as a stability-critical code path.
pub use ;
pub use ;
pub use L2capChannel;
pub use Peripheral;
pub use ;