deviceplug/btleplug

Android - Peripheral Connect Error

Closed this issue · 2 comments

Hi,

I'm using a Tauri Plugin (v2/beta) to handle Bluetooth operations. I can successfully request Bluetooth permissions and scan for devices. However, the application crashes when I try to connect to a device.

Tauri connect Command:

#[tauri::command]
pub(crate) async fn connect<R: Runtime>(
    _app: AppHandle<R>,
    _printer_store: State<'_, Arc<Mutex<PrinterStore>>>,
    time: u64,
    device: Device,
) -> Result<()> {
    let printer_store = Arc::clone(&_printer_store);
    let conn = device.conn;

    info!("Connecting to device: {:?}", device);

    match conn {
        ConnectionType::BLE => {
            #[cfg(feature = "ble")]
            {
                #[cfg(target_os = "android")]
                {
                    _app.escpos()
                        .btleplug_context_spawn(async move {
                            let mut printer_store_android = printer_store.lock().await;
                            let adapter = FinderBLE::get_adapter()
                                .await
                                .map_err(|_| Error::BLEAdapterNotFound)?;
                            let scanned_devices =
                                FinderBLE::scan(&adapter, vec![], Duration::from_secs(time as u64))
                                    .await
                                    .map_err(|_| Error::BLEScan)?;

                            if let Some(device_found) = scanned_devices
                                .into_iter()
                                .find(|d| d.address().to_string() == device.address)
                            {
                                info!("Connecting to device: {:?}", device_found);
                                let device_peripheral = FinderBLE::connect(device_found)
                                    .await
                                    .map_err(|_| Error::BLEConnect(device.address))?;
                                info!("Connected to device: {:?}", device_peripheral);
                                let mut printer = PrinterESCPOSBLE::new(device_peripheral)
                                    .await
                                    .map_err(|_| Error::BLEPrinterInstance)?;
                                info!("Printer instance created");
                                printer_store_android.printer = Printer::BLE(printer);
                                printer_store_android.connected = true;
                            }

                            Ok::<(), Error>(())
                        })
                        .await
                        .map_err(|_err| Error::BLEbtleplugContextSpawn(_err.to_string()))?;
                }
            }
            #[cfg(not(feature = "ble"))]
            {
                return Err(Error::BLEFeatureNotEnabled);
            }
        }
        ConnectionType::USB => {
            #[cfg(feature = "usb")]
            {
                todo!()
            }
            #[cfg(not(feature = "usb"))]
            {
                return Err(Error::USBFeatureNotEnabled);
            }
        }
    }
    Ok(())
}

Connect fn (Wrapped on FinderBLE) -> FinderBLE::connect(peripheral).await

  pub async fn connect(
            peripheral: btleplug::platform::Peripheral,
        ) -> Result<btleplug::platform::Peripheral, Box<dyn Error>> {
            log::info!(
                "eco_print::FinderBLE::connect() -> start with peripheral: {:?}",
                peripheral
            );
            let connected = peripheral.is_connected().await?;

            log::info!(
                "eco_print::FinderBLE::connect() -> is_connected: {:?}",
                connected
            );
            if !connected {
                log::info!(
                    "Connecting to {:?}",
                    peripheral.properties().await?.unwrap().local_name
                );
                peripheral.connect().await?;
            }
            Ok(peripheral)
        }

Logcat:

08-13 16:37:28.644 27245 27300 E GPUAUX  : [AUX]GuiExtAuxCheckAuxPath:667: Null anb
08-13 16:37:28.645 27245 27300 E gralloc4: Empty SMPTE 2094-40 data
08-13 16:37:33.265 27245 27397 I TauriPluginEscpos: eco_print::escpos::finder::ble: eco_print::FinderBLE::scan() -> peripherals found: [JObject { internal: 0x390e, lifetime: PhantomData<&()> }, JObject { internal: 0x2b0a, lifetime: PhantomData<&()> }, JObject { internal: 0x4386, lifetime: PhantomData<&()> }, JObject { internal: 0x2e8a, lifetime: PhantomData<&()> }, JObject { internal: 0x352a, lifetime: PhantomData<&()> }, JObject { internal: 0x3552, lifetime: PhantomData<&()> }, JObject { internal: 0x38ea, lifetime: PhantomData<&()> }]
08-13 16:37:33.266 27245 27397 I TauriPluginEscpos: tauri_plugin_escpos::commands: Connecting to device: JObject { internal: 0x38ea, lifetime: PhantomData<&()> }
08-13 16:37:33.266 27245 27397 I TauriPluginEscpos: eco_print::escpos::finder::ble: eco_print::FinderBLE::connect() -> start with peripheral: JObject { internal: 0x38ea, lifetime: PhantomData<&()> }
08-13 16:37:33.271 27245 27397 I TauriPluginEscpos: eco_print::escpos::finder::ble: eco_print::FinderBLE::connect() -> is_connected: false
08-13 16:37:33.271 27245 27397 I TauriPluginEscpos: eco_print::escpos::finder::ble: Connecting to Some("KP-1020")
08-13 16:37:33.287 27245 27323 I RustStdoutStderr: thread 'TauriPluginEscpos-2' panicked at C:\Users\gabri\.cargo\registry\src\index.crates.io-6f17d22bba15001f\jni-utils-0.1.1\rust\future.rs:42:98:
08-13 16:37:33.287 27245 27323 I RustStdoutStderr: called `Option::unwrap()` on a `None` value
08-13 16:37:33.287 27245 27323 I RustStdoutStderr: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
08-13 16:37:33.291 27245 27437 E TauriPluginEscpos: tauri_plugin_escpos::error: Error btleplug context spawn: task 31 panicked
08-13 16:37:33.308 27245 27245 W Tauri/Console: File: http://tauri.localhost/node_modules/.vite/deps/vue.js?v=75e191f8 - Line 1528 - Msg: [Vue warn]: Unhandled error during execution of native event handler
08-13 16:37:33.308 27245 27245 W Tauri/Console:   at <App>
08-13 16:37:33.310 27245 27245 E Tauri/Console: File: http://tauri.localhost/ - Line 0 - Msg: Uncaught (in promise) Error btleplug context spawn: task 31 panicked

The crash seems to be related to this code segment where the panic occurs:
File: 08-13 16:37:33.287 27245 27323 I RustStdoutStderr: thread 'TauriPluginEscpos-2' panicked at C:\Users\gabri.cargo\registry\src\index.crates.io-6f17d22bba15001f\jni-utils-0.1.1\rust\future.rs:42:98:

    pub fn from_env(env: &'b JNIEnv<'a>, obj: JObject<'a>) -> Result<Self> {
        let poll = env.get_method_id(
            JClass::from(crate::classcache::get_class("io/github/gedgygedgy/rust/future/Future").unwrap().as_obj()),
            "poll",
            "(Lio/github/gedgygedgy/rust/task/Waker;)Lio/github/gedgygedgy/rust/task/PollResult;",
        )?;
        Ok(Self {
            internal: obj,
            poll,
            env,
        })
    }

https://github.com/lnxdxtf/tauri-plugin-escpos
https://github.com/lnxdxtf/eco_print

qdot commented

I'm not sure how much help we're gonna be here. Binding to the JNI is a nightmare as is, and I have no idea what context the tauri plugin brings things up in, as it's not our project and I have no tauri experience. You might try filing this on the tauri plugin instead of here.

Hi @lnxdxtf! I have the same issue but for my Flutter app. Would it be possible to know how the issue was resolved? Thanks a lot!
Just in case, here is the similar error I get :

I/flutter ( 6877): A panic occurred in Rust.
I/flutter ( 6877): panicked at /home/gabriel_bergeron/.cargo/registry/src/index.crates.io-6f17d22bba15001f/jni-utils-0.1.1/rust/future.rs:42:98:
I/flutter ( 6877): called `Option::unwrap()` on a `None` value