Skip to content

Repository files navigation

NightWatcher SQM (WordPress plugin)

The WordPress side of NightWatcher. The NightWatcher daemon pushes Sky Quality Meter readings to this plugin's authenticated REST endpoint; the plugin stores them and renders a read-only, date-range sky-brightness graph.

Push (not pull) means the daemon can stay on a private home network — nothing needs to reach inward to it.

nightwatcherd (home LAN)  ──HTTPS POST──►  /wp-json/nightwatcher/v1/ingest  ──►  wp table
                                                                                   │
   [nightwatcher_graph] shortcode  ◄── /wp-json/nightwatcher/v1/readings ◄─────────┘

The nightwatcher_graph shortcode on a WordPress page: SQM sky brightness with Sun/Moon altitude and ambient-temperature overlays, drawn client-side from the pushed data

Install

  1. Copy this folder into wp-content/plugins/nightwatcher-wp/ and activate it — this creates its tables (see Database).
  2. Settings → NightWatcher SQMGenerate a strong token, and copy the Ingest URL.
  3. In NightWatcher, add a webhook export target with that URL and the token as the bearer secret.
  4. Put the shortcode on a page: [nightwatcher_graph sensor="DSN036" days="7"].

Database

The plugin keeps its data in WordPress's own MySQL/MariaDB database — there is no separate server or manual schema step. On activation it creates three tables under your $wpdb prefix via dbDelta, using only standard column types, so any MySQL/MariaDB that runs your WordPress works:

Table (default prefix) One row per Grows
wp_nightwatcher_sensors sensor (id, location, timezone) no
wp_nightwatcher_readings SQM reading (mag/arcsec², sensor temp) yes
wp_nightwatcher_weather co-located ambient-weather point yes

The database user WordPress already uses needs only the usual privileges it grants (CREATE/ALTER for activation, INSERT/SELECT in normal use, DELETE if you prune) — nothing special.

Footprint. At a 5-minute push cadence the two growing tables each add ~288 rows/day per sensor — about 15–25 MB/year per sensor including indexes. Both de-duplicate on (sensor_id, ts_utc), so re-sending an overlapping window (e.g. a NightWatcher backfill) never bloats them.

Keeping it bounded. This database is a read-only mirror — NightWatcher's own database and the monthly DSN files are the source of truth — so it is safe to prune here without losing data. To cap disk use:

  • Trim old rows. Safe to re-run; keep at least the longest range your graph offers:

    DELETE FROM wp_nightwatcher_readings WHERE ts_utc < UTC_TIMESTAMP() - INTERVAL 400 DAY;
    DELETE FROM wp_nightwatcher_weather  WHERE ts_utc < UTC_TIMESTAMP() - INTERVAL 400 DAY;

    Schedule it from host cron or WP-Cron to make retention automatic.

  • Mind your host's database-size quota. Shared hosting usually enforces one; reaching it fails new writes rather than filling the whole disk.

  • Cap binary logs if MySQL binary logging is enabled (binlog_expire_logs_seconds) — unmanaged binlogs can fill a disk faster than this data ever will.

The ingest contract

NightWatcher's webhook exporter sends:

POST /wp-json/nightwatcher/v1/ingest
Authorization: Bearer <token>
Content-Type: application/json

{
  "site_id": "DSN036-S",
  "sensor": { "id": "DSN036", "name": "CrestaLoma Observatory", "latitude": 31.95, "longitude": -111.6,
              "elevation_m": 1200, "timezone": "America/Phoenix" },
  "readings": [
    { "ts_utc": "2026-07-20 05:00:00", "mag_arcsec2": 21.34, "temp_c": 18.2, "quality": "ok" }
  ]
}

Response: { "ok": true, "sensor_id": "DSN036", "received": N, "stored": M }. Readings are de-duplicated on (sensor_id, ts_utc), so re-sending an overlapping window is safe.

REST endpoints

Method Route Auth Purpose
POST /nightwatcher/v1/ingest Bearer token Receive a push of sensor metadata + readings
GET /nightwatcher/v1/readings?sensor=&from=&to= public Readings for the graph (defaults to last 7 days)
GET /nightwatcher/v1/sensors public Known sensors + metadata

Shortcode

[nightwatcher_graph sensor="DSN036" days="7" height="320" title="CrestaLoma Observatory sky brightness"]

Renders a uPlot line of mag/arcsec² over time with From/To date pickers. When the sensor has coordinates, Sun and Moon altitude are overlaid (dashed lines on a right-side degrees axis) with a moon-phase glyph riding on the Moon line — computed in-browser from the sensor's location. When NightWatcher also pushes co-located weather, an ambient temperature line (°C) is overlaid too. Visitors toggle each with the graph's Sun/Moon/Ambient checkboxes; set the per-graph default with sun="0", moon="0", and/or ambient="0". A Live checkbox auto-refreshes the graph as new readings arrive (off by default; enable it per embed with live="1", and each visitor's choice is remembered in their browser). Vendored uPlot (MIT) and SunCalc (BSD-2-Clause); no external CDNs.

Attribute Default Meaning
sensor Sensor id to graph (required)
days 7 Initial range, in days back from now
height 320 Graph height in px
title Optional heading above the graph
sun 1 Show the Sun-altitude overlay by default (0 to hide)
moon 1 Show the Moon-altitude overlay + phase glyph by default (0 to hide)
ambient 1 Show the ambient-temperature overlay by default, when weather is available (0 to hide)
live 0 Start with Live auto-refresh on (1); visitors can toggle it, and the choice is remembered per browser

Layout

nightwatcher-wp.php            plugin bootstrap (hooks, activation)
includes/class-nw-store.php    tables + upsert/query
includes/class-nw-rest.php     REST routes (ingest + read)
includes/class-nw-settings.php admin settings (token + endpoint URLs)
includes/class-nw-shortcode.php [nightwatcher_graph]
assets/js/nightwatcher.js      graph (uPlot)
assets/css/nightwatcher.css    graph styles
assets/vendor/uPlot.*          vendored uPlot

License

GPL-3.0-or-later, matching NightWatcher.

About

WordPress plugin: receive and display NightWatcher SQM readings (read-only, date-range graph)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages