diff --git a/examples/bridge-app/telink/include/AppEvent.h b/examples/bridge-app/telink/include/AppEvent.h deleted file mode 100644 index f570dfd1e7cdf7..00000000000000 --- a/examples/bridge-app/telink/include/AppEvent.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * 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 - -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); - -class LEDWidget; - -struct AppEvent -{ - enum AppEventTypes - { - kEventType_Button = 0, - kEventType_Timer, - kEventType_UpdateLedState, - kEventType_IdentifyStart, - kEventType_IdentifyStop, - kEventType_Lighting, - }; - - uint16_t Type; - - union - { - struct - { - uint8_t Action; - } ButtonEvent; - struct - { - void * Context; - } TimerEvent; - struct - { - uint8_t Action; - int32_t Actor; - } LightingEvent; - struct - { - LEDWidget * LedWidget; - } UpdateLedStateEvent; - }; - - EventHandler Handler; -}; diff --git a/examples/bridge-app/telink/src/AppTask.cpp b/examples/bridge-app/telink/src/AppTask.cpp index 76a59c4de5e293..e080e40eb5dda9 100644 --- a/examples/bridge-app/telink/src/AppTask.cpp +++ b/examples/bridge-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -539,10 +539,10 @@ void AppTask::LightingActionEventHandler(AppEvent * aEvent) Action_t action = INVALID_ACTION; int32_t actor = 0; - if (aEvent->Type == AppEvent::kEventType_Lighting) + if (aEvent->Type == AppEvent::kEventType_DeviceAction) { - action = static_cast(aEvent->LightingEvent.Action); - actor = aEvent->LightingEvent.Actor; + action = static_cast(aEvent->DeviceEvent.Action); + actor = aEvent->DeviceEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { diff --git a/examples/contact-sensor-app/telink/src/AppTask.cpp b/examples/contact-sensor-app/telink/src/AppTask.cpp index 8ddb43d7b7f084..aa7b28d0679c9f 100644 --- a/examples/contact-sensor-app/telink/src/AppTask.cpp +++ b/examples/contact-sensor-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022-2023 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,9 +67,9 @@ void AppTask::OnStateChanged(ContactSensorManager::State aState) void AppTask::PostContactActionRequest(ContactSensorManager::Action aAction) { AppEvent event; - event.Type = AppEvent::kEventType_Contact; - event.ContactEvent.Action = static_cast(aAction); - event.Handler = ContactActionEventHandler; + event.Type = AppEvent::kEventType_DeviceAction; + event.DeviceEvent.Action = static_cast(aAction); + event.Handler = ContactActionEventHandler; sAppTask.PostEvent(&event); } @@ -95,9 +95,9 @@ void AppTask::ContactActionEventHandler(AppEvent * aEvent) ChipLogProgress(NotSpecified, "ContactActionEventHandler"); - if (aEvent->Type == AppEvent::kEventType_Contact) + if (aEvent->Type == AppEvent::kEventType_DeviceAction) { - action = static_cast(aEvent->ContactEvent.Action); + action = static_cast(aEvent->DeviceEvent.Action); } else if (aEvent->Type == AppEvent::kEventType_Button) { diff --git a/examples/contact-sensor-app/telink/src/ContactSensorManager.cpp b/examples/contact-sensor-app/telink/src/ContactSensorManager.cpp index a5822df5f8515e..efb5244db59755 100644 --- a/examples/contact-sensor-app/telink/src/ContactSensorManager.cpp +++ b/examples/contact-sensor-app/telink/src/ContactSensorManager.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,15 +54,15 @@ bool ContactSensorManager::IsContactClosed() void ContactSensorManager::InitiateAction(Action aAction) { AppEvent event; - event.Type = AppEvent::kEventType_Contact; - event.ContactEvent.Action = static_cast(aAction); - event.Handler = HandleAction; + event.Type = AppEvent::kEventType_DeviceAction; + event.DeviceEvent.Action = static_cast(aAction); + event.Handler = HandleAction; GetAppTask().PostEvent(&event); } void ContactSensorManager::HandleAction(AppEvent * aEvent) { - Action action = static_cast(aEvent->ContactEvent.Action); + Action action = static_cast(aEvent->DeviceEvent.Action); // Change current state based on action: // - if state is closed and action is signal lost, change state to opened // - if state is opened and action is signal detected, change state to closed diff --git a/examples/light-switch-app/telink/include/IdentifyCommand.h b/examples/light-switch-app/telink/include/IdentifyCommand.h new file mode 100644 index 00000000000000..1e94f338157eda --- /dev/null +++ b/examples/light-switch-app/telink/include/IdentifyCommand.h @@ -0,0 +1,270 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * 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 "controller/InvokeInteraction.h" +#include "controller/ReadInteraction.h" +#include + +#if defined(CONFIG_CHIP_LIB_SHELL) +#include "lib/shell/Engine.h" +#include "lib/shell/commands/Help.h" +#endif // CONFIG_CHIP_LIB_SHELL + +using namespace chip; +using namespace chip::app; + +#if defined(CONFIG_CHIP_LIB_SHELL) +using Shell::Engine; +using Shell::shell_command_t; +using Shell::streamer_get; +using Shell::streamer_printf; + +Engine sShellSwitchIdentifySubCommands; +Engine sShellSwitchIdentifyReadSubCommands; +Engine sShellSwitchGroupsIdentifySubCommands; +#endif // CONFIG_CHIP_LIB_SHELL + +void ProcessIdentifyUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding, + OperationalDeviceProxy * peer_device) +{ + auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) { + ChipLogProgress(NotSpecified, "Read Identify attribute succeeds"); + }; + + auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) { + ChipLogError(NotSpecified, "Read Identify attribute failed: %" CHIP_ERROR_FORMAT, error.Format()); + }; + + VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + + switch (data->attributeId) + { + case Clusters::Identify::Attributes::AttributeList::Id: + Controller::ReadAttribute( + peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); + break; + + case Clusters::Identify::Attributes::IdentifyTime::Id: + Controller::ReadAttribute( + peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); + break; + + case Clusters::Identify::Attributes::IdentifyType::Id: + Controller::ReadAttribute( + peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); + break; + } +} + +void ProcessIdentifyUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding, + OperationalDeviceProxy * peer_device) +{ + auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { + ChipLogProgress(NotSpecified, "Identify command succeeds"); + }; + + auto onFailure = [](CHIP_ERROR error) { + ChipLogError(NotSpecified, "Identify command failed: %" CHIP_ERROR_FORMAT, error.Format()); + }; + + VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + + Clusters::Identify::Commands::Identify::Type identifyCommand; + Clusters::Identify::Commands::TriggerEffect::Type triggerEffectCommand; + + switch (data->commandId) + { + case Clusters::Identify::Commands::Identify::Id: + identifyCommand.identifyTime = static_cast(data->args[0]); + Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, + identifyCommand, onSuccess, onFailure); + break; + + case Clusters::Identify::Commands::TriggerEffect::Id: + triggerEffectCommand.effectIdentifier = static_cast(data->args[0]); + triggerEffectCommand.effectVariant = static_cast(data->args[1]); + Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, + triggerEffectCommand, onSuccess, onFailure); + break; + } +} + +void ProcessIdentifyGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding) +{ + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + + Clusters::Identify::Commands::Identify::Type identifyCommand; + Clusters::Identify::Commands::TriggerEffect::Type triggerEffectCommand; + + switch (data->commandId) + { + case Clusters::Identify::Commands::Identify::Id: + identifyCommand.identifyTime = static_cast(data->args[0]); + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, identifyCommand); + break; + + case Clusters::Identify::Commands::TriggerEffect::Id: + triggerEffectCommand.effectIdentifier = static_cast(data->args[0]); + triggerEffectCommand.effectVariant = static_cast(data->args[1]); + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, triggerEffectCommand); + break; + } +} + +#if defined(CONFIG_CHIP_LIB_SHELL) +/******************************************************** + * Identify switch shell functions + *********************************************************/ + +CHIP_ERROR IdentifyHelpHandler(int argc, char ** argv) +{ + sShellSwitchIdentifySubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR IdentifySwitchCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return IdentifyHelpHandler(argc, argv); + } + + return sShellSwitchIdentifySubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR IdentifyCommandHandler(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->commandId = Clusters::Identify::Commands::Identify::Id; + data->clusterId = Clusters::Identify::Id; + data->args[0] = atoi(argv[0]); + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR TriggerEffectSwitchCommandHandler(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->commandId = Clusters::Identify::Commands::TriggerEffect::Id; + data->clusterId = Clusters::Identify::Id; + data->args[0] = atoi(argv[0]); + data->args[1] = atoi(argv[1]); + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +/******************************************************** + * Identify Read switch shell functions + *********************************************************/ + +CHIP_ERROR IdentifyReadHelpHandler(int argc, char ** argv) +{ + sShellSwitchIdentifyReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR IdentifyRead(int argc, char ** argv) +{ + if (argc == 0) + { + return IdentifyReadHelpHandler(argc, argv); + } + + return sShellSwitchIdentifyReadSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR IdentifyReadAttributeList(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->attributeId = Clusters::Identify::Attributes::AttributeList::Id; + data->clusterId = Clusters::Identify::Id; + data->isReadAttribute = true; + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR IdentifyReadIdentifyTime(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->attributeId = Clusters::Identify::Attributes::IdentifyTime::Id; + data->clusterId = Clusters::Identify::Id; + data->isReadAttribute = true; + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR IdentifyReadIdentifyType(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->attributeId = Clusters::Identify::Attributes::IdentifyType::Id; + data->clusterId = Clusters::Identify::Id; + data->isReadAttribute = true; + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +/******************************************************** + * Groups Identify switch shell functions + *********************************************************/ + +CHIP_ERROR GroupsIdentifyHelpHandler(int argc, char ** argv) +{ + sShellSwitchGroupsIdentifySubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR GroupsIdentifySwitchCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return GroupsIdentifyHelpHandler(argc, argv); + } + + return sShellSwitchGroupsIdentifySubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR GroupIdentifyCommandHandler(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->commandId = Clusters::Identify::Commands::Identify::Id; + data->clusterId = Clusters::Identify::Id; + data->args[0] = atoi(argv[0]); + data->isGroup = true; + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR GroupTriggerEffectSwitchCommandHandler(int argc, char ** argv) +{ + BindingCommandData * data = Platform::New(); + data->commandId = Clusters::Identify::Commands::TriggerEffect::Id; + data->clusterId = Clusters::Identify::Id; + data->args[0] = atoi(argv[0]); + data->args[1] = atoi(argv[1]); + data->isGroup = true; + + DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} +#endif // CONFIG_CHIP_LIB_SHELL diff --git a/examples/light-switch-app/telink/include/binding-handler.h b/examples/light-switch-app/telink/include/binding-handler.h index 6d1bb9717fd713..10dbc7a27af828 100755 --- a/examples/light-switch-app/telink/include/binding-handler.h +++ b/examples/light-switch-app/telink/include/binding-handler.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 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. @@ -27,8 +27,11 @@ void BindingWorkerFunction(intptr_t context); struct BindingCommandData { + chip::AttributeId attributeId; chip::EndpointId localEndpointId = 1; chip::CommandId commandId; chip::ClusterId clusterId; - bool isGroup = false; + bool isGroup = false; + bool isReadAttribute = false; + uint32_t args[7]; }; diff --git a/examples/light-switch-app/telink/src/binding-handler.cpp b/examples/light-switch-app/telink/src/binding-handler.cpp index 23ab22ff454b98..22c83a8b9fd788 100644 --- a/examples/light-switch-app/telink/src/binding-handler.cpp +++ b/examples/light-switch-app/telink/src/binding-handler.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 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. @@ -16,8 +16,8 @@ */ #include "binding-handler.h" - #include "AppConfig.h" +#include "IdentifyCommand.h" #include "app/CommandSender.h" #include "app/clusters/bindings/BindingManager.h" #include "app/server/Server.h" @@ -113,24 +113,46 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation BindingCommandData * data = static_cast(context); data->isGroup = IsGroupBound(); - if (binding.type == MATTER_MULTICAST_BINDING && data->isGroup) + if (data->isReadAttribute) { - switch (data->clusterId) + // It should always enter here if isReadAttribute is true + if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { - case Clusters::OnOff::Id: - ProcessOnOffGroupBindingCommand(data->commandId, binding); - break; + switch (data->clusterId) + { + case Clusters::Identify::Id: + ProcessIdentifyUnicastBindingRead(data, binding, peer_device); + break; + } } } - else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) + else { - switch (data->clusterId) + if (binding.type == MATTER_MULTICAST_BINDING && data->isGroup) + { + switch (data->clusterId) + { + case Clusters::Identify::Id: + ProcessIdentifyGroupBindingCommand(data, binding); + break; + case Clusters::OnOff::Id: + ProcessOnOffGroupBindingCommand(data->commandId, binding); + break; + } + } + else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { - case Clusters::OnOff::Id: - VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); - ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), - peer_device->GetSecureSession().Value()); - break; + switch (data->clusterId) + { + case Clusters::Identify::Id: + ProcessIdentifyUnicastBindingCommand(data, binding, peer_device); + break; + case Clusters::OnOff::Id: + VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), + peer_device->GetSecureSession().Value()); + break; + } } } } @@ -346,11 +368,26 @@ static void RegisterSwitchCommands() { static const shell_command_t sSwitchSubCommands[] = { { &SwitchHelpHandler, "help", "Usage: switch " }, + { &IdentifySwitchCommandHandler, "identify", " Usage: switch identify " }, { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff " }, { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups " }, { &BindingSwitchCommandHandler, "binding", "Usage: switch binding " } }; + static const shell_command_t sSwitchIdentifySubCommands[] = { + { &IdentifyHelpHandler, "help", "Usage: switch identify " }, + { &IdentifyCommandHandler, "identify", "identify Usage: switch identify identify" }, + { &TriggerEffectSwitchCommandHandler, "triggereffect", "triggereffect Usage: switch identify triggereffect" }, + { &IdentifyRead, "read", "Usage : switch identify read " } + }; + + static const shell_command_t sSwitchIdentifyReadSubCommands[] = { + { &IdentifyReadHelpHandler, "help", "Usage : switch identify read " }, + { &IdentifyReadAttributeList, "attlist", "Read attribute list" }, + { &IdentifyReadIdentifyTime, "identifytime", "Read identifytime attribute" }, + { &IdentifyReadIdentifyType, "identifytype", "Read identifytype attribute" }, + }; + static const shell_command_t sSwitchOnOffSubCommands[] = { { &OnOffHelpHandler, "help", "Usage : switch ononff " }, { &OnSwitchCommandHandler, "on", "Sends on command to bound lighting app" }, @@ -362,6 +399,12 @@ static void RegisterSwitchCommands() { &GroupsOnOffSwitchCommandHandler, "onoff", "Usage: switch groups onoff " } }; + static const shell_command_t sSwitchGroupsIdentifySubCommands[] = { + { &GroupsIdentifyHelpHandler, "help", "Usage: switch groups onoff " }, + { &GroupIdentifyCommandHandler, "identify", "Sends identify command to bound group" }, + { &GroupTriggerEffectSwitchCommandHandler, "triggereffect", "Sends triggereffect command to group" }, + }; + static const shell_command_t sSwitchGroupsOnOffSubCommands[] = { { &GroupsOnOffHelpHandler, "help", "Usage: switch groups onoff " }, { &GroupOnSwitchCommandHandler, "on", "Sends on command to bound group" }, @@ -378,7 +421,11 @@ static void RegisterSwitchCommands() static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch", "Light-switch commands. Usage: switch " }; + sShellSwitchGroupsIdentifySubCommands.RegisterCommands(sSwitchGroupsIdentifySubCommands, + ArraySize(sSwitchGroupsIdentifySubCommands)); sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwitchGroupsOnOffSubCommands, ArraySize(sSwitchGroupsOnOffSubCommands)); + sShellSwitchIdentifySubCommands.RegisterCommands(sSwitchIdentifySubCommands, ArraySize(sSwitchIdentifySubCommands)); + sShellSwitchIdentifyReadSubCommands.RegisterCommands(sSwitchIdentifyReadSubCommands, ArraySize(sSwitchIdentifyReadSubCommands)); sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands)); sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands)); sShellSwitchBindingSubCommands.RegisterCommands(sSwitchBindingSubCommands, ArraySize(sSwitchBindingSubCommands)); diff --git a/examples/lighting-app/telink/src/AppTask.cpp b/examples/lighting-app/telink/src/AppTask.cpp index bb4dc4150db2be..f250de450def21 100644 --- a/examples/lighting-app/telink/src/AppTask.cpp +++ b/examples/lighting-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022-2023 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -48,7 +48,7 @@ void AppTask::PowerOnFactoryReset(void) { LOG_INF("Lighting App Power On Factory Reset"); AppEvent event; - event.Type = AppEvent::kEventType_Lighting; + event.Type = AppEvent::kEventType_DeviceAction; event.Handler = PowerOnFactoryResetEventHandler; GetAppTask().PostEvent(&event); } @@ -77,7 +77,7 @@ CHIP_ERROR AppTask::Init(void) if (status == Protocols::InteractionModel::Status::Success) { // Set actual state to stored before reboot - SetInitiateAction(storedValue ? ON_ACTION : OFF_ACTION, static_cast(AppEvent::kEventType_Lighting), nullptr); + SetInitiateAction(storedValue ? ON_ACTION : OFF_ACTION, static_cast(AppEvent::kEventType_DeviceAction), nullptr); } return CHIP_NO_ERROR; @@ -88,10 +88,10 @@ void AppTask::LightingActionEventHandler(AppEvent * aEvent) Fixture_Action action = INVALID_ACTION; int32_t actor = 0; - if (aEvent->Type == AppEvent::kEventType_Lighting) + if (aEvent->Type == AppEvent::kEventType_DeviceAction) { - action = static_cast(aEvent->LightingEvent.Action); - actor = aEvent->LightingEvent.Actor; + action = static_cast(aEvent->DeviceEvent.Action); + actor = aEvent->DeviceEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { diff --git a/examples/lighting-app/telink/src/ZclCallbacks.cpp b/examples/lighting-app/telink/src/ZclCallbacks.cpp index 75b43f7c39eee1..e28d31c833de43 100644 --- a/examples/lighting-app/telink/src/ZclCallbacks.cpp +++ b/examples/lighting-app/telink/src/ZclCallbacks.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,14 +42,14 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & { ChipLogDetail(Zcl, "Cluster OnOff: attribute OnOff set to %u", *value); GetAppTask().SetInitiateAction(*value ? AppTask::ON_ACTION : AppTask::OFF_ACTION, - static_cast(AppEvent::kEventType_Lighting), value); + static_cast(AppEvent::kEventType_DeviceAction), value); } else if (clusterId == LevelControl::Id && attributeId == LevelControl::Attributes::CurrentLevel::Id) { if (GetAppTask().IsTurnedOn()) { ChipLogDetail(Zcl, "Cluster LevelControl: attribute CurrentLevel set to %u", *value); - GetAppTask().SetInitiateAction(AppTask::LEVEL_ACTION, static_cast(AppEvent::kEventType_Lighting), value); + GetAppTask().SetInitiateAction(AppTask::LEVEL_ACTION, static_cast(AppEvent::kEventType_DeviceAction), value); } else { @@ -79,7 +79,7 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & } ChipLogDetail(Zcl, "New XY color: %u|%u", xy.x, xy.y); - GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_XY, static_cast(AppEvent::kEventType_Lighting), + GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_XY, static_cast(AppEvent::kEventType_DeviceAction), (uint8_t *) &xy); } /* HSV color space */ @@ -101,14 +101,15 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & hsv.s = *value; } ChipLogDetail(Zcl, "New HSV color: hue = %u| saturation = %u", hsv.h, hsv.s); - GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_HSV, static_cast(AppEvent::kEventType_Lighting), + GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_HSV, static_cast(AppEvent::kEventType_DeviceAction), (uint8_t *) &hsv); } /* Temperature Mireds color space */ else if (attributeId == ColorControl::Attributes::ColorTemperatureMireds::Id) { ChipLogDetail(Zcl, "New Temperature Mireds color = %u", *(uint16_t *) value); - GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_CT, static_cast(AppEvent::kEventType_Lighting), value); + GetAppTask().SetInitiateAction(AppTask::COLOR_ACTION_CT, static_cast(AppEvent::kEventType_DeviceAction), + value); } else { diff --git a/examples/lock-app/telink/src/AppTask.cpp b/examples/lock-app/telink/src/AppTask.cpp index 46e34db66710e5..540a14f76f64ba 100644 --- a/examples/lock-app/telink/src/AppTask.cpp +++ b/examples/lock-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -130,11 +130,11 @@ void AppTask::LockActionEventHandler(AppEvent * aEvent) { case LockManager::kState_NotFulyLocked: case LockManager::kState_LockCompleted: - LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION, LockManager::OperationSource::kButton, + LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::UNLOCK_ACTION, LockManager::OperationSource::kButton, kExampleEndpointId); break; case LockManager::kState_UnlockCompleted: - LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION, LockManager::OperationSource::kButton, + LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::LOCK_ACTION, LockManager::OperationSource::kButton, kExampleEndpointId); break; default: diff --git a/examples/lock-app/telink/src/ZclCallbacks.cpp b/examples/lock-app/telink/src/ZclCallbacks.cpp index 7eaf0b303fd697..e4bd320981877c 100644 --- a/examples/lock-app/telink/src/ZclCallbacks.cpp +++ b/examples/lock-app/telink/src/ZclCallbacks.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,7 +75,7 @@ bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const N { ChipLogProgress(Zcl, "Door Lock App: Lock Command endpoint=%d", endpointId); - return LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION, LockManager::OperationSource::kRemote, + return LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::LOCK_ACTION, LockManager::OperationSource::kRemote, endpointId, err, fabricIdx, nodeId, pinCode); } @@ -85,8 +85,8 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const { ChipLogProgress(Zcl, "Door Lock App: Unlock Command endpoint=%d", endpointId); - return LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION, LockManager::OperationSource::kRemote, - endpointId, err, fabricIdx, nodeId, pinCode); + return LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::UNLOCK_ACTION, + LockManager::OperationSource::kRemote, endpointId, err, fabricIdx, nodeId, pinCode); } // TODO : Add helper function to call from the Unlock command if we establish Unbolt doesn't need a different behaviour than Unlock @@ -96,8 +96,8 @@ bool emberAfPluginDoorLockOnDoorUnboltCommand(chip::EndpointId endpointId, const { ChipLogProgress(Zcl, "Door Lock App: Unbolt Command endpoint=%d", endpointId); - return LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::UNBOLT_ACTION, LockManager::OperationSource::kRemote, - endpointId, err, fabricIdx, nodeId, pinCode); + return LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::UNBOLT_ACTION, + LockManager::OperationSource::kRemote, endpointId, err, fabricIdx, nodeId, pinCode); } bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, CredentialTypeEnum credentialType, @@ -170,5 +170,6 @@ DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t h void emberAfPluginDoorLockOnAutoRelock(chip::EndpointId endpointId) { // Apply the relock state in the application control - LockMgr().LockAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION, LockManager::OperationSource::kRemote, endpointId); + LockMgr().LockAction(AppEvent::kEventType_DeviceAction, LockManager::LOCK_ACTION, LockManager::OperationSource::kRemote, + endpointId); } diff --git a/examples/platform/telink/common/include/AppEventCommon.h b/examples/platform/telink/common/include/AppEventCommon.h index b9fa40ece20bc5..dea362f24c50a7 100644 --- a/examples/platform/telink/common/include/AppEventCommon.h +++ b/examples/platform/telink/common/include/AppEventCommon.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,15 +31,9 @@ struct AppEvent { kEventType_Button = 0, kEventType_Timer, - kEventType_UpdateLedState, kEventType_IdentifyStart, kEventType_IdentifyStop, - kEventType_Lighting, - kEventType_Thermostat, - kEventType_Install, - kEventType_Contact, - kEventType_Start, - kEventType_Lock + kEventType_DeviceAction }; uint16_t Type; @@ -58,20 +52,7 @@ struct AppEvent { uint8_t Action; int32_t Actor; - } LightingEvent; - struct - { - uint8_t Action; - } ContactEvent; - struct - { - uint8_t Action; - int32_t Actor; - } StartEvent; - struct - { - LEDWidget * LedWidget; - } UpdateLedStateEvent; + } DeviceEvent; }; EventHandler Handler; diff --git a/examples/platform/telink/common/include/AppTaskCommon.h b/examples/platform/telink/common/include/AppTaskCommon.h index 6218427e963a51..b1e5ad356692bb 100644 --- a/examples/platform/telink/common/include/AppTaskCommon.h +++ b/examples/platform/telink/common/include/AppTaskCommon.h @@ -56,6 +56,8 @@ class LedManager; class PwmManager; class ButtonManager; +struct Identify; + class AppTaskCommon { public: @@ -66,6 +68,8 @@ class AppTaskCommon void PostEvent(AppEvent * event); static void IdentifyEffectHandler(Clusters::Identify::EffectIdentifierEnum aEffect); + static void IdentifyStartHandler(Identify *); + static void IdentifyStopHandler(Identify *); #ifdef CONFIG_CHIP_PW_RPC enum ButtonId_t diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index 9f268b74da3e55..5ddf137eb36923 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -88,20 +89,16 @@ void OnIdentifyTriggerEffect(Identify * identify) } Identify sIdentify = { - kExampleEndpointId, - [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStart"); }, - [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStop"); }, - Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, + kExampleEndpointId, AppTask::IdentifyStartHandler, + AppTask::IdentifyStopHandler, Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, OnIdentifyTriggerEffect, }; #endif -#if CONFIG_CHIP_FACTORY_DATA // NOTE! This key is for test/certification only and should not be available in production devices! uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; -#endif class AppCallbacks : public AppDelegate { @@ -271,8 +268,15 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) // Init ZCL Data Model and start server static CommonCaseDeviceServerInitParams initParams; + static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; + VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); +#if CONFIG_CHIP_OTA_REQUESTOR + static OTATestEventTriggerHandler sOtaTestEventTriggerHandler{}; + VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); +#endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.appDelegate = &sCallbacks; + initParams.appDelegate = &sCallbacks; + initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); #if APP_SET_DEVICE_INFO_PROVIDER @@ -314,6 +318,30 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) return CHIP_NO_ERROR; } +void AppTaskCommon::IdentifyStartHandler(Identify *) +{ + AppEvent event; + + event.Type = AppEvent::kEventType_IdentifyStart; + event.Handler = [](AppEvent * event) { + ChipLogProgress(Zcl, "OnIdentifyStart"); + PwmManager::getInstance().setPwmBlink(PwmManager::EAppPwm_Indication, kIdentifyBlinkRateMs, kIdentifyBlinkRateMs); + }; + GetAppTask().PostEvent(&event); +} + +void AppTaskCommon::IdentifyStopHandler(Identify *) +{ + AppEvent event; + + event.Type = AppEvent::kEventType_IdentifyStop; + event.Handler = [](AppEvent * event) { + ChipLogProgress(Zcl, "OnIdentifyStop"); + PwmManager::getInstance().setPwm(PwmManager::EAppPwm_Indication, false); + }; + GetAppTask().PostEvent(&event); +} + #ifdef CONFIG_CHIP_PW_RPC void AppTaskCommon::ButtonEventHandler(ButtonId_t btnId, bool btnPressed) { diff --git a/examples/pump-app/telink/src/AppTask.cpp b/examples/pump-app/telink/src/AppTask.cpp index a7a360b934cd8f..10e58c3e2edc73 100644 --- a/examples/pump-app/telink/src/AppTask.cpp +++ b/examples/pump-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -85,10 +85,10 @@ void AppTask::ActionCompleted(PumpManager::Action_t action, int32_t actor) void AppTask::PostStartActionRequest(int32_t actor, PumpManager::Action_t action) { AppEvent event; - event.Type = AppEvent::kEventType_Start; - event.StartEvent.Actor = actor; - event.StartEvent.Action = action; - event.Handler = StartActionEventHandler; + event.Type = AppEvent::kEventType_DeviceAction; + event.DeviceEvent.Actor = actor; + event.DeviceEvent.Action = action; + event.Handler = StartActionEventHandler; sAppTask.PostEvent(&event); } @@ -97,10 +97,10 @@ void AppTask::StartActionEventHandler(AppEvent * aEvent) PumpManager::Action_t action = PumpManager::INVALID_ACTION; int32_t actor = 0; - if (aEvent->Type == AppEvent::kEventType_Start) + if (aEvent->Type == AppEvent::kEventType_DeviceAction) { - action = static_cast(aEvent->StartEvent.Action); - actor = aEvent->StartEvent.Actor; + action = static_cast(aEvent->DeviceEvent.Action); + actor = aEvent->DeviceEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { diff --git a/examples/pump-controller-app/telink/src/AppTask.cpp b/examples/pump-controller-app/telink/src/AppTask.cpp index 681f0fa4fd799e..b36888cda159fd 100644 --- a/examples/pump-controller-app/telink/src/AppTask.cpp +++ b/examples/pump-controller-app/telink/src/AppTask.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,10 +47,10 @@ void AppTask::StartActionEventHandler(AppEvent * aEvent) PumpManager::Action_t action = PumpManager::INVALID_ACTION; int32_t actor = 0; - if (aEvent->Type == AppEvent::kEventType_Start) + if (aEvent->Type == AppEvent::kEventType_DeviceAction) { - action = static_cast(aEvent->StartEvent.Action); - actor = aEvent->StartEvent.Actor; + action = static_cast(aEvent->DeviceEvent.Action); + actor = aEvent->DeviceEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { @@ -103,10 +103,10 @@ void AppTask::ActionCompleted(PumpManager::Action_t action, int32_t actor) void AppTask::PostStartActionRequest(int32_t actor, PumpManager::Action_t action) { AppEvent event; - event.Type = AppEvent::kEventType_Start; - event.StartEvent.Actor = actor; - event.StartEvent.Action = action; - event.Handler = StartActionEventHandler; + event.Type = AppEvent::kEventType_DeviceAction; + event.DeviceEvent.Actor = actor; + event.DeviceEvent.Action = action; + event.Handler = StartActionEventHandler; sAppTask.PostEvent(&event); } diff --git a/scripts/tools/telink/mfg_tool.py b/scripts/tools/telink/mfg_tool.py index c55e1fe4ca3c4a..dcc41d788215d9 100644 --- a/scripts/tools/telink/mfg_tool.py +++ b/scripts/tools/telink/mfg_tool.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (c) 2022 Project CHIP Authors +# Copyright (c) 2022-2024 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. @@ -671,6 +671,7 @@ def base64_str(s): return base64.b64decode(s) check_str_range(args.hw_ver_str, 1, 64, 'Hardware version string') check_str_range(args.mfg_date, 8, 16, 'Manufacturing date') check_str_range(args.rd_id_uid, 16, 32, 'Rotating device Unique id') + check_str_range(args.enable_key, 32, 32, 'Enable Key') # Validates the attestation related arguments # DAC key and DAC cert both should be present or none diff --git a/src/platform/telink/FactoryDataProvider.cpp b/src/platform/telink/FactoryDataProvider.cpp index 806cdb2cfe9391..ba02131911370f 100644 --- a/src/platform/telink/FactoryDataProvider.cpp +++ b/src/platform/telink/FactoryDataProvider.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 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. @@ -18,7 +18,7 @@ #include "FactoryDataProvider.h" #include "CHIPDevicePlatformConfig.h" #include - +#include #if CONFIG_CHIP_CERTIFICATION_DECLARATION_STORAGE #include #include @@ -329,11 +329,12 @@ template CHIP_ERROR FactoryDataProvider::GetEnableKey(MutableByteSpan & enableKey) { ReturnErrorCodeIf(!mFactoryData.enable_key.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); - ReturnErrorCodeIf(enableKey.size() < mFactoryData.enable_key.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(enableKey.size() < mFactoryData.enable_key.len / 2, CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(enableKey.data(), mFactoryData.enable_key.data, mFactoryData.enable_key.len); + Encoding::HexToBytes((const char *) mFactoryData.enable_key.data, mFactoryData.enable_key.len, enableKey.data(), + enableKey.size()); - enableKey.reduce_size(mFactoryData.enable_key.len); + enableKey.reduce_size(mFactoryData.enable_key.len / 2); return CHIP_NO_ERROR; }