Le chiavi lette dalle pagine vengono confrontate con quelle che /summary e /stats restituiscono davvero: la UI non si puo' eseguire senza il kit Silica, quindi un refuso resterebbe invisibile fino al primo build sul telefono.
9.9 KiB
harbour-aira — versione italiana
English version: 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, ordinata come l'app ufficiale: temperatura esterna e in casa / assente in alto, una frase di stato in chiaro ("Relax: la pompa di calore funziona regolarmente"), poi la scheda dell'impianto con le due letture che contano (temperatura stanza e acqua calda, ognuna con il suo obiettivo). Toccando la scheda si apre la pagina dell'impianto. Sotto, i comandi: obiettivo della casa con slider 5–30 °C (passi da 0,5 °C) e conferma prima dell'invio, obiettivo ACS (45–60 °C) e i pulsanti del boost
- 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, temperature esterna e interna, zone, ultima lettura), accessori (il termostato a parete con temperatura, umidità, segnale, batteria), versioni del software e numero di errori
- Altri comandi: assenza, night mode per un'ora, riscaldamento forzato, funzione riscaldamento on/off, ciclo legionella, ACS on/off e verifica impianto, con lo stato attuale in cima
- 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 | Dati | Impianto |
|---|---|---|
![]() |
![]() |
![]() |
| Altri comandi | 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/: istruzioni complete in
bridge/README.md (in inglese, perché è la parte che serve a
chi prova l'app su un altro impianto).
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.
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):
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
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.
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
- 61/61 verifiche del nucleo, compilazione senza warning
- 48/48 verifiche offline del bridge (
bridge/test_bridge_commands.py), comprese le conversioni Wh→kWh e degli importi delle statistiche - 170/170 stringhe tradotte nel catalogo italiano: il test carica il
.qmcompilato come famain.cppe 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) qmllintpulito 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, scheda impianto, riscaldamento e acqua
qml/pages/DataPage.qml energia, efficienza e risparmi
qml/pages/PlantPage.qml stato, accessori, versioni, errori
qml/pages/CommandsPage.qml gli altri comandi, con lo stato attuale in cima
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/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
translations/ harbour-aira-it.ts (l'inglese è la lingua sorgente)
docs/anteprima/ anteprime di layout in inglese (in italiano: it/)
Licenza
MIT.





