From 5fbabfa51972ad9a81679ad791cb3876ffc14d1c Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 8 Dec 2022 00:21:25 +0100 Subject: [PATCH] Fix some glitches in energy chats if the user changes the time zone --- libnymea-app/energy/energylogs.cpp | 40 +++++++++++++++++-- libnymea-app/energy/energylogs.h | 1 + nymea-app/ui/mainviews/EnergyView.qml | 27 ------------- .../ui/mainviews/energy/ConsumerStats.qml | 2 +- .../ui/mainviews/energy/PowerBalanceStats.qml | 14 ++++--- 5 files changed, 47 insertions(+), 37 deletions(-) diff --git a/libnymea-app/energy/energylogs.cpp b/libnymea-app/energy/energylogs.cpp index 86da4a73..487d0c73 100644 --- a/libnymea-app/energy/energylogs.cpp +++ b/libnymea-app/energy/energylogs.cpp @@ -184,19 +184,51 @@ EnergyLogEntry *EnergyLogs::get(int index) const return m_list.at(index); } -EnergyLogEntry *EnergyLogs::find(const QDateTime ×tamp) +int EnergyLogs::indexOf(const QDateTime ×tamp) { if (m_list.isEmpty()) { - return nullptr; + return -1; } QDateTime first = m_list.first()->timestamp(); int index = qRound(1.0 * first.secsTo(timestamp) / (m_sampleRate * 60)); if (index < 0 || index >= m_list.count()) { // qWarning() << "finding:" << timestamp << index << first.toString() << "NOT FOUND" << m_list.last()->timestamp(); - return nullptr; + return -1; } // qWarning() << "finding:" << timestamp << index << first.toString() << m_list.at(index)->timestamp(); + + + // Normally, if the DB is in a consistent state, we can rely that the above finds the correct entry. + // However, if the user changes the timezone, during the lifetime, or other woes may appear like NTP + // changing time which may cause inconsistent entries like passing the same time twice, we could end up + // off by one. In order to compensate for that, we'll see if the next or previous entries may be closer + // In theory we could even be off by some more samples in very rare circumstances, but unlikely enough + // to not bother with that at this point. + QDateTime found = m_list.at(index)->timestamp(); + QDateTime previous = index > 0 ? m_list.at(index-1)->timestamp() : found; + QDateTime next = index < m_list.count() - 1 ? m_list.at(index+1)->timestamp() : found; + + int diffToFound = qAbs(timestamp.secsTo(found)); + int diffToPrevious = qAbs(timestamp.secsTo(previous)); + int diffToNext = qAbs(timestamp.secsTo(next)); + if (diffToPrevious < diffToFound && diffToPrevious < diffToNext) { +// qWarning() << "Correcting to previous" << index << m_list.count() << found << previous << diffToPrevious << diffToFound; + return index - 1; + } + if (diffToNext < diffToFound) { +// qWarning() << "Correcting to next" << index << m_list.count() << found << next << diffToNext << diffToFound; + return index + 1; + } + return index; +} + +EnergyLogEntry *EnergyLogs::find(const QDateTime ×tamp) +{ + int index = indexOf(timestamp); + if (index < 0) { + return nullptr; + } return m_list.at(index); } @@ -255,7 +287,7 @@ void EnergyLogs::getLogsResponse(int commandId, const QVariantMap ¶ms) if (!entries.isEmpty()) { if (m_list.isEmpty()) { - qCDebug(dcEnergyLogs()) << "Energy logs received"; +// qCDebug(dcEnergyLogs()) << "Energy logs received" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson()); beginInsertRows(QModelIndex(), 0, entries.count()); m_list.append(entries); endInsertRows(); diff --git a/libnymea-app/energy/energylogs.h b/libnymea-app/energy/energylogs.h index dc3c85fc..fc9e88e0 100644 --- a/libnymea-app/energy/energylogs.h +++ b/libnymea-app/energy/energylogs.h @@ -85,6 +85,7 @@ public: double maxValue() const; Q_INVOKABLE EnergyLogEntry* get(int index) const; + Q_INVOKABLE int indexOf(const QDateTime ×tamp); Q_INVOKABLE EnergyLogEntry* find(const QDateTime ×tamp); Q_INVOKABLE QList entries() const; diff --git a/nymea-app/ui/mainviews/EnergyView.qml b/nymea-app/ui/mainviews/EnergyView.qml index 28217441..e5634a85 100644 --- a/nymea-app/ui/mainviews/EnergyView.qml +++ b/nymea-app/ui/mainviews/EnergyView.qml @@ -112,21 +112,6 @@ MainViewBase { rowSpacing: 0 columnSpacing: 0 - -// CurrentConsumptionBalancePieChart { -// Layout.fillWidth: true -// Layout.preferredHeight: width -// energyManager: energyManager -// visible: producers.count > 0 -// animationsEnabled: Qt.application.active && root.isCurrentItem -// } -// CurrentProductionBalancePieChart { -// Layout.fillWidth: true -// Layout.preferredHeight: width -// energyManager: energyManager -// visible: producers.count > 0 -// animationsEnabled: Qt.application.active && root.isCurrentItem -// } CurrentPowerBalancePieChart { Layout.fillWidth: true Layout.preferredHeight: width @@ -150,18 +135,6 @@ MainViewBase { producers: producers } -// PowerConsumptionBalanceHistory { -// Layout.fillWidth: true -// Layout.preferredHeight: width -// visible: producers.count > 0 -// } - -// PowerProductionBalanceHistory { -// Layout.fillWidth: true -// Layout.preferredHeight: width -// visible: producers.count > 0 -// } - ConsumersPieChart { Layout.fillWidth: true Layout.preferredHeight: width diff --git a/nymea-app/ui/mainviews/energy/ConsumerStats.qml b/nymea-app/ui/mainviews/energy/ConsumerStats.qml index 24313f31..a77d9b74 100644 --- a/nymea-app/ui/mainviews/energy/ConsumerStats.qml +++ b/nymea-app/ui/mainviews/energy/ConsumerStats.qml @@ -107,7 +107,7 @@ StatsBase { // print("timestamp:", timestamp, "previous:", previousTimestamp) var entry = thingPowerLogs.find(timestamp) var previousEntry = thingPowerLogs.find(previousTimestamp); - if (entry && (previousEntry || !d.loading)) { + if (timestamp < upcomingTimestamp && entry && (previousEntry || !d.loading)) { // print("found entry:", entry.timestamp, previousEntry) var consumption = entry.totalConsumption if (previousEntry) { diff --git a/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml b/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml index 946c2e1e..effe0392 100644 --- a/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml +++ b/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml @@ -55,17 +55,21 @@ StatsBase { return; } + var upcomingTimestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.config.count) // print("refreshing config start", d.config.startTime(), "upcoming:", upcomingTimestamp, "fetchPending", d.fetchPending) for (var i = 0; i < d.config.count; i++) { var timestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.startOffset + i + 1) var previousTimestamp = root.calculateTimestamp(timestamp, d.config.sampleRate, -1) - var entry = powerBalanceLogs.find(timestamp) -// print("timestamp:", timestamp, "found", (entry ? entry.timestamp : "")) + var idx = powerBalanceLogs.indexOf(timestamp); + var entry = powerBalanceLogs.get(idx) +// print("timestamp:", timestamp, "previousTimestamp:", previousTimestamp) var previousEntry = powerBalanceLogs.find(previousTimestamp); - if (entry && (previousEntry || !d.loading)) { -// print("found entry:", entry.timestamp, previousEntry) -// print("Acquisition", entry.totalAcquisition) + if (timestamp < upcomingTimestamp && entry && (previousEntry || !d.loading)) { +// print("found entry:", entry.timestamp, entry.totalConsumption) +// if (previousEntry) { +// print("found previous:", previousEntry.timestamp, previousEntry.totalConsumption) +// } var consumption = entry.totalConsumption var production = entry.totalProduction var acquisition = entry.totalAcquisition