From acb7ed22e185575dc2f2f11d5929a49dbef23cc5 Mon Sep 17 00:00:00 2001 From: Alex Godbehere Date: Tue, 1 Oct 2024 13:55:48 +0100 Subject: [PATCH] Refactor typeHandler and add timestamp conversion logic Consolidated log import and formatted long conditions for better readability. Implemented timestamp conversion to ensure consistency with upstream expectations of milliseconds format by detecting and converting from seconds if necessary. --- acs-edge/lib/helpers/typeHandler.ts | 51 +++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/acs-edge/lib/helpers/typeHandler.ts b/acs-edge/lib/helpers/typeHandler.ts index 18dc10b8..e9981d2b 100644 --- a/acs-edge/lib/helpers/typeHandler.ts +++ b/acs-edge/lib/helpers/typeHandler.ts @@ -10,7 +10,7 @@ import * as jsonpointer from 'jsonpointer'; import * as Long from "long"; import {MessageSecurityMode, SecurityPolicy} from "node-opcua"; import {Address} from "@amrc-factoryplus/utilities"; -import {log, logf} from "./log.js"; +import {log} from "./log.js"; export enum serialisationType { ignored = "Defined by Protocol", @@ -250,7 +250,8 @@ export class Metrics { const metric = this.#array[i]; this.#nameIndex[metric.name || ""] = i; // this.#aliasIndex[metric.alias as number] = i; - if (metric.properties != null && metric.properties.address != null && metric.properties.path != null && (metric.properties.method.value as string).search(/^GET/g) > -1) { + if (metric.properties != null && metric.properties.address != null && metric.properties.path != null && (metric.properties.method.value as string).search( + /^GET/g) > -1) { const addr = metric.properties.address.value as string; if (!this.#addrIndex[addr]) { this.#addrIndex[addr] = []; @@ -382,8 +383,11 @@ export function parseValueFromPayload(msg: any, metric: sparkplugMetric, payload if (path) { /* Work around a bug in the JSONPath library */ let newVal = path === "$" && payload === false - ? [ false ] - : JSONPath({path: path, json: payload}); + ? [false] + : JSONPath({ + path: path, + json: payload + }); if (payload === 0 || !Array.isArray(newVal)) { return 0; } else { @@ -467,14 +471,49 @@ export function parseTimeStampFromPayload(msg: any, metric: sparkplugMetric, pay } const timestamp = JSONPath({ - path: '$.timestamp', json: payload + path: '$.timestamp', + json: payload }); - return Array.isArray(timestamp) ? timestamp[0] : undefined; + + const extractedTimestamp = Array.isArray(timestamp) ? timestamp[0] : undefined; + + // The timestamp will be a unix timestamp in milliseconds or + // seconds, however upstream Factory+ expects it to be in + // milliseconds. Here, we detect if the timestamp is in seconds + // and convert it to milliseconds if necessary. + + if (extractedTimestamp) { + if (isTimestampInMilliseconds(extractedTimestamp)) { + return extractedTimestamp; + } + + return extractedTimestamp * 1000; + } + + return undefined; + default: return undefined; } } +function isTimestampInMilliseconds(timestamp: number) { + // Convert the timestamp to a number (in case it's a string) + timestamp = Number(timestamp); + + // Check if the timestamp is in milliseconds or seconds + if (timestamp > 1e12) { + // If it's larger than 1e12 (approximately 13 digits), it's in milliseconds + return true; + } else if (timestamp > 1e9 && timestamp <= 1e12) { + // If it's between 1e9 and 1e12 (approximately 10 digits), it's in seconds + return false; + } + + // Return false by default if the timestamp is outside expected ranges + return false; +} + function parseTypeFromString(type: string, val: any) { // Pass straight through if not a string