229 lines
11 KiB
Markdown
229 lines
11 KiB
Markdown
# harbour-aira — versione italiana
|
|
|
|
*English version: [README.md](README.md)*
|
|
|
|
---
|
|
|
|
# harbour-aira
|
|
|
|
App nativa Sailfish OS per una pompa di calore **Aira Home**: mostra lo stato
|
|
dell'impianto e invia i comandi dell'acqua calda sanitaria e del riscaldamento
|
|
(temperatura obiettivo della casa, per zona).
|
|
|
|
L'interfaccia è in **inglese e italiano**: di serie segue la lingua del telefono
|
|
e ripiega sull'inglese; la si può scegliere anche nelle impostazioni dell'app.
|
|
|
|
## Cosa mostra
|
|
|
|
- **Home**, una schermata da guardare: pallino colorato con lo stato in una riga
|
|
("Tutto regolare", "Sta scaldando l'acqua"), l'ora dell'ultimo aggiornamento, le
|
|
due letture che contano (casa e acqua calda, ognuna con il suo obiettivo)
|
|
affiancate e **toccabili**, e tre azioni rapide: boost, assenza, comandi
|
|
impianto. Sta in una schermata, senza scorrere: i comandi hanno pagine loro
|
|
- **Regolazioni**: obiettivo casa e obiettivo acqua calda, ognuno con il valore
|
|
che l'impianto sta tenendo adesso, lo slider (la proposta: il valore vero non si
|
|
muove), una fila di valori rapidi per le dita fredde e il pulsante di conferma,
|
|
che si accende solo se c'è davvero qualcosa da cambiare. Il boost sta qui
|
|
- **Dati**: calore prodotto, elettricità usata, efficienza (COP) di acqua calda e
|
|
riscaldamento, risparmio in bolletta, CO₂ evitata e risparmio Smart Tariff
|
|
Control, mese per mese. Sono i numeri che Aira calcola nel cloud, gli stessi
|
|
della scheda *Dati* dell'app ufficiale
|
|
- **Impianto**: stato (connessione, modalità, assenza/notte/riscaldamento
|
|
forzato, modalità manuale, sbrinamento, luci di firma, stato pompa, modi
|
|
consentiti, temperature esterna e interna, zone, ultima lettura), accessori (il
|
|
termostato a parete con temperatura, umidità, segnale, batteria), versioni del
|
|
software, numero di errori e verifica impianto. Qui sta anche la frase di stato
|
|
estesa ("Relax: la pompa di calore funziona regolarmente")
|
|
- **Comandi impianto**: quattro interruttori (assenza, riscaldamento forzato,
|
|
riscaldamento, acqua calda attiva) che mostrano lo stato e lo cambiano in un
|
|
tocco, più i pulsanti per quello che uno stato non ce l'ha: ciclo legionella e
|
|
night mode per un'ora. Gli interruttori seguono l'impianto, non lo anticipano
|
|
- **Copertina** con la temperatura della casa
|
|
- Indirizzo e token del bridge stanno nelle impostazioni dell'app (QSettings),
|
|
mai nel binario
|
|
|
|

|
|
|
|
Anteprime del layout (valori veri dell'impianto, **non** screenshot — vedi
|
|
*Stato*). Queste sono in italiano; quelle in inglese stanno in
|
|
`docs/anteprima/`:
|
|
|
|
| Home | Regolazioni | Dati |
|
|
|---|---|---|
|
|
|  |  |  |
|
|
|
|
| Impianto | Comandi impianto | Impostazioni | Copertina |
|
|
|---|---|---|---|
|
|
|  |  |  |  |
|
|
|
|
## La lingua dell'interfaccia
|
|
|
|
L'inglese è la **lingua sorgente** delle stringhe (sta direttamente nel codice);
|
|
l'italiano sta nel catalogo `translations/harbour-aira-it.ts`, che `lupdate`
|
|
aggiorna e `lrelease` compila in build.
|
|
|
|
La scelta fatta nelle impostazioni è salvata in `QSettings` con il codice della
|
|
lingua; vuoto (o lingua assente) significa **lingua di sistema**, con ripiego
|
|
sull'inglese quando non esiste il catalogo corrispondente.
|
|
|
|
Qt 5.6 non ha `QQmlEngine::retranslate()` (arriva con Qt 5.10): installare un
|
|
traduttore non basta a ritradurre quello che è già a schermo. L'app quindi, al
|
|
cambio di lingua, **ricarica la radice QML** — la scelta ha effetto subito, al
|
|
prezzo di tornare alla pagina iniziale.
|
|
|
|
Anche i numeri seguono la lingua: le temperature passano da `QLocale`, quindi in
|
|
italiano si scrive `23,0 °C` e in inglese `23.0 °C`.
|
|
|
|
## Perché c'è un bridge (e non una chiamata diretta al cloud)
|
|
|
|
Il cloud Aira espone **gRPC su HTTP/2**. Qt 5.6 — il toolkit su cui gira ogni
|
|
app Sailfish — **non ha HTTP/2**, quindi un client nativo non può parlarci
|
|
direttamente. Le alternative (impacchettare `grpcio` per aarch64 con
|
|
PyOtherSide, oppure riscrivere Cognito + gRPC in C++) sono fragili e costose.
|
|
|
|
Quindi la logica resta **sul server**, dove Python e i token già funzionano, e
|
|
l'app è un client sottile che parla HTTP/1.1 + JSON. Effetto collaterale
|
|
gradito: credenziali e token non stanno mai sul telefono.
|
|
|
|
```
|
|
Jolla (QML/C++ Qt 5.6) --HTTP/1.1 + JSON--> bridge (Linux in LAN) --gRPC--> cloud Aira
|
|
bridge/aira_bridge.py
|
|
```
|
|
|
|
## Il bridge
|
|
|
|
Il codice sta in [`bridge/`](bridge/): istruzioni complete in
|
|
[bridge/README.md](bridge/README.md) (in inglese, perché è la parte che serve a
|
|
chi prova l'app su un altro impianto).
|
|
|
|
```sh
|
|
cd bridge
|
|
python3 -m venv .venv && . .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
export AIRA_CONFIG_DIR="$HOME/.config/aira"
|
|
python setup_creds.py # email e password Aira: salvate in un file 600
|
|
python aira_bridge.py --port 8790
|
|
```
|
|
|
|
Al primo avvio il bridge genera un token in `$AIRA_CONFIG_DIR/aira_bridge.json`
|
|
(permessi 600): è il valore da incollare nelle impostazioni dell'app.
|
|
API completa in [docs/PROTOCOL.md](docs/PROTOCOL.md).
|
|
|
|
## Impostazioni nell'app
|
|
|
|
Indirizzo e token si configurano nella pagina **Impostazioni** (QSettings in
|
|
`~/.config/harbour/aira/aira.conf`): niente dati personali nel binario.
|
|
|
|
## Build
|
|
|
|
Servono l'SDK Sailfish (`sfdk`) e un target aarch64 (Jolla Phone 2026):
|
|
|
|
```sh
|
|
sfdk target install SailfishOS-5.0.0.62-aarch64
|
|
sfdk target use SailfishOS-5.0.0.62-aarch64
|
|
sfdk build # RPM in RPMS/
|
|
sfdk deploy # sul dispositivo collegato
|
|
```
|
|
|
|
Sorgenti dal tarball (`harbour-aira-<versione>.tar.gz`, se ne hai ricevuto uno):
|
|
estrarre in una cartella **nuova** (mai sopra una estrazione precedente: i
|
|
Makefile restano stale), oppure clonare direttamente questo repository.
|
|
Il log dell'app inizia con `harbour-aira v<versione> build <data>`: serve a
|
|
distinguere una build nuova da una stale senza indovinare.
|
|
|
|
### Verifica locale, senza SDK
|
|
|
|
```sh
|
|
cd tests && mkdir -p build && cd build
|
|
~/Qt/5.15.2/gcc_64/bin/qmake ../core_test.pro && make && ./core_test
|
|
```
|
|
|
|
Copre la logica pura (`src/airajson.cpp`): normalizzazione dell'indirizzo,
|
|
lettura del riassunto e delle statistiche, etichette di stato, corpo dei comandi,
|
|
messaggi d'errore e la formattazione di numeri, importi e mesi della pagina Dati.
|
|
**La UI Silica si verifica solo sul dispositivo.**
|
|
|
|
C'è poi un controllo di **contratto fra bridge e interfaccia**: confronta le
|
|
chiavi che i QML leggono con quelle che il bridge restituisce davvero (26 da
|
|
`/summary`, 15 da `/stats`). Serve il bridge in esecuzione, e nasce dal fatto che
|
|
la UI qui non si può eseguire: un refuso in una chiave si vedrebbe sul telefono
|
|
come un "—" perenne, senza niente nel log.
|
|
|
|
```sh
|
|
python3 tests/ui_contract_check.py # bridge su 127.0.0.1:8790
|
|
python3 tests/ui_contract_check.py http://192.168.3.21:8790
|
|
```
|
|
|
|
## Stato
|
|
|
|
- **79/79** verifiche del nucleo, compilazione senza warning (comprese le frasi
|
|
di stato, breve ed estesa: quello che la Home dice dell'impianto è verificato
|
|
senza telefono)
|
|
- **48/48** verifiche offline del bridge (`bridge/test_bridge_commands.py`),
|
|
comprese le conversioni Wh→kWh e degli importi delle statistiche
|
|
- **190/190** stringhe tradotte nel catalogo italiano: il test carica il `.qm`
|
|
compilato come fa `main.cpp` e verifica che in inglese l'etichetta di stato sia
|
|
la sorgente e in italiano quella tradotta, e che togliendo il catalogo si torni
|
|
all'inglese
|
|
- numeri, importi e nomi dei mesi formattati con `QLocale`: separatore decimale e
|
|
posizione del simbolo di valuta seguono la lingua (verificato per entrambe)
|
|
- `qmllint` pulito su tutti i QML (valida solo la sintassi: senza il modulo
|
|
Silica una proprietà inesistente passa in silenzio)
|
|
- provata dal vivo in **sola lettura** su un impianto Aira Home, statistiche
|
|
comprese: coincidono con quelle mostrate dall'app ufficiale per lo stesso
|
|
periodo (calore prodotto 70,8 kWh, elettricità 29,3 kWh, COP acqua calda 4,42,
|
|
risparmio Smart Tariff Control 2,71 €)
|
|
- **l'app non è ancora stata compilata né eseguita su un telefono**: le immagini
|
|
in `docs/anteprima/` sono anteprime di layout costruite con i valori veri
|
|
dell'impianto, non screenshot
|
|
|
|
Non c'è ancora la UI per il raffrescamento (il bridge sa farlo), né orari e
|
|
curve; le versioni del software si vedono in sola lettura. La pagina Dati dipende
|
|
dal servizio statistiche di Aira: su un impianto appena installato qualche mese
|
|
non ha ancora dati e l'app scrive *nessun dato* invece del numero. Non è nella
|
|
Jolla Store: è un client non ufficiale che parla con le API Aira usando il proprio
|
|
account.
|
|
|
|
## Struttura
|
|
|
|
```
|
|
harbour-aira.pro progetto qmake (icona, qml, docs)
|
|
src/airajson.{h,cpp} logica pura, testabile senza SDK
|
|
src/apiclient.{h,cpp} QNetworkAccessManager + watchdog di timeout
|
|
src/settings.{h,cpp} QSettings su AppConfigLocation (sandbox SailJail)
|
|
src/translator.{h,cpp} lingua dell'interfaccia: locale di sistema, ripiego
|
|
sull'inglese, ricarica della UI al cambio
|
|
src/main.cpp context properties: appSettings, api, translator
|
|
qml/harbour-aira.qml ApplicationWindow + copertina
|
|
qml/pages/MainPage.qml home: stato in una riga, due letture, azioni rapide
|
|
qml/pages/SetpointsPage.qml obiettivi casa e acqua, valori rapidi, boost
|
|
qml/pages/DataPage.qml energia, efficienza e risparmi
|
|
qml/pages/PlantPage.qml stato, accessori, versioni, errori, diagnostica
|
|
qml/pages/CommandsPage.qml i comandi impianto, stato negli interruttori
|
|
qml/pages/SettingsPage.qml
|
|
qml/components/InfoRow.qml etichetta a sinistra, valore a destra
|
|
qml/components/ValueRow.qml titolo e sottotitolo a sinistra, valore grande a destra
|
|
qml/components/ReadingCell.qml lettura toccabile: titolo, valore grande, barra
|
|
qml/components/NoticeBar.qml messaggi dei comandi, ancorati in fondo
|
|
qml/components/ActionButton.qml pulsante di comando, con conferma opzionale
|
|
tests/core_test.cpp verifiche del nucleo (headless)
|
|
tests/ui_contract_check.py chiavi dei QML contro quelle del bridge (bridge attivo)
|
|
bridge/aira_bridge.py servizio HTTP/1.1 + JSON verso il cloud (gRPC)
|
|
bridge/setup_creds.py salva le credenziali Aira (file 600)
|
|
bridge/aira_probe.py sonda di sola lettura: login + stato impianto
|
|
bridge/aira_stats_probe.py sonda di sola lettura delle statistiche del cloud
|
|
bridge/test_bridge_commands.py verifiche offline dei comandi e delle statistiche (48 controlli)
|
|
bridge/harbour-aira-bridge.service unit systemd utente
|
|
bridge/README.md istruzioni di installazione del bridge (inglese)
|
|
docs/PIANO.md piano di progetto e scelte
|
|
docs/PROTOCOL.md API del bridge
|
|
docs/UX-STUDIO.md studio UX e cosa è cambiato nella 0.6.0
|
|
docs/ux/ schemi dello studio UX
|
|
translations/ harbour-aira-it.ts (l'inglese è la lingua sorgente)
|
|
docs/anteprima/ anteprime di layout in inglese (in italiano: it/)
|
|
```
|
|
|
|
## Licenza
|
|
|
|
MIT.
|