227 lines
10 KiB
QML
227 lines
10 KiB
QML
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Copyright 2013 - 2020, nymea GmbH
|
|
* Contact: contact@nymea.io
|
|
*
|
|
* This file is part of nymea.
|
|
* This project including source code and documentation is protected by
|
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
|
* reproduction, publication, editing and translation, are reserved. The use of
|
|
* this project is subject to the terms of a license agreement to be concluded
|
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
|
* under https://nymea.io/license
|
|
*
|
|
* GNU General Public License Usage
|
|
* Alternatively, this project may be redistributed and/or modified under the
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* For any further details and any questions please contact us under
|
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
|
* https://nymea.io/license/faq
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
import QtQuick 2.5
|
|
import QtQuick.Controls 2.1
|
|
import QtQuick.Layouts 1.1
|
|
import QtGraphicalEffects 1.0
|
|
import Nymea 1.0
|
|
import "../components"
|
|
import "../customviews"
|
|
|
|
ThingPageBase {
|
|
id: root
|
|
|
|
readonly property bool isEnergyMeter: root.thing && root.thing.thingClass.interfaces.indexOf("energymeter") >= 0
|
|
readonly property bool isConsumer: root.thing && root.thing.thingClass.interfaces.indexOf("smartmeterconsumer") >= 0
|
|
readonly property bool isProducer: root.thing && root.thingClass.interfaces.indexOf("smartmeterproducer") >= 0
|
|
readonly property bool isBattery: root.thing && root.thingClass.interfaces.indexOf("energystorage") >= 0
|
|
|
|
|
|
readonly property State currentPowerState: root.thing.stateByName("currentPower")
|
|
|
|
// meters, producers, consumers
|
|
readonly property State totalEnergyConsumedState: isEnergyMeter || isConsumer ? root.thing.stateByName("totalEnergyConsumed") : null
|
|
readonly property StateType totalEnergyConsumedStateType: isEnergyMeter || isConsumer ? root.thing.thingClass.stateTypes.findByName("totalEnergyConsumed") : null
|
|
readonly property State totalEnergyProducedState: isEnergyMeter || isProducer ? root.thing.stateByName("totalEnergyProduced") : null
|
|
readonly property StateType totalEnergyProducedStateType: isEnergyMeter || isProducer ? root.thing.thingClass.stateTypes.findByName("totalEnergyProduced") : null
|
|
|
|
// Battery related states
|
|
readonly property State batteryLevelState: isBattery ? root.thing.stateByName("batteryLevel") : null
|
|
readonly property State batteryCriticalState: isBattery ? root.thing.stateByName("batteryCritical") : null
|
|
readonly property State chargingState: isBattery ? root.thing.stateByName("chargingState") : null
|
|
readonly property State capacityState: isBattery ? root.thing.stateByName("capacity") : null
|
|
|
|
|
|
|
|
readonly property real currentPower: currentPowerState ? currentPowerState.value : 0
|
|
|
|
readonly property date now: d.now
|
|
readonly property date startTime: new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
|
|
|
QtObject {
|
|
id: d
|
|
property date now: new Date()
|
|
}
|
|
Timer {
|
|
interval: 60000
|
|
repeat: true
|
|
running: true
|
|
onTriggered: d.now = new Date()
|
|
}
|
|
|
|
GridLayout {
|
|
id: contentGrid
|
|
anchors.fill: parent
|
|
columns: app.landscape ? 2 : 1
|
|
|
|
CircleBackground {
|
|
id: background
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
Layout.margins: Style.hugeMargins
|
|
iconSource: ""
|
|
onColor: batteryLevelState
|
|
? currentPower < 0 ? "crimson" : "limegreen"
|
|
: currentPower < 0 ? "limegreen" : "crimson"
|
|
|
|
Rectangle {
|
|
id: mask
|
|
anchors.centerIn: parent
|
|
width: background.contentItem.width
|
|
height: background.contentItem.height
|
|
radius: width / 2
|
|
visible: false
|
|
}
|
|
|
|
Item {
|
|
id: juice
|
|
anchors.fill: parent
|
|
|
|
Rectangle {
|
|
anchors.centerIn: parent
|
|
width: background.contentItem.width
|
|
height: background.contentItem.height
|
|
property real progress: root.batteryLevelState ? root.batteryLevelState.value / 100 : 0
|
|
anchors.verticalCenterOffset: height * (1 - progress)
|
|
color: batteryCriticalState && batteryCriticalState.value ? "crimson" : "limegreen"
|
|
visible: root.batteryLevelState
|
|
}
|
|
|
|
RadialGradient {
|
|
id: gradient
|
|
anchors.centerIn: parent
|
|
width: background.contentItem.width
|
|
height: background.contentItem.height
|
|
property real progress: Math.abs(root.currentPower) / 10000
|
|
visible: currentPower != 0
|
|
|
|
Behavior on gradientRatio { NumberAnimation { duration: Style.sleepyAnimationDuration; easing.type: Easing.InOutQuad } }
|
|
property real gradientRatio: (1 - progress) * 0.1
|
|
gradient: Gradient{
|
|
GradientStop { position: .399 + gradient.gradientRatio; color: "transparent" }
|
|
GradientStop { position: .5; color: background.onColor }
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.centerIn: parent
|
|
|
|
Label {
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
font: Style.largeFont
|
|
property bool toKilos: Math.abs(currentPower) >= 1000
|
|
property double value: Math.abs(currentPower / (toKilos ? 1000 : 1))
|
|
text: "%1 %2".arg(value.toFixed(toKilos ? 2 : 1)).arg(toKilos ? "kW" : "W")
|
|
}
|
|
|
|
Label {
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
text: {
|
|
if (root.chargingState) {
|
|
switch (root.chargingState.value) {
|
|
case "idle":
|
|
return qsTr("Idle")
|
|
case "charging":
|
|
return qsTr("Charging")
|
|
case "discharging":
|
|
return qsTr("Discharging")
|
|
}
|
|
}
|
|
if (root.isProducer) {
|
|
return qsTr("Producing")
|
|
}
|
|
if (root.isConsumer) {
|
|
return qsTr("Consuming")
|
|
}
|
|
|
|
return root.currentPower < 0 ? qsTr("Returning") : qsTr("Obtaining")
|
|
}
|
|
font: Style.smallFont
|
|
}
|
|
|
|
|
|
Label {
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
font: Style.bigFont
|
|
visible: batteryLevelState
|
|
text: "%1 %".arg(batteryLevelState ? batteryLevelState.value : "")
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
OpacityMask {
|
|
anchors.centerIn: parent
|
|
width: background.contentItem.width
|
|
height: background.contentItem.height
|
|
source: ShaderEffectSource {
|
|
sourceItem: juice
|
|
hideSource: true
|
|
sourceRect: Qt.rect(background.contentItem.x, background.contentItem.y, background.contentItem.width, background.contentItem.height)
|
|
}
|
|
maskSource: mask
|
|
}
|
|
}
|
|
|
|
|
|
ColumnLayout {
|
|
id: textLayout
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
Layout.margins: Style.bigMargins
|
|
spacing: Style.margins
|
|
|
|
Label {
|
|
Layout.fillWidth: true
|
|
visible: isBattery
|
|
wrapMode: Text.WordWrap
|
|
horizontalAlignment: Text.AlignHCenter
|
|
textFormat: Text.RichText
|
|
property bool isCharging: root.chargingState && root.chargingState.value === "charging"
|
|
property bool isDischarging: root.chargingState && root.chargingState.value === "discharging"
|
|
property double availableWh: isBattery ? root.capacityState.value * 1000 * root.batteryLevelState.value / 100 : 0
|
|
property double remainingWh: isCharging ? root.capacityState.value * 1000 - availableWh : availableWh
|
|
property double remainingHours: isBattery ? remainingWh / Math.abs(root.currentPower) : 0
|
|
property date endTime: isBattery ? new Date(new Date().getTime() + remainingHours * 60 * 60 * 1000) : new Date()
|
|
property int n: Math.round(remainingHours)
|
|
|
|
text: isCharging ? qsTr("At the current rate, the battery will be fully charged at %1.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + endTime.toLocaleTimeString(Locale.ShortFormat) + "</span>")
|
|
: isDischarging ? qsTr("At the current rate, the battery will last until %1.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + endTime.toLocaleTimeString(Locale.ShortFormat) + "</span>")
|
|
: ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|