mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 12:17:08 +00:00
120 lines
3.2 KiB
JavaScript
Executable File
120 lines
3.2 KiB
JavaScript
Executable File
#!/usr/bin/node
|
|
|
|
const dgram = require('dgram');
|
|
const cfg = require("../lib/config");
|
|
const { navdata } = require('../lib/db');
|
|
const sendAlert = require("../lib/alerts");
|
|
const headers = require('../lib/headers');
|
|
|
|
function maybeSendError(error, payload = {}) {
|
|
const defaults = {
|
|
title: "UDP listener error",
|
|
description: error.message,
|
|
message: error.message,
|
|
error: error
|
|
};
|
|
|
|
const packet = Object.assign({}, defaults, payload);
|
|
console.error(packet);
|
|
sendAlert(packet);
|
|
}
|
|
|
|
function parseMessages (buffer, formats = [ "hydronav", "labo", "smartsource" ]) {
|
|
const formatHandlers = formats.map( name => headers[name]);
|
|
// [ headers.hydronav, headers.labo, headers.smartsource ];
|
|
|
|
const navData = {
|
|
tstamp: new Date(),
|
|
sequence: null,
|
|
line: null,
|
|
point: null,
|
|
latitude: null,
|
|
longitude: null,
|
|
lineName: null,
|
|
online: null,
|
|
payload: []
|
|
};
|
|
|
|
for (const format of formatHandlers) {
|
|
// console.log(format.name);
|
|
const pos = format.detect(buffer);
|
|
if (pos !== false) {
|
|
try {
|
|
const header = format.parse(buffer.subarray(pos));
|
|
if (header) {
|
|
if (header.sequence) {
|
|
navData.sequence = header.sequence;
|
|
}
|
|
if (header.line) {
|
|
navData.line = header.line;
|
|
}
|
|
if (header.shotPoint) {
|
|
navData.point = header.shotPoint;
|
|
}
|
|
if (header.latitude) {
|
|
navData.latitude = header.latitude;
|
|
}
|
|
if (header.longitude) {
|
|
navData.longitude = header.longitude;
|
|
}
|
|
if (header.easting) {
|
|
navData.easting = header.easting;
|
|
}
|
|
if (header.northing) {
|
|
navData.northing = header.northing;
|
|
}
|
|
if (header.lineName) {
|
|
navData.lineName = header.lineName;
|
|
}
|
|
if (navData.online === null && header.lineStatus) {
|
|
if (["online", "approach", "runout"].includes(header.lineStatus)) {
|
|
navData.online = true;
|
|
} else if (header.lineStatus == "offline") {
|
|
navData.online = false;
|
|
}
|
|
// else unknown
|
|
}
|
|
if (header.tstamp && header._received) {
|
|
header._latency = header._received - header.tstamp;
|
|
}
|
|
navData.payload.push(header);
|
|
}
|
|
} catch (error) {
|
|
maybeSendError(error, {title: `Decoding error for format ${format.name}`});
|
|
}
|
|
}
|
|
}
|
|
return navData;
|
|
}
|
|
|
|
for (const header of (cfg._("global.navigation.headers") || []).filter(h => h.type == "udp")) {
|
|
const server = dgram.createSocket('udp4');
|
|
|
|
server.on('error', (err) => {
|
|
console.error(`server error:\n${err.stack}`);
|
|
maybeSendError(err, {title: "UDP listener error on port "+header.port});
|
|
// server.close();
|
|
});
|
|
|
|
server.on('message', (msg, rinfo) => {
|
|
// console.log(`${header.type} :${header.port} ← ${msg.length} bytes from ${rinfo.address}:${rinfo.port}`);
|
|
|
|
const navData = parseMessages(msg);
|
|
|
|
if (navData.payload.length) {
|
|
navData.payload = navData.payload.reduce( (a, b) => Object.assign(a, b), {});
|
|
delete navData.payload._type;
|
|
// console.log("SAVE", JSON.stringify(navData, null, 4));
|
|
// console.log("META", header.meta);
|
|
navdata.save(navData, header.meta);
|
|
}
|
|
});
|
|
|
|
server.on('listening', () => {
|
|
const address = server.address();
|
|
console.log(`server listening ${address.address}:${address.port}`);
|
|
});
|
|
|
|
server.bind(header.port);
|
|
}
|