UNPKG

signalk-server

Version:

An implementation of a [Signal K](http://signalk.org) server for boats.

95 lines (94 loc) 3.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getToPreferredDelta = void 0; const debug_1 = require("./debug"); const debug = (0, debug_1.createDebug)('signalk-server:sourcepriorities'); const toPrecedences = (sourcePrioritiesMap) => Object.keys(sourcePrioritiesMap).reduce((acc, path) => { const priorityIndices = sourcePrioritiesMap[path].reduce((acc2, { sourceRef, timeout }, i) => { acc2.set(sourceRef, { precedence: i, timeout }); return acc2; }, new Map()); acc.set(path, priorityIndices); return acc; }, new Map()); const getToPreferredDelta = (sourcePrioritiesData, unknownSourceTimeout = 10000) => { if (!sourcePrioritiesData) { debug('No priorities data'); return (delta, _now, _selfContext) => delta; } const precedences = toPrecedences(sourcePrioritiesData); const contextPathTimestamps = new Map(); const setLatest = (context, path, sourceRef, millis) => { let pathLatestTimestamps = contextPathTimestamps.get(context); if (!pathLatestTimestamps) { pathLatestTimestamps = new Map(); contextPathTimestamps.set(context, pathLatestTimestamps); } pathLatestTimestamps.set(path, { sourceRef, timestamp: millis }); }; const getLatest = (context, path) => { const pathLatestTimestamps = contextPathTimestamps.get(context); if (!pathLatestTimestamps) { return { sourceRef: '', timestamp: 0 }; } const latestTimestamp = pathLatestTimestamps.get(path); if (!latestTimestamp) { return { sourceRef: '', timestamp: 0 }; } return latestTimestamp; }; const HIGHESTPRECEDENCE = { precedence: 0, timeout: 0 }; const LOWESTPRECEDENCE = { precedence: Number.POSITIVE_INFINITY, timeout: unknownSourceTimeout }; const isPreferredValue = (path, latest, sourceRef, millis) => { const pathPrecedences = precedences.get(path); if (!pathPrecedences) { return true; } const latestPrecedence = pathPrecedences.get(latest.sourceRef) || HIGHESTPRECEDENCE; const incomingPrecedence = pathPrecedences.get(sourceRef) || LOWESTPRECEDENCE; const latestIsFromHigherPrecedence = latestPrecedence.precedence < incomingPrecedence.precedence; const isPreferred = !latestIsFromHigherPrecedence || millis - latest.timestamp > incomingPrecedence.timeout; if (debug.enabled) { debug(`${path}:${sourceRef}:${isPreferred}:${millis - latest.timestamp}`); } return isPreferred; }; return (delta, now, selfContext) => { if (delta.context === selfContext) { const millis = now.getTime(); delta.updates && delta.updates.forEach((update) => { if ('values' in update) { update.values = update.values.reduce((acc, pathValue) => { const latest = getLatest(delta.context, pathValue.path); const isPreferred = isPreferredValue(pathValue.path, latest, update.$source, millis); if (isPreferred) { setLatest(delta.context, pathValue.path, update.$source, millis); acc.push(pathValue); return acc; } return acc; }, []); } }); } return delta; }; }; exports.getToPreferredDelta = getToPreferredDelta;