mirror of
https://github.com/fossasia/badgemagic-rs
synced 2025-06-25 08:13:58 +00:00
Compare commits
No commits in common. "main" and "commit-98b6f0b" have entirely different histories.
main
...
commit-98b
3 changed files with 11 additions and 116 deletions
44
src/ble.rs
44
src/ble.rs
|
@ -26,50 +26,6 @@ pub struct Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
/// Return a list of all BLE devies as a string representation.
|
|
||||||
pub async fn list_all() -> Result<Vec<String>> {
|
|
||||||
// Run device scan
|
|
||||||
let manager = Manager::new().await.context("create BLE manager")?;
|
|
||||||
let adapters = manager
|
|
||||||
.adapters()
|
|
||||||
.await
|
|
||||||
.context("enumerate bluetooth adapters")?;
|
|
||||||
let adapter = adapters.first().context("no bluetooth adapter found")?;
|
|
||||||
|
|
||||||
adapter
|
|
||||||
.start_scan(ScanFilter {
|
|
||||||
// don't filter by service
|
|
||||||
services: Vec::new(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.context("bluetooth scan start")?;
|
|
||||||
time::sleep(Duration::from_secs(2)).await;
|
|
||||||
|
|
||||||
let mut devices = Vec::new();
|
|
||||||
for peripheral in adapter
|
|
||||||
.peripherals()
|
|
||||||
.await
|
|
||||||
.context("enumerating bluetooth devices")?
|
|
||||||
{
|
|
||||||
let device = async {
|
|
||||||
let props = peripheral
|
|
||||||
.properties()
|
|
||||||
.await?
|
|
||||||
.context("missing device info")?;
|
|
||||||
|
|
||||||
Ok(format!(
|
|
||||||
"{}: name={:?} services={:?}",
|
|
||||||
props.address, props.local_name, props.services
|
|
||||||
))
|
|
||||||
};
|
|
||||||
devices.push(device.await.unwrap_or_else(|err: anyhow::Error| {
|
|
||||||
format!("{} failed to collect info: {err:?}", peripheral.address())
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(devices)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return all supported devices that are found in two seconds.
|
/// Return all supported devices that are found in two seconds.
|
||||||
///
|
///
|
||||||
/// Returns all badges that are in BLE range and are in Bluetooth transfer mode.
|
/// Returns all badges that are in BLE range and are in Bluetooth transfer mode.
|
||||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -9,7 +9,7 @@ use badgemagic::{
|
||||||
usb_hid::Device as UsbDevice,
|
usb_hid::Device as UsbDevice,
|
||||||
};
|
};
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::Parser;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
geometry::Point,
|
geometry::Point,
|
||||||
image::{Image, ImageRawLE},
|
image::{Image, ImageRawLE},
|
||||||
|
@ -43,16 +43,11 @@ struct Args {
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
transport: TransportProtocol,
|
transport: TransportProtocol,
|
||||||
|
|
||||||
/// List all devices visible to a transport and exit
|
|
||||||
#[clap(long)]
|
|
||||||
list_devices: bool,
|
|
||||||
|
|
||||||
/// Path to TOML configuration file
|
/// Path to TOML configuration file
|
||||||
#[clap(required_unless_present = "list_devices")]
|
config: PathBuf,
|
||||||
config: Option<PathBuf>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, ValueEnum)]
|
#[derive(Clone, Deserialize, clap::ValueEnum)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
enum TransportProtocol {
|
enum TransportProtocol {
|
||||||
Usb,
|
Usb,
|
||||||
|
@ -96,48 +91,16 @@ enum Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut args = Args::parse();
|
let args = Args::parse();
|
||||||
|
let config = fs::read_to_string(&args.config)
|
||||||
|
.with_context(|| format!("load config: {:?}", args.config))?;
|
||||||
|
|
||||||
if args.list_devices {
|
|
||||||
return list_devices(&args.transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
let payload = gnerate_payload(&mut args)?;
|
|
||||||
|
|
||||||
write_payload(&args.transport, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn list_devices(transport: &TransportProtocol) -> Result<()> {
|
|
||||||
let devices = match transport {
|
|
||||||
TransportProtocol::Usb => UsbDevice::list_all(),
|
|
||||||
TransportProtocol::Ble => tokio::runtime::Builder::new_current_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()?
|
|
||||||
.block_on(async { BleDevice::list_all().await }),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"found {} {} devices",
|
|
||||||
devices.len(),
|
|
||||||
transport.to_possible_value().unwrap().get_name(),
|
|
||||||
);
|
|
||||||
for device in devices {
|
|
||||||
println!("- {device}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gnerate_payload(args: &mut Args) -> Result<PayloadBuffer> {
|
|
||||||
let config_path = args.config.take().unwrap_or_default();
|
|
||||||
let config = fs::read_to_string(&config_path)
|
|
||||||
.with_context(|| format!("load config: {config_path:?}"))?;
|
|
||||||
let config: Config = {
|
let config: Config = {
|
||||||
let extension = args
|
let extension = args
|
||||||
.format
|
.format
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(AsRef::as_ref)
|
.map(AsRef::as_ref)
|
||||||
.or(config_path.extension())
|
.or(args.config.extension())
|
||||||
.context("missing file extension for config file")?;
|
.context("missing file extension for config file")?;
|
||||||
match extension.to_str().unwrap_or_default() {
|
match extension.to_str().unwrap_or_default() {
|
||||||
"json" => serde_json::from_str(&config).context("parse config")?,
|
"json" => serde_json::from_str(&config).context("parse config")?,
|
||||||
|
@ -226,18 +189,13 @@ fn gnerate_payload(args: &mut Args) -> Result<PayloadBuffer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(payload)
|
match args.transport {
|
||||||
}
|
|
||||||
|
|
||||||
fn write_payload(
|
|
||||||
transport: &TransportProtocol,
|
|
||||||
payload: PayloadBuffer,
|
|
||||||
) -> Result<(), anyhow::Error> {
|
|
||||||
match transport {
|
|
||||||
TransportProtocol::Usb => UsbDevice::single()?.write(payload),
|
TransportProtocol::Usb => UsbDevice::single()?.write(payload),
|
||||||
TransportProtocol::Ble => tokio::runtime::Builder::new_current_thread()
|
TransportProtocol::Ble => tokio::runtime::Builder::new_current_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.build()?
|
.build()?
|
||||||
.block_on(async { BleDevice::single().await?.write(payload).await }),
|
.block_on(async { BleDevice::single().await?.write(payload).await }),
|
||||||
}
|
}?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,25 +29,6 @@ pub struct Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
/// Return a list of all usb devies as a string representation
|
|
||||||
pub fn list_all() -> Result<Vec<String>> {
|
|
||||||
let api = HidApi::new().context("create hid api")?;
|
|
||||||
let devices = api.device_list();
|
|
||||||
|
|
||||||
Ok(devices
|
|
||||||
.map(|info| {
|
|
||||||
format!(
|
|
||||||
"{:?}: vendor_id={:#06x} product_id={:#06x} manufacturer={:?} product={:?}",
|
|
||||||
info.path(),
|
|
||||||
info.vendor_id(),
|
|
||||||
info.product_id(),
|
|
||||||
info.manufacturer_string(),
|
|
||||||
info.product_string(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return all supported devices
|
/// Return all supported devices
|
||||||
pub fn enumerate() -> Result<Vec<Self>> {
|
pub fn enumerate() -> Result<Vec<Self>> {
|
||||||
let api = HidApi::new().context("create hid api")?;
|
let api = HidApi::new().context("create hid api")?;
|
||||||
|
|
Loading…
Reference in a new issue