Git Product home page Git Product logo

Comments (13)

HaoboGu avatar HaoboGu commented on June 26, 2024

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.

alexmoon avatar alexmoon commented on June 26, 2024

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.

HaoboGu avatar HaoboGu commented on June 26, 2024

@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.

alexmoon avatar alexmoon commented on June 26, 2024

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.

HaoboGu avatar HaoboGu commented on June 26, 2024

@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.

alexmoon avatar alexmoon commented on June 26, 2024

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.

HaoboGu avatar HaoboGu commented on June 26, 2024

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.

alexmoon avatar alexmoon commented on June 26, 2024

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.

igiona avatar igiona commented on June 26, 2024

@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.

HaoboGu avatar HaoboGu commented on June 26, 2024

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.

igiona avatar igiona commented on June 26, 2024

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.

HaoboGu avatar HaoboGu commented on June 26, 2024

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.

HaoboGu avatar HaoboGu commented on June 26, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.