Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conn.disconnect #277

Closed
Makuo12 opened this issue Jan 28, 2025 · 7 comments · Fixed by #279
Closed

Conn.disconnect #277

Makuo12 opened this issue Jan 28, 2025 · 7 comments · Fixed by #279

Comments

@Makuo12
Copy link

Makuo12 commented Jan 28, 2025

I wanted to ask if there is a specific way to use conn.disconnect.
Using the ble_bas_peripheral.rs example I created like a timeout async function

async fn timeout(conn: &Connection<'_>) {
    loop {
        Timer::after_secs(5).await;
        println!("running timeout");
        conn.disconnect();
    }
}

The would run along side gatt_events_task

let a = gatt_events_task(
                            &server, &conn, aes, connection_success,
                        read_content, &mut chatacter);
                        let t = timeout(&conn);
let t = timeout(&conn);
match select(a, t).await {}              

I realized that when the timeout gets called sometimes the connection disconnects properly. However sometimes it disconnects and stops the ble from advertising again.

@lulf
Copy link
Member

lulf commented Jan 29, 2025

Calling disconnect() will not cause it to disconnect immediately, but cause the ble_task to perform a disconnect on the controller.

Your timeout function will never finish though due to the loop though, it should be sufficient to call disconnect() only once.

As for advertising not starting, maybe enable some more logging to see if it's failing somewhere early.

@Makuo12
Copy link
Author

Makuo12 commented Jan 29, 2025

So from the logs:
I found out that the ble host is no more found.
When disconnect gets called from GattEvent::Read

                    Ok(Some(GattEvent::Read(event))) => {
                        if event.handle() == level.handle {
                            let value = server.get(&level);
                            info!("[gatt] Read Event to Level Characteristic: {:?}", value);
                        } else if event.handle() == status.handle {
                            let value = server.get(&status);
                            info!("[gatt] Read Event to Status Characteristic: {:?}", value);
                            let success;
                            {
                                let result = *connection_success.lock().await;
                                success = result;
                            }
                            if success {
                                info!("has read success");
                                handle_read_state(&mut status, server, read_content, aes).await;
                                {
                                    let mut read = read_content.lock().await;
                                    if read.state == ReadState::Done {
                                        read.state = ReadState::Price;
                                        *character = 'M';
                                        conn.disconnect();
                                        generic_delay(embassy_time::Delay).await;
                                    }
                                    info!("done 2");
                                }
                            } else {
                                info!("has not read success");
                                *character = 'T';
                                conn.disconnect();
                                generic_delay(embassy_time::Delay).await;
                                continue;
                            }
                        }
                    }

I notice that INFO - [gatt] disconnected: Err(Connection Terminated By Local Host) gets logged which is correct but after some seconds I get the error log BleHost(NotFound), which is called from ble_task

async fn ble_task<C: Controller>(mut runner: Runner<'_, C>) -> bool{
    loop {
        if let Err(e) = runner.run().await {
            let e = defmt::Debug2Format(&e);
            panic!("[ble_task] error: {:?}", e);
        }
    }
}

This error causes it not to start advertising again. I know I can just use a warn rather than a panic but I feel the panic is important because it stops you from using the ble when there is no BleHost anymore.

@lulf
Copy link
Member

lulf commented Jan 29, 2025

So from the logs: I found out that the ble host is no more found. When disconnect gets called from GattEvent::Read

                Ok(Some(GattEvent::Read(event))) => {
                    if event.handle() == level.handle {
                        let value = server.get(&level);
                        info!("[gatt] Read Event to Level Characteristic: {:?}", value);
                    } else if event.handle() == status.handle {
                        let value = server.get(&status);
                        info!("[gatt] Read Event to Status Characteristic: {:?}", value);
                        let success;
                        {
                            let result = *connection_success.lock().await;
                            success = result;
                        }
                        if success {
                            info!("has read success");
                            handle_read_state(&mut status, server, read_content, aes).await;
                            {
                                let mut read = read_content.lock().await;
                                if read.state == ReadState::Done {
                                    read.state = ReadState::Price;
                                    *character = 'M';
                                    conn.disconnect();
                                    generic_delay(embassy_time::Delay).await;
                                }
                                info!("done 2");
                            }
                        } else {
                            info!("has not read success");
                            *character = 'T';
                            conn.disconnect();
                            generic_delay(embassy_time::Delay).await;
                            continue;
                        }
                    }
                }

I notice that INFO - [gatt] disconnected: Err(Connection Terminated By Local Host) gets logged which is correct but after some seconds I get the error log BleHost(NotFound), which is called from ble_task

async fn ble_task<C: Controller>(mut runner: Runner<'_, C>) -> bool{
loop {
if let Err(e) = runner.run().await {
let e = defmt::Debug2Format(&e);
panic!("[ble_task] error: {:?}", e);
}
}
}

This error causes it not to start advertising again. I know I can just use a warn rather than a panic but I feel the panic is important because it stops you from using the ble when there is no BleHost anymore.

Yes, this is the reason advertising is not running, the runner must be running for it to perform operations to the controller. The host should generally not exit unless there is a condition it cannot recover from. So we should figure out why it is not recovering from this.

Could you share more of the logs? Are any of these two warnings printed? https://github.com/embassy-rs/trouble/blob/main/host/src/host.rs#L923-L929

Also, if you enable tracing, which of these gets printed? https://github.com/embassy-rs/trouble/blob/main/host/src/host.rs#L559-L570

@Makuo12
Copy link
Author

Makuo12 commented Jan 29, 2025

This is the error that gets printed [host] tx_fut exit.

[ble_task] BleHost(NotFound)

Backtrace:

0x400e0d85
0x400e0d85 - link::run::{{closure}}
    at /Users/mac/Documents/embed_rust/link/src/lib.rs:93
0x400d2369
0x400d2369 - embassy_executor::raw::SyncExecutor::poll::{{closure}}
    at /Users/mac/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.7.0/src/raw/mod.rs:430
0x400d43e3
0x400d43e3 - async_main::__xtensa_lx_rt_main
    at /Users/mac/Documents/embed_rust/link/src/bin/async_main.rs:16
0x400efafa
0x400efafa - Reset
    at /Users/mac/.cargo/registry/src/index.crates.io-6f17d22bba15001f/xtensa-lx-rt-0.18.0/src/lib.rs:82
0x400d9067
0x400d9067 - ESP32Reset
    at /Users/mac/.cargo/registry/src/index.crates.io-6f17d22bba15001f/esp-hal-0.23.1/src/soc/esp32/mod.rs:122

lulf added a commit that referenced this issue Jan 30, 2025
Connection handles may be marked as disconnected before the runner
has a chance to send responses to it. In that case, log and ignore error.

Fixes #277
@lulf
Copy link
Member

lulf commented Jan 30, 2025

Thanks, I think I know what happens now. Could you try #279 to see if it fixes the issue for you?

lulf added a commit that referenced this issue Jan 30, 2025
Connection handles may be marked as disconnected before the runner
has a chance to send responses to it. In that case, log and ignore error.

Fixes #277
@Makuo12
Copy link
Author

Makuo12 commented Jan 30, 2025

Thank you @lulf , I just tried #279 and it works well as expected. It disconnects and continues advertising with no panic errors

@lulf
Copy link
Member

lulf commented Jan 30, 2025

Thanks for testing @Makuo12 !

@lulf lulf closed this as completed in #279 Jan 30, 2025
lulf added a commit that referenced this issue Jan 30, 2025
Connection handles may be marked as disconnected before the runner
has a chance to send responses to it. In that case, log and ignore error.

Fixes #277
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants