/* * * Copyright (c) 2020-2022 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use std::borrow::Borrow; use std::error::Error; use log::info; 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::data_model::system_model::descriptor; use matter::interaction_model::core::InteractionModel; use matter::persist; use matter::secure_channel::spake2p::VerifierData; use matter::transport::{ mgr::RecvAction, mgr::TransportMgr, packet::MAX_RX_BUF_SIZE, packet::MAX_TX_BUF_SIZE, udp::UdpListener, }; mod dev_att; fn main() -> Result<(), impl Error> { env_logger::init_from_env( env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), ); // 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 mdns = matter::mdns::astro::AstroMdns::new()?; let mut mdns = matter::mdns::libmdns::LibMdns::new()?; //let mut mdns = matter::mdns::DummyMdns {}; let matter = Matter::new_default(&dev_info, &mut mdns, matter::MATTER_PORT); let dev_att = dev_att::HardCodedDevAtt::new(); let psm_path = std::env::temp_dir().join("matter-iot"); info!("Persisting from/to {}", psm_path.display()); let psm = persist::FilePsm::new(psm_path)?; let mut buf = [0; 4096]; if let Some(data) = psm.load("acls", &mut buf)? { matter.load_acls(data)?; } if let Some(data) = psm.load("fabrics", &mut buf)? { matter.load_fabrics(data)?; } matter.start( CommissioningData { // TODO: Hard-coded for now verifier: VerifierData::new_with_pw(123456, *matter.borrow()), discriminator: 250, }, &mut buf, )?; let matter = &matter; let dev_att = &dev_att; let mut transport = TransportMgr::new(matter); smol::block_on(async move { let udp = UdpListener::new().await?; 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?; let mut completion = transport.recv(addr, &mut rx_buf[..len], &mut tx_buf); while let Some(action) = completion.next_action()? { match action { RecvAction::Send(addr, buf) => { udp.send(addr, buf).await?; } 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: &[descriptor::CLUSTER, 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)? { if ctx.send()? { udp.send(ctx.tx.peer, ctx.tx.as_slice()).await?; } } } } } if let Some(data) = matter.store_fabrics(&mut buf)? { psm.store("fabrics", data)?; } if let Some(data) = matter.store_acls(&mut buf)? { psm.store("acls", data)?; } } #[allow(unreachable_code)] Ok::<_, matter::error::Error>(()) })?; Ok::<_, matter::error::Error>(()) } fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a { root_endpoint::handler(0, dev_att, matter) .chain( 1, descriptor::ID, descriptor::DescriptorCluster::new(*matter.borrow()), ) .chain( 1, cluster_on_off::ID, cluster_on_off::OnOffCluster::new(*matter.borrow()), ) }