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:
@@ -0,0 +1,234 @@
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import "../components"
|
||||
|
||||
// Regolazioni: le grandezze che si cambiano (obiettivo casa, obiettivo acqua
|
||||
// calda) e il boost, ognuna con il valore attuale sempre visibile, le
|
||||
// preimpostazioni per le dita fredde e la conferma esplicita.
|
||||
//
|
||||
// Pagina a parte perche' la Home deve restare una schermata da guardare: due
|
||||
// slider dentro la pagina che scorre si contendevano anche il trascinamento.
|
||||
// Qui lo slider e' la PROPOSTA, il numero grande e' quello vero dell'impianto:
|
||||
// i due coincidono solo dopo "Imposta".
|
||||
Page {
|
||||
id: page
|
||||
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
property real pendingHouse: 0
|
||||
property bool houseTouched: false
|
||||
property real pendingWater: 0
|
||||
property bool waterTouched: false
|
||||
|
||||
function raw(key) {
|
||||
return api.summary[key]
|
||||
}
|
||||
|
||||
function fmt(value) { return api.formatValue(value) }
|
||||
|
||||
// Obiettivo vero dell'impianto (zona 1), a passi di mezzo grado.
|
||||
function houseTarget() {
|
||||
var v = page.raw("zone1_setpoint")
|
||||
if (v === undefined || v === null || Number(v) <= 0)
|
||||
return 0
|
||||
return Math.round(Number(v) * 2) / 2
|
||||
}
|
||||
|
||||
function waterTarget() {
|
||||
var v = page.raw("dhw_target")
|
||||
if (v === undefined || v === null)
|
||||
return 0
|
||||
return Math.round(Number(v))
|
||||
}
|
||||
|
||||
// Allinea le proposte ai valori dell'impianto, ma non sovrascrive quello
|
||||
// che l'utente sta scegliendo.
|
||||
function syncFromPlant() {
|
||||
if (!page.houseTouched)
|
||||
page.pendingHouse = page.houseTarget()
|
||||
if (!page.waterTouched)
|
||||
page.pendingWater = page.waterTarget()
|
||||
}
|
||||
|
||||
function houseChanged() { return Math.abs(page.pendingHouse - page.houseTarget()) > 0.001 }
|
||||
function waterChanged() { return Math.abs(page.pendingWater - page.waterTarget()) > 0.001 }
|
||||
|
||||
Component.onCompleted: {
|
||||
page.syncFromPlant()
|
||||
if (api.configured)
|
||||
api.refresh()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: api
|
||||
onSummaryChanged: page.syncFromPlant()
|
||||
}
|
||||
|
||||
SilicaFlickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: col.height + Theme.paddingLarge
|
||||
|
||||
PullDownMenu {
|
||||
MenuItem {
|
||||
text: qsTr("Refresh")
|
||||
onClicked: api.refresh()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Data")
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("DataPage.qml"))
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Plant")
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("PlantPage.qml"))
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Settings")
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: col
|
||||
width: parent.width
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
PageHeader { title: qsTr("Setpoints") }
|
||||
|
||||
// ---- riscaldamento casa ---------------------------------------- //
|
||||
SectionHeader { text: qsTr("Heating the house") }
|
||||
|
||||
ValueRow {
|
||||
title: qsTr("Current target")
|
||||
subtitle: qsTr("What the plant is keeping now")
|
||||
value: page.fmt(page.houseTarget()) + " °C"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: casaSlider
|
||||
width: parent.width
|
||||
label: qsTr("New house target")
|
||||
minimumValue: 5
|
||||
maximumValue: 30
|
||||
stepSize: 0.5
|
||||
value: page.pendingHouse
|
||||
valueText: page.fmt(value) + " °C"
|
||||
onValueChanged: {
|
||||
// Solo un movimento vero dell'utente segna "toccato": il
|
||||
// valore che arriva dall'impianto non deve bloccarlo.
|
||||
if (Math.abs(page.pendingHouse - value) > 0.001) {
|
||||
page.houseTouched = true
|
||||
page.pendingHouse = Math.round(value * 2) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
x: Theme.horizontalPageMargin
|
||||
width: col.width - 2 * Theme.horizontalPageMargin
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Repeater {
|
||||
model: [16, 17, 18, 19, 20, 21]
|
||||
|
||||
Button {
|
||||
width: (col.width - 2 * Theme.horizontalPageMargin
|
||||
- 5 * Theme.paddingSmall) / 6
|
||||
text: modelData + "°"
|
||||
onClicked: {
|
||||
page.houseTouched = true
|
||||
page.pendingHouse = modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
text: qsTr("Set house to %1 °C").arg(page.fmt(page.pendingHouse))
|
||||
confirmText: qsTr("House temperature to %1 °C").arg(page.fmt(page.pendingHouse))
|
||||
enabled: page.houseChanged()
|
||||
onTriggered: api.sendCommand("set_heating_setpoint", page.pendingHouse)
|
||||
}
|
||||
|
||||
// ---- acqua calda sanitaria ------------------------------------- //
|
||||
SectionHeader { text: qsTr("Domestic hot water") }
|
||||
|
||||
ValueRow {
|
||||
title: qsTr("DHW target")
|
||||
subtitle: qsTr("Water now %1 °C").arg(page.fmt(page.raw("dhw_current")))
|
||||
value: page.fmt(page.waterTarget()) + " °C"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: acquaSlider
|
||||
width: parent.width
|
||||
label: qsTr("New target")
|
||||
minimumValue: 45
|
||||
maximumValue: 60
|
||||
stepSize: 1
|
||||
value: page.pendingWater
|
||||
valueText: page.fmt(value) + " °C"
|
||||
onValueChanged: {
|
||||
if (Math.abs(page.pendingWater - value) > 0.001) {
|
||||
page.waterTouched = true
|
||||
page.pendingWater = Math.round(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
x: Theme.horizontalPageMargin
|
||||
width: col.width - 2 * Theme.horizontalPageMargin
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Repeater {
|
||||
model: [45, 47, 50, 55, 60]
|
||||
|
||||
Button {
|
||||
width: (col.width - 2 * Theme.horizontalPageMargin
|
||||
- 4 * Theme.paddingSmall) / 5
|
||||
text: modelData + "°"
|
||||
onClicked: {
|
||||
page.waterTouched = true
|
||||
page.pendingWater = modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
text: qsTr("Set target %1 °C").arg(page.fmt(page.pendingWater))
|
||||
confirmText: qsTr("DHW target to %1 °C").arg(page.fmt(page.pendingWater))
|
||||
enabled: page.waterChanged()
|
||||
onTriggered: api.sendCommand("set_hot_water_target", page.pendingWater)
|
||||
}
|
||||
|
||||
// ---- boost ------------------------------------------------------ //
|
||||
SectionHeader { text: qsTr("Hot water boost") }
|
||||
|
||||
ActionButton {
|
||||
text: qsTr("Start DHW boost")
|
||||
confirmText: qsTr("Starting DHW boost")
|
||||
onTriggered: api.sendCommand("hot_water_boost_on")
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
text: qsTr("Stop DHW boost")
|
||||
confirmText: qsTr("Stopping DHW boost")
|
||||
onTriggered: api.sendCommand("hot_water_boost_off")
|
||||
}
|
||||
|
||||
Label {
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
text: qsTr("Commands go through the bridge and may take a few seconds. The status refreshes by itself afterwards.")
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Item { width: 1; height: Theme.paddingMedium }
|
||||
}
|
||||
}
|
||||
|
||||
NoticeBar { }
|
||||
}
|
||||
Reference in New Issue
Block a user