diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc
index 3141da19..c9f5fad0 100644
--- a/nymea-app/resources.qrc
+++ b/nymea-app/resources.qrc
@@ -281,5 +281,11 @@
ui/mainviews/energy/PowerBalanceHistory.qml
ui/mainviews/energy/CurrentPowerBalancePieChart.qml
ui/components/MultiSelectionTabs.qml
+ ui/mainviews/energy/PowerBalanceHistoryPage.qml
+ ui/mainviews/energy/CurrentPowerBalancePage.qml
+ ui/mainviews/energy/PowerBalanceStatsPage.qml
+ ui/mainviews/energy/ConsumersHistoryPage.qml
+ ui/mainviews/energy/ConsumerStatsPage.qml
+ ui/mainviews/energy/ConsumersPieChartPage.qml
diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml
index b8abf74d..d1b05506 100644
--- a/nymea-app/ui/Nymea.qml
+++ b/nymea-app/ui/Nymea.qml
@@ -142,7 +142,7 @@ ApplicationWindow {
property NymeaDiscovery nymeaDiscovery: NymeaDiscovery {
objectName: "discovery"
awsClient: AWSClient
- bluetoothDiscoveryEnabled: PlatformPermissions.bluetoothPermission === PlatformPermissions.PermissionStatusGranted
+ bluetoothDiscoveryEnabled: false// PlatformPermissions.bluetoothPermission === PlatformPermissions.PermissionStatusGranted
}
property var supportedInterfaces: [
diff --git a/nymea-app/ui/mainviews/EnergyView.qml b/nymea-app/ui/mainviews/EnergyView.qml
index 3effb62d..28217441 100644
--- a/nymea-app/ui/mainviews/EnergyView.qml
+++ b/nymea-app/ui/mainviews/EnergyView.qml
@@ -60,8 +60,6 @@ MainViewBase {
engine: _engine
}
- property var thingColors: [Style.blue, Style.green, Style.red, Style.yellow, Style.purple, Style.orange, Style.lime, Style.pink, Style.darkBlue]
-
ThingsProxy {
id: energyMeters
@@ -169,7 +167,6 @@ MainViewBase {
Layout.preferredHeight: width
energyManager: energyManager
visible: consumers.count > 0
- colors: root.thingColors
consumers: consumers
animationsEnabled: Qt.application.active && root.isCurrentItem && flickable.contentY < y + height && flickable.contentY + flickable.height > y
onAnimationsEnabledChanged: print("animations for consumer balance chart", animationsEnabled ? "enabled" : "disabled")
@@ -180,7 +177,7 @@ MainViewBase {
Layout.fillWidth: true
Layout.preferredHeight: width
visible: consumers.count > 0
- colors: root.thingColors
+ energyManager: energyManager
consumers: consumers
}
@@ -189,7 +186,6 @@ MainViewBase {
Layout.preferredHeight: width
energyManager: energyManager
visible: consumers.count > 0
- colors: root.thingColors
consumers: consumers
}
}
diff --git a/nymea-app/ui/mainviews/energy/ConsumerStats.qml b/nymea-app/ui/mainviews/energy/ConsumerStats.qml
index 2e73eec1..24313f31 100644
--- a/nymea-app/ui/mainviews/energy/ConsumerStats.qml
+++ b/nymea-app/ui/mainviews/energy/ConsumerStats.qml
@@ -9,9 +9,8 @@ StatsBase {
id: root
property EnergyManager energyManager: null
- property var colors: null
-
property ThingsProxy consumers: null
+ property bool titleVisible: true
QtObject {
id: d
@@ -20,6 +19,8 @@ StatsBase {
property int startOffset: 0
+ property Thing selectedThing: null
+
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
@@ -45,6 +46,14 @@ StatsBase {
consumersRepeater.itemAt(i).refresh()
}
}
+
+ function selectThing(thing) {
+ if (d.selectedThing === thing) {
+ d.selectedThing = null
+ } else {
+ d.selectedThing = thing
+ }
+ }
}
ThingPowerLogsLoader {
@@ -146,9 +155,11 @@ StatsBase {
}
barSet = barSeries.append(consumerDelegate.thing.name, values)
- barSet.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
- barSet.borderColor = barSet.color
- barSet.borderWith = 0
+ barSet.color = Qt.binding(function() {
+ return NymeaUtils.generateColor(Style.generationBaseColor, index, d.selectedThing == null || consumerDelegate.thing == d.selectedThing ? 1 : 0.3)
+ })
+ barSet.borderColor = Qt.binding(function(){ return barSet.color})
+ barSet.borderWidth = 0
}
Component.onDestruction: {
barSeries.remove(barSet)
@@ -160,12 +171,17 @@ StatsBase {
anchors.fill: parent
spacing: 0
-// Label {
-// Layout.fillWidth: true
-// Layout.margins: Style.smallMargins
-// horizontalAlignment: Text.AlignHCenter
-// text: qsTr("Consumers totals")
-// }
+ Label {
+ Layout.fillWidth: true
+ Layout.margins: Style.smallMargins
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("Consumers totals")
+ visible: root.titleVisible
+ MouseArea {
+ anchors.fill: parent
+ onClicked: pageStack.push(Qt.resolvedUrl("ConsumerStatsPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
+ }
+ }
SelectionTabs {
id: selectionTabs
@@ -311,6 +327,7 @@ StatsBase {
}
RowLayout {
+ id: legend
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
anchors.leftMargin: chartView.plotArea.x
height: Style.smallIconSize
@@ -318,17 +335,30 @@ StatsBase {
Repeater {
model: root.consumers
- delegate: Item {
+ delegate: MouseArea {
id: legendDelegate
Layout.fillWidth: true
Layout.fillHeight: true
readonly property Thing thing: root.consumers.get(index)
- ColorIcon {
- name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
- size: Style.smallIconSize
- color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
+ onClicked: d.selectThing(thing)
+ Row {
anchors.centerIn: parent
+ spacing: Style.smallMargins
+ ColorIcon {
+ name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
+ size: Style.smallIconSize
+ color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
+ }
+ Label {
+ text: legendDelegate.thing.name
+ width: Math.max(0, legendDelegate.width - x)
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ font: Style.smallFont
+ visible: legend.width / root.consumers.count >= 80
+ }
}
+
}
}
}
@@ -496,7 +526,7 @@ StatsBase {
var consumerDelegate = consumersRepeater.itemAt(i)
var consumer = consumerDelegate.thing
var entry = {
- name: consumer.name,
+ consumer: consumer,
value: consumersRepeater.itemAt(i).barSet.at(toolTip.idx).toFixed(2),
indexInModel: i
}
@@ -518,14 +548,14 @@ StatsBase {
}
delegate: RowLayout {
+ opacity: d.selectedThing == null || d.selectedThing === model.consumer ? 1 : 0.3
Rectangle {
width: Style.extraSmallFont.pixelSize
height: width
- // color: root.colors[model.indexInModel % root.colors.length]
color: NymeaUtils.generateColor(Style.generationBaseColor, model.indexInModel)
}
Label {
- text: "%1: %2 kWh".arg(model.name).arg(model.value)
+ text: "%1: %2 kWh".arg(model.consumer.name).arg(model.value)
font: Style.extraSmallFont
}
}
diff --git a/nymea-app/ui/mainviews/energy/ConsumerStatsPage.qml b/nymea-app/ui/mainviews/energy/ConsumerStatsPage.qml
new file mode 100644
index 00000000..1853812f
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/ConsumerStatsPage.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ property alias energyManager: consumersStats
+ property alias consumers: consumersStats.consumers
+
+ header: NymeaHeader {
+ text: qsTr("Consumers balance")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ ConsumerStats {
+ id: consumersStats
+ anchors.fill: parent
+ titleVisible: false
+ }
+}
diff --git a/nymea-app/ui/mainviews/energy/ConsumersHistory.qml b/nymea-app/ui/mainviews/energy/ConsumersHistory.qml
index 68b051b7..1f5f38f5 100644
--- a/nymea-app/ui/mainviews/energy/ConsumersHistory.qml
+++ b/nymea-app/ui/mainviews/energy/ConsumersHistory.qml
@@ -8,8 +8,9 @@ import "qrc:/ui/components"
Item {
id: root
- property var colors: null
+ property EnergyManager energyManager: null
property ThingsProxy consumers: null
+ property bool titleVisible: true
PowerBalanceLogs {
id: powerBalanceLogs
@@ -53,6 +54,8 @@ Item {
property date now: new Date()
+ property var selectedSeries: null
+
readonly property int range: selectionTabs.currentValue.range
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
readonly property int visibleValues: range / sampleRate
@@ -95,6 +98,15 @@ Item {
logsLoader.fetchLogs();
}
}
+
+ function selectSeries(series) {
+ print("selecting series", series)
+ if (d.selectedSeries === series) {
+ d.selectedSeries = null
+ } else {
+ d.selectedSeries = series
+ }
+ }
}
Connections {
@@ -111,12 +123,17 @@ Item {
anchors.fill: parent
spacing: 0
-// Label {
-// Layout.fillWidth: true
-// Layout.margins: Style.smallMargins
-// horizontalAlignment: Text.AlignHCenter
-// text: qsTr("Consumers history")
-// }
+ Label {
+ Layout.fillWidth: true
+ Layout.margins: Style.smallMargins
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("Consumers history")
+ visible: root.titleVisible
+ MouseArea {
+ anchors.fill: parent
+ onClicked: pageStack.push(Qt.resolvedUrl("ConsumersHistoryPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
+ }
+ }
SelectionTabs {
id: selectionTabs
@@ -456,8 +473,11 @@ Item {
series.lowerSeries = lineSeriesComponent.createObject(series)
series.upperSeries = lineSeriesComponent.createObject(series)
series.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
+ series.opacity = Qt.binding(function() {
+ return d.selectedSeries == null || d.selectedSeries == series ? 1 : 0.3
+ })
series.borderWidth = 0;
- series.borderColor = series.color
+ series.borderColor = series.color
// Add a first point at 0 value
series.lowerSeries.insert(0, new Date().getTime(), 0)
@@ -472,6 +492,7 @@ Item {
}
RowLayout {
+ id: legend
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
anchors.leftMargin: chartView.plotArea.x
height: Style.smallIconSize
@@ -479,23 +500,34 @@ Item {
Repeater {
model: root.consumers
- delegate: Item {
+ delegate: MouseArea {
id: legendDelegate
Layout.fillWidth: true
Layout.fillHeight: true
readonly property Thing thing: root.consumers.get(index)
- ColorIcon {
- name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
- size: Style.smallIconSize
- color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
+ onClicked: d.selectSeries(consumersRepeater.itemAt(index).series)
+ opacity: d.selectedSeries == null || d.selectedSeries === consumersRepeater.itemAt(index).series ? 1 : 0.3
+ Row {
anchors.centerIn: parent
+ spacing: Style.smallMargins
+ ColorIcon {
+ name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
+ size: Style.smallIconSize
+ color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
+ }
+ Label {
+ text: legendDelegate.thing.name
+ width: Math.max(0, legendDelegate.width - x)
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ font: Style.smallFont
+ visible: legend.width / root.consumers.count >= 80
+ }
}
}
}
-
}
-
MouseArea {
id: mouseArea
anchors.fill: parent
@@ -665,20 +697,21 @@ Item {
Repeater {
model: consumersRepeater.count
delegate: RowLayout {
+ readonly property Item chartItem: consumersRepeater.itemAt(index)
id: consumerToolTipDelegate
+ opacity: d.selectedSeries == null || d.selectedSeries === chartItem.series ? 1 : 0.3
Rectangle {
width: Style.extraSmallFont.pixelSize
height: width
- // color: index >= 0 ? root.colors[index % root.colors.length] : "white"
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
}
Label {
- property ThingPowerLogEntry entry: toolTip.idx >= 0 ? consumersRepeater.itemAt(index).logs.find(toolTip.timestamp) : null
+ property ThingPowerLogEntry entry: toolTip.idx >= 0 ? chartItem.logs.find(toolTip.timestamp) : null
property double rawValue: entry ? entry.currentPower : 0
property double displayValue: rawValue >= 1000 ? rawValue / 1000 : rawValue
property string unit: rawValue >= 1000 ? "kW" : "W"
- text: "%1: %2 %3".arg(consumersRepeater.itemAt(index).thing.name).arg(displayValue.toFixed(2)).arg(unit)
+ text: "%1: %2 %3".arg(chartItem.thing.name).arg(displayValue.toFixed(2)).arg(unit)
font: Style.extraSmallFont
}
}
diff --git a/nymea-app/ui/mainviews/energy/ConsumersHistoryPage.qml b/nymea-app/ui/mainviews/energy/ConsumersHistoryPage.qml
new file mode 100644
index 00000000..5edf087d
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/ConsumersHistoryPage.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ property alias energyManager: consumersHistory
+ property alias consumers: consumersHistory.consumers
+
+ header: NymeaHeader {
+ text: qsTr("Power balance totals")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ ConsumersHistory {
+ id: consumersHistory
+ anchors.fill: parent
+ titleVisible: false
+ }
+}
diff --git a/nymea-app/ui/mainviews/energy/ConsumersPieChart.qml b/nymea-app/ui/mainviews/energy/ConsumersPieChart.qml
index ef8cffe2..fc42cb06 100644
--- a/nymea-app/ui/mainviews/energy/ConsumersPieChart.qml
+++ b/nymea-app/ui/mainviews/energy/ConsumersPieChart.qml
@@ -7,23 +7,13 @@ import QtCharts 2.2
import Nymea 1.0
import "qrc:/ui/components"
-ChartView {
+Item {
id: root
- backgroundColor: "transparent"
- animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-// title: qsTr("Consumers balance")
- titleColor: Style.foregroundColor
- legend.visible: false
-
- margins.left: 0
- margins.right: 0
- margins.bottom: 0
- margins.top: 0
property EnergyManager energyManager: null
property ThingsProxy consumers: null
- property var colors: null
property bool animationsEnabled: true
+ property bool titleVisible: true
readonly property Thing rootMeter: engine.thingManager.fetchingData ? null : engine.thingManager.things.getThing(energyManager.rootMeterId)
onRootMeterChanged: updateConsumers()
@@ -72,7 +62,7 @@ ChartView {
}
function updateConsumers() {
- root.animationOptions = ChartView.NoAnimation
+ chart.animationOptions = ChartView.NoAnimation
consumersBalanceSeries.clear();
d.unknownSlice = null
d.idleSlice = null
@@ -115,131 +105,164 @@ ChartView {
d.thingsColorMap = colorMap
- root.animationOptions = Qt.binding(function() {
+ chart.animationOptions = Qt.binding(function() {
return root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
})
}
- PieSeries {
- id: consumersBalanceSeries
- size: 0.88
- holeSize: 0.7
+ Label {
+ id: titleLabel
+ anchors { left: parent.left; top: parent.top; right: parent.right; margins: Style.smallMargins }
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("Consumers balance")
+ visible: root.titleVisible
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ pageStack.push(Qt.resolvedUrl("ConsumersPieChartPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
+ }
+ }
}
- Flickable {
- id: centerLayout
- x: root.plotArea.x + (root.plotArea.width - width) / 2
- y: root.plotArea.y + (root.plotArea.height - height) / 2
- width: Math.min(root.plotArea.width, root.plotArea.width) * 0.65
- height: Math.min(contentColumn.height + topMargin + bottomMargin, width)
- topMargin: Style.smallIconSize
- bottomMargin: Style.smallIconSize
- opacity: 0
-// property int maximumHeight: root.plotArea.height * 0.65
- contentHeight: contentColumn.implicitHeight
+ ChartView {
+ id: chart
- ColumnLayout {
- id: contentColumn
- width: parent.width
- spacing: Style.smallMargins
+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; top: titleLabel.bottom}
+
+ backgroundColor: "transparent"
+ animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
+ titleColor: Style.foregroundColor
+ legend.visible: false
+
+ margins.left: 0
+ margins.right: 0
+ margins.bottom: 0
+ margins.top: 0
+
+
+ PieSeries {
+ id: consumersBalanceSeries
+ size: 0.88
+ holeSize: 0.7
+ }
+
+ Flickable {
+ id: centerLayout
+ x: chart.plotArea.x + (chart.plotArea.width - width) / 2
+ y: chart.plotArea.y + (chart.plotArea.height - height) / 2
+ width: Math.min(chart.plotArea.width, chart.plotArea.width) * 0.65
+ height: Math.min(contentColumn.height + topMargin + bottomMargin, width)
+ topMargin: Style.smallIconSize
+ bottomMargin: Style.smallIconSize
+ opacity: 0
+ // property int maximumHeight: chart.plotArea.height * 0.65
+
+ contentHeight: contentColumn.implicitHeight
ColumnLayout {
- Layout.fillWidth: true
- spacing: 0
- visible: root.rootMeter
- Label {
- text: qsTr("Total")
- font: Style.smallFont
- Layout.topMargin: Style.smallMargins
+ id: contentColumn
+ width: parent.width
+ spacing: Style.smallMargins
+
+ ColumnLayout {
Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- }
-
- Label {
- // We're using the maximum value of the energy managers consumption, the sum of all consumers because:
- // * in a standard setup, the energy manager would know everything and the consumption will always be greater than the sum of all individual consumers
- // * if there is a producer which is unknown to nymea though, it will decrease the consumption on the root meter so it may be smaller than the
- // summation of all consumers. In this particular chart that would be nonsense so in the end we'll only lose the "unknown" power consumption in such a setup
- property double finalTotal: Math.max(energyManager.currentPowerConsumption, d.consumersSummation)
- text: "%1 %2"
- .arg((finalTotal / (finalTotal > 1000 ? 1000 : 1)).toFixed(1))
- .arg(finalTotal > 1000 ? "kW" : "W")
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- font: Style.bigFont
- }
- }
-
- Repeater {
- model: ThingsProxy {
- id: sortedConsumers
- engine: _engine
- parentProxy: root.consumers
- sortStateName: "currentPower"
- sortOrder: Qt.DescendingOrder
- }
-
- delegate: ColumnLayout {
- id: consumerDelegate
- width: parent ? parent.width : 0
spacing: 0
- property Thing consumer: consumers.getThing(model.id)
- property State currentPowerState: consumer ? consumer.stateByName("currentPower") : null
- property double value: currentPowerState ? currentPowerState.value : 0
+ visible: root.rootMeter
+ Label {
+ text: qsTr("Total")
+ font: Style.smallFont
+ Layout.topMargin: Style.smallMargins
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ }
Label {
- text: model.name
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- font: Style.extraSmallFont
- }
- Label {
- color: d.thingsColorMap.hasOwnProperty(consumer) ? d.thingsColorMap[consumer] : "transparent"
+ // We're using the maximum value of the energy managers consumption, the sum of all consumers because:
+ // * in a standard setup, the energy manager would know everything and the consumption will always be greater than the sum of all individual consumers
+ // * if there is a producer which is unknown to nymea though, it will decrease the consumption on the root meter so it may be smaller than the
+ // summation of all consumers. In this particular chart that would be nonsense so in the end we'll only lose the "unknown" power consumption in such a setup
+ property double finalTotal: Math.max(energyManager.currentPowerConsumption, d.consumersSummation)
text: "%1 %2"
- .arg((consumerDelegate.value / (consumerDelegate.value > 1000 ? 1000 : 1)).toFixed(1))
- .arg(consumerDelegate.value > 1000 ? "kW" : "W")
+ .arg((finalTotal / (finalTotal > 1000 ? 1000 : 1)).toFixed(1))
+ .arg(finalTotal > 1000 ? "kW" : "W")
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
- font: Style.smallFont
+ font: Style.bigFont
+ }
+ }
+
+ Repeater {
+ model: ThingsProxy {
+ id: sortedConsumers
+ engine: _engine
+ parentProxy: root.consumers
+ sortStateName: "currentPower"
+ sortOrder: Qt.DescendingOrder
+ }
+
+ delegate: ColumnLayout {
+ id: consumerDelegate
+ width: parent ? parent.width : 0
+ spacing: 0
+ property Thing consumer: consumers.getThing(model.id)
+ property State currentPowerState: consumer ? consumer.stateByName("currentPower") : null
+ property double value: currentPowerState ? currentPowerState.value : 0
+
+ Label {
+ text: model.name
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font: Style.extraSmallFont
+ }
+ Label {
+ color: d.thingsColorMap.hasOwnProperty(consumer) ? d.thingsColorMap[consumer] : "transparent"
+ text: "%1 %2"
+ .arg((consumerDelegate.value / (consumerDelegate.value > 1000 ? 1000 : 1)).toFixed(1))
+ .arg(consumerDelegate.value > 1000 ? "kW" : "W")
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font: Style.smallFont
+ }
}
}
}
+
}
- }
-
- Rectangle {
- id: innerMask
- anchors.fill: centerLayout
- radius: width / 2
- visible: false
- gradient: Gradient {
- GradientStop { position: 0; color: "transparent" }
- GradientStop { position: 1-(centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
- GradientStop { position: (centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
- GradientStop { position: 1; color: "transparent" }
+ Rectangle {
+ id: innerMask
+ anchors.fill: centerLayout
+ radius: width / 2
+ visible: false
+ gradient: Gradient {
+ GradientStop { position: 0; color: "transparent" }
+ GradientStop { position: 1-(centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
+ GradientStop { position: (centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
+ GradientStop { position: 1; color: "transparent" }
+ }
}
- }
- OpacityMask {
- anchors.fill: centerLayout
- source: centerLayout
- maskSource: innerMask
- }
+ OpacityMask {
+ anchors.fill: centerLayout
+ source: centerLayout
+ maskSource: innerMask
+ }
- ColorIcon {
- id: upArrow
- anchors { top: centerLayout.top; horizontalCenter: centerLayout.horizontalCenter }
- size: Style.smallIconSize
- name: "up"
- visible: !centerLayout.atYBeginning
- }
- ColorIcon {
- id: downArrow
- anchors { bottom: centerLayout.bottom; horizontalCenter: centerLayout.horizontalCenter }
- size: Style.smallIconSize
- name: "down"
- visible: !centerLayout.atYEnd
+ ColorIcon {
+ id: upArrow
+ anchors { top: centerLayout.top; horizontalCenter: centerLayout.horizontalCenter }
+ size: Style.smallIconSize
+ name: "up"
+ visible: !centerLayout.atYBeginning
+ }
+ ColorIcon {
+ id: downArrow
+ anchors { bottom: centerLayout.bottom; horizontalCenter: centerLayout.horizontalCenter }
+ size: Style.smallIconSize
+ name: "down"
+ visible: !centerLayout.atYEnd
+ }
}
}
+
diff --git a/nymea-app/ui/mainviews/energy/ConsumersPieChartPage.qml b/nymea-app/ui/mainviews/energy/ConsumersPieChartPage.qml
new file mode 100644
index 00000000..f2b9889f
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/ConsumersPieChartPage.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ property alias energyManager: consumersPieChart.energyManager
+ property alias consumers: consumersPieChart.consumers
+
+ header: NymeaHeader {
+ text: qsTr("Consumers balance")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ ConsumersPieChart {
+ id: consumersPieChart
+ anchors.fill: parent
+ titleVisible: false
+ }
+}
diff --git a/nymea-app/ui/mainviews/energy/CurrentConsumptionBalancePieChart.qml b/nymea-app/ui/mainviews/energy/CurrentConsumptionBalancePieChart.qml
index 80a4440c..0eae0b52 100644
--- a/nymea-app/ui/mainviews/energy/CurrentConsumptionBalancePieChart.qml
+++ b/nymea-app/ui/mainviews/energy/CurrentConsumptionBalancePieChart.qml
@@ -10,7 +10,7 @@ ChartView {
id: consumptionPieChart
backgroundColor: "transparent"
animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
- title: qsTr("My energy mix")
+ title: qsTr("My energy consumption")
titleColor: Style.foregroundColor
legend.visible: false
diff --git a/nymea-app/ui/mainviews/energy/CurrentPowerBalancePage.qml b/nymea-app/ui/mainviews/energy/CurrentPowerBalancePage.qml
new file mode 100644
index 00000000..768e5cba
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/CurrentPowerBalancePage.qml
@@ -0,0 +1,41 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ property EnergyManager energyManager: null
+ property ThingsProxy consumers: null
+ property ThingsProxy producers: null
+
+ header: NymeaHeader {
+ text: qsTr("My energy mix")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ GridLayout {
+ anchors.fill: parent
+ columns: app.landscape ? 2 : 1
+
+ CurrentConsumptionBalancePieChart {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ energyManager: root.energyManager
+ visible: root.producers.count > 0
+ animationsEnabled: Qt.application.active
+ }
+ CurrentProductionBalancePieChart {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ energyManager: root.energyManager
+ visible: root.producers.count > 0
+ animationsEnabled: Qt.application.active
+ }
+ }
+
+
+}
diff --git a/nymea-app/ui/mainviews/energy/CurrentPowerBalancePieChart.qml b/nymea-app/ui/mainviews/energy/CurrentPowerBalancePieChart.qml
index df7a5224..70fb1e20 100644
--- a/nymea-app/ui/mainviews/energy/CurrentPowerBalancePieChart.qml
+++ b/nymea-app/ui/mainviews/energy/CurrentPowerBalancePieChart.qml
@@ -19,6 +19,20 @@ Item {
readonly property double fromProduction: energyManager.currentPowerConsumption - fromGrid - fromStorage
readonly property double toGrid: Math.max(0, - energyManager.currentPowerAcquisition)
+
+ Label {
+ id: titleLabel
+ anchors { left: parent.left; top: parent.top; right: parent.right; margins: Style.smallMargins }
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("My energy mix")
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ pageStack.push(Qt.resolvedUrl("CurrentPowerBalancePage.qml"), {energyManager: root.energyManager})
+ }
+ }
+ }
+
QtObject {
id: d
function formatValue(value) {
@@ -37,11 +51,11 @@ Item {
property int chartSize: width / 2.5
property point acquisitionPos: Qt.point(chartSize/2 + Style.margins, chartSize/2 + Style.margins)
- property point productionPos: Qt.point(root.width - (chartSize/2 + Style.margins), chartSize/2 + Style.margins)
- property point storagePos: Qt.point(chartSize/2 + Style.margins, root.height - (chartSize/2 + Style.margins))
+ property point productionPos: Qt.point(contentContainer.width - (chartSize/2 + Style.margins), chartSize/2 + Style.margins)
+ property point storagePos: Qt.point(chartSize/2 + Style.margins, contentContainer.height - (chartSize/2 + Style.margins))
property point consumptionPos: batteries.count > 0 || producers.count === 0
- ? Qt.point(root.width - (chartSize/2 + Style.margins), root.height - (chartSize/2 + Style.margins))
- : Qt.point(root.width / 2, root.height - (chartSize/2 + Style.margins))
+ ? Qt.point(contentContainer.width - (chartSize/2 + Style.margins), contentContainer.height - (chartSize/2 + Style.margins))
+ : Qt.point(contentContainer.width / 2, contentContainer.height - (chartSize/2 + Style.margins))
}
ThingsProxy {
@@ -66,805 +80,431 @@ Item {
duration: 5000
}
- Canvas {
- id: canvas
- anchors.fill: parent
+ Item {
+ id: contentContainer
+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; top: titleLabel.bottom}
- renderTarget: Canvas.FramebufferObject
- renderStrategy: Canvas.Cooperative
+ Canvas {
+ id: canvas
+ anchors.fill: parent
- onPaint: {
- var ctx = getContext("2d");
+ renderTarget: Canvas.FramebufferObject
+ renderStrategy: Canvas.Cooperative
- var solarPos = Qt.point(d.productionPos.x - width / 2, d.productionPos.y - height / 2)
- var storagePos = Qt.point(d.storagePos.x - width / 2, d.storagePos.y - width / 2)
- var consumptionPos = Qt.point(d.consumptionPos.x - width / 2, d.consumptionPos.y - height / 2)
- var gridPos = Qt.point(d.acquisitionPos.x - width / 2, d.acquisitionPos.y - height / 2)
+ onPaint: {
+ var ctx = getContext("2d");
- ctx.save();
- ctx.reset()
+ var solarPos = Qt.point(d.productionPos.x - width / 2, d.productionPos.y - height / 2)
+ var storagePos = Qt.point(d.storagePos.x - width / 2, d.storagePos.y - width / 2)
+ var consumptionPos = Qt.point(d.consumptionPos.x - width / 2, d.consumptionPos.y - height / 2)
+ var gridPos = Qt.point(d.acquisitionPos.x - width / 2, d.acquisitionPos.y - height / 2)
- ctx.translate(width / 2, height / 2);
+ ctx.save();
+ ctx.reset()
- ctx.strokeStyle = Style.foregroundColor
- ctx.fillStyle = Style.foregroundColor
- ctx.lineWidth = 2
+ ctx.translate(width / 2, height / 2);
- var biggest = Math.max(
- Math.abs(energyManager.currentPowerAcquisition),
- Math.abs(energyManager.currentPowerConsumption),
- Math.abs(energyManager.currentPowerProduction),
- Math.abs(energyManager.currentPowerStorage)
- )
- var size
+ ctx.strokeStyle = Style.foregroundColor
+ ctx.fillStyle = Style.foregroundColor
+ ctx.lineWidth = 2
+
+ var biggest = Math.max(
+ Math.abs(energyManager.currentPowerAcquisition),
+ Math.abs(energyManager.currentPowerConsumption),
+ Math.abs(energyManager.currentPowerProduction),
+ Math.abs(energyManager.currentPowerStorage)
+ )
+ var size
- if (root.toGrid > 0) {
- size = root.toGrid / biggest
- drawDottedCurve(ctx, solarPos, gridPos, size, Style.yellow)
- }
+ if (root.toGrid > 0) {
+ size = root.toGrid / biggest
+ drawDottedCurve(ctx, solarPos, gridPos, size, Style.yellow)
+ }
- if (energyManager.currentPowerProduction < 0 && root.fromProduction) {
- size = root.fromProduction / biggest
- drawDottedCurve(ctx, solarPos, consumptionPos, size, Style.green)
- }
+ if (energyManager.currentPowerProduction < 0 && root.fromProduction) {
+ size = root.fromProduction / biggest
+ drawDottedCurve(ctx, solarPos, consumptionPos, size, Style.green)
+ }
- if (batteries.count > 0) {
- if (energyManager.currentPowerStorage > 0) {
- if (energyManager.currentPowerProduction < 0) {
+ if (batteries.count > 0) {
+ if (energyManager.currentPowerStorage > 0) {
+ if (energyManager.currentPowerProduction < 0) {
+ size = Math.abs(energyManager.currentPowerStorage) / biggest
+ drawDottedCurve(ctx, solarPos, storagePos, size, Style.purple)
+ } else {
+ size = Math.abs(energyManager.currentPowerStorage) / biggest
+ drawDottedCurve(ctx, gridPos, storagePos, size, Style.purple)
+ }
+ }
+
+ if (energyManager.currentPowerStorage < 0) {
size = Math.abs(energyManager.currentPowerStorage) / biggest
- drawDottedCurve(ctx, solarPos, storagePos, size, Style.purple)
- } else {
- size = Math.abs(energyManager.currentPowerStorage) / biggest
- drawDottedCurve(ctx, gridPos, storagePos, size, Style.purple)
+ drawDottedCurve(ctx, storagePos, consumptionPos, size, Style.orange)
}
}
- if (energyManager.currentPowerStorage < 0) {
- size = Math.abs(energyManager.currentPowerStorage) / biggest
- drawDottedCurve(ctx, storagePos, consumptionPos, size, Style.orange)
+ if (energyManager.currentPowerAcquisition > 0) {
+ size = Math.abs(energyManager.currentPowerAcquisition) / biggest
+ drawDottedCurve(ctx, gridPos, consumptionPos, size, Style.red)
+ }
+
+ ctx.restore();
+ }
+
+ function bezierCurvePoint(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, t) {
+ var x = Math.pow(1-t, 3)*p0x + 3*Math.pow(1-t, 2)*t*p1x + 3*(1-t)*Math.pow(t, 2)*p2x + Math.pow(t, 3)*p3x;
+ var y = Math.pow(1-t, 3)*p0y + 3*Math.pow(1-t, 2)*t*p1y + 3*(1-t)*Math.pow(t, 2)*p2y + Math.pow(t, 3)*p3y;
+ return Qt.point(x, y)
+ }
+
+ function circlePoint(center, radius, angle) {
+ var x = center.x + radius * Math.cos(angle * 2 * Math.PI / 360)
+ var y = center.y + radius * Math.sin(angle * 2 * Math.PI / 360)
+ return Qt.point(x, y)
+ }
+
+ function drawDottedCurve(ctx, start, end, size, color) {
+ var c1 = getControlPoint(start)
+ var c2 = getControlPoint(end)
+ ctx.fillStyle = color
+ ctx.strokeStyle = color
+ var count = 10;
+ for (var i = 1; i <= count; i++) {
+ var offset = 1 / count;
+ var progress = d.progress + i * offset
+ if (progress > 1)
+ progress -= 1
+ var point = bezierCurvePoint(start.x, start.y, c1.x, c1.y, c2.x, c2.y, end.x, end.y, progress)
+ // print("painting", d.progress, point.x, point.y)
+ ctx.beginPath();
+ ctx.arc(point.x, point.y, Math.max(1, size * 5), 0, 2 *Math.PI)
+ ctx.stroke();
+ ctx.fill();
+ ctx.closePath();
+
+ }
+
+ }
+
+ function getControlPoint(point) {
+ return Qt.point(point.x * .1, point.y * .1)
+ }
+
+ }
+
+ Item {
+ id: acquisitionItem
+ x: d.acquisitionPos.x - width / 2
+ y: d.acquisitionPos.y - height / 2
+ width: d.chartSize
+ height: d.chartSize
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: acquisitionChart.plotArea.width
+ height: acquisitionChart.plotArea.height
+ color: Style.backgroundColor
+ radius: width / 2
+ }
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ width: acquisitionChart.plotArea.width * 0.8
+ ColorIcon {
+ Layout.alignment: Qt.AlignHCenter
+ size: Style.bigIconSize
+ // color: Style.red
+ name: "/ui/images/power-grid.svg"
+ }
+ Label {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ text: d.formatValue(Math.abs(energyManager.currentPowerAcquisition))
+ // color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.yellow
}
}
- if (energyManager.currentPowerAcquisition > 0) {
- size = Math.abs(energyManager.currentPowerAcquisition) / biggest
- drawDottedCurve(ctx, gridPos, consumptionPos, size, Style.red)
+
+ ChartView {
+ id: acquisitionChart
+ anchors.fill: parent
+ legend.visible: false
+ margins { left: 0; top: 0; right: 0; bottom: 0 }
+ backgroundColor: "transparent"
+ animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
+
+ PieSeries {
+ size: 1
+ holeSize: 0.8
+
+ PieSlice {
+ color: Style.red
+ borderColor: color
+ borderWidth: 0
+ value: root.fromGrid
+ }
+ PieSlice {
+ color: Style.yellow
+ borderColor: color
+ borderWidth: 0
+ value: root.toGrid
+ }
+ PieSlice {
+ color: Style.tooltipBackgroundColor
+ borderColor: color
+ borderWidth: 0
+ value: energyManager.currentPowerAcquisition == 0 ? 1 : 0
+ }
+ }
+ }
+ }
+
+
+ Item {
+ id: productionItem
+ x: d.productionPos.x - width / 2
+ y: d.productionPos.y - height / 2
+ width: d.chartSize
+ height: d.chartSize
+ visible: producers.count > 0
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: productionChart.plotArea.width
+ height: productionChart.plotArea.height
+ color: Style.backgroundColor
+ radius: width / 2
}
- ctx.restore();
- }
-
- function bezierCurvePoint(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, t) {
- var x = Math.pow(1-t, 3)*p0x + 3*Math.pow(1-t, 2)*t*p1x + 3*(1-t)*Math.pow(t, 2)*p2x + Math.pow(t, 3)*p3x;
- var y = Math.pow(1-t, 3)*p0y + 3*Math.pow(1-t, 2)*t*p1y + 3*(1-t)*Math.pow(t, 2)*p2y + Math.pow(t, 3)*p3y;
- return Qt.point(x, y)
- }
-
- function circlePoint(center, radius, angle) {
- var x = center.x + radius * Math.cos(angle * 2 * Math.PI / 360)
- var y = center.y + radius * Math.sin(angle * 2 * Math.PI / 360)
- return Qt.point(x, y)
- }
-
- function drawDottedCurve(ctx, start, end, size, color) {
- var c1 = getControlPoint(start)
- var c2 = getControlPoint(end)
- ctx.fillStyle = color
- ctx.strokeStyle = color
- var count = 10;
- for (var i = 1; i <= count; i++) {
- var offset = 1 / count;
- var progress = d.progress + i * offset
- if (progress > 1)
- progress -= 1
- var point = bezierCurvePoint(start.x, start.y, c1.x, c1.y, c2.x, c2.y, end.x, end.y, progress)
-// print("painting", d.progress, point.x, point.y)
- ctx.beginPath();
- ctx.arc(point.x, point.y, Math.max(1, size * 5), 0, 2 *Math.PI)
- ctx.stroke();
- ctx.fill();
- ctx.closePath();
-
+ ColumnLayout {
+ anchors.centerIn: parent
+ width: productionChart.plotArea.width * 0.8
+ ColorIcon {
+ Layout.alignment: Qt.AlignHCenter
+ size: Style.bigIconSize
+ // color: Style.yellow
+ name: "/ui/images/weathericons/weather-clear-day.svg"
+ }
+ Label {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ text: d.formatValue(Math.abs(energyManager.currentPowerProduction))
+ // color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.green
+ }
}
- }
- function getControlPoint(point) {
- return Qt.point(point.x * .1, point.y * .1)
- }
+ ChartView {
+ id: productionChart
+ anchors.fill: parent
+ legend.visible: false
+ backgroundColor: "transparent"
+ margins { left: 0; top: 0; right: 0; bottom: 0 }
+ animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
- }
+ PieSeries {
+ size: 1
+ holeSize: 0.8
- Item {
- id: acquisitionItem
- x: d.acquisitionPos.x - width / 2
- y: d.acquisitionPos.y - height / 2
- width: d.chartSize
- height: d.chartSize
-
- Rectangle {
- anchors.centerIn: parent
- width: acquisitionChart.plotArea.width
- height: acquisitionChart.plotArea.height
- color: Style.backgroundColor
- radius: width / 2
- }
-
- ColumnLayout {
- anchors.centerIn: parent
- width: acquisitionChart.plotArea.width * 0.8
- ColorIcon {
- Layout.alignment: Qt.AlignHCenter
- size: Style.bigIconSize
- // color: Style.red
- name: "/ui/images/power-grid.svg"
+ PieSlice {
+ color: Style.green
+ borderColor: color
+ borderWidth: 0
+ value: root.fromProduction
+ }
+ PieSlice {
+ color: Style.purple
+ borderColor: color
+ borderWidth: 0
+ value: root.toStorage
+ }
+ PieSlice {
+ color: Style.yellow
+ borderColor: color
+ borderWidth: 0
+ value: root.toGrid
+ }
+ PieSlice {
+ color: Style.tooltipBackgroundColor
+ borderColor: color
+ borderWidth: 0
+ value: energyManager.currentPowerProduction == 0 ? 1 : 0
+ }
+ }
}
+ }
+
+ Item {
+ id: consumptionItem
+ x: d.consumptionPos.x - width / 2
+ y: d.consumptionPos.y - height / 2
+ width: d.chartSize
+ height: d.chartSize
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: consumptionChart.plotArea.width
+ height: consumptionChart.plotArea.height
+ color: Style.backgroundColor
+ radius: width / 2
+ }
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ width: consumptionChart.plotArea.width * 0.8
+ ColorIcon {
+ Layout.alignment: Qt.AlignHCenter
+ size: Style.bigIconSize
+ // color: Style.blue
+ name: "/ui/images/powersocket.svg"
+ }
+ Label {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ text: d.formatValue(energyManager.currentPowerConsumption)
+ // color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.green
+ }
+ }
+
+ ChartView {
+ id: consumptionChart
+ anchors.fill: parent
+ margins { left: 0; top: 0; right: 0; bottom: 0 }
+ legend.visible: false
+ backgroundColor: "transparent"
+ animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
+
+ PieSeries {
+ size: 1
+ holeSize: 0.8
+
+ PieSlice {
+ color: Style.green
+ borderColor: color
+ borderWidth: 0
+ value: root.fromProduction
+ }
+ PieSlice {
+ color: Style.red
+ borderColor: color
+ borderWidth: 0
+ value: root.fromGrid
+ }
+ PieSlice {
+ color: Style.orange
+ borderColor: color
+ borderWidth: 0
+ value: root.fromStorage
+ }
+ }
+ }
+ }
+
+
+ Item {
+ id: batteryItem
+ x: d.storagePos.x - width / 2
+ y: d.storagePos.y - height / 2
+ width: d.chartSize
+ height: d.chartSize
+ visible: batteries.count > 0
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: batteryChart.plotArea.width
+ height: batteryChart.plotArea.height
+ color: Style.backgroundColor
+ radius: width / 2
+ }
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ width: productionChart.plotArea.width * 0.8
+ ColorIcon {
+ Layout.alignment: Qt.AlignHCenter
+ size: Style.bigIconSize
+ // color: Style.purple
+ name: "/ui/images/battery/battery-" + NymeaUtils.pad(Math.round(batteryChart.averageLevel / 10) * 10, 3) + ".svg"
+ }
+ Label {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ text: d.formatValue(Math.abs(energyManager.currentPowerStorage))
+ // color: energyManager.currentPowerStorage >= 0 ? Style.green : Style.red
+ }
+ }
+
Label {
- Layout.fillWidth: true
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: batteryChart.y + batteryChart.plotArea.height * .2
horizontalAlignment: Text.AlignHCenter
- text: d.formatValue(Math.abs(energyManager.currentPowerAcquisition))
-// color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.yellow
- }
- }
-
-
- ChartView {
- id: acquisitionChart
- anchors.fill: parent
- legend.visible: false
- margins { left: 0; top: 0; right: 0; bottom: 0 }
- backgroundColor: "transparent"
- animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-
- PieSeries {
- size: 1
- holeSize: 0.8
-
- PieSlice {
- color: Style.red
- borderColor: color
- borderWidth: 0
- value: root.fromGrid
- }
- PieSlice {
- color: Style.yellow
- borderColor: color
- borderWidth: 0
- value: root.toGrid
- }
- PieSlice {
- color: Style.tooltipBackgroundColor
- borderColor: color
- borderWidth: 0
- value: energyManager.currentPowerAcquisition == 0 ? 1 : 0
- }
- }
- }
- }
-
-
- Item {
- id: productionItem
- x: d.productionPos.x - width / 2
- y: d.productionPos.y - height / 2
- width: d.chartSize
- height: d.chartSize
- visible: producers.count > 0
-
- Rectangle {
- anchors.centerIn: parent
- width: productionChart.plotArea.width
- height: productionChart.plotArea.height
- color: Style.backgroundColor
- radius: width / 2
- }
-
- ColumnLayout {
- anchors.centerIn: parent
- width: productionChart.plotArea.width * 0.8
- ColorIcon {
- Layout.alignment: Qt.AlignHCenter
- size: Style.bigIconSize
- // color: Style.yellow
- name: "/ui/images/weathericons/weather-clear-day.svg"
- }
- Label {
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- text: d.formatValue(Math.abs(energyManager.currentPowerProduction))
- // color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.green
- }
- }
-
-
- ChartView {
- id: productionChart
- anchors.fill: parent
- legend.visible: false
- backgroundColor: "transparent"
- margins { left: 0; top: 0; right: 0; bottom: 0 }
- animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-
- PieSeries {
- size: 1
- holeSize: 0.8
-
- PieSlice {
- color: Style.green
- borderColor: color
- borderWidth: 0
- value: root.fromProduction
- }
- PieSlice {
- color: Style.purple
- borderColor: color
- borderWidth: 0
- value: root.toStorage
- }
- PieSlice {
- color: Style.yellow
- borderColor: color
- borderWidth: 0
- value: root.toGrid
- }
- PieSlice {
- color: Style.tooltipBackgroundColor
- borderColor: color
- borderWidth: 0
- value: energyManager.currentPowerProduction == 0 ? 1 : 0
- }
- }
- }
- }
-
- Item {
- id: consumptionItem
- x: d.consumptionPos.x - width / 2
- y: d.consumptionPos.y - height / 2
- width: d.chartSize
- height: d.chartSize
-
- Rectangle {
- anchors.centerIn: parent
- width: consumptionChart.plotArea.width
- height: consumptionChart.plotArea.height
- color: Style.backgroundColor
- radius: width / 2
- }
-
- ColumnLayout {
- anchors.centerIn: parent
- width: consumptionChart.plotArea.width * 0.8
- ColorIcon {
- Layout.alignment: Qt.AlignHCenter
- size: Style.bigIconSize
- // color: Style.blue
- name: "/ui/images/powersocket.svg"
- }
- Label {
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- text: d.formatValue(energyManager.currentPowerConsumption)
- // color: energyManager.currentPowerAcquisition >= 0 ? Style.red : Style.green
- }
- }
-
- ChartView {
- id: consumptionChart
- anchors.fill: parent
- margins { left: 0; top: 0; right: 0; bottom: 0 }
- legend.visible: false
- backgroundColor: "transparent"
- animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-
- PieSeries {
- size: 1
- holeSize: 0.8
-
- PieSlice {
- color: Style.green
- borderColor: color
- borderWidth: 0
- value: root.fromProduction
- }
- PieSlice {
- color: Style.red
- borderColor: color
- borderWidth: 0
- value: root.fromGrid
- }
- PieSlice {
- color: Style.orange
- borderColor: color
- borderWidth: 0
- value: root.fromStorage
- }
- }
- }
- }
-
-
- Item {
- id: batteryItem
- x: d.storagePos.x - width / 2
- y: d.storagePos.y - height / 2
- width: d.chartSize
- height: d.chartSize
- visible: batteries.count > 0
-
- Rectangle {
- anchors.centerIn: parent
- width: batteryChart.plotArea.width
- height: batteryChart.plotArea.height
- color: Style.backgroundColor
- radius: width / 2
- }
-
- ColumnLayout {
- anchors.centerIn: parent
- width: productionChart.plotArea.width * 0.8
- ColorIcon {
- Layout.alignment: Qt.AlignHCenter
- size: Style.bigIconSize
- // color: Style.purple
- name: "/ui/images/battery/battery-" + NymeaUtils.pad(Math.round(batteryChart.averageLevel / 10) * 10, 3) + ".svg"
- }
- Label {
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- text: d.formatValue(Math.abs(energyManager.currentPowerStorage))
+ font: Style.smallFont
+ text: batteryChart.averageLevel + "%"
// color: energyManager.currentPowerStorage >= 0 ? Style.green : Style.red
}
- }
- Label {
- anchors.horizontalCenter: parent.horizontalCenter
- y: batteryChart.y + batteryChart.plotArea.height * .2
- horizontalAlignment: Text.AlignHCenter
- font: Style.smallFont
- text: batteryChart.averageLevel + "%"
-// color: energyManager.currentPowerStorage >= 0 ? Style.green : Style.red
- }
+ ChartView {
+ id: batteryChart
+ anchors.fill: parent
+ margins { left: 0; top: 0; right: 0; bottom: 0 }
+ legend.visible: false
+ backgroundColor: "transparent"
+ animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
- ChartView {
- id: batteryChart
- anchors.fill: parent
- margins { left: 0; top: 0; right: 0; bottom: 0 }
- legend.visible: false
- backgroundColor: "transparent"
- animationOptions: root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-
- property double totalCapacity: {
- var totalCapacity = 0;
- for (var i = 0; i < batteriesRepeater.count; i++) {
- totalCapacity += batteriesRepeater.itemAt(i).capacityState.value
+ property double totalCapacity: {
+ var totalCapacity = 0;
+ for (var i = 0; i < batteriesRepeater.count; i++) {
+ totalCapacity += batteriesRepeater.itemAt(i).capacityState.value
+ }
+ return totalCapacity;
}
- return totalCapacity;
- }
- property double averageLevel: {
- if (batteriesRepeater.count == 0) {
- return 0;
+ property double averageLevel: {
+ if (batteriesRepeater.count == 0) {
+ return 0;
+ }
+
+ var averageLevel = 0;
+ for (var i = 0; i < batteriesRepeater.count; i++) {
+ averageLevel += batteriesRepeater.itemAt(i).batteryLevelState.value
+ }
+ averageLevel /= batteriesRepeater.count
+ return averageLevel;
}
- var averageLevel = 0;
- for (var i = 0; i < batteriesRepeater.count; i++) {
- averageLevel += batteriesRepeater.itemAt(i).batteryLevelState.value
+ Repeater {
+ id: batteriesRepeater
+ model: batteries
+ delegate: Item {
+ property Thing thing: batteries.get(index)
+ property State batteryLevelState: thing.stateByName("batteryLevel")
+ property State capacityState: thing.stateByName("capacity")
+ }
}
- averageLevel /= batteriesRepeater.count
- return averageLevel;
- }
- Repeater {
- id: batteriesRepeater
- model: batteries
- delegate: Item {
- property Thing thing: batteries.get(index)
- property State batteryLevelState: thing.stateByName("batteryLevel")
- property State capacityState: thing.stateByName("capacity")
- }
- }
+ PieSeries {
+ id: batterySeries
+ size: 1
+ holeSize: 0.8
- PieSeries {
- id: batterySeries
- size: 1
- holeSize: 0.8
-
- PieSlice {
- color: energyManager.currentPowerStorage == 0
- ? Style.foregroundColor
- : root.toStorage > 0
- ? Style.purple
- : Style.orange
- borderColor: color
- borderWidth: 0
- value: batteryChart.averageLevel
- }
- PieSlice {
- color: Style.tooltipBackgroundColor
- borderColor: color
- borderWidth: 0
- value: 100 - batteryChart.averageLevel
+ PieSlice {
+ color: energyManager.currentPowerStorage == 0
+ ? Style.foregroundColor
+ : root.toStorage > 0
+ ? Style.purple
+ : Style.orange
+ borderColor: color
+ borderWidth: 0
+ value: batteryChart.averageLevel
+ }
+ PieSlice {
+ color: Style.tooltipBackgroundColor
+ borderColor: color
+ borderWidth: 0
+ value: 100 - batteryChart.averageLevel
+ }
}
}
}
}
-
}
-
-//ChartView {
-// id: consumptionPieChart
-// backgroundColor: "transparent"
-// animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
-// title: qsTr("My energy mix")
-// titleColor: Style.foregroundColor
-// legend.visible: false
-
-// margins.left: 0
-// margins.right: 0
-// margins.bottom: 0
-// margins.top: 0
-
-// property bool animationsEnabled: true
-// property EnergyManager energyManager: null
-
-// ThingsProxy {
-// id: batteries
-// engine: _engine
-// shownInterfaces: ["energystorage"]
-// }
-
-// PieSeries {
-// id: consumptionBalanceSeries
-// size: 0.88
-// holeSize: 0.7
-
-// property double fromGrid: Math.max(0, energyManager.currentPowerAcquisition)
-// property double fromStorage: -Math.min(0, energyManager.currentPowerStorage)
-// property double toStorage: -Math.min(0, -energyManager.currentPowerStorage)
-// property double fromProduction: energyManager.currentPowerConsumption - fromGrid - fromStorage
-// property double toGrid: Math.max(0, - energyManager.currentPowerAcquisition)
-
-// PieSlice {
-// color: Style.red
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.fromGrid
-// }
-// PieSlice {
-// color: Style.green
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.fromProduction
-// }
-// PieSlice {
-// color: Style.purple
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.fromStorage
-// }
-// PieSlice {
-// color: Style.yellow
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.toGrid
-// }
-// PieSlice {
-// color: Style.orange
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.toStorage
-// }
-
-// PieSlice {
-// color: Style.tooltipBackgroundColor
-// borderColor: color
-// borderWidth: 0
-// value: consumptionBalanceSeries.fromGrid == 0 && consumptionBalanceSeries.fromProduction == 0 && consumptionBalanceSeries.fromStorage == 0 ? 1 : 0
-// }
-// }
-
-// Item {
-// id: centerItem
-
-// x: consumptionPieChart.plotArea.x + (consumptionPieChart.plotArea.width - width) / 2
-// y: consumptionPieChart.plotArea.y + (consumptionPieChart.plotArea.height - height) / 2
-// width: consumptionPieChart.plotArea.width * 0.65
-// height: width
-
-//// Rectangle {
-//// anchors.fill: parent
-//// color: "white"
-//// }
-
-// QtObject {
-// id: d
-// property double progress: 0
-// onProgressChanged: canvas.requestPaint()
-// }
-
-// NumberAnimation {
-// id: progressAnimation
-// target: d
-// property: "progress"
-// from: 0
-// to: 1
-// running: true
-// loops: Animation.Infinite
-// duration: 5000
-// }
-
-
-// Canvas {
-// id: canvas
-// anchors.fill: parent
-
-// property int itemCount: batteries.count > 0 ? 4 : 3
-
-// ColorIcon {
-// property var point: canvas.circlePoint(Qt.point(canvas.width / 2, canvas.height / 2), canvas.height / 2, -90)
-// x: point.x - width / 2
-// y: point.y - height / 2
-// name: "weathericons/weather-clear-day"
-// }
-// ColorIcon {
-// property var point: canvas.circlePoint(Qt.point(canvas.width / 2, canvas.height / 2), canvas.height / 2, -90 + 360 / canvas.itemCount)
-// x: point.x - width / 2
-// y: point.y - height / 2
-// name: "battery/battery-080"
-// visible: batteries.count > 0
-// }
-// ColorIcon {
-// property var point: canvas.circlePoint(Qt.point(canvas.width / 2, canvas.height / 2), canvas.height / 2, -90 + 360 / canvas.itemCount * (batteries.count > 0 ? 2 : 1))
-// x: point.x - width / 2
-// y: point.y - height / 2
-// name: "things"
-// }
-// ColorIcon {
-// property var point: canvas.circlePoint(Qt.point(canvas.width / 2, canvas.height / 2), canvas.height / 2, -90 + 360 / canvas.itemCount * (batteries.count > 0 ? 3 : 2))
-// x: point.x - width / 2
-// y: point.y - height / 2
-// name: "energy"
-// }
-
-// onPaint: {
-// var ctx = getContext("2d");
-
-// var solarPos = circlePoint(Qt.point(0, 0), height / 2, -90)
-// var storagePos = circlePoint(Qt.point(0, 0), height / 2, -90 / 360 * itemCount * 1)
-// var consumptionPos = circlePoint(Qt.point(0, 0), height / 2, -90 + 360 / itemCount * (batteries.count > 0 ? 2 : 1))
-// var gridPos = circlePoint(Qt.point(0, 0), height / 2, -90 + 360 / itemCount * (batteries.count > 0 ? 3 : 2))
-
-// ctx.save();
-// ctx.reset()
-
-// ctx.translate(width / 2, height / 2);
-
-// ctx.strokeStyle = Style.foregroundColor
-// ctx.fillStyle = Style.foregroundColor
-// ctx.lineWidth = 2
-
-//// ctx.beginPath();
-//// ctx.moveTo(0, -height / 2);
-//// ctx.bezierCurveTo(0, -height / 10, -width / 10, 0, -width / 2, 0)
-//// ctx.stroke();
-//// ctx.closePath();
-
-//// ctx.beginPath();
-//// ctx.moveTo(-width / 2, 0);
-//// ctx.bezierCurveTo(-width / 10, 0, 0, height / 10, 0, height / 2)
-//// ctx.stroke();
-//// ctx.closePath();
-
-//// ctx.beginPath();
-//// ctx.moveTo(0, height / 2);
-//// ctx.bezierCurveTo(0, height / 10, width / 10, 0, width / 2, 0)
-//// ctx.stroke();
-//// ctx.closePath();
-
-//// ctx.beginPath();
-//// ctx.moveTo(width / 2, 0);
-//// ctx.bezierCurveTo(width / 10, 0, 0, -height / 10, 0, -height / 2)
-//// ctx.stroke();
-//// ctx.closePath();
-
-// var size = Math.abs(energyManager.currentPowerAcquisition) / Math.abs(energyManager.currentPowerProduction)
-// drawDottedCurve(ctx, solarPos, gridPos, size)
-
-// size = Math.abs(energyManager.currentPowerConsumption) / Math.abs(energyManager.currentPowerProduction)
-// drawDottedCurve(ctx, solarPos, consumptionPos, size)
-
-// if (batteries.count > 0) {
-// size = Math.abs(energyManager.currentPowerStorage) / Math.abs(energyManager.currentPowerProduction)
-// drawDottedCurve(ctx, solarPos, storagePos, size)
-
-// if (energyManager.currentPowerStorage < 0) {
-// size = Math.abs(energyManager.currentPowerStorage) / Math.abs(energyManager.currentPowerConsumption)
-// drawDottedCurve(ctx, storagePos, consumptionPos, size)
-// }
-// }
-
-// if (energyManager.currentPowerAcquisition > 0) {
-// size = Math.abs(energyManager.currentPowerAcquisition) / Math.abs(energyManager.currentPowerConsumption)
-// drawDottedCurve(ctx, gridPos, consumptionPos, size)
-// }
-
-//// var count = 5;
-//// for (var i = 1; i <= count; i++) {
-//// var offset = 1 / count;
-//// var progress = d.progress + i * offset
-//// if (progress > 1)
-//// progress -= 1
-//// var point = bezierCurvePoint(width / 2, 0, width / 10, 0, 0, -height / 10, 0, -height / 2, progress)
-//// // print("painting", d.progress, point.x, point.y)
-//// ctx.beginPath();
-//// ctx.arc(point.x, point.y, 4, 0, 2 *Math.PI)
-//// ctx.stroke();
-//// ctx.closePath();
-
-//// }
-
-
-// ctx.restore();
-// }
-
-// function bezierCurvePoint(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, t) {
-// var x = Math.pow(1-t, 3)*p0x + 3*Math.pow(1-t, 2)*t*p1x + 3*(1-t)*Math.pow(t, 2)*p2x + Math.pow(t, 3)*p3x;
-// var y = Math.pow(1-t, 3)*p0y + 3*Math.pow(1-t, 2)*t*p1y + 3*(1-t)*Math.pow(t, 2)*p2y + Math.pow(t, 3)*p3y;
-// return Qt.point(x, y)
-// }
-
-// function circlePoint(center, radius, angle) {
-// var x = center.x + radius * Math.cos(angle * 2 * Math.PI / 360)
-// var y = center.y + radius * Math.sin(angle * 2 * Math.PI / 360)
-// return Qt.point(x, y)
-// }
-
-// function drawDottedCurve(ctx, start, end, size) {
-// var c1 = getControlPoint(start)
-// var c2 = getControlPoint(end)
-// var count = 10;
-// for (var i = 1; i <= count; i++) {
-// var offset = 1 / count;
-// var progress = d.progress + i * offset
-// if (progress > 1)
-// progress -= 1
-// var point = bezierCurvePoint(start.x, start.y, c1.x, c1.y, c2.x, c2.y, end.x, end.y, progress)
-// // print("painting", d.progress, point.x, point.y)
-// ctx.beginPath();
-// ctx.arc(point.x, point.y, size * 5, 0, 2 *Math.PI)
-// ctx.stroke();
-// ctx.fill();
-// ctx.closePath();
-
-// }
-
-// }
-
-// function getControlPoint(point) {
-// return Qt.point(point.x * .1, point.y * .1)
-// }
-
-// }
-
-// }
-
-
-// Column {
-// id: centerLayout
-// x: consumptionPieChart.plotArea.x + (consumptionPieChart.plotArea.width - width) / 2
-// y: consumptionPieChart.plotArea.y + (consumptionPieChart.plotArea.height - height) / 2
-// width: consumptionPieChart.plotArea.width * 0.65
-//// height: consumptionPieChart.plotArea.height * 0.65
-// height: childrenRect.height
-// spacing: Style.smallMargins
-
-// visible: false
-
-// ColumnLayout {
-// width: parent.width
-// spacing: 0
-// Label {
-// text: qsTr("Consumption")
-// font: Style.smallFont
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// }
-
-// Label {
-// text: "%1 %2"
-// .arg((energyManager.currentPowerConsumption / (energyManager.currentPowerConsumption > 1000 ? 1000 : 1)).toFixed(1))
-// .arg(energyManager.currentPowerConsumption > 1000 ? "kW" : "W")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-//// font: Style.smallFont
-// color: Style.blue
-// }
-// }
-// ColumnLayout {
-// width: parent.width
-// spacing: 0
-// Label {
-// text: qsTr("Production")
-// font: Style.smallFont
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// }
-
-// Label {
-// property double absValue: Math.abs(energyManager.currentPowerProduction)
-// text: "%1 %2"
-// .arg((absValue / (absValue > 1000 ? 1000 : 1)).toFixed(1))
-// .arg(absValue > 1000 ? "kW" : "W")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-//// font: Style.bigFont
-// color: Style.yellow
-
-// }
-// }
-
-
-// ColumnLayout {
-// width: parent.width
-// spacing: 0
-// Label {
-// text: qsTr("From grid")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.extraSmallFont
-// }
-// Label {
-// property double absValue: consumptionBalanceSeries.fromGrid
-// color: Style.red
-// text: "%1 %2"
-// .arg((absValue / (absValue > 1000 ? 1000 : 1)).toFixed(1))
-// .arg(absValue > 1000 ? "kW" : "W")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.smallFont
-// }
-// }
-
-
-// ColumnLayout {
-// width: parent.width
-// spacing: 0
-// Label {
-// text: qsTr("From self production")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.extraSmallFont
-// }
-// Label {
-// color: Style.green
-// property double absValue: consumptionBalanceSeries.fromProduction
-// text: "%1 %2".arg((absValue / (absValue > 1000 ? 1000 : 1)).toFixed(1))
-// .arg(absValue > 1000 ? "kW" : "W")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.smallFont
-// }
-// }
-// ColumnLayout {
-// width: parent.width
-// spacing: 0
-// visible: batteries.count > 0
-// Label {
-// text: energyManager.currentPowerStorage < 0 ? qsTr("From battery") : qsTr("To battery")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.extraSmallFont
-// }
-// Label {
-// color: value < 0 ? Style.purple : Style.orange
-// property double value: energyManager.currentPowerStorage
-// property double absValue: Math.abs(energyManager.currentPowerStorage)
-// text: "%1 %2".arg((absValue / (absValue > 1000 ? 1000 : 1)).toFixed(1))
-// .arg(absValue > 1000 ? "kW" : "W")
-// Layout.fillWidth: true
-// horizontalAlignment: Text.AlignHCenter
-// font: Style.smallFont
-// }
-// }
-// }
-//}
diff --git a/nymea-app/ui/mainviews/energy/PowerBalanceHistory.qml b/nymea-app/ui/mainviews/energy/PowerBalanceHistory.qml
index 4c8ae4d7..9d0ef50b 100644
--- a/nymea-app/ui/mainviews/energy/PowerBalanceHistory.qml
+++ b/nymea-app/ui/mainviews/energy/PowerBalanceHistory.qml
@@ -8,6 +8,8 @@ import "qrc:/ui/components"
Item {
id: root
+ property bool titleVisible: true
+
PowerBalanceLogs {
id: powerBalanceLogs
engine: _engine
@@ -26,6 +28,8 @@ Item {
id: d
property date now: new Date()
+ property var selectedSeries: null
+
readonly property int range: selectionTabs.currentValue.range
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
readonly property int visibleValues: range / sampleRate
@@ -63,6 +67,13 @@ Item {
return timestamp
}
+ function selectSeries(series) {
+ if (d.selectedSeries == series) {
+ d.selectedSeries = null
+ } else {
+ d.selectedSeries = series
+ }
+ }
}
Connections {
@@ -105,12 +116,20 @@ Item {
anchors.fill: parent
spacing: 0
-// Label {
-// Layout.fillWidth: true
-// Layout.margins: Style.smallMargins
-// horizontalAlignment: Text.AlignHCenter
-// text: qsTr("My production history")
-// }
+ Label {
+ id: titleLabel
+ Layout.fillWidth: true
+ Layout.margins: Style.smallMargins
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("My power balance history")
+ visible: root.titleVisible
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ pageStack.push(Qt.resolvedUrl("PowerBalanceHistoryPage.qml"))
+ }
+ }
+ }
SelectionTabs {
id: selectionTabs
@@ -265,6 +284,7 @@ Item {
shadesVisible: false
labelsColor: Style.foregroundColor
}
+
AreaSeries {
id: selfProductionConsumptionSeries
axisX: dateTimeAxis
@@ -273,8 +293,10 @@ Item {
// borderWidth: 2
borderColor: color
name: qsTr("From self production")
+ opacity: d.selectedSeries == null || d.selectedSeries == selfProductionConsumptionSeries ? 1 : 0.3
// visible: false
+ onClicked: d.selectedSeries(selfProductionConsumptionSeries)
lowerSeries: LineSeries {
id: zeroSeries
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
@@ -331,9 +353,11 @@ Item {
color: Style.purple
borderWidth: 0
borderColor: color
+ opacity: d.selectedSeries == null || d.selectedSeries == toStorageSeries ? 1 : 0.3
visible: root.batteries.count > 0
name: qsTr("To battery")
+ onClicked: d.selectSeries(toStorageSeries)
function calculateValue(entry) {
return selfProductionConsumptionSeries.calculateValue(entry) + Math.max(0, entry.storage);
@@ -352,7 +376,6 @@ Item {
}
}
-
AreaSeries {
id: returnSeries
axisX: dateTimeAxis
@@ -361,8 +384,11 @@ Item {
borderWidth: 0
borderColor: color
name: qsTr("To grid")
+ opacity: d.selectedSeries == null || d.selectedSeries == returnSeries ? 1 : 0.3
// visible: false
+ onClicked: d.selectSeries(returnSeries)
+
function calculateValue(entry) {
return toStorageSeries.calculateValue(entry) + Math.max(0, -entry.acquisition)
}
@@ -387,8 +413,10 @@ Item {
borderWidth: 0
borderColor: color
name: qsTr("From battery")
+ opacity: d.selectedSeries == null || d.selectedSeries == fromStorageSeries ? 1 : 0.3
visible: root.batteries.count > 0
+ onClicked: d.selectSeries(fromStorageSeries)
lowerSeries: selfProductionConsumptionUpperSeries
upperSeries: LineSeries {
id: fromStorageUpperSeries
@@ -406,7 +434,6 @@ Item {
}
}
-
AreaSeries {
id: acquisitionSeries
axisX: dateTimeAxis
@@ -415,8 +442,11 @@ Item {
borderWidth: 0
borderColor: color
name: qsTr("From grid")
+ opacity: d.selectedSeries == null || d.selectedSeries == acquisitionSeries ? 1 : 0.3
// visible: false
+ onClicked: d.selectSeries(acquisitionSeries)
+
lowerSeries: fromStorageUpperSeries
upperSeries: LineSeries {
id: acquisitionUpperSeries
@@ -476,89 +506,158 @@ Item {
}
RowLayout {
+ id: legend
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
anchors.leftMargin: chartView.plotArea.x
height: Style.smallIconSize
anchors.margins: Style.margins
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
- ColorIcon {
- name: "weathericons/weather-clear-day"
- size: Style.smallIconSize
- color: Style.green
+ onClicked: d.selectSeries(selfProductionConsumptionSeries)
+ opacity: selfProductionConsumptionSeries.opacity
+ Row {
anchors.centerIn: parent
+ spacing: Style.smallMargins
+ ColorIcon {
+ name: "weathericons/weather-clear-day"
+ size: Style.smallIconSize
+ color: Style.green
+ }
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("Produced")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
+ }
}
}
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
+ onClicked: d.selectSeries(acquisitionSeries)
+ opacity: acquisitionSeries.opacity
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "power-grid"
- size: Style.smallIconSize
- color: Style.red
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "power-grid"
+ size: Style.smallIconSize
+ color: Style.red
+ }
+ ColorIcon {
+ name: "arrow-down"
+ size: Style.smallIconSize
+ color: Style.red
+ }
}
- ColorIcon {
- name: "arrow-down"
- size: Style.smallIconSize
- color: Style.red
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("From grid")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
- Item {
+
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
+ onClicked: d.selectSeries(returnSeries)
+ opacity: returnSeries.opacity
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "power-grid"
- size: Style.smallIconSize
- color: Style.yellow
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "power-grid"
+ size: Style.smallIconSize
+ color: Style.yellow
+ }
+ ColorIcon {
+ name: "arrow-up"
+ size: Style.smallIconSize
+ color: Style.yellow
+ }
}
- ColorIcon {
- name: "arrow-up"
- size: Style.smallIconSize
- color: Style.yellow
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("To grid")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
- Item {
+
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
visible: batteries.count > 0
+ onClicked: d.selectSeries(toStorageSeries)
+ opacity: toStorageSeries.opacity
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "battery/battery-080"
- size: Style.smallIconSize
- color: Style.purple
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "battery/battery-080"
+ size: Style.smallIconSize
+ color: Style.purple
+ }
+ ColorIcon {
+ name: "plus"
+ size: Style.smallIconSize
+ color: Style.purple
+ }
}
- ColorIcon {
- name: "plus"
- size: Style.smallIconSize
- color: Style.purple
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("To battery")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
- Item {
+
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
visible: batteries.count > 0
+ onClicked: d.selectSeries(fromStorageSeries)
+ opacity: fromStorageSeries.opacity
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "battery/battery-040"
- size: Style.smallIconSize
- color: Style.orange
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "battery/battery-040"
+ size: Style.smallIconSize
+ color: Style.orange
+ }
+ ColorIcon {
+ name: "minus"
+ size: Style.smallIconSize
+ color: Style.orange
+ }
}
- ColorIcon {
- name: "minus"
- size: Style.smallIconSize
- color: Style.orange
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("From battery")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
@@ -574,6 +673,7 @@ Item {
hoverEnabled: true
preventStealing: tooltipping || dragging
+ propagateComposedEvents: true
property int startMouseX: 0
property bool dragging: false
diff --git a/nymea-app/ui/mainviews/energy/PowerBalanceHistoryPage.qml b/nymea-app/ui/mainviews/energy/PowerBalanceHistoryPage.qml
new file mode 100644
index 00000000..646bf656
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/PowerBalanceHistoryPage.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ header: NymeaHeader {
+ text: qsTr("My power balance history")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ PowerBalanceHistory {
+ id: powerBalanceHistory
+ anchors.fill: parent
+ titleVisible: false
+ }
+}
diff --git a/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml b/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml
index 55d36029..946c2e1e 100644
--- a/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml
+++ b/nymea-app/ui/mainviews/energy/PowerBalanceStats.qml
@@ -10,6 +10,8 @@ StatsBase {
property EnergyManager energyManager: null
+ property bool titleVisible: true
+
property ThingsProxy producers: ThingsProxy {
engine: _engine
shownInterfaces: ["smartmeterproducer"]
@@ -22,6 +24,8 @@ StatsBase {
property var config: root.configs[selectionTabs.currentValue.config]
property int startOffset: 0
+ property var selectedSet: null
+
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
@@ -38,6 +42,14 @@ StatsBase {
refresh()
}
+ function selectSet(set) {
+ if (d.selectedSet === set) {
+ d.selectedSet = null
+ } else {
+ d.selectedSet = set
+ }
+ }
+
function refresh() {
if (powerBalanceLogs.loadingInhibited) {
return;
@@ -106,12 +118,17 @@ StatsBase {
anchors.fill: parent
spacing: 0
-// Label {
-// Layout.fillWidth: true
-// Layout.margins: Style.smallMargins
-// horizontalAlignment: Text.AlignHCenter
-// text: qsTr("Totals")
-// }
+ Label {
+ Layout.fillWidth: true
+ Layout.margins: Style.smallMargins
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("Totals")
+ visible: root.titleVisible
+ MouseArea {
+ anchors.fill: parent
+ onClicked: pageStack.push(Qt.resolvedUrl("PowerBalanceStatsPage.qml"), {energyManager: root.energyManager, producers: root.producers})
+ }
+ }
SelectionTabs {
id: selectionTabs
@@ -278,7 +295,7 @@ StatsBase {
BarSet {
id: consumptionSet
label: qsTr("Consumed")
- color: Style.blue
+ color: Qt.rgba(Style.blue.r, Style.blue.g, Style.blue.b, d.selectedSet == null || d.selectedSet == consumptionSet ? 1 : 0.3)
borderColor: color
borderWidth: 0
values: {
@@ -292,7 +309,7 @@ StatsBase {
BarSet {
id: productionSet
label: qsTr("Produced")
- color: Style.green
+ color: Qt.rgba(Style.green.r, Style.green.g, Style.green.b, d.selectedSet == null || d.selectedSet == productionSet ? 1 : 0.3)
borderColor: color
borderWidth: 0
values: {
@@ -306,7 +323,7 @@ StatsBase {
BarSet {
id: acquisitionSet
label: qsTr("From grid")
- color: Style.red
+ color: Qt.rgba(Style.red.r, Style.red.g, Style.red.b, d.selectedSet == null || d.selectedSet == acquisitionSet ? 1 : 0.3)
borderColor: color
borderWidth: 0
values: {
@@ -320,7 +337,7 @@ StatsBase {
BarSet {
id: returnSet
label: qsTr("To grid")
- color: Style.yellow
+ color: Qt.rgba(Style.yellow.r, Style.yellow.g, Style.yellow.b, d.selectedSet == null || d.selectedSet == returnSet ? 1 : 0.3)
borderColor: color
borderWidth: 0
values: {
@@ -335,64 +352,113 @@ StatsBase {
}
RowLayout {
+ id: legend
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
anchors.leftMargin: chartView.plotArea.x
height: Style.smallIconSize
anchors.margins: Style.margins
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
- ColorIcon {
- name: "powersocket"
- size: Style.smallIconSize
- color: Style.blue
+ onClicked: d.selectSet(consumptionSet)
+ Row {
anchors.centerIn: parent
+ spacing: Style.smallMargins
+ ColorIcon {
+ name: "powersocket"
+ size: Style.smallIconSize
+ color: Style.blue
+ }
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("Consumed")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
+ }
}
}
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
- ColorIcon {
- name: "weathericons/weather-clear-day"
- size: Style.smallIconSize
- color: Style.green
+ onClicked: d.selectSet(productionSet)
+ Row {
anchors.centerIn: parent
+ spacing: Style.smallMargins
+ ColorIcon {
+ name: "weathericons/weather-clear-day"
+ size: Style.smallIconSize
+ color: Style.green
+ }
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("Produced")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
+ }
}
}
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
+ onClicked: d.selectSet(acquisitionSet)
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "power-grid"
- size: Style.smallIconSize
- color: Style.red
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "power-grid"
+ size: Style.smallIconSize
+ color: Style.red
+ }
+ ColorIcon {
+ name: "arrow-down"
+ size: Style.smallIconSize
+ color: Style.red
+ }
}
- ColorIcon {
- name: "arrow-down"
- size: Style.smallIconSize
- color: Style.red
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("From grid")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
- Item {
+ MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
+ onClicked: d.selectSet(returnSet)
Row {
anchors.centerIn: parent
- ColorIcon {
- name: "power-grid"
- size: Style.smallIconSize
- color: Style.yellow
+ spacing: Style.smallMargins
+ Row {
+ ColorIcon {
+ name: "power-grid"
+ size: Style.smallIconSize
+ color: Style.yellow
+ }
+ ColorIcon {
+ name: "arrow-up"
+ size: Style.smallIconSize
+ color: Style.yellow
+ }
}
- ColorIcon {
- name: "arrow-up"
- size: Style.smallIconSize
- color: Style.yellow
+ Label {
+ width: parent.parent.width - x
+ elide: Text.ElideRight
+ visible: legend.width > 500
+ text: qsTr("To grid")
+ anchors.verticalCenter: parent.verticalCenter
+ font: Style.smallFont
}
}
}
@@ -564,7 +630,7 @@ StatsBase {
Rectangle {
width: Style.extraSmallFont.pixelSize
height: width
- color: Style.yellow
+ color: Style.green
}
Label {
text: d.startOffset !== undefined ? qsTr("Produced: %1 kWh").arg(productionSet.at(toolTip.idx).toFixed(2)) : ""
@@ -586,7 +652,7 @@ StatsBase {
Rectangle {
width: Style.extraSmallFont.pixelSize
height: width
- color: Style.green
+ color: Style.yellow
}
Label {
text: d.startOffset !== undefined ? qsTr("To grid: %1 kWh").arg(returnSet.at(toolTip.idx).toFixed(2)) : ""
diff --git a/nymea-app/ui/mainviews/energy/PowerBalanceStatsPage.qml b/nymea-app/ui/mainviews/energy/PowerBalanceStatsPage.qml
new file mode 100644
index 00000000..683beb43
--- /dev/null
+++ b/nymea-app/ui/mainviews/energy/PowerBalanceStatsPage.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.3
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.2
+import Nymea 1.0
+import "qrc:/ui/components"
+
+Page {
+ id: root
+
+ property alias energyManager: powerBalanceStats
+ property alias producers: powerBalanceStats.producers
+
+ header: NymeaHeader {
+ text: qsTr("Power balance totals")
+ backButtonVisible: true
+ onBackPressed: pageStack.pop()
+ }
+
+ PowerBalanceStats {
+ id: powerBalanceStats
+ anchors.fill: parent
+ titleVisible: false
+ }
+}
diff --git a/nymea-app/ui/utils/NymeaUtils.qml b/nymea-app/ui/utils/NymeaUtils.qml
index 09a20d8a..84a147c0 100644
--- a/nymea-app/ui/utils/NymeaUtils.qml
+++ b/nymea-app/ui/utils/NymeaUtils.qml
@@ -154,7 +154,7 @@ Item {
property bool inhibitChartsAnimation: PlatformHelper.deviceModel.startsWith("SM-G950") // Samsung S8 has a buggy GPU driver :(
property int chartsAnimationOptions: !inhibitChartsAnimation ? ChartView.SeriesAnimations : ChartView.NoAnimation
- function generateColor(baseColor, index) {
+ function generateColor(baseColor, index, alpha) {
var stepSize = 30
var baseHSV = rgb2hsv(baseColor.r, baseColor.g, baseColor.b)
var currentHue = baseHSV[0]
@@ -170,7 +170,7 @@ Item {
}
handledColors.push(currentHue)
}
- return Qt.hsva(currentHue / 360, baseHSV[1], baseHSV[2], 1);
+ return Qt.hsva(currentHue / 360, baseHSV[1], baseHSV[2], alpha || 1);
}
function rgb2hsv(r,g,b) {