From aadd3715f9ced40b0bf25729a9968d9c42a19cb2 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sun, 8 Aug 2021 11:04:28 +0200 Subject: buien: Initial version using external buienradar-store --- modules/subd-buien/.gitignore | 1 + modules/subd-buien/index.html | 279 +++++++++++++++++++++++++++++++++++++++ modules/subd-buien/subd-buien.js | 133 +++++++++++++++++++ 3 files changed, 413 insertions(+) create mode 100644 modules/subd-buien/.gitignore create mode 100644 modules/subd-buien/index.html create mode 100644 modules/subd-buien/subd-buien.js (limited to 'modules') diff --git a/modules/subd-buien/.gitignore b/modules/subd-buien/.gitignore new file mode 100644 index 0000000..6198c27 --- /dev/null +++ b/modules/subd-buien/.gitignore @@ -0,0 +1 @@ +buienradar-store diff --git a/modules/subd-buien/index.html b/modules/subd-buien/index.html new file mode 100644 index 0000000..03c56e8 --- /dev/null +++ b/modules/subd-buien/index.html @@ -0,0 +1,279 @@ + + + + +Buien + + + + + + +

Buien

+ +

Warning: This page can load a lot of images; one frame is between 30KB and 70KB. +One day (288 frames) is about 14MB.

+ +Your browser does not support the <canvas> element. Get a newer/different browser. +
+
+ + + + + + + + + + diff --git a/modules/subd-buien/subd-buien.js b/modules/subd-buien/subd-buien.js new file mode 100644 index 0000000..1d599eb --- /dev/null +++ b/modules/subd-buien/subd-buien.js @@ -0,0 +1,133 @@ +const cmn = require("../$common.js"); +const fs = require("fs"); +const express = require("express"); +const child_process = require("child_process"); + +// NOTE: +// This module expects a buienradar-store instance in the 'buienradar-store' +// directory within this module's directory. The database therein should be +// named 'db', and the background image should be stored under key 'mode' +// (which should probably be the cmpref). + + +// cb : (err, status, stdout : Buffer) -> () +function runDbmanage(bdir, args, cb) { + const options = { + cwd: bdir, + stdio: ["inherit", "pipe", "inherit"], + timeout: 5000, // milliseconds + }; + const proc = child_process.spawn(bdir + "/dbmanage", args, options); + + const outbufs = []; + proc.stdout.on("data", data => { + outbufs.push(data); + }); + + let callbackInvoked = false; + + proc.on("error", err => { + if (callbackInvoked) return; + callbackInvoked = true; + cb(err, null, null); + }); + + proc.on("exit", (code, sig) => { + if (callbackInvoked) return; + callbackInvoked = true; + if (code != null) cb(null, code, Buffer.concat(outbufs)); + else cb("Process terminated by signal", null, null); + }); +} + +// cb : (err, frames : [String]) -> () +function getFramesList(bdir, cb) { + runDbmanage(bdir, ["list", bdir + "/db"], (err, status, out) => { + if (err) cb(err, null); + else if (status != 0) cb("Error getting list of frames from DB", null); + else cb(null, out.toString("utf8").trim().split("\n").filter(s => s != "mode")); + }); +} + +// cb : (err, pngs : Buffer) -> () +function getFramesPng(bdir, stamps, cb) { + runDbmanage(bdir, ["getmultiple", bdir + "/db"].concat(stamps), (err, status, out) => { + if (err) { cb(err, null); return; } + if (status != 0) { cb("Error getting frames from DB", null); return; } + cb(null, out); + + // const pngs = []; + + // let cursor = 0; + // while (cursor < out.length) { + // let pnglen = out.readBigUInt64LE(cursor); + // if (Number(pnglen) != pnglen) { + // cb("PNG too large", null); + // return; + // } + // pnglen = Number(pnglen); + + // pngs.push(out.slice(cursor + 8, cursor + 8 + pnglen)); + // cursor += 8 + pnglen; + // } + + // cb(null, pngs); + }); +} + +// cb : (err, present : Bool) -> () +function checkFramePresent(bdir, stamp, cb) { + runDbmanage(bdir, ["has", bdir + "/db", stamp], (err, status, out) => { + if (err) { cb(err, null); return; } + if (status == 1) { cb("Error getting status from DB", null); return; } + if (status == 0) cb(null, true); + else cb(null, false); + }); +} + +module.exports = function (app, io, moddir) { + const buiendir = moddir + "/buienradar-store"; + console.log(`buien: Using buienradar-store directory '${buiendir}'`); + + const router = express.Router(); + + router.get("/", function (req, res) { + res.sendFile(moddir + "/index.html"); + }); + + router.get("/api/list/json", function (req, res) { + getFramesList(buiendir, (err, frames) => { + if (err) { + console.log(err); + res.sendStatus(500); + } else res.json(frames); + }); + }); + + router.get("/api/images", function (req, res) { + const url = new URL(req.url, `https://${req.headers.host}`); + const stamps = url.searchParams.getAll("s").flatMap(s => s.split(",")); + getFramesPng(buiendir, stamps, (err, buf) => { + if (err) { + console.log(err); + res.sendStatus(500); + } else res.send(buf); + }); + }); + + router.get("/api/has/:stamp", function (req, res) { + checkFramePresent(buiendir, req.params.stamp, (err, present) => { + if (err) { + console.log(err); + res.sendStatus(500); + } else if (present) res.sendStatus(200); + else res.sendStatus(404); + }); + }); + + app.use(function (req, res, next) { + if (req.subdomains.length && req.subdomains[req.subdomains.length - 1] == "buien") { + router.handle(req, res, next); + } else next(); + }); +}; -- cgit v1.2.3-70-g09d2