From 3944f2c98402dffbd6c2a39ff1b5eb6ae689ea97 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Oct 2025 11:12:28 +0200 Subject: [PATCH] Implement handling of SunSpec repeating blocks. * Update code generator to create code for setting up SunSpecModelRepeatingBlock subclasses automatically. * Update SunSpecModel class to provide access to its repeating blocks and to forward received raw data to its repeating blocks. * Use updated code generator to regenerate model classes. --- .../models/sunspecaggregatormodel.cpp | 2 +- .../models/sunspecaggregatormodel.h | 2 +- .../models/sunspecbasemetmodel.cpp | 2 +- libnymea-sunspec/models/sunspecbasemetmodel.h | 2 +- .../models/sunspecbatterymodel.cpp | 2 +- libnymea-sunspec/models/sunspecbatterymodel.h | 2 +- .../models/sunspeccommonmodel.cpp | 2 +- libnymea-sunspec/models/sunspeccommonmodel.h | 2 +- .../models/sunspeccontrolsmodel.cpp | 2 +- .../models/sunspeccontrolsmodel.h | 2 +- ...pecdeltaconnectthreephaseabcmetermodel.cpp | 2 +- ...nspecdeltaconnectthreephaseabcmetermodel.h | 2 +- ...cenergystoragebasemodeldeprecatedmodel.cpp | 2 +- ...pecenergystoragebasemodeldeprecatedmodel.h | 2 +- .../models/sunspecextsettingsmodel.cpp | 2 +- .../models/sunspecextsettingsmodel.h | 2 +- .../models/sunspecflowbatterymodel.cpp | 37 +++++++++++-- .../models/sunspecflowbatterymodel.h | 9 ++- .../models/sunspecflowbatterymodulemodel.cpp | 37 +++++++++++-- .../models/sunspecflowbatterymodulemodel.h | 9 ++- .../models/sunspecflowbatterystackmodel.cpp | 37 +++++++++++-- .../models/sunspecflowbatterystackmodel.h | 9 ++- .../models/sunspecflowbatterystringmodel.cpp | 37 +++++++++++-- .../models/sunspecflowbatterystringmodel.h | 9 ++- .../models/sunspecfreqwattmodel.cpp | 37 +++++++++++-- .../models/sunspecfreqwattmodel.h | 9 ++- .../models/sunspecfreqwattparammodel.cpp | 2 +- .../models/sunspecfreqwattparammodel.h | 2 +- libnymea-sunspec/models/sunspechfrtcmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechfrtcmodel.h | 9 ++- libnymea-sunspec/models/sunspechfrtmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechfrtmodel.h | 9 ++- libnymea-sunspec/models/sunspechfrtxmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechfrtxmodel.h | 9 ++- libnymea-sunspec/models/sunspechvrtcmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechvrtcmodel.h | 9 ++- libnymea-sunspec/models/sunspechvrtmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechvrtmodel.h | 9 ++- libnymea-sunspec/models/sunspechvrtxmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspechvrtxmodel.h | 9 ++- .../sunspecinvertersinglephasefloatmodel.cpp | 2 +- .../sunspecinvertersinglephasefloatmodel.h | 2 +- .../sunspecinvertersinglephasemodel.cpp | 2 +- .../models/sunspecinvertersinglephasemodel.h | 2 +- .../sunspecinvertersplitphasefloatmodel.cpp | 2 +- .../sunspecinvertersplitphasefloatmodel.h | 2 +- .../models/sunspecinvertersplitphasemodel.cpp | 2 +- .../models/sunspecinvertersplitphasemodel.h | 2 +- .../sunspecinverterthreephasefloatmodel.cpp | 2 +- .../sunspecinverterthreephasefloatmodel.h | 2 +- .../models/sunspecinverterthreephasemodel.cpp | 2 +- .../models/sunspecinverterthreephasemodel.h | 2 +- .../models/sunspecirradiancemodel.cpp | 37 +++++++++++-- .../models/sunspecirradiancemodel.h | 9 ++- libnymea-sunspec/models/sunspeclfrtcmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclfrtcmodel.h | 9 ++- libnymea-sunspec/models/sunspeclfrtmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclfrtmodel.h | 9 ++- libnymea-sunspec/models/sunspeclfrtxmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclfrtxmodel.h | 9 ++- .../models/sunspeclithiumionbankmodel.cpp | 37 +++++++++++-- .../models/sunspeclithiumionbankmodel.h | 9 ++- .../models/sunspeclithiumionmodulemodel.cpp | 37 +++++++++++-- .../models/sunspeclithiumionmodulemodel.h | 9 ++- .../models/sunspeclithiumionstringmodel.cpp | 37 +++++++++++-- .../models/sunspeclithiumionstringmodel.h | 9 ++- .../models/sunspeclocationmodel.cpp | 2 +- .../models/sunspeclocationmodel.h | 2 +- libnymea-sunspec/models/sunspeclvrtcmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclvrtcmodel.h | 9 ++- libnymea-sunspec/models/sunspeclvrtmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclvrtmodel.h | 9 ++- libnymea-sunspec/models/sunspeclvrtxmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspeclvrtxmodel.h | 9 ++- .../sunspecmetersinglephasefloatmodel.cpp | 2 +- .../sunspecmetersinglephasefloatmodel.h | 2 +- .../models/sunspecmetersinglephasemodel.cpp | 2 +- .../models/sunspecmetersinglephasemodel.h | 2 +- .../sunspecmetersplitsinglephaseabnmodel.cpp | 2 +- .../sunspecmetersplitsinglephaseabnmodel.h | 2 +- ...sunspecmetersplitsinglephasefloatmodel.cpp | 2 +- .../sunspecmetersplitsinglephasefloatmodel.h | 2 +- ...unspecmeterthreephasedeltaconnectmodel.cpp | 2 +- .../sunspecmeterthreephasedeltaconnectmodel.h | 2 +- .../models/sunspecmeterthreephasemodel.cpp | 2 +- .../models/sunspecmeterthreephasemodel.h | 2 +- .../sunspecmeterthreephasewyeconnectmodel.cpp | 2 +- .../sunspecmeterthreephasewyeconnectmodel.h | 2 +- .../models/sunspecminimetmodel.cpp | 2 +- libnymea-sunspec/models/sunspecminimetmodel.h | 2 +- .../models/sunspecmodelfactory.cpp | 2 +- libnymea-sunspec/models/sunspecmodelfactory.h | 2 +- libnymea-sunspec/models/sunspecmpptmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspecmpptmodel.h | 9 ++- .../models/sunspecnameplatemodel.cpp | 2 +- .../models/sunspecnameplatemodel.h | 2 +- .../models/sunspecpricingmodel.cpp | 2 +- libnymea-sunspec/models/sunspecpricingmodel.h | 2 +- .../models/sunspecreactivecurrentmodel.cpp | 2 +- .../models/sunspecreactivecurrentmodel.h | 2 +- .../models/sunspecrefpointmodel.cpp | 2 +- .../models/sunspecrefpointmodel.h | 2 +- .../models/sunspecschedulemodel.cpp | 37 +++++++++++-- .../models/sunspecschedulemodel.h | 9 ++- ...specsecureacmeterselectedreadingsmodel.cpp | 37 +++++++++++-- ...unspecsecureacmeterselectedreadingsmodel.h | 9 ++- .../models/sunspecsettingsmodel.cpp | 2 +- .../models/sunspecsettingsmodel.h | 2 +- .../models/sunspecsolarmodulemodel.cpp | 2 +- .../models/sunspecsolarmodulemodel.h | 2 +- .../models/sunspecstatusmodel.cpp | 2 +- libnymea-sunspec/models/sunspecstatusmodel.h | 2 +- .../models/sunspecstoragemodel.cpp | 2 +- libnymea-sunspec/models/sunspecstoragemodel.h | 2 +- .../sunspecstringcombineradvancedmodel.cpp | 37 +++++++++++-- .../sunspecstringcombineradvancedmodel.h | 9 ++- .../sunspecstringcombinercurrentmodel.cpp | 37 +++++++++++-- .../sunspecstringcombinercurrentmodel.h | 9 ++- .../models/sunspectrackercontrollermodel.cpp | 37 +++++++++++-- .../models/sunspectrackercontrollermodel.h | 9 ++- .../models/sunspecvoltvarmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspecvoltvarmodel.h | 9 ++- .../models/sunspecvoltwattmodel.cpp | 37 +++++++++++-- .../models/sunspecvoltwattmodel.h | 9 ++- .../models/sunspecwattpfmodel.cpp | 37 +++++++++++-- libnymea-sunspec/models/sunspecwattpfmodel.h | 9 ++- libnymea-sunspec/sunspecdatapoint.cpp | 2 +- libnymea-sunspec/sunspecmodel.cpp | 37 +++++++++++++ libnymea-sunspec/sunspecmodel.h | 5 ++ libnymea-sunspec/sunspecmodelrepeatingblock.h | 6 +- libnymea-sunspec/tools/generate-models.py | 55 +++++++++++++++++-- 131 files changed, 1332 insertions(+), 285 deletions(-) diff --git a/libnymea-sunspec/models/sunspecaggregatormodel.cpp b/libnymea-sunspec/models/sunspecaggregatormodel.cpp index a0c5bf4..db6c4bd 100644 --- a/libnymea-sunspec/models/sunspecaggregatormodel.cpp +++ b/libnymea-sunspec/models/sunspecaggregatormodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecaggregatormodel.h b/libnymea-sunspec/models/sunspecaggregatormodel.h index 271ebcf..3fd5e36 100644 --- a/libnymea-sunspec/models/sunspecaggregatormodel.h +++ b/libnymea-sunspec/models/sunspecaggregatormodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecbasemetmodel.cpp b/libnymea-sunspec/models/sunspecbasemetmodel.cpp index 56b7ac2..6902372 100644 --- a/libnymea-sunspec/models/sunspecbasemetmodel.cpp +++ b/libnymea-sunspec/models/sunspecbasemetmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecbasemetmodel.h b/libnymea-sunspec/models/sunspecbasemetmodel.h index cdbda35..d68c1db 100644 --- a/libnymea-sunspec/models/sunspecbasemetmodel.h +++ b/libnymea-sunspec/models/sunspecbasemetmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecbatterymodel.cpp b/libnymea-sunspec/models/sunspecbatterymodel.cpp index 33d10f3..be67d40 100644 --- a/libnymea-sunspec/models/sunspecbatterymodel.cpp +++ b/libnymea-sunspec/models/sunspecbatterymodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecbatterymodel.h b/libnymea-sunspec/models/sunspecbatterymodel.h index 261dc6d..482457a 100644 --- a/libnymea-sunspec/models/sunspecbatterymodel.h +++ b/libnymea-sunspec/models/sunspecbatterymodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeccommonmodel.cpp b/libnymea-sunspec/models/sunspeccommonmodel.cpp index 0ba2688..a002a36 100644 --- a/libnymea-sunspec/models/sunspeccommonmodel.cpp +++ b/libnymea-sunspec/models/sunspeccommonmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeccommonmodel.h b/libnymea-sunspec/models/sunspeccommonmodel.h index 4f61400..a667a3d 100644 --- a/libnymea-sunspec/models/sunspeccommonmodel.h +++ b/libnymea-sunspec/models/sunspeccommonmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeccontrolsmodel.cpp b/libnymea-sunspec/models/sunspeccontrolsmodel.cpp index dacef9f..fb72328 100644 --- a/libnymea-sunspec/models/sunspeccontrolsmodel.cpp +++ b/libnymea-sunspec/models/sunspeccontrolsmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeccontrolsmodel.h b/libnymea-sunspec/models/sunspeccontrolsmodel.h index 2562268..a006643 100644 --- a/libnymea-sunspec/models/sunspeccontrolsmodel.h +++ b/libnymea-sunspec/models/sunspeccontrolsmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.cpp b/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.cpp index 046f07e..84a0348 100644 --- a/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.cpp +++ b/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.h b/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.h index 14f33c3..e25e6e0 100644 --- a/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.h +++ b/libnymea-sunspec/models/sunspecdeltaconnectthreephaseabcmetermodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.cpp b/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.cpp index 88fc70a..e699f84 100644 --- a/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.cpp +++ b/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.h b/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.h index d96e05f..591b229 100644 --- a/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.h +++ b/libnymea-sunspec/models/sunspecenergystoragebasemodeldeprecatedmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecextsettingsmodel.cpp b/libnymea-sunspec/models/sunspecextsettingsmodel.cpp index 57c7f20..00e8750 100644 --- a/libnymea-sunspec/models/sunspecextsettingsmodel.cpp +++ b/libnymea-sunspec/models/sunspecextsettingsmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecextsettingsmodel.h b/libnymea-sunspec/models/sunspecextsettingsmodel.h index 84a53a8..0e5c6fb 100644 --- a/libnymea-sunspec/models/sunspecextsettingsmodel.h +++ b/libnymea-sunspec/models/sunspecextsettingsmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecflowbatterymodel.cpp b/libnymea-sunspec/models/sunspecflowbatterymodel.cpp index d7a607b..85161f3 100644 --- a/libnymea-sunspec/models/sunspecflowbatterymodel.cpp +++ b/libnymea-sunspec/models/sunspecflowbatterymodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecFlowBatteryModelRepeatingBlock::SunSpecFlowBatteryModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -67,10 +68,8 @@ void SunSpecFlowBatteryModelRepeatingBlock::initDataPoints() } -void SunSpecFlowBatteryModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecFlowBatteryModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("BatStTBD").isValid()) m_batteryStringPointsToBeDetermined = m_dataPoints.value("BatStTBD").toUInt16(); @@ -86,6 +85,8 @@ SunSpecFlowBatteryModel::SunSpecFlowBatteryModel(SunSpecConnection *connection, m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecFlowBatteryModel::setupRepeatingBlocks); } SunSpecFlowBatteryModel::~SunSpecFlowBatteryModel() @@ -159,6 +160,34 @@ void SunSpecFlowBatteryModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecFlowBatteryModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecFlowBatteryModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecFlowBatteryModel *model) { debug.nospace().noquote() << "SunSpecFlowBatteryModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecflowbatterymodel.h b/libnymea-sunspec/models/sunspecflowbatterymodel.h index 68db10b..5dd3b15 100644 --- a/libnymea-sunspec/models/sunspecflowbatterymodel.h +++ b/libnymea-sunspec/models/sunspecflowbatterymodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecFlowBatteryModelRepeatingBlock : public SunSpecModelRepeatingBlock Q_OBJECT public: - explicit SunSpecFlowBatteryModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModel *parent = nullptr); + explicit SunSpecFlowBatteryModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModel *parent); ~SunSpecFlowBatteryModelRepeatingBlock() override = default; SunSpecFlowBatteryModel *parentModel() const; @@ -53,7 +53,7 @@ public: /* Battery String Points To Be Determined */ quint16 batteryStringPointsToBeDetermined() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -90,6 +90,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_batteryPointsToBeDetermined = 0; diff --git a/libnymea-sunspec/models/sunspecflowbatterymodulemodel.cpp b/libnymea-sunspec/models/sunspecflowbatterymodulemodel.cpp index 84a0c58..52abef7 100644 --- a/libnymea-sunspec/models/sunspecflowbatterymodulemodel.cpp +++ b/libnymea-sunspec/models/sunspecflowbatterymodulemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecFlowBatteryModuleModelRepeatingBlock::SunSpecFlowBatteryModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModuleModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -67,10 +68,8 @@ void SunSpecFlowBatteryModuleModelRepeatingBlock::initDataPoints() } -void SunSpecFlowBatteryModuleModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecFlowBatteryModuleModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("StackTBD").isValid()) m_stackPointsToBeDetermined = m_dataPoints.value("StackTBD").toUInt16(); @@ -86,6 +85,8 @@ SunSpecFlowBatteryModuleModel::SunSpecFlowBatteryModuleModel(SunSpecConnection * m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecFlowBatteryModuleModel::setupRepeatingBlocks); } SunSpecFlowBatteryModuleModel::~SunSpecFlowBatteryModuleModel() @@ -159,6 +160,34 @@ void SunSpecFlowBatteryModuleModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecFlowBatteryModuleModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecFlowBatteryModuleModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecFlowBatteryModuleModel *model) { debug.nospace().noquote() << "SunSpecFlowBatteryModuleModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecflowbatterymodulemodel.h b/libnymea-sunspec/models/sunspecflowbatterymodulemodel.h index 86fab5f..3433a7b 100644 --- a/libnymea-sunspec/models/sunspecflowbatterymodulemodel.h +++ b/libnymea-sunspec/models/sunspecflowbatterymodulemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecFlowBatteryModuleModelRepeatingBlock : public SunSpecModelRepeating Q_OBJECT public: - explicit SunSpecFlowBatteryModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModuleModel *parent = nullptr); + explicit SunSpecFlowBatteryModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryModuleModel *parent); ~SunSpecFlowBatteryModuleModelRepeatingBlock() override = default; SunSpecFlowBatteryModuleModel *parentModel() const; @@ -53,7 +53,7 @@ public: /* Stack Points To Be Determined */ quint16 stackPointsToBeDetermined() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -90,6 +90,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_modulePointsToBeDetermined = 0; diff --git a/libnymea-sunspec/models/sunspecflowbatterystackmodel.cpp b/libnymea-sunspec/models/sunspecflowbatterystackmodel.cpp index f8fb6e2..8e00796 100644 --- a/libnymea-sunspec/models/sunspecflowbatterystackmodel.cpp +++ b/libnymea-sunspec/models/sunspecflowbatterystackmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecFlowBatteryStackModelRepeatingBlock::SunSpecFlowBatteryStackModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStackModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -67,10 +68,8 @@ void SunSpecFlowBatteryStackModelRepeatingBlock::initDataPoints() } -void SunSpecFlowBatteryStackModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecFlowBatteryStackModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("CellTBD").isValid()) m_cellPointsToBeDetermined = m_dataPoints.value("CellTBD").toUInt16(); @@ -86,6 +85,8 @@ SunSpecFlowBatteryStackModel::SunSpecFlowBatteryStackModel(SunSpecConnection *co m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecFlowBatteryStackModel::setupRepeatingBlocks); } SunSpecFlowBatteryStackModel::~SunSpecFlowBatteryStackModel() @@ -159,6 +160,34 @@ void SunSpecFlowBatteryStackModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecFlowBatteryStackModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecFlowBatteryStackModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecFlowBatteryStackModel *model) { debug.nospace().noquote() << "SunSpecFlowBatteryStackModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecflowbatterystackmodel.h b/libnymea-sunspec/models/sunspecflowbatterystackmodel.h index 248612f..fb4ce83 100644 --- a/libnymea-sunspec/models/sunspecflowbatterystackmodel.h +++ b/libnymea-sunspec/models/sunspecflowbatterystackmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecFlowBatteryStackModelRepeatingBlock : public SunSpecModelRepeatingB Q_OBJECT public: - explicit SunSpecFlowBatteryStackModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStackModel *parent = nullptr); + explicit SunSpecFlowBatteryStackModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStackModel *parent); ~SunSpecFlowBatteryStackModelRepeatingBlock() override = default; SunSpecFlowBatteryStackModel *parentModel() const; @@ -53,7 +53,7 @@ public: /* Cell Points To Be Determined */ quint16 cellPointsToBeDetermined() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -90,6 +90,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_stackPointsToBeDetermined = 0; diff --git a/libnymea-sunspec/models/sunspecflowbatterystringmodel.cpp b/libnymea-sunspec/models/sunspecflowbatterystringmodel.cpp index 9c624e6..2b3e240 100644 --- a/libnymea-sunspec/models/sunspecflowbatterystringmodel.cpp +++ b/libnymea-sunspec/models/sunspecflowbatterystringmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecFlowBatteryStringModelRepeatingBlock::SunSpecFlowBatteryStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStringModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -397,10 +398,8 @@ void SunSpecFlowBatteryStringModelRepeatingBlock::initDataPoints() } -void SunSpecFlowBatteryStringModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecFlowBatteryStringModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ModIdx").isValid()) m_moduleIndex = m_dataPoints.value("ModIdx").toUInt16(); @@ -473,6 +472,8 @@ SunSpecFlowBatteryStringModel::SunSpecFlowBatteryStringModel(SunSpecConnection * m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecFlowBatteryStringModel::setupRepeatingBlocks); } SunSpecFlowBatteryStringModel::~SunSpecFlowBatteryStringModel() @@ -1116,6 +1117,34 @@ void SunSpecFlowBatteryStringModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecFlowBatteryStringModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecFlowBatteryStringModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecFlowBatteryStringModel *model) { debug.nospace().noquote() << "SunSpecFlowBatteryStringModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecflowbatterystringmodel.h b/libnymea-sunspec/models/sunspecflowbatterystringmodel.h index 7be3fce..d326ab0 100644 --- a/libnymea-sunspec/models/sunspecflowbatterystringmodel.h +++ b/libnymea-sunspec/models/sunspecflowbatterystringmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -167,7 +167,7 @@ public: Q_DECLARE_FLAGS(Modevt2Flags, Modevt2) Q_FLAG(Modevt2) - explicit SunSpecFlowBatteryStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStringModel *parent = nullptr); + explicit SunSpecFlowBatteryStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFlowBatteryStringModel *parent); ~SunSpecFlowBatteryStringModelRepeatingBlock() override = default; SunSpecFlowBatteryStringModel *parentModel() const; @@ -219,7 +219,7 @@ public: /* Reason why the module is currently disabled. */ Moddisrsn disabledReason() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -378,6 +378,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_stringIndex = 0; quint16 m_moduleCount = 0; quint16 m_connectedModuleCount = 0; diff --git a/libnymea-sunspec/models/sunspecfreqwattmodel.cpp b/libnymea-sunspec/models/sunspecfreqwattmodel.cpp index 180acbb..d24c7f1 100644 --- a/libnymea-sunspec/models/sunspecfreqwattmodel.cpp +++ b/libnymea-sunspec/models/sunspecfreqwattmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecFreqWattModelRepeatingBlock::SunSpecFreqWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFreqWattModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1564,10 +1565,8 @@ void SunSpecFreqWattModelRepeatingBlock::initDataPoints() } -void SunSpecFreqWattModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecFreqWattModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1733,6 +1732,8 @@ SunSpecFreqWattModel::SunSpecFreqWattModel(SunSpecConnection *connection, quint1 m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecFreqWattModel::setupRepeatingBlocks); } SunSpecFreqWattModel::~SunSpecFreqWattModel() @@ -2066,6 +2067,34 @@ void SunSpecFreqWattModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecFreqWattModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecFreqWattModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecFreqWattModel *model) { debug.nospace().noquote() << "SunSpecFreqWattModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecfreqwattmodel.h b/libnymea-sunspec/models/sunspecfreqwattmodel.h index b4e5874..447b3ab 100644 --- a/libnymea-sunspec/models/sunspecfreqwattmodel.h +++ b/libnymea-sunspec/models/sunspecfreqwattmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecFreqWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFreqWattModel *parent = nullptr); + explicit SunSpecFreqWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecFreqWattModel *parent); ~SunSpecFreqWattModelRepeatingBlock() override = default; SunSpecFreqWattModel *parentModel() const; @@ -260,7 +260,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -382,6 +382,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspecfreqwattparammodel.cpp b/libnymea-sunspec/models/sunspecfreqwattparammodel.cpp index 0701642..11e61cf 100644 --- a/libnymea-sunspec/models/sunspecfreqwattparammodel.cpp +++ b/libnymea-sunspec/models/sunspecfreqwattparammodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecfreqwattparammodel.h b/libnymea-sunspec/models/sunspecfreqwattparammodel.h index 46f2d93..2f3dc23 100644 --- a/libnymea-sunspec/models/sunspecfreqwattparammodel.h +++ b/libnymea-sunspec/models/sunspecfreqwattparammodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspechfrtcmodel.cpp b/libnymea-sunspec/models/sunspechfrtcmodel.cpp index 717077d..091f694 100644 --- a/libnymea-sunspec/models/sunspechfrtcmodel.cpp +++ b/libnymea-sunspec/models/sunspechfrtcmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHfrtcModelRepeatingBlock::SunSpecHfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtcModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHfrtcModelRepeatingBlock::initDataPoints() } -void SunSpecHfrtcModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHfrtcModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHfrtcModel::SunSpecHfrtcModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHfrtcModel::setupRepeatingBlocks); } SunSpecHfrtcModel::~SunSpecHfrtcModel() @@ -1796,6 +1797,34 @@ void SunSpecHfrtcModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHfrtcModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHfrtcModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHfrtcModel *model) { debug.nospace().noquote() << "SunSpecHfrtcModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechfrtcmodel.h b/libnymea-sunspec/models/sunspechfrtcmodel.h index 46a6796..66b9564 100644 --- a/libnymea-sunspec/models/sunspechfrtcmodel.h +++ b/libnymea-sunspec/models/sunspechfrtcmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtcModel *parent = nullptr); + explicit SunSpecHfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtcModel *parent); ~SunSpecHfrtcModelRepeatingBlock() override = default; SunSpecHfrtcModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspechfrtmodel.cpp b/libnymea-sunspec/models/sunspechfrtmodel.cpp index d873460..60f54df 100644 --- a/libnymea-sunspec/models/sunspechfrtmodel.cpp +++ b/libnymea-sunspec/models/sunspechfrtmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHfrtModelRepeatingBlock::SunSpecHfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHfrtModelRepeatingBlock::initDataPoints() } -void SunSpecHfrtModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHfrtModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHfrtModel::SunSpecHfrtModel(SunSpecConnection *connection, quint16 modbus m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHfrtModel::setupRepeatingBlocks); } SunSpecHfrtModel::~SunSpecHfrtModel() @@ -1796,6 +1797,34 @@ void SunSpecHfrtModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHfrtModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHfrtModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHfrtModel *model) { debug.nospace().noquote() << "SunSpecHfrtModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechfrtmodel.h b/libnymea-sunspec/models/sunspechfrtmodel.h index 1698463..d4d9a61 100644 --- a/libnymea-sunspec/models/sunspechfrtmodel.h +++ b/libnymea-sunspec/models/sunspechfrtmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtModel *parent = nullptr); + explicit SunSpecHfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtModel *parent); ~SunSpecHfrtModelRepeatingBlock() override = default; SunSpecHfrtModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspechfrtxmodel.cpp b/libnymea-sunspec/models/sunspechfrtxmodel.cpp index 7168e9a..cccb3ba 100644 --- a/libnymea-sunspec/models/sunspechfrtxmodel.cpp +++ b/libnymea-sunspec/models/sunspechfrtxmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHfrtxModelRepeatingBlock::SunSpecHfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtxModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHfrtxModelRepeatingBlock::initDataPoints() } -void SunSpecHfrtxModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHfrtxModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHfrtxModel::SunSpecHfrtxModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHfrtxModel::setupRepeatingBlocks); } SunSpecHfrtxModel::~SunSpecHfrtxModel() @@ -1797,6 +1798,34 @@ void SunSpecHfrtxModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHfrtxModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHfrtxModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHfrtxModel *model) { debug.nospace().noquote() << "SunSpecHfrtxModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechfrtxmodel.h b/libnymea-sunspec/models/sunspechfrtxmodel.h index 59bd080..8a3f9d8 100644 --- a/libnymea-sunspec/models/sunspechfrtxmodel.h +++ b/libnymea-sunspec/models/sunspechfrtxmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtxModel *parent = nullptr); + explicit SunSpecHfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHfrtxModel *parent); ~SunSpecHfrtxModelRepeatingBlock() override = default; SunSpecHfrtxModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -346,6 +346,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspechvrtcmodel.cpp b/libnymea-sunspec/models/sunspechvrtcmodel.cpp index 2d06446..4e256c6 100644 --- a/libnymea-sunspec/models/sunspechvrtcmodel.cpp +++ b/libnymea-sunspec/models/sunspechvrtcmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHvrtcModelRepeatingBlock::SunSpecHvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtcModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHvrtcModelRepeatingBlock::initDataPoints() } -void SunSpecHvrtcModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHvrtcModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHvrtcModel::SunSpecHvrtcModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHvrtcModel::setupRepeatingBlocks); } SunSpecHvrtcModel::~SunSpecHvrtcModel() @@ -1796,6 +1797,34 @@ void SunSpecHvrtcModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHvrtcModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHvrtcModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHvrtcModel *model) { debug.nospace().noquote() << "SunSpecHvrtcModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechvrtcmodel.h b/libnymea-sunspec/models/sunspechvrtcmodel.h index 52328d1..66c1d63 100644 --- a/libnymea-sunspec/models/sunspechvrtcmodel.h +++ b/libnymea-sunspec/models/sunspechvrtcmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtcModel *parent = nullptr); + explicit SunSpecHvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtcModel *parent); ~SunSpecHvrtcModelRepeatingBlock() override = default; SunSpecHvrtcModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspechvrtmodel.cpp b/libnymea-sunspec/models/sunspechvrtmodel.cpp index 163dadc..20c5c6c 100644 --- a/libnymea-sunspec/models/sunspechvrtmodel.cpp +++ b/libnymea-sunspec/models/sunspechvrtmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHvrtModelRepeatingBlock::SunSpecHvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHvrtModelRepeatingBlock::initDataPoints() } -void SunSpecHvrtModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHvrtModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHvrtModel::SunSpecHvrtModel(SunSpecConnection *connection, quint16 modbus m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHvrtModel::setupRepeatingBlocks); } SunSpecHvrtModel::~SunSpecHvrtModel() @@ -1796,6 +1797,34 @@ void SunSpecHvrtModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHvrtModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHvrtModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHvrtModel *model) { debug.nospace().noquote() << "SunSpecHvrtModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechvrtmodel.h b/libnymea-sunspec/models/sunspechvrtmodel.h index 3302b16..7b9c165 100644 --- a/libnymea-sunspec/models/sunspechvrtmodel.h +++ b/libnymea-sunspec/models/sunspechvrtmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtModel *parent = nullptr); + explicit SunSpecHvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtModel *parent); ~SunSpecHvrtModelRepeatingBlock() override = default; SunSpecHvrtModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspechvrtxmodel.cpp b/libnymea-sunspec/models/sunspechvrtxmodel.cpp index 208b30c..48bd4a6 100644 --- a/libnymea-sunspec/models/sunspechvrtxmodel.cpp +++ b/libnymea-sunspec/models/sunspechvrtxmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecHvrtxModelRepeatingBlock::SunSpecHvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtxModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecHvrtxModelRepeatingBlock::initDataPoints() } -void SunSpecHvrtxModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecHvrtxModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecHvrtxModel::SunSpecHvrtxModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecHvrtxModel::setupRepeatingBlocks); } SunSpecHvrtxModel::~SunSpecHvrtxModel() @@ -1797,6 +1798,34 @@ void SunSpecHvrtxModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecHvrtxModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecHvrtxModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecHvrtxModel *model) { debug.nospace().noquote() << "SunSpecHvrtxModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspechvrtxmodel.h b/libnymea-sunspec/models/sunspechvrtxmodel.h index 2f7d731..a08cc61 100644 --- a/libnymea-sunspec/models/sunspechvrtxmodel.h +++ b/libnymea-sunspec/models/sunspechvrtxmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecHvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtxModel *parent = nullptr); + explicit SunSpecHvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecHvrtxModel *parent); ~SunSpecHvrtxModelRepeatingBlock() override = default; SunSpecHvrtxModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -346,6 +346,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.cpp b/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.cpp index da4df4c..621c08e 100644 --- a/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.cpp +++ b/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.h b/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.h index ffbdddd..6203599 100644 --- a/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.h +++ b/libnymea-sunspec/models/sunspecinvertersinglephasefloatmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersinglephasemodel.cpp b/libnymea-sunspec/models/sunspecinvertersinglephasemodel.cpp index d4eec7b..5e9d632 100644 --- a/libnymea-sunspec/models/sunspecinvertersinglephasemodel.cpp +++ b/libnymea-sunspec/models/sunspecinvertersinglephasemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersinglephasemodel.h b/libnymea-sunspec/models/sunspecinvertersinglephasemodel.h index 714dbcb..f95cd13 100644 --- a/libnymea-sunspec/models/sunspecinvertersinglephasemodel.h +++ b/libnymea-sunspec/models/sunspecinvertersinglephasemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.cpp b/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.cpp index 7b9bbc4..9f355ea 100644 --- a/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.cpp +++ b/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.h b/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.h index 7e93019..1471f9f 100644 --- a/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.h +++ b/libnymea-sunspec/models/sunspecinvertersplitphasefloatmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersplitphasemodel.cpp b/libnymea-sunspec/models/sunspecinvertersplitphasemodel.cpp index f3cf7a8..ca910dd 100644 --- a/libnymea-sunspec/models/sunspecinvertersplitphasemodel.cpp +++ b/libnymea-sunspec/models/sunspecinvertersplitphasemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinvertersplitphasemodel.h b/libnymea-sunspec/models/sunspecinvertersplitphasemodel.h index 1f14a47..26bdab0 100644 --- a/libnymea-sunspec/models/sunspecinvertersplitphasemodel.h +++ b/libnymea-sunspec/models/sunspecinvertersplitphasemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.cpp b/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.cpp index 51341e4..3b94ee5 100644 --- a/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.cpp +++ b/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.h b/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.h index 9d61f5e..752a349 100644 --- a/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.h +++ b/libnymea-sunspec/models/sunspecinverterthreephasefloatmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinverterthreephasemodel.cpp b/libnymea-sunspec/models/sunspecinverterthreephasemodel.cpp index ab7953f..e363a8e 100644 --- a/libnymea-sunspec/models/sunspecinverterthreephasemodel.cpp +++ b/libnymea-sunspec/models/sunspecinverterthreephasemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecinverterthreephasemodel.h b/libnymea-sunspec/models/sunspecinverterthreephasemodel.h index 6479dba..7ca32be 100644 --- a/libnymea-sunspec/models/sunspecinverterthreephasemodel.h +++ b/libnymea-sunspec/models/sunspecinverterthreephasemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecirradiancemodel.cpp b/libnymea-sunspec/models/sunspecirradiancemodel.cpp index 4c2f728..f886367 100644 --- a/libnymea-sunspec/models/sunspecirradiancemodel.cpp +++ b/libnymea-sunspec/models/sunspecirradiancemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecIrradianceModelRepeatingBlock::SunSpecIrradianceModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecIrradianceModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -131,10 +132,8 @@ void SunSpecIrradianceModelRepeatingBlock::initDataPoints() } -void SunSpecIrradianceModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecIrradianceModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("GHI").isValid()) m_ghi = m_dataPoints.value("GHI").toUInt16(); @@ -162,6 +161,8 @@ SunSpecIrradianceModel::SunSpecIrradianceModel(SunSpecConnection *connection, qu m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecIrradianceModel::setupRepeatingBlocks); } SunSpecIrradianceModel::~SunSpecIrradianceModel() @@ -217,6 +218,34 @@ void SunSpecIrradianceModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecIrradianceModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecIrradianceModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecIrradianceModel *model) { debug.nospace().noquote() << "SunSpecIrradianceModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecirradiancemodel.h b/libnymea-sunspec/models/sunspecirradiancemodel.h index a4f5592..5e148a6 100644 --- a/libnymea-sunspec/models/sunspecirradiancemodel.h +++ b/libnymea-sunspec/models/sunspecirradiancemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecIrradianceModelRepeatingBlock : public SunSpecModelRepeatingBlock Q_OBJECT public: - explicit SunSpecIrradianceModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecIrradianceModel *parent = nullptr); + explicit SunSpecIrradianceModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecIrradianceModel *parent); ~SunSpecIrradianceModelRepeatingBlock() override = default; SunSpecIrradianceModel *parentModel() const; @@ -61,7 +61,7 @@ public: /* Other Irradiance [W/m2] */ quint16 oti() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -101,6 +101,9 @@ protected: private: + void setupRepeatingBlocks(); + + }; diff --git a/libnymea-sunspec/models/sunspeclfrtcmodel.cpp b/libnymea-sunspec/models/sunspeclfrtcmodel.cpp index ab63fa8..2d1f7d8 100644 --- a/libnymea-sunspec/models/sunspeclfrtcmodel.cpp +++ b/libnymea-sunspec/models/sunspeclfrtcmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLfrtcModelRepeatingBlock::SunSpecLfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtcModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLfrtcModelRepeatingBlock::initDataPoints() } -void SunSpecLfrtcModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLfrtcModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLfrtcModel::SunSpecLfrtcModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLfrtcModel::setupRepeatingBlocks); } SunSpecLfrtcModel::~SunSpecLfrtcModel() @@ -1796,6 +1797,34 @@ void SunSpecLfrtcModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLfrtcModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLfrtcModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLfrtcModel *model) { debug.nospace().noquote() << "SunSpecLfrtcModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclfrtcmodel.h b/libnymea-sunspec/models/sunspeclfrtcmodel.h index e700e83..ebdf2ba 100644 --- a/libnymea-sunspec/models/sunspeclfrtcmodel.h +++ b/libnymea-sunspec/models/sunspeclfrtcmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtcModel *parent = nullptr); + explicit SunSpecLfrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtcModel *parent); ~SunSpecLfrtcModelRepeatingBlock() override = default; SunSpecLfrtcModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspeclfrtmodel.cpp b/libnymea-sunspec/models/sunspeclfrtmodel.cpp index 735c049..2673eca 100644 --- a/libnymea-sunspec/models/sunspeclfrtmodel.cpp +++ b/libnymea-sunspec/models/sunspeclfrtmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLfrtModelRepeatingBlock::SunSpecLfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLfrtModelRepeatingBlock::initDataPoints() } -void SunSpecLfrtModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLfrtModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLfrtModel::SunSpecLfrtModel(SunSpecConnection *connection, quint16 modbus m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLfrtModel::setupRepeatingBlocks); } SunSpecLfrtModel::~SunSpecLfrtModel() @@ -1796,6 +1797,34 @@ void SunSpecLfrtModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLfrtModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLfrtModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLfrtModel *model) { debug.nospace().noquote() << "SunSpecLfrtModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclfrtmodel.h b/libnymea-sunspec/models/sunspeclfrtmodel.h index 7e90394..67795fd 100644 --- a/libnymea-sunspec/models/sunspeclfrtmodel.h +++ b/libnymea-sunspec/models/sunspeclfrtmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtModel *parent = nullptr); + explicit SunSpecLfrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtModel *parent); ~SunSpecLfrtModelRepeatingBlock() override = default; SunSpecLfrtModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspeclfrtxmodel.cpp b/libnymea-sunspec/models/sunspeclfrtxmodel.cpp index 2cf88a3..805b1a7 100644 --- a/libnymea-sunspec/models/sunspeclfrtxmodel.cpp +++ b/libnymea-sunspec/models/sunspeclfrtxmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLfrtxModelRepeatingBlock::SunSpecLfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtxModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLfrtxModelRepeatingBlock::initDataPoints() } -void SunSpecLfrtxModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLfrtxModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLfrtxModel::SunSpecLfrtxModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLfrtxModel::setupRepeatingBlocks); } SunSpecLfrtxModel::~SunSpecLfrtxModel() @@ -1797,6 +1798,34 @@ void SunSpecLfrtxModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLfrtxModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLfrtxModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLfrtxModel *model) { debug.nospace().noquote() << "SunSpecLfrtxModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclfrtxmodel.h b/libnymea-sunspec/models/sunspeclfrtxmodel.h index 41ca03b..3558675 100644 --- a/libnymea-sunspec/models/sunspeclfrtxmodel.h +++ b/libnymea-sunspec/models/sunspeclfrtxmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtxModel *parent = nullptr); + explicit SunSpecLfrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLfrtxModel *parent); ~SunSpecLfrtxModelRepeatingBlock() override = default; SunSpecLfrtxModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -346,6 +346,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspeclithiumionbankmodel.cpp b/libnymea-sunspec/models/sunspeclithiumionbankmodel.cpp index 775f531..08e60bf 100644 --- a/libnymea-sunspec/models/sunspeclithiumionbankmodel.cpp +++ b/libnymea-sunspec/models/sunspeclithiumionbankmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLithiumIonBankModelRepeatingBlock::SunSpecLithiumIonBankModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonBankModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -497,10 +498,8 @@ void SunSpecLithiumIonBankModelRepeatingBlock::initDataPoints() } -void SunSpecLithiumIonBankModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLithiumIonBankModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("StrNMod").isValid()) m_moduleCount = m_dataPoints.value("StrNMod").toUInt16(); @@ -591,6 +590,8 @@ SunSpecLithiumIonBankModel::SunSpecLithiumIonBankModel(SunSpecConnection *connec m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLithiumIonBankModel::setupRepeatingBlocks); } SunSpecLithiumIonBankModel::~SunSpecLithiumIonBankModel() @@ -1151,6 +1152,34 @@ void SunSpecLithiumIonBankModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLithiumIonBankModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLithiumIonBankModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLithiumIonBankModel *model) { debug.nospace().noquote() << "SunSpecLithiumIonBankModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclithiumionbankmodel.h b/libnymea-sunspec/models/sunspeclithiumionbankmodel.h index a2e67ae..772e196 100644 --- a/libnymea-sunspec/models/sunspeclithiumionbankmodel.h +++ b/libnymea-sunspec/models/sunspeclithiumionbankmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -156,7 +156,7 @@ public: Q_DECLARE_FLAGS(Strevt1Flags, Strevt1) Q_FLAG(Strevt1) - explicit SunSpecLithiumIonBankModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonBankModel *parent = nullptr); + explicit SunSpecLithiumIonBankModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonBankModel *parent); ~SunSpecLithiumIonBankModelRepeatingBlock() override = default; SunSpecLithiumIonBankModel *parentModel() const; @@ -220,7 +220,7 @@ public: /* Pad register. */ quint16 pad2() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -332,6 +332,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_stringCount = 0; quint16 m_connectedStringCount = 0; float m_maxModuleTemperature = 0; diff --git a/libnymea-sunspec/models/sunspeclithiumionmodulemodel.cpp b/libnymea-sunspec/models/sunspeclithiumionmodulemodel.cpp index abf4721..ea2a061 100644 --- a/libnymea-sunspec/models/sunspeclithiumionmodulemodel.cpp +++ b/libnymea-sunspec/models/sunspeclithiumionmodulemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLithiumIonModuleModelRepeatingBlock::SunSpecLithiumIonModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonModuleModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -102,10 +103,8 @@ void SunSpecLithiumIonModuleModelRepeatingBlock::initDataPoints() } -void SunSpecLithiumIonModuleModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLithiumIonModuleModelRepeatingBlock::processBlockData() { - 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()); @@ -127,6 +126,8 @@ SunSpecLithiumIonModuleModel::SunSpecLithiumIonModuleModel(SunSpecConnection *co m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLithiumIonModuleModel::setupRepeatingBlocks); } SunSpecLithiumIonModuleModel::~SunSpecLithiumIonModuleModel() @@ -697,6 +698,34 @@ void SunSpecLithiumIonModuleModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLithiumIonModuleModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLithiumIonModuleModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLithiumIonModuleModel *model) { debug.nospace().noquote() << "SunSpecLithiumIonModuleModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclithiumionmodulemodel.h b/libnymea-sunspec/models/sunspeclithiumionmodulemodel.h index 0fc26b5..3474887 100644 --- a/libnymea-sunspec/models/sunspeclithiumionmodulemodel.h +++ b/libnymea-sunspec/models/sunspeclithiumionmodulemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: Q_DECLARE_FLAGS(CellstFlags, Cellst) Q_FLAG(Cellst) - explicit SunSpecLithiumIonModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonModuleModel *parent = nullptr); + explicit SunSpecLithiumIonModuleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonModuleModel *parent); ~SunSpecLithiumIonModuleModelRepeatingBlock() override = default; SunSpecLithiumIonModuleModel *parentModel() const; @@ -63,7 +63,7 @@ public: /* Status of the cell. */ CellstFlags cellStatus() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -152,6 +152,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_stringIndex = 0; quint16 m_moduleIndex = 0; quint16 m_moduleCellCount = 0; diff --git a/libnymea-sunspec/models/sunspeclithiumionstringmodel.cpp b/libnymea-sunspec/models/sunspeclithiumionstringmodel.cpp index 7a953e8..9c48ceb 100644 --- a/libnymea-sunspec/models/sunspeclithiumionstringmodel.cpp +++ b/libnymea-sunspec/models/sunspeclithiumionstringmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLithiumIonStringModelRepeatingBlock::SunSpecLithiumIonStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonStringModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -319,10 +320,8 @@ void SunSpecLithiumIonStringModelRepeatingBlock::initDataPoints() } -void SunSpecLithiumIonStringModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLithiumIonStringModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ModNCell").isValid()) m_moduleCellCount = m_dataPoints.value("ModNCell").toUInt16(); @@ -383,6 +382,8 @@ SunSpecLithiumIonStringModel::SunSpecLithiumIonStringModel(SunSpecConnection *co m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLithiumIonStringModel::setupRepeatingBlocks); } SunSpecLithiumIonStringModel::~SunSpecLithiumIonStringModel() @@ -1229,6 +1230,34 @@ void SunSpecLithiumIonStringModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLithiumIonStringModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLithiumIonStringModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLithiumIonStringModel *model) { debug.nospace().noquote() << "SunSpecLithiumIonStringModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclithiumionstringmodel.h b/libnymea-sunspec/models/sunspeclithiumionstringmodel.h index e103d3c..584ddba 100644 --- a/libnymea-sunspec/models/sunspeclithiumionstringmodel.h +++ b/libnymea-sunspec/models/sunspeclithiumionstringmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecLithiumIonStringModelRepeatingBlock : public SunSpecModelRepeatingB Q_OBJECT public: - explicit SunSpecLithiumIonStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonStringModel *parent = nullptr); + explicit SunSpecLithiumIonStringModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLithiumIonStringModel *parent); ~SunSpecLithiumIonStringModelRepeatingBlock() override = default; SunSpecLithiumIonStringModel *parentModel() const; @@ -83,7 +83,7 @@ public: /* Pad register. */ quint16 pad7() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -313,6 +313,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_stringIndex = 0; quint16 m_moduleCount = 0; StFlags m_stringStatus; diff --git a/libnymea-sunspec/models/sunspeclocationmodel.cpp b/libnymea-sunspec/models/sunspeclocationmodel.cpp index b66b577..f4f16cb 100644 --- a/libnymea-sunspec/models/sunspeclocationmodel.cpp +++ b/libnymea-sunspec/models/sunspeclocationmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeclocationmodel.h b/libnymea-sunspec/models/sunspeclocationmodel.h index 33a8d68..d0e127f 100644 --- a/libnymea-sunspec/models/sunspeclocationmodel.h +++ b/libnymea-sunspec/models/sunspeclocationmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspeclvrtcmodel.cpp b/libnymea-sunspec/models/sunspeclvrtcmodel.cpp index caf27d6..9315452 100644 --- a/libnymea-sunspec/models/sunspeclvrtcmodel.cpp +++ b/libnymea-sunspec/models/sunspeclvrtcmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLvrtcModelRepeatingBlock::SunSpecLvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtcModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLvrtcModelRepeatingBlock::initDataPoints() } -void SunSpecLvrtcModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLvrtcModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLvrtcModel::SunSpecLvrtcModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLvrtcModel::setupRepeatingBlocks); } SunSpecLvrtcModel::~SunSpecLvrtcModel() @@ -1796,6 +1797,34 @@ void SunSpecLvrtcModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLvrtcModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLvrtcModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLvrtcModel *model) { debug.nospace().noquote() << "SunSpecLvrtcModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclvrtcmodel.h b/libnymea-sunspec/models/sunspeclvrtcmodel.h index 6df4841..2b1399e 100644 --- a/libnymea-sunspec/models/sunspeclvrtcmodel.h +++ b/libnymea-sunspec/models/sunspeclvrtcmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtcModel *parent = nullptr); + explicit SunSpecLvrtcModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtcModel *parent); ~SunSpecLvrtcModelRepeatingBlock() override = default; SunSpecLvrtcModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspeclvrtmodel.cpp b/libnymea-sunspec/models/sunspeclvrtmodel.cpp index 7a67e4f..85b1fea 100644 --- a/libnymea-sunspec/models/sunspeclvrtmodel.cpp +++ b/libnymea-sunspec/models/sunspeclvrtmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLvrtModelRepeatingBlock::SunSpecLvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLvrtModelRepeatingBlock::initDataPoints() } -void SunSpecLvrtModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLvrtModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLvrtModel::SunSpecLvrtModel(SunSpecConnection *connection, quint16 modbus m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLvrtModel::setupRepeatingBlocks); } SunSpecLvrtModel::~SunSpecLvrtModel() @@ -1796,6 +1797,34 @@ void SunSpecLvrtModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLvrtModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLvrtModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLvrtModel *model) { debug.nospace().noquote() << "SunSpecLvrtModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclvrtmodel.h b/libnymea-sunspec/models/sunspeclvrtmodel.h index 96701c5..2539472 100644 --- a/libnymea-sunspec/models/sunspeclvrtmodel.h +++ b/libnymea-sunspec/models/sunspeclvrtmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtModel *parent = nullptr); + explicit SunSpecLvrtModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtModel *parent); ~SunSpecLvrtModelRepeatingBlock() override = default; SunSpecLvrtModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -341,6 +341,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspeclvrtxmodel.cpp b/libnymea-sunspec/models/sunspeclvrtxmodel.cpp index 21ad4b9..3db7ad0 100644 --- a/libnymea-sunspec/models/sunspeclvrtxmodel.cpp +++ b/libnymea-sunspec/models/sunspeclvrtxmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecLvrtxModelRepeatingBlock::SunSpecLvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtxModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1326,10 +1327,8 @@ void SunSpecLvrtxModelRepeatingBlock::initDataPoints() } -void SunSpecLvrtxModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecLvrtxModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1471,6 +1470,8 @@ SunSpecLvrtxModel::SunSpecLvrtxModel(SunSpecConnection *connection, quint16 modb m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecLvrtxModel::setupRepeatingBlocks); } SunSpecLvrtxModel::~SunSpecLvrtxModel() @@ -1797,6 +1798,34 @@ void SunSpecLvrtxModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecLvrtxModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecLvrtxModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecLvrtxModel *model) { debug.nospace().noquote() << "SunSpecLvrtxModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspeclvrtxmodel.h b/libnymea-sunspec/models/sunspeclvrtxmodel.h index b0a8eb8..c42038f 100644 --- a/libnymea-sunspec/models/sunspeclvrtxmodel.h +++ b/libnymea-sunspec/models/sunspeclvrtxmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecLvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtxModel *parent = nullptr); + explicit SunSpecLvrtxModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecLvrtxModel *parent); ~SunSpecLvrtxModelRepeatingBlock() override = default; SunSpecLvrtxModel *parentModel() const; @@ -228,7 +228,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -346,6 +346,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.cpp b/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.cpp index 8b1b8ab..cadba43 100644 --- a/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.cpp +++ b/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.h b/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.h index 987929b..a4b9805 100644 --- a/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.h +++ b/libnymea-sunspec/models/sunspecmetersinglephasefloatmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersinglephasemodel.cpp b/libnymea-sunspec/models/sunspecmetersinglephasemodel.cpp index a2d7919..5c5f883 100644 --- a/libnymea-sunspec/models/sunspecmetersinglephasemodel.cpp +++ b/libnymea-sunspec/models/sunspecmetersinglephasemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersinglephasemodel.h b/libnymea-sunspec/models/sunspecmetersinglephasemodel.h index a03a751..4bf0dbc 100644 --- a/libnymea-sunspec/models/sunspecmetersinglephasemodel.h +++ b/libnymea-sunspec/models/sunspecmetersinglephasemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.cpp b/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.cpp index 265e53f..9dd774c 100644 --- a/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.cpp +++ b/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.h b/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.h index 1f66df5..3f6a0e1 100644 --- a/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.h +++ b/libnymea-sunspec/models/sunspecmetersplitsinglephaseabnmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.cpp b/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.cpp index 10fad6a..be6e725 100644 --- a/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.cpp +++ b/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.h b/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.h index 4e77b1f..4f45760 100644 --- a/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.h +++ b/libnymea-sunspec/models/sunspecmetersplitsinglephasefloatmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.cpp b/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.cpp index fc5465d..c64d3be 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.cpp +++ b/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.h b/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.h index 7e13cdb..e47ae3b 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.h +++ b/libnymea-sunspec/models/sunspecmeterthreephasedeltaconnectmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasemodel.cpp b/libnymea-sunspec/models/sunspecmeterthreephasemodel.cpp index 0d4a11b..17e54fd 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasemodel.cpp +++ b/libnymea-sunspec/models/sunspecmeterthreephasemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasemodel.h b/libnymea-sunspec/models/sunspecmeterthreephasemodel.h index 9846e56..7cf542d 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasemodel.h +++ b/libnymea-sunspec/models/sunspecmeterthreephasemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.cpp b/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.cpp index c3dc4dd..3b0ef73 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.cpp +++ b/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.h b/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.h index c685bb2..b7692cc 100644 --- a/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.h +++ b/libnymea-sunspec/models/sunspecmeterthreephasewyeconnectmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecminimetmodel.cpp b/libnymea-sunspec/models/sunspecminimetmodel.cpp index 084fe4d..3fd6bb5 100644 --- a/libnymea-sunspec/models/sunspecminimetmodel.cpp +++ b/libnymea-sunspec/models/sunspecminimetmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecminimetmodel.h b/libnymea-sunspec/models/sunspecminimetmodel.h index 07971b0..bf6f84b 100644 --- a/libnymea-sunspec/models/sunspecminimetmodel.h +++ b/libnymea-sunspec/models/sunspecminimetmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmodelfactory.cpp b/libnymea-sunspec/models/sunspecmodelfactory.cpp index aa07151..202f601 100644 --- a/libnymea-sunspec/models/sunspecmodelfactory.cpp +++ b/libnymea-sunspec/models/sunspecmodelfactory.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmodelfactory.h b/libnymea-sunspec/models/sunspecmodelfactory.h index a80af97..31c789a 100644 --- a/libnymea-sunspec/models/sunspecmodelfactory.h +++ b/libnymea-sunspec/models/sunspecmodelfactory.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecmpptmodel.cpp b/libnymea-sunspec/models/sunspecmpptmodel.cpp index 91de8f2..3948683 100644 --- a/libnymea-sunspec/models/sunspecmpptmodel.cpp +++ b/libnymea-sunspec/models/sunspecmpptmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecMpptModelRepeatingBlock::SunSpecMpptModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecMpptModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -201,10 +202,8 @@ void SunSpecMpptModelRepeatingBlock::initDataPoints() } -void SunSpecMpptModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecMpptModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ID").isValid()) m_inputId = m_dataPoints.value("ID").toUInt16(); @@ -247,6 +246,8 @@ SunSpecMpptModel::SunSpecMpptModel(SunSpecConnection *connection, quint16 modbus m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecMpptModel::setupRepeatingBlocks); } SunSpecMpptModel::~SunSpecMpptModel() @@ -435,6 +436,34 @@ void SunSpecMpptModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecMpptModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecMpptModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecMpptModel *model) { debug.nospace().noquote() << "SunSpecMpptModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecmpptmodel.h b/libnymea-sunspec/models/sunspecmpptmodel.h index e5e6f0f..4273021 100644 --- a/libnymea-sunspec/models/sunspecmpptmodel.h +++ b/libnymea-sunspec/models/sunspecmpptmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -86,7 +86,7 @@ public: Q_DECLARE_FLAGS(DcevtFlags, Dcevt) Q_FLAG(Dcevt) - explicit SunSpecMpptModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecMpptModel *parent = nullptr); + explicit SunSpecMpptModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecMpptModel *parent); ~SunSpecMpptModelRepeatingBlock() override = default; SunSpecMpptModel *parentModel() const; @@ -113,7 +113,7 @@ public: /* Module Events */ DcevtFlags moduleEvents() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -199,6 +199,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + qint16 m_currentScaleFactor = 0; qint16 m_voltageScaleFactor = 0; qint16 m_powerScaleFactor = 0; diff --git a/libnymea-sunspec/models/sunspecnameplatemodel.cpp b/libnymea-sunspec/models/sunspecnameplatemodel.cpp index e66d33e..691b223 100644 --- a/libnymea-sunspec/models/sunspecnameplatemodel.cpp +++ b/libnymea-sunspec/models/sunspecnameplatemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecnameplatemodel.h b/libnymea-sunspec/models/sunspecnameplatemodel.h index c2bc556..b940b67 100644 --- a/libnymea-sunspec/models/sunspecnameplatemodel.h +++ b/libnymea-sunspec/models/sunspecnameplatemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecpricingmodel.cpp b/libnymea-sunspec/models/sunspecpricingmodel.cpp index 1229c1d..ccb820f 100644 --- a/libnymea-sunspec/models/sunspecpricingmodel.cpp +++ b/libnymea-sunspec/models/sunspecpricingmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecpricingmodel.h b/libnymea-sunspec/models/sunspecpricingmodel.h index 627e43f..15c34a5 100644 --- a/libnymea-sunspec/models/sunspecpricingmodel.h +++ b/libnymea-sunspec/models/sunspecpricingmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecreactivecurrentmodel.cpp b/libnymea-sunspec/models/sunspecreactivecurrentmodel.cpp index 12a2f04..ab7b5b4 100644 --- a/libnymea-sunspec/models/sunspecreactivecurrentmodel.cpp +++ b/libnymea-sunspec/models/sunspecreactivecurrentmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecreactivecurrentmodel.h b/libnymea-sunspec/models/sunspecreactivecurrentmodel.h index 6ffc8dd..61d034a 100644 --- a/libnymea-sunspec/models/sunspecreactivecurrentmodel.h +++ b/libnymea-sunspec/models/sunspecreactivecurrentmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecrefpointmodel.cpp b/libnymea-sunspec/models/sunspecrefpointmodel.cpp index 3be28eb..bf04fef 100644 --- a/libnymea-sunspec/models/sunspecrefpointmodel.cpp +++ b/libnymea-sunspec/models/sunspecrefpointmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecrefpointmodel.h b/libnymea-sunspec/models/sunspecrefpointmodel.h index f8d8a4c..b5d06f9 100644 --- a/libnymea-sunspec/models/sunspecrefpointmodel.h +++ b/libnymea-sunspec/models/sunspecrefpointmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecschedulemodel.cpp b/libnymea-sunspec/models/sunspecschedulemodel.cpp index 707ba38..7ca75c3 100644 --- a/libnymea-sunspec/models/sunspecschedulemodel.cpp +++ b/libnymea-sunspec/models/sunspecschedulemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecScheduleModelRepeatingBlock::SunSpecScheduleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecScheduleModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -936,10 +937,8 @@ void SunSpecScheduleModelRepeatingBlock::initDataPoints() } -void SunSpecScheduleModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecScheduleModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Scale factors if (m_dataPoints.value("X_SF").isValid()) m_xSf = m_dataPoints.value("X_SF").toInt16(); @@ -1056,6 +1055,8 @@ SunSpecScheduleModel::SunSpecScheduleModel(SunSpecConnection *connection, quint1 m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecScheduleModel::setupRepeatingBlocks); } SunSpecScheduleModel::~SunSpecScheduleModel() @@ -1235,6 +1236,34 @@ void SunSpecScheduleModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecScheduleModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecScheduleModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecScheduleModel *model) { debug.nospace().noquote() << "SunSpecScheduleModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecschedulemodel.h b/libnymea-sunspec/models/sunspecschedulemodel.h index d6959dd..4b5f509 100644 --- a/libnymea-sunspec/models/sunspecschedulemodel.h +++ b/libnymea-sunspec/models/sunspecschedulemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -83,7 +83,7 @@ public: }; Q_ENUM(Ytyp) - explicit SunSpecScheduleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecScheduleModel *parent = nullptr); + explicit SunSpecScheduleModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecScheduleModel *parent); ~SunSpecScheduleModelRepeatingBlock() override = default; SunSpecScheduleModel *parentModel() const; @@ -217,7 +217,7 @@ public: /* Index of active entry in the active schedule. */ quint16 actIndx() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -340,6 +340,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + ActschdFlags m_actSchd; ModenaFlags m_modEna; quint16 m_nSchd = 0; diff --git a/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.cpp b/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.cpp index 74ea32a..1e05764 100644 --- a/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.cpp +++ b/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock::SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecSecureAcMeterSelectedReadingsModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -66,10 +67,8 @@ void SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock::initDataPoints() } -void SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("DS").isValid()) m_dS = m_dataPoints.value("DS").toUInt16(); @@ -85,6 +84,8 @@ SunSpecSecureAcMeterSelectedReadingsModel::SunSpecSecureAcMeterSelectedReadingsM m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecSecureAcMeterSelectedReadingsModel::setupRepeatingBlocks); } SunSpecSecureAcMeterSelectedReadingsModel::~SunSpecSecureAcMeterSelectedReadingsModel() @@ -782,6 +783,34 @@ void SunSpecSecureAcMeterSelectedReadingsModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecSecureAcMeterSelectedReadingsModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecSecureAcMeterSelectedReadingsModel *model) { debug.nospace().noquote() << "SunSpecSecureAcMeterSelectedReadingsModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.h b/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.h index 9b15448..2eb3185 100644 --- a/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.h +++ b/libnymea-sunspec/models/sunspecsecureacmeterselectedreadingsmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -44,7 +44,7 @@ class SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock : public SunSpecMo Q_OBJECT public: - explicit SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecSecureAcMeterSelectedReadingsModel *parent = nullptr); + explicit SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecSecureAcMeterSelectedReadingsModel *parent); ~SunSpecSecureAcMeterSelectedReadingsModelRepeatingBlock() override = default; SunSpecSecureAcMeterSelectedReadingsModel *parentModel() const; @@ -52,7 +52,7 @@ public: QString name() const override; quint16 dS() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -183,6 +183,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + float m_amps = 0; qint16 m_a_SF = 0; float m_voltage = 0; diff --git a/libnymea-sunspec/models/sunspecsettingsmodel.cpp b/libnymea-sunspec/models/sunspecsettingsmodel.cpp index 1355510..c43283e 100644 --- a/libnymea-sunspec/models/sunspecsettingsmodel.cpp +++ b/libnymea-sunspec/models/sunspecsettingsmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecsettingsmodel.h b/libnymea-sunspec/models/sunspecsettingsmodel.h index fb72ca9..86842b6 100644 --- a/libnymea-sunspec/models/sunspecsettingsmodel.h +++ b/libnymea-sunspec/models/sunspecsettingsmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecsolarmodulemodel.cpp b/libnymea-sunspec/models/sunspecsolarmodulemodel.cpp index d2fc9aa..d70bca8 100644 --- a/libnymea-sunspec/models/sunspecsolarmodulemodel.cpp +++ b/libnymea-sunspec/models/sunspecsolarmodulemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecsolarmodulemodel.h b/libnymea-sunspec/models/sunspecsolarmodulemodel.h index c2aa698..24a91a0 100644 --- a/libnymea-sunspec/models/sunspecsolarmodulemodel.h +++ b/libnymea-sunspec/models/sunspecsolarmodulemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecstatusmodel.cpp b/libnymea-sunspec/models/sunspecstatusmodel.cpp index 01ba783..dc6bfcc 100644 --- a/libnymea-sunspec/models/sunspecstatusmodel.cpp +++ b/libnymea-sunspec/models/sunspecstatusmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecstatusmodel.h b/libnymea-sunspec/models/sunspecstatusmodel.h index 952deaf..0e8bbca 100644 --- a/libnymea-sunspec/models/sunspecstatusmodel.h +++ b/libnymea-sunspec/models/sunspecstatusmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecstoragemodel.cpp b/libnymea-sunspec/models/sunspecstoragemodel.cpp index 747a239..aa2440e 100644 --- a/libnymea-sunspec/models/sunspecstoragemodel.cpp +++ b/libnymea-sunspec/models/sunspecstoragemodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecstoragemodel.h b/libnymea-sunspec/models/sunspecstoragemodel.h index 40dbc6f..c47f1ee 100644 --- a/libnymea-sunspec/models/sunspecstoragemodel.h +++ b/libnymea-sunspec/models/sunspecstoragemodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. diff --git a/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.cpp b/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.cpp index bcca919..9480436 100644 --- a/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.cpp +++ b/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecStringCombinerAdvancedModelRepeatingBlock::SunSpecStringCombinerAdvancedModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerAdvancedModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -215,10 +216,8 @@ void SunSpecStringCombinerAdvancedModelRepeatingBlock::initDataPoints() } -void SunSpecStringCombinerAdvancedModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecStringCombinerAdvancedModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("InID").isValid()) m_id = m_dataPoints.value("InID").toUInt16(); @@ -261,6 +260,8 @@ SunSpecStringCombinerAdvancedModel::SunSpecStringCombinerAdvancedModel(SunSpecCo m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecStringCombinerAdvancedModel::setupRepeatingBlocks); } SunSpecStringCombinerAdvancedModel::~SunSpecStringCombinerAdvancedModel() @@ -735,6 +736,34 @@ void SunSpecStringCombinerAdvancedModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecStringCombinerAdvancedModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecStringCombinerAdvancedModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecStringCombinerAdvancedModel *model) { debug.nospace().noquote() << "SunSpecStringCombinerAdvancedModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.h b/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.h index 938881d..6fc3f80 100644 --- a/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.h +++ b/libnymea-sunspec/models/sunspecstringcombineradvancedmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -68,7 +68,7 @@ public: Q_DECLARE_FLAGS(InevtFlags, Inevt) Q_FLAG(Inevt) - explicit SunSpecStringCombinerAdvancedModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerAdvancedModel *parent = nullptr); + explicit SunSpecStringCombinerAdvancedModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerAdvancedModel *parent); ~SunSpecStringCombinerAdvancedModelRepeatingBlock() override = default; SunSpecStringCombinerAdvancedModel *parentModel() const; @@ -95,7 +95,7 @@ public: /* Number of modules in this input string */ quint16 n() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -205,6 +205,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + qint16 m_dCA_SF = 0; qint16 m_dCAhr_SF = 0; qint16 m_dCV_SF = 0; diff --git a/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.cpp b/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.cpp index e60b171..28618d0 100644 --- a/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.cpp +++ b/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecStringCombinerCurrentModelRepeatingBlock::SunSpecStringCombinerCurrentModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerCurrentModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -133,10 +134,8 @@ void SunSpecStringCombinerCurrentModelRepeatingBlock::initDataPoints() } -void SunSpecStringCombinerCurrentModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecStringCombinerCurrentModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("InID").isValid()) m_id = m_dataPoints.value("InID").toUInt16(); @@ -164,6 +163,8 @@ SunSpecStringCombinerCurrentModel::SunSpecStringCombinerCurrentModel(SunSpecConn m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecStringCombinerCurrentModel::setupRepeatingBlocks); } SunSpecStringCombinerCurrentModel::~SunSpecStringCombinerCurrentModel() @@ -479,6 +480,34 @@ void SunSpecStringCombinerCurrentModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecStringCombinerCurrentModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecStringCombinerCurrentModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecStringCombinerCurrentModel *model) { debug.nospace().noquote() << "SunSpecStringCombinerCurrentModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.h b/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.h index 97eb362..ec189da 100644 --- a/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.h +++ b/libnymea-sunspec/models/sunspecstringcombinercurrentmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -68,7 +68,7 @@ public: Q_DECLARE_FLAGS(InevtFlags, Inevt) Q_FLAG(Inevt) - explicit SunSpecStringCombinerCurrentModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerCurrentModel *parent = nullptr); + explicit SunSpecStringCombinerCurrentModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecStringCombinerCurrentModel *parent); ~SunSpecStringCombinerCurrentModelRepeatingBlock() override = default; SunSpecStringCombinerCurrentModel *parentModel() const; @@ -85,7 +85,7 @@ public: /* String Input Amp-Hours [Ah] */ quint32 ampHours() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -174,6 +174,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + qint16 m_dCA_SF = 0; qint16 m_dCAhr_SF = 0; qint16 m_dCV_SF = 0; diff --git a/libnymea-sunspec/models/sunspectrackercontrollermodel.cpp b/libnymea-sunspec/models/sunspectrackercontrollermodel.cpp index 40307db..359942c 100644 --- a/libnymea-sunspec/models/sunspectrackercontrollermodel.cpp +++ b/libnymea-sunspec/models/sunspectrackercontrollermodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecTrackerControllerModelRepeatingBlock::SunSpecTrackerControllerModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecTrackerControllerModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -238,10 +239,8 @@ void SunSpecTrackerControllerModelRepeatingBlock::initDataPoints() } -void SunSpecTrackerControllerModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecTrackerControllerModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("Id").isValid()) m_tracker = m_dataPoints.value("Id").toString(); @@ -281,6 +280,8 @@ SunSpecTrackerControllerModel::SunSpecTrackerControllerModel(SunSpecConnection * m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecTrackerControllerModel::setupRepeatingBlocks); } SunSpecTrackerControllerModel::~SunSpecTrackerControllerModel() @@ -593,6 +594,34 @@ void SunSpecTrackerControllerModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecTrackerControllerModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecTrackerControllerModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecTrackerControllerModel *model) { debug.nospace().noquote() << "SunSpecTrackerControllerModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspectrackercontrollermodel.h b/libnymea-sunspec/models/sunspectrackercontrollermodel.h index 095b0d0..232f98b 100644 --- a/libnymea-sunspec/models/sunspectrackercontrollermodel.h +++ b/libnymea-sunspec/models/sunspectrackercontrollermodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -59,7 +59,7 @@ public: Q_DECLARE_FLAGS(AlmFlags, Alm) Q_FLAG(Alm) - explicit SunSpecTrackerControllerModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecTrackerControllerModel *parent = nullptr); + explicit SunSpecTrackerControllerModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecTrackerControllerModel *parent); ~SunSpecTrackerControllerModelRepeatingBlock() override = default; SunSpecTrackerControllerModel *parentModel() const; @@ -91,7 +91,7 @@ public: /* Tracker alarm conditions */ AlmFlags alarm() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -189,6 +189,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + QString m_controller; Typ m_type; QString m_date; diff --git a/libnymea-sunspec/models/sunspecvoltvarmodel.cpp b/libnymea-sunspec/models/sunspecvoltvarmodel.cpp index d465148..f512bf8 100644 --- a/libnymea-sunspec/models/sunspecvoltvarmodel.cpp +++ b/libnymea-sunspec/models/sunspecvoltvarmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecVoltVarModelRepeatingBlock::SunSpecVoltVarModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltVarModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1424,10 +1425,8 @@ void SunSpecVoltVarModelRepeatingBlock::initDataPoints() } -void SunSpecVoltVarModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecVoltVarModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1581,6 +1580,8 @@ SunSpecVoltVarModel::SunSpecVoltVarModel(SunSpecConnection *connection, quint16 m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecVoltVarModel::setupRepeatingBlocks); } SunSpecVoltVarModel::~SunSpecVoltVarModel() @@ -1909,6 +1910,34 @@ void SunSpecVoltVarModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecVoltVarModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecVoltVarModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecVoltVarModel *model) { debug.nospace().noquote() << "SunSpecVoltVarModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecvoltvarmodel.h b/libnymea-sunspec/models/sunspecvoltvarmodel.h index 25f1e66..7a7b6e7 100644 --- a/libnymea-sunspec/models/sunspecvoltvarmodel.h +++ b/libnymea-sunspec/models/sunspecvoltvarmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -57,7 +57,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecVoltVarModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltVarModel *parent = nullptr); + explicit SunSpecVoltVarModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltVarModel *parent); ~SunSpecVoltVarModelRepeatingBlock() override = default; SunSpecVoltVarModel *parentModel() const; @@ -251,7 +251,7 @@ public: /* Boolean flag indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -368,6 +368,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspecvoltwattmodel.cpp b/libnymea-sunspec/models/sunspecvoltwattmodel.cpp index fe4ea07..a549d0e 100644 --- a/libnymea-sunspec/models/sunspecvoltwattmodel.cpp +++ b/libnymea-sunspec/models/sunspecvoltwattmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecVoltWattModelRepeatingBlock::SunSpecVoltWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltWattModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1444,10 +1445,8 @@ void SunSpecVoltWattModelRepeatingBlock::initDataPoints() } -void SunSpecVoltWattModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecVoltWattModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1601,6 +1600,8 @@ SunSpecVoltWattModel::SunSpecVoltWattModel(SunSpecConnection *connection, quint1 m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecVoltWattModel::setupRepeatingBlocks); } SunSpecVoltWattModel::~SunSpecVoltWattModel() @@ -1931,6 +1932,34 @@ void SunSpecVoltWattModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecVoltWattModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecVoltWattModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecVoltWattModel *model) { debug.nospace().noquote() << "SunSpecVoltWattModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecvoltwattmodel.h b/libnymea-sunspec/models/sunspecvoltwattmodel.h index 26d16d7..a25209f 100644 --- a/libnymea-sunspec/models/sunspecvoltwattmodel.h +++ b/libnymea-sunspec/models/sunspecvoltwattmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -56,7 +56,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecVoltWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltWattModel *parent = nullptr); + explicit SunSpecVoltWattModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecVoltWattModel *parent); ~SunSpecVoltWattModelRepeatingBlock() override = default; SunSpecVoltWattModel *parentModel() const; @@ -250,7 +250,7 @@ public: /* Enumerated value indicates if curve is read-only or can be modified. */ Readonly readOnly() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -368,6 +368,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/models/sunspecwattpfmodel.cpp b/libnymea-sunspec/models/sunspecwattpfmodel.cpp index 9ef97ac..31b03f4 100644 --- a/libnymea-sunspec/models/sunspecwattpfmodel.cpp +++ b/libnymea-sunspec/models/sunspecwattpfmodel.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -34,6 +34,7 @@ SunSpecWattPfModelRepeatingBlock::SunSpecWattPfModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecWattPfModel *parent) : SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent) { + m_parentModel = parent; m_byteOrder = parent->byteOrder(); initDataPoints(); } @@ -1428,10 +1429,8 @@ void SunSpecWattPfModelRepeatingBlock::initDataPoints() } -void SunSpecWattPfModelRepeatingBlock::processBlockData(const QVector blockData) +void SunSpecWattPfModelRepeatingBlock::processBlockData() { - m_blockData = blockData; - // Update properties according to the data point type if (m_dataPoints.value("ActPt").isValid()) m_actPt = m_dataPoints.value("ActPt").toUInt16(); @@ -1585,6 +1584,8 @@ SunSpecWattPfModel::SunSpecWattPfModel(SunSpecConnection *connection, quint16 mo m_modelBlockType = SunSpecModel::ModelBlockTypeFixedAndRepeating; initDataPoints(); + + connect(this, &SunSpecModel::initFinished, this, &SunSpecWattPfModel::setupRepeatingBlocks); } SunSpecWattPfModel::~SunSpecWattPfModel() @@ -1915,6 +1916,34 @@ void SunSpecWattPfModel::processBlockData() qCDebug(dcSunSpecModelData()) << this; } +void SunSpecWattPfModel::setupRepeatingBlocks() +{ + if (!m_repeatingBlocks.isEmpty()) { + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + block->deleteLater(); + } + m_repeatingBlocks.clear(); + } + + const auto headerLength = 2; + const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength; + if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) { + qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:" + << repeatingBlocksDataSize + << "(repeating block size:" + << m_repeatingBlockLength + << "), extra bytes:" + << repeatingBlocksDataSize % m_repeatingBlockLength; + } + const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength; + const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength; + for (int i = 0; i < numberOfBlocks; ++i) { + const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i); + const auto block = new SunSpecWattPfModelRepeatingBlock(i, m_repeatingBlockLength, blockStartRegister, this); + m_repeatingBlocks.append(block); + } +} + QDebug operator<<(QDebug debug, SunSpecWattPfModel *model) { debug.nospace().noquote() << "SunSpecWattPfModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n"; diff --git a/libnymea-sunspec/models/sunspecwattpfmodel.h b/libnymea-sunspec/models/sunspecwattpfmodel.h index 2a35442..1956df8 100644 --- a/libnymea-sunspec/models/sunspecwattpfmodel.h +++ b/libnymea-sunspec/models/sunspecwattpfmodel.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* Copyright 2013 - 2021, nymea GmbH +* Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This fileDescriptor is part of nymea. @@ -50,7 +50,7 @@ public: }; Q_ENUM(Readonly) - explicit SunSpecWattPfModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecWattPfModel *parent = nullptr); + explicit SunSpecWattPfModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecWattPfModel *parent); ~SunSpecWattPfModelRepeatingBlock() override = default; SunSpecWattPfModel *parentModel() const; @@ -241,7 +241,7 @@ public: Readonly readOnly() const; quint16 pad() const; - void processBlockData(const QVector blockData) override; + void processBlockData() override; protected: void initDataPoints() override; @@ -359,6 +359,9 @@ protected: void processBlockData() override; private: + + void setupRepeatingBlocks(); + quint16 m_actCrv = 0; ModenaFlags m_modEna; quint16 m_winTms = 0; diff --git a/libnymea-sunspec/sunspecdatapoint.cpp b/libnymea-sunspec/sunspecdatapoint.cpp index c7bfd34..c45757c 100644 --- a/libnymea-sunspec/sunspecdatapoint.cpp +++ b/libnymea-sunspec/sunspecdatapoint.cpp @@ -755,7 +755,7 @@ QDebug operator<<(QDebug debug, const SunSpecDataPoint &dataPoint) { debug.nospace().noquote() << "DataPoint("; if (dataPoint.description().isEmpty()) { - debug.nospace().noquote() << dataPoint.name(); + debug.nospace().noquote() << dataPoint.name() << ", "; } else { debug.nospace().noquote() << dataPoint.description() << ", " << dataPoint.name() << ", "; } diff --git a/libnymea-sunspec/sunspecmodel.cpp b/libnymea-sunspec/sunspecmodel.cpp index e653859..86e125b 100644 --- a/libnymea-sunspec/sunspecmodel.cpp +++ b/libnymea-sunspec/sunspecmodel.cpp @@ -30,6 +30,7 @@ #include "sunspecmodel.h" #include "sunspecconnection.h" +#include "sunspecmodelrepeatingblock.h" Q_LOGGING_CATEGORY(dcSunSpecModelData, "SunSpecModelData") @@ -95,6 +96,11 @@ SunSpecModel::CommonModelInfo SunSpecModel::commonModelInfo() const return m_commonModelInfo; } +QList SunSpecModel::repeatingBlocks() const +{ + return m_repeatingBlocks; +} + void SunSpecModel::init() { m_initialized = false; @@ -145,6 +151,37 @@ void SunSpecModel::readBlockData() // Fill the private member data using the data points processBlockData(); + // Handle repeating blocks + if (!m_repeatingBlocks.isEmpty()) { + auto repeatingBlocksTotalSize = 0; + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + repeatingBlocksTotalSize += block->blockSize(); + } + const auto repeatingBlocksDataOffset = m_blockData.size() - repeatingBlocksTotalSize; + foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) { + qCDebug(dcSunSpecModelData()) << "Block" << block->blockIndex(); + // Fill the data points + const auto blockOffset = repeatingBlocksDataOffset + block->blockIndex() * block->blockSize(); + foreach (const QString &dataPointName, block->m_dataPoints.keys()) { + const auto dataPointOffset = blockOffset + block->m_dataPoints[dataPointName].addressOffset(); + QVector rawData = m_blockData.mid(dataPointOffset, block->m_dataPoints[dataPointName].size()); + block->m_dataPoints[dataPointName].setRawData(rawData); + qCDebug(dcSunSpecModelData()) + << "Set raw data (offset:" + << dataPointOffset + << ", size:" + << block->m_dataPoints[dataPointName].size() + << "):" + << block->m_dataPoints[dataPointName] + << SunSpecDataPoint::registersToString(rawData) + << (block->m_dataPoints[dataPointName].isValid() ? "Valid" : "Invalid"); + } + + // Fill the private member data using the data points + block->processBlockData(); + } + } + // Make sure initialized gets called setInitializedFinished(); diff --git a/libnymea-sunspec/sunspecmodel.h b/libnymea-sunspec/sunspecmodel.h index 62f8d34..2e2fee1 100644 --- a/libnymea-sunspec/sunspecmodel.h +++ b/libnymea-sunspec/sunspecmodel.h @@ -41,6 +41,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcSunSpecModelData) class SunSpecConnection; +class SunSpecModelRepeatingBlock; class SunSpecModel : public QObject { @@ -86,6 +87,8 @@ public: CommonModelInfo commonModelInfo() const; + QList repeatingBlocks() const; + virtual void init(); virtual void readBlockData(); @@ -109,6 +112,8 @@ protected: CommonModelInfo m_commonModelInfo; + QList m_repeatingBlocks; + void setInitializedFinished(); virtual void processBlockData() = 0; diff --git a/libnymea-sunspec/sunspecmodelrepeatingblock.h b/libnymea-sunspec/sunspecmodelrepeatingblock.h index e60f0f7..8bf0d8d 100644 --- a/libnymea-sunspec/sunspecmodelrepeatingblock.h +++ b/libnymea-sunspec/sunspecmodelrepeatingblock.h @@ -40,6 +40,9 @@ class SunSpecModel; class SunSpecModelRepeatingBlock : public QObject { Q_OBJECT + + friend class SunSpecModel; + public: explicit SunSpecModelRepeatingBlock(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, SunSpecModel *parent = nullptr); virtual ~SunSpecModelRepeatingBlock() = default; @@ -49,7 +52,7 @@ public: quint16 blockIndex() const; quint16 blockSize() const; - virtual void processBlockData(const QVector blockData) = 0; + virtual void processBlockData() = 0; protected: quint16 m_blockIndex; @@ -57,7 +60,6 @@ protected: quint16 m_modbusStartRegister; SunSpecDataPoint::ByteOrder m_byteOrder = SunSpecDataPoint::ByteOrderLittleEndian; - QVector m_blockData; QHash m_dataPoints; virtual void initDataPoints() = 0; diff --git a/libnymea-sunspec/tools/generate-models.py b/libnymea-sunspec/tools/generate-models.py index 22f9ea7..6797ab5 100644 --- a/libnymea-sunspec/tools/generate-models.py +++ b/libnymea-sunspec/tools/generate-models.py @@ -810,6 +810,35 @@ def writeProcessDataImplementation(fileDescriptor, className, dataPoints, parent writeLine(fileDescriptor, ' qCDebug(dcSunSpecModelData()) << this;') +def writeSetupRepeatingBlocksImplementation(fileDescriptor, className): + print('Write setupRepeatingBlocks() implementation') + blockClassName = ("%sRepeatingBlock" % className) + writeLine(fileDescriptor, ' if (!m_repeatingBlocks.isEmpty()) {') + writeLine(fileDescriptor, ' foreach (SunSpecModelRepeatingBlock *block, m_repeatingBlocks) {') + writeLine(fileDescriptor, ' block->deleteLater();') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' m_repeatingBlocks.clear();') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' const auto headerLength = 2;') + writeLine(fileDescriptor, ' const auto repeatingBlocksDataSize = m_blockData.size() - headerLength - m_fixedBlockLength;') + writeLine(fileDescriptor, ' if (repeatingBlocksDataSize % m_repeatingBlockLength != 0) {') + writeLine(fileDescriptor, ' qCWarning(dcSunSpecModelData()) << "Unexpected repeating block data size:"') + writeLine(fileDescriptor, ' << repeatingBlocksDataSize') + writeLine(fileDescriptor, ' << "(repeating block size:"') + writeLine(fileDescriptor, ' << m_repeatingBlockLength') + writeLine(fileDescriptor, ' << "), extra bytes:"') + writeLine(fileDescriptor, ' << repeatingBlocksDataSize % m_repeatingBlockLength;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' const auto numberOfBlocks = repeatingBlocksDataSize / m_repeatingBlockLength;') + writeLine(fileDescriptor, ' const auto repeatingBlocksOffset = m_fixedBlockLength + headerLength;') + writeLine(fileDescriptor, ' for (int i = 0; i < numberOfBlocks; ++i) {') + writeLine(fileDescriptor, ' const auto blockStartRegister = static_cast(modbusStartRegister() + repeatingBlocksOffset + m_repeatingBlockLength * i);') + writeLine(fileDescriptor, ' const auto block = new %s(i, m_repeatingBlockLength, blockStartRegister, this);' % blockClassName) + writeLine(fileDescriptor, ' m_repeatingBlocks.append(block);') + writeLine(fileDescriptor, ' }') + + def writePropertyDebugLine(fileDescriptor, className, modelId): print('Write class debug properties') modelData = models[modelId] @@ -868,7 +897,7 @@ def writeRepeatingBlockClassDefinition(fileDescriptor, className, modelId): writeClassFlags(fileDescriptor, className, dataPoints) # Constructor - writeLine(fileDescriptor, ' explicit %s(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, %s *parent = nullptr);' % (blockClassName, className)) + writeLine(fileDescriptor, ' explicit %s(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, %s *parent);' % (blockClassName, className)) writeLine(fileDescriptor, ' ~%s() override = default;' % blockClassName) writeLine(fileDescriptor) @@ -880,7 +909,7 @@ def writeRepeatingBlockClassDefinition(fileDescriptor, className, modelId): addPropertiesMethodDeclaration(fileDescriptor, dataPoints) writeLine(fileDescriptor) - writeLine(fileDescriptor, ' void processBlockData(const QVector blockData) override;') + writeLine(fileDescriptor, ' void processBlockData() override;') # Protected members writeLine(fileDescriptor) @@ -925,6 +954,7 @@ def writeRepeatingBlockClassImplementation(fileDescriptor, className, modelId): writeLine(fileDescriptor, '%s::%s(quint16 blockIndex, quint16 blockSize, quint16 modbusStartRegister, %s *parent) :' % (blockClassName, blockClassName, className)) writeLine(fileDescriptor, ' SunSpecModelRepeatingBlock(blockIndex, blockSize, modbusStartRegister, parent)') writeLine(fileDescriptor, '{') + writeLine(fileDescriptor, ' m_parentModel = parent;') writeLine(fileDescriptor, ' m_byteOrder = parent->byteOrder();') writeLine(fileDescriptor, ' initDataPoints();') writeLine(fileDescriptor, '}') @@ -964,10 +994,8 @@ def writeRepeatingBlockClassImplementation(fileDescriptor, className, modelId): writeLine(fileDescriptor) # Process data - writeLine(fileDescriptor, 'void %s::processBlockData(const QVector blockData)' % blockClassName) + writeLine(fileDescriptor, 'void %s::processBlockData()' % blockClassName) writeLine(fileDescriptor, '{') - writeLine(fileDescriptor, ' m_blockData = blockData;') - writeLine(fileDescriptor) writeProcessDataImplementation(fileDescriptor, blockClassName, dataPoints, modelData['group']['points']) writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -1063,6 +1091,10 @@ def writeHeaderFile(headerFileName, className, modelId): # Private members writeLine(fileDescriptor) writeLine(fileDescriptor, 'private:') + if containingRepeatingBlock: + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' void setupRepeatingBlocks();') + writeLine(fileDescriptor) addPropertiesDeclaration(fileDescriptor, dataPoints) writeLine(fileDescriptor) @@ -1112,6 +1144,9 @@ def writeSourceFile(sourceFileName, className, modelId): #writeLine(fileDescriptor, ' if (modelLength != m_modelLengthSunSpec)') #writeLine(fileDescriptor, ' qCWarning(dcSunSpecModelData()) << qobject_cast(this) << "does not have the same length as specified from SunSpec" << m_modelLengthSunSpec;') writeLine(fileDescriptor, ' initDataPoints();') + if containingRepeatingBlock: + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(this, &SunSpecModel::initFinished, this, &%s::setupRepeatingBlocks);' % className) writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -1174,11 +1209,19 @@ def writeSourceFile(sourceFileName, className, modelId): # Process data writeLine(fileDescriptor, 'void %s::processBlockData()' % className) - writeLine(fileDescriptor, '{') + writeLine(fileDescriptor, '{') writeProcessDataImplementation(fileDescriptor, className, dataPoints) writeLine(fileDescriptor, '}') writeLine(fileDescriptor) + if containingRepeatingBlock: + # Setup repeating blocks + writeLine(fileDescriptor, 'void %s::setupRepeatingBlocks()' % className) + writeLine(fileDescriptor, '{') + writeSetupRepeatingBlocksImplementation(fileDescriptor, className) + writeLine(fileDescriptor, '}') + writeLine(fileDescriptor) + # Debug operator writeLine(fileDescriptor, 'QDebug operator<<(QDebug debug, %s *model)' % className) writeLine(fileDescriptor, '{')