blob: 8865501fcca6fe8d8820781a57c013108309ad48 [file] [log] [blame]
/*
*
* Copyright (c) 2024 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 <WhmInstance.h>
#include <WhmManufacturer.h>
#include <water-heater-mode.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
#include <app/clusters/water-heater-management-server/water-heater-management-server.h>
using namespace chip;
using namespace chip::app::Clusters::WaterHeaterManagement;
using Protocols::InteractionModel::Status;
namespace chip {
namespace app {
namespace Clusters {
namespace WaterHeaterManagement {
CHIP_ERROR WhmManufacturer::Init()
{
WaterHeaterManagementDelegate * dg = GetWhmManufacturer()->GetWhmDelegate();
if (dg == nullptr)
{
ChipLogError(AppServer, "WhmDelegate is not initialized");
return CHIP_ERROR_UNINITIALIZED;
}
dg->SetHeaterTypes(BitMask<WaterHeaterHeatSourceBitmap>(WaterHeaterHeatSourceBitmap::kImmersionElement1));
dg->SetHeatDemand(BitMask<WaterHeaterHeatSourceBitmap>(WaterHeaterHeatSourceBitmap::kImmersionElement1));
dg->SetEstimatedHeatRequired(10000);
return CHIP_NO_ERROR;
}
CHIP_ERROR WhmManufacturer::Shutdown()
{
return CHIP_NO_ERROR;
}
BitMask<WaterHeaterHeatSourceBitmap> WhmManufacturer::DetermineHeatingSources()
{
WaterHeaterManagementDelegate * dg = GetWhmManufacturer()->GetWhmDelegate();
if (dg == nullptr)
{
ChipLogError(AppServer, "WhmDelegate is not initialized");
return BitMask<WaterHeaterHeatSourceBitmap>(0);
}
// A list of valid heaterTypes
uint8_t waterHeaterTypeValues[] = {
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kImmersionElement1),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kImmersionElement2),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kHeatPump),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kBoiler),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kOther),
};
// The corresponding list of valid headerDemands
uint8_t waterHeaterDemandValues[] = {
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kImmersionElement1),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kImmersionElement2),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kHeatPump),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kBoiler),
static_cast<uint8_t>(WaterHeaterHeatSourceBitmap::kOther),
};
// Iterate across the valid waterHeaterTypes seeing which heating sources are available based on heaterTypes.
// Set the corresponding bit in the heaterDemand bitmap.
BitMask<WaterHeaterHeatSourceBitmap> heaterTypes = dg->GetHeaterTypes();
uint8_t heaterDemandMask = 0;
for (uint16_t idx = 0; idx < static_cast<uint16_t>(sizeof(waterHeaterTypeValues) / sizeof(waterHeaterTypeValues[0])); idx++)
{
// Is this heating source being used?
if (heaterTypes.Raw() & waterHeaterTypeValues[idx])
{
heaterDemandMask |= waterHeaterDemandValues[idx];
}
}
return BitMask<WaterHeaterHeatSourceBitmap>(heaterDemandMask);
}
Status WhmManufacturer::TurnHeatingOn(bool emergencyBoost)
{
Status status = Status::Success;
ChipLogProgress(AppServer, "WhmManufacturer::TurnHeatingOn");
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
if (emergencyBoost)
{
// emergencyBoost that the consumer wants the water to be heated as quickly as practicable.
// Thus, cause multiple heat sources to be activated
dg->SetHeatDemand(BitMask<WaterHeaterHeatSourceBitmap>(WaterHeaterHeatSourceBitmap::kImmersionElement1,
WaterHeaterHeatSourceBitmap::kImmersionElement2));
}
else
{
dg->SetHeatDemand(BitMask<WaterHeaterHeatSourceBitmap>(WaterHeaterHeatSourceBitmap::kImmersionElement1));
}
return status;
}
Status WhmManufacturer::TurnHeatingOff()
{
Status status = Status::Success;
ChipLogProgress(AppServer, "WhmManufacturer::TurnHeatingOff");
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
dg->SetHeatDemand(BitMask<WaterHeaterHeatSourceBitmap>(0));
return status;
}
Status WhmManufacturer::BoostCommandStarted(uint32_t duration, Optional<bool> oneShot, Optional<bool> emergencyBoost,
Optional<int16_t> temporarySetpoint, Optional<chip::Percent> targetPercentage,
Optional<chip::Percent> targetReheat)
{
return Status::Success;
}
Status WhmManufacturer::BoostCommandCancelled()
{
return Status::Success;
}
void WhmManufacturer::BoostCommandFinished() {}
WaterHeaterManagementDelegate * GetWhmDelegate()
{
WhmManufacturer * mn = GetWhmManufacturer();
VerifyOrDieWithMsg(mn != nullptr, AppServer, "WhmManufacturer is null");
WaterHeaterManagementDelegate * wg = mn->GetWhmDelegate();
VerifyOrDieWithMsg(wg != nullptr, AppServer, "WhmDelegate is null");
return wg;
}
void SetTestEventTrigger_BasicInstallationTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate installation in a 100L tank full of water at 20C, with a target temperature of 60C, in OFF mode
dg->SetTankVolume(100);
dg->SetTargetWaterTemperature(6000);
dg->SetHeaterTypes(BitMask<WaterHeaterHeatSourceBitmap>(WaterHeaterHeatSourceBitmap::kImmersionElement1));
dg->DrawOffHotWater(100, 2000);
}
void SetTestEventTrigger_BasicInstallationTestEventClear() {}
void SetTestEventTrigger_WaterTemperature20CTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate 100% of the water in the tank being at 20C
dg->SetWaterTemperature(2000);
}
void SetTestEventTrigger_WaterTemperature61CTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate 100% of the water in the tank being at 61C
dg->SetWaterTemperature(6100);
}
void SetTestEventTrigger_WaterTemperature66CTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate 100% of the water in the tank being at 66C
dg->SetWaterTemperature(6600);
}
void SetTestEventTrigger_ManualModeTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate the Water Heater Mode being set to MANUAL
Status status = dg->SetWaterHeaterMode(WaterHeaterMode::kModeManual);
if (status != Status::Success)
{
ChipLogError(Zcl, "SetTestEventTrigger_OffModeTestEvent setting mode -> KModeManual failed 0x%02x", to_underlying(status));
}
}
void SetTestEventTrigger_OffModeTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate the Water Heater Mode being set to OFF
Status status = dg->SetWaterHeaterMode(WaterHeaterMode::kModeOff);
if (status != Status::Success)
{
ChipLogError(Zcl, "SetTestEventTrigger_OffModeTestEvent setting mode -> KModeOff failed 0x%02x", to_underlying(status));
}
}
void SetTestEventTrigger_DrawOffHotWaterTestEvent()
{
WaterHeaterManagementDelegate * dg = GetWhmDelegate();
// Simulate drawing off 25% of the tank volume of hot water, replaced with water at 20C
dg->DrawOffHotWater(25, 2000);
}
} // namespace WaterHeaterManagement
} // namespace Clusters
} // namespace app
} // namespace chip
using namespace chip::app::Clusters::WaterHeaterManagement;
bool HandleWaterHeaterManagementTestEventTrigger(uint64_t eventTrigger)
{
WaterHeaterManagementTrigger trigger = static_cast<WaterHeaterManagementTrigger>(eventTrigger);
switch (trigger)
{
case WaterHeaterManagementTrigger::kBasicInstallationTestEvent:
ChipLogProgress(Support,
"[Whm::kBasicInstallationTestEvent] => Simulate installation in a 100L tank full of water at 20C, with a "
"target temperature of 60C, in OFF mode");
SetTestEventTrigger_BasicInstallationTestEvent();
break;
case WaterHeaterManagementTrigger::kBasicInstallationTestEventClear:
ChipLogProgress(Support, "[Whm::kBasicInstallationTestEventClear] => End simulation of installation");
SetTestEventTrigger_BasicInstallationTestEventClear();
break;
case WaterHeaterManagementTrigger::kWaterTemperature20CTestEvent:
ChipLogProgress(Support, "[Whm::kWaterTemperature20CTestEvent] => Simulate 100%% of the water in the tank being at 20C");
SetTestEventTrigger_WaterTemperature20CTestEvent();
break;
case WaterHeaterManagementTrigger::kWaterTemperature61CTestEvent:
ChipLogProgress(Support, "[Whm::kWaterTemperature61CTestEvent] => Simulate 100%% of the water in the tank being at 61C");
SetTestEventTrigger_WaterTemperature61CTestEvent();
break;
case WaterHeaterManagementTrigger::kWaterTemperature66CTestEvent:
ChipLogProgress(Support, "[Whm::kWaterTemperature66CTestEvent] => Simulate 100%% of the water in the tank being at 66C");
SetTestEventTrigger_WaterTemperature66CTestEvent();
break;
case WaterHeaterManagementTrigger::kManualModeTestEvent:
ChipLogProgress(Support, "[Whm::kManualModeTestEvent] => Simulate the Water Heater Mode being set to MANUAL");
SetTestEventTrigger_ManualModeTestEvent();
break;
case WaterHeaterManagementTrigger::kOffModeTestEvent:
ChipLogProgress(Support, "[Whm::kOffModeTestEvent] => Simulate the Water Heater Mode being set to OFF");
SetTestEventTrigger_OffModeTestEvent();
break;
case WaterHeaterManagementTrigger::kDrawOffHotWaterTestEvent:
ChipLogProgress(Support,
"[Whm::kDrawOffHotWaterTestEvent] => Simulate drawing off 25%% of the tank volume of hot water, replaced "
"with water at 20C");
SetTestEventTrigger_DrawOffHotWaterTestEvent();
break;
default:
return false;
}
return true;
}