Comments (13)
The following is the trace log, it seems the bond info has been saved correctly, but the board is disconnected everytime after saving system attributes:
INFO Hello NRF BLE!
└─ rmk_nrf52840::____embassy_main_task::{async_fn#0} @ src\main.rs:32
INFO softdevice RAM: 31496 bytes
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:138
WARN You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to 20007b08
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:151
INFO Loaded bond info: SystemAttribute { length: 13, data: [2, 0, 2, 0, 26, 0, 2, 0, 1, 0, 38, 0, 2, 0, 1, 0, 2, 215, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255] }, loaded length: Ok(())
└─ rmk::initialize_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\Projects\Rust\rmk\rmk\src\lib.rs:264
INFO BLE Advertising
└─ rmk::initialize_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\Projects\Rust\rmk\rmk\src\lib.rs:272
TRACE ble evt 16
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
DEBUG conn_params conn_sup_timeout=200 max_conn_interval=12 min_conn_interval=12 slave_latency=0
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:125
DEBUG connected role=Peripheral peer_addr=Public:[ab, e2, d4, 7d, b2, 7c]
└─ nrf_softdevice::ble::peripheral::advertise_inner::{async_fn#0}::{closure#1} @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:125
TRACE conn 0: connected
└─ nrf_softdevice::ble::connection::{impl#9}::new::{closure#0} @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
INFO Starting GATT server
└─ rmk::initialize_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\Projects\Rust\rmk\rmk\src\lib.rs:283
TRACE ble evt 36
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
DEBUG on_data_length_update conn_handle=3 max_rx_octets=251 max_rx_time_us=2120 max_tx_octets=251 max_tx_time_us=2120
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:125
TRACE ble evt 35
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
TRACE on_data_length_update_request conn_handle=3 max_rx_octets=251 max_rx_time_us=17040 max_tx_octets=251 max_tx_time_us=17040
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
TRACE ble evt 36
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
DEBUG on_data_length_update conn_handle=3 max_rx_octets=251 max_rx_time_us=2120 max_tx_octets=251 max_tx_time_us=2120
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:125
TRACE ble evt 20
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
TRACE ble evt sec info request: enc_info=1, id_info=0, sign_info=0, master_id: { ediv: 9d18, rand: [124, 40, 24, 8, 84, 105, 188, 75] }, peer_addr: { addr: [171, 226, 212, 125, 178, 124], addr_id_peer: 0, addr_type: 0 }
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
INFO Getting bond for: id: MasterId { ediv: 40216, rand: [124, 40, 24, 8, 84, 105, 188, 75] }
└─ rmk::ble::bonder::{impl#4}::get_key @ E:\Projects\Rust\rmk\rmk\src\ble\bonder.rs:140
TRACE ble evt 17
└─ nrf_softdevice::ble::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
TRACE on_disconnected conn_handle=3
└─ nrf_softdevice::ble::gap::on_evt @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
INFO Saving system attributes for: Public:[ab, e2, d4, 7d, b2, 7c]
└─ rmk::ble::bonder::{impl#4}::save_sys_attrs @ E:\Projects\Rust\rmk\rmk\src\ble\bonder.rs:149
TRACE conn 0: disconnected
└─ nrf_softdevice::ble::connection::{impl#6}::on_disconnected @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\1a017b4\nrf-softdevice\src\fmt.rs:112
I also tried to use Nrf-Connected mobile app to test the program, the app always shows the following log:
Scanner On
Device Scanned
Device Appearance switched from Generic to HID
Failed to Connect: Peer removed pairing information
from nrf-softdevice.
That means that your central device is trying to connect using keys that don't match the keys you're providing as part of the pairing procedure. You need to forget the device on the central and then re-pair to generate new keys. You then need to save those keys after receiving the on_bonded
callback. save_sys_attrs
just stores some state information such as which characteristics the central has requested notifications so that the connection state can be restored on reconnect. It will only be called when the connection is disconnected.
from nrf-softdevice.
@alexmoon Thanks for the reply! I just made my device reconnect to host by saving keys in on_bonded
. Reconnection is good, but there is another problem: after reconnection, when I try to send HID report to host, gatt_server::notify_value
returns NotifyValueError(Raw(BleGattsSysAttrMissing))
.
This error only occurs after reconnection. If I delete the device from host, connect the device as a new device, all the functions work well, no NotifyValueError
. Do you have any idea of solving it?
from nrf-softdevice.
In your on_connected
handler you need to call gatt_server::set_sys_attrs()
with the data you saved for that peer in your save_sys_attrs()
impl.
from nrf-softdevice.
@alexmoon I cannot find any on_connected
handler in the library. Do you mean server_callback
of gatt_server::run
here?
match peripheral::advertise_pairable(sd, adv, &config, bonder).await {
Ok(conn) => {
// Run the GATT server on the connection. This returns when the connection gets disconnected.
let ble_fut = gatt_server::run(&conn, &ble_server, server_callback);
}
Err(e) => {
error!("Advertise error: {}", e)
}
}
from nrf-softdevice.
Sorry, on_connected
is from my firmware. Basically you just need to call set_sys_attrs
as soon as you're connected (i.e. in the Ok
branch of your match
expression, before you call gatt_server::run
). Note that if your peer is using private resolvable addresses, you will need to use the saved identity key to resolve the address in order to identify the correct saved sys_attrs to use.
from nrf-softdevice.
Thanks a lot! I've got my project work.
Pairing-bonding and storing keys are quite common in BLE apps. NRF has one already: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Flib_peer_manager.html
Is it possible to have a built-in peer manager in nrf-softdevice
?
from nrf-softdevice.
That's outside the scope of nrf-softdevice
, which is just trying to provide a safe wrapper around the softdevice library. However, it would be quite useful as a third party crate.
from nrf-softdevice.
@HaoboGu have you had to go through address resolution as well?
The Peer manager in the SDK is quite a complex module, does it really boils down to only a handful of write/fetch from the flash?
Would you be ok with sharing your solution?
from nrf-softdevice.
The Peer manager in the SDK is quite a complex module, does it really boils down to only a handful of write/fetch from the flash?
NRF's peer manager is quite more complex, I just have a simplest version of it. You can checkout here: https://github.com/HaoboGu/rmk/blob/main/rmk/src/ble/bonder.rs
from nrf-softdevice.
The Peer manager in the SDK is quite a complex module, does it really boils down to only a handful of write/fetch from the flash?
NRF's peer manager is quite more complex, I just have a simplest version of it. You can checkout here: https://github.com/HaoboGu/rmk/blob/main/rmk/src/ble/bonder.rs
Nice work, impressively simple, thanks for sharing!
I wonder what feature does the SDK Peer manager provide that your approach doesn't?
To me it seems to cover all the needs for bonding multiple devices (for a BLE peripheral)...
from nrf-softdevice.
I wonder what feature does the SDK Peer manager provide that your approach doesn't?
AFAIK, random device addresses is not supported currently.
from nrf-softdevice.
I just found I didn't really solve the problem. I called load_sys_attrs
after connected:
match peripheral::advertise_pairable(sd, adv, &config, bonder).await {
Ok(conn) => {
info!("Connected to BLE");
bonder.load_sys_attrs(&conn);
let ble_fut = gatt_server::run(&conn, &ble_server, server_callback);
}
Err(e) => {
error!("Advertise error: {}", e)
}
}
where my load_sys_attrs
is:
fn load_sys_attrs(&self, conn: &Connection) {
let addr = conn.peer_address();
info!("Loading system attributes for {}", addr);
let bond_info = self.bond_info.borrow();
let sys_attr = bond_info
.iter()
.filter(|(_, b)| b.sys_attr.length != 0 && b.removed == false)
.find(|(_, b)| b.peer.peer_id.is_match(addr))
.map(|(_, b)| &b.sys_attr.data[0..b.sys_attr.length]);
info!("call set_sys_attrs in load_sys_attrs: {}, {}", sys_attr, sys_attr.unwrap().len());
if let Err(err) = set_sys_attrs(conn, sys_attr) {
warn!("SecurityHandler failed to set sys attrs: {:?}", err);
}
}
The first connection and reconnection are both good, but once I tried to send HID report, the gatt_server::notify_value(self.conn, self.handle, report)
returns a Raw(InvalidState)
error. Here is the full log of the first and second connection:
first(all good):
INFO start!
└─ rmk_nrf52840::____embassy_main_task::{async_fn#0} @ src\main.rs:11
INFO Enabling ext hfosc...
└─ rmk_nrf52840::____embassy_main_task::{async_fn#0} @ src\main.rs:11
INFO softdevice RAM: 29456 bytes
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\cdee83c\nrf-softdevice\src\fmt.rs:138
WARN You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to 20007310
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\cdee83c\nrf-softdevice\src\fmt.rs:151
INFO Loaded saved bond info: 1
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:199
INFO USB suspended, BLE Advertising
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:243
INFO Connected to BLE
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:249
INFO Loading system attributes for Public:[ab, e2, d4, 7d, b2, 7c]
└─ rmk::ble::nrf::bonder::{impl#4}::load_sys_attrs @ E:\rmk\rmk\src\ble\nrf\bonder.rs:210
INFO call set_sys_attrs in load_sys_attrs: Some([13, 0, 2, 0, 0, 0, 26, 0, 2, 0, 0, 0, 38, 0, 2, 0, 0, 0, 45, 0, 2, 0, 0, 0, 49, 0, 2, 0, 0, 0, 53, 0, 2, 0, 0, 0, 57, 0, 2, 0, 0, 0, 78, 188]), 44
└─ rmk::ble::nrf::bonder::{impl#4}::load_sys_attrs @ E:\rmk\rmk\src\ble\nrf\bonder.rs:220
INFO Starting GATT server 200 ms later
└─ rmk::ble::nrf::run_ble_keyboard::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:333
INFO on_security_update, new security mode: JustWorks
└─ rmk::ble::nrf::bonder::{impl#4}::on_security_update @ E:\rmk\rmk\src\ble\nrf\bonder.rs:94
DEBUG On bonded: storing bond for MasterId { ediv: 25868, rand: [130, 88, 153, 22, 65, 23, 20, 21] }
└─ rmk::ble::nrf::bonder::{impl#4}::on_bonded @ E:\rmk\rmk\src\ble\nrf\bonder.rs:105
INFO ON BOND: get sys attr: [13, 0, 2, 0, 0, 0, 26, 0, 2, 0, 0, 0, 38, 0, 2, 0, 0, 0, 45, 0, 2, 0, 0, 0, 49, 0, 2, 0, 0, 0, 53, 0, 2, 0, 0, 0, 57, 0, 2, 0, 0, 0, 78, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], size:44
└─ rmk::ble::nrf::bonder::{impl#4}::on_bonded @ E:\rmk\rmk\src\ble\nrf\bonder.rs:130
DEBUG Sent bond info to flash channel
└─ rmk::ble::nrf::bonder::{impl#4}::on_bonded @ E:\rmk\rmk\src\ble\nrf\bonder.rs:152
INFO Saving bond info: BondInfo(BondInfo { slot_num: 0, peer: Peer { master_id: MasterId { ediv: 25868, rand: [130, 88, 153, 22, 65, 23, 20, 21] }, key: EncryptionInfo { ltk: [2, 53, 199, 84, 1, 229, 28, 117, 196, 197, 66, 170, 76, 165, 44, 252], flags: 64 }, peer_id: IdentityKey { irk: IdentityResolutionKey { irk: [13, 235, 235, 74, 4, 237, 34, 11, 38, 15, 13, 77, 96, 179, 252, 154] }, addr: Public:[ab, e2, d4, 7d, b2, 7c] } }, sys_attr: SystemAttribute { length: 44, data: [13, 0, 2, 0, 0, 0, 26, 0, 2, 0, 0, 0, 38, 0, 2, 0, 0, 0, 45, 0, 2, 0, 0, 0, 49, 0, 2, 0, 0, 0, 53, 0, 2, 0, 0, 0, 57, 0, 2, 0, 0, 0, 78, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, removed: false })
└─ rmk::storage::{impl#2}::run::{async_fn#0} @ E:\rmk\rmk\src\storage.rs:420
INFO HID input keyboard cccd: [1, 0]
└─ rmk::ble::nrf::hid_service::{impl#0}::on_write @ E:\rmk\rmk\src\ble\nrf\hid_service.rs:201
INFO HID input media keys: [1, 0]
└─ rmk::ble::nrf::hid_service::{impl#0}::on_write @ E:\rmk\rmk\src\ble\nrf\hid_service.rs:211
INFO HID input via keys: [1, 0]
└─ rmk::ble::nrf::hid_service::{impl#0}::on_write @ E:\rmk\rmk\src\ble\nrf\hid_service.rs:209
INFO HID output keyboard: [0]
└─ rmk::ble::nrf::hid_service::{impl#0}::on_write @ E:\rmk\rmk\src\ble\nrf\hid_service.rs:207
DEBUG Sending keyboard report: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0]
└─ rmk::keyboard::{impl#0}::send_keyboard_report::{async_fn#0} @ E:\rmk\rmk\src\keyboard.rs:135
DEBUG Sending keyboard report: [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
└─ rmk::keyboard::{impl#0}::send_keyboard_report::{async_fn#0} @ E:\rmk\rmk\src\keyboard.rs:135
second(reconnection, notify value error):
INFO start!
└─ rmk_nrf52840::____embassy_main_task::{async_fn#0} @ src\main.rs:11
INFO Enabling ext hfosc...
└─ rmk_nrf52840::____embassy_main_task::{async_fn#0} @ src\main.rs:11
INFO softdevice RAM: 29456 bytes
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\cdee83c\nrf-softdevice\src\fmt.rs:138
WARN You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to 20007310
└─ nrf_softdevice::softdevice::{impl#0}::enable @ C:\Users\haobo\.cargo\git\checkouts\nrf-softdevice-03ef4aef10e777e4\cdee83c\nrf-softdevice\src\fmt.rs:151
INFO Loaded saved bond info: 1
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:199
INFO USB suspended, BLE Advertising
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:243
INFO Connected to BLE
└─ rmk::ble::nrf::initialize_nrf_ble_keyboard_with_config_and_run::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:249
INFO Loading system attributes for Public:[ab, e2, d4, 7d, b2, 7c]
└─ rmk::ble::nrf::bonder::{impl#4}::load_sys_attrs @ E:\rmk\rmk\src\ble\nrf\bonder.rs:210
INFO call set_sys_attrs in load_sys_attrs: Some([13, 0, 2, 0, 0, 0, 26, 0, 2, 0, 0, 0, 38, 0, 2, 0, 0, 0, 45, 0, 2, 0, 0, 0, 49, 0, 2, 0, 0, 0, 53, 0, 2, 0, 0, 0, 57, 0, 2, 0, 0, 0, 78, 188]), 44
└─ rmk::ble::nrf::bonder::{impl#4}::load_sys_attrs @ E:\rmk\rmk\src\ble\nrf\bonder.rs:220
INFO Starting GATT server 200 ms later
└─ rmk::ble::nrf::run_ble_keyboard::{async_fn#0} @ E:\rmk\rmk\src\ble\nrf.rs:333
DEBUG Getting bond for MasterId { ediv: 25868, rand: [130, 88, 153, 22, 65, 23, 20, 21] }
└─ rmk::ble::nrf::bonder::{impl#4}::get_key @ E:\rmk\rmk\src\ble\nrf\bonder.rs:165
INFO on_security_update, new security mode: JustWorks
└─ rmk::ble::nrf::bonder::{impl#4}::on_security_update @ E:\rmk\rmk\src\ble\nrf\bonder.rs:94
DEBUG Sending keyboard report: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0]
└─ rmk::keyboard::{impl#0}::send_keyboard_report::{async_fn#0} @ E:\rmk\rmk\src\keyboard.rs:135
ERROR Send ble report error: Raw(InvalidState)
└─ rmk::ble::nrf::server::{impl#1}::write::{async_fn#0}::{closure#0} @ E:\rmk\rmk\src\ble\nrf\server.rs:44
And same as before, if I remove bonder.load_sys_attrs(&conn);
, then I get Raw(BleGattsSysAttrMissing)
error.
@alexmoon Do you have any ideas? I'll much appreciate if you can help!
from nrf-softdevice.
Related Issues (20)
- Connecting with 2M PHY HOT 4
- L2CAP Channel API Design Flaws HOT 1
- Switch examples to use default `gatts_attr_tab_size` ? HOT 1
- Add descriptor to a characteristic HOT 2
- NRF52832/S132 Freezes Upon Connection HOT 3
- There is currently no way to disable the SoftDevice HOT 2
- Softdevice peripheral clash with RNG peripheral HOT 3
- Implement `NorFlash` for `Flash` HOT 2
- Debugging HOT 1
- Softdevice.run_with_callback never calls the callback HOT 1
- Improve defmt trace HOT 1
- Could not execute process probe-run --chip nRF52840_xxAA HOT 3
- Security connection HOT 1
- Allow to open/close a BLE pairing&bonding window HOT 4
- Flash Capacity Definition Discrepancy for nRF52832 and nRF52833 Chips HOT 3
- Custom GATT service with u64 characteristic causes the application to stuck/crash in build-release mode HOT 6
- Bindgen dependency requirement?
- `InvalidState` after re-connecting HOT 8
- S340 SoftDevice support (for ANT) HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nrf-softdevice.