diff --git a/examples/oven-app/oven-app-common/include/CookSurfaceEndpoint.h b/examples/oven-app/oven-app-common/include/CookSurfaceEndpoint.h index 36049a9c91..49bf95f298 100644 --- a/examples/oven-app/oven-app-common/include/CookSurfaceEndpoint.h +++ b/examples/oven-app/oven-app-common/include/CookSurfaceEndpoint.h @@ -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. + */ + + 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; }; diff --git a/examples/oven-app/oven-app-common/include/CookTopEndpoint.h b/examples/oven-app/oven-app-common/include/CookTopEndpoint.h index 6dbda29462..cfe073d046 100644 --- a/examples/oven-app/oven-app-common/include/CookTopEndpoint.h +++ b/examples/oven-app/oven-app-common/include/CookTopEndpoint.h @@ -38,10 +38,22 @@ class CookTopEndpoint */ CHIP_ERROR Init(); - void HandleOffCommand(); + /** + * @brief Set On/Off state for the CookTop + * @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; EndpointId mEndpointId = kInvalidEndpointId; }; diff --git a/examples/oven-app/oven-app-common/include/OvenEndpoint.h b/examples/oven-app/oven-app-common/include/OvenEndpoint.h index ecf59b277a..c699089de1 100644 --- a/examples/oven-app/oven-app-common/include/OvenEndpoint.h +++ b/examples/oven-app/oven-app-common/include/OvenEndpoint.h @@ -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 & 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[]; @@ -77,8 +84,10 @@ class OvenModeDelegate : public ModeBase::Delegate class TemperatureControlledCabinetEndpoint { public: + static constexpr uint8_t kModeBaseFeatures = 0; // No specific features for ModeBase::Instance TemperatureControlledCabinetEndpoint(EndpointId endpointId) : - mEndpointId(endpointId), mOvenModeDelegate(mEndpointId), mOvenModeInstance(&mOvenModeDelegate, mEndpointId, OvenMode::Id, 0) + mEndpointId(endpointId), mOvenModeDelegate(mEndpointId), + mOvenModeInstance(&mOvenModeDelegate, mEndpointId, OvenMode::Id, kModeBaseFeatures) {} /** @@ -89,6 +98,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; diff --git a/examples/oven-app/oven-app-common/src/CookSurfaceEndpoint.cpp b/examples/oven-app/oven-app-common/src/CookSurfaceEndpoint.cpp index 0390162d77..453034d828 100644 --- a/examples/oven-app/oven-app-common/src/CookSurfaceEndpoint.cpp +++ b/examples/oven-app/oven-app-common/src/CookSurfaceEndpoint.cpp @@ -17,14 +17,26 @@ */ #include "CookSurfaceEndpoint.h" -#include +#include +#include using namespace chip; +using namespace chip::app::Clusters; using namespace chip::app::Clusters::CookSurface; CHIP_ERROR CookSurfaceEndpoint::Init() { + // Placeholder for user Init return CHIP_NO_ERROR; } -void CookSurfaceEndpoint::HandleOffCommand() {} +chip::Protocols::InteractionModel::Status CookSurfaceEndpoint::GetOnOffState(bool & state) +{ + return OnOffServer::Instance().getOnOffValue(mEndpointId, &state); +} + +chip::Protocols::InteractionModel::Status CookSurfaceEndpoint::SetOnOffState(bool state) +{ + CommandId commandId = state ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id; + return OnOffServer::Instance().setOnOffValue(mEndpointId, commandId, false); +} diff --git a/examples/oven-app/oven-app-common/src/CookTopEndpoint.cpp b/examples/oven-app/oven-app-common/src/CookTopEndpoint.cpp index 871bcd5a58..5c630ef513 100644 --- a/examples/oven-app/oven-app-common/src/CookTopEndpoint.cpp +++ b/examples/oven-app/oven-app-common/src/CookTopEndpoint.cpp @@ -24,7 +24,12 @@ using namespace chip::app::Clusters::CookTop; CHIP_ERROR CookTopEndpoint::Init() { + // Placeholder for user Init return CHIP_NO_ERROR; } -void CookTopEndpoint::HandleOffCommand() {} +chip::Protocols::InteractionModel::Status CookTopEndpoint::SetOnOffState(bool state) +{ + CommandId commandId = state ? OnOff::Commands::On::Id : OnOff::Commands::Off::Id; + return OnOffServer::Instance().setOnOffValue(mEndpointId, commandId, false); +} diff --git a/examples/oven-app/oven-app-common/src/OvenEndpoint.cpp b/examples/oven-app/oven-app-common/src/OvenEndpoint.cpp index 48f1a3bc12..d73627b5bf 100644 --- a/examples/oven-app/oven-app-common/src/OvenEndpoint.cpp +++ b/examples/oven-app/oven-app-common/src/OvenEndpoint.cpp @@ -17,7 +17,10 @@ */ #include "OvenEndpoint.h" +#include #include + +#include "OvenManager.h" #include #include #include @@ -29,59 +32,55 @@ using namespace chip::app::Clusters::Oven; using namespace chip::app::Clusters::OvenMode; using namespace chip::app::Clusters::TemperatureControlledCabinet; using chip::Protocols::InteractionModel::Status; +using detail::Structs::ModeTagStruct::Type; // Static member definitions -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsBake[1] = { { .value = to_underlying(ModeTag::kBake) } }; +const Type OvenModeDelegate::sModeTagsBake[1] = { { .value = to_underlying(ModeTag::kBake) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsConvection[1] = { { .value = to_underlying( - ModeTag::kConvection) } }; +const Type OvenModeDelegate::sModeTagsConvection[1] = { { .value = to_underlying(ModeTag::kConvection) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsGrill[1] = { { .value = to_underlying(ModeTag::kGrill) } }; +const Type OvenModeDelegate::sModeTagsGrill[1] = { { .value = to_underlying(ModeTag::kGrill) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsRoast[1] = { { .value = to_underlying(ModeTag::kRoast) } }; +const Type OvenModeDelegate::sModeTagsRoast[1] = { { .value = to_underlying(ModeTag::kRoast) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsClean[1] = { { .value = to_underlying(ModeTag::kClean) } }; +const Type OvenModeDelegate::sModeTagsClean[1] = { { .value = to_underlying(ModeTag::kClean) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsConvectionBake[1] = { { .value = to_underlying( - ModeTag::kConvectionBake) } }; +const Type OvenModeDelegate::sModeTagsConvectionBake[1] = { { .value = to_underlying(ModeTag::kConvectionBake) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsConvectionRoast[1] = { { .value = to_underlying( - ModeTag::kConvectionRoast) } }; +const Type OvenModeDelegate::sModeTagsConvectionRoast[1] = { { .value = to_underlying(ModeTag::kConvectionRoast) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsWarming[1] = { { .value = - to_underlying(ModeTag::kWarming) } }; +const Type OvenModeDelegate::sModeTagsWarming[1] = { { .value = to_underlying(ModeTag::kWarming) } }; -const detail::Structs::ModeTagStruct::Type OvenModeDelegate::sModeTagsProofing[1] = { { .value = - to_underlying(ModeTag::kProofing) } }; +const Type OvenModeDelegate::sModeTagsProofing[1] = { { .value = to_underlying(ModeTag::kProofing) } }; const detail::Structs::ModeOptionStruct::Type OvenModeDelegate::skModeOptions[to_underlying(OvenModes::kModeCount)] = { { .label = CharSpan::fromCharString("Bake"), .mode = to_underlying(OvenModes::kModeBake), - .modeTags = DataModel::List(sModeTagsBake) }, + .modeTags = DataModel::List(sModeTagsBake) }, { .label = CharSpan::fromCharString("Convection"), .mode = to_underlying(OvenModes::kModeConvection), - .modeTags = DataModel::List(sModeTagsConvection) }, + .modeTags = DataModel::List(sModeTagsConvection) }, { .label = CharSpan::fromCharString("Grill"), .mode = to_underlying(OvenModes::kModeGrill), - .modeTags = DataModel::List(sModeTagsGrill) }, + .modeTags = DataModel::List(sModeTagsGrill) }, { .label = CharSpan::fromCharString("Roast"), .mode = to_underlying(OvenModes::kModeRoast), - .modeTags = DataModel::List(sModeTagsRoast) }, + .modeTags = DataModel::List(sModeTagsRoast) }, { .label = CharSpan::fromCharString("Clean"), .mode = to_underlying(OvenModes::kModeClean), - .modeTags = DataModel::List(sModeTagsClean) }, + .modeTags = DataModel::List(sModeTagsClean) }, { .label = CharSpan::fromCharString("Convection Bake"), .mode = to_underlying(OvenModes::kModeConvectionBake), - .modeTags = DataModel::List(sModeTagsConvectionBake) }, + .modeTags = DataModel::List(sModeTagsConvectionBake) }, { .label = CharSpan::fromCharString("Convection Roast"), .mode = to_underlying(OvenModes::kModeConvectionRoast), - .modeTags = DataModel::List(sModeTagsConvectionRoast) }, + .modeTags = DataModel::List(sModeTagsConvectionRoast) }, { .label = CharSpan::fromCharString("Warming"), .mode = to_underlying(OvenModes::kModeWarming), - .modeTags = DataModel::List(sModeTagsWarming) }, + .modeTags = DataModel::List(sModeTagsWarming) }, { .label = CharSpan::fromCharString("Proofing"), .mode = to_underlying(OvenModes::kModeProofing), - .modeTags = DataModel::List(sModeTagsProofing) } + .modeTags = DataModel::List(sModeTagsProofing) } }; CHIP_ERROR OvenModeDelegate::Init() @@ -92,8 +91,50 @@ CHIP_ERROR OvenModeDelegate::Init() void OvenModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response) { - 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, ¤tMode); + 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); } @@ -135,3 +176,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; +} diff --git a/examples/oven-app/silabs/BUILD.gn b/examples/oven-app/silabs/BUILD.gn index 4f13c657e8..c304802ba9 100644 --- a/examples/oven-app/silabs/BUILD.gn +++ b/examples/oven-app/silabs/BUILD.gn @@ -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 = [] diff --git a/examples/oven-app/silabs/include/AppEvent.h b/examples/oven-app/silabs/include/AppEvent.h index 429a66ce04..cdea818337 100644 --- a/examples/oven-app/silabs/include/AppEvent.h +++ b/examples/oven-app/silabs/include/AppEvent.h @@ -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 @@ -35,6 +38,7 @@ struct AppEvent : public BaseAppEvent { uint8_t Action; int32_t Actor; + void * Context; } OvenEvent; }; }; diff --git a/examples/oven-app/silabs/include/AppTask.h b/examples/oven-app/silabs/include/AppTask.h index 002ce6ae5d..1cf8cc0766 100644 --- a/examples/oven-app/silabs/include/AppTask.h +++ b/examples/oven-app/silabs/include/AppTask.h @@ -87,13 +87,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); }; diff --git a/examples/oven-app/silabs/include/OvenManager.h b/examples/oven-app/silabs/include/OvenManager.h index 05370eca12..1b0f373bd5 100644 --- a/examples/oven-app/silabs/include/OvenManager.h +++ b/examples/oven-app/silabs/include/OvenManager.h @@ -31,11 +31,28 @@ #include "CookSurfaceEndpoint.h" #include "CookTopEndpoint.h" #include "OvenEndpoint.h" + +#include "AppEvent.h" + +#include +#include +#include #include +#include +#include class OvenManager { + public: + enum State_t + { + kCookTopState_Off = 0, + kCookTopState_On, + kCookSurfaceState_Off, + kCookSurfaceState_On + }; + /** * @brief Initializes the OvenManager and its associated resources. * @@ -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; + 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; diff --git a/examples/oven-app/silabs/src/AppSupportedTemperatureLevelsDelegate.cpp b/examples/oven-app/silabs/src/AppSupportedTemperatureLevelsDelegate.cpp index 31121786ff..d13ace66db 100644 --- a/examples/oven-app/silabs/src/AppSupportedTemperatureLevelsDelegate.cpp +++ b/examples/oven-app/silabs/src/AppSupportedTemperatureLevelsDelegate.cpp @@ -31,8 +31,8 @@ CHIP_ERROR AppSupportedTemperatureLevelsDelegate::RegisterSupportedLevels(Endpoi ChipLogError(AppServer, "RegisterSupportedLevels: invalid levels/null or count=0")); VerifyOrReturnError(mRegisteredEndpointCount < kNumCookSurfaceEndpoints, CHIP_ERROR_NO_MEMORY, - ChipLogError(AppServer, "RegisterSupportedLevels: capacity exceeded (%zu)", mRegisteredEndpointCount)); - + ChipLogError(AppServer, "RegisterSupportedLevels: capacity exceeded (%u)", + static_cast(mRegisteredEndpointCount))); // Prevent duplicate endpoints for (size_t i = 0; i < mRegisteredEndpointCount; ++i) { diff --git a/examples/oven-app/silabs/src/AppTask.cpp b/examples/oven-app/silabs/src/AppTask.cpp index beaf4ba6fe..f733ca066d 100644 --- a/examples/oven-app/silabs/src/AppTask.cpp +++ b/examples/oven-app/silabs/src/AppTask.cpp @@ -70,9 +70,8 @@ CHIP_ERROR AppTask::AppInit() GetLCD().Init((uint8_t *) "Oven-App"); #endif - // Initialization of Oven Manager and endpoints of oven and ovenpanel. + // Initialization of Oven Manager and endpoints of oven. OvenManager::GetInstance().Init(); - // Update the LCD with the Stored value. Show QR Code if not provisioned #ifdef DISPLAY_ENABLED GetLCD().WriteDemoUI(false); diff --git a/examples/oven-app/silabs/src/DataModelCallbacks.cpp b/examples/oven-app/silabs/src/DataModelCallbacks.cpp index 60b7c32f5b..b709880170 100644 --- a/examples/oven-app/silabs/src/DataModelCallbacks.cpp +++ b/examples/oven-app/silabs/src/DataModelCallbacks.cpp @@ -22,6 +22,7 @@ #include +#include "OvenManager.h" #include #include #include @@ -36,11 +37,28 @@ using namespace ::chip; void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, uint8_t * value) { - switch (attributePath.mClusterId) + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + switch (clusterId) { case app::Clusters::Identify::Id: - ChipLogProgress(Zcl, "Identify cluster ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", - ChipLogValueMEI(attributePath.mAttributeId), type, *value, size); + ChipLogDetail(Zcl, "Identify cluster ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", ChipLogValueMEI(attributeId), + type, *value, size); + break; + case app::Clusters::OnOff::Id: + ChipLogDetail(Zcl, "OnOff cluster ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", ChipLogValueMEI(attributeId), + type, *value, size); + OvenManager::GetInstance().OnOffAttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size); + break; + case app::Clusters::TemperatureControl::Id: + ChipLogDetail(Zcl, "TemperatureControl cluster ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", + ChipLogValueMEI(attributeId), type, *value, size); + OvenManager::GetInstance().TempCtrlAttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size); + break; + case app::Clusters::OvenMode::Id: + ChipLogDetail(Zcl, "OvenMode cluster ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", ChipLogValueMEI(attributeId), + type, *value, size); + OvenManager::GetInstance().OvenModeAttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size); break; default: break; diff --git a/examples/oven-app/silabs/src/OvenManager.cpp b/examples/oven-app/silabs/src/OvenManager.cpp index cc10d5300e..2f84684b2f 100644 --- a/examples/oven-app/silabs/src/OvenManager.cpp +++ b/examples/oven-app/silabs/src/OvenManager.cpp @@ -22,6 +22,12 @@ #include "OvenEndpoint.h" #include +#include +#include + +#include "AppConfig.h" +#include "AppTask.h" + #include #define MAX_TEMPERATURE 30000 @@ -38,6 +44,12 @@ OvenManager OvenManager::sOvenMgr; void OvenManager::Init() { DeviceLayer::PlatformMgr().LockChipStack(); + + // Initialize states + mCookTopState = kCookTopState_Off; + mCookSurfaceState1 = kCookSurfaceState_Off; + mCookSurfaceState2 = kCookSurfaceState_Off; + // Endpoint initializations VerifyOrReturn(mOvenEndpoint.Init() == CHIP_NO_ERROR, ChipLogError(AppServer, "OvenEndpoint Init failed")); @@ -118,3 +130,83 @@ CHIP_ERROR OvenManager::SetTemperatureControlledCabinetInitialState(EndpointId t return CHIP_NO_ERROR; } + +void OvenManager::TempCtrlAttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size) +{ + switch (endpointId) + { + case kTemperatureControlledCabinetEndpoint: + // TODO: Update the LCD with the new Temperature Control attribute value + break; + default: + break; + } +} + +void OvenManager::OnOffAttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size) +{ + switch (endpointId) + { + case kCookTopEndpoint: + mCookTopState = (*value != 0) ? kCookTopState_On : kCookTopState_Off; + // Turn on/off the associated cook surfaces. + mCookSurfaceEndpoint1.SetOnOffState(*value); + mCookSurfaceEndpoint2.SetOnOffState(*value); + break; + case kCookSurfaceEndpoint1: + case kCookSurfaceEndpoint2: + if (endpointId == kCookSurfaceEndpoint1) + mCookSurfaceState1 = (*value != 0) ? kCookSurfaceState_On : kCookSurfaceState_Off; + else + mCookSurfaceState2 = (*value != 0) ? kCookSurfaceState_On : kCookSurfaceState_Off; + + bool cookSurfaceEndpoint1State; + bool cookSurfaceEndpoint2State; + mCookSurfaceEndpoint1.GetOnOffState(cookSurfaceEndpoint1State); + mCookSurfaceEndpoint2.GetOnOffState(cookSurfaceEndpoint2State); + // Turn off CookTop if both the CookSurfaces are off. + if (!cookSurfaceEndpoint1State && !cookSurfaceEndpoint2State) + { + mCookTopEndpoint.SetOnOffState(false); + mCookTopState = kCookTopState_Off; + } + break; + default: + break; + } + + // Post an event to AppTask for the hardware actions (like LCD and LED update). + AppEvent event = {}; + event.Type = AppEvent::kEventType_UIUpdate; + event.Handler = OvenActionHandler; + AppTask::GetAppTask().PostEvent(&event); +} + +void OvenManager::OvenModeAttributeChangeHandler(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value, + uint16_t size) +{ + VerifyOrReturn(endpointId == kTemperatureControlledCabinetEndpoint, + ChipLogError(AppServer, "Command received over Unsupported Endpoint")); + // Post an event to AppTask for the hardware actions (like LCD and LED update). + AppEvent event = {}; + event.Type = AppEvent::kEventType_UIUpdate; + event.Handler = OvenActionHandler; + AppTask::GetAppTask().PostEvent(&event); +} + +void OvenManager::OvenActionHandler(AppEvent * aEvent) +{ + // TODO: hardware Action : Update the LEDs and LCD of oven-app as required. +} + +bool OvenManager::IsTransitionBlocked(uint8_t fromMode, uint8_t toMode) +{ + for (auto const & bt : kBlockedTransitions) + { + if (bt.fromMode == fromMode && bt.toMode == toMode) + { + return true; + } + } + return false; +}