BetterFrame/nodered/src/bf-event-in.js

59 lines
2.3 KiB
JavaScript
Raw Normal View History

/**
* bf-event-in fire a flow whenever a BetterFrame kiosk event matching a
* topic pattern arrives.
*
* Two delivery paths can land here:
* 1. The BF server has forwarded an authenticated kiosk event via the
* `/in/kiosk/<topic>` ingest endpoint. The flow operator wires an
* `http in` node on that path and connects it to this node we just
* filter by topic.
* 2. A separate flow injects msg.topic + msg.payload directly.
*
* In other words, bf-event-in is a pure filter/router. It does NOT itself
* subscribe to the BF server; that wiring is done with stock Node-RED http-in
* or websocket nodes upstream.
*/
module.exports = function (RED) {
function BfEventInNode(config) {
RED.nodes.createNode(this, config);
const node = this;
const pattern = (config.topic_pattern || "").trim();
// Convert glob-ish pattern to RegExp: `gpio.button.*` → /^gpio\.button\..*$/
function toRegex(p) {
if (!p) return null;
const escaped = p.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
return new RegExp("^" + escaped + "$");
}
const re = toRegex(pattern);
node.on("input", function (msg, send, done) {
// Common BF envelope shape:
// { topic, kiosk_id, camera_id, source_type, payload }
// We accept either a fully-formed msg or one where the body lives in
// msg.payload (typical for Node-RED http-in).
const body = (msg && msg.payload && typeof msg.payload === "object") ? msg.payload : {};
const topic = msg.topic || body.topic || "";
if (!topic) {
node.status({ fill: "yellow", shape: "ring", text: "no topic" });
return done && done();
}
if (re && !re.test(String(topic))) {
// Filter miss — drop silently.
return done && done();
}
const out = {
topic: String(topic),
kiosk_id: msg.kiosk_id || body.kiosk_id || body.source_kiosk_id || null,
camera_id: msg.camera_id || body.camera_id || body.source_camera_id || null,
source_type: body.source_type || null,
payload: body.payload !== undefined ? body.payload : body,
};
node.status({ fill: "green", shape: "dot", text: out.topic });
send(out);
done && done();
});
}
RED.nodes.registerType("bf-event-in", BfEventInNode);
};