Files
coresync/src/identity.js
znetsixe aefec90485 chore: initial coresync scaffold
EVOLV CoreSync node — FROST/SensorThings handoff path. First version forwards FROST-ready HTTP request messages on the dbase output; a downstream Node-RED http-request node performs the actual POST and feeds responses back on msg.topic = "frost.response". Lazy stream resolver, latest-wins queue for unresolved/FROST-down streams (keep first + latest, drop middle), knot-emit on slope change, provenance preserved in Observation parameters.

Interview state + open Q20 (slope angle vs. relative delta) recorded in superproject CORESYNC_FROST_INTERVIEW_HANDOFF.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:07:12 +02:00

77 lines
2.1 KiB
JavaScript

'use strict';
const DEFAULT_UNITS = {
pressure: 'Pa',
flow: 'm3/s',
power: 'W',
temperature: 'K',
density: 'kg/m3',
level: 'm',
volume: 'm3',
control: '1',
percentage: '1',
efficiency: '1',
};
function firstPresent(...values) {
for (const value of values) {
if (value !== undefined && value !== null && value !== '') return value;
}
return undefined;
}
function sanitizeToken(value, fallback) {
const raw = firstPresent(value, fallback);
return String(raw || '').trim();
}
function parseFieldKey(fieldKey) {
const parts = String(fieldKey || '').split('.').filter(Boolean);
return {
type: parts[0] || 'value',
variant: parts[1] || 'measured',
position: parts[2] || 'atEquipment',
sensorTag: parts[3] || undefined,
};
}
function resolveIdentity(input, options = {}) {
const tags = input.tags || {};
const parsed = parseFieldKey(input.fieldKey);
const thingTag = sanitizeToken(
options.assetTagOverride,
tags.tagcode || tags.tagCode || tags.asset_tagCode || tags.asset_tagcode || input.measurement,
);
const type = sanitizeToken(input.type, parsed.type).toLowerCase();
const variant = sanitizeToken(input.variant, parsed.variant).toLowerCase();
const position = sanitizeToken(input.position, parsed.position);
const sensorTag = sanitizeToken(
options.sensorTagOverride,
parsed.sensorTag || tags.sensorTag || tags.sensor_tagCode || `${variant.toUpperCase()}-${thingTag}`,
);
const unit = sanitizeToken(input.unit, tags.unit || input.source?.unit || DEFAULT_UNITS[type] || '1');
const streamKey = [thingTag, type, variant, position, sensorTag].join(':');
return {
thingTag,
type,
variant,
position,
sensorTag,
unit,
fieldKey: input.fieldKey,
streamKey,
thingExternalKey: `thing:${thingTag}`,
observedPropertyExternalKey: `observedProperty:${type}`,
sensorExternalKey: `sensor:${sensorTag}`,
featureOfInterestExternalKey: `foi:${thingTag}:${position}`,
datastreamExternalKey: `datastream:${streamKey}`,
};
}
module.exports = {
DEFAULT_UNITS,
parseFieldKey,
resolveIdentity,
};