From 5403065fdc17c2bd51194cfb429a37a59e878186 Mon Sep 17 00:00:00 2001 From: Michael Rupp <95718139+mykrupp@users.noreply.github.com> Date: Fri, 29 Apr 2022 14:55:55 -0400 Subject: [PATCH] Lock example for efr32 (#17651) Restyled by whitespace Restyled by clang-format Restyled by gn Remove duplicate user and credential structure. Utilize provided door lock server structure that uses Span.h Restyled by whitespace Restyled by clang-format Update lock-app documentation Restyled by prettier-markdown Add endpoint id to setlockstate function, add a todo comment for schedule functions fix comment, have unimplemented code return failure code review comments zap regen fix misspell reviewdog Restyled by whitespace Restyled by clang-format Restyled by gn bump timeout because it timed out Add includes to esp32 app, needed due to zap file updates update CMakeLists.txt for esp32 disable TI automation logging for size constraint remove some unused code manual restyle --- .github/workflows/examples-nrfconnect.yaml | 4 +- examples/lock-app/cc13x2x7_26x2x7/args.gni | 4 +- examples/lock-app/efr32/BUILD.gn | 23 +- examples/lock-app/efr32/README.md | 43 +- examples/lock-app/efr32/include/AppConfig.h | 6 +- examples/lock-app/efr32/include/AppTask.h | 8 +- .../lock-app/efr32/include/BoltLockManager.h | 85 ---- .../efr32/include/CHIPProjectConfig.h | 8 +- .../lock-app/efr32/include/FreeRTOSConfig.h | 4 +- examples/lock-app/efr32/include/LockManager.h | 114 +++++ examples/lock-app/efr32/src/AppTask.cpp | 219 +++++++-- .../lock-app/efr32/src/BoltLockManager.cpp | 225 ---------- examples/lock-app/efr32/src/LockManager.cpp | 421 ++++++++++++++++++ examples/lock-app/efr32/src/ZclCallbacks.cpp | 100 ++++- examples/lock-app/efr32/src/main.cpp | 56 ++- examples/lock-app/efr32/with_pw_rpc.gni | 1 - examples/lock-app/esp32/main/CMakeLists.txt | 4 + examples/lock-app/lock-common/lock-app.matter | 95 ++++ examples/lock-app/lock-common/lock-app.zap | 40 +- src/platform/EFR32/EFR32Config.h | 5 + .../zap-generated/IMClusterCommandHandler.cpp | 134 ++++++ .../PluginApplicationCallbacks.h | 2 + zzz_generated/lock-app/zap-generated/access.h | 18 + .../lock-app/zap-generated/callback-stub.cpp | 16 + .../lock-app/zap-generated/endpoint_config.h | 91 +++- .../lock-app/zap-generated/gen_config.h | 12 + 26 files changed, 1289 insertions(+), 449 deletions(-) delete mode 100644 examples/lock-app/efr32/include/BoltLockManager.h create mode 100644 examples/lock-app/efr32/include/LockManager.h delete mode 100644 examples/lock-app/efr32/src/BoltLockManager.cpp create mode 100644 examples/lock-app/efr32/src/LockManager.cpp diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index f2d1c5ee108c62..96b09cb932add4 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -25,7 +25,7 @@ concurrency: jobs: nrfconnect: name: nRF Connect SDK - timeout-minutes: 120 + timeout-minutes: 125 env: BUILD_TYPE: nrfconnect @@ -174,7 +174,7 @@ jobs: examples/pump-controller-app/nrfconnect/build/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK All Clusters App on nRF52840 DK - timeout-minutes: 10 + timeout-minutes: 15 run: | scripts/examples/nrfconnect_example.sh all-clusters-app nrf52840dk_nrf52840 -DCONF_FILE=prj_dfu.conf .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ diff --git a/examples/lock-app/cc13x2x7_26x2x7/args.gni b/examples/lock-app/cc13x2x7_26x2x7/args.gni index ebb3a78797278f..d982dce73c11c5 100644 --- a/examples/lock-app/cc13x2x7_26x2x7/args.gni +++ b/examples/lock-app/cc13x2x7_26x2x7/args.gni @@ -30,8 +30,8 @@ chip_enable_ota_requestor = true # Disable CHIP Logging #chip_progress_logging = false -#chip_detail_logging = false -#chip_automation_logging = false +chip_detail_logging = false +chip_automation_logging = false # BLE options chip_config_network_layer_ble = true diff --git a/examples/lock-app/efr32/BUILD.gn b/examples/lock-app/efr32/BUILD.gn index f9bbbcab940988..56b75c8530a6d9 100644 --- a/examples/lock-app/efr32/BUILD.gn +++ b/examples/lock-app/efr32/BUILD.gn @@ -15,9 +15,9 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("//build_overrides/efr32_sdk.gni") +import("//build_overrides/pigweed.gni") import("${build_root}/config/defaults.gni") - import("${efr32_sdk_build_root}/efr32_executable.gni") import("${efr32_sdk_build_root}/efr32_sdk.gni") @@ -40,6 +40,7 @@ declare_args() { # PIN code for PASE session establishment. setupPinCode = 20202021 + setupDiscriminator = 3840 # Monitor & log memory usage at runtime. enable_heap_monitoring = false @@ -115,6 +116,7 @@ efr32_sdk("sdk") { defines = [ "BOARD_ID=${efr32_board}", "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setupDiscriminator}", "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}", ] @@ -124,13 +126,6 @@ efr32_sdk("sdk") { "PW_RPC_ENABLED", ] } - if (use_rs911x) { - defines += rs911x_defs - include_dirs += rs911x_plat_incs - } else if (use_wf200) { - defines += wf200_defs - include_dirs += wf200_plat_incs - } # WiFi Settings if (chip_enable_wifi) { @@ -149,7 +144,6 @@ efr32_sdk("sdk") { # Using LWIP instead of the native TCP/IP stack defines += efr32_lwip_defs } - if (sl_wfx_config_softap) { defines += [ "SL_WFX_CONFIG_SOFTAP" ] } @@ -162,7 +156,6 @@ efr32_sdk("sdk") { efr32_executable("lock_app") { output_name = "chip-efr32-lock-example.out" include_dirs = [ "include" ] - defines = [] sources = [ @@ -170,7 +163,7 @@ efr32_executable("lock_app") { "${examples_plat_dir}/heap_4_silabs.c", "${examples_plat_dir}/init_efrPlatform.cpp", "src/AppTask.cpp", - "src/BoltLockManager.cpp", + "src/LockManager.cpp", "src/ZclCallbacks.cpp", "src/main.cpp", ] @@ -248,7 +241,6 @@ efr32_executable("lock_app") { defines += [ "DISPLAY_ENABLED" ] if (show_qr_code) { defines += [ "QR_CODE_ENABLED" ] - deps += [ "${chip_root}/examples/common/QRCode" ] } } @@ -295,16 +287,16 @@ efr32_executable("lock_app") { } if (enable_heap_monitoring) { - defines += [ "HEAP_MONITORING" ] sources += [ "${examples_plat_dir}/MemMonitoring.cpp" ] + defines += [ "HEAP_MONITORING" ] } ldscript = "${examples_plat_dir}/ldscripts/${efr32_family}.ld" - ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] - inputs = [ ldscript ] + ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + if (chip_print_memory_usage) { ldflags += [ "-Wl,--print-memory-usage", @@ -322,7 +314,6 @@ efr32_executable("lock_app") { output_dir = root_out_dir } - group("efr32") { deps = [ ":lock_app" ] } diff --git a/examples/lock-app/efr32/README.md b/examples/lock-app/efr32/README.md index ab1fe655e5a037..b8a4e5e1730d8b 100644 --- a/examples/lock-app/efr32/README.md +++ b/examples/lock-app/efr32/README.md @@ -262,9 +262,9 @@ combination with JLinkRTTClient as follows: **LED 1** Simulates the Lock The following states are possible: - - _Solid On_ ; Bolt is locked + - _Solid On_ ; Bolt is unlocked - _Blinking_ ; Bolt is moving to the desired state - - _Off_ ; Bolt is unlocked + - _Off_ ; Bolt is locked **Push Button 0** @@ -284,12 +284,47 @@ combination with JLinkRTTClient as follows: [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md) - Here is an example with the CHIPTool: +Here is some CHIPTool examples: + Pairing with chip-tool: ``` chip-tool pairing ble-thread 1 hex: 20202021 3840 + ``` - chip-tool onoff toggle 1 1 + Set a user: + ``` + ./out/chip-tool doorlock set-user OperationType UserIndex UserName UserUniqueId UserStatus UserType CredentialRule node-id/group-id + ./out/chip-tool doorlock set-user 0 1 "mike" 5 1 0 0 1 1 --timedInteractionTimeoutMs 1000 + ``` + + Set a credential: + ``` + ./out/chip-tool doorlock set-credential OperationType Credential CredentialData UserIndex UserStatus UserType node-id/group-id + ./out/chip-tool doorlock set-credential 0 '{ "credentialType": 1, "credentialIndex": 1 }' "123456" 1 null null 1 1 --timedInteractionTimeoutMs 1000 + ``` + + Changing a credential: + ``` + ./out/chip-tool doorlock set-credential OperationType Credential CredentialData UserIndex UserStatus UserType node-id/group-id + ./out/chip-tool doorlock set-credential 2 '{ "credentialType": 1, "credentialIndex": 1 }' "123457" 1 null null 1 1 --timedInteractionTimeoutMs 1000 + ``` + + Get a user: + ``` + ./out/chip-tool doorlock get-user UserIndex node-id/group-id + ./out/chip-tool doorlock get-user 1 1 1 + ``` + + Unlock door: + ``` + ./out/chip-tool doorlock unlock-door node-id/group-id + ./out/chip-tool doorlock unlock-door 1 1 + ``` + + Lock door: + ``` + ./out/chip-tool doorlock lock-door node-id/group-id + ./out/chip-tool doorlock lock-door 1 1 ``` ### Notes diff --git a/examples/lock-app/efr32/include/AppConfig.h b/examples/lock-app/efr32/include/AppConfig.h index 84b588c4997970..852083cb9cbd91 100644 --- a/examples/lock-app/efr32/include/AppConfig.h +++ b/examples/lock-app/efr32/include/AppConfig.h @@ -19,13 +19,13 @@ #pragma once -// ---- Lock Example App Config ---- +// ---- Door lock Example App Config ---- -#define APP_TASK_NAME "Lck" +#define APP_TASK_NAME "Lock" // Time it takes in ms for the simulated actuator to move from one // state to another. -#define ACTUATOR_MOVEMENT_PERIOS_MS 2000 +#define ACTUATOR_MOVEMENT_PERIOS_MS 10 // EFR Logging #ifdef __cplusplus diff --git a/examples/lock-app/efr32/include/AppTask.h b/examples/lock-app/efr32/include/AppTask.h index 9c871c2bfcae54..67803623f2fbc8 100644 --- a/examples/lock-app/efr32/include/AppTask.h +++ b/examples/lock-app/efr32/include/AppTask.h @@ -23,7 +23,7 @@ #include #include "AppEvent.h" -#include "BoltLockManager.h" +#include "LockManager.h" #include "sl_simple_button_instances.h" #include "FreeRTOS.h" @@ -46,7 +46,7 @@ class AppTask CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); - void PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction); + void ActionRequest(int32_t aActor, LockManager::Action_t aAction); void PostEvent(const AppEvent * event); void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction); @@ -56,8 +56,8 @@ class AppTask CHIP_ERROR Init(); - static void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor); - static void ActionCompleted(BoltLockManager::Action_t aAction); + static void ActionInitiated(LockManager::Action_t aAction, int32_t aActor); + static void ActionCompleted(LockManager::Action_t aAction); void CancelTimer(void); diff --git a/examples/lock-app/efr32/include/BoltLockManager.h b/examples/lock-app/efr32/include/BoltLockManager.h deleted file mode 100644 index febb9b7c071928..00000000000000 --- a/examples/lock-app/efr32/include/BoltLockManager.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Copyright (c) 2019 Google LLC. - * 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 "AppEvent.h" - -#include "FreeRTOS.h" -#include "timers.h" // provides FreeRTOS timer support - -#include - -class BoltLockManager -{ -public: - enum Action_t - { - LOCK_ACTION = 0, - UNLOCK_ACTION, - - INVALID_ACTION - } Action; - - enum State_t - { - kState_LockingInitiated = 0, - kState_LockingCompleted, - kState_UnlockingInitiated, - kState_UnlockingCompleted, - } State; - - CHIP_ERROR Init(); - bool IsUnlocked(); - void EnableAutoRelock(bool aOn); - void SetAutoLockDuration(uint32_t aDurationInSecs); - bool IsActionInProgress(); - bool InitiateAction(int32_t aActor, Action_t aAction); - - typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); - typedef void (*Callback_fn_completed)(Action_t); - void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); - -private: - friend BoltLockManager & BoltLockMgr(void); - State_t mState; - - Callback_fn_initiated mActionInitiated_CB; - Callback_fn_completed mActionCompleted_CB; - - bool mAutoRelock; - uint32_t mAutoLockDuration; - bool mAutoLockTimerArmed; - - void CancelTimer(void); - void StartTimer(uint32_t aTimeoutMs); - - static void TimerEventHandler(TimerHandle_t xTimer); - static void AutoReLockTimerEventHandler(AppEvent * aEvent); - static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); - - static BoltLockManager sLock; -}; - -inline BoltLockManager & BoltLockMgr(void) -{ - return BoltLockManager::sLock; -} diff --git a/examples/lock-app/efr32/include/CHIPProjectConfig.h b/examples/lock-app/efr32/include/CHIPProjectConfig.h index cc930f85bc796f..118cb5e3fd31f7 100644 --- a/examples/lock-app/efr32/include/CHIPProjectConfig.h +++ b/examples/lock-app/efr32/include/CHIPProjectConfig.h @@ -32,7 +32,10 @@ #ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 +#endif // For convenience, Chip Security Test Mode can be enabled and the // requirement for authentication in various protocols can be disabled. @@ -41,18 +44,19 @@ // including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS. // #define CHIP_CONFIG_SECURITY_TEST_MODE 0 +#define CHIP_CONFIG_REQUIRE_AUTH 1 /** * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID * - * 0xFFF1: Test vendor. + * 0xFFF1: Test vendor */ #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 /** * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID * - * 0x8006: example lock-app + * 0x8006: example lock app */ #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8006 diff --git a/examples/lock-app/efr32/include/FreeRTOSConfig.h b/examples/lock-app/efr32/include/FreeRTOSConfig.h index a747d9a8b413ca..54d7b544fda0ff 100644 --- a/examples/lock-app/efr32/include/FreeRTOSConfig.h +++ b/examples/lock-app/efr32/include/FreeRTOSConfig.h @@ -163,7 +163,7 @@ to all Cortex-M ports, and do not rely on any particular library functions. */ #define configKERNEL_INTERRUPT_PRIORITY (255) /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 48 // 96 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 48 #define configENABLE_FPU 0 #define configENABLE_MPU 0 /* FreeRTOS Secure Side Only and TrustZone Security Extension */ @@ -189,7 +189,7 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configUSE_TRACE_FACILITY 1 #define configQUEUE_REGISTRY_SIZE (10) #define configUSE_QUEUE_SETS (0) -#define configUSE_NEWLIB_REENTRANT (0) +#define configUSE_NEWLIB_REENTRANT (1) #define configENABLE_BACKWARD_COMPATIBILITY (1) #define configSUPPORT_STATIC_ALLOCATION (1) #define configSUPPORT_DYNAMIC_ALLOCATION (1) diff --git a/examples/lock-app/efr32/include/LockManager.h b/examples/lock-app/efr32/include/LockManager.h new file mode 100644 index 00000000000000..dad3c119884b18 --- /dev/null +++ b/examples/lock-app/efr32/include/LockManager.h @@ -0,0 +1,114 @@ +/* + * + * Copyright (c) 2019 Google LLC. + * 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 + +#include "AppEvent.h" + +#include "FreeRTOS.h" +#include "timers.h" // provides FreeRTOS timer support + +#include + +using namespace ::chip; + +#define DOOR_LOCK_MAX_CREDENTIAL_SIZE 8 + +static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 20; + +class LockManager +{ +public: + enum Action_t + { + LOCK_ACTION = 0, + UNLOCK_ACTION, + + INVALID_ACTION + } Action; + + enum State_t + { + kState_LockInitiated = 0, + kState_LockCompleted, + kState_UnlockInitiated, + kState_UnlockCompleted, + } State; + + CHIP_ERROR Init(chip::app::DataModel::Nullable state); + bool NextState(); + bool IsActionInProgress(); + bool InitiateAction(int32_t aActor, Action_t aAction); + + typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); + typedef void (*Callback_fn_completed)(Action_t); + void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); + + bool Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err); + bool Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err); + + bool GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const; + bool SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, const chip::CharSpan & userName, + uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * credentials, size_t totalCredentials); + + bool GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) const; + + bool SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData); + + bool setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, + DlOperationError & err); + const char * lockStateToString(DlLockState lockState) const; + + bool ReadConfigValues(); + +private: + friend LockManager & LockMgr(); + chip::EndpointId mEndpointId; + State_t mState; + + Callback_fn_initiated mActionInitiated_CB; + Callback_fn_completed mActionCompleted_CB; + + void CancelTimer(void); + void StartTimer(uint32_t aTimeoutMs); + + static void TimerEventHandler(TimerHandle_t xTimer); + static void AutoLockTimerEventHandler(AppEvent * aEvent); + static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); + + EmberAfPluginDoorLockUserInfo mLockUser; + EmberAfPluginDoorLockCredentialInfo mLockCredentials; + + char mUserName[DOOR_LOCK_MAX_USER_NAME_SIZE]; + uint8_t mCredentialData[DOOR_LOCK_MAX_CREDENTIAL_SIZE]; + DlCredential mCredentials[DOOR_LOCK_MAX_CREDENTIALS_PER_USER]; + + static LockManager sLock; +}; + +inline LockManager & LockMgr() +{ + return LockManager::sLock; +} diff --git a/examples/lock-app/efr32/src/AppTask.cpp b/examples/lock-app/efr32/src/AppTask.cpp index ec4bb10f44a964..1f593f41322ab2 100644 --- a/examples/lock-app/efr32/src/AppTask.cpp +++ b/examples/lock-app/efr32/src/AppTask.cpp @@ -26,9 +26,15 @@ #include "qrcodegen.h" #endif // DISPLAY_ENABLED #include "sl_simple_led_instances.h" +#include #include #include +#include #include +#include + +#include +#include #include #include #include @@ -38,11 +44,13 @@ #include #include -#include - #include #include +#include + +#include + #include #if CHIP_ENABLE_OPENTHREAD #include @@ -53,7 +61,7 @@ #include "wfx_host_events.h" #include #include -#endif +#endif /* SL_WIFI */ #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 @@ -64,12 +72,15 @@ #define SYSTEM_STATE_LED &sl_led_led0 #define LOCK_STATE_LED &sl_led_led1 #define APP_FUNCTION_BUTTON &sl_button_btn0 -#define APP_LOCK_BUTTON &sl_button_btn1 +#define APP_LOCK_SWITCH &sl_button_btn1 + +using chip::app::Clusters::DoorLock::DlLockState; +using chip::app::Clusters::DoorLock::DlOperationError; +using chip::app::Clusters::DoorLock::DlOperationSource; using namespace chip; -using namespace chip::TLV; -using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Internal; namespace { TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. @@ -87,23 +98,86 @@ bool sIsWiFiAttached = false; app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance())); -#endif +#endif /* SL_WIFI */ #if CHIP_ENABLE_OPENTHREAD bool sIsThreadProvisioned = false; bool sIsThreadEnabled = false; -#endif +#endif /* CHIP_ENABLE_OPENTHREAD */ bool sHaveBLEConnections = false; +bool configValueSet = false; + +EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT; + +uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(AppEvent)]; +StaticQueue_t sAppEventQueueStruct; StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; + +/********************************************************** + * Identify Callbacks + *********************************************************/ + +namespace { +void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState) +{ + sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT; +} +} // namespace + +void OnTriggerIdentifyEffect(Identify * identify) +{ + sIdentifyEffect = identify->mCurrentEffectIdentifier; + + if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE) + { + ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d", + identify->mEffectVariant); + sIdentifyEffect = static_cast(identify->mEffectVariant); + } + + switch (sIdentifyEffect) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted, + identify); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT: + (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify); + (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted, + identify); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT: + (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify); + sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT; + break; + default: + ChipLogProgress(Zcl, "No identifier effect"); + } +} + +Identify gIdentify = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED, + OnTriggerIdentifyEffect, +}; + } // namespace +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + AppTask AppTask::sAppTask; CHIP_ERROR AppTask::StartAppTask() { - sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); + sAppEventQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent), sAppEventQueueBuffer, &sAppEventQueueStruct); if (sAppEventQueue == NULL) { EFR32_LOG("Failed to allocate app event queue"); @@ -117,6 +191,8 @@ CHIP_ERROR AppTask::StartAppTask() CHIP_ERROR AppTask::Init() { + CHIP_ERROR err = CHIP_NO_ERROR; + #ifdef SL_WIFI /* * Wait for the WiFi to be initialized @@ -151,26 +227,42 @@ CHIP_ERROR AppTask::Init() } EFR32_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); - CHIP_ERROR err = BoltLockMgr().Init(); + + // Initial lock state + chip::app::DataModel::Nullable state; + chip::EndpointId endpointId{ 1 }; + chip::DeviceLayer::PlatformMgr().LockChipStack(); + chip::app::Clusters::DoorLock::Attributes::LockState::Get(endpointId, state); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + + err = LockMgr().Init(state); if (err != CHIP_NO_ERROR) { - EFR32_LOG("BoltLockMgr().Init() failed"); + EFR32_LOG("LockMgr().Init() failed"); appError(err); } - BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted); + LockMgr().SetCallbacks(ActionInitiated, ActionCompleted); // Initialize LEDs LEDWidget::InitGpio(); sStatusLED.Init(SYSTEM_STATE_LED); - sLockLED.Init(LOCK_STATE_LED); - sLockLED.Set(!BoltLockMgr().IsUnlocked()); + + if (state.Value() == DlLockState::kUnlocked) + { + sLockLED.Set(true); + } + else + { + sLockLED.Set(false); + } + chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr)); ConfigurationMgr().LogDeviceConfig(); - // Print setup info on LCD if available +// Print setup info on LCD if available #ifdef DISPLAY_ENABLED std::string QRCode; @@ -204,6 +296,13 @@ void AppTask::AppTaskMain(void * pvParameter) while (true) { + // Users and credentials should be checked once from nvm flash on boot + if (!configValueSet) + { + LockMgr().ReadConfigValues(); + configValueSet = true; + } + BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10)); while (eventReceived == pdTRUE) { @@ -222,11 +321,11 @@ void AppTask::AppTaskMain(void * pvParameter) sIsWiFiProvisioned = ConnectivityMgr().IsWiFiStationProvisioned(); sIsWiFiEnabled = ConnectivityMgr().IsWiFiStationEnabled(); sIsWiFiAttached = ConnectivityMgr().IsWiFiStationConnected(); -#endif +#endif /* SL_WIFI */ #if CHIP_ENABLE_OPENTHREAD sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned(); sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled(); -#endif +#endif /* CHIP_ENABLE_OPENTHREAD */ sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0); PlatformMgr().UnlockChipStack(); } @@ -245,6 +344,25 @@ void AppTask::AppTaskMain(void * pvParameter) // Otherwise, blink the LED ON for a very short time. if (sAppTask.mFunction != kFunction_FactoryReset) { + if (gIdentify.mActive) + { + sStatusLED.Blink(250, 250); + } + if (sIdentifyEffect != EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT) + { + if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK) + { + sStatusLED.Blink(50, 50); + } + if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE) + { + sStatusLED.Blink(1000, 1000); + } + if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY) + { + sStatusLED.Blink(300, 700); + } + } #if CHIP_ENABLE_OPENTHREAD if (sIsThreadProvisioned && sIsThreadEnabled) #else @@ -265,24 +383,24 @@ void AppTask::AppTaskMain(void * pvParameter) void AppTask::LockActionEventHandler(AppEvent * aEvent) { bool initiated = false; - BoltLockManager::Action_t action; + LockManager::Action_t action; int32_t actor; CHIP_ERROR err = CHIP_NO_ERROR; if (aEvent->Type == AppEvent::kEventType_Lock) { - action = static_cast(aEvent->LockEvent.Action); + action = static_cast(aEvent->LockEvent.Action); actor = aEvent->LockEvent.Actor; } else if (aEvent->Type == AppEvent::kEventType_Button) { - if (BoltLockMgr().IsUnlocked()) + if (LockMgr().NextState() == true) { - action = BoltLockManager::LOCK_ACTION; + action = LockManager::LOCK_ACTION; } else { - action = BoltLockManager::UNLOCK_ACTION; + action = LockManager::UNLOCK_ACTION; } actor = AppEvent::kEventType_Button; } @@ -293,7 +411,7 @@ void AppTask::LockActionEventHandler(AppEvent * aEvent) if (err == CHIP_NO_ERROR) { - initiated = BoltLockMgr().InitiateAction(actor, action); + initiated = LockMgr().InitiateAction(actor, action); if (!initiated) { @@ -313,7 +431,7 @@ void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAc button_event.Type = AppEvent::kEventType_Button; button_event.ButtonEvent.Action = btnAction; - if (buttonHandle == APP_LOCK_BUTTON && btnAction == SL_SIMPLE_BUTTON_PRESSED) + if (buttonHandle == APP_LOCK_SWITCH && btnAction == SL_SIMPLE_BUTTON_PRESSED) { button_event.Handler = LockActionEventHandler; sAppTask.PostEvent(&button_event); @@ -398,7 +516,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) if (!ConnectivityMgr().IsWiFiStationProvisioned()) #else if (!ConnectivityMgr().IsThreadProvisioned()) -#endif +#endif /* !SL_WIFI */ { // Enable BLE advertisements ConnectivityMgr().SetBLEAdvertisingEnabled(true); @@ -409,7 +527,7 @@ void AppTask::FunctionHandler(AppEvent * aEvent) else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset) { // Set lock status LED back to show state of lock. - sLockLED.Set(!BoltLockMgr().IsUnlocked()); + sLockLED.Set(!LockMgr().NextState()); sAppTask.CancelTimer(); @@ -453,43 +571,38 @@ void AppTask::StartTimer(uint32_t aTimeoutInMs) mFunctionTimerActive = true; } -void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) +void AppTask::ActionInitiated(LockManager::Action_t aAction, int32_t aActor) { - // If the action has been initiated by the lock, update the bolt lock trait - // and start flashing the LEDs rapidly to indicate action initiation. - if (aAction == BoltLockManager::LOCK_ACTION) + // Action initiated, update the light led + if (aAction == LockManager::LOCK_ACTION) { EFR32_LOG("Lock Action has been initiated") + sLockLED.Set(false); } - else if (aAction == BoltLockManager::UNLOCK_ACTION) + else if (aAction == LockManager::UNLOCK_ACTION) { EFR32_LOG("Unlock Action has been initiated") + sLockLED.Set(true); } if (aActor == AppEvent::kEventType_Button) { sAppTask.mSyncClusterToButtonAction = true; } - - sLockLED.Blink(50, 50); } -void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) +void AppTask::ActionCompleted(LockManager::Action_t aAction) { - // if the action has been completed by the lock, update the bolt lock trait. - // Turn on the lock LED if in a LOCKED state OR - // Turn off the lock LED if in an UNLOCKED state. - if (aAction == BoltLockManager::LOCK_ACTION) + // if the action has been completed by the lock, update the lock trait. + // Turn off the lock LED if in a LOCKED state OR + // Turn on the lock LED if in an UNLOCKED state. + if (aAction == LockManager::LOCK_ACTION) { EFR32_LOG("Lock Action has been completed") - - sLockLED.Set(true); } - else if (aAction == BoltLockManager::UNLOCK_ACTION) + else if (aAction == LockManager::UNLOCK_ACTION) { EFR32_LOG("Unlock Action has been completed") - - sLockLED.Set(false); } if (sAppTask.mSyncClusterToButtonAction) @@ -499,7 +612,7 @@ void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) } } -void AppTask::PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction) +void AppTask::ActionRequest(int32_t aActor, LockManager::Action_t aAction) { AppEvent event; event.Type = AppEvent::kEventType_Lock; @@ -535,6 +648,10 @@ void AppTask::PostEvent(const AppEvent * aEvent) if (!status) EFR32_LOG("Failed to post event to app task event queue"); } + else + { + EFR32_LOG("Event Queue is NULL should never happen"); + } } void AppTask::DispatchEvent(AppEvent * aEvent) @@ -551,13 +668,17 @@ void AppTask::DispatchEvent(AppEvent * aEvent) void AppTask::UpdateClusterState(intptr_t context) { - uint8_t newValue = !BoltLockMgr().IsUnlocked(); + bool unlocked = LockMgr().NextState(); + DlLockState newState = unlocked ? DlLockState::kUnlocked : DlLockState::kLocked; + + DlOperationSource source = DlOperationSource::kUnspecified; + + // write the new lock value + EmberAfStatus status = + DoorLockServer::Instance().SetLockState(1, newState, source) ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE; - // write the new on/off value - EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, - (uint8_t *) &newValue, ZCL_BOOLEAN_ATTRIBUTE_TYPE); if (status != EMBER_ZCL_STATUS_SUCCESS) { - EFR32_LOG("ERR: updating on/off %x", status); + EFR32_LOG("ERR: updating lock state %x", status); } } diff --git a/examples/lock-app/efr32/src/BoltLockManager.cpp b/examples/lock-app/efr32/src/BoltLockManager.cpp deleted file mode 100644 index e68f67d52fbe17..00000000000000 --- a/examples/lock-app/efr32/src/BoltLockManager.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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 "BoltLockManager.h" - -#include "AppConfig.h" -#include "AppTask.h" -#include - -BoltLockManager BoltLockManager::sLock; - -TimerHandle_t sLockTimer; - -CHIP_ERROR BoltLockManager::Init() -{ - // Create FreeRTOS sw timer for lock timer. - sLockTimer = xTimerCreate("lockTmr", // Just a text name, not used by the RTOS kernel - 1, // == default timer period (mS) - false, // no timer reload (==one-shot) - (void *) this, // init timer id = lock obj context - TimerEventHandler // timer callback handler - ); - - if (sLockTimer == NULL) - { - EFR32_LOG("sLockTimer timer create failed"); - appError(APP_ERROR_CREATE_TIMER_FAILED); - } - - mState = kState_LockingCompleted; - mAutoLockTimerArmed = false; - mAutoRelock = false; - mAutoLockDuration = 0; - - return CHIP_NO_ERROR; -} - -void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) -{ - mActionInitiated_CB = aActionInitiated_CB; - mActionCompleted_CB = aActionCompleted_CB; -} - -bool BoltLockManager::IsActionInProgress() -{ - return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated); -} - -bool BoltLockManager::IsUnlocked() -{ - return (mState == kState_UnlockingCompleted); -} - -void BoltLockManager::EnableAutoRelock(bool aOn) -{ - mAutoRelock = aOn; -} - -void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs) -{ - mAutoLockDuration = aDurationInSecs; -} - -bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction) -{ - bool action_initiated = false; - State_t new_state; - - // Initiate Lock/Unlock Action only when the previous one is complete. - if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION) - { - action_initiated = true; - - new_state = kState_UnlockingInitiated; - } - else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION) - { - action_initiated = true; - - new_state = kState_LockingInitiated; - } - - if (action_initiated) - { - if (mAutoLockTimerArmed && new_state == kState_LockingInitiated) - { - // If auto lock timer has been armed and someone initiates locking, - // cancel the timer and continue as normal. - mAutoLockTimerArmed = false; - - CancelTimer(); - } - - StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); - - // Since the timer started successfully, update the state and trigger callback - mState = new_state; - - if (mActionInitiated_CB) - { - mActionInitiated_CB(aAction, aActor); - } - } - - return action_initiated; -} - -void BoltLockManager::StartTimer(uint32_t aTimeoutMs) -{ - if (xTimerIsTimerActive(sLockTimer)) - { - EFR32_LOG("app timer already started!"); - CancelTimer(); - } - - // timer is not active, change its period to required value (== restart). - // FreeRTOS- Block for a maximum of 100 ticks if the change period command - // cannot immediately be sent to the timer command queue. - if (xTimerChangePeriod(sLockTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS) - { - EFR32_LOG("sLockTimer timer start() failed"); - appError(APP_ERROR_START_TIMER_FAILED); - } -} - -void BoltLockManager::CancelTimer(void) -{ - if (xTimerStop(sLockTimer, 0) == pdFAIL) - { - EFR32_LOG("Lock timer timer stop() failed"); - appError(APP_ERROR_STOP_TIMER_FAILED); - } -} - -void BoltLockManager::TimerEventHandler(TimerHandle_t xTimer) -{ - // Get lock obj context from timer id. - BoltLockManager * lock = static_cast(pvTimerGetTimerID(xTimer)); - - // The timer event handler will be called in the context of the timer task - // once sLockTimer expires. Post an event to apptask queue with the actual handler - // so that the event can be handled in the context of the apptask. - AppEvent event; - event.Type = AppEvent::kEventType_Timer; - event.TimerEvent.Context = lock; - if (lock->mAutoLockTimerArmed) - { - event.Handler = AutoReLockTimerEventHandler; - } - else - { - event.Handler = ActuatorMovementTimerEventHandler; - } - GetAppTask().PostEvent(&event); -} - -void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent) -{ - BoltLockManager * lock = static_cast(aEvent->TimerEvent.Context); - int32_t actor = 0; - - // Make sure auto lock timer is still armed. - if (!lock->mAutoLockTimerArmed) - { - return; - } - - lock->mAutoLockTimerArmed = false; - - EFR32_LOG("Auto Re-Lock has been triggered!"); - - lock->InitiateAction(actor, LOCK_ACTION); -} - -void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) -{ - Action_t actionCompleted = INVALID_ACTION; - - BoltLockManager * lock = static_cast(aEvent->TimerEvent.Context); - - if (lock->mState == kState_LockingInitiated) - { - lock->mState = kState_LockingCompleted; - actionCompleted = LOCK_ACTION; - } - else if (lock->mState == kState_UnlockingInitiated) - { - lock->mState = kState_UnlockingCompleted; - actionCompleted = UNLOCK_ACTION; - } - - if (actionCompleted != INVALID_ACTION) - { - if (lock->mActionCompleted_CB) - { - lock->mActionCompleted_CB(actionCompleted); - } - - if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION) - { - // Start the timer for auto relock - lock->StartTimer(lock->mAutoLockDuration * 1000); - - lock->mAutoLockTimerArmed = true; - - EFR32_LOG("Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration); - } - } -} diff --git a/examples/lock-app/efr32/src/LockManager.cpp b/examples/lock-app/efr32/src/LockManager.cpp new file mode 100644 index 00000000000000..39b507daa4e6d4 --- /dev/null +++ b/examples/lock-app/efr32/src/LockManager.cpp @@ -0,0 +1,421 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "LockManager.h" + +#include "AppConfig.h" +#include "AppTask.h" +#include +#include +#include + +LockManager LockManager::sLock; + +TimerHandle_t sLockTimer; + +using namespace ::chip::DeviceLayer::Internal; + +CHIP_ERROR LockManager::Init(chip::app::DataModel::Nullable state) +{ + // Create FreeRTOS sw timer for lock timer. + sLockTimer = xTimerCreate("lockTmr", // Just a text name, not used by the RTOS kernel + 1, // == default timer period (mS) + false, // no timer reload (==one-shot) + (void *) this, // init timer id = lock obj context + TimerEventHandler // timer callback handler + ); + + if (sLockTimer == NULL) + { + EFR32_LOG("sLockTimer timer create failed"); + return APP_ERROR_CREATE_TIMER_FAILED; + } + + if (state.Value() == DlLockState::kUnlocked) + mState = kState_UnlockCompleted; + else + mState = kState_LockCompleted; + + return CHIP_NO_ERROR; +} + +bool LockManager::ReadConfigValues() +{ + size_t outLen; + EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_LockUser, reinterpret_cast(&mLockUser), + sizeof(EmberAfPluginDoorLockUserInfo), outLen); + EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_Credential, reinterpret_cast(&mLockCredentials), + sizeof(EmberAfPluginDoorLockCredentialInfo), outLen); + + EFR32Config::ReadConfigValueStr(EFR32Config::kConfigKey_LockUserName, mUserName, DOOR_LOCK_USER_NAME_BUFFER_SIZE, outLen); + + EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_CredentialData, mCredentialData, sizeof(mCredentialData), outLen); + + EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_UserCredentials, reinterpret_cast(&mCredentials), + sizeof(DlCredential), outLen); + + return true; +} + +void LockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) +{ + mActionInitiated_CB = aActionInitiated_CB; + mActionCompleted_CB = aActionCompleted_CB; +} + +bool LockManager::IsActionInProgress() +{ + return (mState == kState_LockInitiated || mState == kState_UnlockInitiated); +} + +bool LockManager::NextState() +{ + return (mState == kState_UnlockCompleted); +} + +bool LockManager::InitiateAction(int32_t aActor, Action_t aAction) +{ + bool action_initiated = false; + State_t new_state; + + // Initiate Turn Lock/Unlock Action only when the previous one is complete. + if (mState == kState_LockCompleted && aAction == UNLOCK_ACTION) + { + action_initiated = true; + + new_state = kState_UnlockInitiated; + } + else if (mState == kState_UnlockCompleted && aAction == LOCK_ACTION) + { + action_initiated = true; + + new_state = kState_LockInitiated; + } + + if (action_initiated) + { + + StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); + + // Since the timer started successfully, update the state and trigger callback + mState = new_state; + + if (mActionInitiated_CB) + { + mActionInitiated_CB(aAction, aActor); + } + } + + return action_initiated; +} + +void LockManager::StartTimer(uint32_t aTimeoutMs) +{ + if (xTimerIsTimerActive(sLockTimer)) + { + EFR32_LOG("app timer already started!"); + CancelTimer(); + } + + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(sLockTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS) + { + EFR32_LOG("sLockTimer timer start() failed"); + appError(APP_ERROR_START_TIMER_FAILED); + } +} + +void LockManager::CancelTimer(void) +{ + if (xTimerStop(sLockTimer, 0) == pdFAIL) + { + EFR32_LOG("sLockTimer stop() failed"); + appError(APP_ERROR_STOP_TIMER_FAILED); + } +} + +void LockManager::TimerEventHandler(TimerHandle_t xTimer) +{ + // Get lock obj context from timer id. + LockManager * lock = static_cast(pvTimerGetTimerID(xTimer)); + + // The timer event handler will be called in the context of the timer task + // once sLockTimer expires. Post an event to apptask queue with the actual handler + // so that the event can be handled in the context of the apptask. + AppEvent event; + event.Type = AppEvent::kEventType_Timer; + event.TimerEvent.Context = lock; + event.Handler = ActuatorMovementTimerEventHandler; + GetAppTask().PostEvent(&event); +} + +void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) +{ + Action_t actionCompleted = INVALID_ACTION; + + LockManager * lock = static_cast(aEvent->TimerEvent.Context); + + if (lock->mState == kState_LockInitiated) + { + lock->mState = kState_LockCompleted; + actionCompleted = LOCK_ACTION; + } + else if (lock->mState == kState_UnlockInitiated) + { + lock->mState = kState_UnlockCompleted; + actionCompleted = UNLOCK_ACTION; + } + + if (actionCompleted != INVALID_ACTION) + { + if (lock->mActionCompleted_CB) + { + lock->mActionCompleted_CB(actionCompleted); + } + } +} + +bool LockManager::Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err) +{ + return setLockState(endpointId, DlLockState::kLocked, pin, err); +} + +bool LockManager::Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err) +{ + return setLockState(endpointId, DlLockState::kUnlocked, pin, err); +} + +bool LockManager::GetUser(uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) const +{ + // chip::ByteSpan credentialData(mLockCredentials.credentialData, mLockCredentials.credentialDataSize); + ChipLogProgress(Zcl, "Door Lock App: LockManager::GetUser [endpoint=%d,userIndex=%hu]", mEndpointId, userIndex); + + const auto & userInDb = mLockUser; + user.userStatus = userInDb.userStatus; + if (DlUserStatus::kAvailable == user.userStatus) + { + ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d]", mEndpointId); + return true; + } + + user.userName = chip::CharSpan(userInDb.userName.data(), userInDb.userName.size()); + user.credentials = chip::Span(userInDb.credentials.data(), userInDb.credentials.size()); + user.userUniqueId = userInDb.userUniqueId; + user.userType = userInDb.userType; + user.credentialRule = userInDb.credentialRule; + user.createdBy = userInDb.createdBy; + user.lastModifiedBy = userInDb.lastModifiedBy; + + ChipLogDetail(Zcl, + "Found occupied user " + "[endpoint=%d,name=\"%.*s\",credentialsCount=%u,uniqueId=%lx,type=%u,credentialRule=%u," + "createdBy=%d,lastModifiedBy=%d]", + mEndpointId, static_cast(user.userName.size()), user.userName.data(), user.credentials.size(), + user.userUniqueId, to_underlying(user.userType), to_underlying(user.credentialRule), user.createdBy, + user.lastModifiedBy); + + return true; +} + +bool LockManager::SetUser(uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, + const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype, + DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::SetUser " + "[endpoint=%d,userIndex=%d,creator=%d,modifier=%d,userName=%s,uniqueId=%ld " + "userStatus=%u,userType=%u,credentialRule=%u,credentials=%p,totalCredentials=%u]", + mEndpointId, userIndex, creator, modifier, userName.data(), uniqueId, to_underlying(userStatus), + to_underlying(usertype), to_underlying(credentialRule), credentials, totalCredentials); + + auto & userInStorage = mLockUser; + + if (userName.size() > DOOR_LOCK_MAX_USER_NAME_SIZE) + { + ChipLogError(Zcl, "Cannot set user - user name is too long [endpoint=%d,index=%d]", mEndpointId, userIndex); + return false; + } + + if (totalCredentials > sizeof(DOOR_LOCK_MAX_CREDENTIALS_PER_USER)) + { + ChipLogError(Zcl, "Cannot set user - total number of credentials is too big [endpoint=%d,index=%d,totalCredentials=%u]", + mEndpointId, userIndex, totalCredentials); + return false; + } + + chip::Platform::CopyString(mUserName, userName); + mUserName[userName.size()] = 0; + userInStorage.userName = chip::CharSpan(mUserName, userName.size()); + userInStorage.userUniqueId = uniqueId; + userInStorage.userStatus = userStatus; + userInStorage.userType = usertype; + userInStorage.credentialRule = credentialRule; + userInStorage.lastModifiedBy = modifier; + userInStorage.createdBy = creator; + + for (size_t i = 0; i < totalCredentials; ++i) + { + mCredentials[i] = credentials[i]; + mCredentials[i].CredentialType = 1; + mCredentials[i].CredentialIndex = i + 1; + } + + userInStorage.credentials = chip::Span(mCredentials, totalCredentials); + + // Save user information in NVM flash + EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_LockUser, reinterpret_cast(&userInStorage), + sizeof(EmberAfPluginDoorLockUserInfo)); + + EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_UserCredentials, reinterpret_cast(&mCredentials), + sizeof(DlCredential)); + + EFR32Config::WriteConfigValueStr(EFR32Config::kConfigKey_LockUserName, mUserName, sizeof(userName.size())); + + ChipLogProgress(Zcl, "Successfully set the user [mEndpointId=%d,index=%d]", mEndpointId, userIndex); + + return true; +} + +bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) const +{ + ChipLogProgress(Zcl, "Lock App: LockManager::GetCredential [credentialType=%u]", to_underlying(credentialType)); + + const auto & credentialInStorage = mLockCredentials; + + credential.status = credentialInStorage.status; + if (DlCredentialStatus::kAvailable == credential.status) + { + ChipLogDetail(Zcl, "Found unoccupied credential "); + return true; + } + credential.credentialType = credentialInStorage.credentialType; + credential.credentialData = credentialInStorage.credentialData; + + ChipLogDetail(Zcl, "Found occupied credential [type=%u,dataSize=%u]", to_underlying(credential.credentialType), + credential.credentialData.size()); + + return true; +} + +bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + ChipLogProgress(Zcl, + "Door Lock App: LockManager::SetCredential " + "[credentialStatus=%u,credentialType=%u,credentialDataSize=%u]", + to_underlying(credentialStatus), to_underlying(credentialType), credentialData.size()); + + auto & credentialInStorage = mLockCredentials; + if (credentialData.size() > DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE) + { + ChipLogError(Zcl, + "Cannot get the credential - data size exceeds limit " + "[dataSize=%u,maxDataSize=%u]", + credentialData.size(), DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE); + return false; + } + credentialInStorage.status = credentialStatus; + credentialInStorage.credentialType = credentialType; + + memcpy(mCredentialData, credentialData.data(), credentialData.size()); + mCredentialData[credentialData.size()] = 0; + + credentialInStorage.credentialData = chip::ByteSpan{ mCredentialData, credentialData.size() }; + + // Save user information in NVM flash + EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_Credential, reinterpret_cast(&credentialInStorage), + sizeof(EmberAfPluginDoorLockCredentialInfo)); + + EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_CredentialData, reinterpret_cast(&mCredentialData), + credentialData.size()); + + ChipLogProgress(Zcl, "Successfully set the credential [credentialType=%u]", to_underlying(credentialType)); + + return true; +} + +const char * LockManager::lockStateToString(DlLockState lockState) const +{ + switch (lockState) + { + case DlLockState::kNotFullyLocked: + return "Not Fully Locked"; + case DlLockState::kLocked: + return "Locked"; + case DlLockState::kUnlocked: + return "Unlocked"; + } + + return "Unknown"; +} + +bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, + DlOperationError & err) +{ + DlLockState curState = DlLockState::kLocked; + if (mState == kState_UnlockCompleted) + curState = DlLockState::kUnlocked; + + if (curState == lockState) + { + ChipLogDetail(Zcl, "Door Lock App: door is already locked, ignoring command to set lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + return false; + } + + if (!pin.HasValue()) + { + ChipLogDetail(Zcl, "Door Lock App: PIN code is not specified, setting door lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + curState = lockState; + + return true; + } + + // Check the PIN code + for (uint8_t i; i < 10; i++) + { + if (mLockCredentials.credentialType != DlCredentialType::kPin || mLockCredentials.status == DlCredentialStatus::kAvailable) + { + continue; + } + + if (mLockCredentials.credentialData.data_equal(pin.Value())) + { + ChipLogDetail(Zcl, + "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]", + lockStateToString(lockState), mEndpointId); + + curState = lockState; + + return true; + } + } + + ChipLogDetail(Zcl, + "Door Lock App: specified PIN code was not found in the database, ignoring command to set lock state to \"%s\" " + "[endpointId=%d]", + lockStateToString(lockState), mEndpointId); + + err = DlOperationError::kInvalidCredential; + return false; +} diff --git a/examples/lock-app/efr32/src/ZclCallbacks.cpp b/examples/lock-app/efr32/src/ZclCallbacks.cpp index bdccc6859fbf4c..1f8bd0600ce791 100644 --- a/examples/lock-app/efr32/src/ZclCallbacks.cpp +++ b/examples/lock-app/efr32/src/ZclCallbacks.cpp @@ -21,7 +21,8 @@ */ #include "AppConfig.h" -#include "BoltLockManager.h" +#include "LockManager.h" +#include #include #include @@ -30,18 +31,22 @@ using namespace ::chip; using namespace ::chip::app::Clusters; +using namespace ::chip::DeviceLayer::Internal; void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) { - if (attributePath.mClusterId == OnOff::Id && attributePath.mAttributeId == OnOff::Attributes::OnOff::Id) + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); + + if (clusterId == DoorLock::Id && attributeId == DoorLock::Attributes::LockState::Id) { - BoltLockMgr().InitiateAction(AppEvent::kEventType_Lock, - *value ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); + ChipLogProgress(Zcl, "Door lock cluster: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); } } -/** @brief OnOff Cluster Init +/** @brief DoorLock Cluster Init * * This function is called when a specific cluster is initialized. It gives the * application an opportunity to take care of cluster initialization procedures. @@ -49,14 +54,85 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & * * @param endpoint Ver.: always * - * TODO Issue #3841 - * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster - * attributes to the default value. - * The logic here expects something similar to the deprecated Plugins callback - * emberAfPluginOnOffClusterServerPostInitCallback. - * */ -void emberAfOnOffClusterInitCallback(EndpointId endpoint) +void emberAfDoorLockClusterInitCallback(EndpointId endpoint) { // TODO: implement any additional Cluster Server init actions } + +bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional & pinCode, DlOperationError & err) +{ + ChipLogProgress(Zcl, "Door Lock App: Lock Command endpoint=%d", endpointId); + bool status = LockMgr().Lock(endpointId, pinCode, err); + if (status == true) + { + LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION); + } + return status; +} + +bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional & pinCode, + DlOperationError & err) +{ + ChipLogProgress(Zcl, "Door Lock App: Unlock Command endpoint=%d", endpointId); + bool status = LockMgr().Unlock(endpointId, pinCode, err); + if (status == true) + { + LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION); + } + + return status; +} + +bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType, + EmberAfPluginDoorLockCredentialInfo & credential) +{ + return LockMgr().GetCredential(endpointId, credentialIndex, credentialType, credential); +} + +bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialStatus credentialStatus, + DlCredentialType credentialType, const chip::ByteSpan & credentialData) +{ + return LockMgr().SetCredential(endpointId, credentialIndex, credentialStatus, credentialType, credentialData); +} + +bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) +{ + return LockMgr().GetUser(userIndex, user); +} + +bool emberAfPluginDoorLockSetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, + chip::FabricIndex modifier, const chip::CharSpan & userName, uint32_t uniqueId, + DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule, + const DlCredential * credentials, size_t totalCredentials) +{ + + return LockMgr().SetUser(userIndex, creator, modifier, userName, uniqueId, userStatus, usertype, credentialRule, credentials, + totalCredentials); +} + +// TODO: These functions will be supported by door-lock-server in the future. These are set to return failure until implemented. +DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, + EmberAfPluginDoorLockWeekDaySchedule & schedule) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, + EmberAfPluginDoorLockYearDaySchedule & schedule) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, + DlScheduleStatus status, DlDaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute, + uint8_t endHour, uint8_t endMinute) +{ + return DlStatus::kFailure; +} + +DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, + DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime) +{ + return DlStatus::kFailure; +} diff --git a/examples/lock-app/efr32/src/main.cpp b/examples/lock-app/efr32/src/main.cpp index a67a7b7967719c..79b1ff23c6053d 100644 --- a/examples/lock-app/efr32/src/main.cpp +++ b/examples/lock-app/efr32/src/main.cpp @@ -40,6 +40,10 @@ #include "sl_system_kernel.h" #include +#ifdef EFR32_OTA_ENABLED +#include "OTAConfig.h" +#endif // EFR32_OTA_ENABLED + #ifdef HEAP_MONITORING #include "MemMonitoring.h" #endif @@ -48,18 +52,6 @@ #include "lcd.h" #endif -#if PW_RPC_ENABLED -#include "Rpc.h" -#endif - -#ifdef ENABLE_CHIP_SHELL -#include "matter_shell.h" -#endif - -#ifdef EFR32_OTA_ENABLED -#include "OTAConfig.h" -#endif // EFR32_OTA_ENABLED - #include #if CHIP_ENABLE_OPENTHREAD #include @@ -78,6 +70,15 @@ #include "wfx_host_events.h" #endif /* RS911X_WIFI */ +#if PW_RPC_ENABLED +#include "Rpc.h" +#endif + +#ifdef ENABLE_CHIP_SHELL +#include "matter_shell.h" +#endif + +#define BLE_DEV_NAME "SiLabs-Door-Lock" using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; @@ -124,12 +125,15 @@ int main(void) chip::rpc::Init(); #endif +#ifdef HEAP_MONITORING + MemMonitoring::startHeapMonitoring(); +#endif + EFR32_LOG("=================================================="); - EFR32_LOG("chip-efr32-lock-example starting"); + EFR32_LOG("chip-efr32-door-lock-example starting"); EFR32_LOG("=================================================="); EFR32_LOG("Init CHIP Stack"); - // Init Chip memory management before the stack chip::Platform::MemoryInit(); @@ -139,7 +143,7 @@ int main(void) EFR32_LOG("PlatformMgr().InitChipStack() failed"); appError(ret); } - chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName("EFR32_LOCK"); + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(BLE_DEV_NAME); #if CHIP_ENABLE_OPENTHREAD EFR32_LOG("Initializing OpenThread stack"); ret = ThreadStackMgr().InitThreadStack(); @@ -180,6 +184,14 @@ int main(void) appError(ret); } +#ifdef WF200_WIFI + // Start wfx bus communication task. + wfx_bus_start(); +#ifdef SL_WFX_USE_SECURE_LINK + wfx_securelink_task_start(); // start securelink key renegotiation task +#endif // SL_WFX_USE_SECURE_LINK +#endif /* WF200_WIFI */ + #if CHIP_ENABLE_OPENTHREAD EFR32_LOG("Starting OpenThread task"); @@ -191,13 +203,13 @@ int main(void) appError(ret); } #endif // CHIP_ENABLE_OPENTHREAD -#ifdef WF200_WIFI - // Start wfx bus communication task. - wfx_bus_start(); -#ifdef SL_WFX_USE_SECURE_LINK - wfx_securelink_task_start(); // start securelink key renegotiation task -#endif // SL_WFX_USE_SECURE_LINK -#endif /* WF200_WIFI */ +#ifdef RS911X_WIFI + /* + * Start up any RSI interface stuff + * (Not required) - Note that wfx_wifi_start will deal with + * starting up a rsi task - which will initialize the SPI interface. + */ +#endif #ifdef EFR32_OTA_ENABLED chip::DeviceLayer::PlatformMgr().LockChipStack(); OTAConfig::Init(); diff --git a/examples/lock-app/efr32/with_pw_rpc.gni b/examples/lock-app/efr32/with_pw_rpc.gni index eddb9ae4278054..d0a8f2c0485f06 100644 --- a/examples/lock-app/efr32/with_pw_rpc.gni +++ b/examples/lock-app/efr32/with_pw_rpc.gni @@ -14,7 +14,6 @@ # add this gni as import in your build args to use pigweed in the example # 'import("//with_pw_rpc.gni")' -# *WIP* pigweed is not fully integrated in this EFR example yet import("//build_overrides/chip.gni") import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni") diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index 85f8d7b0963d93..f194e021bbfdf5 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -61,6 +61,8 @@ idf_component_register(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" PRIV_REQUIRES bt chip QRCode) get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) @@ -174,6 +176,8 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" PRIV_REQUIRES chip QRCode bt) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 0d02f98dc247a2..e4a3d37b2cf6f2 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -927,6 +927,99 @@ server cluster GeneralDiagnostics = 51 { readonly attribute int16u clusterRevision = 65533; } +server cluster Groups = 4 { + readonly attribute bitmap8 nameSupport = 0; + readonly attribute int16u clusterRevision = 65533; + + request struct AddGroupRequest { + group_id groupId = 0; + CHAR_STRING groupName = 1; + } + + request struct ViewGroupRequest { + group_id groupId = 0; + } + + request struct GetGroupMembershipRequest { + group_id groupList[] = 0; + } + + request struct RemoveGroupRequest { + group_id groupId = 0; + } + + request struct AddGroupIfIdentifyingRequest { + group_id groupId = 0; + CHAR_STRING groupName = 1; + } + + response struct AddGroupResponse = 0 { + ENUM8 status = 0; + group_id groupId = 1; + } + + response struct ViewGroupResponse = 1 { + ENUM8 status = 0; + group_id groupId = 1; + CHAR_STRING groupName = 2; + } + + response struct GetGroupMembershipResponse = 2 { + nullable INT8U capacity = 0; + group_id groupList[] = 1; + } + + response struct RemoveGroupResponse = 3 { + ENUM8 status = 0; + group_id groupId = 1; + } + + command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; + command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; + command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; + command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; + command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; + command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; +} + +server cluster Identify = 3 { + enum IdentifyEffectIdentifier : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum IdentifyEffectVariant : ENUM8 { + kDefault = 0; + } + + enum IdentifyIdentifyType : ENUM8 { + kNone = 0; + kVisibleLight = 1; + kVisibleLED = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + response struct IdentifyQueryResponse = 0 { + INT16U timeout = 0; + } + + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + command access(invoke: manage) IdentifyQuery(): IdentifyQueryResponse = 1; +} + server cluster LocalizationConfiguration = 43 { attribute char_string<35> activeLocale = 1; readonly attribute CHAR_STRING supportedLocales[] = 2; @@ -1735,6 +1828,8 @@ endpoint 0 { endpoint 1 { server cluster Descriptor; server cluster DoorLock; + server cluster Groups; + server cluster Identify; server cluster OnOff; server cluster PowerSource; } diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index ee25a90a9d4b5a..52143ca2713b50 100755 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -5128,7 +5128,7 @@ "mfgCode": null, "define": "IDENTIFY_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { "name": "IdentifyQueryResponse", @@ -5253,7 +5253,7 @@ "mfgCode": null, "define": "GROUPS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { "name": "AddGroupResponse", @@ -6719,10 +6719,10 @@ "mfgCode": null, "side": "server", "included": 1, - "storageOption": "RAM", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "1", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -7388,6 +7388,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "AttributeList", "code": 65531, @@ -7556,4 +7586,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/src/platform/EFR32/EFR32Config.h b/src/platform/EFR32/EFR32Config.h index 1943b902ca2e61..78019633342ae7 100644 --- a/src/platform/EFR32/EFR32Config.h +++ b/src/platform/EFR32/EFR32Config.h @@ -114,6 +114,11 @@ class EFR32Config static constexpr Key kConfigKey_WiFiPSK = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0D); static constexpr Key kConfigKey_WiFiSEC = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0E); static constexpr Key kConfigKey_GroupKeyBase = EFR32ConfigKey(kMatterConfig_KeyBase, 0x0F); + static constexpr Key kConfigKey_LockUser = EFR32ConfigKey(kMatterConfig_KeyBase, 0x10); + static constexpr Key kConfigKey_Credential = EFR32ConfigKey(kMatterConfig_KeyBase, 0x11); + static constexpr Key kConfigKey_LockUserName = EFR32ConfigKey(kMatterConfig_KeyBase, 0x12); + static constexpr Key kConfigKey_CredentialData = EFR32ConfigKey(kMatterConfig_KeyBase, 0x13); + static constexpr Key kConfigKey_UserCredentials = EFR32ConfigKey(kMatterConfig_KeyBase, 0x14); static constexpr Key kConfigKey_GroupKeyMax = EFR32ConfigKey(kMatterConfig_KeyBase, 0x1E); // Allows 16 Group Keys to be created. static constexpr Key kConfigKey_UniqueId = EFR32ConfigKey(kMatterFactory_KeyBase, 0x1F); diff --git a/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp index e65fe6cb694505..df6e20c7b712be 100644 --- a/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp @@ -392,6 +392,134 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } // namespace GeneralCommissioning +namespace Groups { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::AddGroup::Id: { + Commands::AddGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::ViewGroup::Id: { + Commands::ViewGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::GetGroupMembership::Id: { + Commands::GetGroupMembership::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveGroup::Id: { + Commands::RemoveGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveAllGroups::Id: { + Commands::RemoveAllGroups::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddGroupIfIdentifying::Id: { + Commands::AddGroupIfIdentifying::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Groups + +namespace Identify { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::Identify::Id: { + Commands::Identify::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::IdentifyQuery::Id: { + Commands::IdentifyQuery::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Identify + namespace NetworkCommissioning { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) @@ -816,6 +944,12 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: case Clusters::GeneralCommissioning::Id: Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; + case Clusters::Groups::Id: + Clusters::Groups::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::Identify::Id: + Clusters::Identify::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; case Clusters::NetworkCommissioning::Id: Clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; diff --git a/zzz_generated/lock-app/zap-generated/PluginApplicationCallbacks.h b/zzz_generated/lock-app/zap-generated/PluginApplicationCallbacks.h index 67145acc8f0389..06a4d946cef149 100644 --- a/zzz_generated/lock-app/zap-generated/PluginApplicationCallbacks.h +++ b/zzz_generated/lock-app/zap-generated/PluginApplicationCallbacks.h @@ -32,6 +32,8 @@ MatterFixedLabelPluginServerInitCallback(); \ MatterGeneralCommissioningPluginServerInitCallback(); \ MatterGeneralDiagnosticsPluginServerInitCallback(); \ + MatterGroupsPluginServerInitCallback(); \ + MatterIdentifyPluginServerInitCallback(); \ MatterLocalizationConfigurationPluginServerInitCallback(); \ MatterNetworkCommissioningPluginServerInitCallback(); \ MatterOtaSoftwareUpdateProviderPluginClientInitCallback(); \ diff --git a/zzz_generated/lock-app/zap-generated/access.h b/zzz_generated/lock-app/zap-generated/access.h index 011901d517f30a..15851d1a390ef2 100644 --- a/zzz_generated/lock-app/zap-generated/access.h +++ b/zzz_generated/lock-app/zap-generated/access.h @@ -210,6 +210,12 @@ 48, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ 48, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ 48, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + 4, /* Cluster: Groups, Command: AddGroup, Privilege: manage */ \ + 4, /* Cluster: Groups, Command: RemoveGroup, Privilege: manage */ \ + 4, /* Cluster: Groups, Command: RemoveAllGroups, Privilege: manage */ \ + 4, /* Cluster: Groups, Command: AddGroupIfIdentifying, Privilege: manage */ \ + 3, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + 3, /* Cluster: Identify, Command: IdentifyQuery, Privilege: manage */ \ 49, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ 49, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ 49, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ @@ -247,6 +253,12 @@ 0, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ 2, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ 4, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + 0, /* Cluster: Groups, Command: AddGroup, Privilege: manage */ \ + 3, /* Cluster: Groups, Command: RemoveGroup, Privilege: manage */ \ + 4, /* Cluster: Groups, Command: RemoveAllGroups, Privilege: manage */ \ + 5, /* Cluster: Groups, Command: AddGroupIfIdentifying, Privilege: manage */ \ + 0, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + 1, /* Cluster: Identify, Command: IdentifyQuery, Privilege: manage */ \ 0, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ 2, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ 3, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ @@ -284,6 +296,12 @@ kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + kMatterAccessPrivilegeManage, /* Cluster: Groups, Command: AddGroup, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Groups, Command: RemoveGroup, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Groups, Command: RemoveAllGroups, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Groups, Command: AddGroupIfIdentifying, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Identify, Command: IdentifyQuery, Privilege: manage */ \ kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ diff --git a/zzz_generated/lock-app/zap-generated/callback-stub.cpp b/zzz_generated/lock-app/zap-generated/callback-stub.cpp index 6c3b8338df0036..15b215628ecb48 100644 --- a/zzz_generated/lock-app/zap-generated/callback-stub.cpp +++ b/zzz_generated/lock-app/zap-generated/callback-stub.cpp @@ -59,6 +59,12 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_GENERAL_DIAGNOSTICS_CLUSTER_ID: emberAfGeneralDiagnosticsClusterInitCallback(endpoint); break; + case ZCL_GROUPS_CLUSTER_ID: + emberAfGroupsClusterInitCallback(endpoint); + break; + case ZCL_IDENTIFY_CLUSTER_ID: + emberAfIdentifyClusterInitCallback(endpoint); + break; case ZCL_LOCALIZATION_CONFIGURATION_CLUSTER_ID: emberAfLocalizationConfigurationClusterInitCallback(endpoint); break; @@ -154,6 +160,16 @@ void __attribute__((weak)) emberAfGeneralDiagnosticsClusterInitCallback(Endpoint // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfGroupsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfIdentifyClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfLocalizationConfigurationClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/zzz_generated/lock-app/zap-generated/endpoint_config.h b/zzz_generated/lock-app/zap-generated/endpoint_config.h index 9e8c29b5115e8b..2f937716d3c907 100644 --- a/zzz_generated/lock-app/zap-generated/endpoint_config.h +++ b/zzz_generated/lock-app/zap-generated/endpoint_config.h @@ -565,7 +565,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 237 +#define GENERATED_ATTRIBUTE_COUNT 241 #define GENERATED_ATTRIBUTES \ { \ \ @@ -843,6 +843,14 @@ ZAP_EMPTY_DEFAULT() }, /* label list */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ \ + /* Endpoint: 1, Cluster: Identify (server) */ \ + { 0x00000000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0x0000) }, /* identify time */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(4) }, /* ClusterRevision */ \ + \ + /* Endpoint: 1, Cluster: Groups (server) */ \ + { 0x00000000, ZAP_TYPE(BITMAP8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* name support */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(4) }, /* ClusterRevision */ \ + \ /* Endpoint: 1, Cluster: On/Off (server) */ \ { 0x00000000, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* OnOff */ \ { 0x00004000, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_SIMPLE_DEFAULT(1) }, /* GlobalSceneControl */ \ @@ -873,10 +881,11 @@ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Door Lock (server) */ \ - { 0x00000000, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_SIMPLE_DEFAULT(2) }, /* LockState */ \ - { 0x00000001, ZAP_TYPE(ENUM8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* LockType */ \ - { 0x00000002, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_EMPTY_DEFAULT() }, /* ActuatorEnabled */ \ - { 0x00000003, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* DoorState */ \ + { 0x00000000, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_SIMPLE_DEFAULT(1) }, /* LockState */ \ + { 0x00000001, ZAP_TYPE(ENUM8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* LockType */ \ + { 0x00000002, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_EMPTY_DEFAULT() }, /* ActuatorEnabled */ \ + { 0x00000003, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* DoorState */ \ { 0x00000011, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfTotalUsersSupported */ \ { 0x00000012, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfPINUsersSupported */ \ { 0x00000013, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(10) }, /* NumberOfRFIDUsersSupported */ \ @@ -926,6 +935,13 @@ (EmberAfGenericClusterFunction) emberAfTimeFormatLocalizationClusterServerInitCallback, \ (EmberAfGenericClusterFunction) MatterTimeFormatLocalizationClusterServerPreAttributeChangedCallback, \ }; \ + const EmberAfGenericClusterFunction chipFuncArrayIdentifyServer[] = { \ + (EmberAfGenericClusterFunction) emberAfIdentifyClusterServerInitCallback, \ + (EmberAfGenericClusterFunction) MatterIdentifyClusterServerAttributeChangedCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayGroupsServer[] = { \ + (EmberAfGenericClusterFunction) emberAfGroupsClusterServerInitCallback, \ + }; \ const EmberAfGenericClusterFunction chipFuncArrayOnOffServer[] = { \ (EmberAfGenericClusterFunction) emberAfOnOffClusterServerInitCallback, \ }; \ @@ -1007,6 +1023,29 @@ 0x00000005 /* CSRResponse */, \ 0x00000008 /* NOCResponse */, \ chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 1, Cluster: Identify (server) */\ + /* client_generated */ \ + 0x00000000 /* Identify */, \ + 0x00000001 /* IdentifyQuery */, \ + chip::kInvalidCommandId /* end of list */, \ + /* server_generated */ \ + 0x00000000 /* IdentifyQueryResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 1, Cluster: Groups (server) */\ + /* client_generated */ \ + 0x00000000 /* AddGroup */, \ + 0x00000001 /* ViewGroup */, \ + 0x00000002 /* GetGroupMembership */, \ + 0x00000003 /* RemoveGroup */, \ + 0x00000004 /* RemoveAllGroups */, \ + 0x00000005 /* AddGroupIfIdentifying */, \ + chip::kInvalidCommandId /* end of list */, \ + /* server_generated */ \ + 0x00000000 /* AddGroupResponse */, \ + 0x00000001 /* ViewGroupResponse */, \ + 0x00000002 /* GetGroupMembershipResponse */, \ + 0x00000003 /* RemoveGroupResponse */, \ + chip::kInvalidCommandId /* end of list */, \ /* Endpoint: 1, Cluster: On/Off (server) */\ /* client_generated */ \ 0x00000000 /* Off */, \ @@ -1036,7 +1075,7 @@ // clang-format on #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 25 +#define GENERATED_CLUSTER_COUNT 27 // clang-format off #define GENERATED_CLUSTERS { \ @@ -1271,21 +1310,43 @@ .acceptedCommandList = nullptr ,\ .generatedCommandList = nullptr ,\ },\ + { \ + /* Endpoint: 1, Cluster: Identify (server) */ \ + .clusterId = 0x00000003, \ + .attributes = ZAP_ATTRIBUTE_INDEX(190), \ + .attributeCount = 2, \ + .clusterSize = 4, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ + .functions = chipFuncArrayIdentifyServer, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 48 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 51 ) ,\ + },\ + { \ + /* Endpoint: 1, Cluster: Groups (server) */ \ + .clusterId = 0x00000004, \ + .attributes = ZAP_ATTRIBUTE_INDEX(192), \ + .attributeCount = 2, \ + .clusterSize = 3, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + .functions = chipFuncArrayGroupsServer, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 53 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 60 ) ,\ + },\ { \ /* Endpoint: 1, Cluster: On/Off (server) */ \ .clusterId = 0x00000006, \ - .attributes = ZAP_ATTRIBUTE_INDEX(190), \ + .attributes = ZAP_ATTRIBUTE_INDEX(194), \ .attributeCount = 7, \ .clusterSize = 13, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ .functions = chipFuncArrayOnOffServer, \ - .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 48 ) ,\ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 65 ) ,\ .generatedCommandList = nullptr ,\ },\ { \ /* Endpoint: 1, Cluster: Descriptor (server) */ \ .clusterId = 0x0000001D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(197), \ + .attributes = ZAP_ATTRIBUTE_INDEX(201), \ .attributeCount = 5, \ .clusterSize = 0, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -1296,7 +1357,7 @@ { \ /* Endpoint: 1, Cluster: Power Source (server) */ \ .clusterId = 0x0000002F, \ - .attributes = ZAP_ATTRIBUTE_INDEX(202), \ + .attributes = ZAP_ATTRIBUTE_INDEX(206), \ .attributeCount = 9, \ .clusterSize = 133, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -1307,12 +1368,12 @@ { \ /* Endpoint: 1, Cluster: Door Lock (server) */ \ .clusterId = 0x00000101, \ - .attributes = ZAP_ATTRIBUTE_INDEX(211), \ + .attributes = ZAP_ATTRIBUTE_INDEX(215), \ .attributeCount = 26, \ .clusterSize = 40, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ .functions = chipFuncArrayDoorLockServer, \ - .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 52 ) ,\ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 69 ) ,\ .generatedCommandList = nullptr ,\ },\ } @@ -1321,12 +1382,12 @@ #define ZAP_CLUSTER_INDEX(index) (&generatedClusters[index]) -#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 24 +#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 26 // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 21, 593 }, { ZAP_CLUSTER_INDEX(21), 4, 186 }, \ + { ZAP_CLUSTER_INDEX(0), 21, 593 }, { ZAP_CLUSTER_INDEX(21), 6, 193 }, \ } // Largest attribute size is needed for various buffers @@ -1338,7 +1399,7 @@ static_assert(ATTRIBUTE_LARGEST <= CHIP_CONFIG_MAX_ATTRIBUTE_STORE_ELEMENT_SIZE, #define ATTRIBUTE_SINGLETONS_SIZE (37) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (779) +#define ATTRIBUTE_MAX_SIZE (786) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) diff --git a/zzz_generated/lock-app/zap-generated/gen_config.h b/zzz_generated/lock-app/zap-generated/gen_config.h index cfb19fdb9885f4..38cfa7f1165da7 100644 --- a/zzz_generated/lock-app/zap-generated/gen_config.h +++ b/zzz_generated/lock-app/zap-generated/gen_config.h @@ -39,6 +39,8 @@ #define EMBER_AF_FIXED_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_GROUPS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_NETWORK_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_OTA_PROVIDER_CLUSTER_CLIENT_ENDPOINT_COUNT (1) @@ -105,6 +107,16 @@ #define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS_SERVER #define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS +// Use this macro to check if the server side of the Groups cluster is included +#define ZCL_USING_GROUPS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_GROUPS_SERVER +#define EMBER_AF_PLUGIN_GROUPS + +// Use this macro to check if the server side of the Identify cluster is included +#define ZCL_USING_IDENTIFY_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_IDENTIFY_SERVER +#define EMBER_AF_PLUGIN_IDENTIFY + // Use this macro to check if the server side of the Localization Configuration cluster is included #define ZCL_USING_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER #define EMBER_AF_PLUGIN_LOCALIZATION_CONFIGURATION_SERVER