Skip to content

Commit 5e3127f

Browse files
Add water heater management cluster sdk support (#34339)
* Add base water-heater-mode-cluster support into control files and regenerate files * Add support for the water-heater-management cluster SDK * Add support for the water-heater-management cluster SDK * Add support for the water-heater-management cluster SDK * Add support for the water-heater-management cluster SDK * Define chip_enable_water_heater_management_trigger and CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER * Restyled by isort * Add accidentally deleted Mode_WaterHeater.xml back * Address review comments from Tennessee Carmel-Veilleux * Add WaterHeaterManagementTestEventTriggerHandler.h * Apply various review comments from Boris Zbarsky * Apply various review comments from Boris Zbarsky * Addressing review comments from Boris * Addressing review comments from Boris * Restyled by whitespace * Restyled by clang-format * Address review comment from Tennessee * Update with review comments from Boris * Fix compilation introduced during merge --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 13fe13a commit 5e3127f

File tree

13 files changed

+511
-450
lines changed

13 files changed

+511
-450
lines changed

examples/platform/linux/AppMain.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
9191
#include <app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h>
9292
#endif
93+
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
94+
#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
95+
#endif
9396
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
9497
#include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
9598
#endif
@@ -556,6 +559,10 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl)
556559
static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler;
557560
sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler);
558561
#endif
562+
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
563+
static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler;
564+
sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler);
565+
#endif
559566
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
560567
static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler;
561568
sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler);

examples/platform/linux/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ declare_args() {
2424
chip_enable_boolean_state_configuration_trigger = false
2525
chip_enable_energy_evse_trigger = false
2626
chip_enable_energy_reporting_trigger = false
27+
chip_enable_water_heater_management_trigger = false
2728
chip_enable_device_energy_management_trigger = false
2829
}
2930

@@ -125,6 +126,7 @@ source_set("app-main") {
125126
"CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER=${chip_enable_boolean_state_configuration_trigger}",
126127
"CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER=${chip_enable_energy_evse_trigger}",
127128
"CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER=${chip_enable_energy_reporting_trigger}",
129+
"CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER=${chip_enable_water_heater_management_trigger}",
128130
"CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER=${chip_enable_device_energy_management_trigger}",
129131
]
130132

src/app/chip_data_model.gni

+6
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,12 @@ template("chip_data_model") {
398398
"${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.cpp",
399399
"${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.h",
400400
]
401+
} else if (cluster == "water-heater-management-server") {
402+
sources += [
403+
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
404+
"${_app_root}/clusters/${cluster}/${cluster}.h",
405+
"${_app_root}/clusters/${cluster}/WaterHeaterManagementTestEventTriggerHandler.h",
406+
]
401407
} else if (cluster == "thread-network-directory-server") {
402408
sources += [
403409
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include <app-common/zap-generated/cluster-objects.h>
21+
#include <app/TestEventTriggerDelegate.h>
22+
23+
/**
24+
* @brief User handler for handling the test event trigger
25+
*
26+
* @note If TestEventTrigger is enabled, it needs to be implemented in the app
27+
*
28+
* @param eventTrigger Event trigger to handle
29+
*
30+
* @retval true on success
31+
* @retval false if error happened
32+
*/
33+
bool HandleWaterHeaterManagementTestEventTrigger(uint64_t eventTrigger);
34+
35+
namespace chip {
36+
37+
/*
38+
* These Test EventTrigger values can be used to produce artificial water heater configuration
39+
* and water temperatures.
40+
*
41+
* They are sent along with the enableKey (manufacturer defined secret)
42+
* in the General Diagnostic cluster TestEventTrigger command
43+
*/
44+
enum class WaterHeaterManagementTrigger : uint64_t
45+
{
46+
// Simulate installation in a 100L tank full of water at 20C, with a target temperature of 60C, in OFF mode
47+
kBasicInstallationTestEvent = 0x0094'0000'0000'0000,
48+
49+
// End simulation of installation
50+
kBasicInstallationTestEventClear = 0x0094'0000'0000'0001,
51+
52+
// Simulate 100% of the water in the tank being at 20C
53+
kWaterTemperature20CTestEvent = 0x0094'0000'0000'0002,
54+
55+
// Simulate 100% of the water in the tank being at 61C
56+
kWaterTemperature61CTestEvent = 0x0094'0000'0000'0003,
57+
58+
// Simulate 100% of the water in the tank being at 66C
59+
kWaterTemperature66CTestEvent = 0x0094'0000'0000'0004,
60+
61+
// Simulate the Water Heater Mode being set to MANUAL
62+
kManualModeTestEvent = 0x0094'0000'0000'0005,
63+
64+
// Simulate the Water Heater Mode being set to OFF
65+
kOffModeTestEvent = 0x0094'0000'0000'0006,
66+
67+
// Simulate drawing off 25% of the tank volume of hot water, replaced with water at 20C
68+
kDrawOffHotWaterTestEvent = 0x0094'0000'0000'0007,
69+
};
70+
71+
class WaterHeaterManagementTestEventTriggerHandler : public TestEventTriggerHandler
72+
{
73+
public:
74+
WaterHeaterManagementTestEventTriggerHandler() {}
75+
76+
CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override
77+
{
78+
if (HandleWaterHeaterManagementTestEventTrigger(eventTrigger))
79+
{
80+
return CHIP_NO_ERROR;
81+
}
82+
return CHIP_ERROR_INVALID_ARGUMENT;
83+
}
84+
};
85+
86+
} // namespace chip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "water-heater-management-server.h"
18+
19+
#include <app/AttributeAccessInterface.h>
20+
#include <app/AttributeAccessInterfaceRegistry.h>
21+
#include <app/ConcreteAttributePath.h>
22+
#include <app/InteractionModelEngine.h>
23+
#include <app/util/attribute-storage.h>
24+
25+
using namespace chip;
26+
using namespace chip::app;
27+
using namespace chip::app::Clusters;
28+
using namespace chip::app::Clusters::WaterHeaterManagement;
29+
using namespace chip::app::Clusters::WaterHeaterManagement::Attributes;
30+
31+
using chip::Protocols::InteractionModel::Status;
32+
33+
namespace chip {
34+
namespace app {
35+
namespace Clusters {
36+
namespace WaterHeaterManagement {
37+
38+
constexpr uint16_t kClusterRevision = 1;
39+
40+
CHIP_ERROR Instance::Init()
41+
{
42+
ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this));
43+
VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE);
44+
45+
return CHIP_NO_ERROR;
46+
}
47+
48+
void Instance::Shutdown()
49+
{
50+
InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this);
51+
unregisterAttributeAccessOverride(this);
52+
}
53+
54+
bool Instance::HasFeature(Feature aFeature) const
55+
{
56+
return mFeature.Has(aFeature);
57+
}
58+
59+
// AttributeAccessInterface
60+
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
61+
{
62+
switch (aPath.mAttributeId)
63+
{
64+
case HeaterTypes::Id:
65+
return aEncoder.Encode(mDelegate.GetHeaterTypes());
66+
case HeatDemand::Id:
67+
return aEncoder.Encode(mDelegate.GetHeatDemand());
68+
case TankVolume::Id:
69+
if (!HasFeature(Feature::kEnergyManagement))
70+
{
71+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
72+
}
73+
return aEncoder.Encode(mDelegate.GetTankVolume());
74+
case EstimatedHeatRequired::Id:
75+
if (!HasFeature(Feature::kEnergyManagement))
76+
{
77+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
78+
}
79+
return aEncoder.Encode(mDelegate.GetEstimatedHeatRequired());
80+
case TankPercentage::Id:
81+
if (!HasFeature(Feature::kTankPercent))
82+
{
83+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
84+
}
85+
return aEncoder.Encode(mDelegate.GetTankPercentage());
86+
case BoostState::Id:
87+
return aEncoder.Encode(mDelegate.GetBoostState());
88+
89+
/* FeatureMap - is held locally */
90+
case FeatureMap::Id:
91+
return aEncoder.Encode(mFeature);
92+
case ClusterRevision::Id:
93+
return aEncoder.Encode(kClusterRevision);
94+
}
95+
96+
/* Allow all other unhandled attributes to fall through to Ember */
97+
return CHIP_NO_ERROR;
98+
}
99+
100+
void Instance::InvokeCommand(HandlerContext & handlerContext)
101+
{
102+
using namespace Commands;
103+
104+
switch (handlerContext.mRequestPath.mCommandId)
105+
{
106+
case Boost::Id:
107+
HandleCommand<Boost::DecodableType>(
108+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleBoost(ctx, commandData); });
109+
return;
110+
case CancelBoost::Id:
111+
HandleCommand<CancelBoost::DecodableType>(
112+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCancelBoost(ctx, commandData); });
113+
return;
114+
}
115+
}
116+
117+
void Instance::HandleBoost(HandlerContext & ctx, const Commands::Boost::DecodableType & commandData)
118+
{
119+
uint32_t duration = commandData.duration;
120+
Optional<bool> oneShot = commandData.oneShot;
121+
Optional<bool> emergencyBoost = commandData.emergencyBoost;
122+
Optional<int16_t> temporarySetpoint = commandData.temporarySetpoint;
123+
Optional<Percent> targetPercentage = commandData.targetPercentage;
124+
Optional<Percent> targetReheat = commandData.targetReheat;
125+
126+
// Notify the appliance if the appliance hardware cannot be adjusted, then return Failure
127+
if (HasFeature(WaterHeaterManagement::Feature::kTankPercent))
128+
{
129+
if (targetPercentage.HasValue())
130+
{
131+
if (targetPercentage.Value() > 100)
132+
{
133+
ChipLogError(Zcl, "Bad targetPercentage %u", targetPercentage.Value());
134+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
135+
return;
136+
}
137+
}
138+
139+
if (targetReheat.HasValue())
140+
{
141+
if (targetReheat.Value() > 100)
142+
{
143+
ChipLogError(Zcl, "Bad targetReheat %u", targetReheat.Value());
144+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
145+
return;
146+
}
147+
148+
if (!targetPercentage.HasValue())
149+
{
150+
ChipLogError(Zcl, "targetPercentage must be specified if targetReheat specified");
151+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
152+
return;
153+
}
154+
155+
if (oneShot.HasValue())
156+
{
157+
ChipLogError(Zcl, "Cannot specify targetReheat with targetPercentage and oneShot. oneShot must be excluded");
158+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
159+
return;
160+
}
161+
}
162+
}
163+
else if (targetPercentage.HasValue() || targetReheat.HasValue())
164+
{
165+
ChipLogError(Zcl, "Cannot specify targetPercentage or targetReheat if the feature TankPercent is not supported");
166+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
167+
return;
168+
}
169+
170+
Status status = mDelegate.HandleBoost(duration, oneShot, emergencyBoost, temporarySetpoint, targetPercentage, targetReheat);
171+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
172+
if (status != Status::Success)
173+
{
174+
ChipLogError(Zcl, "WHM: Boost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status));
175+
}
176+
}
177+
178+
void Instance::HandleCancelBoost(HandlerContext & ctx, const Commands::CancelBoost::DecodableType & commandData)
179+
{
180+
Status status = mDelegate.HandleCancelBoost();
181+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
182+
if (status != Status::Success)
183+
{
184+
ChipLogError(Zcl, "WHM: CancelBoost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status));
185+
return;
186+
}
187+
}
188+
189+
} // namespace WaterHeaterManagement
190+
} // namespace Clusters
191+
} // namespace app
192+
} // namespace chip

0 commit comments

Comments
 (0)