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

118 save le advertising reports #133

Merged
merged 21 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a08f62b
inital commit with advertisements being written
potto216 Feb 8, 2024
752b4ba
added byte and ascii printing of manufacturer data
potto216 Feb 8, 2024
01a2cd0
added code for recorded time stamp and also the secvice data as a string
potto216 Feb 9, 2024
21c69d4
Merge branch 'master' into 118-Save-LE-Advertising-Reports
potto216 Mar 5, 2024
658f4b4
Switched to JSON lines
potto216 Mar 5, 2024
0ae2992
added comment line option of -a
potto216 Mar 9, 2024
9a9c25b
Merge remote-tracking branch 'origin/master' into 118-Save-LE-Adverti…
potto216 Mar 23, 2024
98265c4
Respond to PR review. Also needed to modify bluer/src/session.rs to s…
potto216 Mar 23, 2024
b1924e9
Respond to PR comments. Need to resolve is_enabled issue.
potto216 Mar 23, 2024
b186219
Respond to PR comments. moved logging functionality into log_device f…
potto216 Mar 24, 2024
df7138c
Respond to PR comments. fixed initalization.
potto216 Mar 24, 2024
21a0da8
Merge branch '118-Save-LE-Advertising-Reports' of https://github.com/…
potto216 Mar 24, 2024
a542249
Respond to PR comments. fixed initalization.
potto216 Mar 24, 2024
8bdbe94
Merge branch '118-Save-LE-Advertising-Reports' of https://github.com/…
potto216 Mar 24, 2024
efdcdf8
Respond to PR comments. fixed initalization.
potto216 Mar 24, 2024
d08e84c
Merge branch '118-Save-LE-Advertising-Reports' of https://github.com/…
potto216 Mar 24, 2024
e57800a
Respond to PR comments. fixed initalization.
potto216 Mar 24, 2024
d86e611
Merge branch '118-Save-LE-Advertising-Reports' of https://github.com/…
potto216 Mar 24, 2024
8b2a3a5
Respond to PR comments. Hopefully final commit because having git con…
potto216 Mar 24, 2024
ab235cf
Respond to PR comments. Hopefully final commit because having git con…
potto216 Mar 24, 2024
05aca5c
Fix issues in PR.
surban Mar 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bluer-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ path = "src/rfcat.rs"

[dependencies]
bluer = { version = "0.17.0", path = "../bluer", features = ["full"] }

futures = "0.3"
tokio = { version = "1", features = [
"fs",
"io-std",
"io-util",
"process",
Expand All @@ -48,3 +50,6 @@ log = "0.4"
hex = { version = "0.4" }
rand = "0.8"
uuid = { version = "1", features = ["v4"] }
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde-jsonlines = { version = "0.5.0", features = ["async"] }
81 changes: 75 additions & 6 deletions bluer-tools/src/blumon.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,84 @@
//! Scans for and monitors Bluetooth devices.

use bluer::{id, Adapter, AdapterEvent, Address};
use chrono::{DateTime, Utc};
use clap::Parser;
use crossterm::{
cursor, execute, queue,
style::{self, Stylize},
terminal::{self, ClearType},
};
use futures::{pin_mut, FutureExt, StreamExt};
use serde::Serialize;
use serde_jsonlines::AsyncJsonLinesWriter;
use std::{
collections::HashMap,
convert::TryFrom,
io::stdout,
iter,
path::PathBuf,
time::{Duration, Instant},
};
use tokio::time::sleep;
use tokio::{fs::File, time::sleep};
use uuid::Uuid;

use bluer::{id, Adapter, AdapterEvent, Address, AddressType, Device};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

const MAX_AGO: u64 = 30;
const UPDATE_INTERVAL: Duration = Duration::from_secs(1);

/// Monitor Bluetooth advertisements.
#[derive(Parser, Debug)]
pub struct Opts {
/// Appends received Bluetooth advertisements to specified file in JSON lines format.
#[clap(short = 'l', long, name = "FILENAME")]
advertisement_log: Option<PathBuf>,
}

/// A line in the advertisement log.
#[derive(Serialize, Debug)]
pub struct AdvertisementLogLine {
received: DateTime<Utc>,
address: Address,
address_type: AddressType,
name: String,
manufacturer_data: HashMap<u16, Vec<u8>>,
service_data: HashMap<Uuid, Vec<u8>>,
rssi: i16,
}

impl AdvertisementLogLine {
async fn new(device: &Device) -> Result<Self> {
Ok(Self {
received: Utc::now(),
address: device.address(),
address_type: device.address_type().await?,
name: device.name().await?.unwrap_or_default(),
manufacturer_data: device.manufacturer_data().await?.unwrap_or_default(),
service_data: device.service_data().await?.unwrap_or_default(),
rssi: device.rssi().await?.unwrap_or_default(),
})
}
}

/// Logs advertisements to file in JSON lines format.
struct AdvertisementLogger(AsyncJsonLinesWriter<File>);

impl AdvertisementLogger {
fn new(writer: File) -> Self {
Self(AsyncJsonLinesWriter::new(writer))
}

async fn log_device(&mut self, device: &Device) -> Result<()> {
if let Ok(line) = AdvertisementLogLine::new(device).await {
self.0.write(&line).await?;
self.0.flush().await?;
}
Ok(())
}
}

fn clear_line(row: u16) {
queue!(stdout(), cursor::MoveTo(0, row), terminal::DisableLineWrap, terminal::Clear(ClearType::CurrentLine))
.unwrap();
Expand All @@ -41,14 +99,14 @@ struct DeviceData {
}

impl DeviceMonitor {
pub async fn run(adapter: Adapter) -> Result<()> {
pub async fn run(adapter: Adapter, logger: Option<AdvertisementLogger>) -> Result<()> {
let (_, n_rows) = terminal::size()?;
let mut this =
Self { adapter, n_rows, empty_rows: (2..n_rows - 1).rev().collect(), devices: HashMap::new() };
this.perform().await
this.perform(logger).await
}

async fn perform(&mut self) -> Result<()> {
async fn perform(&mut self, mut logger: Option<AdvertisementLogger>) -> Result<()> {
let device_events = self.adapter.discover_devices_with_changes().await?;
pin_mut!(device_events);

Expand All @@ -63,6 +121,9 @@ impl DeviceMonitor {
Some(data) => data.last_seen = Instant::now(),
None => self.add_device(addr).await,
}
if let (Some(logger), Ok(device)) = (&mut logger, self.adapter.device(addr)) {
logger.log_device(&device).await?;
}
},
AdapterEvent::DeviceRemoved(addr) => self.remove_device(addr).await,
_ => (),
Expand Down Expand Up @@ -175,9 +236,17 @@ impl DeviceMonitor {
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
env_logger::init();

let opts = Opts::parse();

let session = bluer::Session::new().await?;
let adapter = session.default_adapter().await?;

let logger = match opts.advertisement_log {
Some(path) => Some(AdvertisementLogger::new(File::options().append(true).create(true).open(path).await?)),
None => None,
};

execute!(
stdout(),
terminal::Clear(ClearType::All),
Expand All @@ -187,7 +256,7 @@ async fn main() -> Result<()> {
.unwrap();

adapter.set_powered(true).await?;
DeviceMonitor::run(adapter).await?;
DeviceMonitor::run(adapter, logger).await?;

Ok(())
}
Loading