Skip to content

Commit c978828

Browse files
author
Dennis Braun
committed
Adjust SNR thresholds to match Vodafone VFKD guidelines
Warning: 30 -> 33 dB (VFKD regelkonform > 33.1 dB for 256QAM) Critical: 25 -> 29 dB (VFKD sofortige Beseitigung < 29 dB)
1 parent 5f13d6b commit c978828

File tree

5 files changed

+20
-19
lines changed

5 files changed

+20
-19
lines changed

app/analyzer.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
US_POWER_WARN = 50.0
1414
US_POWER_CRIT = 54.0
1515

16-
# SNR / MER (dB): good >30, marginal 25-30, bad <25
17-
SNR_WARN = 30.0
18-
SNR_CRIT = 25.0
16+
# SNR / MER (dB): good >33, marginal 29-33, bad <29
17+
# Based on Vodafone VFKD guidelines: 256QAM regelkonform > 33.1 dB
18+
SNR_WARN = 33.0
19+
SNR_CRIT = 29.0
1920

2021
# Uncorrectable errors threshold
2122
UNCORR_ERRORS_CRIT = 10000

app/event_detector.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
# Thresholds for event detection
99
POWER_SHIFT_THRESHOLD = 2.0 # dBmV shift to trigger power_change
10-
SNR_WARN_THRESHOLD = 30.0
11-
SNR_CRIT_THRESHOLD = 25.0
10+
SNR_WARN_THRESHOLD = 33.0
11+
SNR_CRIT_THRESHOLD = 29.0
1212
UNCORR_SPIKE_THRESHOLD = 1000
1313

1414
# QAM hierarchy: higher value = better modulation

app/templates/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@
10121012
<div class="range-zone range-good" style="width:50%"></div>
10131013
<div class="range-marker val-{{ snr_health }}" style="left:{{ snr_marker }}%"></div>
10141014
</div>
1015-
<div class="range-labels"><span>15</span><span>25</span><span>30</span><span>45 dB</span></div>
1015+
<div class="range-labels"><span>15</span><span>29</span><span>33</span><span>45 dB</span></div>
10161016
</div>
10171017
</div>
10181018
</div>
@@ -1021,7 +1021,7 @@
10211021
<tr><td>{{ t.card_power_range }}</td><td>{{ s.ds_power_min }} ... {{ s.ds_power_max }} dBmV</td></tr>
10221022
<tr><td>SNR {{ t.card_power_range }}</td><td>{{ s.ds_snr_min }} ... {{ s.ds_snr_avg }} dB</td></tr>
10231023
<tr><td>{{ t.channels }}</td><td>{{ s.ds_total }} {{ t.downstream|lower }}</td></tr>
1024-
<tr><td>{{ t.card_ideal_range }}</td><td>-7...+7 dBmV / SNR &gt;30 dB</td></tr>
1024+
<tr><td>{{ t.card_ideal_range }}</td><td>-7...+7 dBmV / SNR &gt;33 dB</td></tr>
10251025
</table>
10261026
</div>
10271027
</div>
@@ -1190,7 +1190,7 @@ <h2 class="section-title">{{ t.downstream }} ({{ ds|length }} {{ t.channels }})<
11901190
<td data-sort="{{ ch.channel_id }}">{{ ch.channel_id }}</td>
11911191
<td>{{ ch.frequency }}</td>
11921192
<td data-sort="{{ ch.power if ch.power is not none else 0 }}" class="{% if ch.power is not none %}{% if ch.power|abs > 10 %}val-crit{% elif ch.power|abs > 7 %}val-warn{% else %}val-good{% endif %}{% endif %}">{{ ch.power }}</td>
1193-
<td data-sort="{{ ch.snr if ch.snr is not none else 0 }}" class="{% if ch.snr is not none %}{% if ch.snr < 25 %}val-crit{% elif ch.snr < 30 %}val-warn{% else %}val-good{% endif %}{% endif %}">{{ ch.snr if ch.snr is not none else "-" }}</td>
1193+
<td data-sort="{{ ch.snr if ch.snr is not none else 0 }}" class="{% if ch.snr is not none %}{% if ch.snr < 29 %}val-crit{% elif ch.snr < 33 %}val-warn{% else %}val-good{% endif %}{% endif %}">{{ ch.snr if ch.snr is not none else "-" }}</td>
11941194
<td>{{ ch.modulation }}</td>
11951195
<td data-sort="{{ ch.correctable_errors }}">{{ ch.correctable_errors|fmt_k }}</td>
11961196
<td data-sort="{{ ch.uncorrectable_errors }}">{{ ch.uncorrectable_errors|fmt_k }}</td>
@@ -2113,9 +2113,9 @@ <h2>{{ t.export_title }}</h2>
21132113
{yMin: -12, yMax: 12}
21142114
];
21152115
var DS_SNR_ZONES = [
2116-
{min: 15, max: 30, color: "rgba(244,67,54,0.35)"},
2117-
{min: 30, max: 35, color: "rgba(255,152,0,0.30)"},
2118-
{min: 35, max: 50, color: "rgba(76,175,80,0.25)"},
2116+
{min: 15, max: 29, color: "rgba(244,67,54,0.35)"},
2117+
{min: 29, max: 33, color: "rgba(255,152,0,0.30)"},
2118+
{min: 33, max: 50, color: "rgba(76,175,80,0.25)"},
21192119
{yMin: 25, yMax: 45}
21202120
];
21212121
var US_POWER_ZONES = [

tests/test_analyzer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ def test_us_power_warning(self):
119119
assert "us_power_warn" in result["summary"]["health_issues"]
120120

121121
def test_snr_warning(self):
122-
"""SNR 28 dB is marginal (between 25-30)."""
122+
"""SNR 31 dB is marginal (between 29-33)."""
123123
data = _make_data(
124-
ds30=[_make_ds30(1, power=2.0, mse="-28")],
124+
ds30=[_make_ds30(1, power=2.0, mse="-31")],
125125
us30=[_make_us30(1, power=42.0)],
126126
)
127127
result = analyze(data)
@@ -163,9 +163,9 @@ def test_us_power_critical(self):
163163
assert "us_power_critical" in result["summary"]["health_issues"]
164164

165165
def test_snr_critical(self):
166-
"""SNR 22 dB is critical (<25)."""
166+
"""SNR 27 dB is critical (<29)."""
167167
data = _make_data(
168-
ds30=[_make_ds30(1, power=2.0, mse="-22")],
168+
ds30=[_make_ds30(1, power=2.0, mse="-27")],
169169
us30=[_make_us30(1, power=42.0)],
170170
)
171171
result = analyze(data)

tests/test_events.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,15 @@ def test_power_no_event_small_shift(self, detector):
208208
assert len(power_events) == 0
209209

210210
def test_snr_drop_warning(self, detector):
211-
detector.check(_make_analysis(ds_snr_min=32.0))
212-
events = detector.check(_make_analysis(ds_snr_min=28.0))
211+
detector.check(_make_analysis(ds_snr_min=35.0))
212+
events = detector.check(_make_analysis(ds_snr_min=31.0))
213213
snr_events = [e for e in events if e["event_type"] == "snr_change"]
214214
assert len(snr_events) == 1
215215
assert snr_events[0]["severity"] == "warning"
216216

217217
def test_snr_drop_critical(self, detector):
218-
detector.check(_make_analysis(ds_snr_min=28.0))
219-
events = detector.check(_make_analysis(ds_snr_min=23.0))
218+
detector.check(_make_analysis(ds_snr_min=31.0))
219+
events = detector.check(_make_analysis(ds_snr_min=27.0))
220220
snr_events = [e for e in events if e["event_type"] == "snr_change"]
221221
assert len(snr_events) == 1
222222
assert snr_events[0]["severity"] == "critical"

0 commit comments

Comments
 (0)