0.6.0 blocco 1: Home di consultazione e pagina Regolazioni
- Home: stato in una riga col pallino, due letture grandi toccabili, tre azioni rapide; via i due slider, i sette pulsanti e la scheda separata. - Nuova pagina Regolazioni: un blocco per grandezza, valore attuale sempre visibile, preimpostazioni per le dita fredde, conferma esplicita; il pulsante e' attivo solo se c'e' davvero qualcosa da cambiare. - Messaggi dei comandi spostati in ApiClient (api.notice) con NoticeBar ancorata in fondo: prima nascevano fuori dallo schermo. - Stato breve/esteso/livello in C++ (testabile senza SDK), 18 verifiche nuove: 79/79. - stale + lastUpdate: la Home dice 'aggiornato alle HH:MM' e spegne i numeri vecchi invece di farli passare per freschi. - 192/192 stringhe tradotte (54 nuove).
This commit is contained in:
+174
-376
@@ -2,27 +2,65 @@ import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import "../components"
|
||||
|
||||
// Dashboard dell'impianto, ordinata come la schermata iniziale dell'app
|
||||
// ufficiale Aira: in alto la temperatura esterna, poi il messaggio di stato,
|
||||
// poi la scheda dell'impianto con le due letture principali (casa e acqua
|
||||
// calda). I comandi restano piu' sotto, perche' qui si possono dare davvero.
|
||||
// Legge api.summary (QVariantMap dal C++), quindi non dipende dallo scope
|
||||
// delle property del main qml.
|
||||
// Home: una schermata da GUARDARE, non un modulo da compilare.
|
||||
//
|
||||
// Stato in una riga, le due letture che contano (casa e acqua calda), tre
|
||||
// azioni rapide. Le regolazioni stanno in SetpointsPage, gli altri comandi in
|
||||
// CommandsPage, i numeri in DataPage, i dettagli in PlantPage: qui solo quello
|
||||
// che si guarda molte volte al giorno, senza scorrere (docs/UX-STUDIO.md).
|
||||
Page {
|
||||
id: page
|
||||
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
// obiettivo ACS scelto dall'utente (non sovrascritto dal refresh finche'
|
||||
// non lo tocca, altrimenti lo slider "salta" a ogni lettura)
|
||||
property int targetAcs: 55
|
||||
property bool targetAcsTouched: false
|
||||
// obiettivo della casa (zona 1); parte dalla temperatura attuale e non
|
||||
// viene sovrascritto dal refresh finche' l'utente non lo tocca
|
||||
property real targetCasa: 20
|
||||
property bool targetCasaTouched: false
|
||||
property string notice: ""
|
||||
property bool noticeIsError: false
|
||||
function raw(key) {
|
||||
return api.summary[key]
|
||||
}
|
||||
|
||||
// I numeri si formattano nel C++ (ApiClient::formatValue): cosi' il
|
||||
// separatore decimale segue la lingua dell'app, non il toFixed di JS.
|
||||
function fmt(value) { return api.formatValue(value) }
|
||||
|
||||
function count(key) {
|
||||
var v = page.raw(key)
|
||||
if (v === undefined || v === null)
|
||||
return "—"
|
||||
return String(Math.round(Number(v)))
|
||||
}
|
||||
|
||||
// Colore del pallino di stato. Il livello (0 regolare, 1 modo attivo,
|
||||
// 2 errore) lo calcola il C++; qui si sceglie il colore, e l'ambra quando
|
||||
// i numeri sono vecchi: un dato vecchio non e' un dato buono.
|
||||
function statusColor() {
|
||||
if (!api.hasData || api.stale)
|
||||
return "orange"
|
||||
var livello = api.statusLevel()
|
||||
if (livello === 2)
|
||||
return Theme.errorColor
|
||||
if (livello === 1)
|
||||
return Theme.highlightColor
|
||||
return "#4caf50"
|
||||
}
|
||||
|
||||
// Quanto e' carica l'acqua calda verso l'obiettivo (da 10 °C in su).
|
||||
function waterProgress() {
|
||||
var ora = Number(page.raw("dhw_current"))
|
||||
var obiettivo = Number(page.raw("dhw_target"))
|
||||
if (!(obiettivo > 10) || isNaN(ora))
|
||||
return 0
|
||||
return (ora - 10) / (obiettivo - 10)
|
||||
}
|
||||
|
||||
// Riga sotto il titolo: dice anche quando i numeri sono vecchi.
|
||||
function updateText() {
|
||||
if (!api.hasData)
|
||||
return qsTr("No data yet")
|
||||
if (api.stale)
|
||||
return qsTr("Not updated · last %1").arg(api.lastUpdate)
|
||||
if (api.lastUpdate.length === 0)
|
||||
return ""
|
||||
return qsTr("Updated at %1").arg(api.lastUpdate)
|
||||
}
|
||||
|
||||
function openSettings() {
|
||||
pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
|
||||
@@ -40,100 +78,14 @@ Page {
|
||||
pageStack.push(Qt.resolvedUrl("DataPage.qml"))
|
||||
}
|
||||
|
||||
function showNotice(msg, isError) {
|
||||
page.notice = msg
|
||||
page.noticeIsError = isError === true
|
||||
noticeTimer.restart()
|
||||
}
|
||||
|
||||
function raw(key) {
|
||||
return api.summary[key]
|
||||
}
|
||||
|
||||
// I numeri si formattano nel C++ (ApiClient::formatValue): cosi' il
|
||||
// separatore decimale segue la lingua dell'app, non il toFixed di JS.
|
||||
function fmt(value) { return api.formatValue(value) }
|
||||
|
||||
function temp(key) {
|
||||
return api.formatValue(page.raw(key))
|
||||
}
|
||||
|
||||
function count(key) {
|
||||
var v = page.raw(key)
|
||||
if (v === undefined || v === null)
|
||||
return "—"
|
||||
return String(Math.round(Number(v)))
|
||||
}
|
||||
|
||||
// "2026-10-09 18:52:17.199340" -> "18:52"
|
||||
function shortTime(s) {
|
||||
if (!s)
|
||||
return "—"
|
||||
var parts = String(s).split(" ")
|
||||
if (parts.length < 2)
|
||||
return String(s)
|
||||
return parts[1].substring(0, 5)
|
||||
}
|
||||
|
||||
// Messaggio grande in cima: e' la frase che l'app ufficiale mette al centro
|
||||
// della schermata iniziale ("Relax, la tua pompa di calore..."). Si sceglie
|
||||
// in ordine di importanza: errori, modalita' attive, pompa in funzione.
|
||||
function stateMessage() {
|
||||
if (!api.configured)
|
||||
return ""
|
||||
var errs = Number(page.raw("errors_count"))
|
||||
if (errs > 0)
|
||||
return (errs === 1)
|
||||
? qsTr("Attention: one error on the plant")
|
||||
: qsTr("Attention: %1 errors on the plant").arg(errs)
|
||||
if (page.raw("away_mode") === true)
|
||||
return qsTr("Away mode: the house is saving energy.")
|
||||
if (page.raw("night_mode") === true)
|
||||
return qsTr("Night mode is on.")
|
||||
if (page.raw("force_heating") === true)
|
||||
return qsTr("Boost: the house is heating at full power.")
|
||||
if (page.raw("hot_water_heating") === true)
|
||||
return qsTr("The heat pump is heating the hot water.")
|
||||
if (String(page.raw("pump_active_state") || "").indexOf("RUNNING") >= 0)
|
||||
return qsTr("The heat pump is working.")
|
||||
return qsTr("Relax: the heat pump is running smoothly.")
|
||||
}
|
||||
|
||||
// Riga piccola sotto il messaggio: modalita' e ora dell'ultima lettura.
|
||||
function statusDetail() {
|
||||
if (!api.configured)
|
||||
return ""
|
||||
return qsTr("%1 · last reading %2")
|
||||
.arg(api.modeLabel(page.raw("operating_status")))
|
||||
.arg(page.shortTime(page.raw("pump_updated")))
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: noticeTimer
|
||||
interval: 4000
|
||||
onTriggered: page.notice = ""
|
||||
Component.onCompleted: {
|
||||
if (api.configured)
|
||||
api.refresh()
|
||||
}
|
||||
|
||||
// Fuori dal pulsante: dentro il pulsante i figli finiscono nel contentItem.
|
||||
RemorseItem { id: remorse }
|
||||
|
||||
Connections {
|
||||
target: api
|
||||
onErrorOccurred: page.showNotice(message, true)
|
||||
onCommandFinished: page.showNotice(message, !ok)
|
||||
onSummaryChanged: {
|
||||
if (!page.targetAcsTouched) {
|
||||
var v = page.raw("dhw_target")
|
||||
if (v !== undefined && v !== null)
|
||||
page.targetAcs = Math.round(Number(v))
|
||||
}
|
||||
if (!page.targetCasaTouched) {
|
||||
var c = page.raw("zone1_setpoint")
|
||||
if (c !== undefined && c !== null && Number(c) > 0)
|
||||
page.targetCasa = Math.round(Number(c) * 2) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SilicaFlickable {
|
||||
id: flick
|
||||
anchors.fill: parent
|
||||
@@ -154,10 +106,6 @@ Page {
|
||||
text: qsTr("Plant")
|
||||
onClicked: page.openPlant()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Other commands")
|
||||
onClicked: page.openCommands()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Settings")
|
||||
onClicked: page.openSettings()
|
||||
@@ -169,17 +117,9 @@ Page {
|
||||
width: parent.width
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
PageHeader { title: "Aira" }
|
||||
|
||||
// ---- avvisi ---------------------------------------------------- //
|
||||
Label {
|
||||
visible: page.notice.length > 0
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
text: page.notice
|
||||
color: page.noticeIsError ? Theme.errorColor : Theme.highlightColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
wrapMode: Text.Wrap
|
||||
PageHeader {
|
||||
title: "Aira"
|
||||
description: page.updateText()
|
||||
}
|
||||
|
||||
// ---- bridge non configurato ------------------------------------ //
|
||||
@@ -200,300 +140,158 @@ Page {
|
||||
onClicked: page.openSettings()
|
||||
}
|
||||
|
||||
// ---- barra in alto: fuori casa / a casa ------------------------ //
|
||||
// ---- stato in una riga ----------------------------------------- //
|
||||
Item {
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
height: fuori.height
|
||||
height: Math.max(stato.height, pallino.height, attesa.height)
|
||||
|
||||
Label {
|
||||
id: fuori
|
||||
anchors.left: parent.left
|
||||
text: qsTr("Outside %1 °C").arg(page.temp("outdoor_temperature"))
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
Rectangle {
|
||||
id: pallino
|
||||
width: Theme.fontSizeSmall * 0.6
|
||||
height: width
|
||||
radius: width / 2
|
||||
color: page.statusColor()
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
id: stato
|
||||
anchors {
|
||||
left: pallino.right
|
||||
leftMargin: Theme.paddingMedium
|
||||
right: attesa.left
|
||||
rightMargin: Theme.paddingMedium
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: api.stateShort()
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: attesa
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: page.raw("away_mode") === true ? qsTr("Away") : qsTr("At home")
|
||||
color: page.raw("away_mode") === true ? Theme.highlightColor : Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
size: BusyIndicatorSize.Small
|
||||
running: api.busy
|
||||
visible: api.busy
|
||||
}
|
||||
}
|
||||
|
||||
// ---- messaggio di stato (il "centro" della schermata ufficiale) - //
|
||||
Label {
|
||||
// ---- le due letture che contano -------------------------------- //
|
||||
Row {
|
||||
id: letture
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
text: page.stateMessage()
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
ReadingCell {
|
||||
width: (letture.width - letture.spacing) / 2
|
||||
title: qsTr("House")
|
||||
value: page.fmt(page.raw("zone1_temperature")) + " °C"
|
||||
subtitle: qsTr("target %1 °C").arg(page.fmt(page.raw("zone1_setpoint")))
|
||||
valueColor: api.stale ? Theme.secondaryColor : Theme.primaryColor
|
||||
onTapped: pageStack.push(Qt.resolvedUrl("SetpointsPage.qml"))
|
||||
}
|
||||
|
||||
ReadingCell {
|
||||
width: (letture.width - letture.spacing) / 2
|
||||
title: qsTr("Hot water")
|
||||
value: page.fmt(page.raw("dhw_current")) + " °C"
|
||||
subtitle: qsTr("target %1 °C").arg(page.fmt(page.raw("dhw_target")))
|
||||
progress: page.waterProgress()
|
||||
showBar: true
|
||||
valueColor: api.stale ? Theme.secondaryColor : Theme.primaryColor
|
||||
onTapped: pageStack.push(Qt.resolvedUrl("SetpointsPage.qml"))
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
text: page.statusDetail()
|
||||
text: qsTr("Tap a value to adjust it")
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
// ---- scheda dell'impianto -------------------------------------- //
|
||||
// Come la scheda dispositivo dell'app ufficiale: intestazione con
|
||||
// nome e connessione, poi le due letture principali. Toccandola si
|
||||
// apre la pagina "Impianto" (accessori, versioni, errori).
|
||||
// ---- azioni rapide --------------------------------------------- //
|
||||
SectionHeader {
|
||||
visible: api.configured
|
||||
text: qsTr("Quick actions")
|
||||
}
|
||||
|
||||
Row {
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Button {
|
||||
id: boostBtn
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
text: qsTr("Boost")
|
||||
onClicked: remorse.execute(boostBtn, qsTr("Starting DHW boost"),
|
||||
function() { api.sendCommand("hot_water_boost_on") })
|
||||
}
|
||||
|
||||
Button {
|
||||
id: assenzaBtn
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
// Il pulsante dice cosa succede premendolo, non lo stato.
|
||||
text: page.raw("away_mode") ? qsTr("Back home") : qsTr("Away mode")
|
||||
onClicked: {
|
||||
if (page.raw("away_mode")) {
|
||||
remorse.execute(assenzaBtn, qsTr("Away mode off"),
|
||||
function() { api.sendCommand("away_mode_off") })
|
||||
} else {
|
||||
remorse.execute(assenzaBtn, qsTr("Away mode on"),
|
||||
function() { api.sendCommand("away_mode_on") })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
text: qsTr("Commands")
|
||||
onClicked: page.openCommands()
|
||||
}
|
||||
}
|
||||
|
||||
// ---- letture di contorno (si toccano: portano a Impianto) ------ //
|
||||
BackgroundItem {
|
||||
id: scheda
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
height: schedaCol.height + 3 * Theme.paddingMedium
|
||||
height: contornoTxt.height + Theme.paddingMedium
|
||||
onClicked: page.openPlant()
|
||||
|
||||
Column {
|
||||
id: schedaCol
|
||||
x: Theme.paddingMedium
|
||||
y: Theme.paddingMedium
|
||||
width: parent.width - 2 * Theme.paddingMedium
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: intestazione.height
|
||||
|
||||
Column {
|
||||
id: intestazione
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: freccia.left
|
||||
rightMargin: Theme.paddingSmall
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Aira heat pump")
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Connected through the cloud")
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: freccia
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: "›"
|
||||
color: Theme.highlightColor
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
}
|
||||
}
|
||||
|
||||
ValueRow {
|
||||
title: qsTr("Room temperature")
|
||||
subtitle: qsTr("Target %1 °C").arg(page.temp("zone1_setpoint"))
|
||||
value: page.temp("zone1_temperature") + " °C"
|
||||
}
|
||||
|
||||
ValueRow {
|
||||
title: qsTr("Domestic hot water")
|
||||
subtitle: qsTr("Target %1 °C").arg(page.temp("dhw_target"))
|
||||
value: page.temp("dhw_current") + " °C"
|
||||
Label {
|
||||
id: contornoTxt
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: qsTr("Outside %1 °C · Thermostat %2 °C · Zones %3")
|
||||
.arg(page.fmt(page.raw("outdoor_temperature")))
|
||||
.arg(page.fmt(page.raw("thermostat_temperature")))
|
||||
.arg(page.count("zones"))
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
// ---- riscaldamento della casa ---------------------------------- //
|
||||
SectionHeader { visible: api.configured; text: qsTr("Heating the house") }
|
||||
|
||||
Label {
|
||||
visible: api.configured
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Heating setpoint %1 °C · %2")
|
||||
.arg(page.temp("zone1_setpoint"))
|
||||
.arg(api.modeLabel(page.raw("zone1_mode")))
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: casaSlider
|
||||
visible: api.configured
|
||||
width: parent.width
|
||||
label: qsTr("New house target")
|
||||
minimumValue: 5
|
||||
maximumValue: 30
|
||||
stepSize: 0.5
|
||||
value: page.targetCasa
|
||||
valueText: page.fmt(value) + " °C"
|
||||
onValueChanged: {
|
||||
page.targetCasaTouched = true
|
||||
page.targetCasa = Math.round(value * 2) / 2
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: setCasaButton
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Set house to %1 °C").arg(page.fmt(page.targetCasa))
|
||||
onClicked: remorse.execute(setCasaButton,
|
||||
qsTr("House temperature to %1 °C").arg(page.fmt(page.targetCasa)),
|
||||
function() { api.sendCommand("set_heating_setpoint", page.targetCasa) })
|
||||
}
|
||||
|
||||
// ---- acqua calda sanitaria ------------------------------------- //
|
||||
SectionHeader { visible: api.configured; text: qsTr("Domestic hot water") }
|
||||
|
||||
ProgressBar {
|
||||
visible: api.configured
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 4 * Theme.horizontalPageMargin
|
||||
minimumValue: 20
|
||||
maximumValue: 65
|
||||
value: {
|
||||
var v = page.raw("dhw_current")
|
||||
return (v === undefined || v === null) ? 0 : Number(v)
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
visible: api.configured
|
||||
width: parent.width
|
||||
label: qsTr("New target")
|
||||
minimumValue: 45
|
||||
maximumValue: 60
|
||||
stepSize: 1
|
||||
value: page.targetAcs
|
||||
valueText: page.fmt(value) + " °C"
|
||||
onValueChanged: {
|
||||
page.targetAcsTouched = true
|
||||
page.targetAcs = Math.round(value)
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: setAcsButton
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Set target %1 °C").arg(page.targetAcs)
|
||||
onClicked: remorse.execute(setAcsButton,
|
||||
qsTr("DHW target to %1 °C").arg(page.targetAcs),
|
||||
function() { api.sendCommand("set_hot_water_target", page.targetAcs) })
|
||||
}
|
||||
|
||||
Button {
|
||||
id: boostOnButton
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Start DHW boost")
|
||||
onClicked: remorse.execute(boostOnButton, qsTr("Starting DHW boost"),
|
||||
function() { api.sendCommand("hot_water_boost_on") })
|
||||
}
|
||||
|
||||
Button {
|
||||
id: boostOffButton
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Stop DHW boost")
|
||||
onClicked: remorse.execute(boostOffButton, qsTr("Stopping DHW boost"),
|
||||
function() { api.sendCommand("hot_water_boost_off") })
|
||||
}
|
||||
|
||||
// ---- altre pagine ---------------------------------------------- //
|
||||
SectionHeader { visible: api.configured; text: qsTr("Details") }
|
||||
|
||||
Button {
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Plant and accessories")
|
||||
onClicked: page.openPlant()
|
||||
}
|
||||
|
||||
Button {
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Consumption and savings")
|
||||
onClicked: page.openData()
|
||||
}
|
||||
|
||||
Button {
|
||||
visible: api.configured
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
text: qsTr("Other commands")
|
||||
onClicked: page.openCommands()
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
visible: api.busy
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
size: BusyIndicatorSize.Small
|
||||
running: true
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: api.configured
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
text: qsTr("Commands are sent to the bridge and from there to the plant: they may take a few seconds.")
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Item { width: 1; height: Theme.paddingMedium }
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (api.configured)
|
||||
api.refresh()
|
||||
}
|
||||
NoticeBar { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user