diff --git a/slc/apps/refrigerator_app/thread/README.md b/slc/apps/refrigerator_app/thread/README.md index 13a486473..3670da30d 100644 --- a/slc/apps/refrigerator_app/thread/README.md +++ b/slc/apps/refrigerator_app/thread/README.md @@ -7,6 +7,7 @@ The Matter over Thread refrigerator example is a baseline demonstration of a fri - [Purpose/Scope](#purposescope) - [Prerequisites/Setup Requirements](#prerequisitessetup-requirements) - [Steps to Run Demo](#steps-to-run-demo) +- [Extending Base App Implementation](#extending-base-app-implementation) - [Troubleshooting](#troubleshooting) - [Resources](#resources) - [Report Bugs & Get Support](#report-bugs--get-support) @@ -94,6 +95,126 @@ This sample app works out of the box with no additional configuration required. | LED 0 | Short flash off | Provisioned, no full Thread connectivity | | LED 0 | Solid on | Fully provisioned with Thread connectivity | +## Extending Base App Implementation + +### CustomerAppTask + +To implement custom app behavior you can override any Silicon Labs implemented API in the CustomerAppTask file. This example provides `CustomerAppTask.h` and `CustomerAppTask.cpp` for that purpose. The base implementation and the full set of overridable `*Impl()` APIs are supplied by the build system in `AppTask.cpp` and `AppTaskImpl.h` under `autogen/`. Any `*Impl()` you do not override keeps the Silicon Labs default behavior. + +### How to Override APIs + +`CustomerAppTask` derives from the base AppTask through the Curiously Recurring +Template Pattern (CRTP). You override only the `*Impl()` methods you need, the +base declares one `*Impl()` per overridable API. Steps: + +1. Find the method to override in the base API (see + [Override API reference](#override-api-reference) below). +2. Declare the same method signature in `CustomerAppTask` in your + `CustomerAppTask.h` under `private:`. Match the base `*Impl()` signature + exactly — note that `*Impl()` overrides are **non-static instance methods** + even when the public dispatcher (e.g. `ButtonEventHandler`) is `static`. +3. Implement the method in `CustomerAppTask.cpp`. +4. Build. The CRTP layer automatically routes each call to your `*Impl()` if + present, otherwise to the Silicon Labs default. + +### DataModelCallbacks and CustomerAppTask + +What used to live in `DataModelCallbacks.cpp` now lives in `AppTask.cpp`. The +Matter SDK's `MatterPostAttributeChangeCallback` is implemented in +`examples/platform/silabs/BaseApplication.cpp` and forwards to +`AppTask::DMPostAttributeChangeCallback` (defined in `AppTask.cpp`), which you +can customize via `DMPostAttributeChangeCallbackImpl()` in `CustomerAppTask`. + +Forwarding into `AppTask` still goes through CRTP as in +[How to Override APIs](#how-to-override-apis). + +- **Methods that already exist in the AppTask** — Customize them by overriding + the matching `*Impl()` method in `CustomerAppTask`. Do not edit the + `AppTask.cpp` for app-specific behavior. + +- **New custom data model methods** — Add them in `CustomerAppTask` directly. + Do not add new application logic in autogenerated sources; those edits will + not survive regeneration or project upgrades. + +### Sample Implementation + +The following shows a minimal example `CustomerAppTask` that overrides +`AppInitImpl()` and `ButtonEventHandlerImpl()`. + +**CustomerAppTask.h** + +```cpp +#pragma once +#include "AppTaskImpl.h" + +/** Minimal AppTaskImpl-derived class. Override only the *Impl() methods you need **/ +class CustomerAppTask : public AppTaskImpl +{ +public: + static CustomerAppTask & GetAppTask() { return sAppTask; } + +private: + friend class AppTaskImpl; + CHIP_ERROR AppInitImpl(); + void ButtonEventHandlerImpl(uint8_t button, uint8_t btnAction); + static CustomerAppTask sAppTask; +}; +``` + +**CustomerAppTask.cpp** + +```cpp +#include "CustomerAppTask.h" +#include "AppTask.h" +#include "AppEvent.h" +#include +#include + +#define APP_FUNCTION_BUTTON 0 + +CustomerAppTask CustomerAppTask::sAppTask; + +AppTask & AppTask::GetAppTask() +{ + return CustomerAppTask::GetAppTask(); +} + +CHIP_ERROR CustomerAppTask::AppInitImpl() +{ + SILABS_LOG("CustomerAppTask: custom implementation (AppInitImpl)"); + CHIP_ERROR err = AppTask::AppInit(); + if (err == CHIP_NO_ERROR) + { + // Override the SDK default button handler registered in AppTask::AppInit(). + chip::DeviceLayer::Silabs::GetPlatform().SetButtonsCb(CustomerAppTask::ButtonEventHandler); + } + return err; +} + +void CustomerAppTask::ButtonEventHandlerImpl(uint8_t button, uint8_t btnAction) +{ + SILABS_LOG("CustomerAppTask: custom implementation (ButtonEventHandlerImpl)"); + AppEvent aEvent = {}; + aEvent.Type = AppEvent::kEventType_Button; + aEvent.ButtonEvent.Action = btnAction; + + if (button == APP_FUNCTION_BUTTON) + { + aEvent.Handler = BaseApplication::ButtonHandler; + AppTask::GetAppTask().PostEvent(&aEvent); + } +} +``` + +### Override API Reference + +The base API and implementation are generated into your project and live under `autogen/` directory. These files are regenerated on every project upgrade and match your installed SDK version. Use them as the reference for overridable methods and app configuration. + +| File | Purpose | +|------|--------| +| `autogen/AppTaskImpl.h` | Declarations of every overridable `*Impl()` method. Copy the signatures you need from here into `CustomerAppTask.h`. | +| `autogen/AppTask.cpp` | Silicon Labs default implementation of AppTask. This is what runs for any `*Impl()` you do not override. Use as reference when customizing behavior. | + ## Troubleshooting **Device does not advertise over BLE** diff --git a/slc/apps/refrigerator_app/thread/matter_thread_soc_refrigerator_app_freertos.slcp b/slc/apps/refrigerator_app/thread/matter_thread_soc_refrigerator_app_freertos.slcp index 69a6c90af..6ad5841b4 100644 --- a/slc/apps/refrigerator_app/thread/matter_thread_soc_refrigerator_app_freertos.slcp +++ b/slc/apps/refrigerator_app/thread/matter_thread_soc_refrigerator_app_freertos.slcp @@ -74,31 +74,28 @@ config_file: - path: ../../../../provision.mattpconf directory: provision file_id: provision_config + - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/include/RefrigeratorConfig.h + file_id: refrigerator_config include: - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/include file_list: - path: AppConfig.h - path: AppEvent.h - - path: AppTask.h - path: CHIPProjectConfig.h - - path: RefrigeratorManager.h - - path: refrigerator-and-temperature-controlled-cabinet-mode.h - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/refrigerator-common/include file_list: - path: static-supported-temperature-levels.h + - path: ../../../../third_party/matter_sdk/examples/platform/silabs/customer + file_list: + - path: CustomerAppTask.h + directory: include source: - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/AppTask.cpp - directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp + - path: ../../../../third_party/matter_sdk/examples/platform/silabs/customer/CustomerAppTask.cpp directory: src - path: ../../../../third_party/matter_sdk/examples/platform/silabs/main.cpp directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/DataModelCallbacks.cpp - directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/refrigerator-and-temperature-controlled-cabinet-mode.cpp - directory: src - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp directory: src diff --git a/slc/apps/refrigerator_app/wifi/README.md b/slc/apps/refrigerator_app/wifi/README.md index cecba46f8..e28248eca 100644 --- a/slc/apps/refrigerator_app/wifi/README.md +++ b/slc/apps/refrigerator_app/wifi/README.md @@ -7,6 +7,7 @@ The Matter over Wi-Fi refrigerator example is a baseline demonstration of a frid - [Purpose/Scope](#purposescope) - [Prerequisites/Setup Requirements](#prerequisitessetup-requirements) - [Steps to Run Demo](#steps-to-run-demo) +- [Extending Base App Implementation](#extending-base-app-implementation) - [Troubleshooting](#troubleshooting) - [Resources](#resources) - [Report Bugs & Get Support](#report-bugs--get-support) @@ -88,6 +89,126 @@ This sample app works out of the box with no additional configuration required. | LED 0 | Short flash off | Provisioned, no full service connectivity | | LED 0 | Solid on | Fully provisioned with service connectivity | +## Extending Base App Implementation + +### CustomerAppTask + +To implement custom app behavior you can override any Silicon Labs implemented API in the CustomerAppTask file. This example provides `CustomerAppTask.h` and `CustomerAppTask.cpp` for that purpose. The base implementation and the full set of overridable `*Impl()` APIs are supplied by the build system in `AppTask.cpp` and `AppTaskImpl.h` under `autogen/`. Any `*Impl()` you do not override keeps the Silicon Labs default behavior. + +### How to Override APIs + +`CustomerAppTask` derives from the base AppTask through the Curiously Recurring +Template Pattern (CRTP). You override only the `*Impl()` methods you need, the +base declares one `*Impl()` per overridable API. Steps: + +1. Find the method to override in the base API (see + [Override API reference](#override-api-reference) below). +2. Declare the same method signature in `CustomerAppTask` in your + `CustomerAppTask.h` under `private:`. Match the base `*Impl()` signature + exactly — note that `*Impl()` overrides are **non-static instance methods** + even when the public dispatcher (e.g. `ButtonEventHandler`) is `static`. +3. Implement the method in `CustomerAppTask.cpp`. +4. Build. The CRTP layer automatically routes each call to your `*Impl()` if + present, otherwise to the Silicon Labs default. + +### DataModelCallbacks and CustomerAppTask + +What used to live in `DataModelCallbacks.cpp` now lives in `AppTask.cpp`. The +Matter SDK's `MatterPostAttributeChangeCallback` is implemented in +`examples/platform/silabs/BaseApplication.cpp` and forwards to +`AppTask::DMPostAttributeChangeCallback` (defined in `AppTask.cpp`), which you +can customize via `DMPostAttributeChangeCallbackImpl()` in `CustomerAppTask`. + +Forwarding into `AppTask` still goes through CRTP as in +[How to Override APIs](#how-to-override-apis). + +- **Methods that already exist in the AppTask** — Customize them by overriding + the matching `*Impl()` method in `CustomerAppTask`. Do not edit the + `AppTask.cpp` for app-specific behavior. + +- **New custom data model methods** — Add them in `CustomerAppTask` directly. + Do not add new application logic in autogenerated sources; those edits will + not survive regeneration or project upgrades. + +### Sample Implementation + +The following shows a minimal example `CustomerAppTask` that overrides +`AppInitImpl()` and `ButtonEventHandlerImpl()`. + +**CustomerAppTask.h** + +```cpp +#pragma once +#include "AppTaskImpl.h" + +/** Minimal AppTaskImpl-derived class. Override only the *Impl() methods you need **/ +class CustomerAppTask : public AppTaskImpl +{ +public: + static CustomerAppTask & GetAppTask() { return sAppTask; } + +private: + friend class AppTaskImpl; + CHIP_ERROR AppInitImpl(); + void ButtonEventHandlerImpl(uint8_t button, uint8_t btnAction); + static CustomerAppTask sAppTask; +}; +``` + +**CustomerAppTask.cpp** + +```cpp +#include "CustomerAppTask.h" +#include "AppTask.h" +#include "AppEvent.h" +#include +#include + +#define APP_FUNCTION_BUTTON 0 + +CustomerAppTask CustomerAppTask::sAppTask; + +AppTask & AppTask::GetAppTask() +{ + return CustomerAppTask::GetAppTask(); +} + +CHIP_ERROR CustomerAppTask::AppInitImpl() +{ + SILABS_LOG("CustomerAppTask: custom implementation (AppInitImpl)"); + CHIP_ERROR err = AppTask::AppInit(); + if (err == CHIP_NO_ERROR) + { + // Override the SDK default button handler registered in AppTask::AppInit(). + chip::DeviceLayer::Silabs::GetPlatform().SetButtonsCb(CustomerAppTask::ButtonEventHandler); + } + return err; +} + +void CustomerAppTask::ButtonEventHandlerImpl(uint8_t button, uint8_t btnAction) +{ + SILABS_LOG("CustomerAppTask: custom implementation (ButtonEventHandlerImpl)"); + AppEvent aEvent = {}; + aEvent.Type = AppEvent::kEventType_Button; + aEvent.ButtonEvent.Action = btnAction; + + if (button == APP_FUNCTION_BUTTON) + { + aEvent.Handler = BaseApplication::ButtonHandler; + AppTask::GetAppTask().PostEvent(&aEvent); + } +} +``` + +### Override API Reference + +The base API and implementation are generated into your project and live under `autogen/` directory. These files are regenerated on every project upgrade and match your installed SDK version. Use them as the reference for overridable methods and app configuration. + +| File | Purpose | +|------|--------| +| `autogen/AppTaskImpl.h` | Declarations of every overridable `*Impl()` method. Copy the signatures you need from here into `CustomerAppTask.h`. | +| `autogen/AppTask.cpp` | Silicon Labs default implementation of AppTask. This is what runs for any `*Impl()` you do not override. Use as reference when customizing behavior. | + ## Troubleshooting **Device does not advertise over BLE** diff --git a/slc/apps/refrigerator_app/wifi/matter_wifi_soc_refrigerator_app_freertos.slcp b/slc/apps/refrigerator_app/wifi/matter_wifi_soc_refrigerator_app_freertos.slcp index dc672316f..7a8708999 100644 --- a/slc/apps/refrigerator_app/wifi/matter_wifi_soc_refrigerator_app_freertos.slcp +++ b/slc/apps/refrigerator_app/wifi/matter_wifi_soc_refrigerator_app_freertos.slcp @@ -98,31 +98,28 @@ config_file: - path: ../../../../provision.mattpconf directory: provision file_id: provision_config + - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/include/RefrigeratorConfig.h + file_id: refrigerator_config include: - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/include file_list: - path: AppConfig.h - path: AppEvent.h - - path: AppTask.h - path: CHIPProjectConfig.h - - path: RefrigeratorManager.h - - path: refrigerator-and-temperature-controlled-cabinet-mode.h - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/refrigerator-common/include file_list: - path: static-supported-temperature-levels.h + - path: ../../../../third_party/matter_sdk/examples/platform/silabs/customer + file_list: + - path: CustomerAppTask.h + directory: include source: - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/AppTask.cpp - directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp + - path: ../../../../third_party/matter_sdk/examples/platform/silabs/customer/CustomerAppTask.cpp directory: src - path: ../../../../third_party/matter_sdk/examples/platform/silabs/main.cpp directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/DataModelCallbacks.cpp - directory: src - - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/silabs/src/refrigerator-and-temperature-controlled-cabinet-mode.cpp - directory: src - path: ../../../../third_party/matter_sdk/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp directory: src diff --git a/slc/component/matter-examples/matter_refrigerator.slcc b/slc/component/matter-examples/matter_refrigerator.slcc index 162283c53..52f7378ff 100644 --- a/slc/component/matter-examples/matter_refrigerator.slcc +++ b/slc/component/matter-examples/matter_refrigerator.slcc @@ -7,5 +7,12 @@ id: matter_refrigerator quality: production provides: - name: matter_refrigerator +metadata: + sbom: + license: "Apache 2.0" +template_file: + - path: third_party/matter_sdk/examples/refrigerator-app/silabs/include/AppTask.h + - path: third_party/matter_sdk/examples/refrigerator-app/silabs/include/AppTaskImpl.h + - path: third_party/matter_sdk/examples/refrigerator-app/silabs/src/AppTask.cpp ui_hints: visibility: never diff --git a/third_party/matter_sdk b/third_party/matter_sdk index 97d863db9..76543ceae 160000 --- a/third_party/matter_sdk +++ b/third_party/matter_sdk @@ -1 +1 @@ -Subproject commit 97d863db9d0e2860f7e7e5a0c8ba199eb0658860 +Subproject commit 76543ceaed5496ac2652a0cb8b9b8642ae02f97f