Serial monitor redesign: Test box button, InfluxDB row in the checklist
- Test box: restart + start-up capture + online InfluxDB check (data newer than the restart), with a status strip; checklist and findings are the main view, live log / guided troubleshooting / box details are tabs, rarely used actions in a More menu - light palette on all systems (macOS dark mode made the colours unreadable) - new rule influx.invalid_value: -inf from a silent microphone makes InfluxDB reject every upload (HTTP 400); guide end names it - exclusive serial port on macOS/Linux: two tool windows no longer split the log between them - InfluxDB check: `since` filter, neutral wording when nothing new arrives Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
66cb804102
commit
bb933ff748
13 files changed
+422
-83
No files matched your search
@@ -334,3 +334,15 @@ def test_quick_check_green_ends_with_influx_check(influx_rig):
|
||||
runner.answer("GREEN")
|
||||
runner.answer("0") # heartbeat blinking
|
||||
assert runner.guide.id == "influx" and actions == ["influx"]
|
||||
|
||||
|
||||
def test_influx_rejected_upload_is_named(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
board(*BOOT, "microphone,device=A4CB8FC9473C dbfs=-inf,db=-inf 1790805114000000000",
|
||||
"io,device=A4CB8FC9473C dbfs=-inf,db=-inf 1790805215000000000") # USB dropped characters
|
||||
assert sum(k.startswith("influx.invalid_value") for k in engine.findings) == 1
|
||||
runner.start("influx")
|
||||
runner.influx_result("silent", "No new data in InfluxDB since the test started")
|
||||
clock.t += 300
|
||||
runner.tick()
|
||||
assert runner.end.id == "invalid_value"
|
||||
+13
-1
@@ -67,7 +67,7 @@ def test_offline_box_whose_sensors_stopped_before_status():
|
||||
latest = {"device_status": _t(29 * 60), "microphone": _t(29 * 60),
|
||||
"as7341_adc": _t(21 * 1440), "bme688": _t(21 * 1440), "sen66": _t(21 * 1440)}
|
||||
c = influx.classify(latest, NOW)
|
||||
assert c.outcome == influx.SENSORS_MISSING and "offline now" in c.summary
|
||||
assert c.outcome == influx.SENSORS_MISSING and "Nothing new" in c.summary
|
||||
assert any("stopped" in d for d in c.details)
|
||||
assert any("21 days ago" in d for d in c.details)
|
||||
|
||||
@@ -140,3 +140,15 @@ def test_check_device_sends_token_header_and_normalized_mac(monkeypatch):
|
||||
assert req.get_header("Authorization") == "Token tok"
|
||||
assert "tok" not in req.full_url and req.full_url.endswith("/api/v2/query?org=kota")
|
||||
assert b'"A4CB8FC9473C"' in req.data
|
||||
|
||||
|
||||
def test_since_ignores_data_from_before_the_test():
|
||||
# healthy a few minutes ago, but nothing since the box was restarted by the test
|
||||
latest = {"device_status": _t(5), "microphone": _t(5), "as7341_adc": _t(5), "bme688": _t(5), "sen66": _t(5)}
|
||||
assert influx.classify(latest, NOW).outcome == influx.OK
|
||||
c = influx.classify(latest, NOW, since=_t(2))
|
||||
assert c.outcome == influx.SILENT and "since the test started" in c.summary
|
||||
latest.update(device_status=_t(0), microphone=_t(0))
|
||||
assert influx.classify(latest, NOW, since=_t(2)).outcome == influx.SENSORS_MISSING
|
||||
latest.update(as7341_adc=_t(0), bme688=_t(0), sen66=_t(2.5)) # within the clock slack
|
||||
assert influx.classify(latest, NOW, since=_t(2)).outcome == influx.OK
|
||||
@@ -19,3 +19,34 @@ def test_main_window_builds_with_all_tabs():
|
||||
assert "InfluxDB access..." in settings
|
||||
w.serial_tab.shutdown()
|
||||
app.processEvents()
|
||||
|
||||
|
||||
def test_serial_tab_checklist_and_test_strip():
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
from kota_tech.core.logline import parse_line
|
||||
from kota_tech.service import influx
|
||||
from kota_tech.ui.main_window import INFLUX_ROW, MainWindow
|
||||
app = QApplication.instance() or QApplication([])
|
||||
w = MainWindow()
|
||||
st = w.serial_tab
|
||||
assert st.test_btn.text().endswith("Test box")
|
||||
assert [st.side_tabs.tabText(i) for i in range(st.side_tabs.count())] == \
|
||||
["Live log", "Guided troubleshooting", "Box details"]
|
||||
st.influx_config = lambda: None # no token (never touch real settings)
|
||||
rows = st._cloud_rows()
|
||||
assert rows[0][0] == "off" and "not set up" in rows[0][1]
|
||||
st.influx_config = lambda: influx.InfluxConfig("t") # pretend access is set up
|
||||
assert st._cloud_rows()[0] == ("pending", f"{INFLUX_ROW} - press Test box")
|
||||
st._on_influx(influx.InfluxCheck(influx.SENSORS_MISSING, "Status arrives, sensor data does not",
|
||||
details=["SEN66 (air quality): no data"]))
|
||||
rows = st._cloud_rows()
|
||||
assert rows[0][0] == "bad" and rows[1][0] == "note"
|
||||
st._engine.feed(parse_line("ESP-ROM:esp32s3-20210327"))
|
||||
st._diag_dirty = True
|
||||
st._refresh_diag()
|
||||
texts = [st.diag.milestones.item(i).text() for i in range(st.diag.milestones.count())]
|
||||
assert any(INFLUX_ROW in t for t in texts)
|
||||
assert "Test box" in st.test_status.text()
|
||||
st.shutdown()
|
||||
app.processEvents()
|
||||
Reference in new issue
Block a user