diff --git a/Cargo.toml b/Cargo.toml index 4ff9cac..d644105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,9 @@ debug = true opt-level = "z" [features] -default = ["std"] +default = ["std", "async-io-mini"] std = ["rs-matter/std", "esp-idf-svc/std"] -examples = ["std", "async-io", "esp-idf-svc/binstart", "esp-idf-svc/critical-section"] # Enable only when building the examples +examples = ["std", "async-io-mini", "esp-idf-svc/binstart", "esp-idf-svc/critical-section"] # Enable only when building the examples [dependencies] log = { version = "0.4", default-features = false } diff --git a/src/stack.rs b/src/stack.rs index 4fd8468..c137572 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,5 +1,3 @@ -use core::borrow::Borrow; -use core::cell::RefCell; use core::fmt::Write as _; use core::net::{Ipv6Addr, SocketAddr, SocketAddrV6}; use core::pin::pin; @@ -16,38 +14,19 @@ use esp_idf_svc::nvs::{EspNvs, EspNvsPartition, NvsPartitionId}; use log::info; -use rs_matter::acl::AclMgr; -use rs_matter::data_model::cluster_basic_information::{self, BasicInfoCluster, BasicInfoConfig}; +use rs_matter::data_model::cluster_basic_information::BasicInfoConfig; use rs_matter::data_model::core::IMBuffer; -use rs_matter::data_model::objects::{AsyncHandler, AsyncMetadata, EmptyHandler, HandlerCompat}; -use rs_matter::data_model::sdm::admin_commissioning::AdminCommCluster; +use rs_matter::data_model::objects::{AsyncHandler, AsyncMetadata}; use rs_matter::data_model::sdm::dev_att::DevAttDataFetcher; -use rs_matter::data_model::sdm::failsafe::FailSafe; -use rs_matter::data_model::sdm::general_commissioning::GenCommCluster; -use rs_matter::data_model::sdm::general_diagnostics::GenDiagCluster; -use rs_matter::data_model::sdm::group_key_management::GrpKeyMgmtCluster; -use rs_matter::data_model::sdm::noc::NocCluster; -use rs_matter::data_model::sdm::{ - admin_commissioning, general_commissioning, general_diagnostics, group_key_management, noc, - nw_commissioning, -}; use rs_matter::data_model::subscriptions::Subscriptions; -use rs_matter::data_model::system_model::access_control::AccessControlCluster; -use rs_matter::data_model::system_model::descriptor::DescriptorCluster; -use rs_matter::data_model::system_model::{access_control, descriptor}; use rs_matter::error::ErrorCode; -use rs_matter::fabric::FabricMgr; -use rs_matter::mdns::Mdns; use rs_matter::pairing::DiscoveryCapabilities; use rs_matter::respond::DefaultResponder; -use rs_matter::secure_channel::pake::PaseMgr; use rs_matter::transport::network::{NetworkReceive, NetworkSend}; use rs_matter::utils::buf::{BufferAccess, PooledBuffers}; -use rs_matter::utils::epoch::Epoch; -use rs_matter::utils::rand::Rand; use rs_matter::utils::select::Coalesce; use rs_matter::utils::signal::Signal; -use rs_matter::{handler_chain_type, CommissioningData, Matter, MATTER_PORT}; +use rs_matter::{CommissioningData, Matter, MATTER_PORT}; use crate::error::Error; use crate::multicast::{join_multicast_v4, join_multicast_v6}; @@ -409,123 +388,6 @@ where } } -/// A type representing the type of the root (Endpoint 0) handler -/// which is generic over the operational transport clusters (i.e. Ethernet, Wifi or Thread) -pub type RootEndpointHandler<'a, NWCOMM, NWDIAG> = handler_chain_type!( - NWCOMM, - NWDIAG, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat, - HandlerCompat -); - -/// A utility function to instantiate the root (Endpoint 0) handler. -/// Besides a reference to the main `Matter` object, this function -/// needs user-supplied implementations of the network commissioning -/// and network diagnostics clusters. -pub fn handler<'a, NWCOMM, NWDIAG, T>( - matter: &'a T, - nwcomm: NWCOMM, - nwdiag_id: u32, - nwdiag: NWDIAG, -) -> RootEndpointHandler<'a, NWCOMM, NWDIAG> -where - T: Borrow> - + Borrow - + Borrow> - + Borrow> - + Borrow> - + Borrow> - + Borrow - + Borrow - + Borrow - + 'a, -{ - wrap( - 0, - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - *matter.borrow(), - *matter.borrow(), - nwcomm, - nwdiag_id, - nwdiag, - ) -} - -#[allow(clippy::too_many_arguments)] -fn wrap<'a, NWCOMM, NWDIAG>( - endpoint_id: u16, - basic_info: &'a BasicInfoConfig<'a>, - dev_att: &'a dyn DevAttDataFetcher, - pase: &'a RefCell, - fabric: &'a RefCell, - acl: &'a RefCell, - failsafe: &'a RefCell, - mdns: &'a dyn Mdns, - epoch: Epoch, - rand: Rand, - nwcomm: NWCOMM, - nwdiag_id: u32, - nwdiag: NWDIAG, -) -> RootEndpointHandler<'a, NWCOMM, NWDIAG> { - EmptyHandler - .chain( - endpoint_id, - group_key_management::ID, - HandlerCompat(GrpKeyMgmtCluster::new(rand)), - ) - .chain( - endpoint_id, - general_diagnostics::ID, - HandlerCompat(GenDiagCluster::new(rand)), - ) - .chain( - endpoint_id, - access_control::ID, - HandlerCompat(AccessControlCluster::new(acl, rand)), - ) - .chain( - endpoint_id, - noc::ID, - HandlerCompat(NocCluster::new( - dev_att, fabric, acl, failsafe, mdns, epoch, rand, - )), - ) - .chain( - endpoint_id, - admin_commissioning::ID, - HandlerCompat(AdminCommCluster::new(pase, mdns, rand)), - ) - .chain( - endpoint_id, - general_commissioning::ID, - HandlerCompat(GenCommCluster::new(failsafe, false, rand)), - ) - .chain( - endpoint_id, - cluster_basic_information::ID, - HandlerCompat(BasicInfoCluster::new(basic_info, rand)), - ) - .chain( - endpoint_id, - descriptor::ID, - HandlerCompat(DescriptorCluster::new(rand)), - ) - .chain(endpoint_id, nwdiag_id, nwdiag) - .chain(endpoint_id, nw_commissioning::ID, nwcomm) -} - /// A utility function to initialize the `async-io` Reactor which is /// used for IP-based networks (UDP and TCP). /// diff --git a/src/stack/eth.rs b/src/stack/eth.rs index f992fc9..ff7065d 100644 --- a/src/stack/eth.rs +++ b/src/stack/eth.rs @@ -5,23 +5,18 @@ use esp_idf_svc::nvs::{EspNvsPartition, NvsPartitionId}; use log::info; -use rs_matter::data_model::cluster_basic_information; -use rs_matter::data_model::objects::{ - AsyncHandler, AsyncMetadata, Cluster, Endpoint, HandlerCompat, -}; +use rs_matter::data_model::objects::{AsyncHandler, AsyncMetadata, Endpoint, HandlerCompat}; +use rs_matter::data_model::root_endpoint; +use rs_matter::data_model::root_endpoint::{handler, OperNwType, RootEndpointHandler}; use rs_matter::data_model::sdm::ethernet_nw_diagnostics::EthNwDiagCluster; use rs_matter::data_model::sdm::nw_commissioning::EthNwCommCluster; -use rs_matter::data_model::sdm::{ - admin_commissioning, ethernet_nw_diagnostics, general_commissioning, general_diagnostics, - group_key_management, noc, nw_commissioning, -}; -use rs_matter::data_model::system_model::{access_control, descriptor}; +use rs_matter::data_model::sdm::{ethernet_nw_diagnostics, nw_commissioning}; use rs_matter::pairing::DiscoveryCapabilities; use rs_matter::CommissioningData; use crate::error::Error; use crate::netif::NetifAccess; -use crate::{handler, MatterStack, Network, RootEndpointHandler}; +use crate::{MatterStack, Network}; /// An implementation of the `Network` trait for Ethernet. /// @@ -46,17 +41,14 @@ impl<'a> MatterStack<'a, Eth> { /// Return a metadata for the root (Endpoint 0) of the Matter Node /// configured for Ethernet network. pub const fn root_metadata() -> Endpoint<'static> { - Endpoint { - id: 0, - device_type: rs_matter::data_model::device_types::DEV_TYPE_ROOT_NODE, - clusters: &CLUSTERS, - } + root_endpoint::endpoint(0, OperNwType::Ethernet) } /// Return a handler for the root (Endpoint 0) of the Matter Node /// configured for Ethernet network. pub fn root_handler(&self) -> EthRootEndpointHandler<'_> { handler( + 0, self.matter(), HandlerCompat(EthNwCommCluster::new(*self.matter().borrow())), ethernet_nw_diagnostics::ID, @@ -106,16 +98,3 @@ pub type EthRootEndpointHandler<'a> = RootEndpointHandler< HandlerCompat, HandlerCompat, >; - -const CLUSTERS: [Cluster<'static>; 10] = [ - descriptor::CLUSTER, - cluster_basic_information::CLUSTER, - general_commissioning::CLUSTER, - nw_commissioning::ETH_CLUSTER, - admin_commissioning::CLUSTER, - noc::CLUSTER, - access_control::CLUSTER, - general_diagnostics::CLUSTER, - ethernet_nw_diagnostics::CLUSTER, - group_key_management::CLUSTER, -]; diff --git a/src/stack/wifible.rs b/src/stack/wifible.rs index bf26b3f..1ebaded 100644 --- a/src/stack/wifible.rs +++ b/src/stack/wifible.rs @@ -29,16 +29,14 @@ use esp_idf_svc::wifi::{AsyncWifi, EspWifi}; use log::info; -use rs_matter::data_model::cluster_basic_information; -use rs_matter::data_model::objects::{ - AsyncHandler, AsyncMetadata, Cluster, Endpoint, HandlerCompat, -}; +use rs_matter::data_model::objects::{AsyncHandler, AsyncMetadata, Endpoint, HandlerCompat}; +use rs_matter::data_model::root_endpoint; +use rs_matter::data_model::root_endpoint::{handler, OperNwType, RootEndpointHandler}; use rs_matter::data_model::sdm::failsafe::FailSafe; -use rs_matter::data_model::sdm::{ - admin_commissioning, general_commissioning, general_diagnostics, group_key_management, noc, - nw_commissioning, +use rs_matter::data_model::sdm::wifi_nw_diagnostics; +use rs_matter::data_model::sdm::wifi_nw_diagnostics::{ + WiFiSecurity, WiFiVersion, WifiNwDiagCluster, WifiNwDiagData, }; -use rs_matter::data_model::system_model::{access_control, descriptor}; use rs_matter::pairing::DiscoveryCapabilities; use rs_matter::transport::network::btp::{Btp, BtpContext}; use rs_matter::utils::select::Coalesce; @@ -47,8 +45,8 @@ use rs_matter::CommissioningData; use crate::ble::{BtpGattContext, BtpGattPeripheral}; use crate::error::Error; use crate::wifi::mgmt::WifiManager; -use crate::wifi::{comm, diag, WifiContext}; -use crate::{handler, MatterStack, Network, RootEndpointHandler}; +use crate::wifi::{comm, WifiContext}; +use crate::{MatterStack, Network}; const MAX_WIFI_NETWORKS: usize = 2; const GATTS_APP_ID: u16 = 0; @@ -87,21 +85,28 @@ impl<'a> MatterStack<'a, WifiBle> { /// Return a metadata for the root (Endpoint 0) of the Matter Node /// configured for BLE+Wifi network. pub const fn root_metadata() -> Endpoint<'static> { - Endpoint { - id: 0, - device_type: rs_matter::data_model::device_types::DEV_TYPE_ROOT_NODE, - clusters: &CLUSTERS, - } + root_endpoint::endpoint(0, OperNwType::Wifi) } /// Return a handler for the root (Endpoint 0) of the Matter Node /// configured for BLE+Wifi network. pub fn root_handler(&self) -> WifiBleRootEndpointHandler<'_> { handler( + 0, self.matter(), comm::WifiNwCommCluster::new(*self.matter().borrow(), &self.network.wifi_context), - diag::ID, - HandlerCompat(diag::WifiNwDiagCluster::new(*self.matter().borrow())), + wifi_nw_diagnostics::ID, + HandlerCompat(WifiNwDiagCluster::new( + *self.matter().borrow(), + // TODO: Update with actual information + WifiNwDiagData { + bssid: [0; 6], + security_type: WiFiSecurity::Unspecified, + wifi_version: WiFiVersion::B, + channel_number: 20, + rssi: 0, + }, + )), ) } @@ -262,18 +267,5 @@ impl<'a> MatterStack<'a, WifiBle> { pub type WifiBleRootEndpointHandler<'a> = RootEndpointHandler< 'a, comm::WifiNwCommCluster<'a, MAX_WIFI_NETWORKS, NoopRawMutex>, - HandlerCompat, + HandlerCompat, >; - -const CLUSTERS: [Cluster<'static>; 10] = [ - descriptor::CLUSTER, - cluster_basic_information::CLUSTER, - general_commissioning::CLUSTER, - nw_commissioning::WIFI_CLUSTER, - admin_commissioning::CLUSTER, - noc::CLUSTER, - access_control::CLUSTER, - general_diagnostics::CLUSTER, - diag::CLUSTER, - group_key_management::CLUSTER, -]; diff --git a/src/wifi.rs b/src/wifi.rs index b2b24f4..05a16ac 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -12,7 +12,6 @@ use rs_matter::utils::notification::Notification; use rs_matter::utils::writebuf::WriteBuf; pub mod comm; -pub mod diag; pub mod mgmt; #[derive(Debug, Clone, ToTLV, FromTLV)] diff --git a/src/wifi/diag.rs b/src/wifi/diag.rs deleted file mode 100644 index f8334b4..0000000 --- a/src/wifi/diag.rs +++ /dev/null @@ -1,203 +0,0 @@ -use rs_matter::{ - attribute_enum, command_enum, - data_model::objects::*, - error::{Error, ErrorCode}, - tlv::{TLVElement, TagType}, - transport::exchange::Exchange, - utils::rand::Rand, -}; - -use log::info; - -use rs_matter_macros::{FromTLV, ToTLV}; -use strum::{EnumDiscriminants, FromRepr}; - -pub const ID: u32 = 0x0036; - -#[derive(FromRepr, EnumDiscriminants)] -#[repr(u16)] -pub enum Attributes { - Bssid = 0x00, - SecurityType(AttrType) = 0x01, - WifiVersion(AttrType) = 0x02, - ChannelNumber(AttrType) = 0x03, - Rssi(AttrType) = 0x04, - BeaconLostCount(AttrType) = 0x05, - BeaconRxCount(AttrType) = 0x06, - PacketMulticastRxCount(AttrType) = 0x07, - PacketMulticastTxCount(AttrType) = 0x08, - PacketUnicastRxCount(AttrType) = 0x09, - PacketUnicastTxCount(AttrType) = 0x0a, - CurrentMaxRate(AttrType) = 0x0b, - OverrunCount(AttrType) = 0x0c, -} - -attribute_enum!(Attributes); - -#[derive(FromRepr, EnumDiscriminants)] -#[repr(u32)] -pub enum Commands { - ResetCounts = 0x0, -} - -command_enum!(Commands); - -pub const CLUSTER: Cluster<'static> = Cluster { - id: ID as _, - feature_map: 0, - attributes: &[ - FEATURE_MAP, - ATTRIBUTE_LIST, - Attribute::new( - AttributesDiscriminants::Bssid as u16, - Access::RV, - Quality::NONE, - ), - Attribute::new( - AttributesDiscriminants::SecurityType as u16, - Access::RV, - Quality::FIXED, - ), - Attribute::new( - AttributesDiscriminants::WifiVersion as u16, - Access::RV, - Quality::FIXED, - ), - Attribute::new( - AttributesDiscriminants::ChannelNumber as u16, - Access::RV, - Quality::FIXED, - ), - Attribute::new( - AttributesDiscriminants::Rssi as u16, - Access::RV, - Quality::FIXED, - ), - ], - commands: &[CommandsDiscriminants::ResetCounts as _], -}; - -#[derive(Debug, Copy, Clone, Eq, PartialEq, FromTLV, ToTLV, FromRepr)] -#[repr(u8)] -pub enum WiFiSecurity { - Unspecified = 0, - Unencrypted = 1, - Wep = 2, - WpaPersonal = 3, - Wpa2Personal = 4, - Wpa3Personal = 5, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, FromTLV, ToTLV, FromRepr)] -#[repr(u8)] -pub enum WiFiVersion { - A = 0, - B = 1, - G = 2, - N = 3, - AC = 4, - AX = 5, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, FromTLV, ToTLV, FromRepr)] -#[repr(u8)] -pub enum AssociationFailure { - Unknown = 0, - AssociationFailed = 1, - AuthenticationFailed = 2, - SsidNotFound = 3, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, FromTLV, ToTLV, FromRepr)] -#[repr(u8)] -pub enum ConnectionStatus { - Connected = 0, - NotConnected = 1, -} - -/// A cluster implementing the Matter Wifi Diagnostics Cluster. -pub struct WifiNwDiagCluster { - data_ver: Dataver, -} - -impl WifiNwDiagCluster { - /// Create a new instance. - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - } - } - - /// Read the value of an attribute. - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { - if attr.is_system() { - CLUSTER.read(attr.attr_id, writer) - } else { - // TODO - match attr.attr_id.try_into()? { - Attributes::Bssid => writer.str8(TagType::Anonymous, &[0; 6]), - Attributes::SecurityType(codec) => { - codec.encode(writer, WiFiSecurity::Unspecified) - } - Attributes::WifiVersion(codec) => codec.encode(writer, WiFiVersion::B), - Attributes::ChannelNumber(codec) => codec.encode(writer, 20), - Attributes::Rssi(codec) => codec.encode(writer, 0), - _ => Err(ErrorCode::AttributeNotFound.into()), - } - } - } else { - Ok(()) - } - } - - /// Write the value of an attribute. - pub fn write(&self, _attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - let _data = data.with_dataver(self.data_ver.get())?; - - self.data_ver.changed(); - - Ok(()) - } - - /// Invoke a command. - pub fn invoke( - &self, - _exchange: &Exchange, - cmd: &CmdDetails, - _data: &TLVElement, - _encoder: CmdDataEncoder, - ) -> Result<(), Error> { - match cmd.cmd_id.try_into()? { - Commands::ResetCounts => { - info!("ResetCounts: Not yet supported"); - } - } - - self.data_ver.changed(); - - Ok(()) - } -} - -impl Handler for WifiNwDiagCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - WifiNwDiagCluster::read(self, attr, encoder) - } - - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - WifiNwDiagCluster::write(self, attr, data) - } - - fn invoke( - &self, - exchange: &Exchange, - cmd: &CmdDetails, - data: &TLVElement, - encoder: CmdDataEncoder, - ) -> Result<(), Error> { - WifiNwDiagCluster::invoke(self, exchange, cmd, data, encoder) - } -} - -impl NonBlockingHandler for WifiNwDiagCluster {}