From 15967809168f5ede063fca9d5e69d50c2c94b245 Mon Sep 17 00:00:00 2001 From: Boernsman Date: Thu, 4 Feb 2021 14:02:11 +0100 Subject: [PATCH] fixed storage actions --- sunspec/integrationpluginsunspec.cpp | 25 +++------------ sunspec/sunspec.cpp | 9 +++++- sunspec/sunspec.h | 4 ++- sunspec/sunspecinverter.cpp | 22 ++++++------- sunspec/sunspecmeter.cpp | 32 +++++++++---------- sunspec/sunspecstorage.cpp | 48 +++++++++++++++++----------- sunspec/sunspecstorage.h | 14 ++++++-- 7 files changed, 82 insertions(+), 72 deletions(-) diff --git a/sunspec/integrationpluginsunspec.cpp b/sunspec/integrationpluginsunspec.cpp index 9ac48e8..c6a95ed 100644 --- a/sunspec/integrationpluginsunspec.cpp +++ b/sunspec/integrationpluginsunspec.cpp @@ -284,24 +284,7 @@ void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info) Thing *thing = info->thing(); Action action = info->action(); - if (thing->thingClassId() == sunspecSinglePhaseInverterThingClassId || - thing->thingClassId() == sunspecSplitPhaseInverterThingClassId || - thing->thingClassId() == sunspecThreePhaseInverterThingClassId) { - - SunSpecInverter *sunSpecInverter = m_sunSpecInverters.value(thing); - if (!sunSpecInverter) { - qWarning(dcSunSpec()) << "Could not find SunSpec inverter for thing" << thing->name(); - info->finish(Thing::ThingErrorHardwareNotAvailable); - return; - } - info->finish(Thing::ThingErrorActionTypeNotFound); - - } else if (thing->thingClassId() == sunspecSinglePhaseMeterThingClassId || - thing->thingClassId() == sunspecSplitPhaseMeterThingClassId || - thing->thingClassId() == sunspecThreePhaseMeterThingClassId) { - info->finish(Thing::ThingErrorActionTypeNotFound); - - } else if (thing->thingClassId() == sunspecStorageThingClassId) { + if (thing->thingClassId() == sunspecStorageThingClassId) { SunSpecStorage *sunSpecStorage = m_sunSpecStorages.value(thing); if (!sunSpecStorage) { qWarning(dcSunSpec()) << "Could not find sunspec instance for thing"; @@ -481,7 +464,7 @@ void IntegrationPluginSunSpec::onPluginConfigurationChanged(const ParamTypeId &p m_refreshTimer->startTimer(refreshTime); } } else if (paramTypeId == sunSpecPluginNumberOfRetriesParamTypeId) { - qCDebug(dcSunSpec()) << "Updating number of retires" << value.toUInt(); + qCDebug(dcSunSpec()) << "Updating number of retries" << value.toUInt(); Q_FOREACH(SunSpec *connection, m_sunSpecConnections) { connection->setNumberOfRetries(value.toUInt()); } @@ -592,7 +575,7 @@ void IntegrationPluginSunSpec::onFoundSunSpecModel(SunSpec::ModelId modelId, int emit autoThingsAppeared({descriptor}); } break; default: - qCDebug(dcSunSpec()) << "Block Id not handled"; + qCDebug(dcSunSpec()) << "Model Id not handled"; } } @@ -823,7 +806,7 @@ void IntegrationPluginSunSpec::onMeterDataReceived(const SunSpecMeter::MeterData qCDebug(dcSunSpec()) << " - Voltage LL" << meterData.voltageLL << "[V]"; qCDebug(dcSunSpec()) << " - Phase voltage AB" << meterData.phaseVoltageAB << "[V]"; qCDebug(dcSunSpec()) << " - Phase voltage BC" << meterData.phaseVoltageBC << "[V]"; - qCDebug(dcSunSpec()) << " - Phase voltage CA" << meterData.phaseVoltageCA<< "[V]"; + qCDebug(dcSunSpec()) << " - Phase voltage CA" << meterData.phaseVoltageCA << "[V]"; qCDebug(dcSunSpec()) << " - Frequency" << meterData.frequency << "[Hz]"; qCDebug(dcSunSpec()) << " - Total real power" << meterData.totalRealPower << "[W]"; qCDebug(dcSunSpec()) << " - Total real energy exported" << meterData.totalRealEnergyExported<< "[kWH]"; diff --git a/sunspec/sunspec.cpp b/sunspec/sunspec.cpp index 5aa4794..262cf5f 100644 --- a/sunspec/sunspec.cpp +++ b/sunspec/sunspec.cpp @@ -354,13 +354,20 @@ QByteArray SunSpec::convertModbusRegisters(const QVector &modbusData, i return bytes; } -float SunSpec::convertValueWithSSF(quint32 rawValue, quint16 sunssf) +float SunSpec::convertToFloatWithSSF(quint32 rawValue, quint16 sunssf) { float value; value = rawValue * pow(10, static_cast(sunssf)); return value; } +quint32 SunSpec::convertFromFloatWithSSF(float value, quint16 sunssf) +{ + quint32 rawValue; + rawValue = value / pow(10, static_cast(sunssf)); + return rawValue; +} + float SunSpec::convertFloatValues(quint16 rawValue0, quint16 rawValue1) { suns_modbus_v32_t value; diff --git a/sunspec/sunspec.h b/sunspec/sunspec.h index 971b919..45f58b4 100644 --- a/sunspec/sunspec.h +++ b/sunspec/sunspec.h @@ -190,7 +190,9 @@ public: void readModelHeader(uint modbusAddress); void readModelDataBlock(uint modbusAddress, uint modelLength); //modbusAddress = model start address, model length is without header - float convertValueWithSSF(quint32 rawValue, quint16 sunssf); + float convertToFloatWithSSF(quint32 rawValue, quint16 sunssf); + quint32 convertFromFloatWithSSF(float value, quint16 sunssf); + float convertFloatValues(quint16 rawValue0, quint16 rawValue1); QByteArray convertModbusRegister(const uint16_t &modbusData); QBitArray convertModbusRegisterBits(const uint16_t &modbusData); diff --git a/sunspec/sunspecinverter.cpp b/sunspec/sunspecinverter.cpp index 0f1dbb8..de61418 100644 --- a/sunspec/sunspecinverter.cpp +++ b/sunspec/sunspecinverter.cpp @@ -120,23 +120,23 @@ void SunSpecInverter::onModelDataBlockReceived(SunSpec::ModelId modelId, uint le case SunSpec::ModelIdInverterSinglePhase: case SunSpec::ModelIdInverterSplitPhase: case SunSpec::ModelIdInverterThreePhase: { - inverterData.acCurrent= m_connection->convertValueWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]); - inverterData.acPower = m_connection->convertValueWithSSF(data[Model10X::Model10XACPower], data[Model10X::Model10XWattScaleFactor]); - inverterData.lineFrequency = m_connection->convertValueWithSSF(data[Model10X::Model10XLineFrequency], data[Model10X::Model10XHerzScaleFactor]); + inverterData.acCurrent= m_connection->convertToFloatWithSSF(data[Model10X::Model10XAcCurrent], data[Model10X::Model10XAmpereScaleFactor]); + inverterData.acPower = m_connection->convertToFloatWithSSF(data[Model10X::Model10XACPower], data[Model10X::Model10XWattScaleFactor]); + inverterData.lineFrequency = m_connection->convertToFloatWithSSF(data[Model10X::Model10XLineFrequency], data[Model10X::Model10XHerzScaleFactor]); quint16 ampereScaleFactor = data[Model10X::Model10XAmpereScaleFactor]; - inverterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseACurrent], ampereScaleFactor); - inverterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseBCurrent], ampereScaleFactor); - inverterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseCCurrent], ampereScaleFactor); + inverterData.phaseACurrent = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseACurrent], ampereScaleFactor); + inverterData.phaseBCurrent = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseBCurrent], ampereScaleFactor); + inverterData.phaseCCurrent = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseCCurrent], ampereScaleFactor); quint16 voltageScaleFactor = data[Model10X::Model10XVoltageScaleFactor]; - inverterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageAN], voltageScaleFactor); - inverterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageBN], voltageScaleFactor); - inverterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model10X::Model10XPhaseVoltageCN], voltageScaleFactor); + inverterData.phaseVoltageAN = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseVoltageAN], voltageScaleFactor); + inverterData.phaseVoltageBN = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseVoltageBN], voltageScaleFactor); + inverterData.phaseVoltageCN = m_connection->convertToFloatWithSSF(data[Model10X::Model10XPhaseVoltageCN], voltageScaleFactor); quint32 acEnergy = ((static_cast(data.value(Model10X::Model10XAcEnergy))<<16)|static_cast(data.value(Model10X::Model10XAcEnergy+1))); - inverterData.acEnergy = m_connection->convertValueWithSSF(acEnergy, data[Model10X::Model10XWattHoursScaleFactor]); + inverterData.acEnergy = m_connection->convertToFloatWithSSF(acEnergy, data[Model10X::Model10XWattHoursScaleFactor]); - inverterData.cabinetTemperature = m_connection->convertValueWithSSF(data[Model10X::Model10XCabinetTemperature], data[Model10X::Model10XTemperatureScaleFactor]); + inverterData.cabinetTemperature = m_connection->convertToFloatWithSSF(data[Model10X::Model10XCabinetTemperature], data[Model10X::Model10XTemperatureScaleFactor]); inverterData.event1 = bitfieldToSunSpecEvent1(data[Model10X::Model10XEvent1], data[Model10X::Model10XEvent1+1]); inverterData.operatingState = SunSpec::SunSpecOperatingState(data[Model10X::Model10XOperatingState]); emit inverterDataReceived(inverterData); diff --git a/sunspec/sunspecmeter.cpp b/sunspec/sunspecmeter.cpp index 093c81b..a9bb23e 100644 --- a/sunspec/sunspecmeter.cpp +++ b/sunspec/sunspecmeter.cpp @@ -98,24 +98,24 @@ void SunSpecMeter::onModelDataBlockReceived(SunSpec::ModelId modelId, uint lengt MeterData meterData; quint16 currentScaleFactor = data[Model20XCurrentScaleFactor]; - meterData.totalAcCurrent = m_connection->convertValueWithSSF(data[Model20XTotalAcCurrent], currentScaleFactor); - meterData.phaseACurrent = m_connection->convertValueWithSSF(data[Model20XPhaseACurrent], currentScaleFactor); - meterData.phaseBCurrent = m_connection->convertValueWithSSF(data[Model20XPhaseBCurrent], currentScaleFactor); - meterData.phaseCCurrent = m_connection->convertValueWithSSF(data[Model20XPhaseCCurrent], currentScaleFactor); + meterData.totalAcCurrent = m_connection->convertToFloatWithSSF(data[Model20XTotalAcCurrent], currentScaleFactor); + meterData.phaseACurrent = m_connection->convertToFloatWithSSF(data[Model20XPhaseACurrent], currentScaleFactor); + meterData.phaseBCurrent = m_connection->convertToFloatWithSSF(data[Model20XPhaseBCurrent], currentScaleFactor); + meterData.phaseCCurrent = m_connection->convertToFloatWithSSF(data[Model20XPhaseCCurrent], currentScaleFactor); quint16 voltageScaleFactor = data[Model20XVoltageScaleFactor]; - meterData.voltageLN = m_connection->convertValueWithSSF(data[Model20XVoltageLN], voltageScaleFactor); - meterData.phaseVoltageAN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageAN], voltageScaleFactor); - meterData.phaseVoltageBN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageBN], voltageScaleFactor); - meterData.phaseVoltageCN = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageCN], voltageScaleFactor); - meterData.voltageLL = m_connection->convertValueWithSSF(data[Model20XVoltageLL], voltageScaleFactor); - meterData.phaseVoltageAB = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageAB], voltageScaleFactor); - meterData.phaseVoltageBC = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageBC], voltageScaleFactor); - meterData.phaseVoltageCA = m_connection->convertValueWithSSF(data[Model20XPhaseVoltageCA], voltageScaleFactor); - meterData.frequency = m_connection->convertValueWithSSF(data[Model20XFrequency], data[Model20XFrequencyScaleFactor]); - meterData.totalRealPower = m_connection->convertValueWithSSF(data[Model20XTotalRealPower], data[Model20XRealPowerScaleFactor]); + meterData.voltageLN = m_connection->convertToFloatWithSSF(data[Model20XVoltageLN], voltageScaleFactor); + meterData.phaseVoltageAN = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageAN], voltageScaleFactor); + meterData.phaseVoltageBN = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageBN], voltageScaleFactor); + meterData.phaseVoltageCN = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageCN], voltageScaleFactor); + meterData.voltageLL = m_connection->convertToFloatWithSSF(data[Model20XVoltageLL], voltageScaleFactor); + meterData.phaseVoltageAB = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageAB], voltageScaleFactor); + meterData.phaseVoltageBC = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageBC], voltageScaleFactor); + meterData.phaseVoltageCA = m_connection->convertToFloatWithSSF(data[Model20XPhaseVoltageCA], voltageScaleFactor); + meterData.frequency = m_connection->convertToFloatWithSSF(data[Model20XFrequency], data[Model20XFrequencyScaleFactor]); + meterData.totalRealPower = m_connection->convertToFloatWithSSF(data[Model20XTotalRealPower], data[Model20XRealPowerScaleFactor]); quint16 energyScaleFactor = data[Model20XRealEnergyScaleFactor]; - meterData.totalRealEnergyExported = m_connection->convertValueWithSSF(data[Model20XTotalRealEnergyExported], energyScaleFactor); - meterData.totalRealEnergyImported = m_connection->convertValueWithSSF(data[Model20XTotalRealEnergyImported], energyScaleFactor);; + meterData.totalRealEnergyExported = m_connection->convertToFloatWithSSF(data[Model20XTotalRealEnergyExported], energyScaleFactor); + meterData.totalRealEnergyImported = m_connection->convertToFloatWithSSF(data[Model20XTotalRealEnergyImported], energyScaleFactor);; meterData.meterEventFlags = (static_cast(data[Model20XMeterEventFlags]) << 16) | data[Model20XMeterEventFlags+1]; emit meterDataReceived(meterData); diff --git a/sunspec/sunspecstorage.cpp b/sunspec/sunspecstorage.cpp index dab9bc5..d5eba36 100644 --- a/sunspec/sunspecstorage.cpp +++ b/sunspec/sunspecstorage.cpp @@ -100,22 +100,32 @@ QUuid SunSpecStorage::setStorageControlMode(bool chargingEnabled, bool dischargi return m_connection->writeHoldingRegister(modbusRegister, value); } -QUuid SunSpecStorage::setChargingRate(int rate) +QUuid SunSpecStorage::setChargingRate(float rate) { - //Register Name InWRte - /* Defines the maximum charge rate (charge limit). Default is 100% */ - + if (!m_scaleFactorsSet) { + qCWarning(dcSunSpec()) << "SunSpecStorage: Set charging rate, scale factors are not set"; + return ""; + } + if (rate < 0.00 || rate > 100.00) { + qCWarning(dcSunSpec()) << "SunSpecStorage: Set charging rate, rate out of boundaries [0, 100]"; + return ""; + } uint modbusRegister = m_modelModbusStartRegister + Model124::Model124WChaGra; - int16_t value = rate * 100; + quint16 value = m_connection->convertFromFloatWithSSF(rate, m_WChaDisChaGra_SF); return m_connection->writeHoldingRegister(modbusRegister, value); } -QUuid SunSpecStorage::setDischargingRate(int charging) +QUuid SunSpecStorage::setDischargingRate(float rate) { - //Register Name OutWRte - /* Defines the maximum discharge rate (discharge limit). Default is 100% */ + if (!m_scaleFactorsSet) { + qCWarning(dcSunSpec()) << "SunSpecStorage: Set discharging rate, scale factors are not set"; + } + if (rate < 0.00 || rate > 100.00) { + qCWarning(dcSunSpec()) << "SunSpecStorage: Set doscharging rate, rate out of boundaries [0, 100]"; + return ""; + } uint modbusRegister = m_modelModbusStartRegister + Model124::Model124WDisChaGra; - quint16 value = charging * 100; + quint16 value = m_connection->convertFromFloatWithSSF(rate, m_WChaDisChaGra_SF); return m_connection->writeHoldingRegister(modbusRegister, value); } @@ -134,21 +144,21 @@ void SunSpecStorage::onModelDataBlockReceived(SunSpec::ModelId modelId, uint len switch (modelId) { case SunSpec::ModelIdStorage: { StorageData mandatory; - mandatory.WChaMax = m_connection->convertValueWithSSF(data[Model124WChaMax], data[Model124WChaMax_SF]); - mandatory.WChaGra = m_connection->convertValueWithSSF(data[Model124WChaGra], data[Model124WChaDisChaGra_SF]); - mandatory.WDisChaGra = m_connection->convertValueWithSSF(data[Model124WDisChaGra], data[Model124WChaDisChaGra_SF]); + mandatory.WChaMax = m_connection->convertToFloatWithSSF(data[Model124WChaMax], data[Model124WChaMax_SF]); + mandatory.WChaGra = m_connection->convertToFloatWithSSF(data[Model124WChaGra], data[Model124WChaDisChaGra_SF]); + mandatory.WDisChaGra = m_connection->convertToFloatWithSSF(data[Model124WDisChaGra], data[Model124WChaDisChaGra_SF]); mandatory.StorCtl_Mod_ChargingEnabled = data[Model124StorCtl_Mod]&0x01; mandatory.StorCtl_Mod_DischargingEnabled = data[Model124StorCtl_Mod]&0x02; StorageDataOptional optional; - optional.VAChaMax = m_connection->convertValueWithSSF(data[Model124VAChaMax], data[Model124VAChaMax_SF]); - optional.MinRsvPct = m_connection->convertValueWithSSF(data[Model124MinRsvPct], data[Model124MinRsvPct_SF]); - optional.ChaState = m_connection->convertValueWithSSF(data[Model124ChaState], data[Model124ChaState_SF]); - optional.StorAval = m_connection->convertValueWithSSF(data[Model124StorAval], data[Model124StorAval_SF]); - optional.InBatV = m_connection->convertValueWithSSF(data[Model124InBatV], data[Model124InBatV_SF]); + optional.VAChaMax = m_connection->convertToFloatWithSSF(data[Model124VAChaMax], data[Model124VAChaMax_SF]); + optional.MinRsvPct = m_connection->convertToFloatWithSSF(data[Model124MinRsvPct], data[Model124MinRsvPct_SF]); + optional.ChaState = m_connection->convertToFloatWithSSF(data[Model124ChaState], data[Model124ChaState_SF]); + optional.StorAval = m_connection->convertToFloatWithSSF(data[Model124StorAval], data[Model124StorAval_SF]); + optional.InBatV = m_connection->convertToFloatWithSSF(data[Model124InBatV], data[Model124InBatV_SF]); optional.ChaSt = ChargingStatus(data[Model124ChaSt]); - optional.OutWRte = m_connection->convertValueWithSSF(data[Model124OutWRte], data[Model124InOutWRte_SF]); - optional.InWRte = m_connection->convertValueWithSSF(data[Model124InWRte], data[Model124InOutWRte_SF]); + optional.OutWRte = m_connection->convertToFloatWithSSF(data[Model124OutWRte], data[Model124InOutWRte_SF]); + optional.InWRte = m_connection->convertToFloatWithSSF(data[Model124InWRte], data[Model124InOutWRte_SF]); optional.InOutWRte_WinTms = data[Model124InOutWRte_WinTms]; optional.InOutWRte_RvrtTms = data[Model124InOutWRte_RvrtTms]; optional.InOutWRte_RmpTms = data[Model124InOutWRte_RmpTms]; diff --git a/sunspec/sunspecstorage.h b/sunspec/sunspecstorage.h index 49b6bdc..4995753 100644 --- a/sunspec/sunspecstorage.h +++ b/sunspec/sunspecstorage.h @@ -46,8 +46,8 @@ public: void getStorageModelDataBlock(); QUuid setGridCharging(bool enabled); - QUuid setDischargingRate(int rate); - QUuid setChargingRate(int rate); + QUuid setDischargingRate(float rate); + QUuid setChargingRate(float rate); QUuid setStorageControlMode(bool chargingEnabled, bool dischargingEnabled); enum StorageControl { @@ -79,7 +79,7 @@ public: Model124WChaGra = 1, Model124WDisChaGra = 2, Model124StorCtl_Mod = 3, - Model124WChaMax_SF = 16, + Model124WChaMax_SF = 16, Model124WChaDisChaGra_SF = 17, }; @@ -135,6 +135,14 @@ private: uint m_modelModbusStartRegister = 40000; bool m_initFinishedSuccess = false; + // Scale factors needed to perform write requests + bool m_scaleFactorsSet = false; + quint16 m_WChaMax_SF = 0; + quint16 m_WChaDisChaGra_SF = 0; + quint16 m_VAChaMax_SF = 0; + quint16 m_MinRsvPct_SF = 0; + quint16 m_InOutWRte_SF = 0; + private slots: void onModelDataBlockReceived(SunSpec::ModelId modelId, uint length, const QVector &data);