Skip to content

Commit 2b0a729

Browse files
Dennis Braunclaude
andcommitted
Fix speedtest card color: compute health from booked speed ratio
The speedtest card always showed green (health-good). Now computes health class based on download speed vs. booked speed from settings: >=80% = green, 50-80% = yellow/warning, <50% = red/critical. Upload values are colored independently. Falls back to green when no booked speed is configured. Adds booked_download / booked_upload settings (Mbps) with i18n support for EN, DE, FR, ES. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2b6ec32 commit 2b0a729

File tree

8 files changed

+67
-4
lines changed

8 files changed

+67
-4
lines changed

app/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
"bqm_url": "",
3838
"speedtest_tracker_url": "",
3939
"speedtest_tracker_token": "",
40+
"booked_download": 0,
41+
"booked_upload": 0,
4042
}
4143

4244
ENV_MAP = {
@@ -72,7 +74,7 @@
7274
"fritz_password": "modem_password",
7375
}
7476

75-
INT_KEYS = {"mqtt_port", "poll_interval", "web_port", "history_days"}
77+
INT_KEYS = {"mqtt_port", "poll_interval", "web_port", "history_days", "booked_download", "booked_upload"}
7678

7779

7880
class ConfigManager:

app/i18n/de.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@
214214
"speedtest_url_hint": "Basis-URL deiner Speedtest Tracker Instanz",
215215
"speedtest_token": "API-Token",
216216
"speedtest_token_hint": "Bearer-Token aus den Speedtest Tracker Einstellungen",
217+
"booked_download": "Gebuchter Download (Mbps)",
218+
"booked_download_hint": "Vertraglich gebuchte Download-Geschwindigkeit in Mbps fuer die Bewertung",
219+
"booked_upload": "Gebuchter Upload (Mbps)",
220+
"booked_upload_hint": "Vertraglich gebuchte Upload-Geschwindigkeit in Mbps fuer die Bewertung",
217221
"speedtest_setup_title": "Speedtest Tracker Integration",
218222
"speedtest_setup_intro": "Speedtest Tracker ist eine selbst gehostete App, die regelmaessig Ookla-Speedtests durchfuehrt. DOCSight kann deine Speedtest-Ergebnisse neben den Modemsignaldaten anzeigen.",
219223
"speedtest_setup_benefits_title": "Warum Speedtest Tracker nutzen?",

app/i18n/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@
214214
"speedtest_url_hint": "Base URL of your Speedtest Tracker instance",
215215
"speedtest_token": "API Token",
216216
"speedtest_token_hint": "Bearer token from Speedtest Tracker settings",
217+
"booked_download": "Booked Download (Mbps)",
218+
"booked_download_hint": "Contracted download speed in Mbps for health calculation",
219+
"booked_upload": "Booked Upload (Mbps)",
220+
"booked_upload_hint": "Contracted upload speed in Mbps for health calculation",
217221
"speedtest_setup_title": "Speedtest Tracker Integration",
218222
"speedtest_setup_intro": "Speedtest Tracker is a self-hosted app that runs periodic Ookla speed tests. DOCSight can display your speed test results alongside modem signal data for a complete picture of your connection.",
219223
"speedtest_setup_benefits_title": "Why use Speedtest Tracker?",

app/i18n/es.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@
209209
"speedtest_url_hint": "URL base de tu instancia de Speedtest Tracker",
210210
"speedtest_token": "Token API",
211211
"speedtest_token_hint": "Token Bearer de la configuración de Speedtest Tracker",
212+
"booked_download": "Descarga contratada (Mbps)",
213+
"booked_download_hint": "Velocidad de descarga contratada en Mbps para el calculo de estado",
214+
"booked_upload": "Subida contratada (Mbps)",
215+
"booked_upload_hint": "Velocidad de subida contratada en Mbps para el calculo de estado",
212216
"speedtest_setup_title": "Integración con Speedtest Tracker",
213217
"speedtest_setup_intro": "Speedtest Tracker es una aplicación autoalojada que ejecuta pruebas de velocidad Ookla periódicas. DOCSight puede mostrar tus resultados de speedtest junto a los datos de señal del módem.",
214218
"speedtest_setup_benefits_title": "¿Por qué usar Speedtest Tracker?",

app/i18n/fr.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@
206206
"speedtest_url_hint": "URL de base de votre instance Speedtest Tracker",
207207
"speedtest_token": "Jeton API",
208208
"speedtest_token_hint": "Jeton Bearer depuis les paramètres de Speedtest Tracker",
209+
"booked_download": "Debit descendant souscrit (Mbps)",
210+
"booked_download_hint": "Debit descendant contractuel en Mbps pour le calcul de sante",
211+
"booked_upload": "Debit montant souscrit (Mbps)",
212+
"booked_upload_hint": "Debit montant contractuel en Mbps pour le calcul de sante",
209213
"speedtest_setup_title": "Intégration Speedtest Tracker",
210214
"speedtest_setup_intro": "Speedtest Tracker est une application auto-hébergée qui effectue des tests de vitesse Ookla périodiques. DOCSight peut afficher vos résultats de speedtest à côté des données du signal modem.",
211215
"speedtest_setup_benefits_title": "Pourquoi utiliser Speedtest Tracker ?",

app/templates/index.html

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,36 @@
10091009

10101010
{# ── Card 4: Speed (Speedtest Tracker) ── #}
10111011
{% if speedtest_configured and speedtest_latest %}
1012-
<div class="metric-card health-good">
1012+
{# Compute speed health based on booked speed: >=80% good, 50-80% warn, <50% crit #}
1013+
{% if booked_download and booked_download > 0 %}
1014+
{% set dl_ratio = speedtest_latest.download_mbps / booked_download %}
1015+
{% if dl_ratio >= 0.8 %}
1016+
{% set speed_health = 'health-good' %}
1017+
{% set dl_val_class = 'val-good' %}
1018+
{% elif dl_ratio >= 0.5 %}
1019+
{% set speed_health = 'health-warn' %}
1020+
{% set dl_val_class = 'val-warn' %}
1021+
{% else %}
1022+
{% set speed_health = 'health-crit' %}
1023+
{% set dl_val_class = 'val-bad' %}
1024+
{% endif %}
1025+
{% else %}
1026+
{% set speed_health = 'health-good' %}
1027+
{% set dl_val_class = 'val-good' %}
1028+
{% endif %}
1029+
{% if booked_upload and booked_upload > 0 %}
1030+
{% set ul_ratio = speedtest_latest.upload_mbps / booked_upload %}
1031+
{% if ul_ratio >= 0.8 %}
1032+
{% set ul_val_class = 'val-good' %}
1033+
{% elif ul_ratio >= 0.5 %}
1034+
{% set ul_val_class = 'val-warn' %}
1035+
{% else %}
1036+
{% set ul_val_class = 'val-bad' %}
1037+
{% endif %}
1038+
{% else %}
1039+
{% set ul_val_class = 'val-good' %}
1040+
{% endif %}
1041+
<div class="metric-card {{ speed_health }}">
10131042
<div class="metric-card-header" onclick="toggleCard(this.parentNode)">
10141043
<span class="status-dot"></span>
10151044
<span class="card-title">&#9889; {{ t.speed }}</span>
@@ -1018,11 +1047,11 @@
10181047
<div class="metric-card-body">
10191048
<div class="metric-row">
10201049
<div class="metric-item">
1021-
<div class="metric-value val-good">{{ speedtest_latest.download_human or (speedtest_latest.download_mbps ~ ' Mbps') }}</div>
1050+
<div class="metric-value {{ dl_val_class }}">{{ speedtest_latest.download_human or (speedtest_latest.download_mbps ~ ' Mbps') }}</div>
10221051
<div class="metric-label">{{ t.download }}</div>
10231052
</div>
10241053
<div class="metric-item">
1025-
<div class="metric-value val-good">{{ speedtest_latest.upload_human or (speedtest_latest.upload_mbps ~ ' Mbps') }}</div>
1054+
<div class="metric-value {{ ul_val_class }}">{{ speedtest_latest.upload_human or (speedtest_latest.upload_mbps ~ ' Mbps') }}</div>
10261055
<div class="metric-label">{{ t.upload }}</div>
10271056
</div>
10281057
</div>

app/templates/settings.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,16 @@ <h2>{{ t.general }}</h2>
245245
<input type="password" id="speedtest_tracker_token" name="speedtest_tracker_token" value="" placeholder="{% if config.speedtest_tracker_token %}{{ t.saved_ph }}{% endif %}">
246246
<span class="hint">{{ t.speedtest_token_hint }}</span>
247247
</div>
248+
<div class="form-row">
249+
<label for="booked_download">{{ t.booked_download }}</label>
250+
<input type="number" id="booked_download" name="booked_download" value="{{ config.booked_download or '' }}" min="0" step="1" placeholder="e.g. 1000">
251+
<span class="hint">{{ t.booked_download_hint }}</span>
252+
</div>
253+
<div class="form-row">
254+
<label for="booked_upload">{{ t.booked_upload }}</label>
255+
<input type="number" id="booked_upload" name="booked_upload" value="{{ config.booked_upload or '' }}" min="0" step="1" placeholder="e.g. 50">
256+
<span class="hint">{{ t.booked_upload_hint }}</span>
257+
</div>
248258
</div>
249259
</details>
250260

app/web.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ def index():
231231
bqm_configured = _config_manager.is_bqm_configured() if _config_manager else False
232232
speedtest_configured = _config_manager.is_speedtest_configured() if _config_manager else False
233233
speedtest_latest = _state.get("speedtest_latest")
234+
booked_download = _config_manager.get("booked_download", 0) if _config_manager else 0
235+
booked_upload = _config_manager.get("booked_upload", 0) if _config_manager else 0
234236
conn_info = _state.get("connection_info") or {}
235237
dev_info = _state.get("device_info") or {}
236238

@@ -269,6 +271,8 @@ def _has_us_ofdma(analysis):
269271
bqm_configured=bqm_configured,
270272
speedtest_configured=speedtest_configured,
271273
speedtest_latest=speedtest_latest,
274+
booked_download=booked_download,
275+
booked_upload=booked_upload,
272276
uncorr_pct=_compute_uncorr_pct(snapshot),
273277
has_us_ofdma=_has_us_ofdma(snapshot),
274278
device_info=dev_info,
@@ -288,6 +292,8 @@ def _has_us_ofdma(analysis):
288292
bqm_configured=bqm_configured,
289293
speedtest_configured=speedtest_configured,
290294
speedtest_latest=speedtest_latest,
295+
booked_download=booked_download,
296+
booked_upload=booked_upload,
291297
uncorr_pct=_compute_uncorr_pct(_state["analysis"]),
292298
has_us_ofdma=_has_us_ofdma(_state["analysis"]),
293299
device_info=dev_info,

0 commit comments

Comments
 (0)