Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/src/bin/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ fn main() -> Result<(), Error> {
let on_off_handler_ep2 = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
2,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(false),
);
let on_off_handler_ep3 = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
3,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(false),
);

// Create the Data Model instance
Expand Down
87 changes: 11 additions & 76 deletions examples/src/bin/chip_tool_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
//! A dedicated Matter device for ConnectedHomeIP YAML integration tests.
//! Implements On/Off and Unit Testing clusters over Ethernet.

use core::cell::Cell;
use core::pin::pin;

use std::net::UdpSocket;
Expand All @@ -36,13 +35,11 @@ use log::info;
use rs_matter::dm::clusters::basic_info::{
BasicInfoConfig, ColorEnum, ProductAppearance, ProductFinishEnum,
};
use rs_matter::dm::clusters::decl::on_off as on_off_cluster;
use rs_matter::dm::clusters::desc::{self, ClusterHandler as _};
use rs_matter::dm::clusters::level_control::LevelControlHooks;
use rs_matter::dm::clusters::net_comm::NetworkType;
use rs_matter::dm::clusters::on_off::{
self, EffectVariantEnum, OnOffHandler, OnOffHooks, StartUpOnOffEnum,
};
use rs_matter::dm::clusters::on_off::test::TestOnOffDeviceLogic;
use rs_matter::dm::clusters::on_off::{self, OnOffHandler, OnOffHooks};
use rs_matter::dm::clusters::unit_testing::{
ClusterHandler as _, UnitTestingHandler, UnitTestingHandlerData,
};
Expand All @@ -52,20 +49,18 @@ use rs_matter::dm::endpoints;
use rs_matter::dm::networks::unix::UnixNetifs;
use rs_matter::dm::subscriptions::DefaultSubscriptions;
use rs_matter::dm::{
Async, AsyncHandler, AsyncMetadata, Cluster, DataModel, Dataver, EmptyHandler, Endpoint,
EpClMatcher, Node,
Async, AsyncHandler, AsyncMetadata, DataModel, Dataver, EmptyHandler, Endpoint, EpClMatcher,
Node,
};
use rs_matter::error::Error;
use rs_matter::pairing::DiscoveryCapabilities;
use rs_matter::persist::{Psm, NO_NETWORKS};
use rs_matter::respond::DefaultResponder;
use rs_matter::tlv::Nullable;
use rs_matter::transport::MATTER_SOCKET_BIND_ADDR;
use rs_matter::utils::cell::RefCell;
use rs_matter::utils::init::InitMaybeUninit;
use rs_matter::utils::select::Coalesce;
use rs_matter::utils::storage::pooled::PooledBuffers;
use rs_matter::with;
use rs_matter::{clusters, devices, Matter, MATTER_PORT};

use static_cell::StaticCell;
Expand Down Expand Up @@ -136,8 +131,11 @@ fn main() -> Result<(), Error> {
.init_with(DefaultSubscriptions::init());

// Our on-off cluster
let on_off_handler =
OnOffHandler::new_standalone(Dataver::new_rand(matter.rand()), 1, OnOffDeviceLogic::new());
let on_off_handler = OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
1,
TestOnOffDeviceLogic::new(false),
);

// Our unit testing cluster data
let unit_testing_data = UNIT_TESTING_DATA
Expand Down Expand Up @@ -247,7 +245,7 @@ const NODE: Node<'static> = Node {
device_types: devices!(DEV_TYPE_ON_OFF_LIGHT),
clusters: clusters!(
desc::DescHandler::CLUSTER,
OnOffDeviceLogic::CLUSTER,
TestOnOffDeviceLogic::CLUSTER,
UnitTestingHandler::CLUSTER
),
},
Expand Down Expand Up @@ -276,7 +274,7 @@ fn dm_handler<'a, OH: OnOffHooks, LH: LevelControlHooks>(
Async(desc::DescHandler::new(Dataver::new_rand(matter.rand())).adapt()),
)
.chain(
EpClMatcher::new(Some(1), Some(OnOffDeviceLogic::CLUSTER.id)),
EpClMatcher::new(Some(1), Some(TestOnOffDeviceLogic::CLUSTER.id)),
on_off::HandlerAsyncAdaptor(on_off),
)
.chain(
Expand All @@ -293,66 +291,3 @@ fn dm_handler<'a, OH: OnOffHooks, LH: LevelControlHooks>(
),
)
}

// Implementing the OnOff business logic

#[derive(Default)]
pub struct OnOffDeviceLogic {
on_off: Cell<bool>,
start_up_on_off: Cell<Option<StartUpOnOffEnum>>,
}

impl OnOffDeviceLogic {
pub fn new() -> Self {
Self {
on_off: Cell::new(false),
start_up_on_off: Cell::new(None),
}
}
}

impl OnOffHooks for OnOffDeviceLogic {
const CLUSTER: Cluster<'static> = on_off_cluster::FULL_CLUSTER
.with_revision(6)
.with_features(on_off_cluster::Feature::LIGHTING.bits())
.with_attrs(with!(
required;
on_off_cluster::AttributeId::OnOff
| on_off_cluster::AttributeId::GlobalSceneControl
| on_off_cluster::AttributeId::OnTime
| on_off_cluster::AttributeId::OffWaitTime
| on_off_cluster::AttributeId::StartUpOnOff
))
.with_cmds(with!(
on_off_cluster::CommandId::Off
| on_off_cluster::CommandId::On
| on_off_cluster::CommandId::Toggle
| on_off_cluster::CommandId::OffWithEffect
| on_off_cluster::CommandId::OnWithRecallGlobalScene
| on_off_cluster::CommandId::OnWithTimedOff
));

fn on_off(&self) -> bool {
self.on_off.get()
}

fn set_on_off(&self, on: bool) {
self.on_off.set(on);
}

fn start_up_on_off(&self) -> Nullable<StartUpOnOffEnum> {
match self.start_up_on_off.get() {
Some(value) => Nullable::some(value),
None => Nullable::none(),
}
}

fn set_start_up_on_off(&self, value: Nullable<StartUpOnOffEnum>) -> Result<(), Error> {
self.start_up_on_off.set(value.into_option());
Ok(())
}

async fn handle_off_with_effect(&self, _effect: EffectVariantEnum) {
// no effect
}
}
16 changes: 0 additions & 16 deletions examples/src/bin/dimmable_light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ use std::path::PathBuf;

use embassy_futures::select::{select3, select4};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
#[cfg(not(feature = "chip-test"))]
use embassy_time::{Duration, Timer};

use async_signal::{Signal, Signals};
use log::{error, info, trace};
Expand All @@ -43,8 +41,6 @@ use rs_matter::dm::clusters::decl::on_off as on_off_cluster;
use rs_matter::dm::clusters::desc::{self, ClusterHandler as _};
use rs_matter::dm::clusters::level_control::{self, LevelControlHooks};
use rs_matter::dm::clusters::net_comm::NetworkType;
#[cfg(not(feature = "chip-test"))]
use rs_matter::dm::clusters::on_off::OutOfBandMessage;
use rs_matter::dm::clusters::on_off::{self, OnOffHooks, StartUpOnOffEnum};
use rs_matter::dm::devices::test::{TEST_DEV_ATT, TEST_DEV_COMM, TEST_DEV_DET};
use rs_matter::dm::devices::DEV_TYPE_DIMMABLE_LIGHT;
Expand Down Expand Up @@ -536,16 +532,4 @@ impl OnOffHooks for OnOffDeviceLogic {
async fn handle_off_with_effect(&self, _effect: on_off::EffectVariantEnum) {
// no effect
}

#[cfg(not(feature = "chip-test"))]
async fn run<F: Fn(OutOfBandMessage)>(&self, notify: F) {
loop {
// In a real example we wait for physical interaction.
Timer::after(Duration::from_secs(5)).await;
match self.on_off() {
true => notify(OutOfBandMessage::Off),
false => notify(OutOfBandMessage::On),
}
}
}
}
2 changes: 1 addition & 1 deletion examples/src/bin/media_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn main() -> Result<(), Error> {
let on_off_handler = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
1,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(false),
);

// Create the Data Model instance
Expand Down
20 changes: 3 additions & 17 deletions examples/src/bin/onoff_light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ use core::pin::pin;

use std::net::UdpSocket;

use embassy_futures::select::{select3, select4};
use embassy_futures::select::{select, select4};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_time::{Duration, Timer};

use log::info;

Expand Down Expand Up @@ -116,7 +115,7 @@ fn run() -> Result<(), Error> {
let on_off_handler = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
1,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(true),
);

// Create the Data Model instance
Expand All @@ -143,19 +142,6 @@ fn run() -> Result<(), Error> {
// Run the background job of the data model
let mut dm_job = pin!(dm.run());

// This is a sample code that simulates state changes triggered by the HAL
// Changes will be properly communicated to the Matter controllers and other Matter apps (i.e. Google Home, Alexa), thanks to subscriptions
let mut device = pin!(async {
loop {
Timer::after(Duration::from_secs(5)).await;

on_off_handler.set_on_off(!on_off_handler.on_off());
subscriptions.notify_cluster_changed(1, TestOnOffDeviceLogic::CLUSTER.id);

info!("Lamp toggled");
}
});

// Create, load and run the persister
let socket = async_io::Async::<UdpSocket>::bind(MATTER_SOCKET_BIND_ADDR)?;

Expand Down Expand Up @@ -188,7 +174,7 @@ fn run() -> Result<(), Error> {
&mut transport,
&mut mdns,
&mut persist,
select3(&mut respond, &mut device, &mut dm_job).coalesce(),
select(&mut respond, &mut dm_job).coalesce(),
);

// Run with a simple `block_on`. Any local executor would do.
Expand Down
22 changes: 4 additions & 18 deletions examples/src/bin/onoff_light_bt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ use core::pin::pin;

use std::net::UdpSocket;

use embassy_futures::select::{select, select3, select4};
use embassy_futures::select::{select, select4};

use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_time::{Duration, Timer};
use log::{info, warn};

use rs_matter::dm::clusters::desc::{self, ClusterHandler as _};
Expand Down Expand Up @@ -135,7 +134,7 @@ fn run<N: NetCtl + WifiDiag>(connection: &Connection, net_ctl: N) -> Result<(),
let on_off_handler = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(matter.rand()),
1,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(true),
);

// A storage for the Wifi networks
Expand Down Expand Up @@ -165,19 +164,6 @@ fn run<N: NetCtl + WifiDiag>(connection: &Connection, net_ctl: N) -> Result<(),
// Run the background job of the data model
let mut dm_job = pin!(dm.run());

// This is a sample code that simulates state changes triggered by the HAL
// Changes will be properly communicated to the Matter controllers and other Matter apps (i.e. Google Home, Alexa), thanks to subscriptions
let mut device = pin!(async {
loop {
Timer::after(Duration::from_secs(5)).await;

on_off_handler.set_on_off(!on_off_handler.on_off());
subscriptions.notify_cluster_changed(1, TestOnOffDeviceLogic::CLUSTER.id);

info!("Lamp toggled");
}
});

// Create, load and run the persister
let mut psm: Psm<4096> = Psm::new();
let path = std::env::temp_dir().join("rs-matter");
Expand Down Expand Up @@ -207,7 +193,7 @@ fn run<N: NetCtl + WifiDiag>(connection: &Connection, net_ctl: N) -> Result<(),
&mut transport,
&mut bluetooth,
select(&mut wifi_prov_task, &mut persist).coalesce(),
select3(&mut respond, &mut device, &mut dm_job).coalesce(),
select(&mut respond, &mut dm_job).coalesce(),
);

// Run with a simple `block_on`. Any local executor would do.
Expand All @@ -227,7 +213,7 @@ fn run<N: NetCtl + WifiDiag>(connection: &Connection, net_ctl: N) -> Result<(),
&mut transport,
&mut mdns,
&mut persist,
select3(&mut respond, &mut device, &mut dm_job).coalesce(),
select(&mut respond, &mut dm_job).coalesce(),
);

// Run with a simple `block_on`. Any local executor would do.
Expand Down
2 changes: 1 addition & 1 deletion examples/src/bin/speaker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn main() -> Result<(), Error> {
let on_off_handler = on_off::OnOffHandler::new(
Dataver::new_rand(matter.rand()),
1,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(true),
);

// LevelControl cluster setup
Expand Down
31 changes: 29 additions & 2 deletions rs-matter/src/dm/clusters/on_off.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,12 +924,16 @@ impl LevelControlHooks for NoLevelControl {
}

pub mod test {
use embassy_time::{Duration, Timer};

use crate::error::Error;
use crate::tlv::Nullable;
use core::cell::Cell;

use crate::dm::clusters::decl::on_off as on_off_cluster;
use crate::dm::clusters::on_off::{EffectVariantEnum, OnOffHooks, StartUpOnOffEnum};
use crate::dm::clusters::on_off::{
EffectVariantEnum, OnOffHooks, OutOfBandMessage, StartUpOnOffEnum,
};
use crate::dm::Cluster;

use crate::with;
Expand All @@ -939,13 +943,15 @@ pub mod test {
pub struct TestOnOffDeviceLogic {
on_off: Cell<bool>,
start_up_on_off: Cell<Option<StartUpOnOffEnum>>,
toggle_periodically: bool,
}

impl TestOnOffDeviceLogic {
pub const fn new() -> Self {
pub const fn new(toggle_periodically: bool) -> Self {
Self {
on_off: Cell::new(false),
start_up_on_off: Cell::new(None),
toggle_periodically,
}
}
}
Expand Down Expand Up @@ -986,5 +992,26 @@ pub mod test {
async fn handle_off_with_effect(&self, _effect: EffectVariantEnum) {
// no effect
}

async fn run<F: Fn(OutOfBandMessage)>(&self, notify: F) {
if self.toggle_periodically {
loop {
// In a real example we wait for physical interaction.
Timer::after(Duration::from_secs(5)).await;
match self.on_off() {
true => {
info!("Emulation: out of band switch off");
notify(OutOfBandMessage::Off);
}
false => {
info!("Emulation: out of band switch on");
notify(OutOfBandMessage::On);
}
}
}
} else {
core::future::pending::<()>().await
}
}
}
}
2 changes: 1 addition & 1 deletion rs-matter/tests/common/e2e/im/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl<'a> E2eRunner {
let on_off_handler = on_off::OnOffHandler::new_standalone(
Dataver::new_rand(self.matter.rand()),
1,
TestOnOffDeviceLogic::new(),
TestOnOffDeviceLogic::new(false),
);

E2eTestHandler::new(&self.matter, on_off_handler)
Expand Down