UNPKG

node-opcua-data-value

Version:

pure nodejs OPCUA SDK - module data-value

619 lines (618 loc) 27.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataValueT = exports.DataValue = void 0; exports.encodeDataValue = encodeDataValue; exports.decodeDataValue = decodeDataValue; exports.apply_timestamps = apply_timestamps; exports.apply_timestamps_no_copy = apply_timestamps_no_copy; exports.extractRange = extractRange; exports.sourceTimestampHasChanged = sourceTimestampHasChanged; exports.serverTimestampHasChanged = serverTimestampHasChanged; exports.timestampHasChanged = timestampHasChanged; exports.sameStatusCode = sameStatusCode; exports.sameDataValue = sameDataValue; /** * @module node-opcua-data-value */ const node_opcua_assert_1 = require("node-opcua-assert"); const node_opcua_date_time_1 = require("node-opcua-date-time"); const node_opcua_factory_1 = require("node-opcua-factory"); const node_opcua_status_code_1 = require("node-opcua-status-code"); const node_opcua_variant_1 = require("node-opcua-variant"); const node_opcua_basic_types_1 = require("node-opcua-basic-types"); const node_opcua_debug_1 = require("node-opcua-debug"); const node_opcua_data_model_1 = require("node-opcua-data-model"); const DataValueEncodingByte_enum_1 = require("./DataValueEncodingByte_enum"); const TimestampsToReturn_enum_1 = require("./TimestampsToReturn_enum"); const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename); // tslint:disable:no-bitwise function getDataValue_EncodingByte(dataValue) { let encodingMask = 0; if (dataValue.value && dataValue.value.dataType !== node_opcua_variant_1.DataType.Null) { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.Value; } // if (dataValue.statusCode !== null ) { if (dataValue.statusCode !== null && typeof dataValue.statusCode === "object" && dataValue.statusCode.value !== 0) { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.StatusCode; } if (dataValue.sourceTimestamp && dataValue.sourceTimestamp !== "null") { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.SourceTimestamp; } // the number of picoseconds that can be encoded are // 100 nano * 10000; // above this the value contains the excess in pico second to make the sourceTimestamp more accurate if (dataValue.sourcePicoseconds ? dataValue.sourcePicoseconds % 100000 : false) { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.SourcePicoseconds; } if (dataValue.serverTimestamp && dataValue.serverTimestamp !== "null") { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerTimestamp; } if (dataValue.serverPicoseconds ? dataValue.serverPicoseconds % 100000 : false) { encodingMask |= DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerPicoseconds; } return encodingMask; } /** * @internal * @param dataValue * @param stream */ function encodeDataValue(dataValue, stream) { const encodingMask = getDataValue_EncodingByte(dataValue); (0, node_opcua_assert_1.assert)(isFinite(encodingMask) && encodingMask >= 0 && encodingMask <= 0x3f); // write encoding byte (0, node_opcua_basic_types_1.encodeUInt8)(encodingMask, stream); // write value as Variant if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.Value) { if (!dataValue.value) { dataValue.value = new node_opcua_variant_1.Variant(); } // c8 ignore next if (!dataValue.value.encode) { errorLog(" CANNOT FIND ENCODE METHOD ON VARIANT !!! HELP", JSON.stringify(dataValue, null, " ")); } dataValue.value.encode(stream); } // write statusCode if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.StatusCode) { (0, node_opcua_basic_types_1.encodeStatusCode)(dataValue.statusCode, stream); } // write sourceTimestamp if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourceTimestamp && dataValue.sourceTimestamp !== null) { (0, node_opcua_basic_types_1.encodeHighAccuracyDateTime)(dataValue.sourceTimestamp, dataValue.sourcePicoseconds, stream); } // write sourcePicoseconds if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourcePicoseconds) { (0, node_opcua_assert_1.assert)(dataValue.sourcePicoseconds !== null); const sourcePicoseconds = Math.floor((dataValue.sourcePicoseconds % 100000) / 10); (0, node_opcua_basic_types_1.encodeUInt16)(sourcePicoseconds, stream); } // write serverTimestamp if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerTimestamp && dataValue.serverTimestamp !== null) { (0, node_opcua_basic_types_1.encodeHighAccuracyDateTime)(dataValue.serverTimestamp, dataValue.serverPicoseconds, stream); } // write serverPicoseconds if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerPicoseconds) { (0, node_opcua_assert_1.assert)(dataValue.serverPicoseconds !== null); const serverPicoseconds = Math.floor((dataValue.serverPicoseconds % 100000) / 10); // we encode 10-picoseconds (0, node_opcua_basic_types_1.encodeUInt16)(serverPicoseconds, stream); } } function decodeDebugDataValue(dataValue, stream, options) { const tracer = options.tracer; let cur = stream.length; const encodingMask = (0, node_opcua_basic_types_1.decodeUInt8)(stream); (0, node_opcua_assert_1.assert)(encodingMask <= 0x3f); tracer.trace("member", "encodingByte", "0x" + encodingMask.toString(16), cur, stream.length, "Mask"); tracer.encoding_byte(encodingMask, DataValueEncodingByte_enum_1.DataValueEncodingByte, cur, stream.length); if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.Value) { dataValue.value = new node_opcua_variant_1.Variant(); dataValue.value.decodeDebug(stream, options); } // read statusCode cur = stream.length; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.StatusCode) { dataValue.statusCode = (0, node_opcua_basic_types_1.decodeStatusCode)(stream); tracer.trace("member", "statusCode", dataValue.statusCode, cur, stream.length, "StatusCode"); } // read sourceTimestamp cur = stream.length; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourceTimestamp) { const [d, picoseconds] = (0, node_opcua_basic_types_1.decodeHighAccuracyDateTime)(stream); dataValue.sourceTimestamp = d; dataValue.sourcePicoseconds = picoseconds | 0; tracer.trace("member", "sourceTimestamp", dataValue.sourceTimestamp, cur, stream.length, "DateTime"); } // read sourcePicoseconds cur = stream.length; dataValue.sourcePicoseconds = 0; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourcePicoseconds) { const tenPico = (0, node_opcua_basic_types_1.decodeUInt16)(stream); dataValue.sourcePicoseconds += tenPico * 10; tracer.trace("member", "sourcePicoseconds", dataValue.sourcePicoseconds, cur, stream.length, "UInt16"); } // read serverTimestamp cur = stream.length; dataValue.serverPicoseconds = 0; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerTimestamp) { const [d, picoseconds] = (0, node_opcua_basic_types_1.decodeHighAccuracyDateTime)(stream); dataValue.serverTimestamp = d; dataValue.serverPicoseconds = picoseconds | 0; tracer.trace("member", "serverTimestamp", dataValue.serverTimestamp, cur, stream.length, "DateTime"); } // read serverPicoseconds cur = stream.length; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerPicoseconds) { const tenPico = (0, node_opcua_basic_types_1.decodeUInt16)(stream); dataValue.serverPicoseconds += tenPico * 10; tracer.trace("member", "serverPicoseconds", dataValue.serverPicoseconds, cur, stream.length, "UInt16"); } } function decodeDataValueInternal(dataValue, stream) { const encodingMask = (0, node_opcua_basic_types_1.decodeUInt8)(stream); if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.Value) { dataValue.value = new node_opcua_variant_1.Variant(); dataValue.value.decode(stream); } // read statusCode if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.StatusCode) { dataValue.statusCode = (0, node_opcua_basic_types_1.decodeStatusCode)(stream); } else { dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good; } dataValue.sourcePicoseconds = 0; // read sourceTimestamp if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourceTimestamp) { const [d, picoseconds] = (0, node_opcua_basic_types_1.decodeHighAccuracyDateTime)(stream); dataValue.sourceTimestamp = d; dataValue.sourcePicoseconds += picoseconds | 0; } // read sourcePicoseconds if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.SourcePicoseconds) { dataValue.sourcePicoseconds += (0, node_opcua_basic_types_1.decodeUInt16)(stream) * 10; } // read serverTimestamp dataValue.serverPicoseconds = 0; if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerTimestamp) { const [d, picoseconds] = (0, node_opcua_basic_types_1.decodeHighAccuracyDateTime)(stream); dataValue.serverTimestamp = d; dataValue.serverPicoseconds += picoseconds | 0; } // read serverPicoseconds if (encodingMask & DataValueEncodingByte_enum_1.DataValueEncodingByte.ServerPicoseconds) { dataValue.serverPicoseconds += (0, node_opcua_basic_types_1.decodeUInt16)(stream) * 10; } } function decodeDataValue(stream, dataValue) { dataValue = dataValue || new DataValue(); decodeDataValueInternal(dataValue, stream); return dataValue; } function isValidDataValue(self) { if (self.value !== null && typeof self.value === "object") { (0, node_opcua_assert_1.assert)(self.value); return self.value.isValid(); } else { (0, node_opcua_assert_1.assert)(!self.value); // in this case StatusCode shall not be Good (0, node_opcua_assert_1.assert)(self.statusCode.isNotGood()); } return true; } // OPC-UA part 4 - $7.7 const schemaDataValue = (0, node_opcua_factory_1.buildStructuredType)({ baseType: "BaseUAObject", name: "DataValue", category: node_opcua_factory_1.FieldCategory.basic, fields: [ { name: "Value", fieldType: "Variant", defaultValue: null }, { name: "StatusCode", fieldType: "StatusCode", defaultValue: node_opcua_status_code_1.StatusCodes.Good }, { name: "SourceTimestamp", fieldType: "DateTime", defaultValue: null }, { name: "SourcePicoseconds", fieldType: "UInt16", defaultValue: 0 }, { name: "ServerTimestamp", fieldType: "DateTime", defaultValue: null }, { name: "ServerPicoseconds", fieldType: "UInt16", defaultValue: 0 } ] }); function toMicroNanoPico(picoseconds) { return "" + w((picoseconds / 1000000) >> 0) + "." + w(((picoseconds % 1000000) / 1000) >> 0) + "." + w(picoseconds % 1000 >> 0); // + " (" + picoseconds+ ")"; } function d(timestamp, picoseconds) { return timestamp ? timestamp.toISOString() + " $ " + toMicroNanoPico(picoseconds) : "null"; // + " " + (this.serverTimestamp ? this.serverTimestamp.getTime() :"-"); } const emptyObject = {}; class DataValue extends node_opcua_factory_1.BaseUAObject { /** * @internal */ static possibleFields = [ "value", "statusCode", "sourceTimestamp", "sourcePicoseconds", "serverTimestamp", "serverPicoseconds" ]; /** * @internal */ static schema = schemaDataValue; value; statusCode; sourceTimestamp; sourcePicoseconds; serverTimestamp; serverPicoseconds; /** * */ constructor(options) { super(); if (options === null) { this.statusCode = node_opcua_status_code_1.StatusCodes.Bad; this.sourceTimestamp = null; this.sourcePicoseconds = 0; this.serverTimestamp = null; this.serverPicoseconds = 0; this.value = new node_opcua_variant_1.Variant(null); return; } options = options || emptyObject; /* c8 ignore next */ if (node_opcua_factory_1.parameters.debugSchemaHelper) { const schema = schemaDataValue; (0, node_opcua_factory_1.check_options_correctness_against_schema)(this, schema, options); } if (options.value === undefined || options.value === null) { this.value = new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Null }); } else { this.value = options.value ? new node_opcua_variant_1.Variant(options.value) : new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Null }); } this.statusCode = (0, node_opcua_status_code_1.coerceStatusCode)(options.statusCode || node_opcua_status_code_1.StatusCodes.Good); this.sourceTimestamp = options.sourceTimestamp ? (0, node_opcua_date_time_1.coerceDateTime)(options.sourceTimestamp) : null; this.sourcePicoseconds = options.sourcePicoseconds || 0; this.serverTimestamp = options.serverTimestamp ? (0, node_opcua_date_time_1.coerceDateTime)(options.serverTimestamp) : null; this.serverPicoseconds = options.serverPicoseconds || 0; } encode(stream) { encodeDataValue(this, stream); } decode(stream) { decodeDataValueInternal(this, stream); } decodeDebug(stream, options) { decodeDebugDataValue(this, stream, options); } isValid() { return isValidDataValue(this); } toString() { let str = "{ /* DataValue */"; if (this.value) { str += "\n" + " value: " + node_opcua_variant_1.Variant.prototype.toString.apply(this.value); // this.value.toString(); } else { str += "\n" + " value: <null>"; } str += "\n" + " statusCode: " + (this.statusCode ? this.statusCode.toString() : "null"); str += "\n" + " serverTimestamp: " + d(this.serverTimestamp, this.serverPicoseconds); str += "\n" + " sourceTimestamp: " + d(this.sourceTimestamp, this.sourcePicoseconds); str += "\n" + "}"; return str; } clone() { return new DataValue({ serverPicoseconds: this.serverPicoseconds, serverTimestamp: this.serverTimestamp, sourcePicoseconds: this.sourcePicoseconds, sourceTimestamp: this.sourceTimestamp, statusCode: this.statusCode, value: this.value ? this.value.clone() : undefined }); } } exports.DataValue = DataValue; DataValue.prototype.schema = DataValue.schema; (0, node_opcua_factory_1.registerSpecialVariantEncoder)(DataValue); function w(n) { return n.toString().padStart(3, "0"); } function _partial_clone(dataValue) { const cloneDataValue = new DataValue({ value: undefined }); cloneDataValue.value = dataValue.value; cloneDataValue.statusCode = dataValue.statusCode; return cloneDataValue; } /** * apply the provided timestampsToReturn flag to the dataValue and return a cloned dataValue * with the specified timestamps. * @param dataValue * @param timestampsToReturn * @param attributeId * @returns */ function apply_timestamps(dataValue, timestampsToReturn, attributeId) { let cloneDataValue = null; let now = null; // apply timestamps switch (timestampsToReturn) { case TimestampsToReturn_enum_1.TimestampsToReturn.Neither: cloneDataValue = cloneDataValue || _partial_clone(dataValue); break; case TimestampsToReturn_enum_1.TimestampsToReturn.Server: cloneDataValue = cloneDataValue || _partial_clone(dataValue); cloneDataValue.serverTimestamp = dataValue.serverTimestamp; cloneDataValue.serverPicoseconds = dataValue.serverPicoseconds; if (!cloneDataValue.serverTimestamp) { now = now || (0, node_opcua_date_time_1.getCurrentClock)(); cloneDataValue.serverTimestamp = now.timestamp; cloneDataValue.serverPicoseconds = now.picoseconds; } break; case TimestampsToReturn_enum_1.TimestampsToReturn.Source: cloneDataValue = cloneDataValue || _partial_clone(dataValue); cloneDataValue.sourceTimestamp = dataValue.sourceTimestamp; cloneDataValue.sourcePicoseconds = dataValue.sourcePicoseconds; break; case TimestampsToReturn_enum_1.TimestampsToReturn.Both: default: (0, node_opcua_assert_1.assert)(timestampsToReturn === TimestampsToReturn_enum_1.TimestampsToReturn.Both); cloneDataValue = cloneDataValue || _partial_clone(dataValue); cloneDataValue.serverTimestamp = dataValue.serverTimestamp; cloneDataValue.serverPicoseconds = dataValue.serverPicoseconds; if (!dataValue.serverTimestamp) { now = now || (0, node_opcua_date_time_1.getCurrentClock)(); cloneDataValue.serverTimestamp = now.timestamp; cloneDataValue.serverPicoseconds = now.picoseconds; } cloneDataValue.sourceTimestamp = dataValue.sourceTimestamp; cloneDataValue.sourcePicoseconds = dataValue.sourcePicoseconds; break; } // unset sourceTimestamp unless AttributeId is Value if (attributeId !== node_opcua_data_model_1.AttributeIds.Value) { cloneDataValue.sourceTimestamp = null; } return cloneDataValue; } /** * * @param dataValue a DataValue * @param timestampsToReturn a TimestampsToReturn flag to determine which timestamp should be kept * @param attributeId if attributeId is not Value, sourceTimestamp will forcefully be set to null * @param now an optional current clock to be used to set the serverTimestamp * @returns */ function apply_timestamps_no_copy(dataValue, timestampsToReturn, attributeId, now) { switch (timestampsToReturn) { case TimestampsToReturn_enum_1.TimestampsToReturn.Neither: dataValue.sourceTimestamp = null; dataValue.sourcePicoseconds = 0; dataValue.serverTimestamp = null; dataValue.serverPicoseconds = 0; break; case TimestampsToReturn_enum_1.TimestampsToReturn.Server: dataValue.sourceTimestamp = null; dataValue.sourcePicoseconds = 0; if (!dataValue.serverTimestamp) { now = now || (0, node_opcua_date_time_1.getCurrentClock)(); dataValue.serverTimestamp = now.timestamp; dataValue.serverPicoseconds = now.picoseconds; } break; case TimestampsToReturn_enum_1.TimestampsToReturn.Source: break; case TimestampsToReturn_enum_1.TimestampsToReturn.Both: default: (0, node_opcua_assert_1.assert)(timestampsToReturn === TimestampsToReturn_enum_1.TimestampsToReturn.Both); if (!dataValue.serverTimestamp) { now = now || (0, node_opcua_date_time_1.getCurrentClock)(); dataValue.serverTimestamp = now.timestamp; dataValue.serverPicoseconds = now.picoseconds; } break; } // unset sourceTimestamp unless AttributeId is Value if (attributeId !== node_opcua_data_model_1.AttributeIds.Value) { dataValue.sourceTimestamp = null; } return dataValue; } /** * @deprecated */ function apply_timestamps2(dataValue, timestampsToReturn, attributeId) { (0, node_opcua_assert_1.assert)(attributeId > 0); (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(dataValue, "serverTimestamp")); (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(dataValue, "sourceTimestamp")); const cloneDataValue = new DataValue({}); cloneDataValue.value = dataValue.value; cloneDataValue.statusCode = dataValue.statusCode; const now = (0, node_opcua_date_time_1.getCurrentClock)(); // apply timestamps switch (timestampsToReturn) { case TimestampsToReturn_enum_1.TimestampsToReturn.Server: cloneDataValue.serverTimestamp = dataValue.serverTimestamp; cloneDataValue.serverPicoseconds = dataValue.serverPicoseconds; cloneDataValue.serverTimestamp = now.timestamp; cloneDataValue.serverPicoseconds = now.picoseconds; break; case TimestampsToReturn_enum_1.TimestampsToReturn.Source: cloneDataValue.sourceTimestamp = dataValue.sourceTimestamp; cloneDataValue.sourcePicoseconds = dataValue.sourcePicoseconds; break; case TimestampsToReturn_enum_1.TimestampsToReturn.Both: cloneDataValue.serverTimestamp = dataValue.serverTimestamp; cloneDataValue.serverPicoseconds = dataValue.serverPicoseconds; cloneDataValue.serverTimestamp = now.timestamp; cloneDataValue.serverPicoseconds = now.picoseconds; cloneDataValue.sourceTimestamp = dataValue.sourceTimestamp; cloneDataValue.sourcePicoseconds = dataValue.sourcePicoseconds; break; } // unset sourceTimestamp unless AttributeId is Value if (attributeId !== node_opcua_data_model_1.AttributeIds.Value) { cloneDataValue.sourceTimestamp = null; } return cloneDataValue; } /* * @param dataValue * @param result * @return {DataValue} * @private * @static */ function _clone_with_array_replacement(dataValue, result) { const statusCode = result.statusCode.isGood() ? dataValue.statusCode : result.statusCode; const clonedDataValue = new DataValue({ statusCode, serverTimestamp: dataValue.serverTimestamp, serverPicoseconds: dataValue.serverPicoseconds, sourceTimestamp: dataValue.sourceTimestamp, sourcePicoseconds: dataValue.sourcePicoseconds, value: { dataType: node_opcua_variant_1.DataType.Null } }); clonedDataValue.value.dataType = dataValue.value.dataType; clonedDataValue.value.arrayType = dataValue.value.arrayType; clonedDataValue.value.dimensions = result.dimensions; if (Array.isArray(result.array)) { clonedDataValue.value.value = [...result.array]; } else { clonedDataValue.value.value = result.array; } return clonedDataValue; } function canRange(dataValue) { return (dataValue.value && (dataValue.value.arrayType !== node_opcua_variant_1.VariantArrayType.Scalar || (dataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Scalar && dataValue.value.dataType === node_opcua_variant_1.DataType.ByteString) || (dataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Scalar && dataValue.value.dataType === node_opcua_variant_1.DataType.String))); } /** * return a deep copy of the dataValue by applying indexRange if necessary on Array/Matrix * @param dataValue {DataValue} * @param indexRange {NumericalRange} * @return {DataValue} */ function extractRange(dataValue, indexRange) { const variant = dataValue.value; if (indexRange && canRange(dataValue)) { if (!indexRange.isValid()) { return new DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadIndexRangeInvalid }); } // let's extract an array of elements corresponding to the indexRange const result = indexRange.extract_values(variant.value, variant.dimensions); dataValue = _clone_with_array_replacement(dataValue, result); } else { // clone the whole data Value dataValue = dataValue.clone(); } return dataValue; } function sameDate(date1, date2) { if (date1 === date2) { return true; } if (date1 && date2 === null) { return false; } if (date1 === null && date2) { return false; } if (date1 === null || date2 === null) { return false; } return date1.getTime() === date2.getTime(); } /** * returns true if the sourceTimestamp and sourcePicoseconds of the two dataValue are different * @param dataValue1 * @param dataValue2 * @returns */ function sourceTimestampHasChanged(dataValue1, dataValue2) { return (!sameDate(dataValue1.sourceTimestamp, dataValue2.sourceTimestamp) || dataValue1.sourcePicoseconds !== dataValue2.sourcePicoseconds); } /** * returns true if the serverTimestamp and serverPicoseconds of the two dataValue are different * @param dataValue1 * @param dataValue2 * @returns */ function serverTimestampHasChanged(dataValue1, dataValue2) { return (!sameDate(dataValue1.serverTimestamp, dataValue2.serverTimestamp) || dataValue1.serverPicoseconds !== dataValue2.serverPicoseconds); } /** * return if the timestamps of the two dataValue are different * * - if timestampsToReturn is not specified, both sourceTimestamp are compared * - if timestampsToReturn is **Neither**, the function returns false * - if timestampsToReturn is **Both**, both sourceTimestamp and serverTimestamp are compared * - if timestampsToReturn is **Source**, only sourceTimestamp are compared * - if timestampsToReturn is **Server**, only serverTimestamp are compared * * @param dataValue1 * @param dataValue2 * @param timestampsToReturn * @returns */ function timestampHasChanged(dataValue1, dataValue2, timestampsToReturn) { // TODO: timestampsToReturn = timestampsToReturn || { key: "Neither"}; if (timestampsToReturn === undefined) { return sourceTimestampHasChanged(dataValue1, dataValue2); // || serverTimestampHasChanged(dataValue1, dataValue2); } switch (timestampsToReturn) { case TimestampsToReturn_enum_1.TimestampsToReturn.Neither: return false; case TimestampsToReturn_enum_1.TimestampsToReturn.Both: return sourceTimestampHasChanged(dataValue1, dataValue2) || serverTimestampHasChanged(dataValue1, dataValue2); case TimestampsToReturn_enum_1.TimestampsToReturn.Source: return sourceTimestampHasChanged(dataValue1, dataValue2); default: (0, node_opcua_assert_1.assert)(timestampsToReturn === TimestampsToReturn_enum_1.TimestampsToReturn.Server); return serverTimestampHasChanged(dataValue1, dataValue2); } } /** * @param statusCode1 * @param statusCode2 * @returns true if the two statusCodes are identical, i.e have the same value */ function sameStatusCode(statusCode1, statusCode2) { return statusCode1.value === statusCode2.value; } /** * @return {boolean} true if data values are identical */ function sameDataValue(v1, v2, timestampsToReturn) { if (v1 === v2) { return true; } if (v1 && !v2) { return false; } if (v2 && !v1) { return false; } if (!sameStatusCode(v1.statusCode, v2.statusCode)) { return false; } if (timestampHasChanged(v1, v2, timestampsToReturn)) { return false; } return (0, node_opcua_variant_1.sameVariant)(v1.value, v2.value); } class DataValueT extends DataValue { } exports.DataValueT = DataValueT; //# sourceMappingURL=datavalue.js.map