Some more work on the power balance stats

This commit is contained in:
Michael Zanetti 2021-11-26 11:16:33 +01:00
parent a2708d918b
commit 6f04164513
5 changed files with 303 additions and 143 deletions

View File

@ -75,6 +75,12 @@ void EnergyLogs::setSampleRate(SampleRate sampleRate)
if (m_sampleRate != sampleRate) {
m_sampleRate = sampleRate;
emit sampleRateChanged();
beginResetModel();
qDeleteAll(m_list);
m_list.clear();
endResetModel();
fetchLogs();
}
}

View File

@ -121,7 +121,7 @@ void PowerBalanceLogs::addEntry(PowerBalanceLogEntry *entry)
EnergyLogEntry *PowerBalanceLogs::find(const QDateTime &timestamp) const
{
qWarning() << "Finding log entry for timestamp:" << timestamp;
// qWarning() << "Finding log entry for timestamp:" << timestamp;
int oldest = 0;
int newest = rowCount() - 1;
EnergyLogEntry *entry = nullptr;
@ -131,7 +131,7 @@ EnergyLogEntry *PowerBalanceLogs::find(const QDateTime &timestamp) const
EnergyLogEntry *newestEntry = get(newest);
int middle = (newest - oldest) / 2 + oldest;
EnergyLogEntry *middleEntry = get(middle);
qWarning() << "Oldest:" << oldestEntry->timestamp().toString() << "Middle:" << middleEntry->timestamp().toString() << "Newest:" << newestEntry->timestamp().toString() << ":" << (newest - oldest);
// qWarning() << "Oldest:" << oldestEntry->timestamp().toString() << "Middle:" << middleEntry->timestamp().toString() << "Newest:" << newestEntry->timestamp().toString() << ":" << (newest - oldest);
if (timestamp <= oldestEntry->timestamp()) {
return oldestEntry;
}
@ -144,9 +144,9 @@ EnergyLogEntry *PowerBalanceLogs::find(const QDateTime &timestamp) const
}
if (timestamp < middleEntry->timestamp()) {
oldest = middle;
} else {
newest = middle;
} else {
oldest = middle;
}
if ((newest - oldest) <= 1) {

View File

@ -97,54 +97,54 @@ MainViewBase {
columnSpacing: 0
CurrentConsumptionBalancePieChart {
Layout.fillWidth: true
Layout.preferredHeight: width
energyManager: energyManager
visible: producers.count > 0
}
CurrentProductionBalancePieChart {
Layout.fillWidth: true
Layout.preferredHeight: width
energyManager: energyManager
visible: producers.count > 0
}
// CurrentConsumptionBalancePieChart {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// energyManager: energyManager
// visible: producers.count > 0
// }
// CurrentProductionBalancePieChart {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// energyManager: energyManager
// visible: producers.count > 0
// }
PowerConsumptionBalanceHistory {
Layout.fillWidth: true
Layout.preferredHeight: width
visible: producers.count > 0
}
// PowerConsumptionBalanceHistory {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// visible: producers.count > 0
// }
PowerProductionBalanceHistory {
Layout.fillWidth: true
Layout.preferredHeight: width
visible: producers.count > 0
}
// PowerProductionBalanceHistory {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// visible: producers.count > 0
// }
ConsumersBarChart {
Layout.fillWidth: true
Layout.preferredHeight: width
energyManager: energyManager
visible: consumers.count > 0
}
ConsumersHistory {
Layout.fillWidth: true
Layout.preferredHeight: width
visible: consumers.count > 0
}
// ConsumersBarChart {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// energyManager: energyManager
// visible: consumers.count > 0
// }
// ConsumersHistory {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// visible: consumers.count > 0
// }
PowerBalanceStats {
Layout.fillWidth: true
Layout.preferredHeight: width
energyManager: energyManager
}
ConsumerStats {
Layout.fillWidth: true
Layout.preferredHeight: width
energyManager: energyManager
visible: consumers.count > 0
}
// ConsumerStats {
// Layout.fillWidth: true
// Layout.preferredHeight: width
// energyManager: energyManager
// visible: consumers.count > 0
// }
}
}

View File

@ -21,6 +21,7 @@ ChartView {
property EnergyManager energyManager: null
readonly property date dayStart: {
var d = new Date();
d.setHours(0,0,0,0);

View File

@ -3,24 +3,55 @@ import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3
import QtCharts 2.3
import Nymea 1.0
import "qrc:/ui/components/"
ChartView {
ColumnLayout {
id: root
backgroundColor: "transparent"
legend.alignment: Qt.AlignBottom
legend.font: Style.extraSmallFont
legend.labelColor: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0 ? Style.foregroundColor : Style.gray
// margins.left: 0
margins.right: 0
margins.bottom: 0
margins.top: 0
title: qsTr("Energy consumption statistics")
titleColor: Style.foregroundColor
property EnergyManager energyManager: null
readonly property date minuteStart: {
var d = new Date();
d.setSeconds(0, 0)
return d;
}
readonly property var minutesList: {
var ret = []
for (var i = 15; i >= 0; i--) {
var last = new Date(minuteStart)
ret.push(last.setTime(last.getTime() - i * 60 * 1000))
}
return ret;
}
readonly property var minutesListNames: {
var ret = []
for (var i = 0; i < minutesList.length; i++) {
ret.push(new Date(minutesList[i]).toLocaleString(Qt.locale(), "hh:mm"))
}
return ret;
}
readonly property date hourStart: {
var d = new Date();
d.setMinutes(0, 0, 0);
return d;
}
readonly property var hoursList: {
var ret = []
for (var i = 24; i >= 0; i--) {
var last = new Date(hourStart)
}
return ret;
}
readonly property var hoursListNames: {
var ret = [];
for (var i = 0; i < hoursList.length; i++) {
ret.push(new Date(hoursList[i]).toLocaleString(Qt.locale(), "dd"));
}
return ret;
}
readonly property date dayStart: {
var d = new Date();
d.setHours(0,0,0,0);
@ -65,21 +96,101 @@ ChartView {
return d;
}
Label {
Layout.fillWidth: true
Layout.margins: Style.smallMargins
horizontalAlignment: Text.AlignHCenter
text: qsTr("Energy consumption statistics")
}
SelectionTabs {
id: selectionTabs
Layout.fillWidth: true
Layout.leftMargin: Style.smallMargins
Layout.rightMargin: Style.smallMargins
model: ListModel {
// ListElement {
// modelData: qsTr("Year")
// sampleRate: EnergyLogs.SampleRate1Year
// }
// ListElement {
// text: qsTr("Month")
// sampleRate: EnergyLogs.SampleRate1Month
// }
// ListElement {
// text: qsTr("Week")
// sampleRate: EnergyLogs.SampleRate1Week
// }
Component.onCompleted: {
append({modelData: qsTr("Day"), config: "days", sampleRate: EnergyLogs.SampleRate1Day, startTime: yearStart, sampleList: daysList, sampleListNames: daysListNames })
append({modelData: qsTr("Hour"), config: "hours", sampleRate: EnergyLogs.SampleRate1Hour, startTime: monthStart, sampleList: hoursList, sampleListNames: hoursListNames })
}
// ListElement {
// modelData: qsTr("Day")
// sampleRate: EnergyLogs.SampleRate1Day
// startTime: weekStart
// }
// ListElement {
// modelData: qsTr("Hour")
// sampleRate: EnergyLogs.SampleRate1Hour
// startTime: dayStart
// }
}
// currentIndex: 3
onCurrentValueChanged: {
print("Selecging model:", currentValue)
powerBalanceLogs.loadingInhibited = true
powerBalanceLogs.sampleRate = currentValue.sampleRate
powerBalanceLogs.startTime = currentValue.startTime
powerBalanceLogs.loadingInhibited = false
consumptionSeries.remove(0, consumptionSeries.count-1)
productionSeries.remove(0, productionSeries.count-1)
acquisitionSeries.remove(0, acquisitionSeries.count-1)
returnSeries.remove(0, returnSeries.count-1)
print("sample list names:", currentValue.sampleListNames)
categoryAxis.categories = currentValue.sampleListNames
}
}
Connections {
target: energyManager
onPowerBalanceChanged: {
var start = powerBalanceLogs.get(powerBalanceLogs.count - 1)
print("updating", start.timestamp, root.energyManager.totalConsumption - (start ? start.totalConsumption : 0))
consumptionSeries.replace(consumptionSeries.count - 1, root.energyManager.totalConsumption - (start ? start.totalConsumption : 0))
productionSeries.replace(productionSeries.count - 1, root.energyManager.totalProduction - (start ? start.totalProduction : 0))
acquisitionSeries.replace(acquisitionSeries.count - 1, root.energyManager.totalAcquisition - (start ? start.totalAcquisition : 0))
returnSeries.replace(returnSeries.count - 1, root.energyManager.totalReturn - (start ? start.totalReturn : 0))
}
}
PowerBalanceLogs {
id: powerBalanceLogs
engine: _engine
sampleRate: EnergyLogs.SampleRate1Day
startTime: root.yearStart;
// sampleRate: EnergyLogs.SampleRate1Day
// startTime: root.yearStart;
sampleRate: selectionTabs.currentValue.sampleRate// EnergyLogs.SampleRate1Min
startTime: selectionTabs.currentValue.startTime // root.weekStart;
property var sampleList: minutesList
onFetchingDataChanged: {
if (!fetchingData) {
for (var i = 0; i < daysList.length; i++) {
var start = powerBalanceLogs.find(new Date(daysList[i]))
for (var i = 0; i < sampleList.length; i++) {
var start = powerBalanceLogs.find(new Date(sampleList[i]))
var end = null;
if (i+1 < daysList.length) {
end = powerBalanceLogs.find(new Date(daysList[i+1]))
if (i+1 < sampleList.length) {
end = powerBalanceLogs.find(new Date(sampleList[i+1]))
}
print("** stats for", daysList[i], new Date(daysList[i]), start.timestamp, start.totalConsumption)
print("** stats for:", new Date(sampleList[i]), start.timestamp, start.totalConsumption)
var consumptionValue = (end != null ? end.totalConsumption : root.energyManager.totalConsumption) - (start ? start.totalConsumption : 0)
var productionValue = (end != null ? end.totalProduction : root.energyManager.totalProduction) - (start ? start.totalProduction : 0)
var acquisitionValue = (end != null ? end.totalAcquisition : root.energyManager.totalAcquisition) - (start ? start.totalAcquisition : 0)
@ -96,98 +207,140 @@ ChartView {
}
}
}
}
Item {
id: labelsLayout
x: Style.smallMargins
y: root.plotArea.y
height: root.plotArea.height
width: plotArea.x - x
enabled: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0
Repeater {
model: valueAxis.tickCount
delegate: Label {
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
width: parent.width - Style.smallMargins
horizontalAlignment: Text.AlignRight
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1)))).toFixed(0) + "kWh"
verticalAlignment: Text.AlignTop
font: Style.extraSmallFont
onEntryAdded: {
if (fetchingData) {
return
}
var start = entry
var consumptionValue = root.energyManager.totalConsumption - (start ? start.totalConsumption : 0)
var productionValue = root.energyManager.totalProduction - (start ? start.totalProduction : 0)
var acquisitionValue = root.energyManager.totalAcquisition - (start ? start.totalAcquisition : 0)
var returnValue = root.energyManager.totalReturn - (start ? start.totalReturn : 0)
consumptionSeries.append(consumptionValue)
productionSeries.append(productionValue)
acquisitionSeries.append(acquisitionValue)
returnSeries.append(returnValue)
consumptionSeries.remove(0, 1);
productionSeries.remove(0, 1);
acquisitionSeries.remove(0, 1);
returnSeries.remove(0, 1);
}
}
BarSeries {
axisX: BarCategoryAxis {
id: categoryAxis
categories: daysListNames
labelsColor: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0 ? Style.foregroundColor : Style.gray
labelsFont: Style.extraSmallFont
gridVisible: false
gridLineColor: Style.tileOverlayColor
lineVisible: false
titleVisible: false
shadesVisible: false
ChartView {
id: chartView
Layout.fillWidth: true
Layout.fillHeight: true
}
axisY: ValueAxis {
id: valueAxis
min: 0
gridLineColor: Style.tileOverlayColor
labelsVisible: false
labelsColor: Style.foregroundColor
labelsFont: Style.extraSmallFont
lineVisible: false
titleVisible: false
shadesVisible: false
backgroundColor: "transparent"
legend.alignment: Qt.AlignBottom
legend.font: Style.extraSmallFont
legend.labelColor: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0 ? Style.foregroundColor : Style.gray
function adjustMax(newValue) {
if (max < newValue) {
max = Math.ceil(newValue / 100) * 100
// margins.left: 0
margins.right: 0
margins.bottom: 0
margins.top: 0
// title: qsTr("Energy consumption statistics")
// titleColor: "red"// Style.foregroundColor
Item {
id: labelsLayout
x: Style.smallMargins
y: chartView.plotArea.y
height: chartView.plotArea.height
width: chartView.plotArea.x - x
enabled: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0
Repeater {
model: valueAxis.tickCount
delegate: Label {
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
width: parent.width - Style.smallMargins
horizontalAlignment: Text.AlignRight
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1)))).toFixed(0) + "kWh"
verticalAlignment: Text.AlignTop
font: Style.extraSmallFont
}
}
}
BarSet {
id: consumptionSeries
label: qsTr("Consumed")
borderWidth: 0
}
BarSet {
id: productionSeries
label: qsTr("Produced")
color: Style.green
borderWidth: 0
borderColor: color
}
BarSet {
id: acquisitionSeries
label: qsTr("From grid")
color: Style.red
borderWidth: 0
borderColor: color
}
BarSet {
id: returnSeries
label: qsTr("To grid")
color: Style.orange
borderWidth: 0
borderColor: color
}
}
BarSeries {
axisX: BarCategoryAxis {
id: categoryAxis
// categories: daysListNames
// categories: minutesListNames
labelsColor: !powerBalanceLogs.fetchingData && powerBalanceLogs.count > 0 ? Style.foregroundColor : Style.gray
Label {
x: root.plotArea.x
y: root.plotArea.y
width: root.plotArea.width
height: root.plotArea.height
wrapMode: Text.WordWrap
text: qsTr("No data available")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: !powerBalanceLogs.fetchingData && powerBalanceLogs.count == 0
labelsFont: Style.extraSmallFont
gridVisible: false
gridLineColor: Style.tileOverlayColor
lineVisible: false
titleVisible: false
shadesVisible: false
}
axisY: ValueAxis {
id: valueAxis
min: 0
gridLineColor: Style.tileOverlayColor
labelsVisible: false
labelsColor: Style.foregroundColor
labelsFont: Style.extraSmallFont
lineVisible: false
titleVisible: false
shadesVisible: false
function adjustMax(newValue) {
if (max < newValue) {
max = newValue // Math.ceil(newValue / 100) * 100
}
}
}
BarSet {
id: consumptionSeries
label: qsTr("Consumed")
borderWidth: 0
}
BarSet {
id: productionSeries
label: qsTr("Produced")
color: Style.green
borderWidth: 0
borderColor: color
}
BarSet {
id: acquisitionSeries
label: qsTr("From grid")
color: Style.red
borderWidth: 0
borderColor: color
}
BarSet {
id: returnSeries
label: qsTr("To grid")
color: Style.orange
borderWidth: 0
borderColor: color
}
}
Label {
x: chartView.plotArea.x
y: chartView.plotArea.y
width: chartView.plotArea.width
height: chartView.plotArea.height
wrapMode: Text.WordWrap
text: qsTr("No data available")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: !powerBalanceLogs.fetchingData && powerBalanceLogs.count == 0
}
}
}