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

Add water heater management cluster sdk support #34339

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dcb4a57
Add base water-heater-mode-cluster support into control files and reg…
PeterC1965 Jul 15, 2024
6935f04
Add support for the water-heater-management cluster SDK
PeterC1965 Jul 15, 2024
f230cfa
Add support for the water-heater-management cluster SDK
PeterC1965 Jul 15, 2024
c2ee681
Add support for the water-heater-management cluster SDK
PeterC1965 Jul 15, 2024
cbbacdb
Add support for the water-heater-management cluster SDK
PeterC1965 Jul 15, 2024
624d9c6
Define chip_enable_water_heater_management_trigger and CHIP_DEVICE_CO…
PeterC1965 Jul 15, 2024
be2a49c
Restyled by isort
restyled-commits Jul 15, 2024
ca7ad50
Add accidentally deleted Mode_WaterHeater.xml back
PeterC1965 Jul 15, 2024
6f49b11
Address review comments from Tennessee Carmel-Veilleux
PeterC1965 Jul 16, 2024
aab0be3
Add WaterHeaterManagementTestEventTriggerHandler.h
PeterC1965 Jul 16, 2024
c837678
Apply various review comments from Boris Zbarsky
PeterC1965 Jul 16, 2024
6c93f6a
Apply various review comments from Boris Zbarsky
PeterC1965 Jul 16, 2024
fc7188a
Addressing review comments from Boris
PeterC1965 Jul 18, 2024
5493664
Addressing review comments from Boris
PeterC1965 Jul 18, 2024
97e6d41
Restyled by whitespace
restyled-commits Jul 18, 2024
bd879b5
Restyled by clang-format
restyled-commits Jul 18, 2024
1668d3a
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 18, 2024
2c43cf0
Address review comment from Tennessee
PeterC1965 Jul 18, 2024
65e7542
Update with review comments from Boris
PeterC1965 Jul 21, 2024
1626daa
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 22, 2024
d38c545
Fix compilation introduced during merge
PeterC1965 Jul 22, 2024
b10398c
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 23, 2024
cf319aa
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 25, 2024
46cd339
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 25, 2024
5c21924
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 26, 2024
e458e09
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 26, 2024
a167c34
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 27, 2024
628dd91
Merge branch 'master' into add-water-heater-management-cluster-sdk-su…
PeterC1965 Jul 28, 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
7 changes: 7 additions & 0 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
#include <app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
#include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
#endif
Expand Down Expand Up @@ -556,6 +559,10 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl)
static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler;
sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler;
sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler;
sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler);
Expand Down
2 changes: 2 additions & 0 deletions examples/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ declare_args() {
chip_enable_boolean_state_configuration_trigger = false
chip_enable_energy_evse_trigger = false
chip_enable_energy_reporting_trigger = false
chip_enable_water_heater_management_trigger = false
chip_enable_device_energy_management_trigger = false
}

Expand Down Expand Up @@ -125,6 +126,7 @@ source_set("app-main") {
"CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER=${chip_enable_boolean_state_configuration_trigger}",
"CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER=${chip_enable_energy_evse_trigger}",
"CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER=${chip_enable_energy_reporting_trigger}",
"CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER=${chip_enable_water_heater_management_trigger}",
"CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER=${chip_enable_device_energy_management_trigger}",
]

Expand Down
6 changes: 6 additions & 0 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,12 @@ template("chip_data_model") {
"${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.cpp",
"${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.h",
]
} else if (cluster == "water-heater-management-server") {
sources += [
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
"${_app_root}/clusters/${cluster}/${cluster}.h",
"${_app_root}/clusters/${cluster}/WaterHeaterManagementTestEventTriggerHandler.h",
]
} else if (cluster == "thread-network-directory-server") {
sources += [
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
Expand Down
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
*
* Copyright (c) 2024 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.
*/

#pragma once

#include <app-common/zap-generated/cluster-objects.h>
#include <app/TestEventTriggerDelegate.h>

/**
* @brief User handler for handling the test event trigger
*
* @note If TestEventTrigger is enabled, it needs to be implemented in the app
*
* @param eventTrigger Event trigger to handle
*
* @retval true on success
* @retval false if error happened
*/
bool HandleWaterHeaterManagementTestEventTrigger(uint64_t eventTrigger);
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved

namespace chip {

/*
* These Test EventTrigger values can be used to produce artificial water heater configuration
* and water temperatures.
*
* They are sent along with the enableKey (manufacturer defined secret)
* in the General Diagnostic cluster TestEventTrigger command
*/
enum class WaterHeaterManagementTrigger : uint64_t
{
// Simulate installation in a 100L tank full of water at 20C, with a target temperature of 60C, in OFF mode
kBasicInstallationTestEvent = 0x0094'0000'0000'0000,

// End simulation of installation
kBasicInstallationTestEventClear = 0x0094'0000'0000'0001,

// Simulate 100% of the water in the tank being at 20C
kWaterTemperature20CTestEvent = 0x0094'0000'0000'0002,

// Simulate 100% of the water in the tank being at 61C
kWaterTemperature61CTestEvent = 0x0094'0000'0000'0003,

// Simulate 100% of the water in the tank being at 66C
kWaterTemperature66CTestEvent = 0x0094'0000'0000'0004,

// Simulate the Water Heater Mode being set to MANUAL
kManualModeTestEvent = 0x0094'0000'0000'0005,

// Simulate the Water Heater Mode being set to OFF
kOffModeTestEvent = 0x0094'0000'0000'0006,

// Simulate drawing off 25% of the tank volume of hot water, replaced with water at 20C
kDrawOffHotWaterTestEvent = 0x0094'0000'0000'0007,
};

class WaterHeaterManagementTestEventTriggerHandler : public TestEventTriggerHandler
{
public:
WaterHeaterManagementTestEventTriggerHandler() {}

CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override
{
if (HandleWaterHeaterManagementTestEventTrigger(eventTrigger))
{
return CHIP_NO_ERROR;
}
return CHIP_ERROR_INVALID_ARGUMENT;
}
};

} // namespace chip
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Copyright (c) 2024 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 "water-heater-management-server.h"

#include <app/AttributeAccessInterface.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/ConcreteAttributePath.h>
#include <app/InteractionModelEngine.h>
#include <app/util/attribute-storage.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::WaterHeaterManagement;
using namespace chip::app::Clusters::WaterHeaterManagement::Attributes;

using chip::Protocols::InteractionModel::Status;

namespace chip {
namespace app {
namespace Clusters {
namespace WaterHeaterManagement {

constexpr uint16_t kClusterRevision = 1;

CHIP_ERROR Instance::Init()
{
ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this));
VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE);

return CHIP_NO_ERROR;
}

void Instance::Shutdown()
{
InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this);
unregisterAttributeAccessOverride(this);
}

bool Instance::HasFeature(Feature aFeature) const
{
return mFeature.Has(aFeature);
}

// AttributeAccessInterface
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
{
switch (aPath.mAttributeId)
{
case HeaterTypes::Id:
return aEncoder.Encode(mDelegate.GetHeaterTypes());
case HeatDemand::Id:
return aEncoder.Encode(mDelegate.GetHeatDemand());
case TankVolume::Id:
if (!HasFeature(Feature::kEnergyManagement))
{
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
return aEncoder.Encode(mDelegate.GetTankVolume());
case EstimatedHeatRequired::Id:
if (!HasFeature(Feature::kEnergyManagement))
{
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
return aEncoder.Encode(mDelegate.GetEstimatedHeatRequired());
case TankPercentage::Id:
if (!HasFeature(Feature::kTankPercent))
{
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
return aEncoder.Encode(mDelegate.GetTankPercentage());
case BoostState::Id:
return aEncoder.Encode(mDelegate.GetBoostState());

/* FeatureMap - is held locally */
case FeatureMap::Id:
return aEncoder.Encode(mFeature);
case ClusterRevision::Id:
return aEncoder.Encode(kClusterRevision);
}

/* Allow all other unhandled attributes to fall through to Ember */
return CHIP_NO_ERROR;
}

void Instance::InvokeCommand(HandlerContext & handlerContext)
{
using namespace Commands;

switch (handlerContext.mRequestPath.mCommandId)
{
case Boost::Id:
HandleCommand<Boost::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleBoost(ctx, commandData); });
return;
case CancelBoost::Id:
HandleCommand<CancelBoost::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCancelBoost(ctx, commandData); });
return;
}
}

void Instance::HandleBoost(HandlerContext & ctx, const Commands::Boost::DecodableType & commandData)
{
uint32_t duration = commandData.duration;
Optional<bool> oneShot = commandData.oneShot;
Optional<bool> emergencyBoost = commandData.emergencyBoost;
Optional<int16_t> temporarySetpoint = commandData.temporarySetpoint;
Optional<Percent> targetPercentage = commandData.targetPercentage;
Optional<Percent> targetReheat = commandData.targetReheat;

// Notify the appliance if the appliance hardware cannot be adjusted, then return Failure
if (HasFeature(WaterHeaterManagement::Feature::kTankPercent))
{
if (targetPercentage.HasValue())
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
{
if (targetPercentage.Value() > 100)
{
ChipLogError(Zcl, "Bad targetPercentage %u", targetPercentage.Value());
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
return;
}
}

if (targetReheat.HasValue())
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
{
if (targetReheat.Value() > 100)
{
ChipLogError(Zcl, "Bad targetReheat %u", targetReheat.Value());
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
return;
}

if (!targetPercentage.HasValue())
{
ChipLogError(Zcl, "targetPercentage must be specified if targetReheat specified");
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
return;
}

if (oneShot.HasValue())
{
ChipLogError(Zcl, "Cannot specify targetReheat with targetPercentage and oneShot. oneShot must be excluded");
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
return;
}
}
}
else if (targetPercentage.HasValue() || targetReheat.HasValue())
{
ChipLogError(Zcl, "Cannot specify targetPercentage or targetReheat if the feature TankPercent is not supported");
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
return;
}

Status status = mDelegate.HandleBoost(duration, oneShot, emergencyBoost, temporarySetpoint, targetPercentage, targetReheat);
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
if (status != Status::Success)
{
ChipLogError(Zcl, "WHM: Boost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status));
}
}

void Instance::HandleCancelBoost(HandlerContext & ctx, const Commands::CancelBoost::DecodableType & commandData)
{
Status status = mDelegate.HandleCancelBoost();
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
if (status != Status::Success)
{
ChipLogError(Zcl, "WHM: CancelBoost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status));
return;
}
}

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