/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 . * * 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 "sunspecflowbatterystringmodel.h" #include "sunspecconnection.h" SunSpecFlowBatteryStringModelRepeatingBlock::SunSpecFlowBatteryStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStringModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { m_byteOrder = parent->byteOrder(); initDataPoints(); } QString SunSpecFlowBatteryStringModelRepeatingBlock::name() const { return "module"; } SunSpecFlowBatteryStringModel *SunSpecFlowBatteryStringModelRepeatingBlock::parentModel() const { return m_parentModel; } quint16 SunSpecFlowBatteryStringModelRepeatingBlock::moduleIndex() const { return m_moduleIndex; } quint16 SunSpecFlowBatteryStringModelRepeatingBlock::stackCount() const { return m_stackCount; } SunSpecFlowBatteryStringModelRepeatingBlock::ModstFlags SunSpecFlowBatteryStringModelRepeatingBlock::moduleStatus() const { return m_moduleStatus; } float SunSpecFlowBatteryStringModelRepeatingBlock::moduleStateOfCharge() const { return m_moduleStateOfCharge; } float SunSpecFlowBatteryStringModelRepeatingBlock::openCircuitVoltage() const { return m_openCircuitVoltage; } float SunSpecFlowBatteryStringModelRepeatingBlock::externalVoltage() const { return m_externalVoltage; } float SunSpecFlowBatteryStringModelRepeatingBlock::maximumCellVoltage() const { return m_maximumCellVoltage; } quint16 SunSpecFlowBatteryStringModelRepeatingBlock::maxCellVoltageCell() const { return m_maxCellVoltageCell; } float SunSpecFlowBatteryStringModelRepeatingBlock::minimumCellVoltage() const { return m_minimumCellVoltage; } quint16 SunSpecFlowBatteryStringModelRepeatingBlock::minCellVoltageCell() const { return m_minCellVoltageCell; } float SunSpecFlowBatteryStringModelRepeatingBlock::averageCellVoltage() const { return m_averageCellVoltage; } float SunSpecFlowBatteryStringModelRepeatingBlock::anolyteTemperature() const { return m_anolyteTemperature; } float SunSpecFlowBatteryStringModelRepeatingBlock::catholyteTemperature() const { return m_catholyteTemperature; } SunSpecFlowBatteryStringModelRepeatingBlock::ModconstFlags SunSpecFlowBatteryStringModelRepeatingBlock::contactorStatus() const { return m_contactorStatus; } SunSpecFlowBatteryStringModelRepeatingBlock::Modevt1Flags SunSpecFlowBatteryStringModelRepeatingBlock::moduleEvent1() const { return m_moduleEvent1; } SunSpecFlowBatteryStringModelRepeatingBlock::Modevt2Flags SunSpecFlowBatteryStringModelRepeatingBlock::moduleEvent2() const { return m_moduleEvent2; } SunSpecFlowBatteryStringModelRepeatingBlock::Modconfail SunSpecFlowBatteryStringModelRepeatingBlock::connectionFailureReason() const { return m_connectionFailureReason; } SunSpecFlowBatteryStringModelRepeatingBlock::Modsetena SunSpecFlowBatteryStringModelRepeatingBlock::enableDisableModule() const { return m_enableDisableModule; } QModbusReply *SunSpecFlowBatteryStringModelRepeatingBlock::setEnableDisableModule(Modsetena enableDisableModule) { SunSpecDataPoint dp = m_dataPoints.value("ModSetEna"); QVector registers = SunSpecDataPoint::convertFromUInt16(static_cast(enableDisableModule)); QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length()); request.setValues(registers); return m_parentModel->connection()->modbusTcpClient()->sendWriteRequest(request, m_parentModel->connection()->slaveId()); } SunSpecFlowBatteryStringModelRepeatingBlock::Modsetcon SunSpecFlowBatteryStringModelRepeatingBlock::connectDisconnectModule() const { return m_connectDisconnectModule; } QModbusReply *SunSpecFlowBatteryStringModelRepeatingBlock::setConnectDisconnectModule(Modsetcon connectDisconnectModule) { SunSpecDataPoint dp = m_dataPoints.value("ModSetCon"); QVector registers = SunSpecDataPoint::convertFromUInt16(static_cast(connectDisconnectModule)); QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, m_modbusStartRegister + dp.addressOffset(), registers.length()); request.setValues(registers); return m_parentModel->connection()->modbusTcpClient()->sendWriteRequest(request, m_parentModel->connection()->slaveId()); } SunSpecFlowBatteryStringModelRepeatingBlock::Moddisrsn SunSpecFlowBatteryStringModelRepeatingBlock::disabledReason() const { return m_disabledReason; } void SunSpecFlowBatteryStringModelRepeatingBlock::initDataPoints() { SunSpecDataPoint moduleIndexDataPoint; moduleIndexDataPoint.setName("ModIdx"); moduleIndexDataPoint.setLabel("Module Index"); moduleIndexDataPoint.setDescription("Index of the module within the string."); moduleIndexDataPoint.setMandatory(true); moduleIndexDataPoint.setSize(1); moduleIndexDataPoint.setAddressOffset(0); moduleIndexDataPoint.setSunSpecDataType("uint16"); moduleIndexDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleIndexDataPoint.name(), moduleIndexDataPoint); SunSpecDataPoint stackCountDataPoint; stackCountDataPoint.setName("ModNStk"); stackCountDataPoint.setLabel("Stack Count"); stackCountDataPoint.setDescription("Number of stacks in this module."); stackCountDataPoint.setMandatory(true); stackCountDataPoint.setSize(1); stackCountDataPoint.setAddressOffset(1); stackCountDataPoint.setSunSpecDataType("uint16"); stackCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(stackCountDataPoint.name(), stackCountDataPoint); SunSpecDataPoint moduleStatusDataPoint; moduleStatusDataPoint.setName("ModSt"); moduleStatusDataPoint.setLabel("Module Status"); moduleStatusDataPoint.setDescription("Current status of the module."); moduleStatusDataPoint.setMandatory(true); moduleStatusDataPoint.setSize(2); moduleStatusDataPoint.setAddressOffset(2); moduleStatusDataPoint.setBlockOffset(0); moduleStatusDataPoint.setSunSpecDataType("bitfield32"); moduleStatusDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleStatusDataPoint.name(), moduleStatusDataPoint); SunSpecDataPoint moduleStateOfChargeDataPoint; moduleStateOfChargeDataPoint.setName("ModSoC"); moduleStateOfChargeDataPoint.setLabel("Module State of Charge"); moduleStateOfChargeDataPoint.setDescription("State of charge for this module."); moduleStateOfChargeDataPoint.setUnits("%"); moduleStateOfChargeDataPoint.setMandatory(true); moduleStateOfChargeDataPoint.setSize(1); moduleStateOfChargeDataPoint.setAddressOffset(4); moduleStateOfChargeDataPoint.setBlockOffset(2); moduleStateOfChargeDataPoint.setScaleFactorName("SoC_SF"); moduleStateOfChargeDataPoint.setSunSpecDataType("uint16"); moduleStateOfChargeDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleStateOfChargeDataPoint.name(), moduleStateOfChargeDataPoint); SunSpecDataPoint openCircuitVoltageDataPoint; openCircuitVoltageDataPoint.setName("ModOCV"); openCircuitVoltageDataPoint.setLabel("Open Circuit Voltage"); openCircuitVoltageDataPoint.setDescription("Open circuit voltage for this module."); openCircuitVoltageDataPoint.setUnits("V"); openCircuitVoltageDataPoint.setMandatory(true); openCircuitVoltageDataPoint.setSize(1); openCircuitVoltageDataPoint.setAddressOffset(5); openCircuitVoltageDataPoint.setBlockOffset(3); openCircuitVoltageDataPoint.setScaleFactorName("OCV_SF"); openCircuitVoltageDataPoint.setSunSpecDataType("uint16"); openCircuitVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(openCircuitVoltageDataPoint.name(), openCircuitVoltageDataPoint); SunSpecDataPoint externalVoltageDataPoint; externalVoltageDataPoint.setName("ModV"); externalVoltageDataPoint.setLabel("External Voltage"); externalVoltageDataPoint.setDescription("External voltage fo this module."); externalVoltageDataPoint.setUnits("V"); externalVoltageDataPoint.setMandatory(true); externalVoltageDataPoint.setSize(1); externalVoltageDataPoint.setAddressOffset(6); externalVoltageDataPoint.setBlockOffset(4); externalVoltageDataPoint.setScaleFactorName("ModV_SF"); externalVoltageDataPoint.setSunSpecDataType("uint16"); externalVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(externalVoltageDataPoint.name(), externalVoltageDataPoint); SunSpecDataPoint maximumCellVoltageDataPoint; maximumCellVoltageDataPoint.setName("ModCellVMax"); maximumCellVoltageDataPoint.setLabel("Maximum Cell Voltage"); maximumCellVoltageDataPoint.setDescription("Maximum voltage for all cells in this module."); maximumCellVoltageDataPoint.setUnits("V"); maximumCellVoltageDataPoint.setSize(1); maximumCellVoltageDataPoint.setAddressOffset(7); maximumCellVoltageDataPoint.setBlockOffset(5); maximumCellVoltageDataPoint.setScaleFactorName("CellV_SF"); maximumCellVoltageDataPoint.setSunSpecDataType("uint16"); maximumCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maximumCellVoltageDataPoint.name(), maximumCellVoltageDataPoint); SunSpecDataPoint maxCellVoltageCellDataPoint; maxCellVoltageCellDataPoint.setName("ModCellVMaxCell"); maxCellVoltageCellDataPoint.setLabel("Max Cell Voltage Cell"); maxCellVoltageCellDataPoint.setDescription("Cell with the maximum cell voltage."); maxCellVoltageCellDataPoint.setSize(1); maxCellVoltageCellDataPoint.setAddressOffset(8); maxCellVoltageCellDataPoint.setBlockOffset(6); maxCellVoltageCellDataPoint.setSunSpecDataType("uint16"); maxCellVoltageCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageCellDataPoint.name(), maxCellVoltageCellDataPoint); SunSpecDataPoint minimumCellVoltageDataPoint; minimumCellVoltageDataPoint.setName("ModCellVMin"); minimumCellVoltageDataPoint.setLabel("Minimum Cell Voltage"); minimumCellVoltageDataPoint.setDescription("Minimum voltage for all cells in this module."); minimumCellVoltageDataPoint.setUnits("V"); minimumCellVoltageDataPoint.setSize(1); minimumCellVoltageDataPoint.setAddressOffset(9); minimumCellVoltageDataPoint.setBlockOffset(7); minimumCellVoltageDataPoint.setScaleFactorName("CellV_SF"); minimumCellVoltageDataPoint.setSunSpecDataType("uint16"); minimumCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minimumCellVoltageDataPoint.name(), minimumCellVoltageDataPoint); SunSpecDataPoint minCellVoltageCellDataPoint; minCellVoltageCellDataPoint.setName("ModCellVMinCell"); minCellVoltageCellDataPoint.setLabel("Min Cell Voltage Cell"); minCellVoltageCellDataPoint.setDescription("Cell with the minimum cell voltage."); minCellVoltageCellDataPoint.setSize(1); minCellVoltageCellDataPoint.setAddressOffset(10); minCellVoltageCellDataPoint.setBlockOffset(8); minCellVoltageCellDataPoint.setSunSpecDataType("uint16"); minCellVoltageCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellVoltageCellDataPoint.name(), minCellVoltageCellDataPoint); SunSpecDataPoint averageCellVoltageDataPoint; averageCellVoltageDataPoint.setName("ModCellVAvg"); averageCellVoltageDataPoint.setLabel("Average Cell Voltage"); averageCellVoltageDataPoint.setDescription("Average voltage for all cells in this module."); averageCellVoltageDataPoint.setUnits("V"); averageCellVoltageDataPoint.setSize(1); averageCellVoltageDataPoint.setAddressOffset(11); averageCellVoltageDataPoint.setBlockOffset(9); averageCellVoltageDataPoint.setScaleFactorName("CellV_SF"); averageCellVoltageDataPoint.setSunSpecDataType("uint16"); averageCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageCellVoltageDataPoint.name(), averageCellVoltageDataPoint); SunSpecDataPoint anolyteTemperatureDataPoint; anolyteTemperatureDataPoint.setName("ModAnoTmp"); anolyteTemperatureDataPoint.setLabel("Anolyte Temperature"); anolyteTemperatureDataPoint.setUnits("C"); anolyteTemperatureDataPoint.setSize(1); anolyteTemperatureDataPoint.setAddressOffset(12); anolyteTemperatureDataPoint.setBlockOffset(10); anolyteTemperatureDataPoint.setScaleFactorName("Tmp_SF"); anolyteTemperatureDataPoint.setSunSpecDataType("uint16"); anolyteTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(anolyteTemperatureDataPoint.name(), anolyteTemperatureDataPoint); SunSpecDataPoint catholyteTemperatureDataPoint; catholyteTemperatureDataPoint.setName("ModCatTmp"); catholyteTemperatureDataPoint.setLabel("Catholyte Temperature"); catholyteTemperatureDataPoint.setUnits("C"); catholyteTemperatureDataPoint.setSize(1); catholyteTemperatureDataPoint.setAddressOffset(13); catholyteTemperatureDataPoint.setBlockOffset(11); catholyteTemperatureDataPoint.setScaleFactorName("Tmp_SF"); catholyteTemperatureDataPoint.setSunSpecDataType("uint16"); catholyteTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(catholyteTemperatureDataPoint.name(), catholyteTemperatureDataPoint); SunSpecDataPoint contactorStatusDataPoint; contactorStatusDataPoint.setName("ModConSt"); contactorStatusDataPoint.setLabel("Contactor Status"); contactorStatusDataPoint.setSize(2); contactorStatusDataPoint.setAddressOffset(14); contactorStatusDataPoint.setBlockOffset(12); contactorStatusDataPoint.setSunSpecDataType("bitfield32"); contactorStatusDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(contactorStatusDataPoint.name(), contactorStatusDataPoint); SunSpecDataPoint moduleEvent1DataPoint; moduleEvent1DataPoint.setName("ModEvt1"); moduleEvent1DataPoint.setLabel("Module Event 1"); moduleEvent1DataPoint.setDescription("Alarms, warnings and status values. Bit flags."); moduleEvent1DataPoint.setMandatory(true); moduleEvent1DataPoint.setSize(2); moduleEvent1DataPoint.setAddressOffset(16); moduleEvent1DataPoint.setBlockOffset(14); moduleEvent1DataPoint.setSunSpecDataType("bitfield32"); moduleEvent1DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleEvent1DataPoint.name(), moduleEvent1DataPoint); SunSpecDataPoint moduleEvent2DataPoint; moduleEvent2DataPoint.setName("ModEvt2"); moduleEvent2DataPoint.setLabel("Module Event 2"); moduleEvent2DataPoint.setDescription("Alarms, warnings and status values. Bit flags."); moduleEvent2DataPoint.setMandatory(true); moduleEvent2DataPoint.setSize(2); moduleEvent2DataPoint.setAddressOffset(18); moduleEvent2DataPoint.setBlockOffset(16); moduleEvent2DataPoint.setSunSpecDataType("bitfield32"); moduleEvent2DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleEvent2DataPoint.name(), moduleEvent2DataPoint); SunSpecDataPoint connectionFailureReasonDataPoint; connectionFailureReasonDataPoint.setName("ModConFail"); connectionFailureReasonDataPoint.setLabel("Connection Failure Reason"); connectionFailureReasonDataPoint.setSize(1); connectionFailureReasonDataPoint.setAddressOffset(20); connectionFailureReasonDataPoint.setBlockOffset(18); connectionFailureReasonDataPoint.setSunSpecDataType("enum16"); connectionFailureReasonDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(connectionFailureReasonDataPoint.name(), connectionFailureReasonDataPoint); SunSpecDataPoint enableDisableModuleDataPoint; enableDisableModuleDataPoint.setName("ModSetEna"); enableDisableModuleDataPoint.setLabel("Enable/Disable Module"); enableDisableModuleDataPoint.setDescription("Enables and disables the module."); enableDisableModuleDataPoint.setSize(1); enableDisableModuleDataPoint.setAddressOffset(21); enableDisableModuleDataPoint.setBlockOffset(19); enableDisableModuleDataPoint.setSunSpecDataType("enum16"); enableDisableModuleDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite); enableDisableModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(enableDisableModuleDataPoint.name(), enableDisableModuleDataPoint); SunSpecDataPoint connectDisconnectModuleDataPoint; connectDisconnectModuleDataPoint.setName("ModSetCon"); connectDisconnectModuleDataPoint.setLabel("Connect/Disconnect Module "); connectDisconnectModuleDataPoint.setDescription("Connects and disconnects the module."); connectDisconnectModuleDataPoint.setSize(1); connectDisconnectModuleDataPoint.setAddressOffset(22); connectDisconnectModuleDataPoint.setBlockOffset(20); connectDisconnectModuleDataPoint.setSunSpecDataType("enum16"); connectDisconnectModuleDataPoint.setAccess(SunSpecDataPoint::AccessReadWrite); connectDisconnectModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(connectDisconnectModuleDataPoint.name(), connectDisconnectModuleDataPoint); SunSpecDataPoint disabledReasonDataPoint; disabledReasonDataPoint.setName("ModDisRsn"); disabledReasonDataPoint.setLabel("Disabled Reason"); disabledReasonDataPoint.setDescription("Reason why the module is currently disabled."); disabledReasonDataPoint.setSize(1); disabledReasonDataPoint.setAddressOffset(23); disabledReasonDataPoint.setBlockOffset(21); disabledReasonDataPoint.setSunSpecDataType("enum16"); disabledReasonDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(disabledReasonDataPoint.name(), disabledReasonDataPoint); } void SunSpecFlowBatteryStringModelRepeatingBlock::processBlockData(const QVector blockData) { m_blockData = blockData; // Update properties according to the data point type if (m_dataPoints.value("ModIdx").isValid()) m_moduleIndex = m_dataPoints.value("ModIdx").toUInt16(); if (m_dataPoints.value("ModNStk").isValid()) m_stackCount = m_dataPoints.value("ModNStk").toUInt16(); if (m_dataPoints.value("ModSt").isValid()) m_moduleStatus = static_cast(m_dataPoints.value("ModSt").toUInt32()); if (m_dataPoints.value("ModSoC").isValid()) m_moduleStateOfCharge = m_dataPoints.value("ModSoC").toFloatWithSSF(m_parentModel->soC_SF()); if (m_dataPoints.value("ModOCV").isValid()) m_openCircuitVoltage = m_dataPoints.value("ModOCV").toFloatWithSSF(m_parentModel->oCV_SF()); if (m_dataPoints.value("ModV").isValid()) m_externalVoltage = m_dataPoints.value("ModV").toFloatWithSSF(m_parentModel->modV_SF()); if (m_dataPoints.value("ModCellVMax").isValid()) m_maximumCellVoltage = m_dataPoints.value("ModCellVMax").toFloatWithSSF(m_parentModel->cellV_SF()); if (m_dataPoints.value("ModCellVMaxCell").isValid()) m_maxCellVoltageCell = m_dataPoints.value("ModCellVMaxCell").toUInt16(); if (m_dataPoints.value("ModCellVMin").isValid()) m_minimumCellVoltage = m_dataPoints.value("ModCellVMin").toFloatWithSSF(m_parentModel->cellV_SF()); if (m_dataPoints.value("ModCellVMinCell").isValid()) m_minCellVoltageCell = m_dataPoints.value("ModCellVMinCell").toUInt16(); if (m_dataPoints.value("ModCellVAvg").isValid()) m_averageCellVoltage = m_dataPoints.value("ModCellVAvg").toFloatWithSSF(m_parentModel->cellV_SF()); if (m_dataPoints.value("ModAnoTmp").isValid()) m_anolyteTemperature = m_dataPoints.value("ModAnoTmp").toFloatWithSSF(m_parentModel->tmp_SF()); if (m_dataPoints.value("ModCatTmp").isValid()) m_catholyteTemperature = m_dataPoints.value("ModCatTmp").toFloatWithSSF(m_parentModel->tmp_SF()); if (m_dataPoints.value("ModConSt").isValid()) m_contactorStatus = static_cast(m_dataPoints.value("ModConSt").toUInt32()); if (m_dataPoints.value("ModEvt1").isValid()) m_moduleEvent1 = static_cast(m_dataPoints.value("ModEvt1").toUInt32()); if (m_dataPoints.value("ModEvt2").isValid()) m_moduleEvent2 = static_cast(m_dataPoints.value("ModEvt2").toUInt32()); if (m_dataPoints.value("ModConFail").isValid()) m_connectionFailureReason = static_cast(m_dataPoints.value("ModConFail").toUInt16()); if (m_dataPoints.value("ModSetEna").isValid()) m_enableDisableModule = static_cast(m_dataPoints.value("ModSetEna").toUInt16()); if (m_dataPoints.value("ModSetCon").isValid()) m_connectDisconnectModule = static_cast(m_dataPoints.value("ModSetCon").toUInt16()); if (m_dataPoints.value("ModDisRsn").isValid()) m_disabledReason = static_cast(m_dataPoints.value("ModDisRsn").toUInt16()); qCDebug(dcSunSpecModelData()) << this; } SunSpecFlowBatteryStringModel::SunSpecFlowBatteryStringModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) : SunSpecModel(connection, modbusStartRegister, 807, modelLength, byteOrder, parent) { m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); } SunSpecFlowBatteryStringModel::~SunSpecFlowBatteryStringModel() { } QString SunSpecFlowBatteryStringModel::name() const { return "flow_battery_string"; } QString SunSpecFlowBatteryStringModel::description() const { return QString(); } QString SunSpecFlowBatteryStringModel::label() const { return "Flow Battery String Model"; } quint16 SunSpecFlowBatteryStringModel::stringIndex() const { return m_stringIndex; } quint16 SunSpecFlowBatteryStringModel::moduleCount() const { return m_moduleCount; } quint16 SunSpecFlowBatteryStringModel::connectedModuleCount() const { return m_connectedModuleCount; } float SunSpecFlowBatteryStringModel::maxModuleVoltage() const { return m_maxModuleVoltage; } quint16 SunSpecFlowBatteryStringModel::maxModuleVoltageModule() const { return m_maxModuleVoltageModule; } float SunSpecFlowBatteryStringModel::minModuleVoltage() const { return m_minModuleVoltage; } quint16 SunSpecFlowBatteryStringModel::minModuleVoltageModule() const { return m_minModuleVoltageModule; } float SunSpecFlowBatteryStringModel::averageModuleVoltage() const { return m_averageModuleVoltage; } float SunSpecFlowBatteryStringModel::maxCellVoltage() const { return m_maxCellVoltage; } quint16 SunSpecFlowBatteryStringModel::maxCellVoltageModule() const { return m_maxCellVoltageModule; } quint16 SunSpecFlowBatteryStringModel::maxCellVoltageStack() const { return m_maxCellVoltageStack; } float SunSpecFlowBatteryStringModel::minCellVoltage() const { return m_minCellVoltage; } quint16 SunSpecFlowBatteryStringModel::minCellVoltageModule() const { return m_minCellVoltageModule; } quint16 SunSpecFlowBatteryStringModel::minCellVoltageStack() const { return m_minCellVoltageStack; } float SunSpecFlowBatteryStringModel::averageCellVoltage() const { return m_averageCellVoltage; } float SunSpecFlowBatteryStringModel::maxTemperature() const { return m_maxTemperature; } quint16 SunSpecFlowBatteryStringModel::maxTemperatureModule() const { return m_maxTemperatureModule; } float SunSpecFlowBatteryStringModel::minTemperature() const { return m_minTemperature; } quint16 SunSpecFlowBatteryStringModel::minTemperatureModule() const { return m_minTemperatureModule; } float SunSpecFlowBatteryStringModel::averageTemperature() const { return m_averageTemperature; } SunSpecFlowBatteryStringModel::Evt1Flags SunSpecFlowBatteryStringModel::stringEvent1() const { return m_stringEvent1; } SunSpecFlowBatteryStringModel::Evt2Flags SunSpecFlowBatteryStringModel::stringEvent2() const { return m_stringEvent2; } quint32 SunSpecFlowBatteryStringModel::vendorEventBitfield1() const { return m_vendorEventBitfield1; } quint32 SunSpecFlowBatteryStringModel::vendorEventBitfield2() const { return m_vendorEventBitfield2; } qint16 SunSpecFlowBatteryStringModel::modV_SF() const { return m_modV_SF; } qint16 SunSpecFlowBatteryStringModel::cellV_SF() const { return m_cellV_SF; } qint16 SunSpecFlowBatteryStringModel::tmp_SF() const { return m_tmp_SF; } qint16 SunSpecFlowBatteryStringModel::soC_SF() const { return m_soC_SF; } qint16 SunSpecFlowBatteryStringModel::oCV_SF() const { return m_oCV_SF; } quint16 SunSpecFlowBatteryStringModel::pad1() const { return m_pad1; } void SunSpecFlowBatteryStringModel::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 stringIndexDataPoint; stringIndexDataPoint.setName("Idx"); stringIndexDataPoint.setLabel("String Index"); stringIndexDataPoint.setDescription("Index of the string within the bank."); stringIndexDataPoint.setMandatory(true); stringIndexDataPoint.setSize(1); stringIndexDataPoint.setAddressOffset(2); stringIndexDataPoint.setBlockOffset(0); stringIndexDataPoint.setSunSpecDataType("uint16"); stringIndexDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(stringIndexDataPoint.name(), stringIndexDataPoint); SunSpecDataPoint moduleCountDataPoint; moduleCountDataPoint.setName("NMod"); moduleCountDataPoint.setLabel("Module Count"); moduleCountDataPoint.setDescription("Number of modules in this string."); moduleCountDataPoint.setMandatory(true); moduleCountDataPoint.setSize(1); moduleCountDataPoint.setAddressOffset(3); moduleCountDataPoint.setBlockOffset(1); moduleCountDataPoint.setSunSpecDataType("uint16"); moduleCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleCountDataPoint.name(), moduleCountDataPoint); SunSpecDataPoint connectedModuleCountDataPoint; connectedModuleCountDataPoint.setName("NModCon"); connectedModuleCountDataPoint.setLabel("Connected Module Count"); connectedModuleCountDataPoint.setDescription("Number of electrically connected modules in this string."); connectedModuleCountDataPoint.setMandatory(true); connectedModuleCountDataPoint.setSize(1); connectedModuleCountDataPoint.setAddressOffset(4); connectedModuleCountDataPoint.setBlockOffset(2); connectedModuleCountDataPoint.setSunSpecDataType("uint16"); connectedModuleCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(connectedModuleCountDataPoint.name(), connectedModuleCountDataPoint); SunSpecDataPoint maxModuleVoltageDataPoint; maxModuleVoltageDataPoint.setName("ModVMax"); maxModuleVoltageDataPoint.setLabel("Max Module Voltage"); maxModuleVoltageDataPoint.setDescription("Maximum voltage for all modules in the string."); maxModuleVoltageDataPoint.setUnits("V"); maxModuleVoltageDataPoint.setMandatory(true); maxModuleVoltageDataPoint.setSize(1); maxModuleVoltageDataPoint.setAddressOffset(5); maxModuleVoltageDataPoint.setBlockOffset(3); maxModuleVoltageDataPoint.setScaleFactorName("ModV_SF"); maxModuleVoltageDataPoint.setSunSpecDataType("uint16"); maxModuleVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxModuleVoltageDataPoint.name(), maxModuleVoltageDataPoint); SunSpecDataPoint maxModuleVoltageModuleDataPoint; maxModuleVoltageModuleDataPoint.setName("ModVMaxMod"); maxModuleVoltageModuleDataPoint.setLabel("Max Module Voltage Module"); maxModuleVoltageModuleDataPoint.setDescription("Module with the maximum voltage."); maxModuleVoltageModuleDataPoint.setSize(1); maxModuleVoltageModuleDataPoint.setAddressOffset(6); maxModuleVoltageModuleDataPoint.setBlockOffset(4); maxModuleVoltageModuleDataPoint.setSunSpecDataType("uint16"); maxModuleVoltageModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxModuleVoltageModuleDataPoint.name(), maxModuleVoltageModuleDataPoint); SunSpecDataPoint minModuleVoltageDataPoint; minModuleVoltageDataPoint.setName("ModVMin"); minModuleVoltageDataPoint.setLabel("Min Module Voltage"); minModuleVoltageDataPoint.setDescription("Minimum voltage for all modules in the string."); minModuleVoltageDataPoint.setUnits("V"); minModuleVoltageDataPoint.setMandatory(true); minModuleVoltageDataPoint.setSize(1); minModuleVoltageDataPoint.setAddressOffset(7); minModuleVoltageDataPoint.setBlockOffset(5); minModuleVoltageDataPoint.setScaleFactorName("ModV_SF"); minModuleVoltageDataPoint.setSunSpecDataType("uint16"); minModuleVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minModuleVoltageDataPoint.name(), minModuleVoltageDataPoint); SunSpecDataPoint minModuleVoltageModuleDataPoint; minModuleVoltageModuleDataPoint.setName("ModVMinMod"); minModuleVoltageModuleDataPoint.setLabel("Min Module Voltage Module"); minModuleVoltageModuleDataPoint.setDescription("Module with the minimum voltage."); minModuleVoltageModuleDataPoint.setSize(1); minModuleVoltageModuleDataPoint.setAddressOffset(8); minModuleVoltageModuleDataPoint.setBlockOffset(6); minModuleVoltageModuleDataPoint.setSunSpecDataType("uint16"); minModuleVoltageModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minModuleVoltageModuleDataPoint.name(), minModuleVoltageModuleDataPoint); SunSpecDataPoint averageModuleVoltageDataPoint; averageModuleVoltageDataPoint.setName("ModVAvg"); averageModuleVoltageDataPoint.setLabel("Average Module Voltage"); averageModuleVoltageDataPoint.setDescription("Average voltage for all modules in the string."); averageModuleVoltageDataPoint.setUnits("V"); averageModuleVoltageDataPoint.setMandatory(true); averageModuleVoltageDataPoint.setSize(1); averageModuleVoltageDataPoint.setAddressOffset(9); averageModuleVoltageDataPoint.setBlockOffset(7); averageModuleVoltageDataPoint.setScaleFactorName("ModV_SF"); averageModuleVoltageDataPoint.setSunSpecDataType("uint16"); averageModuleVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageModuleVoltageDataPoint.name(), averageModuleVoltageDataPoint); SunSpecDataPoint maxCellVoltageDataPoint; maxCellVoltageDataPoint.setName("CellVMax"); maxCellVoltageDataPoint.setLabel("Max Cell Voltage"); maxCellVoltageDataPoint.setDescription("Maximum voltage for all cells in the string."); maxCellVoltageDataPoint.setUnits("V"); maxCellVoltageDataPoint.setSize(1); maxCellVoltageDataPoint.setAddressOffset(10); maxCellVoltageDataPoint.setBlockOffset(8); maxCellVoltageDataPoint.setScaleFactorName("CellV_SF"); maxCellVoltageDataPoint.setSunSpecDataType("uint16"); maxCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageDataPoint.name(), maxCellVoltageDataPoint); SunSpecDataPoint maxCellVoltageModuleDataPoint; maxCellVoltageModuleDataPoint.setName("CellVMaxMod"); maxCellVoltageModuleDataPoint.setLabel("Max Cell Voltage Module"); maxCellVoltageModuleDataPoint.setDescription("Module containing the cell with the maximum voltage."); maxCellVoltageModuleDataPoint.setSize(1); maxCellVoltageModuleDataPoint.setAddressOffset(11); maxCellVoltageModuleDataPoint.setBlockOffset(9); maxCellVoltageModuleDataPoint.setSunSpecDataType("uint16"); maxCellVoltageModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageModuleDataPoint.name(), maxCellVoltageModuleDataPoint); SunSpecDataPoint maxCellVoltageStackDataPoint; maxCellVoltageStackDataPoint.setName("CellVMaxStk"); maxCellVoltageStackDataPoint.setLabel("Max Cell Voltage Stack"); maxCellVoltageStackDataPoint.setDescription("Stack containing the cell with the maximum voltage."); maxCellVoltageStackDataPoint.setSize(1); maxCellVoltageStackDataPoint.setAddressOffset(12); maxCellVoltageStackDataPoint.setBlockOffset(10); maxCellVoltageStackDataPoint.setSunSpecDataType("uint16"); maxCellVoltageStackDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageStackDataPoint.name(), maxCellVoltageStackDataPoint); SunSpecDataPoint minCellVoltageDataPoint; minCellVoltageDataPoint.setName("CellVMin"); minCellVoltageDataPoint.setLabel("Min Cell Voltage"); minCellVoltageDataPoint.setDescription("Minimum voltage for all cells in the string."); minCellVoltageDataPoint.setUnits("V"); minCellVoltageDataPoint.setSize(1); minCellVoltageDataPoint.setAddressOffset(13); minCellVoltageDataPoint.setBlockOffset(11); minCellVoltageDataPoint.setScaleFactorName("CellV_SF"); minCellVoltageDataPoint.setSunSpecDataType("uint16"); minCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellVoltageDataPoint.name(), minCellVoltageDataPoint); SunSpecDataPoint minCellVoltageModuleDataPoint; minCellVoltageModuleDataPoint.setName("CellVMinMod"); minCellVoltageModuleDataPoint.setLabel("Min Cell Voltage Module"); minCellVoltageModuleDataPoint.setDescription("Module containing the cell with the minimum voltage."); minCellVoltageModuleDataPoint.setSize(1); minCellVoltageModuleDataPoint.setAddressOffset(14); minCellVoltageModuleDataPoint.setBlockOffset(12); minCellVoltageModuleDataPoint.setSunSpecDataType("uint16"); minCellVoltageModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellVoltageModuleDataPoint.name(), minCellVoltageModuleDataPoint); SunSpecDataPoint minCellVoltageStackDataPoint; minCellVoltageStackDataPoint.setName("CellVMinStk"); minCellVoltageStackDataPoint.setLabel("Min Cell Voltage Stack"); minCellVoltageStackDataPoint.setDescription("Stack containing the cell with the minimum voltage."); minCellVoltageStackDataPoint.setSize(1); minCellVoltageStackDataPoint.setAddressOffset(15); minCellVoltageStackDataPoint.setBlockOffset(13); minCellVoltageStackDataPoint.setSunSpecDataType("uint16"); minCellVoltageStackDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellVoltageStackDataPoint.name(), minCellVoltageStackDataPoint); SunSpecDataPoint averageCellVoltageDataPoint; averageCellVoltageDataPoint.setName("CellVAvg"); averageCellVoltageDataPoint.setLabel("Average Cell Voltage"); averageCellVoltageDataPoint.setDescription("Average voltage for all cells in the string."); averageCellVoltageDataPoint.setUnits("V"); averageCellVoltageDataPoint.setSize(1); averageCellVoltageDataPoint.setAddressOffset(16); averageCellVoltageDataPoint.setBlockOffset(14); averageCellVoltageDataPoint.setScaleFactorName("CellV_SF"); averageCellVoltageDataPoint.setSunSpecDataType("uint16"); averageCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageCellVoltageDataPoint.name(), averageCellVoltageDataPoint); SunSpecDataPoint maxTemperatureDataPoint; maxTemperatureDataPoint.setName("TmpMax"); maxTemperatureDataPoint.setLabel("Max Temperature"); maxTemperatureDataPoint.setDescription("Maximum electrolyte temperature for all modules in the string."); maxTemperatureDataPoint.setUnits("C"); maxTemperatureDataPoint.setMandatory(true); maxTemperatureDataPoint.setSize(1); maxTemperatureDataPoint.setAddressOffset(17); maxTemperatureDataPoint.setBlockOffset(15); maxTemperatureDataPoint.setScaleFactorName("Tmp_SF"); maxTemperatureDataPoint.setSunSpecDataType("int16"); maxTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxTemperatureDataPoint.name(), maxTemperatureDataPoint); SunSpecDataPoint maxTemperatureModuleDataPoint; maxTemperatureModuleDataPoint.setName("TmpMaxMod"); maxTemperatureModuleDataPoint.setLabel("Max Temperature Module"); maxTemperatureModuleDataPoint.setDescription("Module with the maximum temperature."); maxTemperatureModuleDataPoint.setSize(1); maxTemperatureModuleDataPoint.setAddressOffset(18); maxTemperatureModuleDataPoint.setBlockOffset(16); maxTemperatureModuleDataPoint.setSunSpecDataType("uint16"); maxTemperatureModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxTemperatureModuleDataPoint.name(), maxTemperatureModuleDataPoint); SunSpecDataPoint minTemperatureDataPoint; minTemperatureDataPoint.setName("TmpMin"); minTemperatureDataPoint.setLabel("Min Temperature"); minTemperatureDataPoint.setDescription("Minimum electrolyte temperature for all modules in the string."); minTemperatureDataPoint.setUnits("C"); minTemperatureDataPoint.setMandatory(true); minTemperatureDataPoint.setSize(1); minTemperatureDataPoint.setAddressOffset(19); minTemperatureDataPoint.setBlockOffset(17); minTemperatureDataPoint.setScaleFactorName("Tmp_SF"); minTemperatureDataPoint.setSunSpecDataType("int16"); minTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minTemperatureDataPoint.name(), minTemperatureDataPoint); SunSpecDataPoint minTemperatureModuleDataPoint; minTemperatureModuleDataPoint.setName("TmpMinMod"); minTemperatureModuleDataPoint.setLabel("Min Temperature Module"); minTemperatureModuleDataPoint.setDescription("Module with the minimum temperature."); minTemperatureModuleDataPoint.setSize(1); minTemperatureModuleDataPoint.setAddressOffset(20); minTemperatureModuleDataPoint.setBlockOffset(18); minTemperatureModuleDataPoint.setSunSpecDataType("uint16"); minTemperatureModuleDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minTemperatureModuleDataPoint.name(), minTemperatureModuleDataPoint); SunSpecDataPoint averageTemperatureDataPoint; averageTemperatureDataPoint.setName("TmpAvg"); averageTemperatureDataPoint.setLabel("Average Temperature"); averageTemperatureDataPoint.setDescription("Average electrolyte temperature for all modules in the string."); averageTemperatureDataPoint.setUnits("C"); averageTemperatureDataPoint.setMandatory(true); averageTemperatureDataPoint.setSize(1); averageTemperatureDataPoint.setAddressOffset(21); averageTemperatureDataPoint.setBlockOffset(19); averageTemperatureDataPoint.setScaleFactorName("Tmp_SF"); averageTemperatureDataPoint.setSunSpecDataType("int16"); averageTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageTemperatureDataPoint.name(), averageTemperatureDataPoint); SunSpecDataPoint stringEvent1DataPoint; stringEvent1DataPoint.setName("Evt1"); stringEvent1DataPoint.setLabel("String Event 1"); stringEvent1DataPoint.setDescription("Alarms, warnings and status values. Bit flags."); stringEvent1DataPoint.setMandatory(true); stringEvent1DataPoint.setSize(2); stringEvent1DataPoint.setAddressOffset(22); stringEvent1DataPoint.setBlockOffset(20); stringEvent1DataPoint.setSunSpecDataType("bitfield32"); stringEvent1DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(stringEvent1DataPoint.name(), stringEvent1DataPoint); SunSpecDataPoint stringEvent2DataPoint; stringEvent2DataPoint.setName("Evt2"); stringEvent2DataPoint.setLabel("String Event 2"); stringEvent2DataPoint.setDescription("Alarms, warnings and status values. Bit flags."); stringEvent2DataPoint.setMandatory(true); stringEvent2DataPoint.setSize(2); stringEvent2DataPoint.setAddressOffset(24); stringEvent2DataPoint.setBlockOffset(22); stringEvent2DataPoint.setSunSpecDataType("bitfield32"); stringEvent2DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(stringEvent2DataPoint.name(), stringEvent2DataPoint); SunSpecDataPoint vendorEventBitfield1DataPoint; vendorEventBitfield1DataPoint.setName("EvtVnd1"); vendorEventBitfield1DataPoint.setLabel("Vendor Event Bitfield 1"); vendorEventBitfield1DataPoint.setDescription("Vendor defined events."); vendorEventBitfield1DataPoint.setMandatory(true); vendorEventBitfield1DataPoint.setSize(2); vendorEventBitfield1DataPoint.setAddressOffset(26); vendorEventBitfield1DataPoint.setBlockOffset(24); 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(28); vendorEventBitfield2DataPoint.setBlockOffset(26); vendorEventBitfield2DataPoint.setSunSpecDataType("bitfield32"); vendorEventBitfield2DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(vendorEventBitfield2DataPoint.name(), vendorEventBitfield2DataPoint); SunSpecDataPoint modV_SFDataPoint; modV_SFDataPoint.setName("ModV_SF"); modV_SFDataPoint.setMandatory(true); modV_SFDataPoint.setSize(1); modV_SFDataPoint.setAddressOffset(30); modV_SFDataPoint.setBlockOffset(28); modV_SFDataPoint.setSunSpecDataType("sunssf"); modV_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(modV_SFDataPoint.name(), modV_SFDataPoint); SunSpecDataPoint cellV_SFDataPoint; cellV_SFDataPoint.setName("CellV_SF"); cellV_SFDataPoint.setDescription("Scale factor for voltage."); cellV_SFDataPoint.setMandatory(true); cellV_SFDataPoint.setSize(1); cellV_SFDataPoint.setAddressOffset(31); cellV_SFDataPoint.setBlockOffset(29); cellV_SFDataPoint.setSunSpecDataType("sunssf"); cellV_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(cellV_SFDataPoint.name(), cellV_SFDataPoint); SunSpecDataPoint tmp_SFDataPoint; tmp_SFDataPoint.setName("Tmp_SF"); tmp_SFDataPoint.setDescription("Scale factor for temperature."); tmp_SFDataPoint.setMandatory(true); tmp_SFDataPoint.setSize(1); tmp_SFDataPoint.setAddressOffset(32); tmp_SFDataPoint.setBlockOffset(30); tmp_SFDataPoint.setSunSpecDataType("sunssf"); tmp_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(tmp_SFDataPoint.name(), tmp_SFDataPoint); SunSpecDataPoint soC_SFDataPoint; soC_SFDataPoint.setName("SoC_SF"); soC_SFDataPoint.setDescription("Scale factor for state of charge."); soC_SFDataPoint.setMandatory(true); soC_SFDataPoint.setSize(1); soC_SFDataPoint.setAddressOffset(33); soC_SFDataPoint.setBlockOffset(31); soC_SFDataPoint.setSunSpecDataType("sunssf"); soC_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(soC_SFDataPoint.name(), soC_SFDataPoint); SunSpecDataPoint oCV_SFDataPoint; oCV_SFDataPoint.setName("OCV_SF"); oCV_SFDataPoint.setDescription("Scale factor for open circuit voltage."); oCV_SFDataPoint.setMandatory(true); oCV_SFDataPoint.setSize(1); oCV_SFDataPoint.setAddressOffset(34); oCV_SFDataPoint.setBlockOffset(32); oCV_SFDataPoint.setSunSpecDataType("sunssf"); oCV_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(oCV_SFDataPoint.name(), oCV_SFDataPoint); SunSpecDataPoint pad1DataPoint; pad1DataPoint.setName("Pad1"); pad1DataPoint.setLabel("Pad"); pad1DataPoint.setDescription("Pad register."); pad1DataPoint.setMandatory(true); pad1DataPoint.setSize(1); pad1DataPoint.setAddressOffset(35); pad1DataPoint.setBlockOffset(33); pad1DataPoint.setSunSpecDataType("pad"); pad1DataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(pad1DataPoint.name(), pad1DataPoint); } void SunSpecFlowBatteryStringModel::processBlockData() { // Scale factors if (m_dataPoints.value("ModV_SF").isValid()) m_modV_SF = m_dataPoints.value("ModV_SF").toInt16(); if (m_dataPoints.value("CellV_SF").isValid()) m_cellV_SF = m_dataPoints.value("CellV_SF").toInt16(); if (m_dataPoints.value("Tmp_SF").isValid()) m_tmp_SF = m_dataPoints.value("Tmp_SF").toInt16(); if (m_dataPoints.value("SoC_SF").isValid()) m_soC_SF = m_dataPoints.value("SoC_SF").toInt16(); if (m_dataPoints.value("OCV_SF").isValid()) m_oCV_SF = m_dataPoints.value("OCV_SF").toInt16(); // Update properties according to the data point type if (m_dataPoints.value("Idx").isValid()) m_stringIndex = m_dataPoints.value("Idx").toUInt16(); if (m_dataPoints.value("NMod").isValid()) m_moduleCount = m_dataPoints.value("NMod").toUInt16(); if (m_dataPoints.value("NModCon").isValid()) m_connectedModuleCount = m_dataPoints.value("NModCon").toUInt16(); if (m_dataPoints.value("ModVMax").isValid()) m_maxModuleVoltage = m_dataPoints.value("ModVMax").toFloatWithSSF(m_modV_SF); if (m_dataPoints.value("ModVMaxMod").isValid()) m_maxModuleVoltageModule = m_dataPoints.value("ModVMaxMod").toUInt16(); if (m_dataPoints.value("ModVMin").isValid()) m_minModuleVoltage = m_dataPoints.value("ModVMin").toFloatWithSSF(m_modV_SF); if (m_dataPoints.value("ModVMinMod").isValid()) m_minModuleVoltageModule = m_dataPoints.value("ModVMinMod").toUInt16(); if (m_dataPoints.value("ModVAvg").isValid()) m_averageModuleVoltage = m_dataPoints.value("ModVAvg").toFloatWithSSF(m_modV_SF); if (m_dataPoints.value("CellVMax").isValid()) m_maxCellVoltage = m_dataPoints.value("CellVMax").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("CellVMaxMod").isValid()) m_maxCellVoltageModule = m_dataPoints.value("CellVMaxMod").toUInt16(); if (m_dataPoints.value("CellVMaxStk").isValid()) m_maxCellVoltageStack = m_dataPoints.value("CellVMaxStk").toUInt16(); if (m_dataPoints.value("CellVMin").isValid()) m_minCellVoltage = m_dataPoints.value("CellVMin").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("CellVMinMod").isValid()) m_minCellVoltageModule = m_dataPoints.value("CellVMinMod").toUInt16(); if (m_dataPoints.value("CellVMinStk").isValid()) m_minCellVoltageStack = m_dataPoints.value("CellVMinStk").toUInt16(); if (m_dataPoints.value("CellVAvg").isValid()) m_averageCellVoltage = m_dataPoints.value("CellVAvg").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("TmpMax").isValid()) m_maxTemperature = m_dataPoints.value("TmpMax").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("TmpMaxMod").isValid()) m_maxTemperatureModule = m_dataPoints.value("TmpMaxMod").toUInt16(); if (m_dataPoints.value("TmpMin").isValid()) m_minTemperature = m_dataPoints.value("TmpMin").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("TmpMinMod").isValid()) m_minTemperatureModule = m_dataPoints.value("TmpMinMod").toUInt16(); if (m_dataPoints.value("TmpAvg").isValid()) m_averageTemperature = m_dataPoints.value("TmpAvg").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("Evt1").isValid()) m_stringEvent1 = static_cast(m_dataPoints.value("Evt1").toUInt32()); if (m_dataPoints.value("Evt2").isValid()) m_stringEvent2 = static_cast(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("ModV_SF").isValid()) m_modV_SF = m_dataPoints.value("ModV_SF").toInt16(); if (m_dataPoints.value("CellV_SF").isValid()) m_cellV_SF = m_dataPoints.value("CellV_SF").toInt16(); if (m_dataPoints.value("Tmp_SF").isValid()) m_tmp_SF = m_dataPoints.value("Tmp_SF").toInt16(); if (m_dataPoints.value("SoC_SF").isValid()) m_soC_SF = m_dataPoints.value("SoC_SF").toInt16(); if (m_dataPoints.value("OCV_SF").isValid()) m_oCV_SF = m_dataPoints.value("OCV_SF").toInt16(); if (m_dataPoints.value("Pad1").isValid()) m_pad1 = m_dataPoints.value("Pad1").toUInt16(); qCDebug(dcSunSpecModelData()) << this; } QDebug operator<<(QDebug debug, SunSpecFlowBatteryStringModel *model) { debug.nospace().noquote() << "SunSpecFlowBatteryStringModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; debug.nospace().noquote() << " - " << model->dataPoints().value("Idx") << "-->"; if (model->dataPoints().value("Idx").isValid()) { debug.nospace().noquote() << model->stringIndex() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("NMod") << "-->"; if (model->dataPoints().value("NMod").isValid()) { debug.nospace().noquote() << model->moduleCount() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("NModCon") << "-->"; if (model->dataPoints().value("NModCon").isValid()) { debug.nospace().noquote() << model->connectedModuleCount() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModVMax") << "-->"; if (model->dataPoints().value("ModVMax").isValid()) { debug.nospace().noquote() << model->maxModuleVoltage() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModVMaxMod") << "-->"; if (model->dataPoints().value("ModVMaxMod").isValid()) { debug.nospace().noquote() << model->maxModuleVoltageModule() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModVMin") << "-->"; if (model->dataPoints().value("ModVMin").isValid()) { debug.nospace().noquote() << model->minModuleVoltage() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModVMinMod") << "-->"; if (model->dataPoints().value("ModVMinMod").isValid()) { debug.nospace().noquote() << model->minModuleVoltageModule() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModVAvg") << "-->"; if (model->dataPoints().value("ModVAvg").isValid()) { debug.nospace().noquote() << model->averageModuleVoltage() << "\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("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("CellVMaxStk") << "-->"; if (model->dataPoints().value("CellVMaxStk").isValid()) { debug.nospace().noquote() << model->maxCellVoltageStack() << "\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("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("CellVMinStk") << "-->"; if (model->dataPoints().value("CellVMinStk").isValid()) { debug.nospace().noquote() << model->minCellVoltageStack() << "\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("TmpMax") << "-->"; if (model->dataPoints().value("TmpMax").isValid()) { debug.nospace().noquote() << model->maxTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("TmpMaxMod") << "-->"; if (model->dataPoints().value("TmpMaxMod").isValid()) { debug.nospace().noquote() << model->maxTemperatureModule() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("TmpMin") << "-->"; if (model->dataPoints().value("TmpMin").isValid()) { debug.nospace().noquote() << model->minTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("TmpMinMod") << "-->"; if (model->dataPoints().value("TmpMinMod").isValid()) { debug.nospace().noquote() << model->minTemperatureModule() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("TmpAvg") << "-->"; if (model->dataPoints().value("TmpAvg").isValid()) { debug.nospace().noquote() << model->averageTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("Evt1") << "-->"; if (model->dataPoints().value("Evt1").isValid()) { debug.nospace().noquote() << model->stringEvent1() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("Evt2") << "-->"; if (model->dataPoints().value("Evt2").isValid()) { debug.nospace().noquote() << model->stringEvent2() << "\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("Pad1") << "-->"; if (model->dataPoints().value("Pad1").isValid()) { debug.nospace().noquote() << model->pad1() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } return debug.space().quote(); }