From 9474988d5960449e7afa79238e7d5b2609267a6a Mon Sep 17 00:00:00 2001 From: Michael Rupp <95718139+mykrupp@users.noreply.github.com> Date: Fri, 21 Oct 2022 18:42:40 -0400 Subject: [PATCH] EFR32 lock event generation using matter shell (#23248) * EFR32 lock event generation using matter shell code review comment cleanup * code review comments --- examples/lock-app/efr32/BUILD.gn | 4 + examples/lock-app/efr32/include/AppTask.h | 3 + .../efr32/include/EventHandlerLibShell.h | 40 ++++ examples/lock-app/efr32/src/AppTask.cpp | 12 + .../efr32/src/EventHandlerLibShell.cpp | 211 ++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 examples/lock-app/efr32/include/EventHandlerLibShell.h create mode 100644 examples/lock-app/efr32/src/EventHandlerLibShell.cpp diff --git a/examples/lock-app/efr32/BUILD.gn b/examples/lock-app/efr32/BUILD.gn index fac904a047fee5..996cb0f086a67d 100644 --- a/examples/lock-app/efr32/BUILD.gn +++ b/examples/lock-app/efr32/BUILD.gn @@ -187,6 +187,10 @@ efr32_executable("lock_app") { sources += [ "${examples_plat_dir}/uart.cpp" ] } + if (chip_build_libshell) { + sources += [ "src/EventHandlerLibShell.cpp" ] + } + deps = [ ":sdk", "${chip_root}/examples/lock-app/lock-common", diff --git a/examples/lock-app/efr32/include/AppTask.h b/examples/lock-app/efr32/include/AppTask.h index a28837e776b85a..0c7723475772be 100644 --- a/examples/lock-app/efr32/include/AppTask.h +++ b/examples/lock-app/efr32/include/AppTask.h @@ -49,6 +49,9 @@ #define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) #define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) #define APP_ERROR_ALLOCATION_FAILED CHIP_APPLICATION_ERROR(0x07) +#if defined(ENABLE_CHIP_SHELL) +#define APP_ERROR_TOO_MANY_SHELL_ARGUMENTS CHIP_APPLICATION_ERROR(0x08) +#endif // ENABLE_CHIP_SHELL /********************************************************** * AppTask Declaration diff --git a/examples/lock-app/efr32/include/EventHandlerLibShell.h b/examples/lock-app/efr32/include/EventHandlerLibShell.h new file mode 100644 index 00000000000000..3ad9f11cbf2fdc --- /dev/null +++ b/examples/lock-app/efr32/include/EventHandlerLibShell.h @@ -0,0 +1,40 @@ +/* + * + * 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. + */ +#pragma once + +#include + +class EventData +{ +public: + chip::EventId eventId; +}; + +class AlarmEventData : public EventData +{ +public: + DlAlarmCode alarmCode; +}; + +class DoorStateEventData : public EventData +{ +public: + DlDoorState doorState; +}; + +CHIP_ERROR RegisterLockEvents(); +void EventWorkerFunction(intptr_t context); diff --git a/examples/lock-app/efr32/src/AppTask.cpp b/examples/lock-app/efr32/src/AppTask.cpp index f624eb50073234..ae683cc92f86b5 100644 --- a/examples/lock-app/efr32/src/AppTask.cpp +++ b/examples/lock-app/efr32/src/AppTask.cpp @@ -20,6 +20,9 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" +#if defined(ENABLE_CHIP_SHELL) +#include "EventHandlerLibShell.h" +#endif // ENABLE_CHIP_SHELL #ifdef ENABLE_WSTK_LEDS #include "LEDWidget.h" @@ -161,6 +164,15 @@ CHIP_ERROR AppTask::Init() appError(err); } +#if defined(ENABLE_CHIP_SHELL) + err = RegisterLockEvents(); + if (err != CHIP_NO_ERROR) + { + EFR32_LOG("RegisterLockEvents() failed"); + appError(err); + } +#endif // ENABLE_CHIP_SHELL + // Initial lock state chip::app::DataModel::Nullable state; chip::EndpointId endpointId{ 1 }; diff --git a/examples/lock-app/efr32/src/EventHandlerLibShell.cpp b/examples/lock-app/efr32/src/EventHandlerLibShell.cpp new file mode 100644 index 00000000000000..02979f56238a23 --- /dev/null +++ b/examples/lock-app/efr32/src/EventHandlerLibShell.cpp @@ -0,0 +1,211 @@ +/* + * + * 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 "EventHandlerLibShell.h" +#include "AppTask.h" +#include "lib/shell/Engine.h" +#include "lib/shell/commands/Help.h" + +#include "app/server/Server.h" +#include "platform/CHIPDeviceLayer.h" +#include + +constexpr uint8_t lockEndpoint = 1; + +using namespace chip; +using namespace chip::app; +using namespace Clusters::DoorLock; +using Shell::Engine; +using Shell::shell_command_t; +using Shell::streamer_get; +using Shell::streamer_printf; + +Engine sShellDoorlockSubCommands; +Engine sShellDoorlockEventSubCommands; +Engine sShellDoorlockEventAlarmSubCommands; +Engine sShellDoorlockEventDoorStateSubCommands; + +/******************************************************** + * Doorlock shell functions + *********************************************************/ + +CHIP_ERROR DoorlockHelpHandler(int argc, char ** argv) +{ + sShellDoorlockSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DoorlockCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return DoorlockHelpHandler(argc, argv); + } + + return sShellDoorlockSubCommands.ExecCommand(argc, argv); +} + +/******************************************************** + * Event shell functions + *********************************************************/ + +CHIP_ERROR EventHelpHandler(int argc, char ** argv) +{ + sShellDoorlockEventSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EventDoorlockCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return EventHelpHandler(argc, argv); + } + + return sShellDoorlockEventSubCommands.ExecCommand(argc, argv); +} + +/******************************************************** + * Alarm shell functions + *********************************************************/ + +CHIP_ERROR AlarmHelpHandler(int argc, char ** argv) +{ + sShellDoorlockEventAlarmSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR AlarmEventHandler(int argc, char ** argv) +{ + + if (argc == 0) + { + return AlarmHelpHandler(argc, argv); + } + if (argc >= 2) + { + ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__); + return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS; + } + + AlarmEventData * data = Platform::New(); + data->eventId = Events::DoorLockAlarm::Id; + data->alarmCode = static_cast(atoi(argv[0])); + + DeviceLayer::PlatformMgr().ScheduleWork(EventWorkerFunction, reinterpret_cast(data)); + + return CHIP_NO_ERROR; +} + +/******************************************************** + * Door state shell functions + *********************************************************/ + +CHIP_ERROR DoorStateHelpHandler(int argc, char ** argv) +{ + sShellDoorlockEventDoorStateSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DoorStateEventHandler(int argc, char ** argv) +{ + + if (argc == 0) + { + return DoorStateHelpHandler(argc, argv); + } + if (argc >= 2) + { + ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__); + return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS; + } + + DoorStateEventData * data = Platform::New(); + data->eventId = Events::DoorStateChange::Id; + data->doorState = static_cast(atoi(argv[0])); + + DeviceLayer::PlatformMgr().ScheduleWork(EventWorkerFunction, reinterpret_cast(data)); + + return CHIP_NO_ERROR; +} + +/** + * @brief configures lock matter shell + * + */ + +CHIP_ERROR RegisterLockEvents() +{ + static const shell_command_t sDoorlockSubCommands[] = { { &DoorlockHelpHandler, "help", "Usage: doorlock " }, + { &EventDoorlockCommandHandler, "event", + " Usage: doorlock event " } }; + + static const shell_command_t sDoorlockEventSubCommands[] = { + { &EventHelpHandler, "help", "Usage : doorlock event " }, + { &AlarmEventHandler, "lock-alarm", "Sends lock alarm event to lock app" }, + { &DoorStateEventHandler, "door-state-change", "Sends door state change event to lock app" } + }; + + static const shell_command_t sDoorlockEventAlarmSubCommands[] = { { &AlarmHelpHandler, "help", + "Usage : doorlock event lock-alarm AlarmCode" } }; + + static const shell_command_t sDoorlockEventDoorStateSubCommands[] = { + { &DoorStateHelpHandler, "help", "Usage : doorlock event door-state-change DoorState" } + }; + + static const shell_command_t sDoorLockCommand = { &DoorlockCommandHandler, "doorlock", + "doorlock commands. Usage: doorlock " }; + + sShellDoorlockEventAlarmSubCommands.RegisterCommands(sDoorlockEventAlarmSubCommands, ArraySize(sDoorlockEventAlarmSubCommands)); + + sShellDoorlockEventDoorStateSubCommands.RegisterCommands(sDoorlockEventDoorStateSubCommands, + ArraySize(sDoorlockEventDoorStateSubCommands)); + + sShellDoorlockEventSubCommands.RegisterCommands(sDoorlockEventSubCommands, ArraySize(sDoorlockEventSubCommands)); + sShellDoorlockSubCommands.RegisterCommands(sDoorlockSubCommands, ArraySize(sDoorlockSubCommands)); + + Engine::Root().RegisterCommands(&sDoorLockCommand, 1); + + return CHIP_NO_ERROR; +} + +void EventWorkerFunction(intptr_t context) +{ + VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "EventWorkerFunction - Invalid work data")); + + EventData * data = reinterpret_cast(context); + + switch (data->eventId) + { + case Events::DoorLockAlarm::Id: { + AlarmEventData * alarmData = reinterpret_cast(context); + DoorLockServer::Instance().SendLockAlarmEvent(lockEndpoint, alarmData->alarmCode); + break; + } + + case Events::DoorStateChange::Id: { + DoorStateEventData * doorStateData = reinterpret_cast(context); + DoorLockServer::Instance().SetDoorState(lockEndpoint, doorStateData->doorState); + break; + } + + default: { + ChipLogError(Zcl, "Invalid Event Id %s, line %d", __func__, __LINE__); + break; + } + } +}