-
Notifications
You must be signed in to change notification settings - Fork 45
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
Implement bluetooth mesh support #60
Changes from all commits
26f55a6
f94de1c
c82fca8
ee35298
bc2a554
6f92bec
2dd90b1
edbec54
7515608
092ab9c
38436f0
2e52bd4
575b8f4
146c235
d1045c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,3 +46,4 @@ libc = "0.2" | |
log = "0.4" | ||
hex = { version = "0.4" } | ||
rand = "0.8" | ||
uuid = { version = "1", features = ["v4"] } | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
//! Attach and send/receive BT Mesh messages | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this be useful as a standalone tool? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is just an example for now (as it is tied to the predefined model) ... The proper tool needs more work |
||
//! | ||
//! Example meshd | ||
//! [bluer/bluer]$ sudo /usr/libexec/bluetooth/bluetooth-meshd --config ${PWD}/examples/meshd/config --storage ${PWD}/meshd/lib --debug | ||
//! | ||
//! To demo device join, run client or server without a token | ||
//! [bluer/bluer]$ RUST_LOG=TRACE cargo +nightly run --features=mesh --example mesh_sensor_client | ||
//! | ||
//! Example provisioner | ||
//! [bluer/bluer]$ RUST_LOG=TRACE cargo +nightly run --features=mesh --example mesh_provisioner -- --token 84783e12f11c4dcd --uuid 4bd9876a3e4844bbb4339ef42f614f1f | ||
|
||
use bluer::{ | ||
mesh::{ | ||
application::Application, | ||
element::*, | ||
provisioner::{Provisioner, ProvisionerControlHandle, ProvisionerEvent}, | ||
}, | ||
Uuid, | ||
}; | ||
use btmesh_models::{ | ||
foundation::configuration::{ | ||
app_key::AppKeyMessage, ConfigurationMessage, ConfigurationServer, CONFIGURATION_CLIENT, | ||
CONFIGURATION_SERVER, | ||
}, | ||
Message, Model, | ||
}; | ||
use clap::Parser; | ||
use futures::{pin_mut, StreamExt}; | ||
use std::time::Duration; | ||
use tokio::{signal, sync::mpsc, time::sleep}; | ||
use tokio_stream::wrappers::ReceiverStream; | ||
|
||
#[derive(Parser)] | ||
#[clap(author, version, about, long_about = None)] | ||
struct Args { | ||
#[clap(short, long)] | ||
token: String, | ||
#[clap(short, long)] | ||
uuid: String, | ||
} | ||
|
||
#[tokio::main(flavor = "current_thread")] | ||
async fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
env_logger::init(); | ||
let args = Args::parse(); | ||
let session = bluer::Session::new().await?; | ||
|
||
let mesh = session.mesh().await?; | ||
|
||
let (element_control, element_handle) = element_control(5); | ||
let (app_tx, _app_rx) = mpsc::channel(1); | ||
|
||
let (prov_tx, prov_rx) = mpsc::channel(1); | ||
|
||
let sim = Application { | ||
device_id: Uuid::new_v4(), | ||
elements: vec![Element { | ||
location: None, | ||
models: vec![CONFIGURATION_SERVER, CONFIGURATION_CLIENT], | ||
control_handle: Some(element_handle), | ||
}], | ||
provisioner: Some(Provisioner { | ||
control_handle: ProvisionerControlHandle { messages_tx: prov_tx }, | ||
start_address: 0xbd, | ||
}), | ||
events_tx: app_tx, | ||
agent: Default::default(), | ||
properties: Default::default(), | ||
}; | ||
|
||
let registered = mesh.application(sim.clone()).await?; | ||
let node = mesh.attach(sim.clone(), &args.token).await?; | ||
|
||
node.management.add_node(Uuid::parse_str(&args.uuid)?).await?; | ||
|
||
let mut prov_stream = ReceiverStream::new(prov_rx); | ||
pin_mut!(element_control); | ||
|
||
loop { | ||
tokio::select! { | ||
_ = signal::ctrl_c() => break, | ||
evt = prov_stream.next() => { | ||
match evt { | ||
Some(msg) => { | ||
match msg { | ||
ProvisionerEvent::AddNodeComplete(uuid, unicast, count) => { | ||
println!("Successfully added node {:?} to the address {:#04x} with {:?} elements", uuid, unicast, count); | ||
|
||
sleep(Duration::from_secs(1)).await; | ||
node.add_app_key(0, unicast, 0, 0, false).await?; | ||
|
||
// example composition get | ||
// let message = ConfigurationMessage::CompositionData(CompositionDataMessage::Get(0)); | ||
// node.dev_key_send::<ConfigurationServer>(message, element_path.clone(), unicast, true, 0 as u16).await?; | ||
|
||
// example bind | ||
// let payload = ModelAppPayload { | ||
// element_address: unicast.try_into().map_err(|_| ReqError::Failed)?, | ||
// app_key_index: AppKeyIndex::new(0), | ||
// model_identifier: SENSOR_SERVER, | ||
// }; | ||
|
||
// let message = ConfigurationMessage::from(ModelAppMessage::Bind(payload)); | ||
// node.dev_key_send::<ConfigurationServer>(message, element_path.clone(), unicast, true, 0 as u16).await?; | ||
}, | ||
ProvisionerEvent::AddNodeFailed(uuid, reason) => { | ||
println!("Failed to add node {:?}: '{:?}'", uuid, reason); | ||
break; | ||
} | ||
} | ||
}, | ||
None => break, | ||
} | ||
}, | ||
evt = element_control.next() => { | ||
match evt { | ||
Some(msg) => { | ||
match msg { | ||
ElementEvent::MessageReceived(received) => { | ||
println!("Received element message: {:?}", received); | ||
}, | ||
ElementEvent::DevKeyMessageReceived(received) => { | ||
println!("Received dev key message: {:?}", received); | ||
match ConfigurationServer::parse(&received.opcode, &received.parameters).map_err(|_| std::fmt::Error)? { | ||
Some(message) => { | ||
match message { | ||
ConfigurationMessage::AppKey(key) => { | ||
match key { | ||
AppKeyMessage::Status(status) => { | ||
println!("Received keys {:?} {:?}", status.indexes.net_key(), status.indexes.app_key()) | ||
}, | ||
_ => println!("Received key message {:?}", key.opcode()), | ||
} | ||
break; | ||
}, | ||
_ => { | ||
println!("Received dev key message {:?}", message.opcode()); | ||
break; | ||
} | ||
} | ||
}, | ||
None => break, | ||
} | ||
} | ||
} | ||
}, | ||
None => break, | ||
} | ||
}, | ||
} | ||
} | ||
|
||
// Example agent function | ||
// pub fn display_numeric(req: DisplayNumeric) -> ReqResult<()> { | ||
// println!("Enter '{:?}' on the remote device!", req.number); | ||
// Ok(()) | ||
// } | ||
|
||
println!("Shutting down"); | ||
drop(registered); | ||
sleep(Duration::from_secs(1)).await; | ||
|
||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not necessary