From 3646581008814b0f550106ef1cd474f3c2171deb Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:56:45 -0500 Subject: [PATCH] [Silabs] Add generic witch support to light-switch example (#24642) * Add generic witch support to light-switch example * restyle * move shell init to light-switch-mgr --------- Co-authored-by: Andrei Litvin --- .../light-switch-app/silabs/SiWx917/BUILD.gn | 10 +- .../silabs/SiWx917/src/AppTask.cpp | 60 ++- .../silabs/common/BindingHandler.cpp | 161 +++++++ .../BindingHandler.h} | 0 .../silabs/common/LightSwitchMgr.cpp | 161 +++++++ .../silabs/common/LightSwitchMgr.h | 58 +++ .../ShellCommands.cpp} | 166 +------ .../ShellCommands.h} | 23 +- .../light-switch-app/silabs/efr32/BUILD.gn | 10 +- .../silabs/efr32/src/AppTask.cpp | 54 +-- .../silabs/efr32/src/binding-handler.cpp | 431 ------------------ 11 files changed, 484 insertions(+), 650 deletions(-) create mode 100644 examples/light-switch-app/silabs/common/BindingHandler.cpp rename examples/light-switch-app/silabs/{SiWx917/include/binding-handler.h => common/BindingHandler.h} (100%) create mode 100644 examples/light-switch-app/silabs/common/LightSwitchMgr.cpp create mode 100644 examples/light-switch-app/silabs/common/LightSwitchMgr.h rename examples/light-switch-app/silabs/{SiWx917/src/binding-handler.cpp => common/ShellCommands.cpp} (64%) rename examples/light-switch-app/silabs/{efr32/include/binding-handler.h => common/ShellCommands.h} (61%) delete mode 100644 examples/light-switch-app/silabs/efr32/src/binding-handler.cpp diff --git a/examples/light-switch-app/silabs/SiWx917/BUILD.gn b/examples/light-switch-app/silabs/SiWx917/BUILD.gn index b7bf2c938faf45..ad139445fec618 100644 --- a/examples/light-switch-app/silabs/SiWx917/BUILD.gn +++ b/examples/light-switch-app/silabs/SiWx917/BUILD.gn @@ -147,6 +147,7 @@ efr32_sdk("sdk") { ] include_dirs = [ + "${chip_root}/examples/light-switch-app/silabs/common", "${chip_root}/src/platform/silabs/SiWx917", "${efr32_project_dir}/include", "${examples_plat_dir}", @@ -200,6 +201,8 @@ efr32_executable("light_switch_app") { defines = [] sources = [ + "${chip_root}/examples/light-switch-app/silabs/common/BindingHandler.cpp", + "${chip_root}/examples/light-switch-app/silabs/common/LightSwitchMgr.cpp", "${examples_common_plat_dir}/heap_4_silabs.c", "${examples_plat_dir}/BaseApplication.cpp", "${examples_plat_dir}/init_ccpPlatform.cpp", @@ -207,7 +210,6 @@ efr32_executable("light_switch_app") { "${examples_plat_dir}/siwx917_utils.cpp", "src/AppTask.cpp", "src/ZclCallbacks.cpp", - "src/binding-handler.cpp", "src/main.cpp", ] @@ -228,6 +230,12 @@ efr32_executable("light_switch_app") { "${chip_root}/src/setup_payload", ] + if (chip_build_libshell) { + sources += [ + "${chip_root}/examples/light-switch-app/silabs/common/ShellCommands.cpp", + ] + } + # Attestation Credentials if (chip_build_platform_attestation_credentials_provider) { deps += [ "${examples_plat_dir}:siwx917-attestation-credentials" ] diff --git a/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp b/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp index 9cba97f27dafc2..1886f801ea2e12 100644 --- a/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp +++ b/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp @@ -24,12 +24,14 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" -#include "binding-handler.h" +#include "BindingHandler.h" #ifdef ENABLE_WSTK_LEDS #include "LEDWidget.h" #endif // ENABLE_WSTK_LEDS +#include "LightSwitchMgr.h" + #ifdef DISPLAY_ENABLED #include "lcd.h" #ifdef QR_CODE_ENABLED @@ -37,6 +39,10 @@ #endif // QR_CODE_ENABLED #endif // DISPLAY_ENABLED +#if defined(ENABLE_CHIP_SHELL) +#include "ShellCommands.h" +#endif // defined(ENABLE_CHIP_SHELL) + #include #include #include @@ -59,6 +65,13 @@ #define APP_FUNCTION_BUTTON &sl_button_btn0 #define APP_LIGHT_SWITCH &sl_button_btn1 +namespace { + +constexpr chip::EndpointId kLightSwitchEndpoint = 1; +constexpr chip::EndpointId kGenericSwitchEndpoint = 2; + +} // namespace + using namespace chip; using namespace ::chip::DeviceLayer; @@ -70,8 +83,6 @@ namespace { EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT; -bool mCurrentButtonState = false; - /********************************************************** * Identify Callbacks *********************************************************/ @@ -159,14 +170,17 @@ CHIP_ERROR AppTask::Init() appError(err); } - // Configure Bindings - TODO ERROR PROCESSING - err = InitBindingHandler(); + err = LightSwitchMgr::GetInstance().Init(kLightSwitchEndpoint, kGenericSwitchEndpoint); if (err != CHIP_NO_ERROR) { - SILABS_LOG("InitBindingHandler() failed"); + SILABS_LOG("LightSwitchMgr Init failed!"); appError(err); } +#if defined(ENABLE_CHIP_SHELL) + LightSwtichCommands::RegisterSwitchCommands(); +#endif // defined(ENABLE_CHIP_SHELL) + return err; } @@ -223,36 +237,32 @@ void AppTask::OnIdentifyStop(Identify * identify) void AppTask::SwitchActionEventHandler(AppEvent * aEvent) { - if (aEvent->Type == AppEvent::kEventType_Button) + VerifyOrReturn(aEvent->Type == AppEvent::kEventType_Button); + + static bool mCurrentButtonState = false; + + if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_PRESSED) { - BindingCommandData * data = Platform::New(); - data->clusterId = chip::app::Clusters::OnOff::Id; + mCurrentButtonState = !mCurrentButtonState; + LightSwitchMgr::LightSwitchAction action = + mCurrentButtonState ? LightSwitchMgr::LightSwitchAction::On : LightSwitchMgr::LightSwitchAction::Off; - if (mCurrentButtonState) - { - mCurrentButtonState = false; - data->commandId = chip::app::Clusters::OnOff::Commands::Off::Id; - } - else - { - data->commandId = chip::app::Clusters::OnOff::Commands::On::Id; - mCurrentButtonState = true; - } + LightSwitchMgr::GetInstance().TriggerLightSwitchAction(action); + LightSwitchMgr::GetInstance().GenericSwitchOnInitialPress(); #ifdef DISPLAY_ENABLED sAppTask.GetLCD().WriteDemoUI(mCurrentButtonState); #endif - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + } + else if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_RELEASED) + { + LightSwitchMgr::GetInstance().GenericSwitchOnShortRelease(); } } void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) { - if (buttonHandle == NULL) - { - return; - } + VerifyOrReturn(buttonHandle != NULL); AppEvent button_event = {}; button_event.Type = AppEvent::kEventType_Button; diff --git a/examples/light-switch-app/silabs/common/BindingHandler.cpp b/examples/light-switch-app/silabs/common/BindingHandler.cpp new file mode 100644 index 00000000000000..3f75f79a60d82c --- /dev/null +++ b/examples/light-switch-app/silabs/common/BindingHandler.cpp @@ -0,0 +1,161 @@ +/* + * + * Copyright (c) 2020 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. + */ + +#include "BindingHandler.h" + +#include "AppConfig.h" +#include "app/CommandSender.h" +#include "app/clusters/bindings/BindingManager.h" +#include "app/server/Server.h" +#include "controller/InvokeInteraction.h" +#include "platform/CHIPDeviceLayer.h" +#include +#include + +using namespace chip; +using namespace chip::app; + +namespace { + +void ProcessOnOffUnicastBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding, + Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle) +{ + auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { + ChipLogProgress(NotSpecified, "OnOff command succeeds"); + }; + + auto onFailure = [](CHIP_ERROR error) { + ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format()); + }; + + switch (commandId) + { + case Clusters::OnOff::Commands::Toggle::Id: + Clusters::OnOff::Commands::Toggle::Type toggleCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure); + break; + + case Clusters::OnOff::Commands::On::Id: + Clusters::OnOff::Commands::On::Type onCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, onCommand, onSuccess, onFailure); + break; + + case Clusters::OnOff::Commands::Off::Id: + Clusters::OnOff::Commands::Off::Type offCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, offCommand, onSuccess, onFailure); + break; + } +} + +void ProcessOnOffGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding) +{ + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + + switch (commandId) + { + case Clusters::OnOff::Commands::Toggle::Id: + Clusters::OnOff::Commands::Toggle::Type toggleCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand); + break; + + case Clusters::OnOff::Commands::On::Id: + Clusters::OnOff::Commands::On::Type onCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand); + + break; + + case Clusters::OnOff::Commands::Off::Id: + Clusters::OnOff::Commands::Off::Type offCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand); + break; + } +} + +void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context) +{ + VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); + BindingCommandData * data = static_cast(context); + + if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup) + { + switch (data->clusterId) + { + case Clusters::OnOff::Id: + ProcessOnOffGroupBindingCommand(data->commandId, binding); + break; + } + } + else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup) + { + switch (data->clusterId) + { + case Clusters::OnOff::Id: + VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), + peer_device->GetSecureSession().Value()); + break; + } + } +} + +void LightSwitchContextReleaseHandler(void * context) +{ + VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "LightSwitchContextReleaseHandler: context is null")); + Platform::Delete(static_cast(context)); +} + +void InitBindingHandlerInternal(intptr_t arg) +{ + auto & server = chip::Server::GetInstance(); + chip::BindingManager::GetInstance().Init( + { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); + chip::BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler); + chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler); +} + +} // namespace + +/******************************************************** + * Switch functions + *********************************************************/ + +void SwitchWorkerFunction(intptr_t context) +{ + VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "SwitchWorkerFunction - Invalid work data")); + + BindingCommandData * data = reinterpret_cast(context); + BindingManager::GetInstance().NotifyBoundClusterChanged(data->localEndpointId, data->clusterId, static_cast(data)); +} + +void BindingWorkerFunction(intptr_t context) +{ + VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingWorkerFunction - Invalid work data")); + + EmberBindingTableEntry * entry = reinterpret_cast(context); + AddBindingEntry(*entry); + + Platform::Delete(entry); +} + +CHIP_ERROR InitBindingHandler() +{ + // The initialization of binding manager will try establishing connection with unicast peers + // so it requires the Server instance to be correctly initialized. Post the init function to + // the event queue so that everything is ready when initialization is conducted. + chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal); + return CHIP_NO_ERROR; +} diff --git a/examples/light-switch-app/silabs/SiWx917/include/binding-handler.h b/examples/light-switch-app/silabs/common/BindingHandler.h similarity index 100% rename from examples/light-switch-app/silabs/SiWx917/include/binding-handler.h rename to examples/light-switch-app/silabs/common/BindingHandler.h diff --git a/examples/light-switch-app/silabs/common/LightSwitchMgr.cpp b/examples/light-switch-app/silabs/common/LightSwitchMgr.cpp new file mode 100644 index 00000000000000..dddff2fc047616 --- /dev/null +++ b/examples/light-switch-app/silabs/common/LightSwitchMgr.cpp @@ -0,0 +1,161 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * 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. + */ + +#include "LightSwitchMgr.h" +#include "BindingHandler.h" + +#if defined(ENABLE_CHIP_SHELL) +#include "ShellCommands.h" +#endif // defined(ENABLE_CHIP_SHELL) + +#include "AppConfig.h" +#include "AppEvent.h" + +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; + +LightSwitchMgr LightSwitchMgr::sSwitch; + +/** + * @brief Configures LightSwitchMgr + * This function needs to be call before using the LightSwitchMgr + * + * @param lightSwitchEndpoint endpoint for the light switch device type + * @param genericSwitchEndpoint endpoint for the generic switch device type + */ +CHIP_ERROR LightSwitchMgr::Init(EndpointId lightSwitchEndpoint, chip::EndpointId genericSwitchEndpoint) +{ + VerifyOrReturnError(lightSwitchEndpoint != kInvalidEndpointId, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(genericSwitchEndpoint != kInvalidEndpointId, CHIP_ERROR_INVALID_ARGUMENT); + + mLightSwitchEndpoint = lightSwitchEndpoint; + mGenericSwitchEndpoint = genericSwitchEndpoint; + + // Configure Bindings + CHIP_ERROR error = InitBindingHandler(); + if (error != CHIP_NO_ERROR) + { + SILABS_LOG("InitBindingHandler() failed!"); + appError(error); + } + +#if defined(ENABLE_CHIP_SHELL) + LightSwtichCommands::RegisterSwitchCommands(); +#endif // defined(ENABLE_CHIP_SHELL) + + return error; +} + +/** + * @brief Function that triggers a generic switch OnInitialPress event + */ +void LightSwitchMgr::GenericSwitchOnInitialPress() +{ + GenericSwitchEventData * data = Platform::New(); + + data->endpoint = mGenericSwitchEndpoint; + data->event = Switch::Events::InitialPress::Id; + + DeviceLayer::PlatformMgr().ScheduleWork(GenericSwitchWorkerFunction, reinterpret_cast(data)); +} + +/** + * @brief Function that triggers a generic switch OnShortRelease event + */ +void LightSwitchMgr::GenericSwitchOnShortRelease() +{ + GenericSwitchEventData * data = Platform::New(); + + data->endpoint = mGenericSwitchEndpoint; + data->event = Switch::Events::ShortRelease::Id; + + DeviceLayer::PlatformMgr().ScheduleWork(GenericSwitchWorkerFunction, reinterpret_cast(data)); +} + +void LightSwitchMgr::TriggerLightSwitchAction(LightSwitchAction action, bool isGroupCommand) +{ + BindingCommandData * data = Platform::New(); + + data->clusterId = chip::app::Clusters::OnOff::Id; + data->isGroup = isGroupCommand; + + switch (action) + { + case LightSwitchAction::Toggle: + data->commandId = OnOff::Commands::Toggle::Id; + + break; + + case LightSwitchAction::On: + data->commandId = OnOff::Commands::On::Id; + break; + + case LightSwitchAction::Off: + data->commandId = OnOff::Commands::Off::Id; + break; + + default: + Platform::Delete(data); + return; + break; + } + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); +} + +void LightSwitchMgr::GenericSwitchWorkerFunction(intptr_t context) +{ + + GenericSwitchEventData * data = reinterpret_cast(context); + + switch (data->event) + { + case Switch::Events::InitialPress::Id: { + uint8_t currentPosition = 1; + + // Set new attribute value + Clusters::Switch::Attributes::CurrentPosition::Set(data->endpoint, currentPosition); + + // Trigger event + Clusters::SwitchServer::Instance().OnInitialPress(data->endpoint, currentPosition); + break; + } + case Switch::Events::ShortRelease::Id: { + uint8_t previousPosition = 1; + uint8_t currentPosition = 0; + + // Set new attribute value + Clusters::Switch::Attributes::CurrentPosition::Set(data->endpoint, currentPosition); + + // Trigger event + Clusters::SwitchServer::Instance().OnShortRelease(data->endpoint, previousPosition); + break; + } + default: + break; + } + + Platform::Delete(data); +} diff --git a/examples/light-switch-app/silabs/common/LightSwitchMgr.h b/examples/light-switch-app/silabs/common/LightSwitchMgr.h new file mode 100644 index 00000000000000..adfe75fda9512e --- /dev/null +++ b/examples/light-switch-app/silabs/common/LightSwitchMgr.h @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include +#include +#include + +class LightSwitchMgr +{ +public: + enum class LightSwitchAction : uint8_t + { + Toggle, // Triggers an toggle command + On, // Triggers an On command + Off // Trigger an Off command + }; + + struct GenericSwitchEventData + { + chip::EndpointId endpoint; + chip::EventId event; + }; + + CHIP_ERROR Init(chip::EndpointId lightSwitchEndpoint, chip::EndpointId genericSwitchEndpoint); + + void GenericSwitchOnInitialPress(); + void GenericSwitchOnShortRelease(); + + void TriggerLightSwitchAction(LightSwitchAction action, bool isGroupCommand = false); + + static LightSwitchMgr & GetInstance() { return sSwitch; } + +private: + static LightSwitchMgr sSwitch; + + static void GenericSwitchWorkerFunction(intptr_t context); + + chip::EndpointId mLightSwitchEndpoint = chip::kInvalidEndpointId; + chip::EndpointId mGenericSwitchEndpoint = chip::kInvalidEndpointId; +}; diff --git a/examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp b/examples/light-switch-app/silabs/common/ShellCommands.cpp similarity index 64% rename from examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp rename to examples/light-switch-app/silabs/common/ShellCommands.cpp index 90a2463a088e33..daac5078501858 100644 --- a/examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp +++ b/examples/light-switch-app/silabs/common/ShellCommands.cpp @@ -1,6 +1,8 @@ /* * * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,27 +16,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if defined(ENABLE_CHIP_SHELL) -#include "binding-handler.h" +#include "ShellCommands.h" +#include "BindingHandler.h" -#include "AppConfig.h" -#include "app/CommandSender.h" -#include "app/clusters/bindings/BindingManager.h" -#include "app/server/Server.h" -#include "controller/InvokeInteraction.h" -#include "platform/CHIPDeviceLayer.h" #include -#include - -#if defined(ENABLE_CHIP_SHELL) -#include "lib/shell/Engine.h" -#include "lib/shell/commands/Help.h" -#endif // ENABLE_CHIP_SHELL +#include +#include +#include using namespace chip; using namespace chip::app; -#if defined(ENABLE_CHIP_SHELL) +namespace LightSwtichCommands { + using Shell::Engine; using Shell::shell_command_t; using Shell::streamer_get; @@ -47,99 +43,6 @@ Engine sShellSwitchGroupsSubCommands; Engine sShellSwitchGroupsOnOffSubCommands; Engine sShellSwitchBindingSubCommands; -#endif // defined(ENABLE_CHIP_SHELL) - -namespace { - -void ProcessOnOffUnicastBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding, - Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle) -{ - auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { - ChipLogProgress(NotSpecified, "OnOff command succeeds"); - }; - - auto onFailure = [](CHIP_ERROR error) { - ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format()); - }; - - switch (commandId) - { - case Clusters::OnOff::Commands::Toggle::Id: - Clusters::OnOff::Commands::Toggle::Type toggleCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure); - break; - - case Clusters::OnOff::Commands::On::Id: - Clusters::OnOff::Commands::On::Type onCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, onCommand, onSuccess, onFailure); - break; - - case Clusters::OnOff::Commands::Off::Id: - Clusters::OnOff::Commands::Off::Type offCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, offCommand, onSuccess, onFailure); - break; - } -} - -void ProcessOnOffGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding) -{ - Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); - - switch (commandId) - { - case Clusters::OnOff::Commands::Toggle::Id: - Clusters::OnOff::Commands::Toggle::Type toggleCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand); - break; - - case Clusters::OnOff::Commands::On::Id: - Clusters::OnOff::Commands::On::Type onCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand); - - break; - - case Clusters::OnOff::Commands::Off::Id: - Clusters::OnOff::Commands::Off::Type offCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand); - break; - } -} - -void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context) -{ - VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); - BindingCommandData * data = static_cast(context); - - if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup) - { - switch (data->clusterId) - { - case Clusters::OnOff::Id: - ProcessOnOffGroupBindingCommand(data->commandId, binding); - break; - } - } - else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup) - { - switch (data->clusterId) - { - case Clusters::OnOff::Id: - VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); - ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), - peer_device->GetSecureSession().Value()); - break; - } - } -} - -void LightSwitchContextReleaseHandler(void * context) -{ - VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "LightSwitchContextReleaseHandler: context is null")); - - Platform::Delete(static_cast(context)); -} - -#ifdef ENABLE_CHIP_SHELL /******************************************************** * Switch shell functions @@ -337,9 +240,8 @@ CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv) /** * @brief configures switch matter shell - * */ -static void RegisterSwitchCommands() +void RegisterSwitchCommands() { static const shell_command_t sSwitchSubCommands[] = { { &SwitchHelpHandler, "help", "Usage: switch " }, @@ -383,49 +285,7 @@ static void RegisterSwitchCommands() Engine::Root().RegisterCommands(&sSwitchCommand, 1); } -#endif // ENABLE_CHIP_SHELL - -void InitBindingHandlerInternal(intptr_t arg) -{ - auto & server = chip::Server::GetInstance(); - chip::BindingManager::GetInstance().Init( - { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); - chip::BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler); - chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler); -} - -} // namespace - -/******************************************************** - * Switch functions - *********************************************************/ - -void SwitchWorkerFunction(intptr_t context) -{ - VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "SwitchWorkerFunction - Invalid work data")); - - BindingCommandData * data = reinterpret_cast(context); - BindingManager::GetInstance().NotifyBoundClusterChanged(data->localEndpointId, data->clusterId, static_cast(data)); -} - -void BindingWorkerFunction(intptr_t context) -{ - VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingWorkerFunction - Invalid work data")); - EmberBindingTableEntry * entry = reinterpret_cast(context); - AddBindingEntry(*entry); +} // namespace LightSwtichCommands - Platform::Delete(entry); -} - -CHIP_ERROR InitBindingHandler() -{ - // The initialization of binding manager will try establishing connection with unicast peers - // so it requires the Server instance to be correctly initialized. Post the init function to - // the event queue so that everything is ready when initialization is conducted. - chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal); -#if defined(ENABLE_CHIP_SHELL) - RegisterSwitchCommands(); -#endif - return CHIP_NO_ERROR; -} +#endif // ENABLE_CHIP_SHELL diff --git a/examples/light-switch-app/silabs/efr32/include/binding-handler.h b/examples/light-switch-app/silabs/common/ShellCommands.h similarity index 61% rename from examples/light-switch-app/silabs/efr32/include/binding-handler.h rename to examples/light-switch-app/silabs/common/ShellCommands.h index aed08be25eb5bc..576ad5235ffd6b 100644 --- a/examples/light-switch-app/silabs/efr32/include/binding-handler.h +++ b/examples/light-switch-app/silabs/common/ShellCommands.h @@ -1,6 +1,8 @@ /* * * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +16,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once -#include "app-common/zap-generated/ids/Clusters.h" -#include "app-common/zap-generated/ids/Commands.h" -#include "lib/core/CHIPError.h" +#if defined(ENABLE_CHIP_SHELL) + +namespace LightSwtichCommands { + +void RegisterSwitchCommands(); -CHIP_ERROR InitBindingHandler(); -void SwitchWorkerFunction(intptr_t context); -void BindingWorkerFunction(intptr_t context); +} // namespace LightSwtichCommands -struct BindingCommandData -{ - chip::EndpointId localEndpointId = 1; - chip::CommandId commandId; - chip::ClusterId clusterId; - bool isGroup = false; -}; +#endif // defined(ENABLE_CHIP_SHELL) diff --git a/examples/light-switch-app/silabs/efr32/BUILD.gn b/examples/light-switch-app/silabs/efr32/BUILD.gn index 85ccf1ac6f833f..64c42eccbd9113 100644 --- a/examples/light-switch-app/silabs/efr32/BUILD.gn +++ b/examples/light-switch-app/silabs/efr32/BUILD.gn @@ -158,6 +158,7 @@ efr32_sdk("sdk") { ] include_dirs = [ + "${chip_root}/examples/light-switch-app/silabs/common", "${chip_root}/src/platform/silabs/EFR32", "${efr32_project_dir}/include", "${examples_plat_dir}", @@ -211,6 +212,8 @@ efr32_executable("light_switch_app") { defines = [] sources = [ + "${chip_root}/examples/light-switch-app/silabs/common/BindingHandler.cpp", + "${chip_root}/examples/light-switch-app/silabs/common/LightSwitchMgr.cpp", "${examples_common_plat_dir}/heap_4_silabs.c", "${examples_plat_dir}/BaseApplication.cpp", "${examples_plat_dir}/efr32_utils.cpp", @@ -218,7 +221,6 @@ efr32_executable("light_switch_app") { "${examples_plat_dir}/matter_config.cpp", "src/AppTask.cpp", "src/ZclCallbacks.cpp", - "src/binding-handler.cpp", "src/main.cpp", ] @@ -239,6 +241,12 @@ efr32_executable("light_switch_app") { "${chip_root}/src/setup_payload", ] + if (chip_build_libshell) { + sources += [ + "${chip_root}/examples/light-switch-app/silabs/common/ShellCommands.cpp", + ] + } + # OpenThread Settings if (chip_enable_openthread) { deps += [ diff --git a/examples/light-switch-app/silabs/efr32/src/AppTask.cpp b/examples/light-switch-app/silabs/efr32/src/AppTask.cpp index e1bbc8d782c888..3e817e05901e84 100644 --- a/examples/light-switch-app/silabs/efr32/src/AppTask.cpp +++ b/examples/light-switch-app/silabs/efr32/src/AppTask.cpp @@ -24,13 +24,15 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" -#include "binding-handler.h" +#include "BindingHandler.h" #ifdef ENABLE_WSTK_LEDS #include "LEDWidget.h" #include "sl_simple_led_instances.h" #endif // ENABLE_WSTK_LEDS +#include "LightSwitchMgr.h" + #ifdef DISPLAY_ENABLED #include "lcd.h" #ifdef QR_CODE_ENABLED @@ -60,6 +62,13 @@ #define APP_FUNCTION_BUTTON &sl_button_btn0 #define APP_LIGHT_SWITCH &sl_button_btn1 +namespace { + +constexpr chip::EndpointId kLightSwitchEndpoint = 1; +constexpr chip::EndpointId kGenericSwitchEndpoint = 2; + +} // namespace + using namespace chip; using namespace ::chip::DeviceLayer; @@ -71,8 +80,6 @@ namespace { EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT; -bool mCurrentButtonState = false; - /********************************************************** * Identify Callbacks *********************************************************/ @@ -160,11 +167,10 @@ CHIP_ERROR AppTask::Init() appError(err); } - // Configure Bindings - TODO ERROR PROCESSING - err = InitBindingHandler(); + err = LightSwitchMgr::GetInstance().Init(kLightSwitchEndpoint, kGenericSwitchEndpoint); if (err != CHIP_NO_ERROR) { - SILABS_LOG("InitBindingHandler() failed"); + SILABS_LOG("LightSwitchMgr Init failed!"); appError(err); } @@ -224,42 +230,38 @@ void AppTask::OnIdentifyStop(Identify * identify) void AppTask::SwitchActionEventHandler(AppEvent * aEvent) { - if (aEvent->Type == AppEvent::kEventType_Button) + VerifyOrReturn(aEvent->Type == AppEvent::kEventType_Button); + + static bool mCurrentButtonState = false; + + if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_PRESSED) { - BindingCommandData * data = Platform::New(); - data->clusterId = chip::app::Clusters::OnOff::Id; + mCurrentButtonState = !mCurrentButtonState; + LightSwitchMgr::LightSwitchAction action = + mCurrentButtonState ? LightSwitchMgr::LightSwitchAction::On : LightSwitchMgr::LightSwitchAction::Off; - if (mCurrentButtonState) - { - mCurrentButtonState = false; - data->commandId = chip::app::Clusters::OnOff::Commands::Off::Id; - } - else - { - data->commandId = chip::app::Clusters::OnOff::Commands::On::Id; - mCurrentButtonState = true; - } + LightSwitchMgr::GetInstance().TriggerLightSwitchAction(action); + LightSwitchMgr::GetInstance().GenericSwitchOnInitialPress(); #ifdef DISPLAY_ENABLED sAppTask.GetLCD().WriteDemoUI(mCurrentButtonState); #endif - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + } + else if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_RELEASED) + { + LightSwitchMgr::GetInstance().GenericSwitchOnShortRelease(); } } void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) { - if (buttonHandle == NULL) - { - return; - } + VerifyOrReturn(buttonHandle != NULL); AppEvent button_event = {}; button_event.Type = AppEvent::kEventType_Button; button_event.ButtonEvent.Action = btnAction; - if (buttonHandle == APP_LIGHT_SWITCH && btnAction == SL_SIMPLE_BUTTON_PRESSED) + if (buttonHandle == APP_LIGHT_SWITCH) { button_event.Handler = SwitchActionEventHandler; sAppTask.PostEvent(&button_event); diff --git a/examples/light-switch-app/silabs/efr32/src/binding-handler.cpp b/examples/light-switch-app/silabs/efr32/src/binding-handler.cpp deleted file mode 100644 index 90a2463a088e33..00000000000000 --- a/examples/light-switch-app/silabs/efr32/src/binding-handler.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* - * - * Copyright (c) 2020 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. - */ - -#include "binding-handler.h" - -#include "AppConfig.h" -#include "app/CommandSender.h" -#include "app/clusters/bindings/BindingManager.h" -#include "app/server/Server.h" -#include "controller/InvokeInteraction.h" -#include "platform/CHIPDeviceLayer.h" -#include -#include - -#if defined(ENABLE_CHIP_SHELL) -#include "lib/shell/Engine.h" -#include "lib/shell/commands/Help.h" -#endif // ENABLE_CHIP_SHELL - -using namespace chip; -using namespace chip::app; - -#if defined(ENABLE_CHIP_SHELL) -using Shell::Engine; -using Shell::shell_command_t; -using Shell::streamer_get; -using Shell::streamer_printf; - -Engine sShellSwitchSubCommands; -Engine sShellSwitchOnOffSubCommands; - -Engine sShellSwitchGroupsSubCommands; -Engine sShellSwitchGroupsOnOffSubCommands; - -Engine sShellSwitchBindingSubCommands; -#endif // defined(ENABLE_CHIP_SHELL) - -namespace { - -void ProcessOnOffUnicastBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding, - Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle) -{ - auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { - ChipLogProgress(NotSpecified, "OnOff command succeeds"); - }; - - auto onFailure = [](CHIP_ERROR error) { - ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format()); - }; - - switch (commandId) - { - case Clusters::OnOff::Commands::Toggle::Id: - Clusters::OnOff::Commands::Toggle::Type toggleCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure); - break; - - case Clusters::OnOff::Commands::On::Id: - Clusters::OnOff::Commands::On::Type onCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, onCommand, onSuccess, onFailure); - break; - - case Clusters::OnOff::Commands::Off::Id: - Clusters::OnOff::Commands::Off::Type offCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, offCommand, onSuccess, onFailure); - break; - } -} - -void ProcessOnOffGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding) -{ - Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); - - switch (commandId) - { - case Clusters::OnOff::Commands::Toggle::Id: - Clusters::OnOff::Commands::Toggle::Type toggleCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand); - break; - - case Clusters::OnOff::Commands::On::Id: - Clusters::OnOff::Commands::On::Type onCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand); - - break; - - case Clusters::OnOff::Commands::Off::Id: - Clusters::OnOff::Commands::Off::Type offCommand; - Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand); - break; - } -} - -void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context) -{ - VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); - BindingCommandData * data = static_cast(context); - - if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup) - { - switch (data->clusterId) - { - case Clusters::OnOff::Id: - ProcessOnOffGroupBindingCommand(data->commandId, binding); - break; - } - } - else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup) - { - switch (data->clusterId) - { - case Clusters::OnOff::Id: - VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); - ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), - peer_device->GetSecureSession().Value()); - break; - } - } -} - -void LightSwitchContextReleaseHandler(void * context) -{ - VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "LightSwitchContextReleaseHandler: context is null")); - - Platform::Delete(static_cast(context)); -} - -#ifdef ENABLE_CHIP_SHELL - -/******************************************************** - * Switch shell functions - *********************************************************/ - -CHIP_ERROR SwitchHelpHandler(int argc, char ** argv) -{ - sShellSwitchSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - -CHIP_ERROR SwitchCommandHandler(int argc, char ** argv) -{ - if (argc == 0) - { - return SwitchHelpHandler(argc, argv); - } - - return sShellSwitchSubCommands.ExecCommand(argc, argv); -} - -/******************************************************** - * OnOff switch shell functions - *********************************************************/ - -CHIP_ERROR OnOffHelpHandler(int argc, char ** argv) -{ - sShellSwitchOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - -CHIP_ERROR OnOffSwitchCommandHandler(int argc, char ** argv) -{ - if (argc == 0) - { - return OnOffHelpHandler(argc, argv); - } - - return sShellSwitchOnOffSubCommands.ExecCommand(argc, argv); -} - -CHIP_ERROR OnSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::On::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR OffSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Off::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Toggle::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -/******************************************************** - * bind switch shell functions - *********************************************************/ - -CHIP_ERROR BindingHelpHandler(int argc, char ** argv) -{ - sShellSwitchBindingSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - -CHIP_ERROR BindingSwitchCommandHandler(int argc, char ** argv) -{ - if (argc == 0) - { - return BindingHelpHandler(argc, argv); - } - - return sShellSwitchBindingSubCommands.ExecCommand(argc, argv); -} - -CHIP_ERROR BindingGroupBindCommandHandler(int argc, char ** argv) -{ - VerifyOrReturnError(argc == 2, CHIP_ERROR_INVALID_ARGUMENT); - - EmberBindingTableEntry * entry = Platform::New(); - entry->type = EMBER_MULTICAST_BINDING; - entry->fabricIndex = atoi(argv[0]); - entry->groupId = atoi(argv[1]); - entry->local = 1; // Hardcoded to endpoint 1 for now - entry->clusterId.SetValue(6); // Hardcoded to OnOff cluster for now - - DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR BindingUnicastBindCommandHandler(int argc, char ** argv) -{ - VerifyOrReturnError(argc == 3, CHIP_ERROR_INVALID_ARGUMENT); - - EmberBindingTableEntry * entry = Platform::New(); - entry->type = EMBER_UNICAST_BINDING; - entry->fabricIndex = atoi(argv[0]); - entry->nodeId = atoi(argv[1]); - entry->local = 1; // Hardcoded to endpoint 1 for now - entry->remote = atoi(argv[2]); - entry->clusterId.SetValue(6); // Hardcode to OnOff cluster for now - - DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry)); - return CHIP_NO_ERROR; -} - -/******************************************************** - * Groups switch shell functions - *********************************************************/ - -CHIP_ERROR GroupsHelpHandler(int argc, char ** argv) -{ - sShellSwitchGroupsSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupsSwitchCommandHandler(int argc, char ** argv) -{ - if (argc == 0) - { - return GroupsHelpHandler(argc, argv); - } - - return sShellSwitchGroupsSubCommands.ExecCommand(argc, argv); -} - -/******************************************************** - * Groups OnOff switch shell functions - *********************************************************/ - -CHIP_ERROR GroupsOnOffHelpHandler(int argc, char ** argv) -{ - sShellSwitchGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupsOnOffSwitchCommandHandler(int argc, char ** argv) -{ - if (argc == 0) - { - return GroupsOnOffHelpHandler(argc, argv); - } - - return sShellSwitchGroupsOnOffSubCommands.ExecCommand(argc, argv); -} - -CHIP_ERROR GroupOnSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::On::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupOffSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Off::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Toggle::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -/** - * @brief configures switch matter shell - * - */ -static void RegisterSwitchCommands() -{ - static const shell_command_t sSwitchSubCommands[] = { - { &SwitchHelpHandler, "help", "Usage: switch " }, - { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff " }, - { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups " }, - { &BindingSwitchCommandHandler, "binding", "Usage: switch binding " } - }; - - static const shell_command_t sSwitchOnOffSubCommands[] = { - { &OnOffHelpHandler, "help", "Usage : switch ononff " }, - { &OnSwitchCommandHandler, "on", "Sends on command to bound lighting app" }, - { &OffSwitchCommandHandler, "off", "Sends off command to bound lighting app" }, - { &ToggleSwitchCommandHandler, "toggle", "Sends toggle command to bound lighting app" } - }; - - static const shell_command_t sSwitchGroupsSubCommands[] = { { &GroupsHelpHandler, "help", "Usage: switch groups " }, - { &GroupsOnOffSwitchCommandHandler, "onoff", - "Usage: switch groups onoff " } }; - - static const shell_command_t sSwitchGroupsOnOffSubCommands[] = { - { &GroupsOnOffHelpHandler, "help", "Usage: switch groups onoff " }, - { &GroupOnSwitchCommandHandler, "on", "Sends on command to bound group" }, - { &GroupOffSwitchCommandHandler, "off", "Sends off command to bound group" }, - { &GroupToggleSwitchCommandHandler, "toggle", "Sends toggle command to group" } - }; - - static const shell_command_t sSwitchBindingSubCommands[] = { - { &BindingHelpHandler, "help", "Usage: switch binding " }, - { &BindingGroupBindCommandHandler, "group", "Usage: switch binding group " }, - { &BindingUnicastBindCommandHandler, "unicast", "Usage: switch binding group " } - }; - - static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch", - "Light-switch commands. Usage: switch " }; - - sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwitchGroupsOnOffSubCommands, ArraySize(sSwitchGroupsOnOffSubCommands)); - sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands)); - sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands)); - sShellSwitchBindingSubCommands.RegisterCommands(sSwitchBindingSubCommands, ArraySize(sSwitchBindingSubCommands)); - sShellSwitchSubCommands.RegisterCommands(sSwitchSubCommands, ArraySize(sSwitchSubCommands)); - - Engine::Root().RegisterCommands(&sSwitchCommand, 1); -} -#endif // ENABLE_CHIP_SHELL - -void InitBindingHandlerInternal(intptr_t arg) -{ - auto & server = chip::Server::GetInstance(); - chip::BindingManager::GetInstance().Init( - { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); - chip::BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler); - chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler); -} - -} // namespace - -/******************************************************** - * Switch functions - *********************************************************/ - -void SwitchWorkerFunction(intptr_t context) -{ - VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "SwitchWorkerFunction - Invalid work data")); - - BindingCommandData * data = reinterpret_cast(context); - BindingManager::GetInstance().NotifyBoundClusterChanged(data->localEndpointId, data->clusterId, static_cast(data)); -} - -void BindingWorkerFunction(intptr_t context) -{ - VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingWorkerFunction - Invalid work data")); - - EmberBindingTableEntry * entry = reinterpret_cast(context); - AddBindingEntry(*entry); - - Platform::Delete(entry); -} - -CHIP_ERROR InitBindingHandler() -{ - // The initialization of binding manager will try establishing connection with unicast peers - // so it requires the Server instance to be correctly initialized. Post the init function to - // the event queue so that everything is ready when initialization is conducted. - chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal); -#if defined(ENABLE_CHIP_SHELL) - RegisterSwitchCommands(); -#endif - return CHIP_NO_ERROR; -}