Refactor code handling binary sequence requests.

Instead of the user giving the recipe for the payload, it now
only handles predefined payload configurations. Those are
denoted by the `type` query parameter. The only valid value
as of this commit is `type=2`.

Look at lib/binary/bundle.js for the definition of a type 2
bundle.
This commit is contained in:
D. Berge
2025-08-01 16:47:50 +02:00
parent cc8d790ad8
commit e464f5f887
4 changed files with 171 additions and 46 deletions

View File

@@ -1,55 +1,11 @@
const { bundle } = require('../../../../lib/binary');
const { sequence } = require('../../../../lib/db'); const { sequence } = require('../../../../lib/db');
const { MSGTYPE, encode } = require('../../../../lib/binary');
module.exports = async function (req, res, next) { module.exports = async function (req, res, next) {
try { try {
const json = await sequence.get(req.params.project, req.params.sequence, req.query); const json = await sequence.get(req.params.project, req.params.sequence, req.query);
const data = bundle(json, {type: req.query.type});
let msgType, geometry, error;
switch (req.query.geometry) {
case "F":
case "FINAL":
msgType = MSGTYPE.FINAL_OPT;
geometry = "geometryfinal";
error = "errorfinal";
break;
case "f":
case "final":
msgType = MSGTYPE.FINAL;
geometry = "geometryfinal";
error = "errorfinal";
break;
case "R":
case "RAW":
msgType = MSGTYPE.RAW_OPT;
geometry = "geometryraw";
error = "errorraw";
break;
case "r":
case "raw":
msgType = MSGTYPE.RAW;
geometry = "geometryraw";
error = "errorraw";
break;
case "P":
case "PREPLOT":
msgType = MSGTYPE.PREPLOT_RAWERROR_OPT;
geometry = "geometrypreplot";
error = ["errorfinal", "errorraw"];
break;
case "p":
case "preplot":
default:
msgType = MSGTYPE.PREPLOT;
geometry = "geometrypreplot";
break;
}
const endianness = req.query.endianness != "big";
const data = encode(json, geometry, error, msgType, endianness);
console.log("bundle", data); console.log("bundle", data);
res.status(200).send(Buffer.from(data)); res.status(200).send(Buffer.from(data));

View File

@@ -0,0 +1,166 @@
const d3a = require('d3');
const { encode } = require('@dougal/binary');
function bundle (json, opts = {}) {
const { type, geometries, payload } = opts;
const deltas = [];
const values = [];
// console.log("JSON LENGTH", json.length);
// console.log("OPTS", geometries, payload);
/* Gun information:
*
* - Δelem 0: BigUint64Array + Int16Array timestamps
* - elem 01: Float32Array, Float32Array Raw positions (x, y)
* - elem 23: Int16Array, Int16Array (×10) Raw position errors (i, j)
* - elem 46: Int8Array, Int8Array, Uint8Array Gun deltas (μ, σ, R)
* - elem 79: Uint16Array, Uint8Array, Uint16Array Gun pressures (μ, σ, R)
* - elem 1012: Gun depths (μ, σ, R)
* - elem 1315: Gun fill times (μ, σ, R)
* - elem 1618: Gun delay (μ, σ, R)
* - elem 19: No fire / autofire (in a single byte)
*/
if (type == 2) {
// Add timestamps
deltas.push({
// Timestamp
key: el => el.tstamp.valueOf(),
baseType: BigUint64Array,
incrType: Int16Array
});
// Add raw positions
values.push({
// longitude
key: el => el.geometryraw?.coordinates?.[0] ?? el.geometry.preplot?.coordinates?.[0],
type: Float32Array
});
values.push({
// latitude
key: el => el.geometryraw?.coordinates?.[1] ?? el.geometry.preplot?.coordinates?.[1],
type: Float32Array
});
// Add raw inline, crossline errors
values.push({
// Crossline
key: el => el.errorraw?.coordinates?.[0] * 10,
type: Float32Array
});
values.push({
// Inline
key: el => el.errorraw?.coordinates?.[1] * 10,
type: Float32Array
});
// Include delta errors info
values.push({
// Average
key: el => (el.meta?.raw?.smsrc?.avg_delta ?? 0) * 10,
type: Int8Array
});
values.push({
// Standard deviation
key: el => (el.meta?.raw?.smsrc?.std_delta ?? 0) * 10,
type: Int8Array
});
values.push({
// Spread
key: el => (el.meta?.raw?.smsrc?.spread ?? 0) * 10,
type: Uint8Array
});
// Include pressure info
const press = el => el.meta.raw?.smsrc?.guns?.map( i => i[11] ?? 0) ?? [];
values.push({
// Average
key: el => d3a.mean(press(el)) ?? 0,
type: Uint16Array
});
values.push({
// Standard deviation
key: el => d3a.deviation(press(el)) ?? 0,
type: Uint8Array
});
values.push({
// Spread
key: el => (d3a.max(press(el)) ?? 0) - (d3a.min(press(el)) ?? 0),
type: Uint16Array
});
// Include depth info (× 10)
const depths = el => el.meta.raw?.smsrc?.guns?.map( i => i[10] ?? 0).filter(i => i) ?? [];
values.push({
// Average
key: el => Math.min(d3a.mean(depths(el)) ?? 0, 25.5) * 10,
type: Uint8Array
});
values.push({
// Standard deviation
key: el => (d3a.deviation(depths(el)) ?? 0) * 10,
type: Uint8Array
});
values.push({
// Spread
key: el => ((d3a.max(depths(el)) ?? 0) - (d3a.min(depths(el)) ?? 0)) * 10,
type: Uint8Array
});
// Include fill times
const filltime = el => el.meta.raw?.smsrc?.guns?.map( i => i[13] ?? 0).filter(i => i) ?? [];
values.push({
// Average
key: el => d3a.mean(filltime(el)) ?? 0,
type: Uint16Array
});
values.push({
// Standard deviation
key: el => d3a.deviation(filltime(el)) ?? 0,
type: Uint16Array
});
values.push({
// Spread
key: el => ((d3a.max(filltime(el)) ?? 0) - (d3a.min(filltime(el)) ?? 0)),
type: Uint16Array
});
// Include fire delay
const delay = el => el.meta.raw?.smsrc?.guns?.map( i => i[9] ?? 0).filter(i => i) ?? [];
values.push({
// Average
key: el => (d3a.mean(delay(el)) ?? 0) * 10,
type: Uint16Array
});
values.push({
// Standard deviation
key: el => (d3a.deviation(delay(el)) ?? 0) * 10,
type: Uint16Array
});
values.push({
// Spread
key: el => ((d3a.max(delay(el)) ?? 0) - (d3a.min(delay(el)) ?? 0)) * 10,
type: Uint16Array
});
// Include no fire and autofire (same byte)
values.push({
key: el => (el.meta.raw?.smsrc?.no_fire ?? 0) << 4 | (el.meta.raw?.smsrc?.num_auto ?? 0),
type: Uint8Array
});
}
console.log("DELTAS", deltas);
console.log("VALUES", values);
return encode.sequential(json, el => el.sequence, el => el.point, deltas, values, type)
}
module.exports = { bundle };

View File

@@ -1,3 +1,4 @@
module.exports = { module.exports = {
...require('./bundle'),
}; };

View File

@@ -26,11 +26,13 @@
"linux" "linux"
], ],
"dependencies": { "dependencies": {
"@dougal/binary": "file:../../modules/@dougal/binary",
"@dougal/organisations": "file:../../modules/@dougal/organisations", "@dougal/organisations": "file:../../modules/@dougal/organisations",
"@dougal/user": "file:../../modules/@dougal/user", "@dougal/user": "file:../../modules/@dougal/user",
"body-parser": "gitlab:aaltronav/contrib/expressjs/body-parser", "body-parser": "gitlab:aaltronav/contrib/expressjs/body-parser",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"csv": "^6.3.3", "csv": "^6.3.3",
"d3": "^6.7.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"express": "^4.17.1", "express": "^4.17.1",
"express-jwt": "^8.4.1", "express-jwt": "^8.4.1",