Skip to content
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f24e3f0
Oven App skeleton code with all endpoint initialisations
arun-silabs Oct 16, 2025
90e0388
Restyled by whitespace
restyled-commits Oct 16, 2025
65a5c48
Restyled by clang-format
restyled-commits Oct 16, 2025
1a8dd8d
Address copilot review
arun-silabs Oct 21, 2025
8c86d55
Restyled by clang-format
restyled-commits Oct 21, 2025
204d3a1
Apply suggestions from code review
arun-silabs Oct 21, 2025
ec3943e
Apply suggestions from code review
arun-silabs Oct 21, 2025
2b9505f
Address copilot review comments
arun-silabs Oct 22, 2025
03aa29e
Address review comments and modify the file structures accordingly
arun-silabs Oct 23, 2025
ebf324e
Restyled by gn
restyled-commits Oct 23, 2025
6d73e62
Add required TODOs and optimize the skeleton code
arun-silabs Oct 23, 2025
9f63524
Restyled by whitespace
restyled-commits Oct 23, 2025
d5f86e9
Restyled by clang-format
restyled-commits Oct 23, 2025
00952f3
Cleanup comments
arun-silabs Oct 23, 2025
df13ff4
Address review comments
arun-silabs Oct 28, 2025
3f5eaec
Commands implementation
arun-silabs Oct 26, 2025
dde3035
Add logic to handle the oven-mode change
arun-silabs Oct 26, 2025
c36c1ca
Clean-up the command handling logic
arun-silabs Oct 27, 2025
efdc6e3
Restyled by whitespace
restyled-commits Oct 27, 2025
f1aacf6
Restyled by clang-format
restyled-commits Oct 27, 2025
caad0fb
Address review comments
arun-silabs Oct 28, 2025
c9545d8
Address review comments
arun-silabs Oct 29, 2025
b1e9be0
Restyled by whitespace
restyled-commits Oct 29, 2025
0e0ee4e
Restyled by clang-format
restyled-commits Oct 29, 2025
3643d79
Move ChangeToMode command processing to common layer
arun-silabs Oct 29, 2025
49a6cbb
Restyled by whitespace
restyled-commits Oct 29, 2025
17e72b9
Restyled by clang-format
restyled-commits Oct 29, 2025
5826f8f
Handle review comments
arun-silabs Nov 4, 2025
232fe4f
Rebase with main branch
arun-silabs Nov 5, 2025
50bfb9c
Restyled by whitespace
restyled-commits Nov 5, 2025
efceeac
Restyled by clang-format
restyled-commits Nov 5, 2025
d3cb6fa
Apply suggestions from code review
arun-silabs Nov 5, 2025
ba72490
Address review comments
arun-silabs Nov 5, 2025
f68c4e2
Fix zap issue
arun-silabs Nov 5, 2025
fbc02c4
Restyled by clang-format
restyled-commits Nov 5, 2025
52cb237
Remove redundant cook surface init
arun-silabs Nov 5, 2025
1baad61
Address review comments
arun-silabs Nov 5, 2025
6d426f9
Restyled by clang-format
restyled-commits Nov 5, 2025
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
32 changes: 30 additions & 2 deletions examples/oven-app/oven-app-common/include/CookSurfaceEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,40 @@ class CookSurfaceEndpoint
*/
CHIP_ERROR Init();

void HandleOffCommand();
/**
* @brief Gets the current On/Off state from server.
* @param state Reference to store the current On/Off state.
*
* Note: This helper reads the OnOff attribute from the CHIP attribute storage and
* therefore must be invoked from the CHIP/DeviceLayer task context or while holding
* the CHIP stack lock (DeviceLayer::PlatformMgr().LockChipStack()). Calling this
* API from an arbitrary thread can cause asserts / crashes in the CHIP stack.
* If you are not in the CHIP task, schedule work onto the CHIP task using
* PlatformMgr().ScheduleWork(...) and call this helper from there.
*
* @return Returns Status::Success on success, or an error code on failure.
*/

Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Extra blank line between documentation and function declaration. Remove the blank line on line 55 to maintain consistency with standard documentation formatting practices.

Suggested change

Copilot uses AI. Check for mistakes.
chip::Protocols::InteractionModel::Status GetOnOffState(bool & state);

/**
* @brief Set On/Off state for the CookSurface.
* @param state Desired On/Off state.
*
* Note: This helper writes the OnOff attribute to the CHIP attribute storage and
* therefore must be invoked from the CHIP/DeviceLayer task context or while holding
* the CHIP stack lock (DeviceLayer::PlatformMgr().LockChipStack()). Calling this
* API from an arbitrary thread can cause asserts / crashes in the CHIP stack.
* If you are not in the CHIP task, schedule work onto the CHIP task using
* PlatformMgr().ScheduleWork(...) and call this helper from there.
*
* @return Returns Status::Success on success, or an error code on failure.
*/
chip::Protocols::InteractionModel::Status SetOnOffState(bool state);

EndpointId GetEndpointId() const { return mEndpointId; }

private:
bool currentOnOffState = false;
EndpointId mEndpointId = kInvalidEndpointId;
};

Expand Down
15 changes: 14 additions & 1 deletion examples/oven-app/oven-app-common/include/CookTopEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,20 @@ class CookTopEndpoint
*/
CHIP_ERROR Init();

void HandleOffCommand();
/**
* @brief Set On/Off state for the CookSurface.
* @param state Desired On/Off state.
*
* Note: This helper writes the OnOff attribute to the CHIP attribute storage and
* therefore must be invoked from the CHIP/DeviceLayer task context or while holding
* the CHIP stack lock (DeviceLayer::PlatformMgr().LockChipStack()). Calling this
* API from an arbitrary thread can cause asserts / crashes in the CHIP stack.
* If you are not in the CHIP task, schedule work onto the CHIP task using
* PlatformMgr().ScheduleWork(...) and call this helper from there.
*
* @return Returns Status::Success on success, or an error code on failure.
*/
chip::Protocols::InteractionModel::Status SetOnOffState(bool state);

private:
bool currentOnOffState = false;
Expand Down
16 changes: 15 additions & 1 deletion examples/oven-app/oven-app-common/include/OvenEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ class OvenModeDelegate : public ModeBase::Delegate
CHIP_ERROR GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) override;
CHIP_ERROR GetModeTagsByIndex(uint8_t modeIndex, DataModel::List<detail::Structs::ModeTagStruct::Type> & tags) override;

/**
* @brief Checks if the provided mode is supported.
*
* @param mode The mode to check.
* @return true if the mode is supported, false otherwise.
*/
bool IsSupportedMode(uint8_t mode);

private:
EndpointId mEndpointId;

// Static arrays moved to implementation file to reduce header size
static const detail::Structs::ModeTagStruct::Type sModeTagsBake[];
static const detail::Structs::ModeTagStruct::Type sModeTagsConvection[];
static const detail::Structs::ModeTagStruct::Type sModeTagsGrill[];
Expand Down Expand Up @@ -89,6 +96,13 @@ class TemperatureControlledCabinetEndpoint
*/
CHIP_ERROR Init();

/**
* @brief Get the oven mode delegate instance.
*
* @return Reference to the oven mode delegate.
*/
OvenModeDelegate & GetOvenModeDelegate() { return mOvenModeDelegate; }

private:
EndpointId mEndpointId = kInvalidEndpointId;
OvenModeDelegate mOvenModeDelegate;
Expand Down
2 changes: 0 additions & 2 deletions examples/oven-app/oven-app-common/oven-app.matter
Original file line number Diff line number Diff line change
Expand Up @@ -2589,5 +2589,3 @@ endpoint 5 {
ram attribute clusterRevision default = 4;
}
}


21 changes: 19 additions & 2 deletions examples/oven-app/oven-app-common/src/CookSurfaceEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,31 @@
*/

#include "CookSurfaceEndpoint.h"
#include <lib/core/CHIPError.h>
#include <app/clusters/on-off-server/on-off-server.h>
#include <protocols/interaction_model/StatusCode.h>

using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::CookSurface;

CHIP_ERROR CookSurfaceEndpoint::Init()
{
return CHIP_NO_ERROR;
}

void CookSurfaceEndpoint::HandleOffCommand() {}
chip::Protocols::InteractionModel::Status CookSurfaceEndpoint::GetOnOffState(bool & state)
{
auto status = OnOffServer::Instance().getOnOffValue(mEndpointId, &state);
VerifyOrReturnValue(status == Protocols::InteractionModel::Status::Success, status,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could do without this verify or return and let the higher level handle the logging if necessary. Please remove.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

ChipLogError(AppServer, "ERR: reading on/off %x", to_underlying(status)));
return status;
}

chip::Protocols::InteractionModel::Status CookSurfaceEndpoint::SetOnOffState(bool state)
{
CommandId commandId = state ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id;
auto status = OnOffServer::Instance().setOnOffValue(mEndpointId, commandId, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling 'OnOffServer::Instance().setOnOffValue` must be called from the ChipTask context or with the ChipTask lock else it will cause and assert/chip die.

When called in OnOffAttributeChangeHandler which is called from MatterPostAttributeCallback, we are indeed in the ChipTaskl context. However, if this is called somewhere else then this might not be the case and it can lead to crashes.

If you keep it this way this function usage (an all the copied functionson the other endpoints) needs to be documented to explain this risk/limitation in the usage.

Same goes for the GetOnOffState

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like @jmartinez-silabs said please add a lock on the chip task before doing so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added comments in the header file regarding the usage of this function.
I guess we do not need to add lock on chip-task in this place as the SetOnOffValue is being executed from chiptask only.

VerifyOrReturnValue(status == Protocols::InteractionModel::Status::Success, status,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again since we are returning a status, please remove this check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

ChipLogError(AppServer, "ERR: updating on/off %x", to_underlying(status)));
return status;
}
9 changes: 8 additions & 1 deletion examples/oven-app/oven-app-common/src/CookTopEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ CHIP_ERROR CookTopEndpoint::Init()
return CHIP_NO_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again please add a comment as why this function is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a placeholder function similar to one in CookSurface, added a comment.

}

void CookTopEndpoint::HandleOffCommand() {}
chip::Protocols::InteractionModel::Status CookTopEndpoint::SetOnOffState(bool state)
{
CommandId commandId = state ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id;
auto status = OnOffServer::Instance().setOnOffValue(mEndpointId, commandId, false);
VerifyOrReturnValue(status == Protocols::InteractionModel::Status::Success, status,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this line as we are returning a status

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

ChipLogError(AppServer, "ERR: updating on/off %x", to_underlying(status)));
return status;
}
61 changes: 59 additions & 2 deletions examples/oven-app/oven-app-common/src/OvenEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/

#include "OvenEndpoint.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>

#include "OvenManager.h"
#include <app/clusters/mode-base-server/mode-base-cluster-objects.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -92,8 +95,50 @@ CHIP_ERROR OvenModeDelegate::Init()

void OvenModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't we have a mode enum somewhere in another header file ? is so we should use it instead of the generic uint8_t

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HandleChangeToMode is a function given by the delegate. In the delegate, it has uint8_t as the parameter type.
For oven modes, we have added a mode enum instead of having the modes as some static constants.

{
ChipLogProgress(Zcl, "OvenModeDelegate::HandleChangeToMode: NewMode=%d", NewMode);
// TODO: Implement logic to change the oven mode.
ChipLogProgress(Zcl, "OvenModeDelegate forwarding mode change to OvenManager (ep=%u newMode=%u)", mEndpointId, NewMode);
// Verify newMode is among supported modes
bool supported = IsSupportedMode(NewMode);
if (!supported)
{
response.status = to_underlying(ModeBase::StatusCode::kUnsupportedMode);
return;
}

// Read Current Oven Mode
uint8_t currentMode;
Status attrStatus = OvenMode::Attributes::CurrentMode::Get(mEndpointId, &currentMode);
if (attrStatus != Status::Success)
{
ChipLogError(AppServer, "OvenManager: Failed to read CurrentMode");
response.status = to_underlying(ModeBase::StatusCode::kGenericFailure);
response.statusText.SetValue(CharSpan::fromCharString("Read CurrentMode failed"));
return;
}

// No action needed if current mode is the same as new mode
if (currentMode == NewMode)
{
response.status = to_underlying(ModeBase::StatusCode::kSuccess);
return;
}

if (OvenManager::GetInstance().IsTransitionBlocked(currentMode, NewMode))
{
ChipLogProgress(AppServer, "OvenManager: Blocked transition %u -> %u", currentMode, NewMode);
response.status = to_underlying(ModeBase::StatusCode::kGenericFailure);
response.statusText.SetValue(CharSpan::fromCharString("Transition blocked"));
return;
}

// Write new mode
Status writeStatus = OvenMode::Attributes::CurrentMode::Set(mEndpointId, NewMode);
if (writeStatus != Status::Success)
{
ChipLogError(AppServer, "OvenManager: Failed to write CurrentMode");
response.status = to_underlying(ModeBase::StatusCode::kGenericFailure);
response.statusText.SetValue(CharSpan::fromCharString("Write CurrentMode failed"));
return;
}
response.status = to_underlying(ModeBase::StatusCode::kSuccess);
}

Expand Down Expand Up @@ -135,3 +180,15 @@ CHIP_ERROR OvenEndpoint::Init()
{
return CHIP_NO_ERROR;
}

bool OvenModeDelegate::IsSupportedMode(uint8_t mode)
{
for (auto const & opt : skModeOptions)
{
if (opt.mode == mode)
{
return true;
}
}
return false;
}
1 change: 1 addition & 0 deletions examples/oven-app/silabs/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ if (wifi_soc) {
"${examples_plat_dir}",
"${chip_root}/src/lib",
"${examples_common_plat_dir}",
"${example_oven_dir}/oven-app-common/include",
]

defines = []
Expand Down
4 changes: 4 additions & 0 deletions examples/oven-app/silabs/include/AppEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ struct AppEvent : public BaseAppEvent
enum AppEventTypes
{
kEventType_Oven = BaseAppEvent::kEventType_Max + 1,
kEventType_CookTop,
kEventType_CookSurface,
kEventType_Install,
kEventType_UIUpdate,
};

union
Expand All @@ -35,6 +38,7 @@ struct AppEvent : public BaseAppEvent
{
uint8_t Action;
int32_t Actor;
void * Context;
} OvenEvent;
};
};
10 changes: 1 addition & 9 deletions examples/oven-app/silabs/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "AppEvent.h"
#include "BaseApplication.h"
#include "OvenManager.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not needed, removed it.


#include "FreeRTOS.h"
#include "timers.h" // provides FreeRTOS timer support
Expand Down Expand Up @@ -87,13 +88,4 @@ class AppTask : public BaseApplication
* @return CHIP_ERROR
*/
CHIP_ERROR AppInit() override;

/**
* @brief PB0 Button event processing function
* Press and hold will trigger a factory reset timer start
* Press and release will restart BLEAdvertising if not commissioned
*
* @param aEvent button event being processed
*/
static void ButtonHandler(AppEvent * aEvent);
};
82 changes: 82 additions & 0 deletions examples/oven-app/silabs/include/OvenManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,28 @@
#include "CookSurfaceEndpoint.h"
#include "CookTopEndpoint.h"
#include "OvenEndpoint.h"

#include "AppEvent.h"

#include <app-common/zap-generated/ids/Attributes.h>
#include <app/clusters/mode-base-server/mode-base-cluster-objects.h>
#include <app/clusters/on-off-server/on-off-server.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/TypeTraits.h>
#include <platform/CHIPDeviceLayer.h>

class OvenManager
{

public:
enum State_t
{
kCookTopState_Off = 0,
kCookTopState_On,
kCookSurfaceState_Off,
kCookSurfaceState_On
};

/**
* @brief Initializes the OvenManager and its associated resources.
*
Expand All @@ -52,11 +69,76 @@ class OvenManager
CHIP_ERROR SetCookSurfaceInitialState(chip::EndpointId cookSurfaceEndpoint);

CHIP_ERROR SetTemperatureControlledCabinetInitialState(chip::EndpointId temperatureControlledCabinetEndpoint);
/**
* @brief Handles temperature control attribute changes.
*
* @param endpointId The ID of the endpoint.
* @param attributeId The ID of the attribute.
* @param value Pointer to the new value.
* @param size Size of the new value.
*/
void TempCtrlAttributeChangeHandler(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value, uint16_t size);

/**
* @brief Handles on/off attribute changes.
*
* @param endpointId The ID of the endpoint.
* @param attributeId The ID of the attribute.
* @param value Pointer to the new value.
* @param size Size of the new value.
*/
void OnOffAttributeChangeHandler(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value, uint16_t size);

/**
* @brief Handles oven mode attribute changes.
*
* @param endpointId The ID of the endpoint.
* @param attributeId The ID of the attribute.
* @param value Pointer to the new value.
* @param size Size of the new value.
*/
void OvenModeAttributeChangeHandler(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value, uint16_t size);

/**
* @brief Checks if a transition between two oven modes is blocked.
*
* @param fromMode The current mode.
* @param toMode The desired mode.
* @return True if the transition is blocked, false otherwise.
*/
bool IsTransitionBlocked(uint8_t fromMode, uint8_t toMode);

private:
struct BlockedTransition
{
uint8_t fromMode;
uint8_t toMode;
};

// Disallowed OvenMode Transitions.
static constexpr BlockedTransition kBlockedTransitions[3] = {
{ chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeGrill),
chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeProofing) },
{ chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeProofing),
chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeClean) },
{ chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeClean),
chip::to_underlying(chip::app::Clusters::TemperatureControlledCabinet::OvenModeDelegate::OvenModes::kModeBake) },
};

static OvenManager sOvenMgr;
chip::app::Clusters::AppSupportedTemperatureLevelsDelegate mTemperatureControlDelegate;

State_t mCookTopState;
State_t mCookSurfaceState1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 2 SurfaceState ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

customer requirements mentioned 2 surfaces . so we added 2 surfaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A cook-top can contain multiple cook-surfaces
In our app, we have 2 cook surfaces (as per the requirements doc that we received). . To store the state of these 2 cook-surfaces separately, i have used 2 state variables. There is a possibility that one cook-surface is "On" and another cook-surface is "Off"

State_t mCookSurfaceState2;

/**
* @brief Updates the oven hardware state and UI (LEDs, LCD) in response to an event.
*
* @param aEvent Pointer to the event structure.
*/
static void OvenActionHandler(AppEvent * aEvent);

// Define the endpoint ID for the Oven
static constexpr chip::EndpointId kOvenEndpoint = 1;
static constexpr chip::EndpointId kTemperatureControlledCabinetEndpoint = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ CHIP_ERROR AppSupportedTemperatureLevelsDelegate::RegisterSupportedLevels(Endpoi

VerifyOrReturnError(mRegisteredEndpointCount < kNumCookSurfaceEndpoints, CHIP_ERROR_NO_MEMORY,
ChipLogError(AppServer, "RegisterSupportedLevels: capacity exceeded (%zu)", mRegisteredEndpointCount));

// Prevent duplicate endpoints
for (size_t i = 0; i < mRegisteredEndpointCount; ++i)
{
Expand Down
Loading
Loading