Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions sld250-matter-references/custom-matter-device.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ through this function. The command can then be dissected using conditional logic
to call the proper application functions based on the most recent command
received.

Depending on your sample application, edit the files. For more information, refer to [Application Customization Models](/matter/{build-docspace-version}/matter-api-reference/#application-customization-models). New architecture apps route attribute changes through `CustomerAppTask` and `DMPostAttributeChangeCallbackImpl()`. Legacy architecture apps implement `MatterPostAttributeChangeCallback()` directly in `src/DataModelCallbacks.cpp`.

## Adding a Cluster to a ZAP Configuration

In the ZAP UI, navigate to the Level Control cluster. Make sure this cluster is
Expand All @@ -79,13 +81,31 @@ is set to enabled. Set the default value of this attribute as 1.
Navigate to the commands tab in zap and enable the MoveToLevel command. Now save
the current zap configuration, and run the generate.py script above.

## React to Level Control Cluster Commands in ZclCallbacks
## React to Level Control Cluster Commands

### New Architecture

In a custom implementation of `DMPostAttributeChangeCallbackImpl()` in `src/CustomerAppTask.cpp`, add the following or similar code. This enables the application to react to the MoveToLevel commands.

```cpp
else if (clusterId == LevelControl::Id)
{
ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
ChipLogValueMEI(attributeId), type, *value, size);

if (attributeId == LevelControl::Attributes::CurrentLevel::Id)
{
sLightLED.SetLevel(*value);
}
}
```

### Legacy Architecture

In the MatterPostAttributeCallback function in ZclCallbacks, add the following
line of code or a similar line. This will give the application the ability to react to
MoveToLevel commands. You can define platform-specific behavior for a
MoveToLevel action.

```cpp
else if (clusterId == LevelControl::Id)
{
Expand Down
47 changes: 41 additions & 6 deletions sld295-matter-api-reference/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@ Attributes represent the current state of a device. For instance if the device i

## Attribute Changes

When a ZCL attribute is updated in the data model, the framework will call the `postAttributeChangeCallback`. If this callback is implemented by the device it will be informed of the attribute change. The device may react to the attribute change. For example, in `MatterPostAttributeChangeCallback` in `DataModelCallbacks.cpp` in [onoff-plug-app/src](https://github.com/SiliconLabs/matter_extension/tree/main/examples/onoff-plug-app/src), say we want to add some custom handler code to control an RGB LED when on/off attribute in the `On-Off` Cluster changes:
Depending on your sample app, instructions apply. For more information, refer to [Application customization models](./index.md#application-customization-models).

### New Architecture

When a ZCL attribute is updated in the data model, the framework invokes the post-attribute-change path. The Silicon Labs Matter stack routes this as follows: `MatterPostAttributeChangeCallback` in `BaseApplication.cpp` → `AppTask::DMPostAttributeChangeCallback` in `autogen/AppTask.cpp` → your optional `DMPostAttributeChangeCallbackImpl()` override in `CustomerAppTask`.

If this callback is implemented by the device, it is informed of the attribute change. The device may react to the attribute change. For example, in `DMPostAttributeChangeCallback` function the in `AppTask.cpp` file ([onoff-plug-app/src](https://github.com/SiliconLabsSoftware/matter_sdk/blob/main/examples/onoff-plug-app/silabs/src/AppTask.cpp)), if you want to add a custom handler code to control an RGB LED when on/off attribute in the `On-Off` Cluster changes, implement the following in `DMPostAttributeChangeCallbackImpl` in `src/CustomerAppTask.cpp`:

```cpp
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath,
uint8_t type,
uint16_t size,
uint8_t * value)
void DMPostAttributeChangeCallbackImpl(const chip::app::ConcreteAttributePath & attributePath,
uint8_t type,
uint16_t size,
uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;
ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));

if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
{
/* Custom code */
if (*value)
{ // turn on LED
sl_led_turn_on((sl_led_t *)&sl_simple_rgb_pwm_led_rgb_led0);
Expand All @@ -34,6 +39,36 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
}
```

### Legacy Architecture

When a ZCL attribute is updated in the data model, the framework calls `MatterPostAttributeChangeCallback()` in `src/DataModelCallbacks.cpp`. If this callback is implemented by the device it will be informed of the attribute change. For example, to control an RGB LED when the On/Off attribute changes:

```cpp
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath,
uint8_t type,
uint16_t size,
uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;
ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));

if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
{
if (*value)
{ // turn on LED
sl_led_turn_on((sl_led_t *)&sl_simple_rgb_pwm_led_rgb_led0);
}
else
{// turn off LED
sl_led_turn_off((sl_led_t *)&sl_simple_rgb_pwm_led_rgb_led0);
}
}

//...
}
```

## Header File

This file contains the high level namespaces and constant definitions for Attributes. In Simplicity Studio, this will be generated in the autogen/zap-generated/ folder of the matter project.
Expand Down
4 changes: 3 additions & 1 deletion sld295-matter-api-reference/event.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

Events are records of past state transitions such as a light device's on-off attribute changing from on to off.

The autogenerated file [```include/AppEvent.h```](https://github.com/SiliconLabs/matter_extension/blob/main/examples/template/include/AppEvent.h) houses the definition of the event object used by the application. It contains the event types, the structures for each event, and event handler.
The autogenerated file [```include/AppEvent.h```](https://github.com/SiliconLabs/matter_extension/blob/main/third_party/matter_sdk/examples/template/silabs/include/AppEvent.h) contains the definition of the event object used by the application. It includes the event types, the structures for each event, and event handler.

**New architecture:** Custom event posting and handlers are overridden in the `CustomerAppTask` file, not in `autogen/AppTask.cpp`.

## Header File

Expand Down
31 changes: 29 additions & 2 deletions sld295-matter-api-reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,39 @@ This section covers the various Application Programming Interfaces (APIs) that a

## Application APIs

### Application Customization Models

Matter Extension 2.9.0 migrates a subset of sample apps to the Curiously Recurring Template Pattern (CRTP) based architecture, which removes app manager and DataModelCallbacks files. All other sample apps keep the previous architecture until the patch release.

Check your project in Project Explorer:

| If you see… | Architecture | Where to add custom logic |
|---|---|---|
| `src/CustomerAppTask.cpp` and `autogen/AppTask.cpp` | **New** | Override `*Impl()` hooks in `CustomerAppTask`, do not edit `autogen/AppTask.cpp` |
| `src/DataModelCallbacks.cpp` and editable `src/AppTask.cpp` | **Legacy** | Callbacks in `DataModelCallbacks.cpp`, init and app logic in `src/AppTask.cpp` |

**Sample apps on the new architecture in 2.9.0:**

- Lighting
- Zigbee Matter Light
- On/Off Plug
- Thermostat
- Lock
- Light Switch
- Rangehood
- Platform Template
- Air Quality Sensor

All other Silicon Labs Matter sample apps in this release use the legacy model. Pages below label steps as **New architecture** or **Legacy architecture** where they differ.

### Initialization

The application 'Init' sequence lives in the ```AppTask.cpp``` file, and is called at the beginning of the application to ensure that all components are properly initialized and ready to operate. It sets up necessary callbacks, initializes hardware components, and handles any errors that may occur during the process. This function is crucial for the stable operation of the application.
**New architecture:** Default initialization is included in `autogen/AppTask.cpp`. Override `AppInitImpl()` and other `*Impl()` hooks in `src/CustomerAppTask.cpp` to customize behavior.

**Legacy architecture:** The application Init sequence is included in `src/AppTask.cpp` and is called at the beginning of the application to ensure that all components are properly initialized and ready to operate. It sets up necessary callbacks, initializes hardware components, and handles any errors that may occur during the process.

```cpp
CHIP_ERROR AppTask::Init()
```

The ```AppTask.cpp``` file may also contain event handlers and helper code useful to the application.
The `AppTask.cpp` file may also contain event handlers and helper code useful to the application.
2 changes: 1 addition & 1 deletion sld57-matter-landing-page/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Want to get a Matter application up and running quickly? Here's a high-level ove

4. **[Optional] Customize Matter App Behavior and Logic**
- Use Project Configurator and other Studio tools to customize your app logic: [Developing with Project Configurator](https://docs.silabs.com/ssv6ug/latest/ssv6-configure-project/)
- If necessary, add custom source files for your application logic
- Customize app behavior using the model your sample app provides — see [Application Customization Models](/matter/{build-docspace-version}/matter-api-reference/#application-customization-models). Refactored apps use `CustomerAppTask` and `autogen/AppTask.cpp`, all other apps use `DataModelCallbacks.cpp` and `src/AppTask.cpp`.
- Follow documentation to develop a custom matter device with ZAP and corresponding callbacks: [Custom Matter Device Development](/matter/{build-docspace-version}/matter-references/custom-matter-device)

5. **Build and Flash**
Expand Down
Binary file not shown.
Comment thread
miduggan24 marked this conversation as resolved.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,23 @@ Now that the On/Off cluster has been successfully added to the Sample Door Lock

- Attributes, commands, and events for the cluster are added to your application’s data model.
- Code is generated for attribute storage, command handling, and event notification.
- Callback stubs are generated for you to implement application-specific behavior.
- You interact with the cluster by filling in these stubs and using the generated data structures.
- **New architecture**: implement application-specific behavior in `src/CustomerAppTask.cpp` by overriding `*Impl()` hooks (for example `DMPostAttributeChangeCallbackImpl()`), not by editing `autogen/AppTask.cpp`.
- **Legacy architecture**: Callback stubs are generated for you to implement application-specific behavior. You interact with the cluster by filling in these stubs and using the generated data structures.

Additionally, a corresponding component is automatically added to your project. This occurs because enabling a cluster in ZAP updates your project configuration to include the necessary software components and libraries required to support that cluster’s functionality. For clusters, this functionality is implemented in the `<matter_extension>/third_party/matter_sdk/src/app/clusters` directory. For the On/Off cluster, the server command handlers and related logic can be found in the `/on-off-server/on-off-server.cpp` file.

## Step 4: Add Application Logic

Locate your project's `src/AppTask.cpp` file. This file acts as the central hub for application-specific logic, initialization, and event processing in a Matter application on Silicon Labs platforms. Start by adding two helper functions: a one-shot timer to expire in 10 seconds and the `OnOffTmrExpiryHandler` handler function.
This guide uses the Lock sample app, which is on the **new architecture** in 2.9.0. See [Application Customization Models](/matter/{build-docspace-version}/matter-api-reference/#application-customization-models) to confirm which model your project uses.

### New Architecture

Application logic centers on AppTask, but refactored Matter projects split responsibilities:

- `autogen/AppTask.cpp`: default implementation, regenerated on project upgrade (do not edit for application logic, use as reference only).
- `src/CustomerAppTask.cpp` and `include/CustomerAppTask.h`: your custom logic, add custom code and override `*Impl()` hooks here.

In `src/CustomerAppTask.cpp`, add two helper functions: a one-shot timer to expire in 10 seconds and the `OnOffTmrExpiryHandler` handler function.

```C++
#include "app-common/zap-generated/attributes/Accessors.h"
Expand All @@ -87,45 +96,73 @@ void OnOffTmrStart(){
}
```

Make sure to include `app-common/zap-generated/attributes/Accessors.h` in your `AppTask.cpp` file so you can access cluster attributes.
Include `app-common/zap-generated/attributes/Accessors.h` in `CustomerAppTask.cpp`, so that you can access cluster attributes.

Next we will need an AppTask function to initiate the timer. Add the following function to your AppTask.cpp file:
Next we will need an AppTask function to initiate the timer. Declare `OnOffAttributeWriteStartTimer()` in `include/CustomerAppTask.h` and define it in `src/CustomerAppTask.cpp`:

```C++
void AppTask::OnOffAttributeWriteStartTimer()
void OnOffAttributeWriteStartTimer()
{
OnOffTmrStart();
}
```

This function will have to be defined in AppTask.h as well as part of the AppTask class.
Because you modify the OnOff attribute in `OnOffTmrExpiryHandler()`, restart the timer whenever the OnOff attribute changes. Override `DMPostAttributeChangeCallbackImpl()` in `CustomerAppTask` (the SDK routes attribute changes through `MatterPostAttributeChangeCallback` in `BaseApplication.cpp`, then `AppTask::DMPostAttributeChangeCallback` in autogen):

```C++
void DMPostAttributeChangeCallbackImpl(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;

if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id){
OnOffAttributeWriteStartTimer();
}

}
```

Finally, add a call to `OnOffTmrStart()` at the end of your `AppInitImpl()` override in `CustomerAppTask.cpp` to start the attribute write sequence. The following image illustrates the code flow:

![Code Flow](./images/ClusterLogic6.png)

In the flowchart above, `OnOffAttributeWriteStartTimer()` calls `OnOffTmrStart()` to restart the timer.

### Legacy Architecture

Locate your project's src/AppTask.cpp file. This file acts as the central hub for application-specific logic, initialization, and event processing in a Matter application on Silicon Labs platforms. Start by adding two helper functions: a one-shot timer to expire in 10 seconds and the OnOffTmrExpiryHandler handler function.

Include `app-common/zap-generated/attributes/Accessors.h` in your `AppTask.cpp` file, so that you can access cluster attributes.

Add the timer start function to `AppTask.cpp` and declare it in `AppTask.h`:

Now, locate the `MatterPostAttributeChangeCallback()` function in the `src/DataModelCallbacks.cpp` file. This function is invoked by the application framework after an attribute value has been changed. Because you are modifying the OnOff attribute in the `OnOffTmrExpiryHandler()` function, use this callback to re-initiate the timer so that the attribute continues to toggle. To achieve this, call `AppTask::OnOffAttributeWriteStartTimer()`, which is part of the AppTask context.
```C++
void AppTask::OnOffAttributeWriteStartTimer()
{
OnOffTmrStart();
}
```

To implement this functionality, first obtain the AppTask instance using `AppTask::GetAppTask()`. Modify the `MatterPostAttributeChangeCallback()` function as shown below:
Now, locate the MatterPostAttributeChangeCallback() function in the src/DataModelCallbacks.cpp file. This function is invoked by the application framework after an attribute value has been changed. Because you are modifying the OnOff attribute in the OnOffTmrExpiryHandler() function, use this callback to re-initiate the timer so that the attribute continues to toggle. To achieve this, call AppTask::OnOffAttributeWriteStartTimer(), which is part of the AppTask context.

```C++
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;

// Auto-generated code

if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id){
AppTask::GetAppTask().OnOffAttributeWriteStartTimer();
}

}
```
Make sure to #include "AppTask.h" at the top of the `DataModelCallbacks.cpp` file to call the `AppTask::GetAppTask()` function. For more information on the AppTask, refer to AppTask.h.

Finally, add a call to `OnOffTmrStart()` at the end of the `AppTask::AppInit()` function to start the attribute write sequence. The following image illustrates the code flow:
Make sure to #include "AppTask.h" at the top of the DataModelCallbacks.cpp file to call the AppTask::GetAppTask() function. For more information on the AppTask, refer to AppTask.h.

![Code Flow](./images/ClusterLogic6.jpg)

In the flowchart above, `OnOffAttributeWriteStartTimer()` calls `OnOffTmrStart()` to restart the timer.
Finally, add a call to OnOffTmrStart() at the end of the AppTask::AppInit() function to start the attribute write sequence.

## Step 5: Interact with the On/Off Cluster

Expand Down
Loading