Extending Base App Implementation#
Introduction#
Silicon Labs Matter sample apps that support project upgrades use the Curiously
Recurring Template Pattern (CRTP) so you can customize application behavior
without editing the default AppTask implementation. Override *Impl() hooks
in CustomerAppTask instead of modifying AppTask.cpp directly.
CustomerAppTask#
To implement custom app behavior you can override any Silicon Labs implemented
API in the CustomerAppTask file. Each sample app provides
CustomerAppTask.h
and
CustomerAppTask.cpp
for that purpose. The base implementation and the full set of overridable
*Impl() APIs live in that example’s source tree under include/AppTaskImpl.h
and src/AppTask.cpp. Any *Impl() you do not override keeps the Silicon Labs
default behavior.
To customize behavior, copy
CustomerAppTask.h
and
CustomerAppTask.cpp
from examples/platform/silabs/customer/ into your app’s include/ and src/
folders, then update the corresponding paths in BUILD.gn.
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:
Find the method to override in the base API (see Override API reference below).
Declare the same method signature in
CustomerAppTaskin yourCustomerAppTask.hunderprivate:. Match the base*Impl()signature exactly — note that*Impl()overrides are non-static instance methods even when the public dispatcher (e.g.ButtonEventHandler) isstatic.Implement the method in
CustomerAppTask.cpp.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 before Matter Extension 2.9.0 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.
Methods that already exist in the AppTask — Customize them by overriding the matching
*Impl()method inCustomerAppTask. Do not editAppTask.cppfor app-specific behavior.New custom data model methods — Add them in
CustomerAppTaskdirectly. 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() from the lighting app
implementation.
CustomerAppTask.h
#pragma once
#include "AppTaskImpl.h"
/**
* Minimal AppTaskImpl-derived class. Override only the *Impl() methods you need;
* add AppInitImpl(), GetAppTask(), and sAppTask as required by the CRTP base.
*/
class CustomerAppTask : public AppTaskImpl<CustomerAppTask>
{
public:
static CustomerAppTask & GetAppTask() { return sAppTask; }
private:
friend class AppTaskImpl<CustomerAppTask>;
CHIP_ERROR AppInitImpl();
void ButtonEventHandlerImpl(uint8_t button, uint8_t btnAction);
static CustomerAppTask sAppTask;
};
CustomerAppTask.cpp
#include "CustomerAppTask.h"
#include "AppTask.h"
#include "AppConfig.h"
#include "AppEvent.h"
#include <platform/CHIPDeviceLayer.h>
#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
using namespace ::chip::DeviceLayer::Silabs;
#define APP_FUNCTION_BUTTON 0
#define APP_LIGHT_SWITCH 1
CustomerAppTask CustomerAppTask::sAppTask;
AppTask & AppTask::GetAppTask()
{
return CustomerAppTask::GetAppTask();
}
CHIP_ERROR CustomerAppTask::AppInitImpl()
{
SILABS_LOG("CustomerAppTask: custom implementation (AppInitImpl)");
CHIP_ERROR err = this->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 button_event = {};
button_event.Type = AppEvent::kEventType_Button;
button_event.ButtonEvent.Action = btnAction;
if (button == APP_LIGHT_SWITCH && btnAction == static_cast<uint8_t>(SilabsPlatform::ButtonAction::ButtonPressed))
{
button_event.Handler = LightActionEventHandler;
AppTask::GetAppTask().PostEvent(&button_event);
}
else if (button == APP_FUNCTION_BUTTON)
{
button_event.Handler = BaseApplication::ButtonHandler;
AppTask::GetAppTask().PostEvent(&button_event);
}
}
Override API Reference#
CHIP_ERROR StartAppTask() is declared on AppTask only. It is not an
*Impl() hook: platform code (for example MatterConfig) calls
AppTask::GetAppTask().StartAppTask() with static type AppTask &, which runs
the implementation in AppTask.cpp (creating the FreeRTOS app task via
BaseApplication::StartAppTask(...)). To change startup behavior, edit
AppTask::StartAppTask() or BaseApplication::StartAppTask in your product
sources.
The base API and default AppTask behavior for each sample app are maintained
under that app’s include/AppTaskImpl.h and src/AppTask.cpp. Use those files
as the reference for overridable methods and app configuration.
File |
Purpose |
|---|---|
|
Declarations of every overridable |
|
Silicon Labs default implementation of AppTask. This is what runs for any |