feat(gelios): expand safe B2 telemetry registry
This commit is contained in:
@@ -8,3 +8,7 @@ export { geliosProviderPackageV10 } from "./v10/index.mjs";
|
|||||||
export { geliosProviderPackageV11 } from "./v11/index.mjs";
|
export { geliosProviderPackageV11 } from "./v11/index.mjs";
|
||||||
export { geliosProviderPackageV12 } from "./v12/index.mjs";
|
export { geliosProviderPackageV12 } from "./v12/index.mjs";
|
||||||
export { geliosProviderPackageV13 } from "./v13/index.mjs";
|
export { geliosProviderPackageV13 } from "./v13/index.mjs";
|
||||||
|
export {
|
||||||
|
geliosProviderPackageV14,
|
||||||
|
geliosTelemetryFieldRegistryV6,
|
||||||
|
} from "./v14/index.mjs";
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export {
|
||||||
|
GELIOS_PROVIDER_PACKAGE_ID,
|
||||||
|
GELIOS_PROVIDER_PACKAGE_VERSION,
|
||||||
|
geliosProviderPackageV14,
|
||||||
|
} from "./package.mjs";
|
||||||
|
export { geliosTelemetryFieldRegistryV6 } from "./telemetry-field-registry.mjs";
|
||||||
|
export { geliosCapabilityCatalogV3 } from "../capability-catalog-v3.mjs";
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { geliosProviderPackageV13 } from "../v13/package.mjs";
|
||||||
|
|
||||||
|
export const GELIOS_PROVIDER_PACKAGE_ID = "gelios.provider.v14";
|
||||||
|
export const GELIOS_PROVIDER_PACKAGE_VERSION = "14.0.0";
|
||||||
|
|
||||||
|
const value = structuredClone(geliosProviderPackageV13);
|
||||||
|
value.id = GELIOS_PROVIDER_PACKAGE_ID;
|
||||||
|
value.version = GELIOS_PROVIDER_PACKAGE_VERSION;
|
||||||
|
value.manifest = {
|
||||||
|
...value.manifest,
|
||||||
|
id: "gelios.provider.manifest.v14",
|
||||||
|
version: GELIOS_PROVIDER_PACKAGE_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const geliosProviderPackageV14 = deepFreeze(value);
|
||||||
|
|
||||||
|
function deepFreeze(input) {
|
||||||
|
if (!input || typeof input !== "object" || Object.isFrozen(input)) return input;
|
||||||
|
Object.freeze(input);
|
||||||
|
for (const child of Object.values(input)) deepFreeze(child);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { geliosTelemetryFieldRegistryV5 } from "../v12/telemetry-field-registry.mjs";
|
||||||
|
import {
|
||||||
|
GELIOS_PROVIDER_PACKAGE_ID,
|
||||||
|
GELIOS_PROVIDER_PACKAGE_VERSION,
|
||||||
|
} from "./package.mjs";
|
||||||
|
|
||||||
|
const EXPOSED_SURFACES = Object.freeze([
|
||||||
|
"audit",
|
||||||
|
"data_product",
|
||||||
|
"analytics",
|
||||||
|
"foundry",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const value = structuredClone(geliosTelemetryFieldRegistryV5);
|
||||||
|
value.id = "gelios.units.current.telemetry.v3";
|
||||||
|
value.version = "3.0.0";
|
||||||
|
value.providerPackage = {
|
||||||
|
id: GELIOS_PROVIDER_PACKAGE_ID,
|
||||||
|
version: GELIOS_PROVIDER_PACKAGE_VERSION,
|
||||||
|
};
|
||||||
|
value.sourceNamespace = "gelios.units.telemetry_parameter";
|
||||||
|
|
||||||
|
const existingKeys = new Set(value.entries.map((entry) => entry.sourceKey));
|
||||||
|
for (const sourceKey of inputKeys()) {
|
||||||
|
if (existingKeys.has(sourceKey)) continue;
|
||||||
|
value.entries.push(providerConfiguredNumber(sourceKey));
|
||||||
|
existingKeys.add(sourceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [sourceKey, readingId, label] of [
|
||||||
|
["GSM_level", "sensor.param.gsm_level", "Уровень GSM"],
|
||||||
|
["call_btn", "sensor.param.call_btn", "Состояние кнопки вызова"],
|
||||||
|
["gps_mod", "sensor.param.gps_mod", "Состояние GPS-модуля"],
|
||||||
|
["gsm", "sensor.param.gsm", "Сигнал GSM"],
|
||||||
|
["gsm_st", "sensor.param.gsm_st", "Состояние GSM"],
|
||||||
|
["gyro", "sensor.param.gyro", "Состояние гироскопа"],
|
||||||
|
["ign_virt", "sensor.param.ign_virt", "Виртуальное зажигание"],
|
||||||
|
["nav_st", "sensor.param.nav_st", "Состояние навигации"],
|
||||||
|
["pwr_ext", "sensor.param.pwr_ext", "Внешнее питание"],
|
||||||
|
["pwr_int", "sensor.param.pwr_int", "Внутреннее питание"],
|
||||||
|
["sim1_st", "sensor.param.sim1_st", "Состояние SIM 1"],
|
||||||
|
["sim2_st", "sensor.param.sim2_st", "Состояние SIM 2"],
|
||||||
|
["v_in", "sensor.param.v_in", "Вход питания"],
|
||||||
|
]) {
|
||||||
|
if (existingKeys.has(sourceKey)) continue;
|
||||||
|
value.entries.push(registryNumber(sourceKey, readingId, label));
|
||||||
|
existingKeys.add(sourceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const geliosTelemetryFieldRegistryV6 = deepFreeze(value);
|
||||||
|
|
||||||
|
function inputKeys() {
|
||||||
|
return [
|
||||||
|
...Array.from({ length: 16 }, (_, index) => `in_${index}`),
|
||||||
|
...Array.from({ length: 16 }, (_, index) => `in${index}`),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function providerConfiguredNumber(sourceKey) {
|
||||||
|
return {
|
||||||
|
id: `gelios.sensor-parameter.${sourceKey.replaceAll("_", "-underscore-")}`,
|
||||||
|
sourceKey,
|
||||||
|
status: "approved",
|
||||||
|
sensitivity: "operational",
|
||||||
|
valueType: "number",
|
||||||
|
semanticReading: {
|
||||||
|
id: `sensor.param.${sourceKey}`,
|
||||||
|
labelSource: "provider_configured",
|
||||||
|
unitSource: "provider_configured",
|
||||||
|
},
|
||||||
|
allowedSurfaces: [...EXPOSED_SURFACES],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function registryNumber(sourceKey, readingId, label) {
|
||||||
|
return {
|
||||||
|
id: `gelios.telemetry-parameter.${sourceKey.toLowerCase()}`,
|
||||||
|
sourceKey,
|
||||||
|
status: "approved",
|
||||||
|
sensitivity: "operational",
|
||||||
|
valueType: "number",
|
||||||
|
semanticReading: {
|
||||||
|
id: readingId,
|
||||||
|
labelSource: "registry",
|
||||||
|
label,
|
||||||
|
unitSource: "none",
|
||||||
|
},
|
||||||
|
allowedSurfaces: [...EXPOSED_SURFACES],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function deepFreeze(input) {
|
||||||
|
if (!input || typeof input !== "object" || Object.isFrozen(input)) return input;
|
||||||
|
Object.freeze(input);
|
||||||
|
for (const child of Object.values(input)) deepFreeze(child);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
@@ -17,6 +17,10 @@ import {
|
|||||||
geliosProviderPackageV11,
|
geliosProviderPackageV11,
|
||||||
geliosTelemetryFieldRegistryV4,
|
geliosTelemetryFieldRegistryV4,
|
||||||
} from "../providers/gelios/v11/index.mjs";
|
} from "../providers/gelios/v11/index.mjs";
|
||||||
|
import {
|
||||||
|
geliosProviderPackageV14,
|
||||||
|
geliosTelemetryFieldRegistryV6,
|
||||||
|
} from "../providers/gelios/v14/index.mjs";
|
||||||
|
|
||||||
const positionsConnection = instantiateL2Connection(geliosProviderPackageV11, {
|
const positionsConnection = instantiateL2Connection(geliosProviderPackageV11, {
|
||||||
tenantId: "tenant-compiler-fixture",
|
tenantId: "tenant-compiler-fixture",
|
||||||
@@ -122,6 +126,25 @@ assert.equal(Object.isFrozen(positionsPlan), true);
|
|||||||
assert.equal(Object.isFrozen(positionsPlan.steps), true);
|
assert.equal(Object.isFrozen(positionsPlan.steps), true);
|
||||||
assert.equal(Object.isFrozen(positionsPlan.graphBlueprint), true);
|
assert.equal(Object.isFrozen(positionsPlan.graphBlueprint), true);
|
||||||
|
|
||||||
|
const operationalConnection = instantiateL2Connection(geliosProviderPackageV14, {
|
||||||
|
tenantId: "tenant-compiler-fixture",
|
||||||
|
connectionId: "gelios-operational-telemetry-fixture",
|
||||||
|
collectionProfileId: "gelios.positions.current.realtime.v7",
|
||||||
|
providerCredentialRef: "ndc-credref:provider-compiler-fixture-0001",
|
||||||
|
});
|
||||||
|
const operationalPlan = compileL2ExecutionPlan(
|
||||||
|
geliosProviderPackageV14,
|
||||||
|
operationalConnection,
|
||||||
|
{ telemetryFieldRegistry: geliosTelemetryFieldRegistryV6 },
|
||||||
|
);
|
||||||
|
assert.deepEqual(validateL2ExecutionPlan(operationalPlan), { ok: true, errors: [] });
|
||||||
|
assert.equal(
|
||||||
|
operationalPlan.steps
|
||||||
|
.find((step) => step.kind === "semantic_mapping")
|
||||||
|
.config.telemetryProjection.entries.length,
|
||||||
|
45,
|
||||||
|
);
|
||||||
|
|
||||||
const clonedPlan = compileL2ExecutionPlan(
|
const clonedPlan = compileL2ExecutionPlan(
|
||||||
structuredClone(geliosProviderPackageV11),
|
structuredClone(geliosProviderPackageV11),
|
||||||
structuredClone(positionsConnection),
|
structuredClone(positionsConnection),
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { geliosProviderPackageV10 } from "../providers/gelios/v10/index.mjs";
|
|||||||
import { geliosProviderPackageV11 } from "../providers/gelios/v11/index.mjs";
|
import { geliosProviderPackageV11 } from "../providers/gelios/v11/index.mjs";
|
||||||
import { geliosProviderPackageV12 } from "../providers/gelios/v12/index.mjs";
|
import { geliosProviderPackageV12 } from "../providers/gelios/v12/index.mjs";
|
||||||
import { geliosProviderPackageV13 } from "../providers/gelios/v13/index.mjs";
|
import { geliosProviderPackageV13 } from "../providers/gelios/v13/index.mjs";
|
||||||
|
import { geliosProviderPackageV14 } from "../providers/gelios/v14/index.mjs";
|
||||||
import { normalizeDataProductDefinition } from "../../../services/external-data-plane/src/data-product-policy.mjs";
|
import { normalizeDataProductDefinition } from "../../../services/external-data-plane/src/data-product-policy.mjs";
|
||||||
|
|
||||||
const expectedFields = [
|
const expectedFields = [
|
||||||
@@ -57,6 +58,7 @@ assert.deepEqual(validateProviderPackage(geliosProviderPackageV10), { ok: true,
|
|||||||
assert.deepEqual(validateProviderPackage(geliosProviderPackageV11), { ok: true, errors: [] });
|
assert.deepEqual(validateProviderPackage(geliosProviderPackageV11), { ok: true, errors: [] });
|
||||||
assert.deepEqual(validateProviderPackage(geliosProviderPackageV12), { ok: true, errors: [] });
|
assert.deepEqual(validateProviderPackage(geliosProviderPackageV12), { ok: true, errors: [] });
|
||||||
assert.deepEqual(validateProviderPackage(geliosProviderPackageV13), { ok: true, errors: [] });
|
assert.deepEqual(validateProviderPackage(geliosProviderPackageV13), { ok: true, errors: [] });
|
||||||
|
assert.deepEqual(validateProviderPackage(geliosProviderPackageV14), { ok: true, errors: [] });
|
||||||
assert.equal(geliosProviderPackageV9.id, "gelios.provider.v9");
|
assert.equal(geliosProviderPackageV9.id, "gelios.provider.v9");
|
||||||
assert.equal(geliosProviderPackageV9.version, "9.0.0");
|
assert.equal(geliosProviderPackageV9.version, "9.0.0");
|
||||||
assert.equal(geliosProviderPackageV10.id, "gelios.provider.v10");
|
assert.equal(geliosProviderPackageV10.id, "gelios.provider.v10");
|
||||||
@@ -67,6 +69,8 @@ assert.equal(geliosProviderPackageV12.id, "gelios.provider.v12");
|
|||||||
assert.equal(geliosProviderPackageV12.version, "12.0.1");
|
assert.equal(geliosProviderPackageV12.version, "12.0.1");
|
||||||
assert.equal(geliosProviderPackageV13.id, "gelios.provider.v13");
|
assert.equal(geliosProviderPackageV13.id, "gelios.provider.v13");
|
||||||
assert.equal(geliosProviderPackageV13.version, "13.0.0");
|
assert.equal(geliosProviderPackageV13.version, "13.0.0");
|
||||||
|
assert.equal(geliosProviderPackageV14.id, "gelios.provider.v14");
|
||||||
|
assert.equal(geliosProviderPackageV14.version, "14.0.0");
|
||||||
assert.equal(geliosProviderPackageV8.id, "gelios.provider.v8");
|
assert.equal(geliosProviderPackageV8.id, "gelios.provider.v8");
|
||||||
|
|
||||||
const profileProduct = geliosProviderPackageV8.dataProducts.find((product) => product.id === "fleet.units.profile.current.v1");
|
const profileProduct = geliosProviderPackageV8.dataProducts.find((product) => product.id === "fleet.units.profile.current.v1");
|
||||||
@@ -181,6 +185,7 @@ assert.equal(
|
|||||||
"first",
|
"first",
|
||||||
);
|
);
|
||||||
assert.equal(Object.isFrozen(geliosProviderPackageV13), true);
|
assert.equal(Object.isFrozen(geliosProviderPackageV13), true);
|
||||||
|
assert.equal(Object.isFrozen(geliosProviderPackageV14), true);
|
||||||
const identityMapping = geliosProviderPackageV11.mappingContracts.find(
|
const identityMapping = geliosProviderPackageV11.mappingContracts.find(
|
||||||
(mapping) => mapping.id === "gelios.units.to.fleet.units.identity.current.v1",
|
(mapping) => mapping.id === "gelios.units.to.fleet.units.identity.current.v1",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
geliosTelemetryFieldRegistryV2,
|
geliosTelemetryFieldRegistryV2,
|
||||||
} from "../providers/gelios/v9/index.mjs";
|
} from "../providers/gelios/v9/index.mjs";
|
||||||
|
import {
|
||||||
|
geliosTelemetryFieldRegistryV6,
|
||||||
|
} from "../providers/gelios/v14/index.mjs";
|
||||||
|
|
||||||
assert.deepEqual(validateTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1), {
|
assert.deepEqual(validateTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1), {
|
||||||
ok: true,
|
ok: true,
|
||||||
@@ -65,6 +68,57 @@ assert.notEqual(
|
|||||||
digestTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1),
|
digestTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.deepEqual(validateTelemetryFieldRegistry(geliosTelemetryFieldRegistryV6), {
|
||||||
|
ok: true,
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
const operationalProjection = compileTelemetryFieldProjection(
|
||||||
|
geliosTelemetryFieldRegistryV6,
|
||||||
|
{
|
||||||
|
providerPackageId: "gelios.provider.v14",
|
||||||
|
providerPackageVersion: "14.0.0",
|
||||||
|
dataProductId: "fleet.positions.current.v5",
|
||||||
|
surface: "data_product",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert.equal(operationalProjection.entries.length, 45);
|
||||||
|
assert.deepEqual(
|
||||||
|
operationalProjection.entries
|
||||||
|
.filter((entry) => ["pwr_ext", "gsm_st", "nav_st"].includes(entry.sourceKey))
|
||||||
|
.map((entry) => ({
|
||||||
|
sourceKey: entry.sourceKey,
|
||||||
|
readingId: entry.reading.id,
|
||||||
|
labelSource: entry.reading.labelSource,
|
||||||
|
unitSource: entry.reading.unitSource,
|
||||||
|
})),
|
||||||
|
[
|
||||||
|
{
|
||||||
|
sourceKey: "gsm_st",
|
||||||
|
readingId: "sensor.param.gsm_st",
|
||||||
|
labelSource: "registry",
|
||||||
|
unitSource: "none",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sourceKey: "nav_st",
|
||||||
|
readingId: "sensor.param.nav_st",
|
||||||
|
labelSource: "registry",
|
||||||
|
unitSource: "none",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sourceKey: "pwr_ext",
|
||||||
|
readingId: "sensor.param.pwr_ext",
|
||||||
|
labelSource: "registry",
|
||||||
|
unitSource: "none",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
);
|
||||||
|
for (const forbiddenSourceKey of ["CID", "LAC", "MCC", "MNC", "imei", "commands"]) {
|
||||||
|
assert.equal(
|
||||||
|
operationalProjection.entries.some((entry) => entry.sourceKey === forbiddenSourceKey),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const observedExposed = structuredClone(geliosTelemetryFieldRegistryV1);
|
const observedExposed = structuredClone(geliosTelemetryFieldRegistryV1);
|
||||||
observedExposed.entries.find((entry) => entry.sourceKey === "in_0").allowedSurfaces.push("foundry");
|
observedExposed.entries.find((entry) => entry.sourceKey === "in_0").allowedSurfaces.push("foundry");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
|||||||
Reference in New Issue
Block a user