296 lines
12 KiB
C++
296 lines
12 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Extension : Gestionnaire Pompe à chaleur + ECS — implémentation
|
|
|
|
#include "heatpumpmanager.h"
|
|
|
|
#include <QLoggingCategory>
|
|
Q_DECLARE_LOGGING_CATEGORY(dcNymeaEnergy)
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// HeatPumpManager
|
|
// ─────────────────────────────────────────────────────────────
|
|
|
|
HeatPumpManager::HeatPumpManager(EnergyManager *energyManager,
|
|
ThingManager *thingManager,
|
|
QObject *parent)
|
|
: QObject(parent),
|
|
m_energyManager(energyManager),
|
|
m_thingManager(thingManager)
|
|
{
|
|
// Détecter les Things déjà présents au démarrage
|
|
for (Thing *thing : m_thingManager->configuredThings()) {
|
|
onThingAdded(thing);
|
|
}
|
|
|
|
// S'abonner aux nouveaux appareils
|
|
connect(m_thingManager, &ThingManager::thingAdded,
|
|
this, &HeatPumpManager::onThingAdded);
|
|
connect(m_thingManager, &ThingManager::thingRemoved,
|
|
this, &HeatPumpManager::onThingRemoved);
|
|
}
|
|
|
|
// ─── Accesseurs ──────────────────────────────────────────────
|
|
|
|
QList<HeatPumpDevice *> HeatPumpManager::heatPumps() const
|
|
{
|
|
return m_heatPumps.values();
|
|
}
|
|
|
|
QList<DomesticHotWaterDevice *> HeatPumpManager::dhwDevices() const
|
|
{
|
|
return m_dhwDevices.values();
|
|
}
|
|
|
|
double HeatPumpManager::totalThermalPower() const
|
|
{
|
|
double total = 0;
|
|
for (const HeatPumpDevice *hp : m_heatPumps)
|
|
total += hp->currentPower();
|
|
for (const DomesticHotWaterDevice *dhw : m_dhwDevices)
|
|
total += dhw->currentPower();
|
|
return total;
|
|
}
|
|
|
|
// ─── Contrôle PAC ────────────────────────────────────────────
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::setPower(const ThingId &thingId, bool on)
|
|
{
|
|
HeatPumpDevice *hp = m_heatPumps.value(thingId);
|
|
if (!hp) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: setPower" << on
|
|
<< "on" << hp->name();
|
|
|
|
Action action(kHPStatePower, thingId);
|
|
action.setParams(ParamList() << Param(kHPStatePower, on));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::setMode(const ThingId &thingId,
|
|
const QString &mode)
|
|
{
|
|
HeatPumpDevice *hp = m_heatPumps.value(thingId);
|
|
if (!hp) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
const QStringList validModes = {"heating", "cooling", "auto", "standby"};
|
|
if (!validModes.contains(mode)) return EnergyManager::EnergyErrorInvalidParameter;
|
|
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: setMode" << mode
|
|
<< "on" << hp->name();
|
|
|
|
Action action(kHPActionSetMode, thingId);
|
|
action.setParams(ParamList() << Param(kHPActionParamMode, mode));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::setTargetTemperature(const ThingId &thingId,
|
|
double temperature)
|
|
{
|
|
HeatPumpDevice *hp = m_heatPumps.value(thingId);
|
|
if (!hp) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
if (temperature < 15 || temperature > 65)
|
|
return EnergyManager::EnergyErrorInvalidParameter;
|
|
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: setTargetTemperature"
|
|
<< temperature << "°C on" << hp->name();
|
|
|
|
Action action(kHPActionSetTargetTemperature, thingId);
|
|
action.setParams(ParamList() << Param(kHPActionParamTargetTemp, temperature));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
// ─── Contrôle ECS ────────────────────────────────────────────
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::setDHWPower(const ThingId &thingId,
|
|
bool on)
|
|
{
|
|
DomesticHotWaterDevice *dhw = m_dhwDevices.value(thingId);
|
|
if (!dhw) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: DHW setPower" << on
|
|
<< "on" << dhw->name();
|
|
|
|
Action action(kDHWStatePower, thingId);
|
|
action.setParams(ParamList() << Param(kDHWStatePower, on));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::setDHWTargetTemperature(const ThingId &thingId,
|
|
double temperature)
|
|
{
|
|
DomesticHotWaterDevice *dhw = m_dhwDevices.value(thingId);
|
|
if (!dhw) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
if (temperature < 40 || temperature > 75)
|
|
return EnergyManager::EnergyErrorInvalidParameter;
|
|
|
|
Action action(kDHWStateTargetTemperature, thingId);
|
|
action.setParams(ParamList() << Param(kDHWStateTargetTemperature, temperature));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
EnergyManager::EnergyError HeatPumpManager::triggerDHWBoost(const ThingId &thingId,
|
|
uint durationMinutes)
|
|
{
|
|
DomesticHotWaterDevice *dhw = m_dhwDevices.value(thingId);
|
|
if (!dhw) return EnergyManager::EnergyErrorThingNotFound;
|
|
|
|
if (durationMinutes < 15 || durationMinutes > 120)
|
|
return EnergyManager::EnergyErrorInvalidParameter;
|
|
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: DHW triggerBoost"
|
|
<< durationMinutes << "min on" << dhw->name();
|
|
|
|
Action action(kDHWActionTriggerBoost, thingId);
|
|
action.setParams(ParamList() << Param(kDHWActionParamDuration, durationMinutes));
|
|
m_thingManager->executeAction(action);
|
|
|
|
return EnergyManager::EnergyErrorNoError;
|
|
}
|
|
|
|
// ─── Slots privés ────────────────────────────────────────────
|
|
|
|
void HeatPumpManager::onThingAdded(Thing *thing)
|
|
{
|
|
if (thing->thingClassId() == kHeatPumpThingClassId) {
|
|
setupHeatPump(thing);
|
|
} else if (thing->thingClassId() == kDomesticHotWaterClassId) {
|
|
setupDHWDevice(thing);
|
|
}
|
|
}
|
|
|
|
void HeatPumpManager::onThingRemoved(const ThingId &thingId)
|
|
{
|
|
if (m_heatPumps.contains(thingId)) {
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: PAC supprimée:" << thingId;
|
|
delete m_heatPumps.take(thingId);
|
|
emit heatPumpRemoved(thingId);
|
|
}
|
|
if (m_dhwDevices.contains(thingId)) {
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: ECS supprimée:" << thingId;
|
|
delete m_dhwDevices.take(thingId);
|
|
emit dhwDeviceRemoved(thingId);
|
|
}
|
|
}
|
|
|
|
void HeatPumpManager::onThingStateChanged(Thing *thing,
|
|
const StateType &stateType,
|
|
const QVariant &value,
|
|
const QVariant & /*minValue*/,
|
|
const QVariant & /*maxValue*/)
|
|
{
|
|
if (m_heatPumps.contains(thing->id())) {
|
|
emit heatPumpStateChanged(thing->id(), stateType.name(), value);
|
|
} else if (m_dhwDevices.contains(thing->id())) {
|
|
emit dhwStateChanged(thing->id(), stateType.name(), value);
|
|
}
|
|
}
|
|
|
|
void HeatPumpManager::setupHeatPump(Thing *thing)
|
|
{
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: Nouvelle PAC:"
|
|
<< thing->name() << thing->id();
|
|
|
|
HeatPumpDevice *hp = new HeatPumpDevice(thing, this);
|
|
m_heatPumps.insert(thing->id(), hp);
|
|
|
|
// Écouter les changements d'état
|
|
connect(thing, &Thing::stateValueChanged,
|
|
this, [this, thing](const StateTypeId &stateTypeId, const QVariant &value) {
|
|
Thing *t = qobject_cast<Thing *>(sender());
|
|
if (t) emit heatPumpStateChanged(t->id(), stateTypeId.toString(), value);
|
|
});
|
|
|
|
emit heatPumpAdded(thing->id());
|
|
}
|
|
|
|
void HeatPumpManager::setupDHWDevice(Thing *thing)
|
|
{
|
|
qCDebug(dcNymeaEnergy()) << "HeatPumpManager: Nouvelle ECS:"
|
|
<< thing->name() << thing->id();
|
|
|
|
DomesticHotWaterDevice *dhw = new DomesticHotWaterDevice(thing, this);
|
|
m_dhwDevices.insert(thing->id(), dhw);
|
|
|
|
connect(thing, &Thing::stateValueChanged,
|
|
this, [this, thing](const StateTypeId &stateTypeId, const QVariant &value) {
|
|
Thing *t = qobject_cast<Thing *>(sender());
|
|
if (t) emit dhwStateChanged(t->id(), stateTypeId.toString(), value);
|
|
});
|
|
|
|
emit dhwDeviceAdded(thing->id());
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// HeatPumpDevice
|
|
// ─────────────────────────────────────────────────────────────
|
|
|
|
HeatPumpDevice::HeatPumpDevice(Thing *thing, QObject *parent)
|
|
: QObject(parent), m_thing(thing)
|
|
{}
|
|
|
|
ThingId HeatPumpDevice::id() const { return m_thing->id(); }
|
|
QString HeatPumpDevice::name() const { return m_thing->name(); }
|
|
Thing *HeatPumpDevice::thing() const { return m_thing; }
|
|
|
|
bool HeatPumpDevice::power() const {
|
|
return m_thing->stateValue(kHPStatePower).toBool();
|
|
}
|
|
QString HeatPumpDevice::mode() const {
|
|
return m_thing->stateValue(kHPStateMode).toString();
|
|
}
|
|
double HeatPumpDevice::targetTemperature() const {
|
|
return m_thing->stateValue(kHPStateTargetTemperature).toDouble();
|
|
}
|
|
double HeatPumpDevice::currentTemperature() const {
|
|
return m_thing->stateValue(kHPStateCurrentTemp).toDouble();
|
|
}
|
|
double HeatPumpDevice::currentPower() const {
|
|
return m_thing->stateValue(kHPStateCurrentPower).toDouble();
|
|
}
|
|
double HeatPumpDevice::cop() const {
|
|
return m_thing->stateValue(kHPStateCop).toDouble();
|
|
}
|
|
bool HeatPumpDevice::defrostActive() const {
|
|
return m_thing->stateValue(kHPStateDefrostActive).toBool();
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// DomesticHotWaterDevice
|
|
// ─────────────────────────────────────────────────────────────
|
|
|
|
DomesticHotWaterDevice::DomesticHotWaterDevice(Thing *thing, QObject *parent)
|
|
: QObject(parent), m_thing(thing)
|
|
{}
|
|
|
|
ThingId DomesticHotWaterDevice::id() const { return m_thing->id(); }
|
|
QString DomesticHotWaterDevice::name() const { return m_thing->name(); }
|
|
Thing *DomesticHotWaterDevice::thing() const { return m_thing; }
|
|
|
|
bool DomesticHotWaterDevice::power() const {
|
|
return m_thing->stateValue(kDHWStatePower).toBool();
|
|
}
|
|
double DomesticHotWaterDevice::targetTemperature() const {
|
|
return m_thing->stateValue(kDHWStateTargetTemperature).toDouble();
|
|
}
|
|
double DomesticHotWaterDevice::currentTemperature() const {
|
|
return m_thing->stateValue(kDHWStateCurrentTemp).toDouble();
|
|
}
|
|
bool DomesticHotWaterDevice::boostMode() const {
|
|
return m_thing->stateValue(kDHWStateBoostMode).toBool();
|
|
}
|
|
double DomesticHotWaterDevice::currentPower() const {
|
|
return m_thing->stateValue(kDHWStateCurrentPower).toDouble();
|
|
}
|