673 lines
26 KiB
C++
673 lines
26 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Copyright 2013 - 2021, 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 <https://www.gnu.org/licenses/>.
|
|
*
|
|
* 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 "sunspecsolarmodulemodel.h"
|
|
#include "sunspecconnection.h"
|
|
|
|
SunSpecSolarModuleModel::SunSpecSolarModuleModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) :
|
|
SunSpecModel(connection, modbusStartRegister, 502, modelLength, byteOrder, parent)
|
|
{
|
|
m_modelBlockType = SunSpecModel::ModelBlockTypeFixed;
|
|
|
|
initDataPoints();
|
|
}
|
|
|
|
SunSpecSolarModuleModel::~SunSpecSolarModuleModel()
|
|
{
|
|
|
|
}
|
|
|
|
QString SunSpecSolarModuleModel::name() const
|
|
{
|
|
return "solar_module";
|
|
}
|
|
|
|
QString SunSpecSolarModuleModel::description() const
|
|
{
|
|
return "A solar module model supporting DC-DC converter";
|
|
}
|
|
|
|
QString SunSpecSolarModuleModel::label() const
|
|
{
|
|
return "Solar Module";
|
|
}
|
|
|
|
qint16 SunSpecSolarModuleModel::a_SF() const
|
|
{
|
|
return m_a_SF;
|
|
}
|
|
qint16 SunSpecSolarModuleModel::v_SF() const
|
|
{
|
|
return m_v_SF;
|
|
}
|
|
qint16 SunSpecSolarModuleModel::w_SF() const
|
|
{
|
|
return m_w_SF;
|
|
}
|
|
qint16 SunSpecSolarModuleModel::wh_SF() const
|
|
{
|
|
return m_wh_SF;
|
|
}
|
|
SunSpecSolarModuleModel::Stat SunSpecSolarModuleModel::status() const
|
|
{
|
|
return m_status;
|
|
}
|
|
quint16 SunSpecSolarModuleModel::vendorStatus() const
|
|
{
|
|
return m_vendorStatus;
|
|
}
|
|
SunSpecSolarModuleModel::EvtFlags SunSpecSolarModuleModel::events() const
|
|
{
|
|
return m_events;
|
|
}
|
|
quint32 SunSpecSolarModuleModel::vendorModuleEventFlags() const
|
|
{
|
|
return m_vendorModuleEventFlags;
|
|
}
|
|
quint16 SunSpecSolarModuleModel::control() const
|
|
{
|
|
return m_control;
|
|
}
|
|
|
|
QModbusReply *SunSpecSolarModuleModel::setControl(quint16 control)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("Ctl");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt16(static_cast<quint16>(control));
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
quint32 SunSpecSolarModuleModel::vendorControl() const
|
|
{
|
|
return m_vendorControl;
|
|
}
|
|
|
|
QModbusReply *SunSpecSolarModuleModel::setVendorControl(quint32 vendorControl)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("CtlVend");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt32(static_cast<quint32>(vendorControl));
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
qint32 SunSpecSolarModuleModel::controlValue() const
|
|
{
|
|
return m_controlValue;
|
|
}
|
|
|
|
QModbusReply *SunSpecSolarModuleModel::setControlValue(qint32 controlValue)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("CtlVal");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromInt32(controlValue);
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
quint32 SunSpecSolarModuleModel::timestamp() const
|
|
{
|
|
return m_timestamp;
|
|
}
|
|
float SunSpecSolarModuleModel::outputCurrent() const
|
|
{
|
|
return m_outputCurrent;
|
|
}
|
|
float SunSpecSolarModuleModel::outputVoltage() const
|
|
{
|
|
return m_outputVoltage;
|
|
}
|
|
quint32 SunSpecSolarModuleModel::outputEnergy() const
|
|
{
|
|
return m_outputEnergy;
|
|
}
|
|
float SunSpecSolarModuleModel::outputPower() const
|
|
{
|
|
return m_outputPower;
|
|
}
|
|
qint16 SunSpecSolarModuleModel::temp() const
|
|
{
|
|
return m_temp;
|
|
}
|
|
float SunSpecSolarModuleModel::inputCurrent() const
|
|
{
|
|
return m_inputCurrent;
|
|
}
|
|
float SunSpecSolarModuleModel::inputVoltage() const
|
|
{
|
|
return m_inputVoltage;
|
|
}
|
|
quint32 SunSpecSolarModuleModel::inputEnergy() const
|
|
{
|
|
return m_inputEnergy;
|
|
}
|
|
float SunSpecSolarModuleModel::inputPower() const
|
|
{
|
|
return m_inputPower;
|
|
}
|
|
void SunSpecSolarModuleModel::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 a_SFDataPoint;
|
|
a_SFDataPoint.setName("A_SF");
|
|
a_SFDataPoint.setDescription("Current scale factor");
|
|
a_SFDataPoint.setSize(1);
|
|
a_SFDataPoint.setAddressOffset(2);
|
|
a_SFDataPoint.setBlockOffset(0);
|
|
a_SFDataPoint.setSunSpecDataType("sunssf");
|
|
a_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(a_SFDataPoint.name(), a_SFDataPoint);
|
|
|
|
SunSpecDataPoint v_SFDataPoint;
|
|
v_SFDataPoint.setName("V_SF");
|
|
v_SFDataPoint.setDescription("Voltage scale factor");
|
|
v_SFDataPoint.setSize(1);
|
|
v_SFDataPoint.setAddressOffset(3);
|
|
v_SFDataPoint.setBlockOffset(1);
|
|
v_SFDataPoint.setSunSpecDataType("sunssf");
|
|
v_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(v_SFDataPoint.name(), v_SFDataPoint);
|
|
|
|
SunSpecDataPoint w_SFDataPoint;
|
|
w_SFDataPoint.setName("W_SF");
|
|
w_SFDataPoint.setDescription("Power scale factor");
|
|
w_SFDataPoint.setSize(1);
|
|
w_SFDataPoint.setAddressOffset(4);
|
|
w_SFDataPoint.setBlockOffset(2);
|
|
w_SFDataPoint.setSunSpecDataType("sunssf");
|
|
w_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(w_SFDataPoint.name(), w_SFDataPoint);
|
|
|
|
SunSpecDataPoint wh_SFDataPoint;
|
|
wh_SFDataPoint.setName("Wh_SF");
|
|
wh_SFDataPoint.setDescription("Energy scale factor");
|
|
wh_SFDataPoint.setSize(1);
|
|
wh_SFDataPoint.setAddressOffset(5);
|
|
wh_SFDataPoint.setBlockOffset(3);
|
|
wh_SFDataPoint.setSunSpecDataType("sunssf");
|
|
wh_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(wh_SFDataPoint.name(), wh_SFDataPoint);
|
|
|
|
SunSpecDataPoint statusDataPoint;
|
|
statusDataPoint.setName("Stat");
|
|
statusDataPoint.setLabel("Status");
|
|
statusDataPoint.setDescription("Enumerated value. Module Status Code");
|
|
statusDataPoint.setMandatory(true);
|
|
statusDataPoint.setSize(1);
|
|
statusDataPoint.setAddressOffset(6);
|
|
statusDataPoint.setBlockOffset(4);
|
|
statusDataPoint.setSunSpecDataType("enum16");
|
|
statusDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(statusDataPoint.name(), statusDataPoint);
|
|
|
|
SunSpecDataPoint vendorStatusDataPoint;
|
|
vendorStatusDataPoint.setName("StatVend");
|
|
vendorStatusDataPoint.setLabel("Vendor Status");
|
|
vendorStatusDataPoint.setDescription("Module Vendor Status Code");
|
|
vendorStatusDataPoint.setSize(1);
|
|
vendorStatusDataPoint.setAddressOffset(7);
|
|
vendorStatusDataPoint.setBlockOffset(5);
|
|
vendorStatusDataPoint.setSunSpecDataType("enum16");
|
|
vendorStatusDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorStatusDataPoint.name(), vendorStatusDataPoint);
|
|
|
|
SunSpecDataPoint eventsDataPoint;
|
|
eventsDataPoint.setName("Evt");
|
|
eventsDataPoint.setLabel("Events");
|
|
eventsDataPoint.setDescription("Bitmask value. Module Event Flags");
|
|
eventsDataPoint.setMandatory(true);
|
|
eventsDataPoint.setSize(2);
|
|
eventsDataPoint.setAddressOffset(8);
|
|
eventsDataPoint.setBlockOffset(6);
|
|
eventsDataPoint.setSunSpecDataType("bitfield32");
|
|
eventsDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(eventsDataPoint.name(), eventsDataPoint);
|
|
|
|
SunSpecDataPoint vendorModuleEventFlagsDataPoint;
|
|
vendorModuleEventFlagsDataPoint.setName("EvtVend");
|
|
vendorModuleEventFlagsDataPoint.setLabel("Vendor Module Event Flags");
|
|
vendorModuleEventFlagsDataPoint.setDescription("Vendor specific flags");
|
|
vendorModuleEventFlagsDataPoint.setSize(2);
|
|
vendorModuleEventFlagsDataPoint.setAddressOffset(10);
|
|
vendorModuleEventFlagsDataPoint.setBlockOffset(8);
|
|
vendorModuleEventFlagsDataPoint.setSunSpecDataType("bitfield32");
|
|
vendorModuleEventFlagsDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorModuleEventFlagsDataPoint.name(), vendorModuleEventFlagsDataPoint);
|
|
|
|
SunSpecDataPoint controlDataPoint;
|
|
controlDataPoint.setName("Ctl");
|
|
controlDataPoint.setLabel("Control");
|
|
controlDataPoint.setDescription("Module Control");
|
|
controlDataPoint.setSize(1);
|
|
controlDataPoint.setAddressOffset(12);
|
|
controlDataPoint.setBlockOffset(10);
|
|
controlDataPoint.setSunSpecDataType("enum16");
|
|
controlDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
controlDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(controlDataPoint.name(), controlDataPoint);
|
|
|
|
SunSpecDataPoint vendorControlDataPoint;
|
|
vendorControlDataPoint.setName("CtlVend");
|
|
vendorControlDataPoint.setLabel("Vendor Control");
|
|
vendorControlDataPoint.setDescription("Vendor Module Control");
|
|
vendorControlDataPoint.setSize(2);
|
|
vendorControlDataPoint.setAddressOffset(13);
|
|
vendorControlDataPoint.setBlockOffset(11);
|
|
vendorControlDataPoint.setSunSpecDataType("enum32");
|
|
vendorControlDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
vendorControlDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorControlDataPoint.name(), vendorControlDataPoint);
|
|
|
|
SunSpecDataPoint controlValueDataPoint;
|
|
controlValueDataPoint.setName("CtlVal");
|
|
controlValueDataPoint.setLabel("Control Value");
|
|
controlValueDataPoint.setDescription("Module Control Value");
|
|
controlValueDataPoint.setSize(2);
|
|
controlValueDataPoint.setAddressOffset(15);
|
|
controlValueDataPoint.setBlockOffset(13);
|
|
controlValueDataPoint.setSunSpecDataType("int32");
|
|
controlValueDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
controlValueDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(controlValueDataPoint.name(), controlValueDataPoint);
|
|
|
|
SunSpecDataPoint timestampDataPoint;
|
|
timestampDataPoint.setName("Tms");
|
|
timestampDataPoint.setLabel("Timestamp");
|
|
timestampDataPoint.setDescription("Time in seconds since 2000 epoch");
|
|
timestampDataPoint.setUnits("Secs");
|
|
timestampDataPoint.setSize(2);
|
|
timestampDataPoint.setAddressOffset(17);
|
|
timestampDataPoint.setBlockOffset(15);
|
|
timestampDataPoint.setSunSpecDataType("uint32");
|
|
timestampDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(timestampDataPoint.name(), timestampDataPoint);
|
|
|
|
SunSpecDataPoint outputCurrentDataPoint;
|
|
outputCurrentDataPoint.setName("OutA");
|
|
outputCurrentDataPoint.setLabel("Output Current");
|
|
outputCurrentDataPoint.setDescription("Output Current");
|
|
outputCurrentDataPoint.setUnits("A");
|
|
outputCurrentDataPoint.setSize(1);
|
|
outputCurrentDataPoint.setAddressOffset(19);
|
|
outputCurrentDataPoint.setBlockOffset(17);
|
|
outputCurrentDataPoint.setScaleFactorName("A_SF");
|
|
outputCurrentDataPoint.setSunSpecDataType("int16");
|
|
outputCurrentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(outputCurrentDataPoint.name(), outputCurrentDataPoint);
|
|
|
|
SunSpecDataPoint outputVoltageDataPoint;
|
|
outputVoltageDataPoint.setName("OutV");
|
|
outputVoltageDataPoint.setLabel("Output Voltage");
|
|
outputVoltageDataPoint.setDescription("Output Voltage");
|
|
outputVoltageDataPoint.setUnits("V");
|
|
outputVoltageDataPoint.setSize(1);
|
|
outputVoltageDataPoint.setAddressOffset(20);
|
|
outputVoltageDataPoint.setBlockOffset(18);
|
|
outputVoltageDataPoint.setScaleFactorName("V_SF");
|
|
outputVoltageDataPoint.setSunSpecDataType("int16");
|
|
outputVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(outputVoltageDataPoint.name(), outputVoltageDataPoint);
|
|
|
|
SunSpecDataPoint outputEnergyDataPoint;
|
|
outputEnergyDataPoint.setName("OutWh");
|
|
outputEnergyDataPoint.setLabel("Output Energy");
|
|
outputEnergyDataPoint.setDescription("Output Energy");
|
|
outputEnergyDataPoint.setUnits("Wh");
|
|
outputEnergyDataPoint.setSize(2);
|
|
outputEnergyDataPoint.setAddressOffset(21);
|
|
outputEnergyDataPoint.setBlockOffset(19);
|
|
outputEnergyDataPoint.setScaleFactorName("Wh_SF");
|
|
outputEnergyDataPoint.setSunSpecDataType("acc32");
|
|
outputEnergyDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(outputEnergyDataPoint.name(), outputEnergyDataPoint);
|
|
|
|
SunSpecDataPoint outputPowerDataPoint;
|
|
outputPowerDataPoint.setName("OutPw");
|
|
outputPowerDataPoint.setLabel("Output Power");
|
|
outputPowerDataPoint.setDescription("Output Power");
|
|
outputPowerDataPoint.setUnits("W");
|
|
outputPowerDataPoint.setSize(1);
|
|
outputPowerDataPoint.setAddressOffset(23);
|
|
outputPowerDataPoint.setBlockOffset(21);
|
|
outputPowerDataPoint.setScaleFactorName("W_SF");
|
|
outputPowerDataPoint.setSunSpecDataType("int16");
|
|
outputPowerDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(outputPowerDataPoint.name(), outputPowerDataPoint);
|
|
|
|
SunSpecDataPoint tempDataPoint;
|
|
tempDataPoint.setName("Tmp");
|
|
tempDataPoint.setLabel("Temp");
|
|
tempDataPoint.setDescription("Module Temperature");
|
|
tempDataPoint.setUnits("C");
|
|
tempDataPoint.setSize(1);
|
|
tempDataPoint.setAddressOffset(24);
|
|
tempDataPoint.setBlockOffset(22);
|
|
tempDataPoint.setSunSpecDataType("int16");
|
|
tempDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(tempDataPoint.name(), tempDataPoint);
|
|
|
|
SunSpecDataPoint inputCurrentDataPoint;
|
|
inputCurrentDataPoint.setName("InA");
|
|
inputCurrentDataPoint.setLabel("Input Current");
|
|
inputCurrentDataPoint.setDescription("Input Current");
|
|
inputCurrentDataPoint.setUnits("A");
|
|
inputCurrentDataPoint.setSize(1);
|
|
inputCurrentDataPoint.setAddressOffset(25);
|
|
inputCurrentDataPoint.setBlockOffset(23);
|
|
inputCurrentDataPoint.setScaleFactorName("A_SF");
|
|
inputCurrentDataPoint.setSunSpecDataType("int16");
|
|
inputCurrentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(inputCurrentDataPoint.name(), inputCurrentDataPoint);
|
|
|
|
SunSpecDataPoint inputVoltageDataPoint;
|
|
inputVoltageDataPoint.setName("InV");
|
|
inputVoltageDataPoint.setLabel("Input Voltage");
|
|
inputVoltageDataPoint.setDescription("Input Voltage");
|
|
inputVoltageDataPoint.setUnits("V");
|
|
inputVoltageDataPoint.setSize(1);
|
|
inputVoltageDataPoint.setAddressOffset(26);
|
|
inputVoltageDataPoint.setBlockOffset(24);
|
|
inputVoltageDataPoint.setScaleFactorName("V_SF");
|
|
inputVoltageDataPoint.setSunSpecDataType("int16");
|
|
inputVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(inputVoltageDataPoint.name(), inputVoltageDataPoint);
|
|
|
|
SunSpecDataPoint inputEnergyDataPoint;
|
|
inputEnergyDataPoint.setName("InWh");
|
|
inputEnergyDataPoint.setLabel("Input Energy");
|
|
inputEnergyDataPoint.setDescription("Input Energy");
|
|
inputEnergyDataPoint.setUnits("Wh");
|
|
inputEnergyDataPoint.setSize(2);
|
|
inputEnergyDataPoint.setAddressOffset(27);
|
|
inputEnergyDataPoint.setBlockOffset(25);
|
|
inputEnergyDataPoint.setScaleFactorName("Wh_SF");
|
|
inputEnergyDataPoint.setSunSpecDataType("acc32");
|
|
inputEnergyDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(inputEnergyDataPoint.name(), inputEnergyDataPoint);
|
|
|
|
SunSpecDataPoint inputPowerDataPoint;
|
|
inputPowerDataPoint.setName("InW");
|
|
inputPowerDataPoint.setLabel("Input Power");
|
|
inputPowerDataPoint.setDescription("Input Power");
|
|
inputPowerDataPoint.setUnits("W");
|
|
inputPowerDataPoint.setSize(1);
|
|
inputPowerDataPoint.setAddressOffset(29);
|
|
inputPowerDataPoint.setBlockOffset(27);
|
|
inputPowerDataPoint.setScaleFactorName("W_SF");
|
|
inputPowerDataPoint.setSunSpecDataType("int16");
|
|
inputPowerDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(inputPowerDataPoint.name(), inputPowerDataPoint);
|
|
|
|
}
|
|
|
|
void SunSpecSolarModuleModel::processBlockData()
|
|
{
|
|
// Scale factors
|
|
if (m_dataPoints.value("A_SF").isValid())
|
|
m_a_SF = m_dataPoints.value("A_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("V_SF").isValid())
|
|
m_v_SF = m_dataPoints.value("V_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("W_SF").isValid())
|
|
m_w_SF = m_dataPoints.value("W_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("Wh_SF").isValid())
|
|
m_wh_SF = m_dataPoints.value("Wh_SF").toInt16();
|
|
|
|
|
|
// Update properties according to the data point type
|
|
if (m_dataPoints.value("A_SF").isValid())
|
|
m_a_SF = m_dataPoints.value("A_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("V_SF").isValid())
|
|
m_v_SF = m_dataPoints.value("V_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("W_SF").isValid())
|
|
m_w_SF = m_dataPoints.value("W_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("Wh_SF").isValid())
|
|
m_wh_SF = m_dataPoints.value("Wh_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("Stat").isValid())
|
|
m_status = static_cast<Stat>(m_dataPoints.value("Stat").toUInt16());
|
|
|
|
if (m_dataPoints.value("StatVend").isValid())
|
|
m_vendorStatus = m_dataPoints.value("StatVend").toUInt16();
|
|
|
|
if (m_dataPoints.value("Evt").isValid())
|
|
m_events = static_cast<EvtFlags>(m_dataPoints.value("Evt").toUInt32());
|
|
|
|
if (m_dataPoints.value("EvtVend").isValid())
|
|
m_vendorModuleEventFlags = m_dataPoints.value("EvtVend").toUInt32();
|
|
|
|
if (m_dataPoints.value("Ctl").isValid())
|
|
m_control = m_dataPoints.value("Ctl").toUInt16();
|
|
|
|
if (m_dataPoints.value("CtlVend").isValid())
|
|
m_vendorControl = m_dataPoints.value("CtlVend").toUInt32();
|
|
|
|
if (m_dataPoints.value("CtlVal").isValid())
|
|
m_controlValue = m_dataPoints.value("CtlVal").toInt32();
|
|
|
|
if (m_dataPoints.value("Tms").isValid())
|
|
m_timestamp = m_dataPoints.value("Tms").toUInt32();
|
|
|
|
if (m_dataPoints.value("OutA").isValid())
|
|
m_outputCurrent = m_dataPoints.value("OutA").toFloatWithSSF(m_a_SF);
|
|
|
|
if (m_dataPoints.value("OutV").isValid())
|
|
m_outputVoltage = m_dataPoints.value("OutV").toFloatWithSSF(m_v_SF);
|
|
|
|
if (m_dataPoints.value("OutWh").isValid())
|
|
m_outputEnergy = m_dataPoints.value("OutWh").toFloatWithSSF(m_wh_SF);
|
|
|
|
if (m_dataPoints.value("OutPw").isValid())
|
|
m_outputPower = m_dataPoints.value("OutPw").toFloatWithSSF(m_w_SF);
|
|
|
|
if (m_dataPoints.value("Tmp").isValid())
|
|
m_temp = m_dataPoints.value("Tmp").toInt16();
|
|
|
|
if (m_dataPoints.value("InA").isValid())
|
|
m_inputCurrent = m_dataPoints.value("InA").toFloatWithSSF(m_a_SF);
|
|
|
|
if (m_dataPoints.value("InV").isValid())
|
|
m_inputVoltage = m_dataPoints.value("InV").toFloatWithSSF(m_v_SF);
|
|
|
|
if (m_dataPoints.value("InWh").isValid())
|
|
m_inputEnergy = m_dataPoints.value("InWh").toFloatWithSSF(m_wh_SF);
|
|
|
|
if (m_dataPoints.value("InW").isValid())
|
|
m_inputPower = m_dataPoints.value("InW").toFloatWithSSF(m_w_SF);
|
|
|
|
|
|
qCDebug(dcSunSpecModelData()) << this;
|
|
}
|
|
|
|
QDebug operator<<(QDebug debug, SunSpecSolarModuleModel *model)
|
|
{
|
|
debug.nospace().noquote() << "SunSpecSolarModuleModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n";
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Stat") << "-->";
|
|
if (model->dataPoints().value("Stat").isValid()) {
|
|
debug.nospace().noquote() << model->status() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("StatVend") << "-->";
|
|
if (model->dataPoints().value("StatVend").isValid()) {
|
|
debug.nospace().noquote() << model->vendorStatus() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Evt") << "-->";
|
|
if (model->dataPoints().value("Evt").isValid()) {
|
|
debug.nospace().noquote() << model->events() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("EvtVend") << "-->";
|
|
if (model->dataPoints().value("EvtVend").isValid()) {
|
|
debug.nospace().noquote() << model->vendorModuleEventFlags() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Ctl") << "-->";
|
|
if (model->dataPoints().value("Ctl").isValid()) {
|
|
debug.nospace().noquote() << model->control() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CtlVend") << "-->";
|
|
if (model->dataPoints().value("CtlVend").isValid()) {
|
|
debug.nospace().noquote() << model->vendorControl() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CtlVal") << "-->";
|
|
if (model->dataPoints().value("CtlVal").isValid()) {
|
|
debug.nospace().noquote() << model->controlValue() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Tms") << "-->";
|
|
if (model->dataPoints().value("Tms").isValid()) {
|
|
debug.nospace().noquote() << model->timestamp() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("OutA") << "-->";
|
|
if (model->dataPoints().value("OutA").isValid()) {
|
|
debug.nospace().noquote() << model->outputCurrent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("OutV") << "-->";
|
|
if (model->dataPoints().value("OutV").isValid()) {
|
|
debug.nospace().noquote() << model->outputVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("OutWh") << "-->";
|
|
if (model->dataPoints().value("OutWh").isValid()) {
|
|
debug.nospace().noquote() << model->outputEnergy() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("OutPw") << "-->";
|
|
if (model->dataPoints().value("OutPw").isValid()) {
|
|
debug.nospace().noquote() << model->outputPower() << "\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("InA") << "-->";
|
|
if (model->dataPoints().value("InA").isValid()) {
|
|
debug.nospace().noquote() << model->inputCurrent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("InV") << "-->";
|
|
if (model->dataPoints().value("InV").isValid()) {
|
|
debug.nospace().noquote() << model->inputVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("InWh") << "-->";
|
|
if (model->dataPoints().value("InWh").isValid()) {
|
|
debug.nospace().noquote() << model->inputEnergy() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("InW") << "-->";
|
|
if (model->dataPoints().value("InW").isValid()) {
|
|
debug.nospace().noquote() << model->inputPower() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
|
|
return debug.space().quote();
|
|
}
|