diff --git a/sunspec/integrationpluginsunspec.cpp b/sunspec/integrationpluginsunspec.cpp index 83d5148..ec79e86 100644 --- a/sunspec/integrationpluginsunspec.cpp +++ b/sunspec/integrationpluginsunspec.cpp @@ -34,9 +34,10 @@ #include "solaredgebattery.h" #include +#include #include -#include +// Inverters #include #include #include @@ -44,6 +45,18 @@ #include #include +// Meters +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include IntegrationPluginSunSpec::IntegrationPluginSunSpec() @@ -277,6 +290,10 @@ void IntegrationPluginSunSpec::postSetupThing(Thing *thing) sunSpecThing->readBlockData(); } else if (m_sunSpecInverters.contains(thing)) { m_sunSpecInverters.value(thing)->readBlockData(); + } else if (m_sunSpecMeters.contains(thing)) { + m_sunSpecMeters.value(thing)->readBlockData(); + } else if (m_sunSpecStorages.contains(thing)) { + m_sunSpecStorages.value(thing)->readBlockData(); } else { Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8()); } @@ -298,6 +315,10 @@ void IntegrationPluginSunSpec::thingRemoved(Thing *thing) } else if (m_sunSpecInverters.contains(thing)) { m_sunSpecInverters.remove(thing); + } else if (m_sunSpecMeters.contains(thing)) { + m_sunSpecMeters.remove(thing); + } else if (m_sunSpecStorages.contains(thing)) { + m_sunSpecStorages.remove(thing); } else { Q_ASSERT_X(false, "thingRemoved", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8()); } @@ -315,20 +336,88 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info) Action action = info->action(); if (thing->thingClassId() == sunspecStorageThingClassId) { - SunSpecStorage *sunSpecStorage = qobject_cast(m_sunSpecThings.value(thing)); - if (!sunSpecStorage) { - qWarning(dcSunSpec()) << "Could not find sunspec instance for thing"; + SunSpecStorageModel *storage = qobject_cast(m_sunSpecStorages.value(thing)); + if (!storage) { + qWarning(dcSunSpec()) << "Could not find sunspec model instance for thing" << thing; info->finish(Thing::ThingErrorHardwareNotAvailable); return; } - if (!sunSpecStorage->model()->connection()->connected()) { + if (!thing->stateValue(sunspecStorageConnectedStateTypeId).toBool()) { qWarning(dcSunSpec()) << "Could not execute action for" << thing << "because the SunSpec connection is not connected."; info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("The SunSpec connection is not connected.")); return; } - sunSpecStorage->executeAction(info); + if (action.actionTypeId() == sunspecStorageGridChargingActionTypeId) { + bool gridCharging = action.param(sunspecStorageGridChargingActionGridChargingParamTypeId).value().toBool(); + QModbusReply *reply = storage->setChaGriSet(gridCharging ? SunSpecStorageModel::ChagrisetGrid : SunSpecStorageModel::ChagrisetPv); + if (!reply) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + + connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); + connect(reply, &QModbusReply::finished, info, [info, reply]{ + if (reply->error() != QModbusDevice::NoError) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + info->finish(Thing::ThingErrorNoError); + }); + } else if (action.actionTypeId() == sunspecStorageEnableChargingActionTypeId || action.actionTypeId() == sunspecStorageEnableDischargingActionTypeId) { + SunSpecStorageModel::Storctl_modFlags controlModeFlags; + if (action.param(sunspecStorageEnableChargingActionEnableChargingParamTypeId).value().toBool()) + controlModeFlags.setFlag(SunSpecStorageModel::Storctl_modCharge); + + if (thing->stateValue(sunspecStorageEnableDischargingStateTypeId).toBool()) + controlModeFlags.setFlag(SunSpecStorageModel::Storctl_modDiScharge); + + QModbusReply *reply = storage->setStorCtlMod(controlModeFlags); + if (!reply) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); + connect(reply, &QModbusReply::finished, info, [info, reply]{ + if (reply->error() != QModbusDevice::NoError) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + info->finish(Thing::ThingErrorNoError); + }); + } else if (action.actionTypeId() == sunspecStorageChargingRateActionTypeId) { + QModbusReply *reply = storage->setInWRte(action.param(sunspecStorageChargingRateActionChargingRateParamTypeId).value().toInt()); + if (!reply) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); + connect(reply, &QModbusReply::finished, info, [info, reply]{ + if (reply->error() != QModbusDevice::NoError) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + info->finish(Thing::ThingErrorNoError); + }); + } else if (action.actionTypeId() == sunspecStorageDischargingRateActionTypeId) { + QModbusReply *reply = storage->setOutWRte(action.param(sunspecStorageDischargingRateActionDischargingRateParamTypeId).value().toInt()); + if (!reply) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); + connect(reply, &QModbusReply::finished, info, [info, reply]{ + if (reply->error() != QModbusDevice::NoError) { + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + info->finish(Thing::ThingErrorNoError); + }); + } else { + Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8()); + } + } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(info->thing()->thingClassId().toString()).toUtf8()); } @@ -546,10 +635,8 @@ void IntegrationPluginSunSpec::setupMeter(ThingSetupInfo *info) // Get the model from the connection foreach (SunSpecModel *model, connection->models()) { if (model->modelId() == modelId && model->modbusStartRegister() == modbusStartRegister) { -// m_sunSpecInverters.insert(thing, model); -// connect(model, &SunSpecModel::blockUpdated, this, &IntegrationPluginSunSpec::onInverterBlockUpdated); - SunSpecMeter *meter = new SunSpecMeter(thing, model, this); - m_sunSpecThings.insert(thing, meter); + m_sunSpecMeters.insert(thing, model); + connect(model, &SunSpecModel::blockUpdated, this, &IntegrationPluginSunSpec::onMeterBlockUpdated); info->finish(Thing::ThingErrorNoError); return; } @@ -570,8 +657,8 @@ void IntegrationPluginSunSpec::setupStorage(ThingSetupInfo *info) // Get the model from the connection foreach (SunSpecModel *model, connection->models()) { if (model->modelId() == modelId && model->modbusStartRegister() == modbusStartRegister) { - SunSpecStorage *storage = new SunSpecStorage(thing, model, this); - m_sunSpecThings.insert(thing, storage); + connect(model, &SunSpecModel::blockUpdated, this, &IntegrationPluginSunSpec::onStorageBlockUpdated); + m_sunSpecStorages.insert(thing, model); info->finish(Thing::ThingErrorNoError); return; } @@ -836,6 +923,14 @@ void IntegrationPluginSunSpec::onRefreshTimer() foreach (SunSpecModel *model, m_sunSpecInverters.values()) { model->readBlockData(); } + + foreach (SunSpecModel *model, m_sunSpecMeters.values()) { + model->readBlockData(); + } + + foreach (SunSpecModel *model, m_sunSpecStorages.values()) { + model->readBlockData(); + } } void IntegrationPluginSunSpec::onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value) @@ -990,10 +1085,240 @@ void IntegrationPluginSunSpec::onInverterBlockUpdated() void IntegrationPluginSunSpec::onMeterBlockUpdated() { + SunSpecModel *model = qobject_cast(sender()); + Thing *thing = m_sunSpecMeters.key(model); + if (!thing) return; + switch (model->modelId()) { + case SunSpecModelFactory::ModelIdMeterSinglePhase: { + SunSpecMeterSinglePhaseModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecSinglePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecSinglePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecSinglePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecSinglePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecSinglePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecSinglePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterSinglePhaseFloat: { + SunSpecMeterSinglePhaseFloatModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecSinglePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecSinglePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecSinglePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecSinglePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecSinglePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecSinglePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseAbn: { + SunSpecMeterSplitSinglePhaseAbnModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecSplitPhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterTotalCurrentStateTypeId, meter->amps()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecSplitPhaseMeterLnACVoltageStateTypeId, meter->voltageLn()); + thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecSplitPhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecSplitPhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseFloat: { + SunSpecMeterSplitSinglePhaseFloatModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecSplitPhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecSplitPhaseMeterTotalCurrentStateTypeId, meter->amps()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecSplitPhaseMeterLnACVoltageStateTypeId, meter->voltageLn()); + thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecSplitPhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecSplitPhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterThreePhase: { + SunSpecMeterThreePhaseModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); + thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdDeltaConnectThreePhaseAbcMeter: { + SunSpecDeltaConnectThreePhaseAbcMeterModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); + thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterThreePhaseWyeConnect: { + SunSpecMeterThreePhaseWyeConnectModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); + thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + case SunSpecModelFactory::ModelIdMeterThreePhaseDeltaConnect: { + SunSpecMeterThreePhaseDeltaConnectModel *meter = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << meter; + thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); + thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); + thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); + thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); + thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, model->commonModelInfo().versionString); + break; + } + default: + qCWarning(dcSunSpec()) << "Received block data from unhandled model" << model; + break; + } } void IntegrationPluginSunSpec::onStorageBlockUpdated() { + SunSpecModel *model = qobject_cast(sender()); + Thing *thing = m_sunSpecStorages.key(model); + if (!thing) return; + SunSpecStorageModel *storage = qobject_cast(model); + qCDebug(dcSunSpec()) << thing->name() << "block data updated" << storage; + + thing->setStateValue(sunspecStorageConnectedStateTypeId, true); + thing->setStateValue(sunspecStorageVersionStateTypeId, model->commonModelInfo().versionString); + + thing->setStateValue(sunspecStorageBatteryCriticalStateTypeId, storage->chaState() < 5); + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, qRound(storage->chaState())); + thing->setStateValue(sunspecStorageGridChargingStateTypeId, storage->chaGriSet() == SunSpecStorageModel::ChagrisetGrid); + thing->setStateValue(sunspecStorageEnableChargingStateTypeId, storage->storCtlMod().testFlag(SunSpecStorageModel::Storctl_modCharge)); + thing->setStateValue(sunspecStorageChargingRateStateTypeId, storage->wChaGra()); + thing->setStateValue(sunspecStorageDischargingRateStateTypeId, storage->wDisChaGra()); + + switch (storage->chaSt()) { + case SunSpecStorageModel::ChastOff: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Off"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); + break; + case SunSpecStorageModel::ChastEmpty: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Empty"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); + break; + case SunSpecStorageModel::ChastDischarging: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Discharging"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "discharging"); + break; + case SunSpecStorageModel::ChastCharging: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Charging"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "charging"); + break; + case SunSpecStorageModel::ChastFull: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Full"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); + break; + case SunSpecStorageModel::ChastHolding: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Holding"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); + break; + case SunSpecStorageModel::ChastTesting: + thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Testing"); + thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); + break; + } } diff --git a/sunspec/integrationpluginsunspec.h b/sunspec/integrationpluginsunspec.h index c6dfe68..2e845c6 100644 --- a/sunspec/integrationpluginsunspec.h +++ b/sunspec/integrationpluginsunspec.h @@ -37,8 +37,7 @@ #include #include -#include "sunspecstorage.h" -#include "sunspecmeter.h" +#include "sunspecthing.h" #include @@ -82,6 +81,8 @@ private: QHash m_sunSpecThings; QHash m_sunSpecInverters; + QHash m_sunSpecMeters; + QHash m_sunSpecStorages; bool sunspecThingAlreadyAdded(uint modelId, uint modbusAddress, const ThingId &parentId); void processDiscoveryResult(Thing *thing, SunSpecConnection *connection); diff --git a/sunspec/sunspec.pro b/sunspec/sunspec.pro index 7fd490d..3e52751 100644 --- a/sunspec/sunspec.pro +++ b/sunspec/sunspec.pro @@ -4,13 +4,9 @@ include(../sunspec.pri) SOURCES += \ integrationpluginsunspec.cpp \ solaredgebattery.cpp \ - sunspecmeter.cpp \ - sunspecstorage.cpp \ sunspecthing.cpp HEADERS += \ integrationpluginsunspec.h \ solaredgebattery.h \ - sunspecmeter.h \ - sunspecstorage.h \ sunspecthing.h diff --git a/sunspec/sunspecmeter.cpp b/sunspec/sunspecmeter.cpp deleted file mode 100644 index a549440..0000000 --- a/sunspec/sunspecmeter.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2021, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU Lesser General Public License as published by the Free -* Software Foundation; version 3. This project is distributed in the hope that -* it will be useful, but WITHOUT ANY WARRANTY; without even the implied -* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "sunspecmeter.h" -#include "extern-plugininfo.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -SunSpecMeter::SunSpecMeter(Thing *thing, SunSpecModel *model, QObject *parent) : - SunSpecThing(thing, model, parent) -{ - connect(m_model, &SunSpecModel::blockUpdated, this, &SunSpecMeter::onBlockDataUpdated); -} - -void SunSpecMeter::readBlockData() -{ - m_model->readBlockData(); -} - -void SunSpecMeter::onBlockDataUpdated() -{ - switch (m_model->modelId()) { - case SunSpecModelFactory::ModelIdMeterSinglePhase: { - SunSpecMeterSinglePhaseModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecSinglePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecSinglePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecSinglePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecSinglePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecSinglePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecSinglePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterSinglePhaseFloat: { - SunSpecMeterSinglePhaseFloatModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecSinglePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecSinglePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecSinglePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecSinglePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecSinglePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecSinglePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecSinglePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseAbn: { - SunSpecMeterSplitSinglePhaseAbnModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecSplitPhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalCurrentStateTypeId, meter->amps()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecSplitPhaseMeterLnACVoltageStateTypeId, meter->voltageLn()); - m_thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecSplitPhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecSplitPhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterSplitSinglePhaseFloat: { - SunSpecMeterSplitSinglePhaseFloatModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecSplitPhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecSplitPhaseMeterTotalCurrentStateTypeId, meter->amps()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecSplitPhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecSplitPhaseMeterLnACVoltageStateTypeId, meter->voltageLn()); - m_thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecSplitPhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecSplitPhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecSplitPhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterThreePhase: { - SunSpecMeterThreePhaseModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); - m_thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdDeltaConnectThreePhaseAbcMeter: { - SunSpecDeltaConnectThreePhaseAbcMeterModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); - m_thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterThreePhaseWyeConnect: { - SunSpecMeterThreePhaseWyeConnectModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); - m_thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - case SunSpecModelFactory::ModelIdMeterThreePhaseDeltaConnect: { - SunSpecMeterThreePhaseDeltaConnectModel *meter = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << meter; - m_thing->setStateValue(sunspecThreePhaseMeterConnectedStateTypeId, true); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyProducedStateTypeId, meter->totalWattHoursExported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterTotalEnergyConsumedStateTypeId, meter->totalWattHoursImported() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerStateTypeId, meter->watts()); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseAStateTypeId, meter->totalWattHoursImportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseBStateTypeId, meter->totalWattHoursImportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyConsumedPhaseCStateTypeId, meter->totalWattHoursImportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseAStateTypeId, meter->totalWattHoursExportedPhaseA() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseBStateTypeId, meter->totalWattHoursExportedPhaseB() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterEnergyProducedPhaseCStateTypeId, meter->totalWattHoursExportedPhaseC() / 1000.0); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseAStateTypeId, meter->wattsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseBStateTypeId, meter->wattsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPowerPhaseCStateTypeId, meter->wattsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseAStateTypeId, meter->ampsPhaseA()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseBStateTypeId, meter->ampsPhaseB()); - m_thing->setStateValue(sunspecThreePhaseMeterCurrentPhaseCStateTypeId, meter->ampsPhaseC()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseAStateTypeId, meter->phaseVoltageAn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageBn()); - m_thing->setStateValue(sunspecThreePhaseMeterVoltagePhaseBStateTypeId, meter->phaseVoltageCn()); - m_thing->setStateValue(sunspecThreePhaseMeterFrequencyStateTypeId, meter->hz()); - m_thing->setStateValue(sunspecThreePhaseMeterVersionStateTypeId, m_model->commonModelInfo().versionString); - break; - } - default: - qCWarning(dcSunSpec()) << "Received block data from unhandled model" << m_model; - break; - } -} diff --git a/sunspec/sunspecmeter.h b/sunspec/sunspecmeter.h deleted file mode 100644 index a5abb72..0000000 --- a/sunspec/sunspecmeter.h +++ /dev/null @@ -1,53 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2021, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU Lesser General Public License as published by the Free -* Software Foundation; version 3. This project is distributed in the hope that -* it will be useful, but WITHOUT ANY WARRANTY; without even the implied -* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef SUNSPECMETER_H -#define SUNSPECMETER_H - -#include - -#include "sunspecthing.h" - -class SunSpecMeter : public SunSpecThing -{ - Q_OBJECT -public: - explicit SunSpecMeter(Thing *thing, SunSpecModel *model, QObject *parent = nullptr); - ~SunSpecMeter() override = default; - - void readBlockData() override; - -private slots: - void onBlockDataUpdated() override; - - -}; - -#endif // SUNSPECMETER_H diff --git a/sunspec/sunspecstorage.cpp b/sunspec/sunspecstorage.cpp deleted file mode 100644 index 6261427..0000000 --- a/sunspec/sunspecstorage.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2021, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU Lesser General Public License as published by the Free -* Software Foundation; version 3. This project is distributed in the hope that -* it will be useful, but WITHOUT ANY WARRANTY; without even the implied -* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "sunspecstorage.h" -#include "extern-plugininfo.h" - -#include - -SunSpecStorage::SunSpecStorage(Thing *thing, SunSpecModel *model, QObject *parent) : - SunSpecThing(thing, model, parent) -{ - -} - -void SunSpecStorage::readBlockData() -{ - m_model->readBlockData(); -} - -void SunSpecStorage::executeAction(ThingActionInfo *info) -{ - Thing *thing = info->thing(); - Action action = info->action(); - SunSpecStorageModel *storage = qobject_cast(m_model); - - if (action.actionTypeId() == sunspecStorageGridChargingActionTypeId) { - bool gridCharging = action.param(sunspecStorageGridChargingActionGridChargingParamTypeId).value().toBool(); - QModbusReply *reply = storage->setChaGriSet(gridCharging ? SunSpecStorageModel::ChagrisetGrid : SunSpecStorageModel::ChagrisetPv); - if (!reply) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - - connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); - connect(reply, &QModbusReply::finished, info, [info, reply]{ - if (reply->error() != QModbusDevice::NoError) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - info->finish(Thing::ThingErrorNoError); - }); - } else if (action.actionTypeId() == sunspecStorageEnableChargingActionTypeId || action.actionTypeId() == sunspecStorageEnableDischargingActionTypeId) { - SunSpecStorageModel::Storctl_modFlags controlModeFlags; - if (action.param(sunspecStorageEnableChargingActionEnableChargingParamTypeId).value().toBool()) - controlModeFlags.setFlag(SunSpecStorageModel::Storctl_modCharge); - - if (thing->stateValue(sunspecStorageEnableDischargingStateTypeId).toBool()) - controlModeFlags.setFlag(SunSpecStorageModel::Storctl_modDiScharge); - - QModbusReply *reply = storage->setStorCtlMod(controlModeFlags); - if (!reply) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); - connect(reply, &QModbusReply::finished, info, [info, reply]{ - if (reply->error() != QModbusDevice::NoError) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - info->finish(Thing::ThingErrorNoError); - }); - } else if (action.actionTypeId() == sunspecStorageChargingRateActionTypeId) { - QModbusReply *reply = storage->setInWRte(action.param(sunspecStorageChargingRateActionChargingRateParamTypeId).value().toInt()); - if (!reply) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); - connect(reply, &QModbusReply::finished, info, [info, reply]{ - if (reply->error() != QModbusDevice::NoError) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - info->finish(Thing::ThingErrorNoError); - }); - } else if (action.actionTypeId() == sunspecStorageDischargingRateActionTypeId) { - QModbusReply *reply = storage->setOutWRte(action.param(sunspecStorageDischargingRateActionDischargingRateParamTypeId).value().toInt()); - if (!reply) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater); - connect(reply, &QModbusReply::finished, info, [info, reply]{ - if (reply->error() != QModbusDevice::NoError) { - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - info->finish(Thing::ThingErrorNoError); - }); - } else { - Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8()); - } -} - -void SunSpecStorage::onBlockDataUpdated() -{ - SunSpecStorageModel *storage = qobject_cast(m_model); - qCDebug(dcSunSpec()) << m_thing->name() << "block data updated" << storage; - - m_thing->setStateValue(sunspecStorageConnectedStateTypeId, true); - m_thing->setStateValue(sunspecStorageVersionStateTypeId, m_model->commonModelInfo().versionString); - - m_thing->setStateValue(sunspecStorageBatteryCriticalStateTypeId, storage->chaState() < 5); - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, qRound(storage->chaState())); - m_thing->setStateValue(sunspecStorageGridChargingStateTypeId, storage->chaGriSet() == SunSpecStorageModel::ChagrisetGrid); - m_thing->setStateValue(sunspecStorageEnableChargingStateTypeId, storage->storCtlMod().testFlag(SunSpecStorageModel::Storctl_modCharge)); - m_thing->setStateValue(sunspecStorageChargingRateStateTypeId, storage->wChaGra()); - m_thing->setStateValue(sunspecStorageDischargingRateStateTypeId, storage->wDisChaGra()); - - switch (storage->chaSt()) { - case SunSpecStorageModel::ChastOff: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Off"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); - break; - case SunSpecStorageModel::ChastEmpty: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Empty"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); - break; - case SunSpecStorageModel::ChastDischarging: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Discharging"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "discharging"); - break; - case SunSpecStorageModel::ChastCharging: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Charging"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "charging"); - break; - case SunSpecStorageModel::ChastFull: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Full"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); - break; - case SunSpecStorageModel::ChastHolding: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Holding"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); - break; - case SunSpecStorageModel::ChastTesting: - m_thing->setStateValue(sunspecStorageBatteryLevelStateTypeId, "Testing"); - m_thing->setStateValue(sunspecStorageChargingStateStateTypeId, "idle"); - break; - } - -} diff --git a/sunspec/sunspecstorage.h b/sunspec/sunspecstorage.h deleted file mode 100644 index c0b42a8..0000000 --- a/sunspec/sunspecstorage.h +++ /dev/null @@ -1,56 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2021, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU Lesser General Public License as published by the Free -* Software Foundation; version 3. This project is distributed in the hope that -* it will be useful, but WITHOUT ANY WARRANTY; without even the implied -* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef SUNSPECSTORAGE_H -#define SUNSPECSTORAGE_H - -#include - -#include "sunspecthing.h" - -#include - -class SunSpecStorage : public SunSpecThing -{ - Q_OBJECT -public: - explicit SunSpecStorage(Thing *thing, SunSpecModel *model, QObject *parent = nullptr); - ~SunSpecStorage() override = default; - - void readBlockData() override; - - void executeAction(ThingActionInfo *info) override; - -private slots: - void onBlockDataUpdated() override; - -}; - -#endif // SUNSPECSTORAGE_H