#include "airajson.h" #include #include #include #include #include #include #include namespace AiraJson { QString normalizeBaseUrl(const QString &raw) { QString s = raw.trimmed(); if (s.isEmpty()) return QString(); if (!s.startsWith(QLatin1String("http://")) && !s.startsWith(QLatin1String("https://"))) s.prepend(QLatin1String("http://")); while (s.endsWith(QLatin1Char('/'))) s.chop(1); return s; } QVariantMap parseSummary(const QByteArray &body, bool *ok) { if (ok) *ok = false; QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(body, &err); if (err.error != QJsonParseError::NoError || !doc.isObject()) return QVariantMap(); const QJsonObject root = doc.object(); if (root.value(QStringLiteral("ok")).toBool() == false) return QVariantMap(); const QJsonObject summary = root.value(QStringLiteral("summary")).toObject(); if (summary.isEmpty()) return QVariantMap(); if (ok) *ok = true; return summary.toVariantMap(); } QVariantMap parseStats(const QByteArray &body, bool *ok) { if (ok) *ok = false; QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(body, &err); if (err.error != QJsonParseError::NoError || !doc.isObject()) return QVariantMap(); const QJsonObject root = doc.object(); if (root.value(QStringLiteral("ok")).toBool() == false) return QVariantMap(); const QJsonObject stats = root.value(QStringLiteral("stats")).toObject(); if (stats.isEmpty()) return QVariantMap(); if (ok) *ok = true; return stats.toVariantMap(); } QString modeLabel(const QString &operatingStatus) { const QString s = operatingStatus; if (s == QLatin1String("OPERATING_STATUS_AUTO")) return QCoreApplication::translate("AiraJson", "Automatic"); if (s == QLatin1String("OPERATING_STATUS_HEATING")) return QCoreApplication::translate("AiraJson", "Heating"); if (s == QLatin1String("OPERATING_STATUS_COOLING")) return QCoreApplication::translate("AiraJson", "Cooling"); if (s == QLatin1String("OPERATING_STATUS_HOT_WATER")) return QCoreApplication::translate("AiraJson", "Hot water"); if (s == QLatin1String("OPERATING_STATUS_STANDBY")) return QCoreApplication::translate("AiraJson", "Standby"); if (s == QLatin1String("OPERATING_STATUS_OFF")) return QCoreApplication::translate("AiraJson", "Off"); // Stato della pompa per zona (state.zoneN_mode). if (s == QLatin1String("PUMP_MODE_STATE_HEATING")) return QCoreApplication::translate("AiraJson", "Heating"); if (s == QLatin1String("PUMP_MODE_STATE_COOLING")) return QCoreApplication::translate("AiraJson", "Cooling"); if (s == QLatin1String("PUMP_MODE_STATE_HOT_WATER")) return QCoreApplication::translate("AiraJson", "Hot water"); if (s == QLatin1String("PUMP_MODE_STATE_IDLE")) return QCoreApplication::translate("AiraJson", "Idle"); if (s == QLatin1String("PUMP_MODE_STATE_STANDBY")) return QCoreApplication::translate("AiraJson", "Standby"); if (s == QLatin1String("PUMP_MODE_STATE_OFF")) return QCoreApplication::translate("AiraJson", "Off"); // Stato operativo della pompa (state.pump_active_state). if (s == QLatin1String("PUMP_ACTIVE_STATE_IDLE")) return QCoreApplication::translate("AiraJson", "Stopped"); if (s == QLatin1String("PUMP_ACTIVE_STATE_RUNNING")) return QCoreApplication::translate("AiraJson", "Running"); if (s.isEmpty()) return QStringLiteral("—"); // Sconosciuto: togliamo il prefisso e mostriamo il resto, minuscolo. QString rest = s; rest.remove(QLatin1String("OPERATING_STATUS_")); rest.remove(QLatin1String("PUMP_MODE_STATE_")); rest.remove(QLatin1String("PUMP_ACTIVE_STATE_")); rest.remove(QLatin1String("POWER_PREFERENCE_")); return rest.toLower(); } QString formatValue(const QVariant &value) { // Un decimale: e' il caso delle temperature ("51,0"). return formatNumber(value, 1); } QString formatNumber(const QVariant &value, int decimals) { if (!value.isValid() || value.isNull()) return QStringLiteral("—"); bool isNumber = false; const double d = value.toDouble(&isNumber); if (!isNumber) return QStringLiteral("—"); // QLocale() = locale predefinito, che translator.cpp allinea alla lingua // dell'app: separatore decimale col punto in inglese, con la virgola in // italiano (QString::number darebbe sempre il punto). return QLocale().toString(d, 'f', decimals < 0 ? 0 : decimals); } QString formatMoney(const QVariant &value, const QString ¤cyCode) { if (!value.isValid() || value.isNull()) return QStringLiteral("—"); bool isNumber = false; const double d = value.toDouble(&isNumber); if (!isNumber) return QStringLiteral("—"); // Posizione del simbolo e separatori seguono la lingua dell'app, non la // valuta: "21,78 €" in italiano, "€21.78" in inglese. const QString code = currencyCode.trimmed().toUpper(); QString symbol; if (code == QLatin1String("EUR")) symbol = QString::fromUtf8("€"); else if (!code.isEmpty()) symbol = code; // valuta senza simbolo noto: codice ISO return QLocale().toCurrencyString(d, symbol); } QString monthLabel(const QString &yearMonth) { // "2026-10" -> "ottobre 2026": il nome del mese segue la lingua dell'app. const QStringList parti = yearMonth.split(QLatin1Char('-')); if (parti.size() != 2) return QString(); bool annoOk = false; bool meseOk = false; const int anno = parti.at(0).toInt(&annoOk); const int mese = parti.at(1).toInt(&meseOk); if (!annoOk || !meseOk || mese < 1 || mese > 12) return QString(); return QStringLiteral("%1 %2").arg(QLocale().monthName(mese, QLocale::LongFormat)).arg(anno); } QByteArray commandPayload(const QString &id, const QVariant &value) { QJsonObject o; o.insert(QStringLiteral("id"), id); if (value.isValid() && !value.isNull()) o.insert(QStringLiteral("value"), QJsonValue::fromVariant(value)); return QJsonDocument(o).toJson(QJsonDocument::Compact); } QString errorMessage(const QByteArray &body, int httpStatus) { QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(body, &err); if (err.error == QJsonParseError::NoError && doc.isObject()) { const QString msg = doc.object().value(QStringLiteral("error")).toString(); if (!msg.isEmpty()) return msg; } if (httpStatus == 0) return QCoreApplication::translate("AiraJson", "server unreachable"); return QCoreApplication::translate("AiraJson", "HTTP error %1").arg(httpStatus); } } // namespace AiraJson