I'm excited about everything Rust and especially embedded stuff.
bjoernq / bleps Goto Github PK
View Code? Open in Web Editor NEWA toy-level BLE peripheral stack
License: MIT License
A toy-level BLE peripheral stack
License: MIT License
Howdy!
I've been playing with bleps lately and got it running on nRF52 using their softdevice controller, but it required some modifications to bleps, which got me thinking about where to go from there. For instance, there are a few changes I would like to make:
I would like to hear your opinion on the above before making actual PRs. As specified on the front page, bleps is intended as a toy BLE stack, but are there any plans/goals beyond that? I'm interested in investing some effort to make it work well on nRF.
This is more a question than an issue, but is there a specific reason, why bleps doesn't use generics instead of a dynamic reference to an HCIConnection on the BLE
struct?
If this has a specific reason, please let me know.
The BLE
struct is likely only instantiated once in the entire application and monomorphization will likely even reduce code size here.
let connector = esp_wifi::ble::controller::BleConnector {};
let hci = HciConnector::new(connector, esp_wifi::current_millis);
let service_uuid = Uuid::Uuid128([0x00, 0x00, 0xab, 0xf0, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb]);
let mut ble = Ble::new(&hci);
ble.init().unwrap();
ble.cmd_set_le_advertising_parameters().unwrap();
let advertising_data = create_advertising_data(&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids128(&[service_uuid]),
AdStructure::CompleteLocalName("BLE_TO_ISOTP"),
]);
ble.cmd_set_le_advertising_data(advertising_data).unwrap();
ble.cmd_set_le_advertise_enable(true).unwrap();
Brandons-MacBook-Air:esp32-isotp-ble-bridge-rs brandonros 2022-10-26 11:14:41 $ cargo run --release
warning: Patch `embassy-embedded-hal v0.1.0 (https://github.com/embassy-rs/embassy#ce1cba76)` was not used in the crate graph.
Check that the patched package version and available features are compatible
with the dependency requirements. If the patch has a different version from
what is locked in the Cargo.lock file, run `cargo update` to use the new
version. This may also occur with an optional dependency that is not enabled.
Compiling esp-wifi v0.1.0 (https://github.com/esp-rs/esp-wifi?branch=main#7adb1658)
Compiling esp32_isotp_ble_bridge_rs v0.1.0 (/Users/brandonros/Desktop/esp32-isotp-ble-bridge-rs)
warning: unused variable: `wdt`
--> src/main.rs:146:13
|
146 | let mut wdt = timer_group0.wdt;
| ^^^ help: if this is intentional, prefix it with an underscore: `_wdt`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable does not need to be mutable
--> src/main.rs:146:9
|
146 | let mut wdt = timer_group0.wdt;
| ----^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: static `CHANNEL` is never used
--> src/main.rs:34:8
|
34 | static CHANNEL: StaticCell<Channel<NoopRawMutex, u32, 4>> = StaticCell::new();
| ^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: static `TIMER0` is never used
--> src/main.rs:36:8
|
36 | static TIMER0: Mutex<RefCell<Option<Timer<Timer0<TIMG0>>>>> = Mutex::new(RefCell::new(None));
| ^^^^^^
warning: static `TIMER1` is never used
--> src/main.rs:37:8
|
37 | static TIMER1: Mutex<RefCell<Option<Timer<Timer1<TIMG0>>>>> = Mutex::new(RefCell::new(None));
| ^^^^^^
warning: static `SERIAL0` is never used
--> src/main.rs:38:8
|
38 | static SERIAL0: Mutex<RefCell<Option<Serial<UART0>>>> = Mutex::new(RefCell::new(None));
| ^^^^^^^
warning: function `receiver_task` is never used
--> src/main.rs:40:10
|
40 | async fn receiver_task(receiver: Receiver<'static, NoopRawMutex, u32, 4>) {
| ^^^^^^^^^^^^^
warning: function `sender_task` is never used
--> src/main.rs:59:10
|
59 | async fn sender_task(sender: Sender<'static, NoopRawMutex, u32, 4>) {
| ^^^^^^^^^^^
warning: `esp32_isotp_ble_bridge_rs` (bin "esp32_isotp_ble_bridge_rs") generated 8 warnings
Finished release [optimized] target(s) in 1.44s
Running `espflash --monitor /dev/tty.usbserial-02728E37 --monitor-speed 115200 target/xtensa-esp32-none-elf/release/esp32_isotp_ble_bridge_rs`
Serial port: /dev/tty.usbserial-02728E37
Connecting...
Chip type: ESP32 (revision 3)
Crystal frequency: 40MHz
Flash size: 16MB
Features: WiFi, BT, Dual Core, 240MHz, Coding Scheme None
MAC address: 94:b9:7e:57:4b:18
App/part. size: 295984/16711680 bytes, 1.77%
[00:00:01] ######################################## 16/16 segment 0x1000
[00:00:00] ######################################## 1/1 segment 0x8000
[00:00:16] ######################################## 156/156 segment 0x10000
Flashing has completed!
Commands:
CTRL+R Reset chip
CTRL+C Exit
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0048,len:12
ho 0 tail 12 room 4
load:0x3fff0054,len:4800
load:0x40078000,len:17448
0x40078000 - r_rwip_reset
at ??:??
load:0x4007c428,len:4840
0x4007c428 - r_rwip_reset
at ??:??
entry 0x4007c6a0
0x4007c6a0 - r_rwip_reset
at ??:??
WARN - coex_register_bt_cb 0x40081698
0x40081698 - coex_bt_callback
at ??:??
WARN - coex_schm_register_btdm_callback 0x400df7dc
0x400df7dc - coex_schm_btdm_callback
at ??:??
WARN - coex_wifi_channel_get
!! A panic occured in '/Users/brandonros/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/slice/index.rs', at line 73, column 5
PanicInfo {
payload: Any { .. },
message: Some(
range end index 129 out of range for slice of length 128,
),
location: Location {
file: "/Users/brandonros/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/slice/index.rs",
line: 73,
col: 5,
},
can_unwind: true,
}
Backtrace:
0x400dc009
0x400dc009 - _ZN4core3ops8function6FnOnce9call_once17hf83c65e1c5683b9fE
at ??:??
0x400dc039
0x400dc039 - _ZN4core10intrinsics17const_eval_select17h2e98052629cb9109E
at ??:??
0x400dc095
0x400dc095 - _ZN4core5slice5index24slice_end_index_len_fail17h1a7d586e621fc8b7E
at ??:??
0x400d7fca
0x400d7fca - _ZN5bleps12ad_structure23create_advertising_data17ha24b1c7a30ebd68cE
at ??:??
0x400d14ae
0x400d14ae - _ZN97_$LT$core..future..from_generator..GenFuture$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$4poll17h4c7b5d09e6303bf8E
at ??:??
0x400d1c1c
0x400d1c1c - _ZN16embassy_executor3raw20TaskStorage$LT$F$GT$4poll17h57ceb5a97861a96dE.llvm.11765450987655502707
at ??:??
0x400f7e27
0x400f7e27 - _ZN16embassy_executor3raw8Executor4poll17hb27cb61edfd0c27cE
at ??:??
0x400d1c88
0x400d1c88 - _ZN16embassy_executor4arch8Executor3run17h50320a162ae4a970E
at ??:??
0x400d1e45
0x400d1e45 - main
at ??:??
0x400d947a
0x400d947a - Reset
at ??:??
https://github.com/rust-embedded/embedded-hal/tree/master/embedded-io-async Slightly breaking change, I'm trying to handle this but boy it's a little confusing for somebody not super well versed in traits
async_attribute_server
is basically a copy of all the code in attribute_server
Hi! I notice examples here and in the esp-wifi
crate for advertising device data. Is there a way to view nearby device advertisements? Thank you!
I'm experimenting along these lines:
let bluetooth = peripherals.BT;
let connector = BleConnector::new(&init, bluetooth);
let hci = HciConnector::new(connector, esp_wifi::current_millis);
let mut ble = Ble::new(&hci);
ble.cmd_set_le_scan_rsp_data(
// todo temp
create_advertising_data(&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[Uuid::Uuid16(0x1809)]),
// AdStructure::CompleteLocalName(examples_util::SOC_NAME),
AdStructure::CompleteLocalName("TEST"),
]).unwrap()
).unwrap();
println!("BLE init: {:?}", ble.init());
esp-wifi recently migrated to embassy-net
, which is awesome! Would there be any interest in getting bleps
to use async?
Hello, I'm trying to make a keyboard using esp32 + bleps. I found that it is quite hard to create a gatt service using bleps.
What I'm trying to create is like https://github.com/embassy-rs/nrf-softdevice/blob/master/examples/src/bin/ble_keyboard_peripheral_builder.rs#L289
The following is my code:
let mut hid_info_fn = |_offset: usize, data: &mut [u8]| {
data[0..4].copy_from_slice(&[0x1u8, 0x1u8, 0x00u8, 0x03u8]);
4
};
let mut hid_desc_fn = |_offset: usize, data: &mut [u8]| {
data[0..HID_REPORT_DESCRIPTOR.len()].copy_from_slice(HID_REPORT_DESCRIPTOR);
HID_REPORT_DESCRIPTOR.len()
};
let mut hid_report_fn = |_offset: usize, data: &mut [u8]| {
data[0..8].copy_from_slice(&[0, 0, 0x04, 0,0,0,0,0]);
8
};
let keyboard_desc_value = [1,1u8];
let mut kb_report = [0; 8];
gatt!([service {
uuid: "1812",
characteristics: [
characteristic {
uuid: "2A4A",
read: hid_info_fn,
},
characteristic {
uuid: "2A4B",
read: hid_desc_fn,
},
characteristic {
uuid: "2A4D",
notify: true,
read: hid_report_fn,
descriptors: [
descriptor {
uuid: "2908",
value: keyboard_desc_value,
},
],
},
],
},]);
I think I write the arguments right but the macro just doesn't compile. There is not any info from Rust compiler, even using RUSTFLAGS="-Zmacro-backtrace"
:
$ RUSTFLAGS="-Zmacro-backtrace" cargo build
error: Unexpected
--> src\lib.rs:593:5
|
593 | / gatt!([service {
594 | | uuid: "1812",
595 | | characteristics: [
596 | | characteristic {
... |
615 | | ],
616 | | },]);
| | ^ in this macro invocation
| |________|
|
|
::: C:\Users\haobo\.cargo\git\checkouts\bleps-c5f04b27afb89012\9371d7d\bleps-macros\src\lib.rs:31:1
|
31 | pub fn gatt(input: TokenStream) -> TokenStream {
| ---------------------------------------------- in this expansion of `gatt!`
There is only an Unexpected
error, I cannot get any info about what's unexpected and how to fix it. Any ideas? Thanks!
First of all, thank you so much for your great work!
I'm running bleps with embassy on an ESP32-C3 and was wondering if it's possible to open multiple BLE connections in parallel. Do you have any experience of this?
The chip should support it, but I'm too unfamiliar with Bluetooth to know at what level the parallelism should take place. Would it be enough to give multiple Ble
instances access to the same embedded_io_async::{Read, Write}
BleConnector
instances?
this.dataNotifyCharacteristic.startNotifications()
this.dataNotifyCharacteristic.addEventListener('characteristicvaluechanged', (event) => {
const value = event.target.value
const payload = Buffer.from(value.buffer)
...
is GATT characteristic value changing supported?
ble.cmd_set_le_advertising_data(create_advertising_data(&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[
Uuid::Uuid16(0x1809)
]),
AdStructure::CompleteLocalName("BLE_TO_ISOTP"),
])).unwrap();
am I setting something wrong here?
I have no problems with writing attribute from received raw data in write_function
but I haven't know how return non-static &[u8]
from a read_function
.
It would fix this error:
the trait bound `bleps::Error: Format` is not satisfied
the following other types implement trait `Format`:
&T
&mut T
()
(T0, T1)
(T0, T1, T2)
(T0, T1, T2, T3)
(T0, T1, T2, T3, T4)
(T0, T1, T2, T3, T4, T5)
and 191 others
from this code:
defmt::unwrap!(ble.init().await);
Would you be interested in generalizing AttData
to allow errors and futures? The errors would involve changing AttData
to be like
trait AttData {
fn read(&mut self, offset: usize, data: &mut [u8]) -> Result<usize, AttErrorCode>;
fn write(&mut self, offset: usize, data: &[u8]) -> Result<(), AttErrorCode>;
}
The async version might have to involve another trait, like bleps::async_attribute::Attribute
or something.
You could still of course implement AttData
for FnMut(usize, &[u8])
and similar, so it probably wouldn't cause much breakage.
I have a very strange issue. On Linux, when I listen for notification on a characteristic, notifications works OK, but as soon as I write to any characteristics (even in a different service) they stop. Re-asking for notifications make them works again until the next write.
I've used both the btleplug
library and the official bluer
library.
If I use the ble_server
example from esp32-nimble, it works as expected.
If I use the nRF Connect
app on android as the client, it works as expected.
There is some strange interaction between the Linux Bluetooth stack and bleps
.
Fix tests
Tests in bleps and bleps-macros broke ... should get fixed
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.