On-off example now buildable
This commit is contained in:
parent
17002db7e1
commit
a7ca17fabc
10 changed files with 175 additions and 84 deletions
|
@ -15,4 +15,4 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO pub mod dev_att;
|
||||
pub mod dev_att;
|
||||
|
|
|
@ -15,41 +15,114 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO
|
||||
// mod dev_att;
|
||||
// use matter::core::{self, CommissioningData};
|
||||
// use matter::data_model::cluster_basic_information::BasicInfoConfig;
|
||||
// use matter::data_model::device_types::device_type_add_on_off_light;
|
||||
// use matter::secure_channel::spake2p::VerifierData;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use matter::core::{CommissioningData, Matter};
|
||||
use matter::data_model::cluster_basic_information::BasicInfoConfig;
|
||||
use matter::data_model::cluster_on_off;
|
||||
use matter::data_model::core::DataModel;
|
||||
use matter::data_model::device_types::DEV_TYPE_ON_OFF_LIGHT;
|
||||
use matter::data_model::objects::*;
|
||||
use matter::data_model::root_endpoint;
|
||||
use matter::data_model::sdm::dev_att::DevAttDataFetcher;
|
||||
use matter::interaction_model::core::InteractionModel;
|
||||
use matter::secure_channel::spake2p::VerifierData;
|
||||
use matter::transport::{
|
||||
mgr::RecvAction, mgr::TransportMgr, packet::Packet, packet::MAX_RX_BUF_SIZE,
|
||||
packet::MAX_TX_BUF_SIZE, udp::UdpListener,
|
||||
};
|
||||
|
||||
mod dev_att;
|
||||
|
||||
fn main() {
|
||||
// env_logger::init();
|
||||
// let comm_data = CommissioningData {
|
||||
// // TODO: Hard-coded for now
|
||||
// verifier: VerifierData::new_with_pw(123456),
|
||||
// discriminator: 250,
|
||||
// };
|
||||
env_logger::init();
|
||||
|
||||
// // vid/pid should match those in the DAC
|
||||
// let dev_info = BasicInfoConfig {
|
||||
// vid: 0xFFF1,
|
||||
// pid: 0x8000,
|
||||
// hw_ver: 2,
|
||||
// sw_ver: 1,
|
||||
// sw_ver_str: "1".to_string(),
|
||||
// serial_no: "aabbccdd".to_string(),
|
||||
// device_name: "OnOff Light".to_string(),
|
||||
// };
|
||||
// let dev_att = Box::new(dev_att::HardCodedDevAtt::new());
|
||||
// vid/pid should match those in the DAC
|
||||
let dev_info = BasicInfoConfig {
|
||||
vid: 0xFFF1,
|
||||
pid: 0x8000,
|
||||
hw_ver: 2,
|
||||
sw_ver: 1,
|
||||
sw_ver_str: "1",
|
||||
serial_no: "aabbccdd",
|
||||
device_name: "OnOff Light",
|
||||
};
|
||||
|
||||
// let mut matter = core::Matter::new(dev_info, dev_att, comm_data).unwrap();
|
||||
// let dm = matter.get_data_model();
|
||||
// {
|
||||
// let mut node = dm.node.write().unwrap();
|
||||
// let endpoint = device_type_add_on_off_light(&mut node).unwrap();
|
||||
// println!("Added OnOff Light Device type at endpoint id: {}", endpoint);
|
||||
// println!("Data Model now is: {}", node);
|
||||
// }
|
||||
let mut mdns = matter::sys::LinuxMdns::new().unwrap();
|
||||
|
||||
// matter.start_daemon().unwrap();
|
||||
let matter = Matter::new_default(&dev_info, &mut mdns);
|
||||
|
||||
let dev_att = dev_att::HardCodedDevAtt::new();
|
||||
|
||||
matter
|
||||
.start::<4096>(
|
||||
CommissioningData {
|
||||
// TODO: Hard-coded for now
|
||||
verifier: VerifierData::new_with_pw(123456, *matter.borrow()),
|
||||
discriminator: 250,
|
||||
},
|
||||
&mut [0; 4096],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let matter = &matter;
|
||||
let dev_att = &dev_att;
|
||||
|
||||
let mut transport = TransportMgr::new(matter);
|
||||
|
||||
smol::block_on(async move {
|
||||
let udp = UdpListener::new().await.unwrap();
|
||||
|
||||
loop {
|
||||
let mut rx_buf = [0; MAX_RX_BUF_SIZE];
|
||||
let mut tx_buf = [0; MAX_TX_BUF_SIZE];
|
||||
|
||||
let (len, addr) = udp.recv(&mut rx_buf).await.unwrap();
|
||||
|
||||
let mut rx = Packet::new_rx(&mut rx_buf[..len]);
|
||||
let mut tx = Packet::new_tx(&mut tx_buf);
|
||||
|
||||
let mut completion = transport.recv(addr, &mut rx, &mut tx);
|
||||
|
||||
while let Some(action) = completion.next_action().unwrap() {
|
||||
match action {
|
||||
RecvAction::Send(addr, buf) => {
|
||||
udp.send(addr, buf).await.unwrap();
|
||||
}
|
||||
RecvAction::Interact(mut ctx) => {
|
||||
let node = Node {
|
||||
id: 0,
|
||||
endpoints: &[
|
||||
root_endpoint::endpoint(0),
|
||||
Endpoint {
|
||||
id: 1,
|
||||
device_type: DEV_TYPE_ON_OFF_LIGHT,
|
||||
clusters: &[cluster_on_off::CLUSTER],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let mut handler = handler(matter, dev_att);
|
||||
|
||||
let mut im =
|
||||
InteractionModel(DataModel::new(matter.borrow(), &node, &mut handler));
|
||||
|
||||
if im.handle(&mut ctx).unwrap() {
|
||||
if let Some(addr) = ctx.send().unwrap() {
|
||||
udp.send(addr, ctx.tx.as_slice()).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a {
|
||||
root_endpoint::handler(0, dev_att, matter).chain(
|
||||
1,
|
||||
cluster_on_off::ID,
|
||||
cluster_on_off::OnOffCluster::new(*matter.borrow()),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ name = "matter"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["std", "crypto_mbedtls"]
|
||||
default = ["std", "crypto_mbedtls", "nightly"]
|
||||
std = ["alloc", "env_logger", "chrono", "rand", "qrcode", "smol"]
|
||||
alloc = []
|
||||
nightly = []
|
||||
|
|
|
@ -99,7 +99,7 @@ impl<'a> Matter<'a> {
|
|||
}
|
||||
|
||||
pub fn start<const N: usize>(
|
||||
&mut self,
|
||||
&self,
|
||||
dev_comm: CommissioningData,
|
||||
buf: &mut [u8],
|
||||
) -> Result<(), Error> {
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
|
||||
use super::{
|
||||
cluster_basic_information::{self, BasicInfoCluster, BasicInfoConfig},
|
||||
objects::{Cluster, EmptyHandler},
|
||||
objects::{Cluster, EmptyHandler, Endpoint, EndptId},
|
||||
sdm::{
|
||||
admin_commissioning::{self, AdminCommCluster},
|
||||
dev_att::DevAttDataFetcher,
|
||||
|
@ -47,6 +47,14 @@ pub const CLUSTERS: [Cluster<'static>; 7] = [
|
|||
access_control::CLUSTER,
|
||||
];
|
||||
|
||||
pub fn endpoint(id: EndptId) -> Endpoint<'static> {
|
||||
Endpoint {
|
||||
id,
|
||||
device_type: super::device_types::DEV_TYPE_ROOT_NODE,
|
||||
clusters: &CLUSTERS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handler<'a>(
|
||||
endpoint_id: u16,
|
||||
dev_att: &'a dyn DevAttDataFetcher,
|
||||
|
|
|
@ -710,14 +710,14 @@ impl ResumeSubscribeReq {
|
|||
}
|
||||
|
||||
pub trait InteractionHandler {
|
||||
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error>;
|
||||
fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error>;
|
||||
}
|
||||
|
||||
impl<T> InteractionHandler for &mut T
|
||||
where
|
||||
T: InteractionHandler,
|
||||
{
|
||||
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> {
|
||||
fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
|
||||
(**self).handle(ctx)
|
||||
}
|
||||
}
|
||||
|
@ -728,7 +728,7 @@ impl<T> InteractionModel<T>
|
|||
where
|
||||
T: DataHandler,
|
||||
{
|
||||
pub fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> {
|
||||
pub fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
|
||||
let mut transaction = Transaction::new(&mut ctx.exch_ctx);
|
||||
|
||||
let reply =
|
||||
|
@ -738,7 +738,7 @@ where
|
|||
true
|
||||
};
|
||||
|
||||
Ok(reply.then_some(ctx.tx.as_slice()))
|
||||
Ok(reply)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -747,10 +747,7 @@ impl<T> InteractionModel<T>
|
|||
where
|
||||
T: crate::data_model::core::asynch::AsyncDataHandler,
|
||||
{
|
||||
pub async fn handle_async<'a>(
|
||||
&mut self,
|
||||
ctx: &'a mut ProtoCtx<'_, '_>,
|
||||
) -> Result<Option<&'a [u8]>, Error> {
|
||||
pub async fn handle_async<'a>(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
|
||||
let mut transaction = Transaction::new(&mut ctx.exch_ctx);
|
||||
|
||||
let reply =
|
||||
|
@ -760,7 +757,7 @@ where
|
|||
true
|
||||
};
|
||||
|
||||
Ok(reply.then_some(ctx.tx.as_slice()))
|
||||
Ok(reply)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -768,7 +765,7 @@ impl<T> InteractionHandler for InteractionModel<T>
|
|||
where
|
||||
T: DataHandler,
|
||||
{
|
||||
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> {
|
||||
fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
|
||||
InteractionModel::handle(self, ctx)
|
||||
}
|
||||
}
|
||||
|
@ -782,20 +779,14 @@ pub mod asynch {
|
|||
use super::InteractionModel;
|
||||
|
||||
pub trait AsyncInteractionHandler {
|
||||
async fn handle<'a>(
|
||||
&mut self,
|
||||
ctx: &'a mut ProtoCtx<'_, '_>,
|
||||
) -> Result<Option<&'a [u8]>, Error>;
|
||||
async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error>;
|
||||
}
|
||||
|
||||
impl<T> AsyncInteractionHandler for &mut T
|
||||
where
|
||||
T: AsyncInteractionHandler,
|
||||
{
|
||||
async fn handle<'a>(
|
||||
&mut self,
|
||||
ctx: &'a mut ProtoCtx<'_, '_>,
|
||||
) -> Result<Option<&'a [u8]>, Error> {
|
||||
async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
|
||||
(**self).handle(ctx).await
|
||||
}
|
||||
}
|
||||
|
@ -804,10 +795,7 @@ pub mod asynch {
|
|||
where
|
||||
T: AsyncDataHandler,
|
||||
{
|
||||
async fn handle<'a>(
|
||||
&mut self,
|
||||
ctx: &'a mut ProtoCtx<'_, '_>,
|
||||
) -> Result<Option<&'a [u8]>, Error> {
|
||||
async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
|
||||
InteractionModel::handle_async(self, ctx).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,10 @@ use crate::utils::rand::Rand;
|
|||
use heapless::LinearMap;
|
||||
|
||||
use super::session::CloneData;
|
||||
use super::{mrp::ReliableMessage, packet::Packet, session::SessionHandle, session::SessionMgr};
|
||||
use super::{
|
||||
mrp::ReliableMessage, network::Address, packet::Packet, session::SessionHandle,
|
||||
session::SessionMgr,
|
||||
};
|
||||
|
||||
pub struct ExchangeCtx<'a> {
|
||||
pub exch: &'a mut Exchange,
|
||||
|
@ -40,7 +43,7 @@ pub struct ExchangeCtx<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ExchangeCtx<'a> {
|
||||
pub fn send(&mut self, tx: &mut Packet) -> Result<(), Error> {
|
||||
pub fn send(&mut self, tx: &mut Packet) -> Result<Option<Address>, Error> {
|
||||
self.exch.send(tx, &mut self.sess)
|
||||
}
|
||||
}
|
||||
|
@ -198,10 +201,10 @@ impl Exchange {
|
|||
&mut self,
|
||||
tx: &mut Packet,
|
||||
session: &mut SessionHandle,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<Option<Address>, Error> {
|
||||
if self.state == State::Terminate {
|
||||
info!("Skipping tx for terminated exchange {}", self.id);
|
||||
return Ok(());
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
trace!("payload: {:x?}", tx.as_mut_slice());
|
||||
|
@ -219,7 +222,9 @@ impl Exchange {
|
|||
|
||||
session.pre_send(tx)?;
|
||||
self.mrp.pre_send(tx)?;
|
||||
session.send(tx)
|
||||
session.send(tx)?;
|
||||
|
||||
Ok(Some(session.get_peer_addr()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,11 +359,13 @@ impl ExchangeMgr {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<(), Error> {
|
||||
pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<Address, Error> {
|
||||
let exchange =
|
||||
ExchangeMgr::_get_with_id(&mut self.exchanges, exch_id).ok_or(Error::NoExchange)?;
|
||||
let mut session = self.sess_mgr.get_session_handle(exchange.sess_idx);
|
||||
exchange.send(tx, &mut session)
|
||||
exchange.send(tx, &mut session)?;
|
||||
|
||||
Ok(session.get_peer_addr())
|
||||
}
|
||||
|
||||
pub fn purge(&mut self) {
|
||||
|
@ -381,7 +388,7 @@ impl ExchangeMgr {
|
|||
.map(|(exch_id, _)| *exch_id)
|
||||
}
|
||||
|
||||
pub fn evict_session(&mut self, tx: &mut Packet) -> Result<bool, Error> {
|
||||
pub fn evict_session(&mut self, tx: &mut Packet) -> Result<Option<Address>, Error> {
|
||||
if let Some(index) = self.sess_mgr.get_session_for_eviction() {
|
||||
info!("Sessions full, vacating session with index: {}", index);
|
||||
// If we enter here, we have an LRU session that needs to be reclaimed
|
||||
|
@ -423,11 +430,14 @@ impl ExchangeMgr {
|
|||
// Remove from exchange list
|
||||
self.exchanges.remove(&exch_id);
|
||||
}
|
||||
|
||||
let addr = session.get_peer_addr();
|
||||
|
||||
self.sess_mgr.remove(index);
|
||||
|
||||
Ok(true)
|
||||
Ok(Some(addr))
|
||||
} else {
|
||||
Ok(false)
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +571,7 @@ mod tests {
|
|||
let mut buf = [0; MAX_TX_BUF_SIZE];
|
||||
let tx = &mut Packet::new_tx(&mut buf);
|
||||
let evicted = mgr.evict_session(tx).unwrap();
|
||||
assert!(evicted);
|
||||
assert!(evicted.is_some());
|
||||
|
||||
let session = mgr
|
||||
.add_session(&get_clone_data(new_peer_sess_id, new_local_sess_id))
|
||||
|
|
|
@ -32,6 +32,7 @@ use crate::transport::{exchange, packet::Packet};
|
|||
use crate::utils::epoch::{Epoch, UtcCalendar};
|
||||
use crate::utils::rand::Rand;
|
||||
|
||||
use super::network::Address;
|
||||
use super::proto_ctx::ProtoCtx;
|
||||
use super::session::CloneData;
|
||||
|
||||
|
@ -45,12 +46,13 @@ enum RecvState {
|
|||
}
|
||||
|
||||
pub enum RecvAction<'r, 'p> {
|
||||
Send(&'r [u8]),
|
||||
Send(Address, &'r [u8]),
|
||||
Interact(ProtoCtx<'r, 'p>),
|
||||
}
|
||||
|
||||
pub struct RecvCompletion<'r, 'a, 'p> {
|
||||
mgr: &'r mut TransportMgr<'a>,
|
||||
addr: Address, // TODO: Not used yet
|
||||
rx: &'r mut Packet<'p>,
|
||||
tx: &'r mut Packet<'p>,
|
||||
state: RecvState,
|
||||
|
@ -90,9 +92,10 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
|
|||
self.state = RecvState::Ack;
|
||||
}
|
||||
|
||||
if reply {
|
||||
proto_ctx.send()?;
|
||||
Ok(Some(Some(RecvAction::Send(self.tx.as_slice()))))
|
||||
let addr = if reply { proto_ctx.send()? } else { None };
|
||||
|
||||
if let Some(addr) = addr {
|
||||
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -125,14 +128,22 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
|
|||
Err(err) => Err(err),
|
||||
},
|
||||
RecvState::EvictSession => {
|
||||
self.mgr.exch_mgr.evict_session(self.tx)?;
|
||||
let addr = self.mgr.exch_mgr.evict_session(self.tx)?;
|
||||
self.state = RecvState::OpenExchange;
|
||||
Ok(Some(Some(RecvAction::Send(self.tx.as_slice()))))
|
||||
if let Some(addr) = addr {
|
||||
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
RecvState::EvictSession2(clone_data) => {
|
||||
self.mgr.exch_mgr.evict_session(self.tx)?;
|
||||
let addr = self.mgr.exch_mgr.evict_session(self.tx)?;
|
||||
self.state = RecvState::AddSession(clone_data);
|
||||
Ok(Some(Some(RecvAction::Send(self.tx.as_slice()))))
|
||||
if let Some(addr) = addr {
|
||||
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
RecvState::Ack => {
|
||||
if let Some(exch_id) = self.mgr.exch_mgr.pending_ack() {
|
||||
|
@ -140,8 +151,8 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
|
|||
|
||||
ReliableMessage::prepare_ack(exch_id, self.tx);
|
||||
|
||||
self.mgr.exch_mgr.send(exch_id, self.tx)?;
|
||||
Ok(Some(Some(RecvAction::Send(self.tx.as_slice()))))
|
||||
let addr = self.mgr.exch_mgr.send(exch_id, self.tx)?;
|
||||
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
|
||||
} else {
|
||||
Ok(Some(None))
|
||||
}
|
||||
|
@ -220,11 +231,13 @@ impl<'a> TransportMgr<'a> {
|
|||
|
||||
pub fn recv<'r, 'p>(
|
||||
&'r mut self,
|
||||
addr: Address,
|
||||
rx: &'r mut Packet<'p>,
|
||||
tx: &'r mut Packet<'p>,
|
||||
) -> RecvCompletion<'r, 'a, 'p> {
|
||||
RecvCompletion {
|
||||
mgr: self,
|
||||
addr,
|
||||
rx,
|
||||
tx,
|
||||
state: RecvState::New,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
use crate::error::Error;
|
||||
|
||||
use super::exchange::ExchangeCtx;
|
||||
use super::network::Address;
|
||||
use super::packet::Packet;
|
||||
|
||||
/// This is the context in which a receive packet is being processed
|
||||
|
@ -35,9 +36,7 @@ impl<'a, 'b> ProtoCtx<'a, 'b> {
|
|||
Self { exch_ctx, rx, tx }
|
||||
}
|
||||
|
||||
pub fn send(&mut self) -> Result<&[u8], Error> {
|
||||
self.exch_ctx.exch.send(self.tx, &mut self.exch_ctx.sess)?;
|
||||
|
||||
Ok(self.tx.as_slice())
|
||||
pub fn send(&mut self) -> Result<Option<Address>, Error> {
|
||||
self.exch_ctx.exch.send(self.tx, &mut self.exch_ctx.sess)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ impl UdpListener {
|
|||
Ok((size, Address::Udp(addr)))
|
||||
}
|
||||
|
||||
pub async fn send(&self, out_buf: &[u8], addr: Address) -> Result<usize, Error> {
|
||||
pub async fn send(&self, addr: Address, out_buf: &[u8]) -> Result<usize, Error> {
|
||||
match addr {
|
||||
Address::Udp(addr) => self.socket.send_to(out_buf, addr).await.map_err(|e| {
|
||||
info!("Error on the network: {:?}", e);
|
||||
|
|
Loading…
Add table
Reference in a new issue