Skip to content
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

[Chef] Add AirPurifier device in Chef example #31226

Merged
merged 31 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6192b88
After finish Chef fan control manager
erwinpan1 Jan 3, 2024
077a65d
Add Step command to chef airpurifier
erwinpan1 Jan 3, 2024
6787654
Add chef resource monitoring delegates
erwinpan1 Jan 3, 2024
68a39af
Support Chef AirPurfier for nRFConnect
erwinpan1 Jan 3, 2024
7da034f
Restyled by clang-format
restyled-commits Jan 3, 2024
6f21acd
Enable LocalizationConfigurate / TimeFormatLocalization
erwinpan1 Jan 4, 2024
042e926
Remove TimeFormatLocalization and LocalizationConfiguration
erwinpan1 Jan 9, 2024
f211947
Use std::unique_ptr and ValueOr in AirPurifier sample
erwinpan1 Jan 10, 2024
feed412
Restyled by clang-format
restyled-commits Jan 10, 2024
82e4589
Use ValueOr instead of check IsNull()
erwinpan1 Jan 10, 2024
d3e3b69
Fix typo
erwinpan1 Jan 10, 2024
0ecd838
Replacing with chip::BitMask<ResourceMonitoring::Feature>
erwinpan1 Jan 10, 2024
d3b909a
Fix typo
erwinpan1 Jan 10, 2024
826cf5b
Restyled by clang-format
restyled-commits Jan 10, 2024
add6787
Remove comments
erwinpan1 Jan 10, 2024
a9c4b23
Remove unused comment
erwinpan1 Jan 10, 2024
639c032
Use unique_ptr.reset() instead of unique_ptr = nullptr
erwinpan1 Jan 11, 2024
a05f67f
Remove unused comment
erwinpan1 Jan 11, 2024
1e06b0f
Not using nullptr when using unique_ptr
erwinpan1 Jan 11, 2024
65fdf96
Add comments to std::make_unique<ResourceMonitoring::Instance>
erwinpan1 Jan 11, 2024
6f409fb
Restyled by clang-format
restyled-commits Jan 11, 2024
795a046
Use chip:BitMask(args...) instead of static_cast
erwinpan1 Jan 11, 2024
6dd62d0
Remove comments cause confusion
erwinpan1 Jan 11, 2024
4e570ea
Fix speedSetting
erwinpan1 Jan 11, 2024
c6cb0be
Restyled by clang-format
restyled-commits Jan 11, 2024
690e8b9
Make mFanControlManager a std::unique_ptr
erwinpan1 Jan 11, 2024
b1fc294
Rename kLowest to kLowestSpeed
erwinpan1 Jan 11, 2024
6c80df2
Restyled by clang-format
restyled-commits Jan 11, 2024
446e9b7
When decrease, we don't need to check speedMax
erwinpan1 Jan 12, 2024
e01f3c0
Using std::invoke & lambda to return the step
erwinpan1 Jan 12, 2024
93b9788
Restyled by clang-format
restyled-commits Jan 12, 2024
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
144 changes: 144 additions & 0 deletions examples/chef/common/chef-fan-control-manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/clusters/fan-control-server/fan-control-server.h>
#include <app/util/attribute-storage.h>
#include <app/util/error-mapping.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::FanControl;
using namespace chip::app::Clusters::FanControl::Attributes;
using Protocols::InteractionModel::Status;

namespace {
class ChefFanControlManager : public AttributeAccessInterface, public Delegate
{
public:
ChefFanControlManager(EndpointId aEndpointId) :
AttributeAccessInterface(Optional<EndpointId>(aEndpointId), FanControl::Id), Delegate(aEndpointId)
{}

CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
Status HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) override;

private:
CHIP_ERROR ReadPercentCurrent(AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadSpeedCurrent(AttributeValueEncoder & aEncoder);
};

static std::unique_ptr<ChefFanControlManager> mFanControlManager;

CHIP_ERROR ChefFanControlManager::ReadPercentCurrent(AttributeValueEncoder & aEncoder)
{
// Return PercentSetting attribute value for now
DataModel::Nullable<Percent> percentSetting;
EmberAfStatus status = PercentSetting::Get(mEndpoint, percentSetting);

VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, CHIP_ERROR_READ_FAILED);

return aEncoder.Encode(percentSetting.ValueOr(0));
}

CHIP_ERROR ChefFanControlManager::ReadSpeedCurrent(AttributeValueEncoder & aEncoder)
{
// Return SpeedCurrent attribute value for now
DataModel::Nullable<uint8_t> speedSetting;
EmberAfStatus status = SpeedSetting::Get(mEndpoint, speedSetting);

VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, CHIP_ERROR_READ_FAILED);

return aEncoder.Encode(speedSetting.ValueOr(0));
}

Status ChefFanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff)
{
ChipLogProgress(NotSpecified, "ChefFanControlManager::HandleStep aDirection %d, aWrap %d, aLowestOff %d",
to_underlying(aDirection), aWrap, aLowestOff);

VerifyOrReturnError(aDirection != StepDirectionEnum::kUnknownEnumValue, Status::InvalidCommand);

EmberAfStatus status;

uint8_t speedMax;
status = SpeedMax::Get(mEndpoint, &speedMax);
VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::InvalidCommand);

uint8_t speedCurrent;
status = SpeedCurrent::Get(mEndpoint, &speedCurrent);
VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::InvalidCommand);

DataModel::Nullable<uint8_t> speedSetting;
status = SpeedSetting::Get(mEndpoint, speedSetting);
VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::InvalidCommand);

uint8_t newSpeedSetting;
uint8_t speedValue = speedSetting.ValueOr(speedCurrent);
const uint8_t kLowestSpeed = aLowestOff ? 0 : 1;

if (aDirection == StepDirectionEnum::kIncrease)
{
newSpeedSetting = std::invoke([&]() -> uint8_t {
VerifyOrReturnValue(speedValue < speedMax, (aWrap ? kLowestSpeed : speedMax));
return static_cast<uint8_t>(speedValue + 1);
});
}
else if (aDirection == StepDirectionEnum::kDecrease)
{
newSpeedSetting = std::invoke([&]() -> uint8_t {
VerifyOrReturnValue(speedValue > kLowestSpeed, aWrap ? speedMax : kLowestSpeed);
return static_cast<uint8_t>(speedValue - 1);
});
}

return ToInteractionModelStatus(SpeedSetting::Set(mEndpoint, newSpeedSetting));
}

CHIP_ERROR ChefFanControlManager::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
VerifyOrDie(aPath.mClusterId == FanControl::Id);
VerifyOrDie(aPath.mEndpointId == mEndpoint);

switch (aPath.mAttributeId)
{
case SpeedCurrent::Id:
return ReadSpeedCurrent(aEncoder);
case PercentCurrent::Id:
return ReadPercentCurrent(aEncoder);
default:
break;
}
return CHIP_NO_ERROR;
}

} // anonymous namespace

void emberAfFanControlClusterInitCallback(EndpointId endpoint)
{
VerifyOrDie(!mFanControlManager);
mFanControlManager = std::make_unique<ChefFanControlManager>(endpoint);
registerAttributeAccessOverride(mFanControlManager.get());
FanControl::SetDefaultDelegate(endpoint, mFanControlManager.get());
}
157 changes: 157 additions & 0 deletions examples/chef/common/chef-resource-monitoring-delegates.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
#include <app/clusters/resource-monitoring-server/resource-monitoring-server.h>
#include <chef-resource-monitoring-delegates.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ResourceMonitoring;
using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring;
using namespace chip::app::Clusters::HepaFilterMonitoring;
using chip::Protocols::InteractionModel::Status;

const chip::BitMask<ResourceMonitoring::Feature> gHepaFilterFeatureMap(ResourceMonitoring::Feature::kCondition,
ResourceMonitoring::Feature::kWarning,
ResourceMonitoring::Feature::kReplacementProductList);
const chip::BitMask<ResourceMonitoring::Feature> gActivatedCarbonFeatureMap(ResourceMonitoring::Feature::kCondition,
ResourceMonitoring::Feature::kWarning,
ResourceMonitoring::Feature::kReplacementProductList);

static std::unique_ptr<ActivatedCarbonFilterMonitoringDelegate> gActivatedCarbonFilterDelegate;
static std::unique_ptr<ResourceMonitoring::Instance> gActivatedCarbonFilterInstance;

static std::unique_ptr<HepaFilterMonitoringDelegate> gHepaFilterDelegate;
static std::unique_ptr<ResourceMonitoring::Instance> gHepaFilterInstance;

static ImmutableReplacementProductListManager sReplacementProductListManager;

//-- Activated Carbon Filter Monitoring delegate methods
CHIP_ERROR ActivatedCarbonFilterMonitoringDelegate::Init()
{
ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()");
GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
return CHIP_NO_ERROR;
}

Status ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()
{
ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()");
return Status::Success;
}

Status ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()
{
ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()");
return Status::Success;
}

void ActivatedCarbonFilterMonitoring::Shutdown()
{
gActivatedCarbonFilterInstance.reset();
gActivatedCarbonFilterDelegate.reset();
}

//-- Hepa Filter Monitoring delegate methods
CHIP_ERROR HepaFilterMonitoringDelegate::Init()
{
ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::Init()");
GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
return CHIP_NO_ERROR;
}

Status HepaFilterMonitoringDelegate::PreResetCondition()
{
ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PreResetCondition()");
return Status::Success;
}

Status HepaFilterMonitoringDelegate::PostResetCondition()
{
ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PostResetCondition()");
return Status::Success;
}

void HepaFilterMonitoring::Shutdown()
{
gHepaFilterInstance.reset();
gHepaFilterDelegate.reset();
}

void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
{
VerifyOrDie(!gActivatedCarbonFilterInstance && !gActivatedCarbonFilterDelegate);
gActivatedCarbonFilterDelegate = std::make_unique<ActivatedCarbonFilterMonitoringDelegate>();
bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
gActivatedCarbonFilterInstance = std::make_unique<ResourceMonitoring::Instance>(
gActivatedCarbonFilterDelegate.get(), endpoint, ActivatedCarbonFilterMonitoring::Id,
static_cast<uint32_t>(gActivatedCarbonFeatureMap.Raw()), ResourceMonitoring::DegradationDirectionEnum::kDown,
bResetConditionCommandSupported);
gActivatedCarbonFilterInstance->Init();
}

void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
{
VerifyOrDie(!gHepaFilterInstance && !gHepaFilterDelegate);

gHepaFilterDelegate = std::make_unique<HepaFilterMonitoringDelegate>();
bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
gHepaFilterInstance = std::make_unique<ResourceMonitoring::Instance>(
gHepaFilterDelegate.get(), endpoint, HepaFilterMonitoring::Id, static_cast<uint32_t>(gHepaFilterFeatureMap.Raw()),
ResourceMonitoring::DegradationDirectionEnum::kDown, bResetConditionCommandSupported);
gHepaFilterInstance->Init();
}

CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct & item)
{
if (mIndex >= kReplacementProductListMaxSize)
{
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}

switch (mIndex)
{
case 0:
item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc);
item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233"));
break;
case 1:
item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8);
item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx"));
break;
case 2:
item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan);
item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666"));
break;
case 3:
item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14);
item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx"));
break;
case 4:
item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem);
item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx"));
break;
default:
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved
mIndex++;
return CHIP_NO_ERROR;
}
68 changes: 68 additions & 0 deletions examples/chef/common/chef-resource-monitoring-delegates.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
#include <app/clusters/resource-monitoring-server/resource-monitoring-server.h>

namespace chip {
namespace app {
namespace Clusters {

namespace ActivatedCarbonFilterMonitoring {
class ActivatedCarbonFilterMonitoringDelegate : public ResourceMonitoring::Delegate
{
private:
CHIP_ERROR Init() override;
chip::Protocols::InteractionModel::Status PreResetCondition() override;
chip::Protocols::InteractionModel::Status PostResetCondition() override;

public:
~ActivatedCarbonFilterMonitoringDelegate() override = default;
};

void Shutdown();

} // namespace ActivatedCarbonFilterMonitoring

namespace HepaFilterMonitoring {
class HepaFilterMonitoringDelegate : public ResourceMonitoring::Delegate
{
private:
CHIP_ERROR Init() override;
chip::Protocols::InteractionModel::Status PreResetCondition() override;
chip::Protocols::InteractionModel::Status PostResetCondition() override;

public:
~HepaFilterMonitoringDelegate() override = default;
};

class ImmutableReplacementProductListManager : public ResourceMonitoring::ReplacementProductListManager
{
public:
CHIP_ERROR
Next(chip::app::Clusters::ResourceMonitoring::ReplacementProductStruct & item) override;
};

void Shutdown();

} // namespace HepaFilterMonitoring

} // namespace Clusters
} // namespace app
} // namespace chip
Loading
Loading