1605 lines
68 KiB
C++
1605 lines
68 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 "sunspecbatterymodel.h"
|
|
#include "sunspecconnection.h"
|
|
|
|
SunSpecBatteryModel::SunSpecBatteryModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) :
|
|
SunSpecModel(connection, modbusStartRegister, 802, modelLength, byteOrder, parent)
|
|
{
|
|
m_modelBlockType = SunSpecModel::ModelBlockTypeFixed;
|
|
|
|
initDataPoints();
|
|
}
|
|
|
|
SunSpecBatteryModel::~SunSpecBatteryModel()
|
|
{
|
|
|
|
}
|
|
|
|
QString SunSpecBatteryModel::name() const
|
|
{
|
|
return "battery";
|
|
}
|
|
|
|
QString SunSpecBatteryModel::description() const
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QString SunSpecBatteryModel::label() const
|
|
{
|
|
return "Battery Base Model";
|
|
}
|
|
|
|
float SunSpecBatteryModel::nameplateChargeCapacity() const
|
|
{
|
|
return m_nameplateChargeCapacity;
|
|
}
|
|
float SunSpecBatteryModel::nameplateEnergyCapacity() const
|
|
{
|
|
return m_nameplateEnergyCapacity;
|
|
}
|
|
float SunSpecBatteryModel::nameplateMaxChargeRate() const
|
|
{
|
|
return m_nameplateMaxChargeRate;
|
|
}
|
|
float SunSpecBatteryModel::nameplateMaxDischargeRate() const
|
|
{
|
|
return m_nameplateMaxDischargeRate;
|
|
}
|
|
float SunSpecBatteryModel::selfDischargeRate() const
|
|
{
|
|
return m_selfDischargeRate;
|
|
}
|
|
float SunSpecBatteryModel::nameplateMaxSoC() const
|
|
{
|
|
return m_nameplateMaxSoC;
|
|
}
|
|
float SunSpecBatteryModel::nameplateMinSoC() const
|
|
{
|
|
return m_nameplateMinSoC;
|
|
}
|
|
float SunSpecBatteryModel::maxReservePercent() const
|
|
{
|
|
return m_maxReservePercent;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setMaxReservePercent(float maxReservePercent)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("SocRsvMax");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromFloatWithSSF(maxReservePercent, m_soC_SF, dp.dataType());
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
float SunSpecBatteryModel::minReservePercent() const
|
|
{
|
|
return m_minReservePercent;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setMinReservePercent(float minReservePercent)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("SoCRsvMin");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromFloatWithSSF(minReservePercent, m_soC_SF, dp.dataType());
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
float SunSpecBatteryModel::stateOfCharge() const
|
|
{
|
|
return m_stateOfCharge;
|
|
}
|
|
float SunSpecBatteryModel::depthOfDischarge() const
|
|
{
|
|
return m_depthOfDischarge;
|
|
}
|
|
float SunSpecBatteryModel::stateOfHealth() const
|
|
{
|
|
return m_stateOfHealth;
|
|
}
|
|
quint32 SunSpecBatteryModel::cycleCount() const
|
|
{
|
|
return m_cycleCount;
|
|
}
|
|
SunSpecBatteryModel::Chast SunSpecBatteryModel::chargeStatus() const
|
|
{
|
|
return m_chargeStatus;
|
|
}
|
|
SunSpecBatteryModel::Locremctl SunSpecBatteryModel::controlMode() const
|
|
{
|
|
return m_controlMode;
|
|
}
|
|
quint16 SunSpecBatteryModel::batteryHeartbeat() const
|
|
{
|
|
return m_batteryHeartbeat;
|
|
}
|
|
quint16 SunSpecBatteryModel::controllerHeartbeat() const
|
|
{
|
|
return m_controllerHeartbeat;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setControllerHeartbeat(quint16 controllerHeartbeat)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("CtrlHb");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt16(controllerHeartbeat);
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
quint16 SunSpecBatteryModel::alarmReset() const
|
|
{
|
|
return m_alarmReset;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setAlarmReset(quint16 alarmReset)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("AlmRst");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt16(alarmReset);
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
SunSpecBatteryModel::Typ SunSpecBatteryModel::batteryType() const
|
|
{
|
|
return m_batteryType;
|
|
}
|
|
SunSpecBatteryModel::State SunSpecBatteryModel::stateOfTheBatteryBank() const
|
|
{
|
|
return m_stateOfTheBatteryBank;
|
|
}
|
|
quint16 SunSpecBatteryModel::vendorBatteryBankState() const
|
|
{
|
|
return m_vendorBatteryBankState;
|
|
}
|
|
quint32 SunSpecBatteryModel::warrantyDate() const
|
|
{
|
|
return m_warrantyDate;
|
|
}
|
|
SunSpecBatteryModel::Evt1Flags SunSpecBatteryModel::batteryEvent1Bitfield() const
|
|
{
|
|
return m_batteryEvent1Bitfield;
|
|
}
|
|
quint32 SunSpecBatteryModel::batteryEvent2Bitfield() const
|
|
{
|
|
return m_batteryEvent2Bitfield;
|
|
}
|
|
quint32 SunSpecBatteryModel::vendorEventBitfield1() const
|
|
{
|
|
return m_vendorEventBitfield1;
|
|
}
|
|
quint32 SunSpecBatteryModel::vendorEventBitfield2() const
|
|
{
|
|
return m_vendorEventBitfield2;
|
|
}
|
|
float SunSpecBatteryModel::externalBatteryVoltage() const
|
|
{
|
|
return m_externalBatteryVoltage;
|
|
}
|
|
float SunSpecBatteryModel::maxBatteryVoltage() const
|
|
{
|
|
return m_maxBatteryVoltage;
|
|
}
|
|
float SunSpecBatteryModel::minBatteryVoltage() const
|
|
{
|
|
return m_minBatteryVoltage;
|
|
}
|
|
float SunSpecBatteryModel::maxCellVoltage() const
|
|
{
|
|
return m_maxCellVoltage;
|
|
}
|
|
quint16 SunSpecBatteryModel::maxCellVoltageString() const
|
|
{
|
|
return m_maxCellVoltageString;
|
|
}
|
|
quint16 SunSpecBatteryModel::maxCellVoltageModule() const
|
|
{
|
|
return m_maxCellVoltageModule;
|
|
}
|
|
float SunSpecBatteryModel::minCellVoltage() const
|
|
{
|
|
return m_minCellVoltage;
|
|
}
|
|
quint16 SunSpecBatteryModel::minCellVoltageString() const
|
|
{
|
|
return m_minCellVoltageString;
|
|
}
|
|
quint16 SunSpecBatteryModel::minCellVoltageModule() const
|
|
{
|
|
return m_minCellVoltageModule;
|
|
}
|
|
float SunSpecBatteryModel::averageCellVoltage() const
|
|
{
|
|
return m_averageCellVoltage;
|
|
}
|
|
float SunSpecBatteryModel::totalDcCurrent() const
|
|
{
|
|
return m_totalDcCurrent;
|
|
}
|
|
float SunSpecBatteryModel::maxChargeCurrent() const
|
|
{
|
|
return m_maxChargeCurrent;
|
|
}
|
|
float SunSpecBatteryModel::maxDischargeCurrent() const
|
|
{
|
|
return m_maxDischargeCurrent;
|
|
}
|
|
float SunSpecBatteryModel::totalPower() const
|
|
{
|
|
return m_totalPower;
|
|
}
|
|
SunSpecBatteryModel::Reqinvstate SunSpecBatteryModel::inverterStateRequest() const
|
|
{
|
|
return m_inverterStateRequest;
|
|
}
|
|
float SunSpecBatteryModel::batteryPowerRequest() const
|
|
{
|
|
return m_batteryPowerRequest;
|
|
}
|
|
SunSpecBatteryModel::Setop SunSpecBatteryModel::setOperation() const
|
|
{
|
|
return m_setOperation;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setSetOperation(Setop setOperation)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("SetOp");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt16(static_cast<quint16>(setOperation));
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
SunSpecBatteryModel::Setinvstate SunSpecBatteryModel::setInverterState() const
|
|
{
|
|
return m_setInverterState;
|
|
}
|
|
|
|
QModbusReply *SunSpecBatteryModel::setSetInverterState(Setinvstate setInverterState)
|
|
{
|
|
if (!m_initialized)
|
|
return nullptr;
|
|
|
|
SunSpecDataPoint dp = m_dataPoints.value("SetInvState");
|
|
QVector<quint16> registers = SunSpecDataPoint::convertFromUInt16(static_cast<quint16>(setInverterState));
|
|
|
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length());
|
|
request.setValues(registers);
|
|
|
|
return m_connection->modbusTcpClient()->sendWriteRequest(request, m_connection->slaveId());
|
|
}
|
|
qint16 SunSpecBatteryModel::aHRtg_SF() const
|
|
{
|
|
return m_aHRtg_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::wHRtg_SF() const
|
|
{
|
|
return m_wHRtg_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::wChaDisChaMax_SF() const
|
|
{
|
|
return m_wChaDisChaMax_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::disChaRte_SF() const
|
|
{
|
|
return m_disChaRte_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::soC_SF() const
|
|
{
|
|
return m_soC_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::doD_SF() const
|
|
{
|
|
return m_doD_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::soH_SF() const
|
|
{
|
|
return m_soH_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::v_SF() const
|
|
{
|
|
return m_v_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::cellV_SF() const
|
|
{
|
|
return m_cellV_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::a_SF() const
|
|
{
|
|
return m_a_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::aMax_SF() const
|
|
{
|
|
return m_aMax_SF;
|
|
}
|
|
qint16 SunSpecBatteryModel::w_SF() const
|
|
{
|
|
return m_w_SF;
|
|
}
|
|
void SunSpecBatteryModel::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 nameplateChargeCapacityDataPoint;
|
|
nameplateChargeCapacityDataPoint.setName("AHRtg");
|
|
nameplateChargeCapacityDataPoint.setLabel("Nameplate Charge Capacity");
|
|
nameplateChargeCapacityDataPoint.setDescription("Nameplate charge capacity in amp-hours.");
|
|
nameplateChargeCapacityDataPoint.setUnits("Ah");
|
|
nameplateChargeCapacityDataPoint.setMandatory(true);
|
|
nameplateChargeCapacityDataPoint.setSize(1);
|
|
nameplateChargeCapacityDataPoint.setAddressOffset(2);
|
|
nameplateChargeCapacityDataPoint.setBlockOffset(0);
|
|
nameplateChargeCapacityDataPoint.setScaleFactorName("AHRtg_SF");
|
|
nameplateChargeCapacityDataPoint.setSunSpecDataType("uint16");
|
|
nameplateChargeCapacityDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateChargeCapacityDataPoint.name(), nameplateChargeCapacityDataPoint);
|
|
|
|
SunSpecDataPoint nameplateEnergyCapacityDataPoint;
|
|
nameplateEnergyCapacityDataPoint.setName("WHRtg");
|
|
nameplateEnergyCapacityDataPoint.setLabel("Nameplate Energy Capacity");
|
|
nameplateEnergyCapacityDataPoint.setDescription("Nameplate energy capacity in DC watt-hours.");
|
|
nameplateEnergyCapacityDataPoint.setUnits("Wh");
|
|
nameplateEnergyCapacityDataPoint.setMandatory(true);
|
|
nameplateEnergyCapacityDataPoint.setSize(1);
|
|
nameplateEnergyCapacityDataPoint.setAddressOffset(3);
|
|
nameplateEnergyCapacityDataPoint.setBlockOffset(1);
|
|
nameplateEnergyCapacityDataPoint.setScaleFactorName("WHRtg_SF");
|
|
nameplateEnergyCapacityDataPoint.setSunSpecDataType("uint16");
|
|
nameplateEnergyCapacityDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateEnergyCapacityDataPoint.name(), nameplateEnergyCapacityDataPoint);
|
|
|
|
SunSpecDataPoint nameplateMaxChargeRateDataPoint;
|
|
nameplateMaxChargeRateDataPoint.setName("WChaRteMax");
|
|
nameplateMaxChargeRateDataPoint.setLabel("Nameplate Max Charge Rate");
|
|
nameplateMaxChargeRateDataPoint.setDescription("Maximum rate of energy transfer into the storage device in DC watts.");
|
|
nameplateMaxChargeRateDataPoint.setUnits("W");
|
|
nameplateMaxChargeRateDataPoint.setMandatory(true);
|
|
nameplateMaxChargeRateDataPoint.setSize(1);
|
|
nameplateMaxChargeRateDataPoint.setAddressOffset(4);
|
|
nameplateMaxChargeRateDataPoint.setBlockOffset(2);
|
|
nameplateMaxChargeRateDataPoint.setScaleFactorName("WChaDisChaMax_SF");
|
|
nameplateMaxChargeRateDataPoint.setSunSpecDataType("uint16");
|
|
nameplateMaxChargeRateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateMaxChargeRateDataPoint.name(), nameplateMaxChargeRateDataPoint);
|
|
|
|
SunSpecDataPoint nameplateMaxDischargeRateDataPoint;
|
|
nameplateMaxDischargeRateDataPoint.setName("WDisChaRteMax");
|
|
nameplateMaxDischargeRateDataPoint.setLabel("Nameplate Max Discharge Rate");
|
|
nameplateMaxDischargeRateDataPoint.setDescription("Maximum rate of energy transfer out of the storage device in DC watts.");
|
|
nameplateMaxDischargeRateDataPoint.setUnits("W");
|
|
nameplateMaxDischargeRateDataPoint.setMandatory(true);
|
|
nameplateMaxDischargeRateDataPoint.setSize(1);
|
|
nameplateMaxDischargeRateDataPoint.setAddressOffset(5);
|
|
nameplateMaxDischargeRateDataPoint.setBlockOffset(3);
|
|
nameplateMaxDischargeRateDataPoint.setScaleFactorName("WChaDisChaMax_SF");
|
|
nameplateMaxDischargeRateDataPoint.setSunSpecDataType("uint16");
|
|
nameplateMaxDischargeRateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateMaxDischargeRateDataPoint.name(), nameplateMaxDischargeRateDataPoint);
|
|
|
|
SunSpecDataPoint selfDischargeRateDataPoint;
|
|
selfDischargeRateDataPoint.setName("DisChaRte");
|
|
selfDischargeRateDataPoint.setLabel("Self Discharge Rate");
|
|
selfDischargeRateDataPoint.setDescription("Self discharge rate. Percentage of capacity (WHRtg) discharged per day.");
|
|
selfDischargeRateDataPoint.setUnits("%WHRtg");
|
|
selfDischargeRateDataPoint.setSize(1);
|
|
selfDischargeRateDataPoint.setAddressOffset(6);
|
|
selfDischargeRateDataPoint.setBlockOffset(4);
|
|
selfDischargeRateDataPoint.setScaleFactorName("DisChaRte_SF");
|
|
selfDischargeRateDataPoint.setSunSpecDataType("uint16");
|
|
selfDischargeRateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(selfDischargeRateDataPoint.name(), selfDischargeRateDataPoint);
|
|
|
|
SunSpecDataPoint nameplateMaxSoCDataPoint;
|
|
nameplateMaxSoCDataPoint.setName("SoCMax");
|
|
nameplateMaxSoCDataPoint.setLabel("Nameplate Max SoC");
|
|
nameplateMaxSoCDataPoint.setDescription("Manufacturer maximum state of charge, expressed as a percentage.");
|
|
nameplateMaxSoCDataPoint.setUnits("%WHRtg");
|
|
nameplateMaxSoCDataPoint.setSize(1);
|
|
nameplateMaxSoCDataPoint.setAddressOffset(7);
|
|
nameplateMaxSoCDataPoint.setBlockOffset(5);
|
|
nameplateMaxSoCDataPoint.setScaleFactorName("SoC_SF");
|
|
nameplateMaxSoCDataPoint.setSunSpecDataType("uint16");
|
|
nameplateMaxSoCDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateMaxSoCDataPoint.name(), nameplateMaxSoCDataPoint);
|
|
|
|
SunSpecDataPoint nameplateMinSoCDataPoint;
|
|
nameplateMinSoCDataPoint.setName("SoCMin");
|
|
nameplateMinSoCDataPoint.setLabel("Nameplate Min SoC");
|
|
nameplateMinSoCDataPoint.setDescription("Manufacturer minimum state of charge, expressed as a percentage.");
|
|
nameplateMinSoCDataPoint.setUnits("%WHRtg");
|
|
nameplateMinSoCDataPoint.setSize(1);
|
|
nameplateMinSoCDataPoint.setAddressOffset(8);
|
|
nameplateMinSoCDataPoint.setBlockOffset(6);
|
|
nameplateMinSoCDataPoint.setScaleFactorName("SoC_SF");
|
|
nameplateMinSoCDataPoint.setSunSpecDataType("uint16");
|
|
nameplateMinSoCDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(nameplateMinSoCDataPoint.name(), nameplateMinSoCDataPoint);
|
|
|
|
SunSpecDataPoint maxReservePercentDataPoint;
|
|
maxReservePercentDataPoint.setName("SocRsvMax");
|
|
maxReservePercentDataPoint.setLabel("Max Reserve Percent");
|
|
maxReservePercentDataPoint.setDescription("Setpoint for maximum reserve for storage as a percentage of the nominal maximum storage.");
|
|
maxReservePercentDataPoint.setUnits("%WHRtg");
|
|
maxReservePercentDataPoint.setSize(1);
|
|
maxReservePercentDataPoint.setAddressOffset(9);
|
|
maxReservePercentDataPoint.setBlockOffset(7);
|
|
maxReservePercentDataPoint.setScaleFactorName("SoC_SF");
|
|
maxReservePercentDataPoint.setSunSpecDataType("uint16");
|
|
maxReservePercentDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
maxReservePercentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxReservePercentDataPoint.name(), maxReservePercentDataPoint);
|
|
|
|
SunSpecDataPoint minReservePercentDataPoint;
|
|
minReservePercentDataPoint.setName("SoCRsvMin");
|
|
minReservePercentDataPoint.setLabel("Min Reserve Percent");
|
|
minReservePercentDataPoint.setDescription("Setpoint for minimum reserve for storage as a percentage of the nominal maximum storage.");
|
|
minReservePercentDataPoint.setUnits("%WHRtg");
|
|
minReservePercentDataPoint.setSize(1);
|
|
minReservePercentDataPoint.setAddressOffset(10);
|
|
minReservePercentDataPoint.setBlockOffset(8);
|
|
minReservePercentDataPoint.setScaleFactorName("SoC_SF");
|
|
minReservePercentDataPoint.setSunSpecDataType("uint16");
|
|
minReservePercentDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
minReservePercentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(minReservePercentDataPoint.name(), minReservePercentDataPoint);
|
|
|
|
SunSpecDataPoint stateOfChargeDataPoint;
|
|
stateOfChargeDataPoint.setName("SoC");
|
|
stateOfChargeDataPoint.setLabel("State of Charge");
|
|
stateOfChargeDataPoint.setDescription("State of charge, expressed as a percentage.");
|
|
stateOfChargeDataPoint.setUnits("%WHRtg");
|
|
stateOfChargeDataPoint.setMandatory(true);
|
|
stateOfChargeDataPoint.setSize(1);
|
|
stateOfChargeDataPoint.setAddressOffset(11);
|
|
stateOfChargeDataPoint.setBlockOffset(9);
|
|
stateOfChargeDataPoint.setScaleFactorName("SoC_SF");
|
|
stateOfChargeDataPoint.setSunSpecDataType("uint16");
|
|
stateOfChargeDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(stateOfChargeDataPoint.name(), stateOfChargeDataPoint);
|
|
|
|
SunSpecDataPoint depthOfDischargeDataPoint;
|
|
depthOfDischargeDataPoint.setName("DoD");
|
|
depthOfDischargeDataPoint.setLabel("Depth of Discharge");
|
|
depthOfDischargeDataPoint.setDescription("Depth of discharge, expressed as a percentage.");
|
|
depthOfDischargeDataPoint.setUnits("%");
|
|
depthOfDischargeDataPoint.setSize(1);
|
|
depthOfDischargeDataPoint.setAddressOffset(12);
|
|
depthOfDischargeDataPoint.setBlockOffset(10);
|
|
depthOfDischargeDataPoint.setScaleFactorName("DoD_SF");
|
|
depthOfDischargeDataPoint.setSunSpecDataType("uint16");
|
|
depthOfDischargeDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(depthOfDischargeDataPoint.name(), depthOfDischargeDataPoint);
|
|
|
|
SunSpecDataPoint stateOfHealthDataPoint;
|
|
stateOfHealthDataPoint.setName("SoH");
|
|
stateOfHealthDataPoint.setLabel("State of Health");
|
|
stateOfHealthDataPoint.setDescription("Percentage of battery life remaining.");
|
|
stateOfHealthDataPoint.setUnits("%");
|
|
stateOfHealthDataPoint.setSize(1);
|
|
stateOfHealthDataPoint.setAddressOffset(13);
|
|
stateOfHealthDataPoint.setBlockOffset(11);
|
|
stateOfHealthDataPoint.setScaleFactorName("SoH_SF");
|
|
stateOfHealthDataPoint.setSunSpecDataType("uint16");
|
|
stateOfHealthDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(stateOfHealthDataPoint.name(), stateOfHealthDataPoint);
|
|
|
|
SunSpecDataPoint cycleCountDataPoint;
|
|
cycleCountDataPoint.setName("NCyc");
|
|
cycleCountDataPoint.setLabel("Cycle Count");
|
|
cycleCountDataPoint.setDescription("Number of cycles executed in the battery.");
|
|
cycleCountDataPoint.setSize(2);
|
|
cycleCountDataPoint.setAddressOffset(14);
|
|
cycleCountDataPoint.setBlockOffset(12);
|
|
cycleCountDataPoint.setSunSpecDataType("uint32");
|
|
cycleCountDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(cycleCountDataPoint.name(), cycleCountDataPoint);
|
|
|
|
SunSpecDataPoint chargeStatusDataPoint;
|
|
chargeStatusDataPoint.setName("ChaSt");
|
|
chargeStatusDataPoint.setLabel("Charge Status");
|
|
chargeStatusDataPoint.setDescription("Charge status of storage device. Enumeration.");
|
|
chargeStatusDataPoint.setSize(1);
|
|
chargeStatusDataPoint.setAddressOffset(16);
|
|
chargeStatusDataPoint.setBlockOffset(14);
|
|
chargeStatusDataPoint.setSunSpecDataType("enum16");
|
|
chargeStatusDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(chargeStatusDataPoint.name(), chargeStatusDataPoint);
|
|
|
|
SunSpecDataPoint controlModeDataPoint;
|
|
controlModeDataPoint.setName("LocRemCtl");
|
|
controlModeDataPoint.setLabel("Control Mode");
|
|
controlModeDataPoint.setDescription("Battery control mode. Enumeration.");
|
|
controlModeDataPoint.setMandatory(true);
|
|
controlModeDataPoint.setSize(1);
|
|
controlModeDataPoint.setAddressOffset(17);
|
|
controlModeDataPoint.setBlockOffset(15);
|
|
controlModeDataPoint.setSunSpecDataType("enum16");
|
|
controlModeDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(controlModeDataPoint.name(), controlModeDataPoint);
|
|
|
|
SunSpecDataPoint batteryHeartbeatDataPoint;
|
|
batteryHeartbeatDataPoint.setName("Hb");
|
|
batteryHeartbeatDataPoint.setLabel("Battery Heartbeat");
|
|
batteryHeartbeatDataPoint.setDescription("Value is incremented every second with periodic resets to zero.");
|
|
batteryHeartbeatDataPoint.setSize(1);
|
|
batteryHeartbeatDataPoint.setAddressOffset(18);
|
|
batteryHeartbeatDataPoint.setBlockOffset(16);
|
|
batteryHeartbeatDataPoint.setSunSpecDataType("uint16");
|
|
batteryHeartbeatDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(batteryHeartbeatDataPoint.name(), batteryHeartbeatDataPoint);
|
|
|
|
SunSpecDataPoint controllerHeartbeatDataPoint;
|
|
controllerHeartbeatDataPoint.setName("CtrlHb");
|
|
controllerHeartbeatDataPoint.setLabel("Controller Heartbeat");
|
|
controllerHeartbeatDataPoint.setDescription("Value is incremented every second with periodic resets to zero.");
|
|
controllerHeartbeatDataPoint.setSize(1);
|
|
controllerHeartbeatDataPoint.setAddressOffset(19);
|
|
controllerHeartbeatDataPoint.setBlockOffset(17);
|
|
controllerHeartbeatDataPoint.setSunSpecDataType("uint16");
|
|
controllerHeartbeatDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
controllerHeartbeatDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(controllerHeartbeatDataPoint.name(), controllerHeartbeatDataPoint);
|
|
|
|
SunSpecDataPoint alarmResetDataPoint;
|
|
alarmResetDataPoint.setName("AlmRst");
|
|
alarmResetDataPoint.setLabel("Alarm Reset");
|
|
alarmResetDataPoint.setDescription("Used to reset any latched alarms. 1 = Reset.");
|
|
alarmResetDataPoint.setMandatory(true);
|
|
alarmResetDataPoint.setSize(1);
|
|
alarmResetDataPoint.setAddressOffset(20);
|
|
alarmResetDataPoint.setBlockOffset(18);
|
|
alarmResetDataPoint.setSunSpecDataType("uint16");
|
|
alarmResetDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
alarmResetDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(alarmResetDataPoint.name(), alarmResetDataPoint);
|
|
|
|
SunSpecDataPoint batteryTypeDataPoint;
|
|
batteryTypeDataPoint.setName("Typ");
|
|
batteryTypeDataPoint.setLabel("Battery Type");
|
|
batteryTypeDataPoint.setDescription("Type of battery. Enumeration.");
|
|
batteryTypeDataPoint.setMandatory(true);
|
|
batteryTypeDataPoint.setSize(1);
|
|
batteryTypeDataPoint.setAddressOffset(21);
|
|
batteryTypeDataPoint.setBlockOffset(19);
|
|
batteryTypeDataPoint.setSunSpecDataType("enum16");
|
|
batteryTypeDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(batteryTypeDataPoint.name(), batteryTypeDataPoint);
|
|
|
|
SunSpecDataPoint stateOfTheBatteryBankDataPoint;
|
|
stateOfTheBatteryBankDataPoint.setName("State");
|
|
stateOfTheBatteryBankDataPoint.setLabel("State of the Battery Bank");
|
|
stateOfTheBatteryBankDataPoint.setDescription("State of the battery bank. Enumeration.");
|
|
stateOfTheBatteryBankDataPoint.setMandatory(true);
|
|
stateOfTheBatteryBankDataPoint.setSize(1);
|
|
stateOfTheBatteryBankDataPoint.setAddressOffset(22);
|
|
stateOfTheBatteryBankDataPoint.setBlockOffset(20);
|
|
stateOfTheBatteryBankDataPoint.setSunSpecDataType("enum16");
|
|
stateOfTheBatteryBankDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(stateOfTheBatteryBankDataPoint.name(), stateOfTheBatteryBankDataPoint);
|
|
|
|
SunSpecDataPoint vendorBatteryBankStateDataPoint;
|
|
vendorBatteryBankStateDataPoint.setName("StateVnd");
|
|
vendorBatteryBankStateDataPoint.setLabel("Vendor Battery Bank State");
|
|
vendorBatteryBankStateDataPoint.setDescription("Vendor specific battery bank state. Enumeration.");
|
|
vendorBatteryBankStateDataPoint.setSize(1);
|
|
vendorBatteryBankStateDataPoint.setAddressOffset(23);
|
|
vendorBatteryBankStateDataPoint.setBlockOffset(21);
|
|
vendorBatteryBankStateDataPoint.setSunSpecDataType("enum16");
|
|
vendorBatteryBankStateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorBatteryBankStateDataPoint.name(), vendorBatteryBankStateDataPoint);
|
|
|
|
SunSpecDataPoint warrantyDateDataPoint;
|
|
warrantyDateDataPoint.setName("WarrDt");
|
|
warrantyDateDataPoint.setLabel("Warranty Date");
|
|
warrantyDateDataPoint.setDescription("Date the device warranty expires.");
|
|
warrantyDateDataPoint.setSize(2);
|
|
warrantyDateDataPoint.setAddressOffset(24);
|
|
warrantyDateDataPoint.setBlockOffset(22);
|
|
warrantyDateDataPoint.setSunSpecDataType("uint32");
|
|
warrantyDateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(warrantyDateDataPoint.name(), warrantyDateDataPoint);
|
|
|
|
SunSpecDataPoint batteryEvent1BitfieldDataPoint;
|
|
batteryEvent1BitfieldDataPoint.setName("Evt1");
|
|
batteryEvent1BitfieldDataPoint.setLabel("Battery Event 1 Bitfield");
|
|
batteryEvent1BitfieldDataPoint.setDescription("Alarms and warnings. Bit flags.");
|
|
batteryEvent1BitfieldDataPoint.setMandatory(true);
|
|
batteryEvent1BitfieldDataPoint.setSize(2);
|
|
batteryEvent1BitfieldDataPoint.setAddressOffset(26);
|
|
batteryEvent1BitfieldDataPoint.setBlockOffset(24);
|
|
batteryEvent1BitfieldDataPoint.setSunSpecDataType("bitfield32");
|
|
batteryEvent1BitfieldDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(batteryEvent1BitfieldDataPoint.name(), batteryEvent1BitfieldDataPoint);
|
|
|
|
SunSpecDataPoint batteryEvent2BitfieldDataPoint;
|
|
batteryEvent2BitfieldDataPoint.setName("Evt2");
|
|
batteryEvent2BitfieldDataPoint.setLabel("Battery Event 2 Bitfield");
|
|
batteryEvent2BitfieldDataPoint.setDescription("Alarms and warnings. Bit flags.");
|
|
batteryEvent2BitfieldDataPoint.setMandatory(true);
|
|
batteryEvent2BitfieldDataPoint.setSize(2);
|
|
batteryEvent2BitfieldDataPoint.setAddressOffset(28);
|
|
batteryEvent2BitfieldDataPoint.setBlockOffset(26);
|
|
batteryEvent2BitfieldDataPoint.setSunSpecDataType("bitfield32");
|
|
batteryEvent2BitfieldDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(batteryEvent2BitfieldDataPoint.name(), batteryEvent2BitfieldDataPoint);
|
|
|
|
SunSpecDataPoint vendorEventBitfield1DataPoint;
|
|
vendorEventBitfield1DataPoint.setName("EvtVnd1");
|
|
vendorEventBitfield1DataPoint.setLabel("Vendor Event Bitfield 1");
|
|
vendorEventBitfield1DataPoint.setDescription("Vendor defined events.");
|
|
vendorEventBitfield1DataPoint.setMandatory(true);
|
|
vendorEventBitfield1DataPoint.setSize(2);
|
|
vendorEventBitfield1DataPoint.setAddressOffset(30);
|
|
vendorEventBitfield1DataPoint.setBlockOffset(28);
|
|
vendorEventBitfield1DataPoint.setSunSpecDataType("bitfield32");
|
|
vendorEventBitfield1DataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorEventBitfield1DataPoint.name(), vendorEventBitfield1DataPoint);
|
|
|
|
SunSpecDataPoint vendorEventBitfield2DataPoint;
|
|
vendorEventBitfield2DataPoint.setName("EvtVnd2");
|
|
vendorEventBitfield2DataPoint.setLabel("Vendor Event Bitfield 2");
|
|
vendorEventBitfield2DataPoint.setDescription("Vendor defined events.");
|
|
vendorEventBitfield2DataPoint.setMandatory(true);
|
|
vendorEventBitfield2DataPoint.setSize(2);
|
|
vendorEventBitfield2DataPoint.setAddressOffset(32);
|
|
vendorEventBitfield2DataPoint.setBlockOffset(30);
|
|
vendorEventBitfield2DataPoint.setSunSpecDataType("bitfield32");
|
|
vendorEventBitfield2DataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(vendorEventBitfield2DataPoint.name(), vendorEventBitfield2DataPoint);
|
|
|
|
SunSpecDataPoint externalBatteryVoltageDataPoint;
|
|
externalBatteryVoltageDataPoint.setName("V");
|
|
externalBatteryVoltageDataPoint.setLabel("External Battery Voltage");
|
|
externalBatteryVoltageDataPoint.setDescription("DC Bus Voltage.");
|
|
externalBatteryVoltageDataPoint.setUnits("V");
|
|
externalBatteryVoltageDataPoint.setMandatory(true);
|
|
externalBatteryVoltageDataPoint.setSize(1);
|
|
externalBatteryVoltageDataPoint.setAddressOffset(34);
|
|
externalBatteryVoltageDataPoint.setBlockOffset(32);
|
|
externalBatteryVoltageDataPoint.setScaleFactorName("V_SF");
|
|
externalBatteryVoltageDataPoint.setSunSpecDataType("uint16");
|
|
externalBatteryVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(externalBatteryVoltageDataPoint.name(), externalBatteryVoltageDataPoint);
|
|
|
|
SunSpecDataPoint maxBatteryVoltageDataPoint;
|
|
maxBatteryVoltageDataPoint.setName("VMax");
|
|
maxBatteryVoltageDataPoint.setLabel("Max Battery Voltage");
|
|
maxBatteryVoltageDataPoint.setDescription("Instantaneous maximum battery voltage.");
|
|
maxBatteryVoltageDataPoint.setUnits("V");
|
|
maxBatteryVoltageDataPoint.setSize(1);
|
|
maxBatteryVoltageDataPoint.setAddressOffset(35);
|
|
maxBatteryVoltageDataPoint.setBlockOffset(33);
|
|
maxBatteryVoltageDataPoint.setScaleFactorName("V_SF");
|
|
maxBatteryVoltageDataPoint.setSunSpecDataType("uint16");
|
|
maxBatteryVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxBatteryVoltageDataPoint.name(), maxBatteryVoltageDataPoint);
|
|
|
|
SunSpecDataPoint minBatteryVoltageDataPoint;
|
|
minBatteryVoltageDataPoint.setName("VMin");
|
|
minBatteryVoltageDataPoint.setLabel("Min Battery Voltage");
|
|
minBatteryVoltageDataPoint.setDescription("Instantaneous minimum battery voltage.");
|
|
minBatteryVoltageDataPoint.setUnits("V");
|
|
minBatteryVoltageDataPoint.setSize(1);
|
|
minBatteryVoltageDataPoint.setAddressOffset(36);
|
|
minBatteryVoltageDataPoint.setBlockOffset(34);
|
|
minBatteryVoltageDataPoint.setScaleFactorName("V_SF");
|
|
minBatteryVoltageDataPoint.setSunSpecDataType("uint16");
|
|
minBatteryVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(minBatteryVoltageDataPoint.name(), minBatteryVoltageDataPoint);
|
|
|
|
SunSpecDataPoint maxCellVoltageDataPoint;
|
|
maxCellVoltageDataPoint.setName("CellVMax");
|
|
maxCellVoltageDataPoint.setLabel("Max Cell Voltage");
|
|
maxCellVoltageDataPoint.setDescription("Maximum voltage for all cells in the bank.");
|
|
maxCellVoltageDataPoint.setUnits("V");
|
|
maxCellVoltageDataPoint.setSize(1);
|
|
maxCellVoltageDataPoint.setAddressOffset(37);
|
|
maxCellVoltageDataPoint.setBlockOffset(35);
|
|
maxCellVoltageDataPoint.setScaleFactorName("CellV_SF");
|
|
maxCellVoltageDataPoint.setSunSpecDataType("uint16");
|
|
maxCellVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxCellVoltageDataPoint.name(), maxCellVoltageDataPoint);
|
|
|
|
SunSpecDataPoint maxCellVoltageStringDataPoint;
|
|
maxCellVoltageStringDataPoint.setName("CellVMaxStr");
|
|
maxCellVoltageStringDataPoint.setLabel("Max Cell Voltage String");
|
|
maxCellVoltageStringDataPoint.setDescription("String containing the cell with maximum voltage.");
|
|
maxCellVoltageStringDataPoint.setSize(1);
|
|
maxCellVoltageStringDataPoint.setAddressOffset(38);
|
|
maxCellVoltageStringDataPoint.setBlockOffset(36);
|
|
maxCellVoltageStringDataPoint.setSunSpecDataType("uint16");
|
|
maxCellVoltageStringDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxCellVoltageStringDataPoint.name(), maxCellVoltageStringDataPoint);
|
|
|
|
SunSpecDataPoint maxCellVoltageModuleDataPoint;
|
|
maxCellVoltageModuleDataPoint.setName("CellVMaxMod");
|
|
maxCellVoltageModuleDataPoint.setLabel("Max Cell Voltage Module");
|
|
maxCellVoltageModuleDataPoint.setDescription("Module containing the cell with maximum voltage.");
|
|
maxCellVoltageModuleDataPoint.setSize(1);
|
|
maxCellVoltageModuleDataPoint.setAddressOffset(39);
|
|
maxCellVoltageModuleDataPoint.setBlockOffset(37);
|
|
maxCellVoltageModuleDataPoint.setSunSpecDataType("uint16");
|
|
maxCellVoltageModuleDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxCellVoltageModuleDataPoint.name(), maxCellVoltageModuleDataPoint);
|
|
|
|
SunSpecDataPoint minCellVoltageDataPoint;
|
|
minCellVoltageDataPoint.setName("CellVMin");
|
|
minCellVoltageDataPoint.setLabel("Min Cell Voltage");
|
|
minCellVoltageDataPoint.setDescription("Minimum voltage for all cells in the bank.");
|
|
minCellVoltageDataPoint.setUnits("V");
|
|
minCellVoltageDataPoint.setSize(1);
|
|
minCellVoltageDataPoint.setAddressOffset(40);
|
|
minCellVoltageDataPoint.setBlockOffset(38);
|
|
minCellVoltageDataPoint.setScaleFactorName("CellV_SF");
|
|
minCellVoltageDataPoint.setSunSpecDataType("uint16");
|
|
minCellVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(minCellVoltageDataPoint.name(), minCellVoltageDataPoint);
|
|
|
|
SunSpecDataPoint minCellVoltageStringDataPoint;
|
|
minCellVoltageStringDataPoint.setName("CellVMinStr");
|
|
minCellVoltageStringDataPoint.setLabel("Min Cell Voltage String");
|
|
minCellVoltageStringDataPoint.setDescription("String containing the cell with minimum voltage.");
|
|
minCellVoltageStringDataPoint.setSize(1);
|
|
minCellVoltageStringDataPoint.setAddressOffset(41);
|
|
minCellVoltageStringDataPoint.setBlockOffset(39);
|
|
minCellVoltageStringDataPoint.setSunSpecDataType("uint16");
|
|
minCellVoltageStringDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(minCellVoltageStringDataPoint.name(), minCellVoltageStringDataPoint);
|
|
|
|
SunSpecDataPoint minCellVoltageModuleDataPoint;
|
|
minCellVoltageModuleDataPoint.setName("CellVMinMod");
|
|
minCellVoltageModuleDataPoint.setLabel("Min Cell Voltage Module");
|
|
minCellVoltageModuleDataPoint.setDescription("Module containing the cell with minimum voltage.");
|
|
minCellVoltageModuleDataPoint.setSize(1);
|
|
minCellVoltageModuleDataPoint.setAddressOffset(42);
|
|
minCellVoltageModuleDataPoint.setBlockOffset(40);
|
|
minCellVoltageModuleDataPoint.setSunSpecDataType("uint16");
|
|
minCellVoltageModuleDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(minCellVoltageModuleDataPoint.name(), minCellVoltageModuleDataPoint);
|
|
|
|
SunSpecDataPoint averageCellVoltageDataPoint;
|
|
averageCellVoltageDataPoint.setName("CellVAvg");
|
|
averageCellVoltageDataPoint.setLabel("Average Cell Voltage");
|
|
averageCellVoltageDataPoint.setDescription("Average cell voltage for all cells in the bank.");
|
|
averageCellVoltageDataPoint.setUnits("V");
|
|
averageCellVoltageDataPoint.setSize(1);
|
|
averageCellVoltageDataPoint.setAddressOffset(43);
|
|
averageCellVoltageDataPoint.setBlockOffset(41);
|
|
averageCellVoltageDataPoint.setScaleFactorName("CellV_SF");
|
|
averageCellVoltageDataPoint.setSunSpecDataType("uint16");
|
|
averageCellVoltageDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(averageCellVoltageDataPoint.name(), averageCellVoltageDataPoint);
|
|
|
|
SunSpecDataPoint totalDcCurrentDataPoint;
|
|
totalDcCurrentDataPoint.setName("A");
|
|
totalDcCurrentDataPoint.setLabel("Total DC Current");
|
|
totalDcCurrentDataPoint.setDescription("Total DC current flowing to/from the battery bank.");
|
|
totalDcCurrentDataPoint.setUnits("A");
|
|
totalDcCurrentDataPoint.setMandatory(true);
|
|
totalDcCurrentDataPoint.setSize(1);
|
|
totalDcCurrentDataPoint.setAddressOffset(44);
|
|
totalDcCurrentDataPoint.setBlockOffset(42);
|
|
totalDcCurrentDataPoint.setScaleFactorName("A_SF");
|
|
totalDcCurrentDataPoint.setSunSpecDataType("int16");
|
|
totalDcCurrentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(totalDcCurrentDataPoint.name(), totalDcCurrentDataPoint);
|
|
|
|
SunSpecDataPoint maxChargeCurrentDataPoint;
|
|
maxChargeCurrentDataPoint.setName("AChaMax");
|
|
maxChargeCurrentDataPoint.setLabel("Max Charge Current");
|
|
maxChargeCurrentDataPoint.setDescription("Instantaneous maximum DC charge current.");
|
|
maxChargeCurrentDataPoint.setUnits("A");
|
|
maxChargeCurrentDataPoint.setSize(1);
|
|
maxChargeCurrentDataPoint.setAddressOffset(45);
|
|
maxChargeCurrentDataPoint.setBlockOffset(43);
|
|
maxChargeCurrentDataPoint.setScaleFactorName("AMax_SF");
|
|
maxChargeCurrentDataPoint.setSunSpecDataType("uint16");
|
|
maxChargeCurrentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxChargeCurrentDataPoint.name(), maxChargeCurrentDataPoint);
|
|
|
|
SunSpecDataPoint maxDischargeCurrentDataPoint;
|
|
maxDischargeCurrentDataPoint.setName("ADisChaMax");
|
|
maxDischargeCurrentDataPoint.setLabel("Max Discharge Current");
|
|
maxDischargeCurrentDataPoint.setDescription("Instantaneous maximum DC discharge current.");
|
|
maxDischargeCurrentDataPoint.setUnits("A");
|
|
maxDischargeCurrentDataPoint.setSize(1);
|
|
maxDischargeCurrentDataPoint.setAddressOffset(46);
|
|
maxDischargeCurrentDataPoint.setBlockOffset(44);
|
|
maxDischargeCurrentDataPoint.setScaleFactorName("AMax_SF");
|
|
maxDischargeCurrentDataPoint.setSunSpecDataType("uint16");
|
|
maxDischargeCurrentDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(maxDischargeCurrentDataPoint.name(), maxDischargeCurrentDataPoint);
|
|
|
|
SunSpecDataPoint totalPowerDataPoint;
|
|
totalPowerDataPoint.setName("W");
|
|
totalPowerDataPoint.setLabel("Total Power");
|
|
totalPowerDataPoint.setDescription("Total power flowing to/from the battery bank.");
|
|
totalPowerDataPoint.setUnits("W");
|
|
totalPowerDataPoint.setMandatory(true);
|
|
totalPowerDataPoint.setSize(1);
|
|
totalPowerDataPoint.setAddressOffset(47);
|
|
totalPowerDataPoint.setBlockOffset(45);
|
|
totalPowerDataPoint.setScaleFactorName("W_SF");
|
|
totalPowerDataPoint.setSunSpecDataType("int16");
|
|
totalPowerDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(totalPowerDataPoint.name(), totalPowerDataPoint);
|
|
|
|
SunSpecDataPoint inverterStateRequestDataPoint;
|
|
inverterStateRequestDataPoint.setName("ReqInvState");
|
|
inverterStateRequestDataPoint.setLabel("Inverter State Request");
|
|
inverterStateRequestDataPoint.setDescription("Request from battery to start or stop the inverter. Enumeration.");
|
|
inverterStateRequestDataPoint.setSize(1);
|
|
inverterStateRequestDataPoint.setAddressOffset(48);
|
|
inverterStateRequestDataPoint.setBlockOffset(46);
|
|
inverterStateRequestDataPoint.setSunSpecDataType("enum16");
|
|
inverterStateRequestDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(inverterStateRequestDataPoint.name(), inverterStateRequestDataPoint);
|
|
|
|
SunSpecDataPoint batteryPowerRequestDataPoint;
|
|
batteryPowerRequestDataPoint.setName("ReqW");
|
|
batteryPowerRequestDataPoint.setLabel("Battery Power Request");
|
|
batteryPowerRequestDataPoint.setDescription("AC Power requested by battery.");
|
|
batteryPowerRequestDataPoint.setUnits("W");
|
|
batteryPowerRequestDataPoint.setSize(1);
|
|
batteryPowerRequestDataPoint.setAddressOffset(49);
|
|
batteryPowerRequestDataPoint.setBlockOffset(47);
|
|
batteryPowerRequestDataPoint.setScaleFactorName("W_SF");
|
|
batteryPowerRequestDataPoint.setSunSpecDataType("int16");
|
|
batteryPowerRequestDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(batteryPowerRequestDataPoint.name(), batteryPowerRequestDataPoint);
|
|
|
|
SunSpecDataPoint setOperationDataPoint;
|
|
setOperationDataPoint.setName("SetOp");
|
|
setOperationDataPoint.setLabel("Set Operation");
|
|
setOperationDataPoint.setDescription("Instruct the battery bank to perform an operation such as connecting. Enumeration.");
|
|
setOperationDataPoint.setMandatory(true);
|
|
setOperationDataPoint.setSize(1);
|
|
setOperationDataPoint.setAddressOffset(50);
|
|
setOperationDataPoint.setBlockOffset(48);
|
|
setOperationDataPoint.setSunSpecDataType("enum16");
|
|
setOperationDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
setOperationDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(setOperationDataPoint.name(), setOperationDataPoint);
|
|
|
|
SunSpecDataPoint setInverterStateDataPoint;
|
|
setInverterStateDataPoint.setName("SetInvState");
|
|
setInverterStateDataPoint.setLabel("Set Inverter State");
|
|
setInverterStateDataPoint.setDescription("Set the current state of the inverter.");
|
|
setInverterStateDataPoint.setMandatory(true);
|
|
setInverterStateDataPoint.setSize(1);
|
|
setInverterStateDataPoint.setAddressOffset(51);
|
|
setInverterStateDataPoint.setBlockOffset(49);
|
|
setInverterStateDataPoint.setSunSpecDataType("enum16");
|
|
setInverterStateDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite);
|
|
setInverterStateDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(setInverterStateDataPoint.name(), setInverterStateDataPoint);
|
|
|
|
SunSpecDataPoint aHRtg_SFDataPoint;
|
|
aHRtg_SFDataPoint.setName("AHRtg_SF");
|
|
aHRtg_SFDataPoint.setDescription("Scale factor for charge capacity.");
|
|
aHRtg_SFDataPoint.setMandatory(true);
|
|
aHRtg_SFDataPoint.setSize(1);
|
|
aHRtg_SFDataPoint.setAddressOffset(52);
|
|
aHRtg_SFDataPoint.setBlockOffset(50);
|
|
aHRtg_SFDataPoint.setSunSpecDataType("sunssf");
|
|
aHRtg_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(aHRtg_SFDataPoint.name(), aHRtg_SFDataPoint);
|
|
|
|
SunSpecDataPoint wHRtg_SFDataPoint;
|
|
wHRtg_SFDataPoint.setName("WHRtg_SF");
|
|
wHRtg_SFDataPoint.setDescription("Scale factor for energy capacity.");
|
|
wHRtg_SFDataPoint.setMandatory(true);
|
|
wHRtg_SFDataPoint.setSize(1);
|
|
wHRtg_SFDataPoint.setAddressOffset(53);
|
|
wHRtg_SFDataPoint.setBlockOffset(51);
|
|
wHRtg_SFDataPoint.setSunSpecDataType("sunssf");
|
|
wHRtg_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(wHRtg_SFDataPoint.name(), wHRtg_SFDataPoint);
|
|
|
|
SunSpecDataPoint wChaDisChaMax_SFDataPoint;
|
|
wChaDisChaMax_SFDataPoint.setName("WChaDisChaMax_SF");
|
|
wChaDisChaMax_SFDataPoint.setDescription("Scale factor for maximum charge and discharge rate.");
|
|
wChaDisChaMax_SFDataPoint.setMandatory(true);
|
|
wChaDisChaMax_SFDataPoint.setSize(1);
|
|
wChaDisChaMax_SFDataPoint.setAddressOffset(54);
|
|
wChaDisChaMax_SFDataPoint.setBlockOffset(52);
|
|
wChaDisChaMax_SFDataPoint.setSunSpecDataType("sunssf");
|
|
wChaDisChaMax_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(wChaDisChaMax_SFDataPoint.name(), wChaDisChaMax_SFDataPoint);
|
|
|
|
SunSpecDataPoint disChaRte_SFDataPoint;
|
|
disChaRte_SFDataPoint.setName("DisChaRte_SF");
|
|
disChaRte_SFDataPoint.setDescription("Scale factor for self discharge rate.");
|
|
disChaRte_SFDataPoint.setSize(1);
|
|
disChaRte_SFDataPoint.setAddressOffset(55);
|
|
disChaRte_SFDataPoint.setBlockOffset(53);
|
|
disChaRte_SFDataPoint.setSunSpecDataType("sunssf");
|
|
disChaRte_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(disChaRte_SFDataPoint.name(), disChaRte_SFDataPoint);
|
|
|
|
SunSpecDataPoint soC_SFDataPoint;
|
|
soC_SFDataPoint.setName("SoC_SF");
|
|
soC_SFDataPoint.setDescription("Scale factor for state of charge values.");
|
|
soC_SFDataPoint.setMandatory(true);
|
|
soC_SFDataPoint.setSize(1);
|
|
soC_SFDataPoint.setAddressOffset(56);
|
|
soC_SFDataPoint.setBlockOffset(54);
|
|
soC_SFDataPoint.setSunSpecDataType("sunssf");
|
|
soC_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(soC_SFDataPoint.name(), soC_SFDataPoint);
|
|
|
|
SunSpecDataPoint doD_SFDataPoint;
|
|
doD_SFDataPoint.setName("DoD_SF");
|
|
doD_SFDataPoint.setDescription("Scale factor for depth of discharge.");
|
|
doD_SFDataPoint.setSize(1);
|
|
doD_SFDataPoint.setAddressOffset(57);
|
|
doD_SFDataPoint.setBlockOffset(55);
|
|
doD_SFDataPoint.setSunSpecDataType("sunssf");
|
|
doD_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(doD_SFDataPoint.name(), doD_SFDataPoint);
|
|
|
|
SunSpecDataPoint soH_SFDataPoint;
|
|
soH_SFDataPoint.setName("SoH_SF");
|
|
soH_SFDataPoint.setDescription("Scale factor for state of health.");
|
|
soH_SFDataPoint.setSize(1);
|
|
soH_SFDataPoint.setAddressOffset(58);
|
|
soH_SFDataPoint.setBlockOffset(56);
|
|
soH_SFDataPoint.setSunSpecDataType("sunssf");
|
|
soH_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(soH_SFDataPoint.name(), soH_SFDataPoint);
|
|
|
|
SunSpecDataPoint v_SFDataPoint;
|
|
v_SFDataPoint.setName("V_SF");
|
|
v_SFDataPoint.setDescription("Scale factor for DC bus voltage.");
|
|
v_SFDataPoint.setMandatory(true);
|
|
v_SFDataPoint.setSize(1);
|
|
v_SFDataPoint.setAddressOffset(59);
|
|
v_SFDataPoint.setBlockOffset(57);
|
|
v_SFDataPoint.setSunSpecDataType("sunssf");
|
|
v_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(v_SFDataPoint.name(), v_SFDataPoint);
|
|
|
|
SunSpecDataPoint cellV_SFDataPoint;
|
|
cellV_SFDataPoint.setName("CellV_SF");
|
|
cellV_SFDataPoint.setDescription("Scale factor for cell voltage.");
|
|
cellV_SFDataPoint.setMandatory(true);
|
|
cellV_SFDataPoint.setSize(1);
|
|
cellV_SFDataPoint.setAddressOffset(60);
|
|
cellV_SFDataPoint.setBlockOffset(58);
|
|
cellV_SFDataPoint.setSunSpecDataType("sunssf");
|
|
cellV_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(cellV_SFDataPoint.name(), cellV_SFDataPoint);
|
|
|
|
SunSpecDataPoint a_SFDataPoint;
|
|
a_SFDataPoint.setName("A_SF");
|
|
a_SFDataPoint.setDescription("Scale factor for DC current.");
|
|
a_SFDataPoint.setMandatory(true);
|
|
a_SFDataPoint.setSize(1);
|
|
a_SFDataPoint.setAddressOffset(61);
|
|
a_SFDataPoint.setBlockOffset(59);
|
|
a_SFDataPoint.setSunSpecDataType("sunssf");
|
|
a_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(a_SFDataPoint.name(), a_SFDataPoint);
|
|
|
|
SunSpecDataPoint aMax_SFDataPoint;
|
|
aMax_SFDataPoint.setName("AMax_SF");
|
|
aMax_SFDataPoint.setDescription("Scale factor for instantaneous DC charge/discharge current.");
|
|
aMax_SFDataPoint.setMandatory(true);
|
|
aMax_SFDataPoint.setSize(1);
|
|
aMax_SFDataPoint.setAddressOffset(62);
|
|
aMax_SFDataPoint.setBlockOffset(60);
|
|
aMax_SFDataPoint.setSunSpecDataType("sunssf");
|
|
aMax_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(aMax_SFDataPoint.name(), aMax_SFDataPoint);
|
|
|
|
SunSpecDataPoint w_SFDataPoint;
|
|
w_SFDataPoint.setName("W_SF");
|
|
w_SFDataPoint.setDescription("Scale factor for AC power request.");
|
|
w_SFDataPoint.setSize(1);
|
|
w_SFDataPoint.setAddressOffset(63);
|
|
w_SFDataPoint.setBlockOffset(61);
|
|
w_SFDataPoint.setSunSpecDataType("sunssf");
|
|
w_SFDataPoint.setByteOrder(m_byteOrder);
|
|
m_dataPoints.insert(w_SFDataPoint.name(), w_SFDataPoint);
|
|
|
|
}
|
|
|
|
void SunSpecBatteryModel::processBlockData()
|
|
{
|
|
// Scale factors
|
|
if (m_dataPoints.value("AHRtg_SF").isValid())
|
|
m_aHRtg_SF = m_dataPoints.value("AHRtg_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("WHRtg_SF").isValid())
|
|
m_wHRtg_SF = m_dataPoints.value("WHRtg_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("WChaDisChaMax_SF").isValid())
|
|
m_wChaDisChaMax_SF = m_dataPoints.value("WChaDisChaMax_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("DisChaRte_SF").isValid())
|
|
m_disChaRte_SF = m_dataPoints.value("DisChaRte_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("SoC_SF").isValid())
|
|
m_soC_SF = m_dataPoints.value("SoC_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("DoD_SF").isValid())
|
|
m_doD_SF = m_dataPoints.value("DoD_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("SoH_SF").isValid())
|
|
m_soH_SF = m_dataPoints.value("SoH_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("V_SF").isValid())
|
|
m_v_SF = m_dataPoints.value("V_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("CellV_SF").isValid())
|
|
m_cellV_SF = m_dataPoints.value("CellV_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("A_SF").isValid())
|
|
m_a_SF = m_dataPoints.value("A_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("AMax_SF").isValid())
|
|
m_aMax_SF = m_dataPoints.value("AMax_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("W_SF").isValid())
|
|
m_w_SF = m_dataPoints.value("W_SF").toInt16();
|
|
|
|
|
|
// Update properties according to the data point type
|
|
if (m_dataPoints.value("AHRtg").isValid())
|
|
m_nameplateChargeCapacity = m_dataPoints.value("AHRtg").toFloatWithSSF(m_aHRtg_SF);
|
|
|
|
if (m_dataPoints.value("WHRtg").isValid())
|
|
m_nameplateEnergyCapacity = m_dataPoints.value("WHRtg").toFloatWithSSF(m_wHRtg_SF);
|
|
|
|
if (m_dataPoints.value("WChaRteMax").isValid())
|
|
m_nameplateMaxChargeRate = m_dataPoints.value("WChaRteMax").toFloatWithSSF(m_wChaDisChaMax_SF);
|
|
|
|
if (m_dataPoints.value("WDisChaRteMax").isValid())
|
|
m_nameplateMaxDischargeRate = m_dataPoints.value("WDisChaRteMax").toFloatWithSSF(m_wChaDisChaMax_SF);
|
|
|
|
if (m_dataPoints.value("DisChaRte").isValid())
|
|
m_selfDischargeRate = m_dataPoints.value("DisChaRte").toFloatWithSSF(m_disChaRte_SF);
|
|
|
|
if (m_dataPoints.value("SoCMax").isValid())
|
|
m_nameplateMaxSoC = m_dataPoints.value("SoCMax").toFloatWithSSF(m_soC_SF);
|
|
|
|
if (m_dataPoints.value("SoCMin").isValid())
|
|
m_nameplateMinSoC = m_dataPoints.value("SoCMin").toFloatWithSSF(m_soC_SF);
|
|
|
|
if (m_dataPoints.value("SocRsvMax").isValid())
|
|
m_maxReservePercent = m_dataPoints.value("SocRsvMax").toFloatWithSSF(m_soC_SF);
|
|
|
|
if (m_dataPoints.value("SoCRsvMin").isValid())
|
|
m_minReservePercent = m_dataPoints.value("SoCRsvMin").toFloatWithSSF(m_soC_SF);
|
|
|
|
if (m_dataPoints.value("SoC").isValid())
|
|
m_stateOfCharge = m_dataPoints.value("SoC").toFloatWithSSF(m_soC_SF);
|
|
|
|
if (m_dataPoints.value("DoD").isValid())
|
|
m_depthOfDischarge = m_dataPoints.value("DoD").toFloatWithSSF(m_doD_SF);
|
|
|
|
if (m_dataPoints.value("SoH").isValid())
|
|
m_stateOfHealth = m_dataPoints.value("SoH").toFloatWithSSF(m_soH_SF);
|
|
|
|
if (m_dataPoints.value("NCyc").isValid())
|
|
m_cycleCount = m_dataPoints.value("NCyc").toUInt32();
|
|
|
|
if (m_dataPoints.value("ChaSt").isValid())
|
|
m_chargeStatus = static_cast<Chast>(m_dataPoints.value("ChaSt").toUInt16());
|
|
|
|
if (m_dataPoints.value("LocRemCtl").isValid())
|
|
m_controlMode = static_cast<Locremctl>(m_dataPoints.value("LocRemCtl").toUInt16());
|
|
|
|
if (m_dataPoints.value("Hb").isValid())
|
|
m_batteryHeartbeat = m_dataPoints.value("Hb").toUInt16();
|
|
|
|
if (m_dataPoints.value("CtrlHb").isValid())
|
|
m_controllerHeartbeat = m_dataPoints.value("CtrlHb").toUInt16();
|
|
|
|
if (m_dataPoints.value("AlmRst").isValid())
|
|
m_alarmReset = m_dataPoints.value("AlmRst").toUInt16();
|
|
|
|
if (m_dataPoints.value("Typ").isValid())
|
|
m_batteryType = static_cast<Typ>(m_dataPoints.value("Typ").toUInt16());
|
|
|
|
if (m_dataPoints.value("State").isValid())
|
|
m_stateOfTheBatteryBank = static_cast<State>(m_dataPoints.value("State").toUInt16());
|
|
|
|
if (m_dataPoints.value("StateVnd").isValid())
|
|
m_vendorBatteryBankState = m_dataPoints.value("StateVnd").toUInt16();
|
|
|
|
if (m_dataPoints.value("WarrDt").isValid())
|
|
m_warrantyDate = m_dataPoints.value("WarrDt").toUInt32();
|
|
|
|
if (m_dataPoints.value("Evt1").isValid())
|
|
m_batteryEvent1Bitfield = static_cast<Evt1Flags>(m_dataPoints.value("Evt1").toUInt32());
|
|
|
|
if (m_dataPoints.value("Evt2").isValid())
|
|
m_batteryEvent2Bitfield = m_dataPoints.value("Evt2").toUInt32();
|
|
|
|
if (m_dataPoints.value("EvtVnd1").isValid())
|
|
m_vendorEventBitfield1 = m_dataPoints.value("EvtVnd1").toUInt32();
|
|
|
|
if (m_dataPoints.value("EvtVnd2").isValid())
|
|
m_vendorEventBitfield2 = m_dataPoints.value("EvtVnd2").toUInt32();
|
|
|
|
if (m_dataPoints.value("V").isValid())
|
|
m_externalBatteryVoltage = m_dataPoints.value("V").toFloatWithSSF(m_v_SF);
|
|
|
|
if (m_dataPoints.value("VMax").isValid())
|
|
m_maxBatteryVoltage = m_dataPoints.value("VMax").toFloatWithSSF(m_v_SF);
|
|
|
|
if (m_dataPoints.value("VMin").isValid())
|
|
m_minBatteryVoltage = m_dataPoints.value("VMin").toFloatWithSSF(m_v_SF);
|
|
|
|
if (m_dataPoints.value("CellVMax").isValid())
|
|
m_maxCellVoltage = m_dataPoints.value("CellVMax").toFloatWithSSF(m_cellV_SF);
|
|
|
|
if (m_dataPoints.value("CellVMaxStr").isValid())
|
|
m_maxCellVoltageString = m_dataPoints.value("CellVMaxStr").toUInt16();
|
|
|
|
if (m_dataPoints.value("CellVMaxMod").isValid())
|
|
m_maxCellVoltageModule = m_dataPoints.value("CellVMaxMod").toUInt16();
|
|
|
|
if (m_dataPoints.value("CellVMin").isValid())
|
|
m_minCellVoltage = m_dataPoints.value("CellVMin").toFloatWithSSF(m_cellV_SF);
|
|
|
|
if (m_dataPoints.value("CellVMinStr").isValid())
|
|
m_minCellVoltageString = m_dataPoints.value("CellVMinStr").toUInt16();
|
|
|
|
if (m_dataPoints.value("CellVMinMod").isValid())
|
|
m_minCellVoltageModule = m_dataPoints.value("CellVMinMod").toUInt16();
|
|
|
|
if (m_dataPoints.value("CellVAvg").isValid())
|
|
m_averageCellVoltage = m_dataPoints.value("CellVAvg").toFloatWithSSF(m_cellV_SF);
|
|
|
|
if (m_dataPoints.value("A").isValid())
|
|
m_totalDcCurrent = m_dataPoints.value("A").toFloatWithSSF(m_a_SF);
|
|
|
|
if (m_dataPoints.value("AChaMax").isValid())
|
|
m_maxChargeCurrent = m_dataPoints.value("AChaMax").toFloatWithSSF(m_aMax_SF);
|
|
|
|
if (m_dataPoints.value("ADisChaMax").isValid())
|
|
m_maxDischargeCurrent = m_dataPoints.value("ADisChaMax").toFloatWithSSF(m_aMax_SF);
|
|
|
|
if (m_dataPoints.value("W").isValid())
|
|
m_totalPower = m_dataPoints.value("W").toFloatWithSSF(m_w_SF);
|
|
|
|
if (m_dataPoints.value("ReqInvState").isValid())
|
|
m_inverterStateRequest = static_cast<Reqinvstate>(m_dataPoints.value("ReqInvState").toUInt16());
|
|
|
|
if (m_dataPoints.value("ReqW").isValid())
|
|
m_batteryPowerRequest = m_dataPoints.value("ReqW").toFloatWithSSF(m_w_SF);
|
|
|
|
if (m_dataPoints.value("SetOp").isValid())
|
|
m_setOperation = static_cast<Setop>(m_dataPoints.value("SetOp").toUInt16());
|
|
|
|
if (m_dataPoints.value("SetInvState").isValid())
|
|
m_setInverterState = static_cast<Setinvstate>(m_dataPoints.value("SetInvState").toUInt16());
|
|
|
|
if (m_dataPoints.value("AHRtg_SF").isValid())
|
|
m_aHRtg_SF = m_dataPoints.value("AHRtg_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("WHRtg_SF").isValid())
|
|
m_wHRtg_SF = m_dataPoints.value("WHRtg_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("WChaDisChaMax_SF").isValid())
|
|
m_wChaDisChaMax_SF = m_dataPoints.value("WChaDisChaMax_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("DisChaRte_SF").isValid())
|
|
m_disChaRte_SF = m_dataPoints.value("DisChaRte_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("SoC_SF").isValid())
|
|
m_soC_SF = m_dataPoints.value("SoC_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("DoD_SF").isValid())
|
|
m_doD_SF = m_dataPoints.value("DoD_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("SoH_SF").isValid())
|
|
m_soH_SF = m_dataPoints.value("SoH_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("V_SF").isValid())
|
|
m_v_SF = m_dataPoints.value("V_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("CellV_SF").isValid())
|
|
m_cellV_SF = m_dataPoints.value("CellV_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("A_SF").isValid())
|
|
m_a_SF = m_dataPoints.value("A_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("AMax_SF").isValid())
|
|
m_aMax_SF = m_dataPoints.value("AMax_SF").toInt16();
|
|
|
|
if (m_dataPoints.value("W_SF").isValid())
|
|
m_w_SF = m_dataPoints.value("W_SF").toInt16();
|
|
|
|
|
|
qCDebug(dcSunSpecModelData()) << this;
|
|
}
|
|
|
|
QDebug operator<<(QDebug debug, SunSpecBatteryModel *model)
|
|
{
|
|
debug.nospace().noquote() << "SunSpecBatteryModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n";
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("AHRtg") << "-->";
|
|
if (model->dataPoints().value("AHRtg").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateChargeCapacity() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("WHRtg") << "-->";
|
|
if (model->dataPoints().value("WHRtg").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateEnergyCapacity() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("WChaRteMax") << "-->";
|
|
if (model->dataPoints().value("WChaRteMax").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateMaxChargeRate() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("WDisChaRteMax") << "-->";
|
|
if (model->dataPoints().value("WDisChaRteMax").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateMaxDischargeRate() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("DisChaRte") << "-->";
|
|
if (model->dataPoints().value("DisChaRte").isValid()) {
|
|
debug.nospace().noquote() << model->selfDischargeRate() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SoCMax") << "-->";
|
|
if (model->dataPoints().value("SoCMax").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateMaxSoC() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SoCMin") << "-->";
|
|
if (model->dataPoints().value("SoCMin").isValid()) {
|
|
debug.nospace().noquote() << model->nameplateMinSoC() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SocRsvMax") << "-->";
|
|
if (model->dataPoints().value("SocRsvMax").isValid()) {
|
|
debug.nospace().noquote() << model->maxReservePercent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SoCRsvMin") << "-->";
|
|
if (model->dataPoints().value("SoCRsvMin").isValid()) {
|
|
debug.nospace().noquote() << model->minReservePercent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SoC") << "-->";
|
|
if (model->dataPoints().value("SoC").isValid()) {
|
|
debug.nospace().noquote() << model->stateOfCharge() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("DoD") << "-->";
|
|
if (model->dataPoints().value("DoD").isValid()) {
|
|
debug.nospace().noquote() << model->depthOfDischarge() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SoH") << "-->";
|
|
if (model->dataPoints().value("SoH").isValid()) {
|
|
debug.nospace().noquote() << model->stateOfHealth() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("NCyc") << "-->";
|
|
if (model->dataPoints().value("NCyc").isValid()) {
|
|
debug.nospace().noquote() << model->cycleCount() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("ChaSt") << "-->";
|
|
if (model->dataPoints().value("ChaSt").isValid()) {
|
|
debug.nospace().noquote() << model->chargeStatus() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("LocRemCtl") << "-->";
|
|
if (model->dataPoints().value("LocRemCtl").isValid()) {
|
|
debug.nospace().noquote() << model->controlMode() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Hb") << "-->";
|
|
if (model->dataPoints().value("Hb").isValid()) {
|
|
debug.nospace().noquote() << model->batteryHeartbeat() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CtrlHb") << "-->";
|
|
if (model->dataPoints().value("CtrlHb").isValid()) {
|
|
debug.nospace().noquote() << model->controllerHeartbeat() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("AlmRst") << "-->";
|
|
if (model->dataPoints().value("AlmRst").isValid()) {
|
|
debug.nospace().noquote() << model->alarmReset() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Typ") << "-->";
|
|
if (model->dataPoints().value("Typ").isValid()) {
|
|
debug.nospace().noquote() << model->batteryType() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("State") << "-->";
|
|
if (model->dataPoints().value("State").isValid()) {
|
|
debug.nospace().noquote() << model->stateOfTheBatteryBank() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("StateVnd") << "-->";
|
|
if (model->dataPoints().value("StateVnd").isValid()) {
|
|
debug.nospace().noquote() << model->vendorBatteryBankState() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("WarrDt") << "-->";
|
|
if (model->dataPoints().value("WarrDt").isValid()) {
|
|
debug.nospace().noquote() << model->warrantyDate() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Evt1") << "-->";
|
|
if (model->dataPoints().value("Evt1").isValid()) {
|
|
debug.nospace().noquote() << model->batteryEvent1Bitfield() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("Evt2") << "-->";
|
|
if (model->dataPoints().value("Evt2").isValid()) {
|
|
debug.nospace().noquote() << model->batteryEvent2Bitfield() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("EvtVnd1") << "-->";
|
|
if (model->dataPoints().value("EvtVnd1").isValid()) {
|
|
debug.nospace().noquote() << model->vendorEventBitfield1() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("EvtVnd2") << "-->";
|
|
if (model->dataPoints().value("EvtVnd2").isValid()) {
|
|
debug.nospace().noquote() << model->vendorEventBitfield2() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("V") << "-->";
|
|
if (model->dataPoints().value("V").isValid()) {
|
|
debug.nospace().noquote() << model->externalBatteryVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("VMax") << "-->";
|
|
if (model->dataPoints().value("VMax").isValid()) {
|
|
debug.nospace().noquote() << model->maxBatteryVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("VMin") << "-->";
|
|
if (model->dataPoints().value("VMin").isValid()) {
|
|
debug.nospace().noquote() << model->minBatteryVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMax") << "-->";
|
|
if (model->dataPoints().value("CellVMax").isValid()) {
|
|
debug.nospace().noquote() << model->maxCellVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMaxStr") << "-->";
|
|
if (model->dataPoints().value("CellVMaxStr").isValid()) {
|
|
debug.nospace().noquote() << model->maxCellVoltageString() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMaxMod") << "-->";
|
|
if (model->dataPoints().value("CellVMaxMod").isValid()) {
|
|
debug.nospace().noquote() << model->maxCellVoltageModule() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMin") << "-->";
|
|
if (model->dataPoints().value("CellVMin").isValid()) {
|
|
debug.nospace().noquote() << model->minCellVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMinStr") << "-->";
|
|
if (model->dataPoints().value("CellVMinStr").isValid()) {
|
|
debug.nospace().noquote() << model->minCellVoltageString() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVMinMod") << "-->";
|
|
if (model->dataPoints().value("CellVMinMod").isValid()) {
|
|
debug.nospace().noquote() << model->minCellVoltageModule() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("CellVAvg") << "-->";
|
|
if (model->dataPoints().value("CellVAvg").isValid()) {
|
|
debug.nospace().noquote() << model->averageCellVoltage() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("A") << "-->";
|
|
if (model->dataPoints().value("A").isValid()) {
|
|
debug.nospace().noquote() << model->totalDcCurrent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("AChaMax") << "-->";
|
|
if (model->dataPoints().value("AChaMax").isValid()) {
|
|
debug.nospace().noquote() << model->maxChargeCurrent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("ADisChaMax") << "-->";
|
|
if (model->dataPoints().value("ADisChaMax").isValid()) {
|
|
debug.nospace().noquote() << model->maxDischargeCurrent() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("W") << "-->";
|
|
if (model->dataPoints().value("W").isValid()) {
|
|
debug.nospace().noquote() << model->totalPower() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("ReqInvState") << "-->";
|
|
if (model->dataPoints().value("ReqInvState").isValid()) {
|
|
debug.nospace().noquote() << model->inverterStateRequest() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("ReqW") << "-->";
|
|
if (model->dataPoints().value("ReqW").isValid()) {
|
|
debug.nospace().noquote() << model->batteryPowerRequest() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SetOp") << "-->";
|
|
if (model->dataPoints().value("SetOp").isValid()) {
|
|
debug.nospace().noquote() << model->setOperation() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
debug.nospace().noquote() << " - " << model->dataPoints().value("SetInvState") << "-->";
|
|
if (model->dataPoints().value("SetInvState").isValid()) {
|
|
debug.nospace().noquote() << model->setInverterState() << "\n";
|
|
} else {
|
|
debug.nospace().noquote() << "NaN\n";
|
|
}
|
|
|
|
|
|
return debug.space().quote();
|
|
}
|