Skip to content

feat: optional web dashboard for exploring the data (/explore) - #80

Merged
firefly-cpp merged 1 commit into
mainfrom
feat/explore
Nov 8, 2026
Merged

firefly-cpp merged 1 commit into
mainfrom
feat/explore

Conversation

@firefly-cpp

Copy link
Copy Markdown
Owner

Summary

An optional web dashboard for monitoring the collected data in a browser, at /explore. It is off by default and separate from data collection: it is only registered when enabled, and it only reads the stored data.

explore:
  - enable: true
  - refresh: 10   # seconds, optional (0 disables auto-refresh)

succulent explore dashboard

What it shows

  • Latest value per column, with a status (In range, Near max/min, Above max/Below min, No reading) and its position between min and max. If a value is missing in the last measurement, the previous value and its time are shown.
  • Data quality: number of measurements, missing values, values outside min/max, typical interval.
  • A chart per numeric column with min/max as dashed lines and out-of-range points marked. Long ranges are averaged server-side (max. 1000 points) so the page stays fast.
  • Latest measurements table, out-of-range cells highlighted.
  • Time range (1 h, 24 h, 7 d, 30 d, all) when timestamps are stored; auto-refresh (paused while the tab is hidden); CSV export when export is enabled.
  • Gallery for the image format (latest image, earlier images, counts and storage used).
  • Light and dark mode; works at phone width.

Design decisions

  • Separate module: succulent/explore.py (Explorer, a Flask blueprint) plus its own templates and static files. The only change to existing code is 10 lines in SucculentAPI.__init__ to register it when enabled.
  • No dependencies, works offline: no CDN, no external fonts, no chart library; charts are SVG drawn by ~100 lines of JS. Devices are often on a local network without internet.
  • Security:
    • Values sent by devices are only ever rendered as text (textContent), never as HTML.
    • Strict Content-Security-Policy (script-src 'self', style-src 'self', no inline code), nosniff, no-store for data.
    • With a password, the browser gets a password prompt and a session cookie (HttpOnly, SameSite=Lax), so the password never appears in URLs or browser history. ?password= is deliberately not accepted for the dashboard. Scripts can use Authorization: Bearer / X-API-Key.
    • Images are served only if they are in the storage folder with an allowed extension, with a sandboxing CSP.
    • Optional secret_key in the configuration keeps sessions across restarts (otherwise a random key per process).

Endpoints

Path Purpose
GET /explore Dashboard (or redirect to the prompt)
GET/POST /explore/login, POST /explore/logout Password prompt
GET /explore/api/data?range=24h Data for the dashboard (JSON)
GET /explore/api/images Image list (JSON, image format)
GET /explore/images/<name> One stored image
GET /explore/export CSV download (only when export is enabled)

Testing

  • New tests/test_explore.py with 24 tests: configuration (off by default, both config styles, invalid values), page and security headers, data summary, ranges, data without timestamps, averaging, export, password prompt/session/headers, gallery and image serving (only stored images, no traversal).
  • Full suite: 75 passed.
  • Checked in Chromium with 24 h of sample data: desktop, phone width, dark mode, password prompt, gallery; no console errors; y-axis labels align with grid lines.
  • Built the wheel and installed it in a clean virtualenv: templates and static files are included and the dashboard works.

Note

/measure rejects values outside min/max, so out-of-range points only appear for data stored before the limits were set or tightened, or imported data. A possible follow-up is to record rejected measurements so the dashboard can show them.


Generated by Claude Code

Add an optional dashboard for monitoring the collected data in a
browser. It is enabled in the configuration and is separate from data
collection: it only reads the stored data.

    explore:
      - enable: true
      - refresh: 10

- New module succulent/explore.py (Explorer, a Flask blueprint),
  registered by SucculentAPI only when enabled
- Dashboard: latest value per column with its position between min
  and max, data quality (measurements, missing values, values outside
  min/max, typical interval), a chart per numeric column with min/max
  lines, and the latest measurements; time ranges with timestamps,
  auto-refresh, CSV export when export is enabled
- Gallery for the image format
- JSON endpoints /explore/api/data (range: 1h, 24h, 7d, 30d, all;
  long series are averaged) and /explore/api/images
- Password prompt with a session cookie, so the password is never in
  the URL; scripts can use the Authorization/X-API-Key headers;
  optional secret_key in the configuration
- No external scripts or fonts, so it works without internet access;
  strict Content-Security-Policy; device values are rendered as text
- Light and dark mode, works at phone width
- Document the dashboard (with a screenshot) and add tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCvw8haRnmyrVKrLkz5Yf8
@firefly-cpp
firefly-cpp merged commit 52ba987 into main Nov 8, 2026
12 checks passed
@firefly-cpp
firefly-cpp deleted the feat/explore branch November 8, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants