Skip to content

Commit

Permalink
wip: bt
Browse files Browse the repository at this point in the history
  • Loading branch information
bagel897 committed Feb 7, 2024
1 parent 5039d31 commit 82f4b37
Show file tree
Hide file tree
Showing 13 changed files with 174 additions and 34 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rustdrop_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ hostname = "0.3.1"
console-subscriber = { version = "0.2.0", optional = true }
mdns-sd = "0.10.3"
num-bigint = "0.4.4"
anyhow = "1.0.79"
anyhow = { version = "1.0.79", features = ["backtrace"] }
flume = "0.11.0"
dirs = "5.0.1"
uuid = "1.7.0"
Expand Down
5 changes: 5 additions & 0 deletions rustdrop_core/src/core/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ pub enum RustdropError {
InvalidMessage(String),
#[error("Invalid endpoint id")]
InvalidEndpointId(),
#[error("Bluetooth Error")]
Bluetooth {
#[from]
source: bluer::Error,
},
}
10 changes: 6 additions & 4 deletions rustdrop_core/src/mediums/ble/common/scan.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use anyhow::Error;
use bluer::monitor::data_type::COMPLETE_LIST_16_BIT_SERVICE_CLASS_UUIDS;
use bluer::monitor::data_type::{
COMPLETE_LIST_16_BIT_SERVICE_CLASS_UUIDS, INCOMPLETE_LIST_128_BIT_SERVICE_CLASS_UUIDS,
};
use bluer::{
monitor::{
data_type::COMPLETE_LIST_128_BIT_SERVICE_CLASS_UUIDS, Monitor, MonitorEvent, Pattern,
Expand Down Expand Up @@ -84,9 +86,9 @@ pub(crate) async fn scan_le<U: UiHandle>(
let pattern = services
.into_iter()
.map(|uuid| Pattern {
data_type: COMPLETE_LIST_16_BIT_SERVICE_CLASS_UUIDS,
data_type: INCOMPLETE_LIST_128_BIT_SERVICE_CLASS_UUIDS,
start_position: 0x00,
content: uuid.as_u16().unwrap().to_be_bytes().to_vec(),
content: uuid.to_bytes_le().to_vec(),
})
.collect();
info!("Scanning for {:?}", pattern);
Expand All @@ -97,7 +99,7 @@ pub(crate) async fn scan_le<U: UiHandle>(
rssi_high_threshold: None,
rssi_low_timeout: None,
rssi_high_timeout: None,
rssi_sampling_period: Some(RssiSamplingPeriod::First),
rssi_sampling_period: Some(RssiSamplingPeriod::All),
patterns: Some(pattern),
..Default::default()
})
Expand Down
2 changes: 1 addition & 1 deletion rustdrop_core/src/mediums/ble/copresence/consts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bluer::Uuid;
use bytes::Bytes;
use uuid::uuid;
pub const SERVICE_ID: &str = "Fast Pair";
pub const SERVICE_ID: &str = "NearbySharing";
pub const SERVICE_UUID_RECIEVING: Uuid = uuid!("0000FEF300001000800000805F9B34FB"); // Device is
// receiving
pub const SERVICE_UUID_SHARING: Uuid = uuid!("0000fe2c-0000-1000-8000-00805f9b34fb"); // device is
Expand Down
20 changes: 19 additions & 1 deletion rustdrop_core/src/mediums/ble/copresence/discovery.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::error::Error;

use tokio::select;
use tracing::info;

use super::consts::{SERVICE_DATA, SERVICE_ID, SERVICE_UUID_RECIEVING, SERVICE_UUID_SHARING};
use crate::{
mediums::ble::common::{advertise::advertise, scan::scan_le},
Expand All @@ -25,6 +28,21 @@ pub(crate) async fn trigger_reciever<U: UiHandle>(
app: &mut Application<U>,
) -> Result<(), Box<dyn Error>> {
advertise(SERVICE_ID.into(), SERVICE_UUID_SHARING, SERVICE_DATA, app).await?;
let (devices, events) = scan_le(vec![SERVICE_UUID_RECIEVING], app).await?;
let (mut devices, mut events) = scan_le(vec![SERVICE_UUID_RECIEVING], app).await?;
app.spawn(
async move {
loop {
select! {
dev = devices.recv() => {
info!("{:?}", dev)
}
event = events.recv() => {
info!("{:?}", event)
}
}
}
},
"discovery_process",
);
Ok(())
}
4 changes: 3 additions & 1 deletion rustdrop_core/src/mediums/bt.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod advertise_recv;
mod advertise_recv;
mod consts;
mod manager;
pub(crate) use manager::Bluetooth;
35 changes: 27 additions & 8 deletions rustdrop_core/src/mediums/bt/advertise_recv.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use anyhow::Error;
use base64::{prelude::BASE64_URL_SAFE, Engine};
use bluer::rfcomm::Profile;
use bluer::rfcomm::{Profile, Role::Server};
use bytes::{BufMut, BytesMut};
use tokio_stream::StreamExt;
use tracing::info;

use crate::{
Expand All @@ -11,38 +12,56 @@ use crate::{
};

use super::consts::PCP;
fn get_name(config: &Config) -> String {
pub(super) fn get_name(config: &Config) -> String {
let mut result = BytesMut::new();
result.put_u8(PCP);
result.extend_from_slice(config.endpoint_id.as_bytes());
result.extend_from_slice(&SERVICE_ID);
result.put_u8(0x0);
result.extend_from_slice(&get_random(6));
let endpoint_info = get_endpoint_info(config);
result.put_u8(endpoint_info.len() as u8);
info!("{:?}", endpoint_info);
result.put_u8(endpoint_info.len().try_into().unwrap());
result.extend_from_slice(&endpoint_info);
result.put_u8((result.len() + 1) as u8);
result.put_u8((result.len() + 1).try_into().unwrap());
BASE64_URL_SAFE.encode(result)
}
pub(crate) async fn adv_bt<U: UiHandle>(app: &mut Application<U>) -> Result<(), Error> {
let name = get_name(&app.config);
let session = bluer::Session::new().await?;
let adapter = session.default_adapter().await?;
adapter.set_powered(true).await?;
// adapter.set_discoverable(true).await?;
let profile = Profile {
uuid: SERVICE_UUID,
name: Some(name),
role: Some(Server),
// name: Some(name),
require_authentication: Some(false),
require_authorization: Some(false),
channel: Some(0),
psm: Some(0),
auto_connect: Some(true),
..Default::default()
};
let mut handle = session.register_profile(profile).await?;
// adapter
// .register_gatt_profile(bluer::gatt::local::Profile {
// uuids: HashSet::from([SERVICE_UUID]),
// ..Default::default()
// })
// .await?;
let cancel = app.child_token();
app.spawn(
async move {
let handle = session.register_profile(profile).await;
info!(
"Advertising on Bluetooth adapter {} with address {}",
"Advertising on Bluetooth adapter {} with name {}",
adapter.name(),
adapter.address().await.unwrap()
name
);
while let Some(req) = handle.next().await {
info!("{:?}", req);
}
info!("No more requests");
cancel.cancelled().await;
},
"BT Adv",
Expand Down
4 changes: 2 additions & 2 deletions rustdrop_core/src/mediums/bt/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use bluer::Uuid;
use hex_literal::hex;
use uuid::uuid;
pub const SERVICE_UUID: Uuid = uuid!("a82efa21-ae5c-3dde-9bbc-f16da7b16c5a");
pub const SERVICE_ID: [u8; 32] =
hex!("fc9f5ed42c8a5e9e94684076ef3bf938a809c60ad354992b0435aebbdc58b97b");
pub const SERVICE_ID: [u8; 3] = hex!("fc9f5e");
// Full: fc9f5ed42c8a5e9e94684076ef3bf938a809c60ad354992b0435aebbdc58b97b
pub const PCP: u8 = 0x23;
84 changes: 84 additions & 0 deletions rustdrop_core/src/mediums/bt/manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::collections::HashSet;

use bluer::{rfcomm::Profile, Adapter, AdapterEvent, DiscoveryFilter, Session};
use tokio_stream::StreamExt;
use tracing::{info, trace};

use crate::{core::RustdropError, Application, UiHandle};

use super::{advertise_recv::get_name, consts::SERVICE_UUID};

pub(crate) struct Bluetooth<U: UiHandle> {
session: Session,
adapter: Adapter,
app: Application<U>,
}
impl<U: UiHandle> Bluetooth<U> {
pub async fn new(app: Application<U>) -> Result<Self, RustdropError> {
let session = bluer::Session::new().await?;
let adapter = session.default_adapter().await?;
Ok(Self {
session,
adapter,
app,
})
}
async fn adv_profile(&mut self, profile: Profile, name: String) -> Result<(), RustdropError> {
let mut handle = self.session.register_profile(profile).await?;
let cancel = self.app.child_token();
info!(
"Advertising on Bluetooth adapter {} with name {}",
self.adapter.name(),
name
);
self.app.spawn(
async move {
while let Some(req) = handle.next().await {
info!("{:?}", req);
}
info!("No more requests");
cancel.cancelled().await;
},
"BT Adv",
);
Ok(())
}
pub(crate) async fn adv_bt(&mut self) -> Result<(), RustdropError> {
// self.discover_bt().await?;
let name = get_name(&self.app.config);
let profile = Profile {
uuid: SERVICE_UUID,
role: Some(bluer::rfcomm::Role::Server),
// name: Some(name),
require_authentication: Some(false),
require_authorization: Some(false),
channel: Some(0),
psm: Some(0),
auto_connect: Some(true),
..Default::default()
};
self.adv_profile(profile, name).await?;
Ok(())
}
pub(crate) async fn discover_bt(&mut self) -> Result<(), RustdropError> {
let filter = DiscoveryFilter {
uuids: HashSet::from([SERVICE_UUID]),
// transport: bluer::DiscoveryTransport::Auto,
..Default::default()
};
self.discover(filter).await?;
Ok(())
}
async fn discover(&mut self, filter: DiscoveryFilter) -> Result<(), RustdropError> {
self.adapter.set_discovery_filter(filter).await?;
let mut discover = self.adapter.discover_devices().await?;
while let Some(discovery) = discover.next().await {
trace!("{:?}", discovery);
if let AdapterEvent::DeviceAdded(addr) = discovery {
let dev = self.adapter.device(addr)?;
info!("{:?}", dev.all_properties().await?);
}
}
Ok(())
}
}
31 changes: 19 additions & 12 deletions rustdrop_core/src/runner/managed.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
use crate::{
core::RustdropError,
mediums::{
ble::{scan_for_incoming, trigger_reciever},
bt::advertise_recv::adv_bt,
bt::Bluetooth,
wlan::{start_wlan, WlanClient},
},
Application, Config, UiHandle,
};
use tracing::info;
pub struct Rustdrop<U: UiHandle> {
app: Application<U>,
bluetooth: Bluetooth<U>,
}
impl<U: UiHandle + From<Config>> Rustdrop<U> {
pub fn new(config: Config) -> Self {
Self {
app: Application::from(config),
}
pub async fn from_config(config: Config) -> Result<Self, RustdropError> {
let app = Application::from(config);
Rustdrop::new(app).await
}
}
impl<U: UiHandle> Rustdrop<U> {
pub async fn start_recieving(&mut self) {
async fn new(app: Application<U>) -> Result<Self, RustdropError> {
Ok(Self {
bluetooth: Bluetooth::new(app.clone()).await?,
app,
})
}
pub async fn start_recieving(&mut self) -> Result<(), RustdropError> {
scan_for_incoming(&mut self.app).await.unwrap();
trigger_reciever(&mut self.app).await.unwrap();
adv_bt(&mut self.app).await.unwrap();
self.bluetooth.adv_bt().await?;
info!("Running server");
start_wlan(&mut self.app).await;
Ok(())
}
pub async fn send_file(&mut self) {
trigger_reciever(&mut self.app).await.unwrap();
Expand All @@ -35,10 +43,9 @@ impl<U: UiHandle> Rustdrop<U> {
self.app.shutdown().await;
}
}
impl<U: UiHandle + Default> Default for Rustdrop<U> {
fn default() -> Self {
Self {
app: Application::default(),
}
impl<U: UiHandle + Default> Rustdrop<U> {
pub async fn default() -> Result<Self, RustdropError> {
let app = Application::default();
Self::new(app).await
}
}
4 changes: 2 additions & 2 deletions rustdrop_core/src/runner/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use tracing::Level;
use tracing_subscriber::{filter::Targets, prelude::*};

use super::managed::Rustdrop;
use crate::SimpleUI;
use crate::{Config, SimpleUI};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
Expand All @@ -25,7 +25,7 @@ fn init_logging() {
pub async fn run_simple() {
init_logging();
let args = Args::parse();
let mut runner: Rustdrop<SimpleUI> = Rustdrop::default();
let mut runner: Rustdrop<SimpleUI> = Rustdrop::default().await.unwrap();
if args.client {
runner.send_file().await;
} else {
Expand Down
4 changes: 2 additions & 2 deletions rustdrop_daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod ui;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let mut rustdrop: Rustdrop<DaemonUI> = Rustdrop::default();
rustdrop.start_recieving().await;
let mut rustdrop: Rustdrop<DaemonUI> = Rustdrop::default().await.unwrap();
rustdrop.start_recieving().await.unwrap();
signal::ctrl_c().await.unwrap();
}

0 comments on commit 82f4b37

Please sign in to comment.