/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 "sunspecstringcombineradvancedmodel.h"
#include "sunspecconnection.h"
SunSpecStringCombinerAdvancedModelRepeatingBlock::SunSpecStringCombinerAdvancedModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerAdvancedModel *parent) :
SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent)
{
m_parentModel = parent;
m_byteOrder = parent->byteOrder();
initDataPoints();
}
QString SunSpecStringCombinerAdvancedModelRepeatingBlock::name() const
{
return "string";
}
SunSpecStringCombinerAdvancedModel *SunSpecStringCombinerAdvancedModelRepeatingBlock::parentModel() const
{
return m_parentModel;
}
quint16 SunSpecStringCombinerAdvancedModelRepeatingBlock::id() const
{
return m_id;
}
SunSpecStringCombinerAdvancedModelRepeatingBlock::InevtFlags SunSpecStringCombinerAdvancedModelRepeatingBlock::inputEvent() const
{
return m_inputEvent;
}
quint32 SunSpecStringCombinerAdvancedModelRepeatingBlock::inputEventVendor() const
{
return m_inputEventVendor;
}
float SunSpecStringCombinerAdvancedModelRepeatingBlock::amps() const
{
return m_amps;
}
quint32 SunSpecStringCombinerAdvancedModelRepeatingBlock::ampHours() const
{
return m_ampHours;
}
float SunSpecStringCombinerAdvancedModelRepeatingBlock::voltage() const
{
return m_voltage;
}
float SunSpecStringCombinerAdvancedModelRepeatingBlock::watts() const
{
return m_watts;
}
quint32 SunSpecStringCombinerAdvancedModelRepeatingBlock::wattHours() const
{
return m_wattHours;
}
quint16 SunSpecStringCombinerAdvancedModelRepeatingBlock::pr() const
{
return m_pr;
}
quint16 SunSpecStringCombinerAdvancedModelRepeatingBlock::n() const
{
return m_n;
}
void SunSpecStringCombinerAdvancedModelRepeatingBlock::initDataPoints()
{
SunSpecDataPoint idDataPoint;
idDataPoint.setName("InID");
idDataPoint.setLabel("ID");
idDataPoint.setDescription("Uniquely identifies this input set");
idDataPoint.setMandatory(true);
idDataPoint.setSize(1);
idDataPoint.setAddressOffset(0);
idDataPoint.setSunSpecDataType("uint16");
idDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(idDataPoint.name(), idDataPoint);
SunSpecDataPoint inputEventDataPoint;
inputEventDataPoint.setName("InEvt");
inputEventDataPoint.setLabel("Input Event");
inputEventDataPoint.setDescription("String Input Event Flags");
inputEventDataPoint.setMandatory(true);
inputEventDataPoint.setSize(2);
inputEventDataPoint.setAddressOffset(1);
inputEventDataPoint.setSunSpecDataType("bitfield32");
inputEventDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inputEventDataPoint.name(), inputEventDataPoint);
SunSpecDataPoint inputEventVendorDataPoint;
inputEventVendorDataPoint.setName("InEvtVnd");
inputEventVendorDataPoint.setLabel("Input Event Vendor");
inputEventVendorDataPoint.setDescription("String Input Vendor Event Flags");
inputEventVendorDataPoint.setSize(2);
inputEventVendorDataPoint.setAddressOffset(3);
inputEventVendorDataPoint.setBlockOffset(1);
inputEventVendorDataPoint.setSunSpecDataType("bitfield32");
inputEventVendorDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inputEventVendorDataPoint.name(), inputEventVendorDataPoint);
SunSpecDataPoint ampsDataPoint;
ampsDataPoint.setName("InDCA");
ampsDataPoint.setLabel("Amps");
ampsDataPoint.setDescription("String Input Current");
ampsDataPoint.setUnits("A");
ampsDataPoint.setMandatory(true);
ampsDataPoint.setSize(1);
ampsDataPoint.setAddressOffset(5);
ampsDataPoint.setBlockOffset(3);
ampsDataPoint.setScaleFactorName("InDCA_SF");
ampsDataPoint.setSunSpecDataType("int16");
ampsDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(ampsDataPoint.name(), ampsDataPoint);
SunSpecDataPoint ampHoursDataPoint;
ampHoursDataPoint.setName("InDCAhr");
ampHoursDataPoint.setLabel("Amp-hours");
ampHoursDataPoint.setDescription("String Input Amp-Hours");
ampHoursDataPoint.setUnits("Ah");
ampHoursDataPoint.setSize(2);
ampHoursDataPoint.setAddressOffset(6);
ampHoursDataPoint.setBlockOffset(4);
ampHoursDataPoint.setScaleFactorName("InDCAhr_SF");
ampHoursDataPoint.setSunSpecDataType("acc32");
ampHoursDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(ampHoursDataPoint.name(), ampHoursDataPoint);
SunSpecDataPoint voltageDataPoint;
voltageDataPoint.setName("InDCV");
voltageDataPoint.setLabel("Voltage");
voltageDataPoint.setDescription("String Input Voltage");
voltageDataPoint.setUnits("V");
voltageDataPoint.setSize(1);
voltageDataPoint.setAddressOffset(8);
voltageDataPoint.setBlockOffset(6);
voltageDataPoint.setScaleFactorName("InDCV_SF");
voltageDataPoint.setSunSpecDataType("int16");
voltageDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(voltageDataPoint.name(), voltageDataPoint);
SunSpecDataPoint wattsDataPoint;
wattsDataPoint.setName("InDCW");
wattsDataPoint.setLabel("Watts");
wattsDataPoint.setDescription("String Input Power");
wattsDataPoint.setUnits("W");
wattsDataPoint.setSize(1);
wattsDataPoint.setAddressOffset(9);
wattsDataPoint.setBlockOffset(7);
wattsDataPoint.setScaleFactorName("InDCW_SF");
wattsDataPoint.setSunSpecDataType("int16");
wattsDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(wattsDataPoint.name(), wattsDataPoint);
SunSpecDataPoint wattHoursDataPoint;
wattHoursDataPoint.setName("InDCWh");
wattHoursDataPoint.setLabel("Watt-hours");
wattHoursDataPoint.setDescription("String Input Energy");
wattHoursDataPoint.setUnits("Wh");
wattHoursDataPoint.setSize(2);
wattHoursDataPoint.setAddressOffset(10);
wattHoursDataPoint.setBlockOffset(8);
wattHoursDataPoint.setScaleFactorName("InDCWh_SF");
wattHoursDataPoint.setSunSpecDataType("acc32");
wattHoursDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(wattHoursDataPoint.name(), wattHoursDataPoint);
SunSpecDataPoint prDataPoint;
prDataPoint.setName("InDCPR");
prDataPoint.setLabel("PR");
prDataPoint.setDescription("String Performance Ratio");
prDataPoint.setUnits("Pct");
prDataPoint.setSize(1);
prDataPoint.setAddressOffset(12);
prDataPoint.setBlockOffset(10);
prDataPoint.setSunSpecDataType("uint16");
prDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(prDataPoint.name(), prDataPoint);
SunSpecDataPoint nDataPoint;
nDataPoint.setName("InN");
nDataPoint.setLabel("N");
nDataPoint.setDescription("Number of modules in this input string");
nDataPoint.setSize(1);
nDataPoint.setAddressOffset(13);
nDataPoint.setBlockOffset(11);
nDataPoint.setSunSpecDataType("uint16");
nDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(nDataPoint.name(), nDataPoint);
}
void SunSpecStringCombinerAdvancedModelRepeatingBlock::processBlockData()
{
// Update properties according to the data point type
if (m_dataPoints.value("InID").isValid())
m_id = m_dataPoints.value("InID").toUInt16();
if (m_dataPoints.value("InEvt").isValid())
m_inputEvent = static_cast(m_dataPoints.value("InEvt").toUInt32());
if (m_dataPoints.value("InEvtVnd").isValid())
m_inputEventVendor = m_dataPoints.value("InEvtVnd").toUInt32();
if (m_dataPoints.value("InDCA").isValid())
m_amps = m_dataPoints.value("InDCA").toFloatWithSSF(m_parentModel->inDCA_SF());
if (m_dataPoints.value("InDCAhr").isValid())
m_ampHours = m_dataPoints.value("InDCAhr").toFloatWithSSF(m_parentModel->inDCAhr_SF());
if (m_dataPoints.value("InDCV").isValid())
m_voltage = m_dataPoints.value("InDCV").toFloatWithSSF(m_parentModel->inDCV_SF());
if (m_dataPoints.value("InDCW").isValid())
m_watts = m_dataPoints.value("InDCW").toFloatWithSSF(m_parentModel->inDCW_SF());
if (m_dataPoints.value("InDCWh").isValid())
m_wattHours = m_dataPoints.value("InDCWh").toFloatWithSSF(m_parentModel->inDCWh_SF());
if (m_dataPoints.value("InDCPR").isValid())
m_pr = m_dataPoints.value("InDCPR").toUInt16();
if (m_dataPoints.value("InN").isValid())
m_n = m_dataPoints.value("InN").toUInt16();
qCDebug(dcSunSpecModelData()) << this;
}
SunSpecStringCombinerAdvancedModel::SunSpecStringCombinerAdvancedModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) :
SunSpecModel(connection, modbusStartRegister, 404, modelLength, byteOrder, parent)
{
m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating;
initDataPoints();
connect(this, &SunSpecModel::initFinished, this, &SunSpecStringCombinerAdvancedModel::setupRepeatingBlocks);
}
SunSpecStringCombinerAdvancedModel::~SunSpecStringCombinerAdvancedModel()
{
}
QString SunSpecStringCombinerAdvancedModel::name() const
{
return "string_combiner";
}
QString SunSpecStringCombinerAdvancedModel::description() const
{
return "An advanced string combiner including voltage and energy measurements";
}
QString SunSpecStringCombinerAdvancedModel::label() const
{
return "String Combiner (Advanced)";
}
qint16 SunSpecStringCombinerAdvancedModel::dCA_SF() const
{
return m_dCA_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::dCAhr_SF() const
{
return m_dCAhr_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::dCV_SF() const
{
return m_dCV_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::dCW_SF() const
{
return m_dCW_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::dCWh_SF() const
{
return m_dCWh_SF;
}
float SunSpecStringCombinerAdvancedModel::rating() const
{
return m_rating;
}
int SunSpecStringCombinerAdvancedModel::n() const
{
return m_n;
}
SunSpecStringCombinerAdvancedModel::EvtFlags SunSpecStringCombinerAdvancedModel::eventFlags() const
{
return m_eventFlags;
}
quint32 SunSpecStringCombinerAdvancedModel::vendorEvent() const
{
return m_vendorEvent;
}
float SunSpecStringCombinerAdvancedModel::amps() const
{
return m_amps;
}
quint32 SunSpecStringCombinerAdvancedModel::ampHours() const
{
return m_ampHours;
}
float SunSpecStringCombinerAdvancedModel::voltage() const
{
return m_voltage;
}
qint16 SunSpecStringCombinerAdvancedModel::temp() const
{
return m_temp;
}
float SunSpecStringCombinerAdvancedModel::watts() const
{
return m_watts;
}
qint16 SunSpecStringCombinerAdvancedModel::pr() const
{
return m_pr;
}
quint32 SunSpecStringCombinerAdvancedModel::wattHours() const
{
return m_wattHours;
}
qint16 SunSpecStringCombinerAdvancedModel::inDCA_SF() const
{
return m_inDCA_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::inDCAhr_SF() const
{
return m_inDCAhr_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::inDCV_SF() const
{
return m_inDCV_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::inDCW_SF() const
{
return m_inDCW_SF;
}
qint16 SunSpecStringCombinerAdvancedModel::inDCWh_SF() const
{
return m_inDCWh_SF;
}
void SunSpecStringCombinerAdvancedModel::initDataPoints()
{
SunSpecDataPoint modelIdDataPoint;
modelIdDataPoint.setName("ID");
modelIdDataPoint.setLabel("Model ID");
modelIdDataPoint.setDescription("Model identifier");
modelIdDataPoint.setMandatory(true);
modelIdDataPoint.setSize(1);
modelIdDataPoint.setAddressOffset(0);
modelIdDataPoint.setSunSpecDataType("uint16");
modelIdDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(modelIdDataPoint.name(), modelIdDataPoint);
SunSpecDataPoint modelLengthDataPoint;
modelLengthDataPoint.setName("L");
modelLengthDataPoint.setLabel("Model Length");
modelLengthDataPoint.setDescription("Model length");
modelLengthDataPoint.setMandatory(true);
modelLengthDataPoint.setSize(1);
modelLengthDataPoint.setAddressOffset(1);
modelLengthDataPoint.setSunSpecDataType("uint16");
modelLengthDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(modelLengthDataPoint.name(), modelLengthDataPoint);
SunSpecDataPoint dCA_SFDataPoint;
dCA_SFDataPoint.setName("DCA_SF");
dCA_SFDataPoint.setDescription("Current scale factor");
dCA_SFDataPoint.setMandatory(true);
dCA_SFDataPoint.setSize(1);
dCA_SFDataPoint.setAddressOffset(2);
dCA_SFDataPoint.setBlockOffset(0);
dCA_SFDataPoint.setSunSpecDataType("sunssf");
dCA_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dCA_SFDataPoint.name(), dCA_SFDataPoint);
SunSpecDataPoint dCAhr_SFDataPoint;
dCAhr_SFDataPoint.setName("DCAhr_SF");
dCAhr_SFDataPoint.setDescription("Amp-hour scale factor");
dCAhr_SFDataPoint.setSize(1);
dCAhr_SFDataPoint.setAddressOffset(3);
dCAhr_SFDataPoint.setBlockOffset(1);
dCAhr_SFDataPoint.setSunSpecDataType("sunssf");
dCAhr_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dCAhr_SFDataPoint.name(), dCAhr_SFDataPoint);
SunSpecDataPoint dCV_SFDataPoint;
dCV_SFDataPoint.setName("DCV_SF");
dCV_SFDataPoint.setDescription("Voltage scale factor");
dCV_SFDataPoint.setSize(1);
dCV_SFDataPoint.setAddressOffset(4);
dCV_SFDataPoint.setBlockOffset(2);
dCV_SFDataPoint.setSunSpecDataType("sunssf");
dCV_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dCV_SFDataPoint.name(), dCV_SFDataPoint);
SunSpecDataPoint dCW_SFDataPoint;
dCW_SFDataPoint.setName("DCW_SF");
dCW_SFDataPoint.setDescription("Power scale factor");
dCW_SFDataPoint.setSize(1);
dCW_SFDataPoint.setAddressOffset(5);
dCW_SFDataPoint.setBlockOffset(3);
dCW_SFDataPoint.setSunSpecDataType("sunssf");
dCW_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dCW_SFDataPoint.name(), dCW_SFDataPoint);
SunSpecDataPoint dCWh_SFDataPoint;
dCWh_SFDataPoint.setName("DCWh_SF");
dCWh_SFDataPoint.setDescription("Energy scale factor");
dCWh_SFDataPoint.setSize(1);
dCWh_SFDataPoint.setAddressOffset(6);
dCWh_SFDataPoint.setBlockOffset(4);
dCWh_SFDataPoint.setSunSpecDataType("sunssf");
dCWh_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dCWh_SFDataPoint.name(), dCWh_SFDataPoint);
SunSpecDataPoint ratingDataPoint;
ratingDataPoint.setName("DCAMax");
ratingDataPoint.setLabel("Rating");
ratingDataPoint.setDescription("Maximum DC Current Rating");
ratingDataPoint.setUnits("A");
ratingDataPoint.setMandatory(true);
ratingDataPoint.setSize(1);
ratingDataPoint.setAddressOffset(7);
ratingDataPoint.setBlockOffset(5);
ratingDataPoint.setScaleFactorName("DCA_SF");
ratingDataPoint.setSunSpecDataType("uint16");
ratingDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(ratingDataPoint.name(), ratingDataPoint);
SunSpecDataPoint nDataPoint;
nDataPoint.setName("N");
nDataPoint.setLabel("N");
nDataPoint.setDescription("Number of Inputs");
nDataPoint.setMandatory(true);
nDataPoint.setSize(1);
nDataPoint.setAddressOffset(8);
nDataPoint.setBlockOffset(6);
nDataPoint.setSunSpecDataType("count");
nDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(nDataPoint.name(), nDataPoint);
SunSpecDataPoint eventFlagsDataPoint;
eventFlagsDataPoint.setName("Evt");
eventFlagsDataPoint.setLabel("Event");
eventFlagsDataPoint.setDescription("Bitmask value. Events");
eventFlagsDataPoint.setMandatory(true);
eventFlagsDataPoint.setSize(2);
eventFlagsDataPoint.setAddressOffset(9);
eventFlagsDataPoint.setBlockOffset(7);
eventFlagsDataPoint.setSunSpecDataType("bitfield32");
eventFlagsDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(eventFlagsDataPoint.name(), eventFlagsDataPoint);
SunSpecDataPoint vendorEventDataPoint;
vendorEventDataPoint.setName("EvtVnd");
vendorEventDataPoint.setLabel("Vendor Event");
vendorEventDataPoint.setDescription("Bitmask value. Vendor defined events");
vendorEventDataPoint.setSize(2);
vendorEventDataPoint.setAddressOffset(11);
vendorEventDataPoint.setBlockOffset(9);
vendorEventDataPoint.setSunSpecDataType("bitfield32");
vendorEventDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(vendorEventDataPoint.name(), vendorEventDataPoint);
SunSpecDataPoint ampsDataPoint;
ampsDataPoint.setName("DCA");
ampsDataPoint.setLabel("Amps");
ampsDataPoint.setDescription("Total measured current");
ampsDataPoint.setUnits("A");
ampsDataPoint.setMandatory(true);
ampsDataPoint.setSize(1);
ampsDataPoint.setAddressOffset(13);
ampsDataPoint.setBlockOffset(11);
ampsDataPoint.setScaleFactorName("DCA_SF");
ampsDataPoint.setSunSpecDataType("int16");
ampsDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(ampsDataPoint.name(), ampsDataPoint);
SunSpecDataPoint ampHoursDataPoint;
ampHoursDataPoint.setName("DCAhr");
ampHoursDataPoint.setLabel("Amp-hours");
ampHoursDataPoint.setDescription("Total metered Amp-hours");
ampHoursDataPoint.setUnits("Ah");
ampHoursDataPoint.setSize(2);
ampHoursDataPoint.setAddressOffset(14);
ampHoursDataPoint.setBlockOffset(12);
ampHoursDataPoint.setScaleFactorName("DCAhr_SF");
ampHoursDataPoint.setSunSpecDataType("acc32");
ampHoursDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(ampHoursDataPoint.name(), ampHoursDataPoint);
SunSpecDataPoint voltageDataPoint;
voltageDataPoint.setName("DCV");
voltageDataPoint.setLabel("Voltage");
voltageDataPoint.setDescription("Output Voltage");
voltageDataPoint.setUnits("V");
voltageDataPoint.setSize(1);
voltageDataPoint.setAddressOffset(16);
voltageDataPoint.setBlockOffset(14);
voltageDataPoint.setScaleFactorName("DCV_SF");
voltageDataPoint.setSunSpecDataType("int16");
voltageDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(voltageDataPoint.name(), voltageDataPoint);
SunSpecDataPoint tempDataPoint;
tempDataPoint.setName("Tmp");
tempDataPoint.setLabel("Temp");
tempDataPoint.setDescription("Internal operating temperature");
tempDataPoint.setUnits("C");
tempDataPoint.setSize(1);
tempDataPoint.setAddressOffset(17);
tempDataPoint.setBlockOffset(15);
tempDataPoint.setSunSpecDataType("int16");
tempDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(tempDataPoint.name(), tempDataPoint);
SunSpecDataPoint wattsDataPoint;
wattsDataPoint.setName("DCW");
wattsDataPoint.setLabel("Watts");
wattsDataPoint.setDescription("Output power");
wattsDataPoint.setUnits("W");
wattsDataPoint.setSize(1);
wattsDataPoint.setAddressOffset(18);
wattsDataPoint.setBlockOffset(16);
wattsDataPoint.setScaleFactorName("DCW_SF");
wattsDataPoint.setSunSpecDataType("int16");
wattsDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(wattsDataPoint.name(), wattsDataPoint);
SunSpecDataPoint prDataPoint;
prDataPoint.setName("DCPR");
prDataPoint.setLabel("PR");
prDataPoint.setDescription("DC Performance ratio value");
prDataPoint.setUnits("Pct");
prDataPoint.setSize(1);
prDataPoint.setAddressOffset(19);
prDataPoint.setBlockOffset(17);
prDataPoint.setSunSpecDataType("int16");
prDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(prDataPoint.name(), prDataPoint);
SunSpecDataPoint wattHoursDataPoint;
wattHoursDataPoint.setName("DCWh");
wattHoursDataPoint.setLabel("Watt-hours");
wattHoursDataPoint.setDescription("Output energy");
wattHoursDataPoint.setUnits("Wh");
wattHoursDataPoint.setSize(2);
wattHoursDataPoint.setAddressOffset(20);
wattHoursDataPoint.setBlockOffset(18);
wattHoursDataPoint.setScaleFactorName("DCWh_SF");
wattHoursDataPoint.setSunSpecDataType("acc32");
wattHoursDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(wattHoursDataPoint.name(), wattHoursDataPoint);
SunSpecDataPoint inDCA_SFDataPoint;
inDCA_SFDataPoint.setName("InDCA_SF");
inDCA_SFDataPoint.setDescription("Current scale factor for inputs");
inDCA_SFDataPoint.setSize(1);
inDCA_SFDataPoint.setAddressOffset(22);
inDCA_SFDataPoint.setBlockOffset(20);
inDCA_SFDataPoint.setSunSpecDataType("sunssf");
inDCA_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inDCA_SFDataPoint.name(), inDCA_SFDataPoint);
SunSpecDataPoint inDCAhr_SFDataPoint;
inDCAhr_SFDataPoint.setName("InDCAhr_SF");
inDCAhr_SFDataPoint.setDescription("Amp-hour scale factor for inputs");
inDCAhr_SFDataPoint.setSize(1);
inDCAhr_SFDataPoint.setAddressOffset(23);
inDCAhr_SFDataPoint.setBlockOffset(21);
inDCAhr_SFDataPoint.setSunSpecDataType("sunssf");
inDCAhr_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inDCAhr_SFDataPoint.name(), inDCAhr_SFDataPoint);
SunSpecDataPoint inDCV_SFDataPoint;
inDCV_SFDataPoint.setName("InDCV_SF");
inDCV_SFDataPoint.setDescription("Voltage scale factor for inputs");
inDCV_SFDataPoint.setSize(1);
inDCV_SFDataPoint.setAddressOffset(24);
inDCV_SFDataPoint.setBlockOffset(22);
inDCV_SFDataPoint.setSunSpecDataType("sunssf");
inDCV_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inDCV_SFDataPoint.name(), inDCV_SFDataPoint);
SunSpecDataPoint inDCW_SFDataPoint;
inDCW_SFDataPoint.setName("InDCW_SF");
inDCW_SFDataPoint.setDescription("Power scale factor for inputs");
inDCW_SFDataPoint.setSize(1);
inDCW_SFDataPoint.setAddressOffset(25);
inDCW_SFDataPoint.setBlockOffset(23);
inDCW_SFDataPoint.setSunSpecDataType("sunssf");
inDCW_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inDCW_SFDataPoint.name(), inDCW_SFDataPoint);
SunSpecDataPoint inDCWh_SFDataPoint;
inDCWh_SFDataPoint.setName("InDCWh_SF");
inDCWh_SFDataPoint.setDescription("Energy scale factor for inputs");
inDCWh_SFDataPoint.setSize(1);
inDCWh_SFDataPoint.setAddressOffset(26);
inDCWh_SFDataPoint.setBlockOffset(24);
inDCWh_SFDataPoint.setSunSpecDataType("sunssf");
inDCWh_SFDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(inDCWh_SFDataPoint.name(), inDCWh_SFDataPoint);
}
void SunSpecStringCombinerAdvancedModel::processBlockData()
{
// Scale factors
if (m_dataPoints.value("DCA_SF").isValid())
m_dCA_SF = m_dataPoints.value("DCA_SF").toInt16();
if (m_dataPoints.value("DCAhr_SF").isValid())
m_dCAhr_SF = m_dataPoints.value("DCAhr_SF").toInt16();
if (m_dataPoints.value("DCV_SF").isValid())
m_dCV_SF = m_dataPoints.value("DCV_SF").toInt16();
if (m_dataPoints.value("DCW_SF").isValid())
m_dCW_SF = m_dataPoints.value("DCW_SF").toInt16();
if (m_dataPoints.value("DCWh_SF").isValid())
m_dCWh_SF = m_dataPoints.value("DCWh_SF").toInt16();
if (m_dataPoints.value("InDCA_SF").isValid())
m_inDCA_SF = m_dataPoints.value("InDCA_SF").toInt16();
if (m_dataPoints.value("InDCAhr_SF").isValid())
m_inDCAhr_SF = m_dataPoints.value("InDCAhr_SF").toInt16();
if (m_dataPoints.value("InDCV_SF").isValid())
m_inDCV_SF = m_dataPoints.value("InDCV_SF").toInt16();
if (m_dataPoints.value("InDCW_SF").isValid())
m_inDCW_SF = m_dataPoints.value("InDCW_SF").toInt16();
if (m_dataPoints.value("InDCWh_SF").isValid())
m_inDCWh_SF = m_dataPoints.value("InDCWh_SF").toInt16();
// Update properties according to the data point type
if (m_dataPoints.value("DCA_SF").isValid())
m_dCA_SF = m_dataPoints.value("DCA_SF").toInt16();
if (m_dataPoints.value("DCAhr_SF").isValid())
m_dCAhr_SF = m_dataPoints.value("DCAhr_SF").toInt16();
if (m_dataPoints.value("DCV_SF").isValid())
m_dCV_SF = m_dataPoints.value("DCV_SF").toInt16();
if (m_dataPoints.value("DCW_SF").isValid())
m_dCW_SF = m_dataPoints.value("DCW_SF").toInt16();
if (m_dataPoints.value("DCWh_SF").isValid())
m_dCWh_SF = m_dataPoints.value("DCWh_SF").toInt16();
if (m_dataPoints.value("DCAMax").isValid())
m_rating = m_dataPoints.value("DCAMax").toFloatWithSSF(m_dCA_SF);
if (m_dataPoints.value("N").isValid())
m_n = m_dataPoints.value("N").toUInt16();
if (m_dataPoints.value("Evt").isValid())
m_eventFlags = static_cast(m_dataPoints.value("Evt").toUInt32());
if (m_dataPoints.value("EvtVnd").isValid())
m_vendorEvent = m_dataPoints.value("EvtVnd").toUInt32();
if (m_dataPoints.value("DCA").isValid())
m_amps = m_dataPoints.value("DCA").toFloatWithSSF(m_dCA_SF);
if (m_dataPoints.value("DCAhr").isValid())
m_ampHours = m_dataPoints.value("DCAhr").toFloatWithSSF(m_dCAhr_SF);
if (m_dataPoints.value("DCV").isValid())
m_voltage = m_dataPoints.value("DCV").toFloatWithSSF(m_dCV_SF);
if (m_dataPoints.value("Tmp").isValid())
m_temp = m_dataPoints.value("Tmp").toInt16();
if (m_dataPoints.value("DCW").isValid())
m_watts = m_dataPoints.value("DCW").toFloatWithSSF(m_dCW_SF);
if (m_dataPoints.value("DCPR").isValid())
m_pr = m_dataPoints.value("DCPR").toInt16();
if (m_dataPoints.value("DCWh").isValid())
m_wattHours = m_dataPoints.value("DCWh").toFloatWithSSF(m_dCWh_SF);
if (m_dataPoints.value("InDCA_SF").isValid())
m_inDCA_SF = m_dataPoints.value("InDCA_SF").toInt16();
if (m_dataPoints.value("InDCAhr_SF").isValid())
m_inDCAhr_SF = m_dataPoints.value("InDCAhr_SF").toInt16();
if (m_dataPoints.value("InDCV_SF").isValid())
m_inDCV_SF = m_dataPoints.value("InDCV_SF").toInt16();
if (m_dataPoints.value("InDCW_SF").isValid())
m_inDCW_SF = m_dataPoints.value("InDCW_SF").toInt16();
if (m_dataPoints.value("InDCWh_SF").isValid())
m_inDCWh_SF = m_dataPoints.value("InDCWh_SF").toInt16();
qCDebug(dcSunSpecModelData()) << this;
}
void SunSpecStringCombinerAdvancedModel::setupRepeatingBlocks()
{
if (!m_repeatingBlocks.isEmpty()) {
foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) {
block->deleteLater();
}
m_repeatingBlocks.clear();
}
const auto headerLength = 2;
const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength;
if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) {
qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:"
<< repeatingBlocksDataSize
<< "(repeating block size:"
<< m_repeatingBlockLength
<< ", extra bytes:"
<< repeatingBlocksDataSize % m_repeatingBlockLength
<< "). Repeating blocks will not be handled!";
return;
}
const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength;
const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength;
for (int i = 0; i < numberOfBlocks; ++i) {
const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i);
const auto block = new SunSpecStringCombinerAdvancedModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this);
m_repeatingBlocks.append(block);
}
}
QDebug operator<<(QDebug debug, SunSpecStringCombinerAdvancedModel *model)
{
debug.nospace().noquote() << "SunSpecStringCombinerAdvancedModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n";
debug.nospace().noquote() << " - " << model->dataPoints().value("DCAMax") << "-->";
if (model->dataPoints().value("DCAMax").isValid()) {
debug.nospace().noquote() << model->rating() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("N") << "-->";
if (model->dataPoints().value("N").isValid()) {
debug.nospace().noquote() << model->n() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Evt") << "-->";
if (model->dataPoints().value("Evt").isValid()) {
debug.nospace().noquote() << model->eventFlags() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("EvtVnd") << "-->";
if (model->dataPoints().value("EvtVnd").isValid()) {
debug.nospace().noquote() << model->vendorEvent() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCA") << "-->";
if (model->dataPoints().value("DCA").isValid()) {
debug.nospace().noquote() << model->amps() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCAhr") << "-->";
if (model->dataPoints().value("DCAhr").isValid()) {
debug.nospace().noquote() << model->ampHours() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCV") << "-->";
if (model->dataPoints().value("DCV").isValid()) {
debug.nospace().noquote() << model->voltage() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Tmp") << "-->";
if (model->dataPoints().value("Tmp").isValid()) {
debug.nospace().noquote() << model->temp() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCW") << "-->";
if (model->dataPoints().value("DCW").isValid()) {
debug.nospace().noquote() << model->watts() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCPR") << "-->";
if (model->dataPoints().value("DCPR").isValid()) {
debug.nospace().noquote() << model->pr() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("DCWh") << "-->";
if (model->dataPoints().value("DCWh").isValid()) {
debug.nospace().noquote() << model->wattHours() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
return debug.space().quote();
}