commit a729199926b82e9102e0998998893bc56d2c384a
parent 13b0868488f8137ad1bd059b876c404a1c8fef7e
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 1 Feb 2026 15:27:30 +0000
PoC BLE support
It advertises, and it enumerates some characteristics. None of them
are hooked up to anthing yet
Diffstat:
4 files changed, 595 insertions(+), 3 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -3,6 +3,17 @@
version = 4
[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -27,6 +38,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -98,6 +115,15 @@ name = "btuuid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0acfef8a77a02866e04f7e2ad3f4c7b32d575696c49c4bbad742b4aecb8e4a3"
+dependencies = [
+ "uuid",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "bytemuck"
@@ -118,6 +144,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "cmac"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa"
+dependencies = [
+ "cipher",
+ "dbl",
+ "digest",
+]
+
+[[package]]
name = "const-default"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -130,6 +177,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
+name = "convert_case"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -145,6 +201,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "generic-array",
+ "rand_core 0.6.4",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "crypto-common"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -285,6 +353,15 @@ dependencies = [
]
[[package]]
+name = "dbl"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "delegate"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -313,6 +390,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -362,6 +440,7 @@ dependencies = [
"rand_core 0.6.4",
"smoltcp",
"static_cell",
+ "trouble-host",
]
[[package]]
@@ -393,6 +472,25 @@ dependencies = [
]
[[package]]
+name = "elliptic-curve"
+version = "0.13.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "hkdf",
+ "rand_core 0.6.4",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "embassy-embedded-hal"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1037,6 +1135,16 @@ dependencies = [
]
[[package]]
+name = "ff"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
+dependencies = [
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1064,6 +1172,30 @@ dependencies = [
]
[[package]]
+name = "futures"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1080,6 +1212,12 @@ dependencies = [
]
[[package]]
+name = "futures-io"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+
+[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1098,6 +1236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
+ "futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
@@ -1117,6 +1256,18 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core 0.6.4",
+ "subtle",
]
[[package]]
@@ -1166,6 +1317,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1191,6 +1360,15 @@ dependencies = [
]
[[package]]
+name = "inout"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "instability"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1234,6 +1412,16 @@ dependencies = [
]
[[package]]
+name = "js-sys"
+version = "0.3.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "libc"
version = "0.2.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1314,6 +1502,22 @@ dependencies = [
]
[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "p256"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+dependencies = [
+ "elliptic-curve",
+ "primeorder",
+]
+
+[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1378,6 +1582,24 @@ dependencies = [
]
[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "primeorder"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+dependencies = [
+ "elliptic-curve",
+]
+
+[[package]]
name = "proc-macro-crate"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1405,6 +1627,25 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.4",
+]
+
+[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1515,6 +1756,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
+name = "sec1"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "semver"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1741,6 +1995,44 @@ dependencies = [
]
[[package]]
+name = "trouble-host"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2881b4859001fe1f48445145cda5149deac9110b1d707ec0a251b7ff6d8bdfa4"
+dependencies = [
+ "aes",
+ "bt-hci",
+ "cmac",
+ "embassy-futures",
+ "embassy-sync 0.7.2",
+ "embassy-time",
+ "embedded-io 0.6.1",
+ "futures",
+ "heapless 0.9.2",
+ "p256",
+ "rand",
+ "rand_chacha",
+ "rand_core 0.6.4",
+ "static_cell",
+ "trouble-host-macros",
+ "zerocopy",
+]
+
+[[package]]
+name = "trouble-host-macros"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcb85bec3a8393c22ca1a7c25c82c2d33689ab412f3487c492fd01a033ede7c2"
+dependencies = [
+ "convert_case",
+ "darling 0.20.11",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.114",
+ "uuid",
+]
+
+[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1759,6 +2051,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1771,6 +2069,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
+name = "uuid"
+version = "1.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1789,6 +2097,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
+name = "wasm-bindgen"
+version = "0.2.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.114",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1853,6 +2206,26 @@ dependencies = [
]
[[package]]
+name = "zerocopy"
+version = "0.8.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.114",
+]
+
+[[package]]
name = "zeroize"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/ecu-esp32/Cargo.toml b/ecu-esp32/Cargo.toml
@@ -72,3 +72,8 @@ ed25519-dalek = { version = "2", default-features = false, features = ["alloc"]
rand_core = "0.6"
nb = "1.1.0"
hashbrown = "0.16.1"
+trouble-host = { version = "0.5.1", default-features = false, features = [
+ "peripheral", "gatt", "derive", "security", "default-packet-pool",
+ "default-packet-pool-mtu-64",
+ "dev-disable-csprng-seed-requirement" # !!!!
+]}
diff --git a/ecu-esp32/src/main.rs b/ecu-esp32/src/main.rs
@@ -8,12 +8,15 @@
use esp_backtrace as _;
use esp_println as _;
+use esp_alloc as _;
+
pub mod ecu;
pub mod wifi;
pub mod mdns;
pub mod streamer;
pub mod ota;
+pub mod wibble;
use esp_hal::{
timer::timg::TimerGroup,
@@ -21,7 +24,7 @@ use esp_hal::{
};
use embassy_executor::Spawner;
-use embassy_futures::join::join;
+use embassy_futures::join::join3;
use embassy_time::Timer;
use esp_radio::Controller;
@@ -58,7 +61,7 @@ async fn main(s : Spawner) {
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
- esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 66320);
+ esp_alloc::heap_allocator!(size: 92 * 1024);
// handwaving: we need the timer to schedule tasks for the rtos,
// and we need the rtos so that the ble works (assumption:
@@ -80,14 +83,16 @@ async fn main(s : Spawner) {
let flasher = Flasher::new(peripherals.FLASH, peripherals.SHA);
- join(
let esp_radio_ctrl = // esp_radio::init().expect("esp_radio init failed");
&*mk_static!(Controller<'static>, esp_radio::init().unwrap());
+
+ join3(
crate::wifi::start_wifi(&s,
esp_radio_ctrl,
flasher,
peripherals.WIFI,
&mut ecu),
+ wibble::run_ble(&esp_radio_ctrl, peripherals.BT),
async {
loop {
Timer::after_millis(1000).await;
diff --git a/ecu-esp32/src/wibble.rs b/ecu-esp32/src/wibble.rs
@@ -0,0 +1,209 @@
+use embassy_time::Timer;
+use trouble_host::prelude::*;
+use esp_radio::ble::controller::BleConnector;
+use esp_radio::Controller as RadioController;
+use log::{warn,info};
+use embassy_futures::join::join;
+use embassy_futures::select::select;
+
+use alloc::string::String;
+
+/// Max number of connections
+const CONNECTIONS_MAX: usize = 1;
+
+/// Max number of L2CAP channels.
+// XXX why not 0?
+const L2CAP_CHANNELS_MAX: usize = 2; // Signal + att
+
+// GATT Server definition
+#[gatt_server]
+struct Server {
+ wifi_provisioning_service: WifiProvisioningService,
+}
+
+
+#[gatt_service(uuid = "76be25c2-0000-44fc-a97c-bcb56c69c926")]
+struct WifiProvisioningService {
+ #[characteristic(uuid = "76be25c2-0801-44fc-a97c-bcb56c69c926", read, notify, value = 0)]
+ connection_state: u8,
+
+ #[characteristic(uuid = "76be25c2-0802-44fc-a97c-bcb56c69c926", read, notify, value = 0)]
+ max_network_index: u8,
+
+ #[characteristic(uuid = "76be25c2-0803-44fc-a97c-bcb56c69c926", write, value = 0)]
+ current_network_index: u8,
+
+ // for arrays > 32 we must supply a default value : see
+ // https://github.com/embassy-rs/trouble/issues/320
+ #[characteristic(uuid = "76be25c2-0804-44fc-a97c-bcb56c69c926",
+ value = [0; 40],
+ read, notify)]
+ current_network: [u8; 40],
+
+ #[characteristic(uuid = "76be25c2-0805-44fc-a97c-bcb56c69c926",
+ value = [0; 64],
+ write)]
+ secret: [u8; 64]
+}
+
+
+pub async fn run_ble(radio_init: &RadioController<'static>,
+ peripheral: esp_hal::peripherals::BT<'_>) {
+ // let radio_init = esp_radio::init().expect("Failed to initialize Wi-Fi/BLE controller");
+ let connector = BleConnector::new(&radio_init, peripheral, Default::default()).expect("connector");
+ let controller: ExternalController<_, 20> = ExternalController::new(connector);
+
+ // Using a fixed "random" address can be useful for testing. In real scenarios, one would
+ // use e.g. the MAC 6 byte array as the address (how to get that varies by the platform).
+ let address: Address = Address::random([0xff, 0x8f, 0x1a, 0x05, 0xe4, 0xff]);
+ info!("Our address = {:?}", address);
+
+ let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = HostResources::new();
+ let stack = trouble_host::new(controller, &mut resources).set_random_address(address);
+ let Host {
+ mut peripheral, runner, ..
+ } = stack.build();
+
+ info!("Starting advertising and GATT service");
+ let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig {
+ name: "eculocate",
+ appearance: &appearance::power_device::GENERIC_POWER_DEVICE,
+ }))
+ .unwrap();
+
+ let _ = join(
+ ble_task(runner),
+ async {
+ loop {
+ match advertise("Eculocate", &mut peripheral, &server).await {
+ Ok(conn) => {
+ // set up tasks when the connection is established to a central, so they don't run when no one is connected.
+ let a = gatt_events_task(&server, &conn);
+ let b = custom_task(&server, &conn, &stack);
+ // run until any task ends (usually because the connection has been closed),
+ // then return to advertising state.
+ select(a, b).await;
+ }
+ Err(e) => {
+ panic!("[adv] error: {:?}", e);
+ }
+ }
+ }
+ })
+ .await;
+}
+
+/// This is a background task that is required to run forever alongside any other BLE tasks.
+///
+async fn ble_task<C: Controller, P: PacketPool>(mut runner: Runner<'_, C, P>) {
+ loop {
+ if let Err(e) = runner.run().await {
+ panic!("[ble_task] error: {:?}", e);
+ }
+ }
+}
+
+/// Stream Events until the connection closes.
+///
+/// This function will handle the GATT events and process them.
+/// This is how we interact with read and write requests.
+async fn gatt_events_task<P: PacketPool>(_server: &Server<'_>, conn: &GattConnection<'_, '_, P>) -> Result<(), Error> {
+ // let level = server.battery_service.level;
+ let reason = loop {
+ match conn.next().await {
+ GattConnectionEvent::Disconnected { reason } => break reason,
+ GattConnectionEvent::Gatt { event } => {
+ // match &event {
+ // // are these clauses important? they don't do anything
+ // // except log
+ // GattEvent::Read(event) => {
+ // if event.handle() == level.handle {
+ // let value = server.get(&level);
+ // info!("[gatt] Read Event to Level Characteristic: {:?}", value);
+ // }
+ // }
+ // GattEvent::Write(event) => {
+ // if event.handle() == level.handle {
+ // info!("[gatt] Write Event to Level Characteristic: {:?}", event.data());
+ // }
+ // }
+ // _ => {}
+ // };
+ // This step is also performed at drop(), but writing it explicitly is necessary
+ // in order to ensure reply is sent.
+ match event.accept() {
+ Ok(reply) => reply.send().await,
+ Err(e) => warn!("[gatt] error sending response: {:?}", e),
+ };
+ }
+ _ => {} // ignore other Gatt Connection Events
+ }
+ };
+ info!("[gatt] disconnected: {:?}", reason);
+ Ok(())
+}
+
+/// Create an advertiser to use to connect to a BLE Central, and wait for it to connect.
+async fn advertise<'values, 'server, C: Controller>(
+ name: &'values str,
+ peripheral: &mut Peripheral<'values, C, DefaultPacketPool>,
+ server: &'server Server<'values>,
+) -> Result<GattConnection<'values, 'server, DefaultPacketPool>, BleHostError<C::Error>> {
+ let mut advertiser_data = [0; 31];
+ let len = AdStructure::encode_slice(
+ &[
+ AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
+ AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
+ AdStructure::CompleteLocalName(name.as_bytes()),
+ ],
+ &mut advertiser_data[..],
+ )?;
+ let advertiser = peripheral
+ .advertise(
+ &Default::default(),
+ Advertisement::ConnectableScannableUndirected {
+ adv_data: &advertiser_data[..len],
+ scan_data: &[],
+ },
+ )
+ .await?;
+ info!("[adv] advertising");
+ let conn = advertiser.accept().await?.with_attribute_server(server)?;
+ info!("[adv] connection established");
+ Ok(conn)
+}
+
+async fn custom_task<C: Controller, P: PacketPool>(
+ _server: &Server<'_>,
+ conn: &GattConnection<'_, '_, P>,
+ stack: &Stack<'_, C, P>,
+) {
+ // let mut tick: u8 = 0;
+ // let level = server.battery_service.level;
+ // let rpm = server.engine_speed_service.rpm;
+ loop {
+ // tick = tick.wrapping_add(1);
+ // info!("[custom_task] notifying connection of tick {}", tick);
+
+ // // if the characteristic does not support notifications,
+ // // this would return an error. Use `set` instead, in that case.
+ // // See inline comments in trouble-host/src/attribute.rs around
+ // // line 631
+
+ // if level.notify(conn, &tick).await.is_err() {
+ // info!("[custom_task] error notifying connection");
+ // break;
+ // };
+ // read RSSI (Received Signal Strength Indicator) of the connection.
+ if let Ok(rssi) = conn.raw().rssi(stack).await {
+ info!("[custom_task] RSSI: {:?}", rssi);
+ } else {
+ info!("[custom_task] error getting RSSI");
+ break;
+ };
+ // let new_rpm = 1200 + 20 * i32::from(tick);
+ // rpm.notify(conn, &new_rpm).await.expect("failed to notify");
+
+ Timer::after_secs(2).await;
+ }
+}