Fixes for the energy dashboard for various corner cases

This commit is contained in:
Michael Zanetti 2022-09-15 17:43:43 +02:00
parent 0ba4b5b193
commit 32b2d42247
7 changed files with 92 additions and 75 deletions

View File

@ -190,7 +190,8 @@ EnergyLogEntry *EnergyLogs::find(const QDateTime &timestamp)
return nullptr; return nullptr;
} }
QDateTime first = m_list.first()->timestamp(); QDateTime first = m_list.first()->timestamp();
int index = 1.0 * first.secsTo(timestamp) / (m_sampleRate * 60);
int index = qRound(1.0 * first.secsTo(timestamp) / (m_sampleRate * 60));
if (index < 0 || index >= m_list.count()) { if (index < 0 || index >= m_list.count()) {
return nullptr; return nullptr;
} }

View File

@ -113,20 +113,20 @@ MainViewBase {
columnSpacing: 0 columnSpacing: 0
CurrentConsumptionBalancePieChart { // CurrentConsumptionBalancePieChart {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
energyManager: energyManager // energyManager: energyManager
visible: producers.count > 0 // visible: producers.count > 0
animationsEnabled: Qt.application.active && root.isCurrentItem // animationsEnabled: Qt.application.active && root.isCurrentItem
} // }
CurrentProductionBalancePieChart { // CurrentProductionBalancePieChart {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
energyManager: energyManager // energyManager: energyManager
visible: producers.count > 0 // visible: producers.count > 0
animationsEnabled: Qt.application.active && root.isCurrentItem // animationsEnabled: Qt.application.active && root.isCurrentItem
} // }
PowerConsumptionBalanceHistory { PowerConsumptionBalanceHistory {
Layout.fillWidth: true Layout.fillWidth: true
@ -134,46 +134,46 @@ MainViewBase {
visible: producers.count > 0 visible: producers.count > 0
} }
PowerProductionBalanceHistory { // PowerProductionBalanceHistory {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
visible: producers.count > 0 // visible: producers.count > 0
} // }
ConsumersPieChart { // ConsumersPieChart {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
energyManager: energyManager // energyManager: energyManager
visible: consumers.count > 0 // visible: consumers.count > 0
colors: root.thingColors // colors: root.thingColors
consumers: consumers // consumers: consumers
animationsEnabled: Qt.application.active && root.isCurrentItem // animationsEnabled: Qt.application.active && root.isCurrentItem
} // }
ConsumersHistory { // ConsumersHistory {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
visible: consumers.count > 0 || rootMeter != null // visible: consumers.count > 0 || rootMeter != null
colors: root.thingColors // colors: root.thingColors
consumers: consumers // consumers: consumers
} // }
PowerBalanceStats { // PowerBalanceStats {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
energyManager: energyManager // energyManager: energyManager
visible: rootMeter != null || producers.count > 0 // visible: rootMeter != null || producers.count > 0
producers: producers // producers: producers
} // }
ConsumerStats { // ConsumerStats {
Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredHeight: width // Layout.preferredHeight: width
energyManager: energyManager // energyManager: energyManager
visible: consumers.count > 0 // visible: consumers.count > 0
colors: root.thingColors // colors: root.thingColors
consumers: consumers // consumers: consumers
} // }
} }
} }
} }

View File

@ -318,31 +318,37 @@ Item {
readonly property Thing thing: consumers.get(index) readonly property Thing thing: consumers.get(index)
property AreaSeries series: null property AreaSeries series: null
function calculateBaseValue(timestamp) {
function getBaseValue(timestamp) {
var ret = 0
if (index > 0) { if (index > 0) {
ret = consumersRepeater.itemAt(index - 1).getBaseValue(timestamp) return consumersRepeater.itemAt(index - 1).calculateValue(timestamp)
} }
return 0
}
function calculateValue(timestamp) {
var ret = calculateBaseValue(timestamp)
var entry = logs.find(timestamp) var entry = logs.find(timestamp)
if (entry) { if (entry) {
ret += entry.currentPower; ret += entry.currentPower;
} }
// print("calculating value for", thing.name, timestamp, ret)
return ret return ret
} }
function insertEntry(idx, entry) { function insertEntry(idx, entry) {
var baseValue = 0; // print("inserting entry for", thing.name, entry.timestamp)
if (index > 0) {
baseValue = consumersRepeater.itemAt(index - 1).getBaseValue(entry.timestamp) var baseValue = calculateBaseValue(entry.timestamp);
} series.lowerSeries.insert(idx, entry.timestamp.getTime(), baseValue)
series.upperSeries.insert(idx, entry.timestamp.getTime(), entry.currentPower + baseValue) series.upperSeries.insert(idx, entry.timestamp.getTime(), baseValue + entry.currentPower)
} }
function addEntries(index, entries) { function addEntries(index, entries) {
print("adding entries for", thing.name) // print("adding entries for", thing.name)
// Remove the leading 0-value entry // Remove the leading 0-value entry
series.lowerSeries.removePoints(0, 1);
series.upperSeries.removePoints(0, 1); series.upperSeries.removePoints(0, 1);
for (var i = 0; i < entries.length; i++) { for (var i = 0; i < entries.length; i++) {
@ -359,6 +365,7 @@ Item {
} }
// Add the leading 0-value entry back // Add the leading 0-value entry back
series.lowerSeries.insert(0, series.upperSeries.at(0).x, 0)
series.upperSeries.insert(0, series.upperSeries.at(0).x, 0) series.upperSeries.insert(0, series.upperSeries.at(0).x, 0)
} }
@ -381,11 +388,14 @@ Item {
onEntriesRemoved: { onEntriesRemoved: {
// Remove the leading 0-value entry // Remove the leading 0-value entry
consumerDelegate.series.lowerSeries.removePoints(0, 1);
consumerDelegate.series.upperSeries.removePoints(0, 1); consumerDelegate.series.upperSeries.removePoints(0, 1);
consumerDelegate.series.lowerSeries.removePoints(index, count)
consumerDelegate.series.upperSeries.removePoints(index, count) consumerDelegate.series.upperSeries.removePoints(index, count)
// Add the leading 0-value entry back // Add the leading 0-value entry back
consumerDelegate.series.lowerSeries.insert(0, consumerDelegate.series.upperSeries.at(0).x, 0)
consumerDelegate.series.upperSeries.insert(0, consumerDelegate.series.upperSeries.at(0).x, 0) consumerDelegate.series.upperSeries.insert(0, consumerDelegate.series.upperSeries.at(0).x, 0)
zeroSeries.shrink() zeroSeries.shrink()
@ -409,13 +419,14 @@ Item {
Component.onCompleted: { Component.onCompleted: {
series = chartView.createSeries(ChartView.SeriesTypeArea, thing.name, dateTimeAxis, valueAxis) series = chartView.createSeries(ChartView.SeriesTypeArea, thing.name, dateTimeAxis, valueAxis)
series.lowerSeries = index == 0 ? zeroSeries : consumersRepeater.itemAt(index - 1).series.upperSeries series.lowerSeries = lineSeriesComponent.createObject(series)
series.upperSeries = lineSeriesComponent.createObject(series) series.upperSeries = lineSeriesComponent.createObject(series)
series.color = NymeaUtils.generateColor(Style.generationBaseColor, index) series.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
series.borderWidth = 0; series.borderWidth = 0;
series.borderColor = series.color series.borderColor = series.color
// Add a first point at 0 value // Add a first point at 0 value
series.lowerSeries.insert(0, new Date().getTime(), 0)
series.upperSeries.insert(0, new Date().getTime(), 0) series.upperSeries.insert(0, new Date().getTime(), 0)
} }
@ -554,7 +565,7 @@ Item {
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height) backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width))) property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width)))
property date timestamp: new Date(d.startTime.getTime() + (idx * d.sampleRate * 60000)) property var timestamp: new Date(Math.min(d.endTime.getTime(), Math.max(d.startTime, d.startTime.getTime() + (idx * d.sampleRate * 60000))))
property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp) property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp)
property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins
@ -574,7 +585,7 @@ Item {
margins: Style.smallMargins margins: Style.smallMargins
} }
Label { Label {
text: toolTip.entry.timestamp.toLocaleString(Qt.locale(), Locale.ShortFormat) text: toolTip.entry ? toolTip.entry.timestamp.toLocaleString(Qt.locale(), Locale.ShortFormat) : 0
font: Style.smallFont font: Style.smallFont
} }
RowLayout { RowLayout {

View File

@ -35,21 +35,26 @@ StatsBase {
onConfigChanged: valueAxis.max = 1 onConfigChanged: valueAxis.max = 1
onStartOffsetChanged: { onStartOffsetChanged: {
print("start offset changed", startOffset)
// print("updating because of offset change. fetchingData", powerBalanceLogs.fetchingData, "fetchPending", d.fetchPending) // print("updating because of offset change. fetchingData", powerBalanceLogs.fetchingData, "fetchPending", d.fetchPending)
refresh() refresh()
} }
onStartTimeChanged: {
print("start time changed", startTime)
}
function refresh() { function refresh() {
if (powerBalanceLogs.loadingInhibited) { if (powerBalanceLogs.loadingInhibited) {
return; return;
} }
var upcomingTimestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.config.count) 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) print("refreshing config start", d.config.startTime(), "upcoming:", upcomingTimestamp, "fetchPending", d.fetchPending)
for (var i = 0; i < d.config.count; i++) { for (var i = 0; i < d.config.count; i++) {
var timestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.startOffset + i + 1) var timestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.startOffset + i + 1)
var previousTimestamp = root.calculateTimestamp(timestamp, d.config.sampleRate, -1) var previousTimestamp = root.calculateTimestamp(timestamp, d.config.sampleRate, -1)
// print("timestamp:", timestamp)
var entry = powerBalanceLogs.find(timestamp) var entry = powerBalanceLogs.find(timestamp)
print("timestamp:", timestamp, "found", (entry ? entry.timestamp : ""))
var previousEntry = powerBalanceLogs.find(previousTimestamp); var previousEntry = powerBalanceLogs.find(previousTimestamp);
if (entry && (previousEntry || !d.loading)) { if (entry && (previousEntry || !d.loading)) {
// print("found entry:", entry.timestamp, previousEntry) // print("found entry:", entry.timestamp, previousEntry)
@ -246,10 +251,10 @@ StatsBase {
categories: { categories: {
var ret = [] var ret = []
print("Updating categories from", d.config.startTime()) // print("Updating categories from", d.config.startTime())
for (var i = 0; i < d.config.count; i++) { for (var i = 0; i < d.config.count; i++) {
var timestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.startOffset + i); var timestamp = root.calculateTimestamp(d.config.startTime(), d.config.sampleRate, d.startOffset + i);
print("*** adding", timestamp, d.startOffset, i) // print("*** adding", timestamp, d.startOffset, i)
ret.push(d.config.toLabel(timestamp)) ret.push(d.config.toLabel(timestamp))
} }
return ret; return ret;

View File

@ -162,7 +162,7 @@ Item {
ActivityIndicator { ActivityIndicator {
x: chartView.plotArea.x + (chartView.plotArea.width - width) / 2 x: chartView.plotArea.x + (chartView.plotArea.width - width) / 2
y: chartView.plotArea.y + (chartView.plotArea.height - height) / 2 + (chartView.plotArea.height / 8) y: chartView.plotArea.y + (chartView.plotArea.height - height) / 2 + (chartView.plotArea.height / 8)
visible: powerBalanceLogs.fetchingData && powerBalanceLogs.get(0).timestamp > d.startTime visible: powerBalanceLogs.fetchingData && (powerBalanceLogs.count == 0 || powerBalanceLogs.get(0).timestamp > d.startTime)
opacity: .5 opacity: .5
} }
Label { Label {
@ -491,7 +491,7 @@ Item {
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height) backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width))) property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width)))
property var timestamp: new Date(d.startTime.getTime() + (idx * d.sampleRate * 60000)) property var timestamp: new Date(Math.min(d.endTime.getTime(), Math.max(d.startTime, d.startTime.getTime() + (idx * d.sampleRate * 60000))))
property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp) property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp)
property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins
@ -511,7 +511,7 @@ Item {
margins: Style.smallMargins margins: Style.smallMargins
} }
Label { Label {
text: toolTip.entry.timestamp.toLocaleString(Qt.locale(), Locale.ShortFormat) text: toolTip.entry ? toolTip.entry.timestamp.toLocaleString(Qt.locale(), Locale.ShortFormat) : ""
font: Style.smallFont font: Style.smallFont
} }

View File

@ -160,7 +160,7 @@ Item {
ActivityIndicator { ActivityIndicator {
x: chartView.plotArea.x + (chartView.plotArea.width - width) / 2 x: chartView.plotArea.x + (chartView.plotArea.width - width) / 2
y: chartView.plotArea.y + (chartView.plotArea.height - height) / 2 + (chartView.plotArea.height / 8) y: chartView.plotArea.y + (chartView.plotArea.height - height) / 2 + (chartView.plotArea.height / 8)
visible: powerBalanceLogs.fetchingData && powerBalanceLogs.get(0).timestamp > d.startTime visible: powerBalanceLogs.fetchingData && (powerBalanceLogs.count == 0 || powerBalanceLogs.get(0).timestamp > d.startTime)
opacity: .5 opacity: .5
} }
Label { Label {
@ -481,7 +481,7 @@ Item {
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height) backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width))) property int idx: Math.min(d.visibleValues, Math.max(0, Math.ceil(mouseArea.mouseX * d.visibleValues / mouseArea.width)))
property var timestamp: new Date(d.startTime.getTime() + (idx * d.sampleRate * 60000)) property var timestamp: new Date(Math.min(d.endTime.getTime(), Math.max(d.startTime, d.startTime.getTime() + (idx * d.sampleRate * 60000))))
property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp) property PowerBalanceLogEntry entry: powerBalanceLogs.find(timestamp)
property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins property int xOnRight: Math.max(0, mouseArea.mouseX) + Style.smallMargins

View File

@ -124,11 +124,11 @@ Item {
function weeksStart() { function weeksStart() {
var d = new Date(); var d = new Date();
d.setHours(0, 0, 0, 0); d.setHours(0, 0, 0, 0);
print("now is:", d, "weeksCount:", weeksCount) // print("now is:", d, "weeksCount:", weeksCount)
// We'll start the week on Monday for now, given that's international ISO standard. For US and Canada we may want to introduce a setting at some point. // We'll start the week on Monday for now, given that's international ISO standard. For US and Canada we may want to introduce a setting at some point.
// JS Date starts on Sunday though, so we'll have to adjust // JS Date starts on Sunday though, so we'll have to adjust
var dayOfWeek = (d.getDay() + 6) % 7 var dayOfWeek = (d.getDay() + 6) % 7
print("getDay", d.getDay(), "dayOfWeek", dayOfWeek, "getDate", d.getDate()) // print("getDay", d.getDay(), "dayOfWeek", dayOfWeek, "getDate", d.getDate())
d.setDate(d.getDate() - dayOfWeek - (weeksCount - 1) * 7); d.setDate(d.getDate() - dayOfWeek - (weeksCount - 1) * 7);
return d return d
} }