0.5.0: riordino come l'app ufficiale (home, Dati, Impianto)

- home: temperatura esterna e in casa/assente in alto, messaggio di stato,
  scheda impianto con temperatura stanza e acqua calda; comandi sotto
- pagina Dati: calore prodotto, elettricita' usata, COP acqua calda e
  riscaldamento, risparmio, CO2 evitata, Smart Tariff Control (mese per mese)
- pagina Impianto: stato, termostato a parete, versioni software, errori
- bridge 0.4.0: rotta /stats (servizio statistiche del cloud) e blocco
  dispositivo in /summary (ID breve, versioni, termostato)
- C++: parseStats, formatNumber, formatMoney, monthLabel (separatore e
  valuta secondo la lingua); 61/61 verifiche del nucleo
- anteprime aggiornate (dati, impianto) in inglese e italiano
This commit is contained in:
2026-10-10 08:59:03 +02:00
parent ec7333a185
commit 4f279a18b0
30 changed files with 2355 additions and 353 deletions
+58
View File
@@ -157,6 +157,64 @@ QString ApiClient::formatValue(const QVariant &value) const
return AiraJson::formatValue(value);
}
QString ApiClient::formatNumber(const QVariant &value, int decimals) const
{
return AiraJson::formatNumber(value, decimals);
}
QString ApiClient::formatMoney(const QVariant &value, const QString &currencyCode) const
{
return AiraJson::formatMoney(value, currencyCode);
}
QString ApiClient::monthLabel(const QString &yearMonth) const
{
return AiraJson::monthLabel(yearMonth);
}
void ApiClient::refreshStats()
{
if (!configured()) {
emit statsRefreshed(false, tr("Set the bridge address and token"));
return;
}
// Il bridge tiene le statistiche in cache (10 minuti): la prima lettura
// interroga il cloud, quindi il tempo massimo e' piu' largo del solito.
QNetworkReply *reply = send("GET", QStringLiteral("/stats"), QByteArray(), 60);
if (!reply) {
emit statsRefreshed(false, tr("Bridge not configured"));
return;
}
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
reply->deleteLater();
const int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
const QByteArray body = reply->readAll();
if (reply->error() != QNetworkReply::NoError || status != 200) {
const QString msg = (reply->error() == QNetworkReply::OperationCanceledError)
? tr("Timeout: no statistics")
: AiraJson::errorMessage(body, status);
qWarning() << "[api] statistiche non riuscite:" << status << msg;
emit statsRefreshed(false, msg);
return;
}
bool ok = false;
const QVariantMap stats = AiraJson::parseStats(body, &ok);
if (!ok) {
qWarning() << "[api] statistiche non interpretabili";
emit statsRefreshed(false, tr("Unreadable response from the bridge"));
return;
}
m_stats = stats;
emit statsChanged(stats);
emit statsRefreshed(true, QString());
});
}
void ApiClient::sendCommand(const QString &id, const QVariant &value)
{
if (!configured()) {