-
Notifications
You must be signed in to change notification settings - Fork 32
[SL-ONLY] Feature/rangehood app #698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
fa46be1
d1ba54b
198abad
cf49e8d
cec579c
497571f
bf8f9f9
0cfc7bd
be0ec91
9774090
10571ae
df0099d
993bfda
b3e1cd7
7242385
b379f88
0518d5f
f8a933f
491011d
9b0f0ad
e524b0d
756eb2e
929417f
37e6fcf
a5e77f8
997a0fb
2cdc309
b58eac2
beed203
cdff3b3
59ca047
62f33a3
4c9f3b5
a86b80e
43e769c
f423e8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /* | ||
| * | ||
| * Copyright (c) 2025 Project CHIP Authors | ||
| * Copyright (c) 2025 Google LLC. | ||
| * All rights reserved. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| #include <app/clusters/fan-control-server/fan-control-server.h> | ||
| #include <app/data-model/Nullable.h> | ||
| #include <lib/core/CHIPError.h> | ||
| #include <lib/core/DataModelTypes.h> | ||
|
|
||
| class ExtractorHoodEndpoint | ||
| { | ||
| public: | ||
| /** | ||
| * @brief Construct the ExtractorHood endpoint. | ||
| * @param endpointId The endpoint ID | ||
| * @param lowPercent Percent value for Low mode (default: 30) | ||
| * @param mediumPercent Percent value for Medium mode (default: 60) | ||
| * @param highPercent Percent value for High/On mode (default: 100) | ||
| * | ||
| * Off is always 0 per spec: "The value 0 SHALL map to Off and be its own range". | ||
| */ | ||
| ExtractorHoodEndpoint(chip::EndpointId endpointId, chip::Percent lowPercent = 30, chip::Percent mediumPercent = 60, | ||
| chip::Percent highPercent = 100) : | ||
| mEndpointId(endpointId), | ||
| mFanModeOffPercent(0), mFanModeLowPercent(lowPercent), mFanModeMediumPercent(mediumPercent), | ||
| mFanModeHighPercent(highPercent) | ||
| {} | ||
|
|
||
| /** | ||
| * @brief Initialize the ExtractorHood endpoint runtime state. | ||
| * Reads current PercentSetting and synchronizes PercentCurrent. | ||
| * | ||
| * @note Must be called after construction and after the Matter stack is initialized. | ||
| * @return CHIP_NO_ERROR on success, error code otherwise | ||
| */ | ||
| CHIP_ERROR Init(); | ||
|
|
||
| chip::app::DataModel::Nullable<chip::Percent> GetPercentSetting() const; | ||
|
|
||
| /** | ||
| * @brief Get the FanMode attribute. | ||
| **/ | ||
| chip::Protocols::InteractionModel::Status GetFanMode(chip::app::Clusters::FanControl::FanModeEnum & fanMode) const; | ||
|
|
||
| /** @brief Set the PercentCurrent attribute if it differs from the current value. | ||
| * | ||
| **/ | ||
| chip::Protocols::InteractionModel::Status SetPercentCurrent(chip::Percent newPercentSetting); | ||
|
|
||
| /** | ||
| * @brief Handle percent setting change and update percent current accordingly | ||
| * This is called when the PercentSetting attribute changes and updates PercentCurrent | ||
| * if the fan mode is not Auto and the value is different | ||
| * | ||
| * @param newPercentSetting The new percent setting value | ||
| * @return Status Success on success, error code otherwise | ||
| */ | ||
| chip::Protocols::InteractionModel::Status HandlePercentSettingChange(chip::Percent newPercentSetting); | ||
|
|
||
| /** | ||
| * @brief Handle fan mode change and update percent current accordingly | ||
| * This maps fan modes to their corresponding percent values and updates the PercentCurrent attribute | ||
| * | ||
| * @param newFanMode The new fan mode to apply | ||
| * @return Status Success on success, error code otherwise | ||
| */ | ||
| chip::Protocols::InteractionModel::Status HandleFanModeChange(chip::app::Clusters::FanControl::FanModeEnum newFanMode); | ||
|
|
||
| /** | ||
| * @brief Update the FanMode attribute | ||
| */ | ||
| chip::Protocols::InteractionModel::Status UpdateFanModeAttribute(chip::app::Clusters::FanControl::FanModeEnum newFanMode); | ||
|
|
||
| /** | ||
| * @brief Toggle fan mode between Off and High | ||
| * This is typically used for button press toggles | ||
| * @return Status Success on success, error code otherwise | ||
| */ | ||
| chip::Protocols::InteractionModel::Status ToggleFanMode(); | ||
|
|
||
| private: | ||
| chip::EndpointId mEndpointId = chip::kInvalidEndpointId; | ||
|
|
||
| // Fan Mode Percent Mappings (set during initialization) | ||
| chip::Percent mFanModeOffPercent; | ||
| chip::Percent mFanModeLowPercent; | ||
| chip::Percent mFanModeMediumPercent; | ||
| chip::Percent mFanModeHighPercent; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* | ||
| * | ||
| * Copyright (c) 2025 Project CHIP Authors | ||
| * All rights reserved. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <app/clusters/on-off-server/on-off-server.h> | ||
| #include <lib/core/CHIPError.h> | ||
| #include <lib/core/DataModelTypes.h> | ||
|
|
||
| class LightEndpoint | ||
| { | ||
| public: | ||
| LightEndpoint(chip::EndpointId endpointId) : mEndpointId(endpointId) {} | ||
|
|
||
| /** | ||
| * @brief Get the current On/Off state from the Matter attribute. | ||
| * @param[out] state true if light is on, false if off on success. | ||
| * @return Interaction Model status code. | ||
| */ | ||
| CHIP_ERROR GetOnOffState(bool & state); | ||
|
|
||
| /** | ||
| * @brief Set On/Off state for the Light. | ||
| * @param[in] state Desired state (true => On, false => Off). | ||
| * @return Interaction Model status code. | ||
| */ | ||
| CHIP_ERROR SetOnOffState(bool state); | ||
|
|
||
| private: | ||
| chip::EndpointId mEndpointId = chip::kInvalidEndpointId; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,230 @@ | ||
| /* | ||
| * | ||
| * Copyright (c) 2025 Project CHIP Authors | ||
| * All rights reserved. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #include "ExtractorHoodEndpoint.h" | ||
|
|
||
| #include <app-common/zap-generated/attributes/Accessors.h> | ||
| #include <app/clusters/fan-control-server/fan-control-server.h> | ||
| #include <lib/core/CHIPError.h> | ||
| #include <lib/support/logging/CHIPLogging.h> | ||
| #include <platform/CHIPDeviceLayer.h> | ||
|
|
||
| #include <algorithm> | ||
|
|
||
| using namespace chip; | ||
| using namespace chip::app; | ||
| using namespace chip::DeviceLayer; | ||
| using namespace chip::app::Clusters; | ||
| using namespace chip::app::Clusters::FanControl; | ||
| using Status = chip::Protocols::InteractionModel::Status; | ||
|
|
||
| CHIP_ERROR ExtractorHoodEndpoint::Init() | ||
| { | ||
| // Initialize percent current from percent setting | ||
| // This ensures the fan speed reflects the current setting on startup | ||
| DeviceLayer::PlatformMgr().LockChipStack(); | ||
| DataModel::Nullable<chip::Percent> percentSettingNullable = GetPercentSetting(); | ||
| DeviceLayer::PlatformMgr().UnlockChipStack(); | ||
|
|
||
| Percent initialPercentSetting = percentSettingNullable.IsNull() ? 0 : percentSettingNullable.Value(); | ||
| DeviceLayer::PlatformMgr().LockChipStack(); | ||
| Status status = HandlePercentSettingChange(initialPercentSetting); | ||
| DeviceLayer::PlatformMgr().UnlockChipStack(); | ||
| if (status != Status::Success) | ||
| { | ||
| ChipLogError(NotSpecified, "ExtractorHoodEndpoint::Init: Failed to initialize PercentCurrent"); | ||
| return CHIP_ERROR_INTERNAL; | ||
| } | ||
|
|
||
| return CHIP_NO_ERROR; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get the PercentSetting attribute. | ||
| * The caller MUST hold the CHIP stack lock before calling this function, | ||
| * unless calling from a CHIP task context where the lock is already held. | ||
| */ | ||
| DataModel::Nullable<Percent> ExtractorHoodEndpoint::GetPercentSetting() const | ||
| { | ||
| DataModel::Nullable<Percent> percentSetting; | ||
|
|
||
| Status status = Clusters::FanControl::Attributes::PercentSetting::Get(mEndpointId, percentSetting); | ||
|
|
||
| VerifyOrReturnValue(status == Status::Success, DataModel::Nullable<Percent>(), | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::GetPercentSetting: failed to get PercentSetting attribute: %d", | ||
| to_underlying(status))); | ||
| return percentSetting; | ||
| } | ||
|
|
||
| /* The caller MUST hold the CHIP stack lock before calling this function, | ||
| * unless calling from a CHIP task context where the lock is already held. | ||
| */ | ||
| Status ExtractorHoodEndpoint::GetFanMode(FanControl::FanModeEnum & fanMode) const | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a Datamodel Command? if so why is this here? If not then this should be a ChipError not a IM::Status
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to check the current FanMode while button event based on which FanMode will be updated. So added GetFanMode function to read directly from server. |
||
| { | ||
| Status status = FanControl::Attributes::FanMode::Get(mEndpointId, &fanMode); | ||
|
|
||
| VerifyOrReturnValue(status == Status::Success, status, | ||
| ChipLogError(NotSpecified, "ExtractorHoodEndpoint::GetFanMode: failed to get FanMode attribute: %d", | ||
| to_underlying(status))); | ||
|
|
||
| return Status::Success; | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * The caller MUST hold the CHIP stack lock before calling this function, | ||
| * unless calling from a CHIP task context where the lock is already held. | ||
| */ | ||
| Status ExtractorHoodEndpoint::SetPercentCurrent(Percent newPercentSetting) | ||
| { | ||
| Percent currentPercentCurrent = 0; | ||
|
|
||
| Status getStatus = FanControl::Attributes::PercentCurrent::Get(mEndpointId, ¤tPercentCurrent); | ||
|
|
||
| // Return error if we can't read current value | ||
| VerifyOrReturnValue(getStatus == Status::Success, getStatus, | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::HandlePercentSettingChange: failed to get currentPercentCurrent: %d", | ||
| to_underlying(getStatus))); | ||
|
|
||
| // No update needed if value is unchanged | ||
| VerifyOrReturnValue(newPercentSetting != currentPercentCurrent, Status::Success); | ||
|
|
||
| Status setStatus = FanControl::Attributes::PercentCurrent::Set(mEndpointId, newPercentSetting); | ||
|
|
||
| VerifyOrReturnValue(setStatus == Status::Success, Status::Failure, | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::SetPercentCurrent: failed to update PercentCurrent attribute: %d", | ||
| to_underlying(setStatus))); | ||
| return Status::Success; | ||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * @brief Handle a change to the PercentSetting attribute, updating PercentCurrent as needed. | ||
| * The caller MUST hold the CHIP stack lock before calling this function, | ||
| * unless calling from a CHIP task context where the lock is already held. | ||
| */ | ||
| Status ExtractorHoodEndpoint::HandlePercentSettingChange(Percent newPercentSetting) | ||
| { | ||
| ChipLogDetail(NotSpecified, "ExtractorHoodEndpoint::HandlePercentSettingChange: %d", newPercentSetting); | ||
| // Get current PercentCurrent to check if it's different | ||
| Percent currentPercentCurrent = 0; | ||
|
|
||
| Status getStatus = FanControl::Attributes::PercentCurrent::Get(mEndpointId, ¤tPercentCurrent); | ||
|
|
||
| // Return error if we can't read current value | ||
| VerifyOrReturnValue(getStatus == Status::Success, getStatus, | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::HandlePercentSettingChange: failed to get PercentCurrent: %d", | ||
| to_underlying(getStatus))); | ||
| // No update needed if value is unchanged | ||
| VerifyOrReturnValue(newPercentSetting != currentPercentCurrent, Status::Success); | ||
|
|
||
| // Get current fan mode to check if it's Auto | ||
| FanControl::FanModeEnum currentFanMode; | ||
|
|
||
| Status fanModeStatus = FanControl::Attributes::FanMode::Get(mEndpointId, ¤tFanMode); | ||
|
|
||
| // Fail if we can't read fan mode | ||
| VerifyOrReturnValue(fanModeStatus == Status::Success, Status::Failure, | ||
| ChipLogError(NotSpecified, "ExtractorHoodEndpoint::HandlePercentSettingChange: failed to get FanMode: %d", | ||
| to_underlying(fanModeStatus))); | ||
|
|
||
| // Don't update PercentCurrent if fan mode is Auto | ||
| VerifyOrReturnValue(currentFanMode != FanControl::FanModeEnum::kAuto, Status::Success); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Smart Mode: Automatic Control BrokenThe |
||
|
|
||
| // Update PercentCurrent to match PercentSetting | ||
| Status setStatus = FanControl::Attributes::PercentCurrent::Set(mEndpointId, newPercentSetting); | ||
|
|
||
| VerifyOrReturnValue( | ||
| setStatus == Status::Success, Status::Failure, | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::HandlePercentSettingChange: failed to update PercentCurrent attribute: %d", | ||
| to_underlying(setStatus))); | ||
| return Status::Success; | ||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Status ExtractorHoodEndpoint::HandleFanModeChange(chip::app::Clusters::FanControl::FanModeEnum newFanMode) | ||
| { | ||
| ChipLogDetail(NotSpecified, "ExtractorHoodEndpoint::HandleFanModeChange: %d", (uint8_t) newFanMode); | ||
|
|
||
| switch (newFanMode) | ||
| { | ||
| case FanControl::FanModeEnum::kOff: { | ||
| return SetPercentCurrent(mFanModeOffPercent); | ||
| } | ||
| case FanControl::FanModeEnum::kLow: { | ||
| return SetPercentCurrent(mFanModeLowPercent); | ||
| } | ||
| case FanControl::FanModeEnum::kMedium: { | ||
| return SetPercentCurrent(mFanModeMediumPercent); | ||
| } | ||
| case FanControl::FanModeEnum::kOn: | ||
| case FanControl::FanModeEnum::kHigh: { | ||
| return SetPercentCurrent(mFanModeHighPercent); | ||
| } | ||
| case FanControl::FanModeEnum::kSmart: | ||
| case FanControl::FanModeEnum::kAuto: { | ||
| // For Auto/Smart modes, update the FanMode attribute to reflect the current mode | ||
| return UpdateFanModeAttribute(newFanMode); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Improve Fan Mode Attribute Update EfficiencyFor Auto and Smart fan modes, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Fan Mode Attribute: Redundant Write IssueFor |
||
| case FanControl::FanModeEnum::kUnknownEnumValue: { | ||
| ChipLogProgress(NotSpecified, "ExtractorHoodEndpoint::HandleFanModeChange: Unknown"); | ||
| return Status::Success; // Don't treat unknown as error | ||
| } | ||
| default: | ||
| return Status::Success; | ||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
| * @brief Update the FanMode attribute. | ||
| * The caller MUST hold the CHIP stack lock before calling this function, | ||
| * unless calling from a CHIP task context where the lock is already held. | ||
| */ | ||
| Status ExtractorHoodEndpoint::UpdateFanModeAttribute(FanControl::FanModeEnum newFanMode) | ||
| { | ||
| Status setStatus = FanControl::Attributes::FanMode::Set(mEndpointId, newFanMode); | ||
|
|
||
| VerifyOrReturnValue(setStatus == Status::Success, Status::Failure, | ||
| ChipLogError(NotSpecified, | ||
| "ExtractorHoodEndpoint::UpdateFanModeAttribute: failed to update FanMode attribute: %d", | ||
| to_underlying(setStatus))); | ||
| return Status::Success; | ||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * @brief Toggle fan mode between Off and High. | ||
| * This is used for button press toggles. | ||
| */ | ||
| Status ExtractorHoodEndpoint::ToggleFanMode() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same comment
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cluster implementation does not have any setters or getter functions to read/write the attributes accordingly, so everything implemented in application. For example, each fan mode change, the percentcurrent will be set to values form 0 to 100. |
||
| { | ||
| FanControl::FanModeEnum currentFanMode = FanControl::FanModeEnum::kUnknownEnumValue; | ||
| Status getStatus = GetFanMode(currentFanMode); | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (getStatus != Status::Success || currentFanMode == FanControl::FanModeEnum::kUnknownEnumValue) | ||
| { | ||
| ChipLogError(NotSpecified, "ExtractorHoodEndpoint::ToggleFanMode: failed to get current fan mode"); | ||
| return Status::Failure; | ||
| } | ||
|
|
||
| FanControl::FanModeEnum target = | ||
| (currentFanMode == FanControl::FanModeEnum::kOff) ? FanControl::FanModeEnum::kHigh : FanControl::FanModeEnum::kOff; | ||
|
|
||
| return UpdateFanModeAttribute(target); | ||
| } | ||
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
bhmanda-silabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.