first commit
This commit is contained in:
89
libmaestro/examples/common/mod.rs
Normal file
89
libmaestro/examples/common/mod.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use bluer::{Address, Device, Session};
|
||||
use bluer::rfcomm::{ProfileHandle, Role, ReqError, Stream, Profile};
|
||||
|
||||
use futures::StreamExt;
|
||||
|
||||
use maestro::pwrpc::Error;
|
||||
use maestro::pwrpc::client::Client;
|
||||
use maestro::pwrpc::types::RpcPacket;
|
||||
|
||||
|
||||
pub async fn run_client<S, E>(mut client: Client<S>) -> Result<()>
|
||||
where
|
||||
S: futures::Sink<RpcPacket>,
|
||||
S: futures::Stream<Item = Result<RpcPacket, E>> + Unpin,
|
||||
Error: From<E>,
|
||||
Error: From<S::Error>,
|
||||
{
|
||||
tokio::select! {
|
||||
res = client.run() => {
|
||||
res?;
|
||||
},
|
||||
sig = tokio::signal::ctrl_c() => {
|
||||
sig?;
|
||||
tracing::trace!("client termination requested");
|
||||
},
|
||||
}
|
||||
|
||||
client.terminate().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn connect_maestro_rfcomm(session: &Session, dev: &Device) -> Result<Stream> {
|
||||
let maestro_profile = Profile {
|
||||
uuid: maestro::UUID,
|
||||
role: Some(Role::Client),
|
||||
require_authentication: Some(false),
|
||||
require_authorization: Some(false),
|
||||
auto_connect: Some(false),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
tracing::debug!("registering maestro profile");
|
||||
let mut handle = session.register_profile(maestro_profile).await?;
|
||||
|
||||
tracing::debug!("connecting to maestro profile");
|
||||
let stream = tokio::try_join!(
|
||||
try_connect_profile(dev),
|
||||
handle_requests_for_profile(&mut handle, dev.address()),
|
||||
)?.1;
|
||||
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
async fn try_connect_profile(dev: &Device) -> Result<()> {
|
||||
const RETRY_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
const MAX_TRIES: u32 = 3;
|
||||
|
||||
let mut i = 0;
|
||||
while let Err(err) = dev.connect_profile(&maestro::UUID).await {
|
||||
if i >= MAX_TRIES { return Err(err.into()) }
|
||||
i += 1;
|
||||
|
||||
tracing::warn!(error=?err, "connecting to profile failed, trying again ({}/{})", i, MAX_TRIES);
|
||||
|
||||
tokio::time::sleep(RETRY_TIMEOUT).await;
|
||||
}
|
||||
|
||||
tracing::debug!(address=%dev.address(), "maestro profile connected");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_requests_for_profile(handle: &mut ProfileHandle, address: Address) -> Result<Stream> {
|
||||
while let Some(req) = handle.next().await {
|
||||
tracing::debug!(address=%req.device(), "received new profile connection request");
|
||||
|
||||
if req.device() == address {
|
||||
tracing::debug!(address=%req.device(), "accepting profile connection request");
|
||||
return Ok(req.accept()?);
|
||||
} else {
|
||||
req.reject(ReqError::Rejected);
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::bail!("profile terminated without requests")
|
||||
}
|
||||
139
libmaestro/examples/maestro_get_battery.rs
Normal file
139
libmaestro/examples/maestro_get_battery.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
//! Simple example for reading battery info via the Maestro service.
|
||||
//!
|
||||
//! Usage:
|
||||
//! cargo run --example maestro_get_battery -- <bluetooth-device-address>
|
||||
|
||||
mod common;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::bail;
|
||||
use bluer::{Address, Session};
|
||||
use futures::StreamExt;
|
||||
|
||||
use maestro::protocol::codec::Codec;
|
||||
use maestro::protocol::types::RuntimeInfo;
|
||||
use maestro::protocol::utils;
|
||||
use maestro::pwrpc::client::{Client, ClientHandle};
|
||||
use maestro::service::MaestroService;
|
||||
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// handle command line arguments
|
||||
let addr = std::env::args().nth(1).expect("need device address as argument");
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
// set up session
|
||||
let session = Session::new().await?;
|
||||
let adapter = session.default_adapter().await?;
|
||||
|
||||
println!("Using adapter '{}'", adapter.name());
|
||||
|
||||
// get device
|
||||
let dev = adapter.device(addr)?;
|
||||
let uuids = {
|
||||
let mut uuids = Vec::from_iter(dev.uuids().await?
|
||||
.unwrap_or_default()
|
||||
.into_iter());
|
||||
|
||||
uuids.sort_unstable();
|
||||
uuids
|
||||
};
|
||||
|
||||
println!("Found device:");
|
||||
println!(" alias: {}", dev.alias().await?);
|
||||
println!(" address: {}", dev.address());
|
||||
println!(" paired: {}", dev.is_paired().await?);
|
||||
println!(" connected: {}", dev.is_connected().await?);
|
||||
println!(" UUIDs:");
|
||||
for uuid in uuids {
|
||||
println!(" {}", uuid);
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("Connecting to Maestro profile");
|
||||
let stream = common::connect_maestro_rfcomm(&session, &dev).await?;
|
||||
|
||||
println!("Profile connected");
|
||||
|
||||
// set up stream for RPC communication
|
||||
let codec = Codec::new();
|
||||
let stream = codec.wrap(stream);
|
||||
|
||||
// set up RPC client
|
||||
let mut client = Client::new(stream);
|
||||
let handle = client.handle();
|
||||
|
||||
// retreive the channel numer
|
||||
let channel = utils::resolve_channel(&mut client).await?;
|
||||
|
||||
let exec_task = common::run_client(client);
|
||||
let battery_task = get_battery(handle, channel);
|
||||
|
||||
let info = tokio::select! {
|
||||
res = exec_task => {
|
||||
match res {
|
||||
Ok(_) => bail!("client terminated unexpectedly without error"),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
},
|
||||
res = battery_task => res,
|
||||
}?;
|
||||
|
||||
let info = info.battery_info
|
||||
.expect("did not receive battery status in runtime-info-changed event");
|
||||
|
||||
println!("Battery status:");
|
||||
|
||||
if let Some(info) = info.case {
|
||||
match info.state {
|
||||
1 => println!(" case: {}% (not charging)", info.level),
|
||||
2 => println!(" case: {}% (charging)", info.level),
|
||||
x => println!(" case: {}% (unknown state: {})", info.level, x),
|
||||
}
|
||||
} else {
|
||||
println!(" case: unknown");
|
||||
}
|
||||
|
||||
if let Some(info) = info.left {
|
||||
match info.state {
|
||||
1 => println!(" left: {}% (not charging)", info.level),
|
||||
2 => println!(" left: {}% (charging)", info.level),
|
||||
x => println!(" left: {}% (unknown state: {})", info.level, x),
|
||||
}
|
||||
} else {
|
||||
println!(" left: unknown");
|
||||
}
|
||||
|
||||
if let Some(info) = info.right {
|
||||
match info.state {
|
||||
1 => println!(" right: {}% (not charging)", info.level),
|
||||
2 => println!(" right: {}% (charging)", info.level),
|
||||
x => println!(" right: {}% (unknown state: {})", info.level, x),
|
||||
}
|
||||
} else {
|
||||
println!(" right: unknown");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_battery(handle: ClientHandle, channel: u32) -> anyhow::Result<RuntimeInfo> {
|
||||
println!("Reading battery info...");
|
||||
println!();
|
||||
|
||||
let mut service = MaestroService::new(handle, channel);
|
||||
|
||||
let mut call = service.subscribe_to_runtime_info()?;
|
||||
let rt_info = if let Some(msg) = call.stream().next().await {
|
||||
msg?
|
||||
} else {
|
||||
bail!("did not receive any runtime-info event");
|
||||
};
|
||||
|
||||
call.cancel_and_wait().await?;
|
||||
Ok(rt_info)
|
||||
}
|
||||
172
libmaestro/examples/maestro_listen.rs
Normal file
172
libmaestro/examples/maestro_listen.rs
Normal file
@@ -0,0 +1,172 @@
|
||||
//! Simple example for listening to Maestro messages sent via the RFCOMM channel.
|
||||
//!
|
||||
//! Usage:
|
||||
//! cargo run --example maestro_listen -- <bluetooth-device-address>
|
||||
|
||||
mod common;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use bluer::{Address, Session};
|
||||
use futures::StreamExt;
|
||||
|
||||
use maestro::protocol::codec::Codec;
|
||||
use maestro::protocol::utils;
|
||||
use maestro::pwrpc::client::{Client, ClientHandle};
|
||||
use maestro::service::{MaestroService, DosimeterService};
|
||||
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// handle command line arguments
|
||||
let addr = std::env::args().nth(1).expect("need device address as argument");
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
// set up session
|
||||
let session = Session::new().await?;
|
||||
let adapter = session.default_adapter().await?;
|
||||
|
||||
println!("Using adapter '{}'", adapter.name());
|
||||
|
||||
// get device
|
||||
let dev = adapter.device(addr)?;
|
||||
let uuids = {
|
||||
let mut uuids = Vec::from_iter(dev.uuids().await?
|
||||
.unwrap_or_default()
|
||||
.into_iter());
|
||||
|
||||
uuids.sort_unstable();
|
||||
uuids
|
||||
};
|
||||
|
||||
println!("Found device:");
|
||||
println!(" alias: {}", dev.alias().await?);
|
||||
println!(" address: {}", dev.address());
|
||||
println!(" paired: {}", dev.is_paired().await?);
|
||||
println!(" connected: {}", dev.is_connected().await?);
|
||||
println!(" UUIDs:");
|
||||
for uuid in uuids {
|
||||
println!(" {}", uuid);
|
||||
}
|
||||
println!();
|
||||
|
||||
// try to reconnect if connection is reset
|
||||
loop {
|
||||
println!("Connecting to Maestro profile");
|
||||
let stream = common::connect_maestro_rfcomm(&session, &dev).await?;
|
||||
|
||||
println!("Profile connected");
|
||||
|
||||
// set up stream for RPC communication
|
||||
let codec = Codec::new();
|
||||
let stream = codec.wrap(stream);
|
||||
|
||||
// set up RPC client
|
||||
let mut client = Client::new(stream);
|
||||
let handle = client.handle();
|
||||
|
||||
// retreive the channel numer
|
||||
let channel = utils::resolve_channel(&mut client).await?;
|
||||
|
||||
let exec_task = common::run_client(client);
|
||||
let listen_task = run_listener(handle, channel);
|
||||
|
||||
tokio::select! {
|
||||
res = exec_task => {
|
||||
match res {
|
||||
Ok(_) => {
|
||||
tracing::trace!("client terminated successfully");
|
||||
return Ok(());
|
||||
},
|
||||
Err(e) => {
|
||||
tracing::error!("client task terminated with error");
|
||||
|
||||
let cause = e.root_cause();
|
||||
if let Some(cause) = cause.downcast_ref::<std::io::Error>() {
|
||||
if cause.raw_os_error() == Some(104) {
|
||||
// The Pixel Buds Pro can hand off processing between each
|
||||
// other. On a switch, the connection is reset. Wait a bit
|
||||
// and then try to reconnect.
|
||||
println!();
|
||||
println!("Connection reset. Attempting to reconnect...");
|
||||
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
},
|
||||
}
|
||||
},
|
||||
res = listen_task => {
|
||||
match res {
|
||||
Ok(_) => {
|
||||
tracing::error!("server terminated stream");
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("main task terminated with error");
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_listener(handle: ClientHandle, channel: u32) -> anyhow::Result<()> {
|
||||
println!("Sending GetSoftwareInfo request");
|
||||
println!();
|
||||
|
||||
let mut service = MaestroService::new(handle.clone(), channel);
|
||||
let mut dosimeter = DosimeterService::new(handle, channel);
|
||||
|
||||
let info = service.get_software_info().await?;
|
||||
println!("{:#?}", info);
|
||||
|
||||
let info = dosimeter.fetch_daily_summaries().await?;
|
||||
println!("{:#?}", info);
|
||||
|
||||
println!();
|
||||
println!("Listening to settings changes...");
|
||||
println!();
|
||||
|
||||
let task_rtinfo = run_listener_rtinfo(service.clone());
|
||||
let task_settings = run_listener_settings(service.clone());
|
||||
let task_dosimeter = run_listener_dosimeter(dosimeter.clone());
|
||||
|
||||
tokio::select! {
|
||||
res = task_rtinfo => res,
|
||||
res = task_settings => res,
|
||||
res = task_dosimeter => res,
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_listener_rtinfo(mut service: MaestroService) -> anyhow::Result<()> {
|
||||
let mut call = service.subscribe_to_runtime_info()?;
|
||||
while let Some(msg) = call.stream().next().await {
|
||||
println!("{:#?}", msg?);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_listener_settings(mut service: MaestroService) -> anyhow::Result<()> {
|
||||
let mut call = service.subscribe_to_settings_changes()?;
|
||||
while let Some(msg) = call.stream().next().await {
|
||||
println!("{:#?}", msg?);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_listener_dosimeter(mut service: DosimeterService) -> anyhow::Result<()> {
|
||||
let mut call = service.subscribe_to_live_db()?;
|
||||
while let Some(msg) = call.stream().next().await {
|
||||
println!("volume: {:#?} dB", (msg.unwrap().intensity.log10() * 10.0).round());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
152
libmaestro/examples/maestro_read_settings.rs
Normal file
152
libmaestro/examples/maestro_read_settings.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
//! Simple example for reading settings on the Pixel Buds Pro via the Maestro service.
|
||||
//!
|
||||
//! Usage:
|
||||
//! cargo run --example maestro_read_settings -- <bluetooth-device-address>
|
||||
|
||||
mod common;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::bail;
|
||||
use bluer::{Address, Session};
|
||||
|
||||
use maestro::protocol::codec::Codec;
|
||||
use maestro::protocol::utils;
|
||||
use maestro::pwrpc::client::{Client, ClientHandle};
|
||||
use maestro::service::MaestroService;
|
||||
use maestro::service::settings::{self, SettingId};
|
||||
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// handle command line arguments
|
||||
let addr = std::env::args().nth(1).expect("need device address as argument");
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
// set up session
|
||||
let session = Session::new().await?;
|
||||
let adapter = session.default_adapter().await?;
|
||||
|
||||
println!("Using adapter '{}'", adapter.name());
|
||||
|
||||
// get device
|
||||
let dev = adapter.device(addr)?;
|
||||
let uuids = {
|
||||
let mut uuids = Vec::from_iter(dev.uuids().await?
|
||||
.unwrap_or_default()
|
||||
.into_iter());
|
||||
|
||||
uuids.sort_unstable();
|
||||
uuids
|
||||
};
|
||||
|
||||
println!("Found device:");
|
||||
println!(" alias: {}", dev.alias().await?);
|
||||
println!(" address: {}", dev.address());
|
||||
println!(" paired: {}", dev.is_paired().await?);
|
||||
println!(" connected: {}", dev.is_connected().await?);
|
||||
println!(" UUIDs:");
|
||||
for uuid in uuids {
|
||||
println!(" {}", uuid);
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("Connecting to Maestro profile");
|
||||
let stream = common::connect_maestro_rfcomm(&session, &dev).await?;
|
||||
|
||||
println!("Profile connected");
|
||||
|
||||
// set up stream for RPC communication
|
||||
let codec = Codec::new();
|
||||
let stream = codec.wrap(stream);
|
||||
|
||||
// set up RPC client
|
||||
let mut client = Client::new(stream);
|
||||
let handle = client.handle();
|
||||
|
||||
// retreive the channel numer
|
||||
let channel = utils::resolve_channel(&mut client).await?;
|
||||
|
||||
let exec_task = common::run_client(client);
|
||||
let settings_task = read_settings(handle, channel);
|
||||
|
||||
tokio::select! {
|
||||
res = exec_task => {
|
||||
match res {
|
||||
Ok(_) => bail!("client terminated unexpectedly without error"),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
},
|
||||
res = settings_task => res,
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_settings(handle: ClientHandle, channel: u32) -> anyhow::Result<()> {
|
||||
let mut service = MaestroService::new(handle.clone(), channel);
|
||||
|
||||
println!();
|
||||
println!("Read via types:");
|
||||
|
||||
// read some typed settings via proxy structs
|
||||
let value = service.read_setting(settings::id::AutoOtaEnable).await?;
|
||||
println!(" Auto-OTA enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::OhdEnable).await?;
|
||||
println!(" OHD enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::OobeIsFinished).await?;
|
||||
println!(" OOBE finished: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::GestureEnable).await?;
|
||||
println!(" Gestures enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::DiagnosticsEnable).await?;
|
||||
println!(" Diagnostics enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::OobeMode).await?;
|
||||
println!(" OOBE mode: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::GestureControl).await?;
|
||||
println!(" Gesture control: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::MultipointEnable).await?;
|
||||
println!(" Multi-point enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::AncrGestureLoop).await?;
|
||||
println!(" ANCR gesture loop: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::CurrentAncrState).await?;
|
||||
println!(" ANC status: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::OttsMode).await?;
|
||||
println!(" OTTS mode: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::VolumeEqEnable).await?;
|
||||
println!(" Volume-EQ enabled: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::CurrentUserEq).await?;
|
||||
println!(" Current user EQ: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::VolumeAsymmetry).await?;
|
||||
println!(" Volume balance/asymmetry: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::SumToMono).await?;
|
||||
println!(" Mono output: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::VolumeExposureNotifications).await?;
|
||||
println!(" Volume level exposure notifications: {}", value);
|
||||
|
||||
let value = service.read_setting(settings::id::SpeechDetection).await?;
|
||||
println!(" Speech detection: {}", value);
|
||||
|
||||
// read settings via variant
|
||||
println!();
|
||||
println!("Read via variants:");
|
||||
|
||||
let value = service.read_setting(SettingId::GestureEnable).await?;
|
||||
println!(" Gesture enable: {:?}", value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
106
libmaestro/examples/maestro_write_settings.rs
Normal file
106
libmaestro/examples/maestro_write_settings.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
//! Simple example for changing settings on the Pixel Buds Pro via the Maestro service.
|
||||
//!
|
||||
//! Sets active nois ecancelling (ANC) state. 1: off, 2: active, 3: aware, 4.adaptive
|
||||
//!
|
||||
//! Usage:
|
||||
//! cargo run --example maestro_write_settings -- <bluetooth-device-address> <anc-state>
|
||||
|
||||
mod common;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::bail;
|
||||
use bluer::{Address, Session};
|
||||
use maestro::protocol::utils;
|
||||
use num_enum::FromPrimitive;
|
||||
|
||||
use maestro::protocol::codec::Codec;
|
||||
use maestro::pwrpc::client::{Client, ClientHandle};
|
||||
use maestro::service::MaestroService;
|
||||
use maestro::service::settings::{AncState, SettingValue};
|
||||
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// handle command line arguments
|
||||
let addr = std::env::args().nth(1).expect("need device address as argument");
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
let anc_state = std::env::args().nth(2).expect("need ANC state as argument");
|
||||
let anc_state = i32::from_str(&anc_state)?;
|
||||
let anc_state = AncState::from_primitive(anc_state);
|
||||
|
||||
if let AncState::Unknown(x) = anc_state {
|
||||
bail!("invalid ANC state {x}");
|
||||
}
|
||||
|
||||
// set up session
|
||||
let session = Session::new().await?;
|
||||
let adapter = session.default_adapter().await?;
|
||||
|
||||
println!("Using adapter '{}'", adapter.name());
|
||||
|
||||
// get device
|
||||
let dev = adapter.device(addr)?;
|
||||
let uuids = {
|
||||
let mut uuids = Vec::from_iter(dev.uuids().await?
|
||||
.unwrap_or_default()
|
||||
.into_iter());
|
||||
|
||||
uuids.sort_unstable();
|
||||
uuids
|
||||
};
|
||||
|
||||
println!("Found device:");
|
||||
println!(" alias: {}", dev.alias().await?);
|
||||
println!(" address: {}", dev.address());
|
||||
println!(" paired: {}", dev.is_paired().await?);
|
||||
println!(" connected: {}", dev.is_connected().await?);
|
||||
println!(" UUIDs:");
|
||||
for uuid in uuids {
|
||||
println!(" {}", uuid);
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("Connecting to Maestro profile");
|
||||
let stream = common::connect_maestro_rfcomm(&session, &dev).await?;
|
||||
|
||||
println!("Profile connected");
|
||||
|
||||
// set up stream for RPC communication
|
||||
let codec = Codec::new();
|
||||
let stream = codec.wrap(stream);
|
||||
|
||||
// set up RPC client
|
||||
let mut client = Client::new(stream);
|
||||
let handle = client.handle();
|
||||
|
||||
// retreive the channel numer
|
||||
let channel = utils::resolve_channel(&mut client).await?;
|
||||
|
||||
let exec_task = common::run_client(client);
|
||||
let settings_task = read_settings(handle, channel, anc_state);
|
||||
|
||||
tokio::select! {
|
||||
res = exec_task => {
|
||||
match res {
|
||||
Ok(_) => bail!("client terminated unexpectedly without error"),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
},
|
||||
res = settings_task => res,
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_settings(handle: ClientHandle, channel: u32, anc_state: AncState) -> anyhow::Result<()> {
|
||||
let mut service = MaestroService::new(handle.clone(), channel);
|
||||
|
||||
println!();
|
||||
println!("Setting ANC status to '{}'", anc_state);
|
||||
|
||||
service.write_setting(SettingValue::CurrentAncrState(anc_state)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user