/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 "sunspeclithiumionmodulemodel.h" #include "sunspecconnection.h" SunSpecLithiumIonModuleModelRepeatingBlock::SunSpecLithiumIonModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonModuleModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { m_byteOrder = parent->byteOrder(); initDataPoints(); } QString SunSpecLithiumIonModuleModelRepeatingBlock::name() const { return "lithium-ion-module-cell"; } SunSpecLithiumIonModuleModel *SunSpecLithiumIonModuleModelRepeatingBlock::parentModel() const { return m_parentModel; } float SunSpecLithiumIonModuleModelRepeatingBlock::cellVoltage() const { return m_cellVoltage; } float SunSpecLithiumIonModuleModelRepeatingBlock::cellTemperature() const { return m_cellTemperature; } SunSpecLithiumIonModuleModelRepeatingBlock::CellstFlags SunSpecLithiumIonModuleModelRepeatingBlock::cellStatus() const { return m_cellStatus; } void SunSpecLithiumIonModuleModelRepeatingBlock::initDataPoints() { SunSpecDataPoint cellVoltageDataPoint; cellVoltageDataPoint.setName("CellV"); cellVoltageDataPoint.setLabel("Cell Voltage"); cellVoltageDataPoint.setDescription("Cell terminal voltage."); cellVoltageDataPoint.setUnits("V"); cellVoltageDataPoint.setMandatory(true); cellVoltageDataPoint.setSize(1); cellVoltageDataPoint.setAddressOffset(0); cellVoltageDataPoint.setScaleFactorName("CellV_SF"); cellVoltageDataPoint.setSunSpecDataType("uint16"); cellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(cellVoltageDataPoint.name(), cellVoltageDataPoint); SunSpecDataPoint cellTemperatureDataPoint; cellTemperatureDataPoint.setName("CellTmp"); cellTemperatureDataPoint.setLabel("Cell Temperature"); cellTemperatureDataPoint.setDescription("Cell temperature."); cellTemperatureDataPoint.setUnits("C"); cellTemperatureDataPoint.setMandatory(true); cellTemperatureDataPoint.setSize(1); cellTemperatureDataPoint.setAddressOffset(1); cellTemperatureDataPoint.setScaleFactorName("Tmp_SF"); cellTemperatureDataPoint.setSunSpecDataType("int16"); cellTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(cellTemperatureDataPoint.name(), cellTemperatureDataPoint); SunSpecDataPoint cellStatusDataPoint; cellStatusDataPoint.setName("CellSt"); cellStatusDataPoint.setLabel("Cell Status"); cellStatusDataPoint.setDescription("Status of the cell."); cellStatusDataPoint.setSize(2); cellStatusDataPoint.setAddressOffset(2); cellStatusDataPoint.setBlockOffset(0); cellStatusDataPoint.setSunSpecDataType("bitfield32"); cellStatusDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(cellStatusDataPoint.name(), cellStatusDataPoint); } void SunSpecLithiumIonModuleModelRepeatingBlock::processBlockData(const QVector blockData) { m_blockData = blockData; // Update properties according to the data point type if (m_dataPoints.value("CellV").isValid()) m_cellVoltage = m_dataPoints.value("CellV").toFloatWithSSF(m_parentModel->cellV_SF()); if (m_dataPoints.value("CellTmp").isValid()) m_cellTemperature = m_dataPoints.value("CellTmp").toFloatWithSSF(m_parentModel->tmp_SF()); if (m_dataPoints.value("CellSt").isValid()) m_cellStatus = static_cast(m_dataPoints.value("CellSt").toUInt32()); qCDebug(dcSunSpecModelData()) << this; } SunSpecLithiumIonModuleModel::SunSpecLithiumIonModuleModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) : SunSpecModel(connection, modbusStartRegister, 805, modelLength, byteOrder, parent) { m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); } SunSpecLithiumIonModuleModel::~SunSpecLithiumIonModuleModel() { } QString SunSpecLithiumIonModuleModel::name() const { return "lithium-ion-module"; } QString SunSpecLithiumIonModuleModel::description() const { return QString(); } QString SunSpecLithiumIonModuleModel::label() const { return "Lithium-Ion Module Model"; } quint16 SunSpecLithiumIonModuleModel::stringIndex() const { return m_stringIndex; } quint16 SunSpecLithiumIonModuleModel::moduleIndex() const { return m_moduleIndex; } quint16 SunSpecLithiumIonModuleModel::moduleCellCount() const { return m_moduleCellCount; } float SunSpecLithiumIonModuleModel::moduleSoC() const { return m_moduleSoC; } float SunSpecLithiumIonModuleModel::depthOfDischarge() const { return m_depthOfDischarge; } float SunSpecLithiumIonModuleModel::moduleSoH() const { return m_moduleSoH; } quint32 SunSpecLithiumIonModuleModel::cycleCount() const { return m_cycleCount; } float SunSpecLithiumIonModuleModel::moduleVoltage() const { return m_moduleVoltage; } float SunSpecLithiumIonModuleModel::maxCellVoltage() const { return m_maxCellVoltage; } quint16 SunSpecLithiumIonModuleModel::maxCellVoltageCell() const { return m_maxCellVoltageCell; } float SunSpecLithiumIonModuleModel::minCellVoltage() const { return m_minCellVoltage; } quint16 SunSpecLithiumIonModuleModel::minCellVoltageCell() const { return m_minCellVoltageCell; } float SunSpecLithiumIonModuleModel::averageCellVoltage() const { return m_averageCellVoltage; } float SunSpecLithiumIonModuleModel::maxCellTemperature() const { return m_maxCellTemperature; } quint16 SunSpecLithiumIonModuleModel::maxCellTemperatureCell() const { return m_maxCellTemperatureCell; } float SunSpecLithiumIonModuleModel::minCellTemperature() const { return m_minCellTemperature; } quint16 SunSpecLithiumIonModuleModel::minCellTemperatureCell() const { return m_minCellTemperatureCell; } float SunSpecLithiumIonModuleModel::averageCellTemperature() const { return m_averageCellTemperature; } quint16 SunSpecLithiumIonModuleModel::balancedCellCount() const { return m_balancedCellCount; } QString SunSpecLithiumIonModuleModel::serialNumber() const { return m_serialNumber; } qint16 SunSpecLithiumIonModuleModel::soC_SF() const { return m_soC_SF; } qint16 SunSpecLithiumIonModuleModel::soH_SF() const { return m_soH_SF; } qint16 SunSpecLithiumIonModuleModel::doD_SF() const { return m_doD_SF; } qint16 SunSpecLithiumIonModuleModel::v_SF() const { return m_v_SF; } qint16 SunSpecLithiumIonModuleModel::cellV_SF() const { return m_cellV_SF; } qint16 SunSpecLithiumIonModuleModel::tmp_SF() const { return m_tmp_SF; } void SunSpecLithiumIonModuleModel::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("StrIdx"); stringIndexDataPoint.setLabel("String Index"); stringIndexDataPoint.setDescription("Index of the string containing the module."); 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 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(3); moduleIndexDataPoint.setBlockOffset(1); moduleIndexDataPoint.setSunSpecDataType("uint16"); moduleIndexDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleIndexDataPoint.name(), moduleIndexDataPoint); SunSpecDataPoint moduleCellCountDataPoint; moduleCellCountDataPoint.setName("NCell"); moduleCellCountDataPoint.setLabel("Module Cell Count"); moduleCellCountDataPoint.setDescription("Count of all cells in the module."); moduleCellCountDataPoint.setMandatory(true); moduleCellCountDataPoint.setSize(1); moduleCellCountDataPoint.setAddressOffset(4); moduleCellCountDataPoint.setBlockOffset(2); moduleCellCountDataPoint.setSunSpecDataType("uint16"); moduleCellCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleCellCountDataPoint.name(), moduleCellCountDataPoint); SunSpecDataPoint moduleSoCDataPoint; moduleSoCDataPoint.setName("SoC"); moduleSoCDataPoint.setLabel("Module SoC"); moduleSoCDataPoint.setDescription("Module state of charge, expressed as a percentage."); moduleSoCDataPoint.setUnits("%"); moduleSoCDataPoint.setSize(1); moduleSoCDataPoint.setAddressOffset(5); moduleSoCDataPoint.setBlockOffset(3); moduleSoCDataPoint.setScaleFactorName("SoC_SF"); moduleSoCDataPoint.setSunSpecDataType("uint16"); moduleSoCDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleSoCDataPoint.name(), moduleSoCDataPoint); SunSpecDataPoint depthOfDischargeDataPoint; depthOfDischargeDataPoint.setName("DoD"); depthOfDischargeDataPoint.setLabel("Depth of Discharge"); depthOfDischargeDataPoint.setDescription("Depth of discharge for the module."); depthOfDischargeDataPoint.setUnits("%"); depthOfDischargeDataPoint.setSize(1); depthOfDischargeDataPoint.setAddressOffset(6); depthOfDischargeDataPoint.setBlockOffset(4); depthOfDischargeDataPoint.setScaleFactorName("DoD_SF"); depthOfDischargeDataPoint.setSunSpecDataType("uint16"); depthOfDischargeDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(depthOfDischargeDataPoint.name(), depthOfDischargeDataPoint); SunSpecDataPoint moduleSoHDataPoint; moduleSoHDataPoint.setName("SoH"); moduleSoHDataPoint.setLabel("Module SoH"); moduleSoHDataPoint.setDescription("Module state of health, expressed as a percentage."); moduleSoHDataPoint.setUnits("%"); moduleSoHDataPoint.setSize(1); moduleSoHDataPoint.setAddressOffset(7); moduleSoHDataPoint.setBlockOffset(5); moduleSoHDataPoint.setScaleFactorName("SoH_SF"); moduleSoHDataPoint.setSunSpecDataType("uint16"); moduleSoHDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleSoHDataPoint.name(), moduleSoHDataPoint); SunSpecDataPoint cycleCountDataPoint; cycleCountDataPoint.setName("NCyc"); cycleCountDataPoint.setLabel("Cycle Count"); cycleCountDataPoint.setDescription("Count of cycles executed."); cycleCountDataPoint.setSize(2); cycleCountDataPoint.setAddressOffset(8); cycleCountDataPoint.setBlockOffset(6); cycleCountDataPoint.setSunSpecDataType("uint32"); cycleCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(cycleCountDataPoint.name(), cycleCountDataPoint); SunSpecDataPoint moduleVoltageDataPoint; moduleVoltageDataPoint.setName("V"); moduleVoltageDataPoint.setLabel("Module Voltage"); moduleVoltageDataPoint.setDescription("Voltage of the module."); moduleVoltageDataPoint.setUnits("V"); moduleVoltageDataPoint.setMandatory(true); moduleVoltageDataPoint.setSize(1); moduleVoltageDataPoint.setAddressOffset(10); moduleVoltageDataPoint.setBlockOffset(8); moduleVoltageDataPoint.setScaleFactorName("V_SF"); moduleVoltageDataPoint.setSunSpecDataType("uint16"); moduleVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(moduleVoltageDataPoint.name(), moduleVoltageDataPoint); SunSpecDataPoint maxCellVoltageDataPoint; maxCellVoltageDataPoint.setName("CellVMax"); maxCellVoltageDataPoint.setLabel("Max Cell Voltage"); maxCellVoltageDataPoint.setDescription("Maximum voltage for all cells in the module."); maxCellVoltageDataPoint.setUnits("V"); maxCellVoltageDataPoint.setMandatory(true); maxCellVoltageDataPoint.setSize(1); maxCellVoltageDataPoint.setAddressOffset(11); maxCellVoltageDataPoint.setBlockOffset(9); maxCellVoltageDataPoint.setScaleFactorName("CellV_SF"); maxCellVoltageDataPoint.setSunSpecDataType("uint16"); maxCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageDataPoint.name(), maxCellVoltageDataPoint); SunSpecDataPoint maxCellVoltageCellDataPoint; maxCellVoltageCellDataPoint.setName("CellVMaxCell"); maxCellVoltageCellDataPoint.setLabel("Max Cell Voltage Cell"); maxCellVoltageCellDataPoint.setDescription("Cell with the maximum voltage."); maxCellVoltageCellDataPoint.setSize(1); maxCellVoltageCellDataPoint.setAddressOffset(12); maxCellVoltageCellDataPoint.setBlockOffset(10); maxCellVoltageCellDataPoint.setSunSpecDataType("uint16"); maxCellVoltageCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellVoltageCellDataPoint.name(), maxCellVoltageCellDataPoint); SunSpecDataPoint minCellVoltageDataPoint; minCellVoltageDataPoint.setName("CellVMin"); minCellVoltageDataPoint.setLabel("Min Cell Voltage"); minCellVoltageDataPoint.setDescription("Minimum voltage for all cells in the module."); minCellVoltageDataPoint.setUnits("V"); minCellVoltageDataPoint.setMandatory(true); 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 minCellVoltageCellDataPoint; minCellVoltageCellDataPoint.setName("CellVMinCell"); minCellVoltageCellDataPoint.setLabel("Min Cell Voltage Cell"); minCellVoltageCellDataPoint.setDescription("Cell with the minimum voltage."); minCellVoltageCellDataPoint.setSize(1); minCellVoltageCellDataPoint.setAddressOffset(14); minCellVoltageCellDataPoint.setBlockOffset(12); minCellVoltageCellDataPoint.setSunSpecDataType("uint16"); minCellVoltageCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellVoltageCellDataPoint.name(), minCellVoltageCellDataPoint); SunSpecDataPoint averageCellVoltageDataPoint; averageCellVoltageDataPoint.setName("CellVAvg"); averageCellVoltageDataPoint.setLabel("Average Cell Voltage"); averageCellVoltageDataPoint.setDescription("Average voltage for all cells in the module."); averageCellVoltageDataPoint.setUnits("V"); averageCellVoltageDataPoint.setMandatory(true); averageCellVoltageDataPoint.setSize(1); averageCellVoltageDataPoint.setAddressOffset(15); averageCellVoltageDataPoint.setBlockOffset(13); averageCellVoltageDataPoint.setScaleFactorName("CellV_SF"); averageCellVoltageDataPoint.setSunSpecDataType("uint16"); averageCellVoltageDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageCellVoltageDataPoint.name(), averageCellVoltageDataPoint); SunSpecDataPoint maxCellTemperatureDataPoint; maxCellTemperatureDataPoint.setName("CellTmpMax"); maxCellTemperatureDataPoint.setLabel("Max Cell Temperature"); maxCellTemperatureDataPoint.setDescription("Maximum temperature for all cells in the module."); maxCellTemperatureDataPoint.setUnits("C"); maxCellTemperatureDataPoint.setMandatory(true); maxCellTemperatureDataPoint.setSize(1); maxCellTemperatureDataPoint.setAddressOffset(16); maxCellTemperatureDataPoint.setBlockOffset(14); maxCellTemperatureDataPoint.setScaleFactorName("Tmp_SF"); maxCellTemperatureDataPoint.setSunSpecDataType("int16"); maxCellTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellTemperatureDataPoint.name(), maxCellTemperatureDataPoint); SunSpecDataPoint maxCellTemperatureCellDataPoint; maxCellTemperatureCellDataPoint.setName("CellTmpMaxCell"); maxCellTemperatureCellDataPoint.setLabel("Max Cell Temperature Cell"); maxCellTemperatureCellDataPoint.setDescription("Cell with the maximum cell temperature."); maxCellTemperatureCellDataPoint.setSize(1); maxCellTemperatureCellDataPoint.setAddressOffset(17); maxCellTemperatureCellDataPoint.setBlockOffset(15); maxCellTemperatureCellDataPoint.setSunSpecDataType("uint16"); maxCellTemperatureCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(maxCellTemperatureCellDataPoint.name(), maxCellTemperatureCellDataPoint); SunSpecDataPoint minCellTemperatureDataPoint; minCellTemperatureDataPoint.setName("CellTmpMin"); minCellTemperatureDataPoint.setLabel("Min Cell Temperature"); minCellTemperatureDataPoint.setDescription("Minimum temperature for all cells in the module."); minCellTemperatureDataPoint.setUnits("C"); minCellTemperatureDataPoint.setMandatory(true); minCellTemperatureDataPoint.setSize(1); minCellTemperatureDataPoint.setAddressOffset(18); minCellTemperatureDataPoint.setBlockOffset(16); minCellTemperatureDataPoint.setScaleFactorName("Tmp_SF"); minCellTemperatureDataPoint.setSunSpecDataType("int16"); minCellTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellTemperatureDataPoint.name(), minCellTemperatureDataPoint); SunSpecDataPoint minCellTemperatureCellDataPoint; minCellTemperatureCellDataPoint.setName("CellTmpMinCell"); minCellTemperatureCellDataPoint.setLabel("Min Cell Temperature Cell"); minCellTemperatureCellDataPoint.setDescription("Cell with the minimum cell temperature."); minCellTemperatureCellDataPoint.setSize(1); minCellTemperatureCellDataPoint.setAddressOffset(19); minCellTemperatureCellDataPoint.setBlockOffset(17); minCellTemperatureCellDataPoint.setSunSpecDataType("uint16"); minCellTemperatureCellDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(minCellTemperatureCellDataPoint.name(), minCellTemperatureCellDataPoint); SunSpecDataPoint averageCellTemperatureDataPoint; averageCellTemperatureDataPoint.setName("CellTmpAvg"); averageCellTemperatureDataPoint.setLabel("Average Cell Temperature"); averageCellTemperatureDataPoint.setDescription("Average temperature for all cells in the module."); averageCellTemperatureDataPoint.setUnits("C"); averageCellTemperatureDataPoint.setMandatory(true); averageCellTemperatureDataPoint.setSize(1); averageCellTemperatureDataPoint.setAddressOffset(20); averageCellTemperatureDataPoint.setBlockOffset(18); averageCellTemperatureDataPoint.setScaleFactorName("Tmp_SF"); averageCellTemperatureDataPoint.setSunSpecDataType("int16"); averageCellTemperatureDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(averageCellTemperatureDataPoint.name(), averageCellTemperatureDataPoint); SunSpecDataPoint balancedCellCountDataPoint; balancedCellCountDataPoint.setName("NCellBal"); balancedCellCountDataPoint.setLabel("Balanced Cell Count"); balancedCellCountDataPoint.setDescription("Number of cells currently being balanced in the module."); balancedCellCountDataPoint.setSize(1); balancedCellCountDataPoint.setAddressOffset(21); balancedCellCountDataPoint.setBlockOffset(19); balancedCellCountDataPoint.setSunSpecDataType("uint16"); balancedCellCountDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(balancedCellCountDataPoint.name(), balancedCellCountDataPoint); SunSpecDataPoint serialNumberDataPoint; serialNumberDataPoint.setName("SN"); serialNumberDataPoint.setLabel("Serial Number"); serialNumberDataPoint.setDescription("Serial number for the module."); serialNumberDataPoint.setSize(16); serialNumberDataPoint.setAddressOffset(22); serialNumberDataPoint.setBlockOffset(20); serialNumberDataPoint.setSunSpecDataType("string"); serialNumberDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(serialNumberDataPoint.name(), serialNumberDataPoint); SunSpecDataPoint soC_SFDataPoint; soC_SFDataPoint.setName("SoC_SF"); soC_SFDataPoint.setDescription("Scale factor for module state of charge."); soC_SFDataPoint.setSize(1); soC_SFDataPoint.setAddressOffset(38); soC_SFDataPoint.setBlockOffset(36); soC_SFDataPoint.setSunSpecDataType("sunssf"); soC_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(soC_SFDataPoint.name(), soC_SFDataPoint); SunSpecDataPoint soH_SFDataPoint; soH_SFDataPoint.setName("SoH_SF"); soH_SFDataPoint.setDescription("Scale factor for module state of health."); soH_SFDataPoint.setSize(1); soH_SFDataPoint.setAddressOffset(39); soH_SFDataPoint.setBlockOffset(37); soH_SFDataPoint.setSunSpecDataType("sunssf"); soH_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(soH_SFDataPoint.name(), soH_SFDataPoint); SunSpecDataPoint doD_SFDataPoint; doD_SFDataPoint.setName("DoD_SF"); doD_SFDataPoint.setDescription("Scale factor for module depth of discharge."); doD_SFDataPoint.setSize(1); doD_SFDataPoint.setAddressOffset(40); doD_SFDataPoint.setBlockOffset(38); doD_SFDataPoint.setSunSpecDataType("sunssf"); doD_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(doD_SFDataPoint.name(), doD_SFDataPoint); SunSpecDataPoint v_SFDataPoint; v_SFDataPoint.setName("V_SF"); v_SFDataPoint.setDescription("Scale factor for module voltage."); v_SFDataPoint.setMandatory(true); v_SFDataPoint.setSize(1); v_SFDataPoint.setAddressOffset(41); v_SFDataPoint.setBlockOffset(39); 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(42); cellV_SFDataPoint.setBlockOffset(40); 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 module temperature."); tmp_SFDataPoint.setMandatory(true); tmp_SFDataPoint.setSize(1); tmp_SFDataPoint.setAddressOffset(43); tmp_SFDataPoint.setBlockOffset(41); tmp_SFDataPoint.setSunSpecDataType("sunssf"); tmp_SFDataPoint.setByteOrder(m_byteOrder); m_dataPoints.insert(tmp_SFDataPoint.name(), tmp_SFDataPoint); } void SunSpecLithiumIonModuleModel::processBlockData() { // Scale factors if (m_dataPoints.value("SoC_SF").isValid()) m_soC_SF = m_dataPoints.value("SoC_SF").toInt16(); if (m_dataPoints.value("SoH_SF").isValid()) m_soH_SF = m_dataPoints.value("SoH_SF").toInt16(); if (m_dataPoints.value("DoD_SF").isValid()) m_doD_SF = m_dataPoints.value("DoD_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("Tmp_SF").isValid()) m_tmp_SF = m_dataPoints.value("Tmp_SF").toInt16(); // Update properties according to the data point type if (m_dataPoints.value("StrIdx").isValid()) m_stringIndex = m_dataPoints.value("StrIdx").toUInt16(); if (m_dataPoints.value("ModIdx").isValid()) m_moduleIndex = m_dataPoints.value("ModIdx").toUInt16(); if (m_dataPoints.value("NCell").isValid()) m_moduleCellCount = m_dataPoints.value("NCell").toUInt16(); if (m_dataPoints.value("SoC").isValid()) m_moduleSoC = 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_moduleSoH = 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("V").isValid()) m_moduleVoltage = m_dataPoints.value("V").toFloatWithSSF(m_v_SF); if (m_dataPoints.value("CellVMax").isValid()) m_maxCellVoltage = m_dataPoints.value("CellVMax").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("CellVMaxCell").isValid()) m_maxCellVoltageCell = m_dataPoints.value("CellVMaxCell").toUInt16(); if (m_dataPoints.value("CellVMin").isValid()) m_minCellVoltage = m_dataPoints.value("CellVMin").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("CellVMinCell").isValid()) m_minCellVoltageCell = m_dataPoints.value("CellVMinCell").toUInt16(); if (m_dataPoints.value("CellVAvg").isValid()) m_averageCellVoltage = m_dataPoints.value("CellVAvg").toFloatWithSSF(m_cellV_SF); if (m_dataPoints.value("CellTmpMax").isValid()) m_maxCellTemperature = m_dataPoints.value("CellTmpMax").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("CellTmpMaxCell").isValid()) m_maxCellTemperatureCell = m_dataPoints.value("CellTmpMaxCell").toUInt16(); if (m_dataPoints.value("CellTmpMin").isValid()) m_minCellTemperature = m_dataPoints.value("CellTmpMin").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("CellTmpMinCell").isValid()) m_minCellTemperatureCell = m_dataPoints.value("CellTmpMinCell").toUInt16(); if (m_dataPoints.value("CellTmpAvg").isValid()) m_averageCellTemperature = m_dataPoints.value("CellTmpAvg").toFloatWithSSF(m_tmp_SF); if (m_dataPoints.value("NCellBal").isValid()) m_balancedCellCount = m_dataPoints.value("NCellBal").toUInt16(); if (m_dataPoints.value("SN").isValid()) m_serialNumber = m_dataPoints.value("SN").toString(); if (m_dataPoints.value("SoC_SF").isValid()) m_soC_SF = m_dataPoints.value("SoC_SF").toInt16(); if (m_dataPoints.value("SoH_SF").isValid()) m_soH_SF = m_dataPoints.value("SoH_SF").toInt16(); if (m_dataPoints.value("DoD_SF").isValid()) m_doD_SF = m_dataPoints.value("DoD_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("Tmp_SF").isValid()) m_tmp_SF = m_dataPoints.value("Tmp_SF").toInt16(); qCDebug(dcSunSpecModelData()) << this; } QDebug operator<<(QDebug debug, SunSpecLithiumIonModuleModel *model) { debug.nospace().noquote() << "SunSpecLithiumIonModuleModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; debug.nospace().noquote() << " - " << model->dataPoints().value("StrIdx") << "-->"; if (model->dataPoints().value("StrIdx").isValid()) { debug.nospace().noquote() << model->stringIndex() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("ModIdx") << "-->"; if (model->dataPoints().value("ModIdx").isValid()) { debug.nospace().noquote() << model->moduleIndex() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("NCell") << "-->"; if (model->dataPoints().value("NCell").isValid()) { debug.nospace().noquote() << model->moduleCellCount() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("SoC") << "-->"; if (model->dataPoints().value("SoC").isValid()) { debug.nospace().noquote() << model->moduleSoC() << "\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->moduleSoH() << "\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("V") << "-->"; if (model->dataPoints().value("V").isValid()) { debug.nospace().noquote() << model->moduleVoltage() << "\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("CellVMaxCell") << "-->"; if (model->dataPoints().value("CellVMaxCell").isValid()) { debug.nospace().noquote() << model->maxCellVoltageCell() << "\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("CellVMinCell") << "-->"; if (model->dataPoints().value("CellVMinCell").isValid()) { debug.nospace().noquote() << model->minCellVoltageCell() << "\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("CellTmpMax") << "-->"; if (model->dataPoints().value("CellTmpMax").isValid()) { debug.nospace().noquote() << model->maxCellTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("CellTmpMaxCell") << "-->"; if (model->dataPoints().value("CellTmpMaxCell").isValid()) { debug.nospace().noquote() << model->maxCellTemperatureCell() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("CellTmpMin") << "-->"; if (model->dataPoints().value("CellTmpMin").isValid()) { debug.nospace().noquote() << model->minCellTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("CellTmpMinCell") << "-->"; if (model->dataPoints().value("CellTmpMinCell").isValid()) { debug.nospace().noquote() << model->minCellTemperatureCell() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("CellTmpAvg") << "-->"; if (model->dataPoints().value("CellTmpAvg").isValid()) { debug.nospace().noquote() << model->averageCellTemperature() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("NCellBal") << "-->"; if (model->dataPoints().value("NCellBal").isValid()) { debug.nospace().noquote() << model->balancedCellCount() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } debug.nospace().noquote() << " - " << model->dataPoints().value("SN") << "-->"; if (model->dataPoints().value("SN").isValid()) { debug.nospace().noquote() << model->serialNumber() << "\n"; } else { debug.nospace().noquote() << "NaN\n"; } return debug.space().quote(); }