From 33935332bc8e321d85978d30ef97ed862ff56c73 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Mon, 25 Jul 2022 11:36:55 -0700 Subject: [PATCH] Add capability to adjust the state of the the switch position (#21144) --- .../linux/AllClustersCommandDelegate.cpp | 208 +++++++++++------- .../linux/AllClustersCommandDelegate.h | 41 +++- examples/all-clusters-app/linux/BUILD.gn | 1 + examples/all-clusters-app/linux/README.md | 24 +- .../all-clusters-app/linux/main-common.cpp | 2 +- examples/platform/linux/NamedPipeCommands.cpp | 2 +- examples/platform/linux/NamedPipeCommands.h | 4 +- 7 files changed, 184 insertions(+), 98 deletions(-) diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp index 89d9761cab1921..3bdc63319c972d 100644 --- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp @@ -32,82 +32,102 @@ using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::DeviceLayer; -void AllClustersCommandDelegate::OnEventCommandReceived(const char * command) +void AllClustersCommandDelegate::OnEventCommandReceived(const char * json) { - mCurrentCommand.assign(command); + Json::Reader reader; - DeviceLayer::PlatformMgr().ScheduleWork(HandleEventCommand, reinterpret_cast(this)); + if (!reader.parse(json, mJsonValue)) + { + ChipLogError(NotSpecified, "Error parsing JSON with error %s:", reader.getFormattedErrorMessages().c_str()); + } + else + { + DeviceLayer::PlatformMgr().ScheduleWork(HandleEventCommand, reinterpret_cast(this)); + } } void AllClustersCommandDelegate::HandleEventCommand(intptr_t context) { auto * self = reinterpret_cast(context); - if (self->mCurrentCommand == "SoftwareFault") + VerifyOrReturn(!self->mJsonValue.empty(), ChipLogError(NotSpecified, "Invalid JSON event command received")); + + std::string name = self->mJsonValue["Name"].asString(); + + if (name == "SoftwareFault") { self->OnSoftwareFaultEventHandler(Clusters::SoftwareDiagnostics::Events::SoftwareFault::Id); } - else if (self->mCurrentCommand == "HardwareFaultChange") + else if (name == "HardwareFaultChange") { self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id); } - else if (self->mCurrentCommand == "RadioFaultChange") + else if (name == "RadioFaultChange") { self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id); } - else if (self->mCurrentCommand == "NetworkFaultChange") + else if (name == "NetworkFaultChange") { self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id); } - else if (self->mCurrentCommand == "SwitchLatched") + else if (name == "SwitchLatched") { - self->OnSwitchEventHandler(Clusters::Switch::Events::SwitchLatched::Id); + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchLatchedHandler(newPosition); } - else if (self->mCurrentCommand == "InitialPress") + else if (name == "InitialPress") { - self->OnSwitchEventHandler(Clusters::Switch::Events::InitialPress::Id); + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchInitialPressedHandler(newPosition); } - else if (self->mCurrentCommand == "LongPress") + else if (name == "LongPress") { - self->OnSwitchEventHandler(Clusters::Switch::Events::LongPress::Id); + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchLongPressedHandler(newPosition); } - else if (self->mCurrentCommand == "ShortRelease") + else if (name == "ShortRelease") { - self->OnSwitchEventHandler(Clusters::Switch::Events::ShortRelease::Id); + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + self->OnSwitchShortReleasedHandler(previousPosition); } - else if (self->mCurrentCommand == "LongRelease") + else if (name == "LongRelease") { - self->OnSwitchEventHandler(Clusters::Switch::Events::LongRelease::Id); + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + self->OnSwitchLongReleasedHandler(previousPosition); } - else if (self->mCurrentCommand == "MultiPressOngoing") + else if (name == "MultiPressOngoing") { - self->OnSwitchEventHandler(Clusters::Switch::Events::MultiPressOngoing::Id); + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + uint8_t count = static_cast(self->mJsonValue["CurrentNumberOfPressesCounted"].asUInt()); + self->OnSwitchMultiPressOngoingHandler(newPosition, count); } - else if (self->mCurrentCommand == "MultiPressComplete") + else if (name == "MultiPressComplete") { - self->OnSwitchEventHandler(Clusters::Switch::Events::MultiPressComplete::Id); + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + uint8_t count = static_cast(self->mJsonValue["TotalNumberOfPressesCounted"].asUInt()); + self->OnSwitchMultiPressOngoingHandler(previousPosition, count); } - else if (self->mCurrentCommand == "PowerOnReboot") + else if (name == "PowerOnReboot") { self->OnRebootSignalHandler(BootReasonType::kPowerOnReboot); } - else if (self->mCurrentCommand == "BrownOutReset") + else if (name == "BrownOutReset") { self->OnRebootSignalHandler(BootReasonType::kBrownOutReset); } - else if (self->mCurrentCommand == "SoftwareWatchdogReset") + else if (name == "SoftwareWatchdogReset") { self->OnRebootSignalHandler(BootReasonType::kSoftwareWatchdogReset); } - else if (self->mCurrentCommand == "HardwareWatchdogReset") + else if (name == "HardwareWatchdogReset") { self->OnRebootSignalHandler(BootReasonType::kHardwareWatchdogReset); } - else if (self->mCurrentCommand == "SoftwareUpdateCompleted") + else if (name == "SoftwareUpdateCompleted") { self->OnRebootSignalHandler(BootReasonType::kSoftwareUpdateCompleted); } - else if (self->mCurrentCommand == "SoftwareReset") + else if (name == "SoftwareReset") { self->OnRebootSignalHandler(BootReasonType::kSoftwareReset); } @@ -115,6 +135,8 @@ void AllClustersCommandDelegate::HandleEventCommand(intptr_t context) { ChipLogError(NotSpecified, "Unhandled command: Should never happens"); } + + self->mJsonValue.clear(); } bool AllClustersCommandDelegate::IsClusterPresentOnAnyEndpoint(ClusterId clusterId) @@ -220,57 +242,87 @@ void AllClustersCommandDelegate::OnSoftwareFaultEventHandler(uint32_t eventId) Clusters::SoftwareDiagnosticsServer::Instance().OnSoftwareFaultDetect(softwareFault); } -void AllClustersCommandDelegate::OnSwitchEventHandler(uint32_t eventId) +void AllClustersCommandDelegate::OnSwitchLatchedHandler(uint8_t newPosition) { - EndpointId endpoint = 1; - uint8_t newPosition = 20; - uint8_t previousPosition = 10; - uint8_t count = 3; + EndpointId endpoint = 1; - if (eventId == Clusters::Switch::Events::SwitchLatched::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::InitialPress::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::LongPress::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::ShortRelease::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); - } - else if (eventId == Clusters::Switch::Events::LongRelease::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); - } - else if (eventId == Clusters::Switch::Events::MultiPressOngoing::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); - } - else if (eventId == Clusters::Switch::Events::MultiPressComplete::Id) - { - EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); - VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); - Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, newPosition, count); - } - else - { - ChipLogError(NotSpecified, "Unknow event ID:%d", eventId); - } + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The latching switch is moved to a new position:%d", newPosition); + + Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); +} + +void AllClustersCommandDelegate::OnSwitchInitialPressedHandler(uint8_t newPosition) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch starts to be pressed:%d", newPosition); + + Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); +} + +void AllClustersCommandDelegate::OnSwitchLongPressedHandler(uint8_t newPosition) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed for a long time:%d", newPosition); + + Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); +} + +void AllClustersCommandDelegate::OnSwitchShortReleasedHandler(uint8_t previousPosition) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The the previous value of the CurrentPosition when the momentary switch has been released:%d", + previousPosition); + + Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); +} + +void AllClustersCommandDelegate::OnSwitchLongReleasedHandler(uint8_t previousPosition) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, + "The the previous value of the CurrentPosition when the momentary switch has been released after having been " + "pressed for a long time:%d", + previousPosition); + + Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); +} + +void AllClustersCommandDelegate::OnSwitchMultiPressOngoingHandler(uint8_t newPosition, uint8_t count) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed in a multi-press sequence:%d", + newPosition); + ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count); + + Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); +} + +void AllClustersCommandDelegate::OnSwitchMultiPressCompleteHandler(uint8_t previousPosition, uint8_t count) +{ + EndpointId endpoint = 1; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The previous position when the momentary switch has been pressed in a multi-press sequence:%d", + previousPosition); + ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count); + + Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, previousPosition, count); } diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.h b/examples/all-clusters-app/linux/AllClustersCommandDelegate.h index 74285343a0f809..5a55319ed674aa 100644 --- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.h +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.h @@ -20,15 +20,16 @@ #include "NamedPipeCommands.h" +#include #include class AllClustersCommandDelegate : public NamedPipeCommandDelegate { public: - void OnEventCommandReceived(const char * command) override; + void OnEventCommandReceived(const char * json) override; private: - std::string mCurrentCommand; + Json::Value mJsonValue; static void HandleEventCommand(intptr_t context); @@ -50,7 +51,39 @@ class AllClustersCommandDelegate : public NamedPipeCommandDelegate void OnSoftwareFaultEventHandler(uint32_t eventId); /** - * Should be called when a switch operation takes place on the Node. + * Should be called when the latching switch is moved to a new position. */ - void OnSwitchEventHandler(uint32_t eventId); + void OnSwitchLatchedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch starts to be pressed. + */ + void OnSwitchInitialPressedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch has been pressed for a "long" time. + */ + void OnSwitchLongPressedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch has been released. + */ + void OnSwitchShortReleasedHandler(uint8_t previousPosition); + + /** + * Should be called when the momentary switch has been released after having been pressed for a long time. + */ + void OnSwitchLongReleasedHandler(uint8_t previousPosition); + + /** + * Should be called to indicate how many times the momentary switch has been pressed in a multi-press + * sequence, during that sequence. + */ + void OnSwitchMultiPressOngoingHandler(uint8_t newPosition, uint8_t count); + + /** + * Should be called to indicate how many times the momentary switch has been pressed in a multi-press + * sequence, after it has been detected that the sequence has ended. + */ + void OnSwitchMultiPressCompleteHandler(uint8_t previousPosition, uint8_t count); }; diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index a53f45d11006d6..70fd87c6afd00b 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -36,6 +36,7 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/platform/linux:app-main", "${chip_root}/src/app/tests/suites/credentials:dac_provider", "${chip_root}/src/lib", + "${chip_root}/third_party/jsoncpp", ] include_dirs = diff --git a/examples/all-clusters-app/linux/README.md b/examples/all-clusters-app/linux/README.md index f92e6995ef4be1..e54d5ecc969214 100644 --- a/examples/all-clusters-app/linux/README.md +++ b/examples/all-clusters-app/linux/README.md @@ -81,7 +81,7 @@ all-cluster-app event named pipe /tmp/chip_all_clusters_fifo-. 1. Generate event `SoftwareFault` when a software fault takes place on the Node. ``` -$ echo SoftwareFault > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"SoftwareFault"}' > /tmp/chip_all_clusters_fifo- ``` #### Trigger `HardwareFault` events @@ -90,21 +90,21 @@ $ echo SoftwareFault > /tmp/chip_all_clusters_fifo- hardware faults currently detected by the Node. ``` -$ echo HardwareFaultChange > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"HardwareFaultChange"}' > /tmp/chip_all_clusters_fifo- ``` 2. Generate event `RadioFaultChange` to indicate a change in the set of radio faults currently detected by the Node. ``` -$ echo RadioFaultChange > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"RadioFaultChange"}' > /tmp/chip_all_clusters_fifo- ``` 3. Generate event `NetworkFaultChange` to indicate a change in the set of network faults currently detected by the Node. ``` -$ echo NetworkFaultChange > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"NetworkFaultChange"}' > /tmp/chip_all_clusters_fifo- ``` 4. Generate event `BootReason` to indicate the reason that caused the device to @@ -129,7 +129,7 @@ $ echo NetworkFaultChange > /tmp/chip_all_clusters_fifo- reboot. ``` -$ echo > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":""}' > /tmp/chip_all_clusters_fifo- ``` #### Trigger Switch events @@ -138,41 +138,41 @@ $ echo > /tmp/chip_all_clusters_fifo- position. ``` -$ echo SwitchLatched > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"SwitchLatched","NewPosition":3}' > /tmp/chip_all_clusters_fifo- ``` 2. Generate event `InitialPress`, when the momentary switch starts to be pressed. ``` -$ echo InitialPress > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"InitialPress","NewPosition":3}' > /tmp/chip_all_clusters_fifo- ``` 3. Generate event `LongPress`, when the momentary switch has been pressed for a "long" time. ``` -$ echo LongPress > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"LongPress","NewPosition":3}' > /tmp/chip_all_clusters_fifo- ``` 4. Generate event `ShortRelease`, when the momentary switch has been released. ``` -$ echo ShortRelease > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"ShortRelease","PreviousPosition":3}' > /tmp/chip_all_clusters_fifo- ``` 5. Generate event `LongRelease` when the momentary switch has been released and after having been pressed for a long time. ``` -$ echo LongRelease > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"LongRelease","PreviousPosition":3}' > /tmp/chip_all_clusters_fifo- ``` 6. Generate event `MultiPressOngoing` to indicate how many times the momentary switch has been pressed in a multi-press sequence, during that sequence. ``` -$ echo MultiPressOngoing > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"MultiPressOngoing","NewPosition":3,"CurrentNumberOfPressesCounted":4}' > /tmp/chip_all_clusters_fifo- ``` 7. Generate event `MultiPressComplete` to indicate how many times the momentary @@ -180,5 +180,5 @@ $ echo MultiPressOngoing > /tmp/chip_all_clusters_fifo- that the sequence has ended. ``` -$ echo MultiPressComplete > /tmp/chip_all_clusters_fifo- +$ echo '{"Name":"MultiPressComplete","PreviousPosition":3,"TotalNumberOfPressesCounted":2}' > /tmp/chip_all_clusters_fifo- ``` diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index c017d3c61a05a0..e42681d16a64e1 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -55,7 +55,7 @@ using namespace chip::DeviceLayer; namespace { -constexpr const char kChipEventFifoPathPrefix[] = "/tmp/chip_all_cluster_fifo_"; +constexpr const char kChipEventFifoPathPrefix[] = "/tmp/chip_all_clusters_fifo_"; LowPowerManager sLowPowerManager; NamedPipeCommands sChipNamedPipeCommands; AllClustersCommandDelegate sAllClustersCommandDelegate; diff --git a/examples/platform/linux/NamedPipeCommands.cpp b/examples/platform/linux/NamedPipeCommands.cpp index 63bad2eb072ccd..4d78cd4c87aab6 100644 --- a/examples/platform/linux/NamedPipeCommands.cpp +++ b/examples/platform/linux/NamedPipeCommands.cpp @@ -24,7 +24,7 @@ #include #include -static constexpr const size_t kChipEventCmdBufSize = 80; +static constexpr const size_t kChipEventCmdBufSize = 256; CHIP_ERROR NamedPipeCommands::Start(std::string & path, NamedPipeCommandDelegate * delegate) { diff --git a/examples/platform/linux/NamedPipeCommands.h b/examples/platform/linux/NamedPipeCommands.h index 16b8cd4cd32c2a..4f908de28748d0 100644 --- a/examples/platform/linux/NamedPipeCommands.h +++ b/examples/platform/linux/NamedPipeCommands.h @@ -24,8 +24,8 @@ class NamedPipeCommandDelegate { public: - virtual ~NamedPipeCommandDelegate() = default; - virtual void OnEventCommandReceived(const char * payload) = 0; + virtual ~NamedPipeCommandDelegate() = default; + virtual void OnEventCommandReceived(const char * json) = 0; }; class NamedPipeCommands