mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 23:26:34 +00:00
fix: Node-RED event forwarding + parse ONVIF Key section (PlateNumber)
Server bridge was forwarding to raw topic paths that no Node-RED node listens on. Now forwards to fixed routes: camera.event, onvif.event, onvif.motion, onvif.anpr — matching what trigger nodes register. ONVIF XML parser now extracts Key section SimpleItems (PlateNumber, etc.) into the data map alongside Data section items. Previously only parsed Source and Data, missing Key-section fields like plate numbers. Node-RED trigger nodes: camera_id filter changed from Number() to String() comparison for UUIDv7 compatibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
eb8abbdff9
commit
488a0ffc3c
6 changed files with 16 additions and 12 deletions
|
|
@ -448,6 +448,11 @@ fn parse_notification_messages(xml: &str) -> Vec<OnvifEvent> {
|
||||||
source.insert(name, value);
|
source.insert(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(key_block) = extract_section(block, "Key") {
|
||||||
|
for (name, value) in parse_simple_items(&key_block) {
|
||||||
|
data.insert(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(data_block) = extract_section(block, "Data") {
|
if let Some(data_block) = extract_section(block, "Data") {
|
||||||
for (name, value) in parse_simple_items(&data_block) {
|
for (name, value) in parse_simple_items(&data_block) {
|
||||||
data.insert(name, value);
|
data.insert(name, value);
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,7 @@ module.exports = function (RED) {
|
||||||
function BfKioskCameraEventNode(config) {
|
function BfKioskCameraEventNode(config) {
|
||||||
RED.nodes.createNode(this, config);
|
RED.nodes.createNode(this, config);
|
||||||
const node = this;
|
const node = this;
|
||||||
const filterIdRaw = (config.camera_id || "").toString().trim();
|
const filterId = (config.camera_id || "").toString().trim() || null;
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
|
||||||
|
|
||||||
async function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = await readJsonBody(req);
|
const body = await readJsonBody(req);
|
||||||
|
|
@ -37,7 +36,7 @@ module.exports = function (RED) {
|
||||||
const cameraId = body.camera_id !== undefined ? body.camera_id
|
const cameraId = body.camera_id !== undefined ? body.camera_id
|
||||||
: body.source_camera_id !== undefined ? body.source_camera_id
|
: body.source_camera_id !== undefined ? body.source_camera_id
|
||||||
: null;
|
: null;
|
||||||
if (filterId !== null && Number(cameraId) !== filterId) {
|
if (filterId !== null && String(cameraId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
}
|
}
|
||||||
const out = {
|
const out = {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ module.exports = function (RED) {
|
||||||
function BfTriggerAnprNode(config) {
|
function BfTriggerAnprNode(config) {
|
||||||
RED.nodes.createNode(this, config);
|
RED.nodes.createNode(this, config);
|
||||||
const node = this;
|
const node = this;
|
||||||
const filterCam = config.camera_id ? Number(config.camera_id) : null;
|
const filterCam = config.camera_id ? String(config.camera_id).trim() : null;
|
||||||
|
|
||||||
async function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = await readJsonBody(req);
|
const body = await readJsonBody(req);
|
||||||
|
|
@ -33,7 +33,7 @@ module.exports = function (RED) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
||||||
if (filterCam !== null && Number(cameraId) !== filterCam) {
|
if (filterCam !== null && String(cameraId) !== filterCam) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ module.exports = function (RED) {
|
||||||
function BfTriggerEventNode(config) {
|
function BfTriggerEventNode(config) {
|
||||||
RED.nodes.createNode(this, config);
|
RED.nodes.createNode(this, config);
|
||||||
const node = this;
|
const node = this;
|
||||||
const filterCam = config.camera_id ? Number(config.camera_id) : null;
|
const filterCam = config.camera_id ? String(config.camera_id).trim() : null;
|
||||||
const filterTopic = (config.topic_filter || "").trim();
|
const filterTopic = (config.topic_filter || "").trim();
|
||||||
|
|
||||||
async function handler(req, res) {
|
async function handler(req, res) {
|
||||||
|
|
@ -27,7 +27,7 @@ module.exports = function (RED) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
||||||
if (filterCam !== null && Number(cameraId) !== filterCam) {
|
if (filterCam !== null && String(cameraId) !== filterCam) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ module.exports = function (RED) {
|
||||||
function BfTriggerMotionNode(config) {
|
function BfTriggerMotionNode(config) {
|
||||||
RED.nodes.createNode(this, config);
|
RED.nodes.createNode(this, config);
|
||||||
const node = this;
|
const node = this;
|
||||||
const filterCam = config.camera_id ? Number(config.camera_id) : null;
|
const filterCam = config.camera_id ? String(config.camera_id).trim() : null;
|
||||||
|
|
||||||
async function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = await readJsonBody(req);
|
const body = await readJsonBody(req);
|
||||||
|
|
@ -34,7 +34,7 @@ module.exports = function (RED) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
const cameraId = body.camera_id ?? body.source_camera_id ?? null;
|
||||||
if (filterCam !== null && Number(cameraId) !== filterCam) {
|
if (filterCam !== null && String(cameraId) !== filterCam) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -735,11 +735,11 @@ function registerKioskRoutes(
|
||||||
nodered.forward(body.topic, out, markForwarded);
|
nodered.forward(body.topic, out, markForwarded);
|
||||||
mqtt.publishEvent(kiosk.id, body.topic, out);
|
mqtt.publishEvent(kiosk.id, body.topic, out);
|
||||||
|
|
||||||
// ONVIF events: also forward to the fixed onvif.event route so the
|
nodered.forward("camera.event", out);
|
||||||
// bf-trigger-motion / bf-trigger-anpr / bf-trigger-event nodes
|
|
||||||
// receive them without needing per-topic route registration.
|
|
||||||
if (body.source_type === "onvif") {
|
if (body.source_type === "onvif") {
|
||||||
nodered.forward("onvif.event", out);
|
nodered.forward("onvif.event", out);
|
||||||
|
nodered.forward("onvif.motion", out);
|
||||||
|
nodered.forward("onvif.anpr", out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue