From 7ddeba17c30a27217522f09b4b2f9de53ebd41b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Pol=C3=A1=C4=8Dek?= Date: Thu, 18 Jan 2024 20:10:59 +0100 Subject: [PATCH 1/2] Add a function to find a BLE peripheral --- Cargo.toml | 2 ++ src/errors_internal.rs | 4 ++++ src/utils_internal.rs | 54 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bd7c924..22d12b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,3 +43,5 @@ specta = { git = "https://github.com/ajmcquilkin/specta.git", version = ">= 1.0. serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", optional = true } thiserror = "1.0.48" +uuid = "1.6.1" +btleplug = "0.11.5" diff --git a/src/errors_internal.rs b/src/errors_internal.rs index 024ccc1..bc293fd 100644 --- a/src/errors_internal.rs +++ b/src/errors_internal.rs @@ -88,6 +88,10 @@ pub enum InternalChannelError { IncomingStreamDataWriteError(#[from] tokio::sync::mpsc::error::SendError), } +#[derive(Error, Debug)] +#[error("Bluetooth low energy connection error")] +pub struct BleConnectionError(); + mod test { #[allow(dead_code)] fn is_send() {} diff --git a/src/utils_internal.rs b/src/utils_internal.rs index bf2ed66..14fa531 100644 --- a/src/utils_internal.rs +++ b/src/utils_internal.rs @@ -1,5 +1,10 @@ +use crate::errors_internal::{BleConnectionError, Error}; +use btleplug::api::{Central, Manager as _, Peripheral as _, ScanFilter}; +use btleplug::platform::{Adapter, Manager, Peripheral}; +use log::error; use std::time::Duration; use std::time::UNIX_EPOCH; +use uuid::Uuid; use rand::{distributions::Standard, prelude::Distribution, Rng}; use tokio_serial::{available_ports, SerialPort, SerialStream}; @@ -7,7 +12,6 @@ use tokio_serial::{available_ports, SerialPort, SerialStream}; use crate::connections::wrappers::encoded_data::{ EncodedToRadioPacket, EncodedToRadioPacketWithHeader, }; -use crate::errors_internal::Error; // Constants declarations @@ -191,6 +195,54 @@ pub async fn build_tcp_stream(address: String) -> Result Result, btleplug::Error> { + adapter + .start_scan(ScanFilter { + services: vec![MSH_SERVICE], + }) + .await?; + adapter.peripherals().await +} + +/// Finds a BLE radio matching a given name and running meshtastic. +/// It searches for the 'MSH_SERVICE' running on the device. +async fn find_ble_radio(name: String) -> Result { + //TODO: support searching both by a name and by a MAC address + let scan_error_fn = |e: btleplug::Error| Error::StreamBuildError { + source: Box::new(e), + description: "Failed to scan for BLE devices".to_owned(), + }; + let manager = Manager::new().await.map_err(scan_error_fn)?; + let adapters = manager.adapters().await.map_err(scan_error_fn)?; + + for adapter in &adapters { + let peripherals = scan_peripherals(&adapter).await; + match peripherals { + Err(e) => { + error!("Error while scanning for meshtastic peripherals: {e:?}"); + // We continue, as there can be another adapter that can work + continue; + } + Ok(peripherals) => { + for peripheral in peripherals { + if let Ok(Some(peripheral_properties)) = peripheral.properties().await { + if peripheral_properties.local_name == Some(name.clone()) { + return Ok(peripheral); + } + } + } + } + } + } + Err(Error::StreamBuildError { + source: Box::new(BleConnectionError()), + description: format!("Failed to find {name}, or meshtastic is not running on the device") + + ", or it's already connected.", + }) +} + /// A helper method to generate random numbers using the `rand` crate. /// /// This method is intended to be used to generate random id values. This method From 6841a649d8ab9dfa33bfe85064580a7d7de552f0 Mon Sep 17 00:00:00 2001 From: Adam McQuilkin <46639306+ajmcquilkin@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:42:34 -0800 Subject: [PATCH 2/2] Added required Ubuntu dependencies to testing flow --- .github/workflows/testing.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index f5c957f..617e638 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -29,6 +29,12 @@ jobs: - name: Install Rust stable uses: dtolnay/rust-toolchain@stable + - name: Install dependencies (Ubuntu only) + if: matrix.platform == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y libdbus-1-dev pkg-config + - name: Run test suite working-directory: ./ run: cargo test