This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-app/nymea-app/ui/devicepages/IrrigationDevicePage.qml

341 lines
13 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 QtQuick.Controls.Material 2.1
import Nymea 1.0
import "../components"
ThingPageBase {
id: root
readonly property var powerStateType: thing.thingClass.stateTypes.findByName("power")
readonly property var powerState: thing.states.getState(powerStateType.id)
readonly property var powerActionType: thing.thingClass.actionTypes.findByName("power");
readonly property bool isOn: powerState && powerState.value === true
QtObject {
id: d
property var pendingRuleCreationId: -1
property var now: new Date()
}
Timer {
running: true
repeat: true
interval: 5000
onTriggered: {
d.now = new Date()
}
}
Component.onCompleted: {
cleanupRules();
}
function waterFor(minutes) {
var rule = engine.ruleManager.createNewRule();
var now = new Date();
var offDate = new Date(now.getTime() + (minutes * 60000));
rule.name = qsTr("Turn %1 off at %2").arg(root.thing.name).arg(Qt.formatDateTime(offDate))
var timeEvent = rule.timeDescriptor.timeEventItems.createNewTimeEventItem();
timeEvent.dateTime = offDate;
timeEvent.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeNone;
rule.timeDescriptor.timeEventItems.addTimeEventItem(timeEvent);
var ruleAction = rule.actions.createNewRuleAction();
ruleAction.thingId = root.thing.id;
ruleAction.interfaceName = "power";
ruleAction.interfaceAction = "power"
ruleAction.ruleActionParams.setRuleActionParamByName("power", false);
rule.actions.addRuleAction(ruleAction)
d.pendingRuleCreationId = engine.ruleManager.addRule(rule);
}
function cleanupRules() {
print("cleaning up stale oneshot watering rules")
for (var i = 0; i < engine.tagsManager.tags.count; i++) {
var tag = engine.tagsManager.tags.get(i);
if (tag.tagId === "oneshot-watering") {
print("have a oneshot-watering tag")
// Delete it if the timer expired already
var rule = engine.ruleManager.rules.getRule(tag.ruleId)
if (rule.timeDescriptor.timeEventItems.get(0).dateTime < new Date()) {
print("need to cleanup rule:", tag.ruleId, rule.timeDescriptor.timeEventItems.get(0).dateTime)
engine.ruleManager.removeRule(tag.ruleId)
} else {
print("Rule still pending:", tag.ruleId)
}
// Also delete it if the irrigation is off already
if (root.powerState.value === false) {
engine.ruleManager.removeRule(tag.ruleId);
}
}
}
}
Connections {
target: engine.ruleManager
onAddRuleReply: {
if (commandId == d.pendingRuleCreationId) {
d.pendingRuleCreationId = -1
if (ruleError != RuleManager.RuleErrorNoError) {
var comp = Qt.createComponent("../components/ErrorDialog.qml")
var popup = comp.createObject(app, {errorCode: ruleError})
popup.open();
return;
}
// Tag the rule so we can clean identify it
engine.tagsManager.tagRule(ruleId, "oneshot-watering", root.thing.id)
// Off rule has been added. Turning on now
if (root.powerState.value === false) {
engine.thingManager.executeAction(root.thing.id, root.powerActionType.id, [{paramTypeId: root.powerActionType.id, value: true}])
}
}
}
}
Connections {
target: root.powerState
onValueChanged: cleanupRules()
}
LogsModelNg {
id: history
engine: _engine
thingId: root.thing.id
typeIds: [root.powerStateType.id]
property var lastWatering: count > 0 ? get(0).timestamp : null
live: true
}
TagsProxyModel {
id: tagsProxy
tags: engine.tagsManager.tags
filterTagId: "oneshot-watering"
filterValue: root.thing.id
}
GridLayout {
id: mainGrid
anchors.fill: parent
anchors.margins: app.margins
columns: app.landscape ? 2 : 1
Item {
Layout.preferredWidth: app.landscape ? parent.width * .4 : parent.width
Layout.preferredHeight: app.landscape ? parent.height : parent.height *.4
AbstractButton {
height: Math.min(Math.min(parent.height, parent.width), Style.iconSize * 5)
width: height
anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: root.powerState.value === true ? Style.accentColor : Style.iconColoor
border.width: 4
radius: width / 2
}
ColorIcon {
id: irrigationIcon
anchors.fill: parent
anchors.margins: app.margins * 1.5
name: "../images/irrigation.svg"
color: root.powerState.value === true ? Style.accentColor : Style.iconColor
}
onClicked: {
var params = []
var param = {}
param["paramTypeId"] = root.powerActionType.paramTypes.get(0).id;
param["value"] = !root.powerState.value;
params.push(param)
engine.thingManager.executeAction(root.thing.id, root.powerStateType.id, params);
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
}
}
}
ColumnLayout {
Layout.preferredWidth: app.landscape ? parent.width * .6 : parent.width
Layout.preferredHeight: app.landscape ? parent.height : parent.height * .6
Item { Layout.fillWidth: true; Layout.fillHeight: true }
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
horizontalAlignment: Text.AlignHCenter
text: root.isOn ? qsTr("Watering since")
: history.lastWatering ? qsTr("Last watering")
: qsTr("This irrigation has not been used yet")
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
horizontalAlignment: Text.AlignHCenter
text: history.lastWatering ? Qt.formatDateTime(history.lastWatering) : ""
font.pixelSize: app.largeFont
color: Style.accentColor
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.bottomMargin: app.margins
horizontalAlignment: Text.AlignHCenter
font.pixelSize: app.smallFont
text: {
if (!history.lastWatering) {
return ""
}
var n = Math.floor((d.now - history.lastWatering) / 60 / 1000)
n = Math.max(0, n)
if (root.isOn) {
if (n < 60) {
return qsTr("%n minute(s)", "", n);
}
n /= 60;
if (n < 24) {
return qsTr("%n hour(s)", "", n);
}
n /= 24;
return qsTr("%n day(s)", "", n);
}
if (n < 60) {
return qsTr("%n minute(s) ago", "", n);
}
n /= 60;
if (n < 24) {
return qsTr("%n hour(s) ago", "", n);
}
n /= 24;
return qsTr("%n day(s) ago", "", n);
}
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.topMargin: app.margins
horizontalAlignment: Text.AlignHCenter
text: tagsProxy.count > 0 ?
//: Irrigation will be turned of at, e.g. 09:00
qsTr("Watering until")
//: Turn on irrigation for, e.g. 5 minutes
: root.isOn ? qsTr("Turn off in") : qsTr("Water for")
}
GridLayout {
columns: 3
visible: tagsProxy.count == 0
Button {
Layout.fillWidth: true
text: qsTr("1 minute")
onClicked: root.waterFor(1)
}
Button {
Layout.fillWidth: true
text: qsTr("2 minutes")
onClicked: root.waterFor(2)
}
Button {
Layout.fillWidth: true
text: qsTr("5 minutes")
onClicked: root.waterFor(5)
}
Button {
Layout.fillWidth: true
text: qsTr("15 minutes")
onClicked: root.waterFor(15)
}
Button {
Layout.fillWidth: true
text: qsTr("30 minutes")
onClicked: root.waterFor(30)
}
Button {
Layout.fillWidth: true
text: qsTr("1 hour")
onClicked: root.waterFor(60)
}
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
horizontalAlignment: Text.AlignHCenter
visible: tagsProxy.count > 0
font.pixelSize: app.largeFont
color: Style.accentColor
text: tagsProxy.count == 0 ? "" : Qt.formatDateTime(engine.ruleManager.rules.getRule(tagsProxy.get(0).ruleId).timeDescriptor.timeEventItems.get(0).dateTime)
}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins; Layout.bottomMargin: app.margins
horizontalAlignment: Text.AlignHCenter
visible: tagsProxy.count > 0
font.pixelSize: app.smallFont
text: {
if (tagsProxy.count == 0) {
return ""
}
var end = engine.ruleManager.rules.getRule(tagsProxy.get(0).ruleId).timeDescriptor.timeEventItems.get(0).dateTime
var n = Math.floor((end - d.now) / 60 / 1000)
n = Math.max(0, n);
if (n < 60) {
return qsTr("%n minute(s) left", "", n);
}
n /= 60;
if (n < 24) {
return qsTr("%n hour(s) left", "", n);
}
n /= 24;
return qsTr("%n day(s) left", "", n);
}
}
Item { Layout.fillWidth: true; Layout.fillHeight: true }
}
}
}