How to use node-opcua-service-history - 10 common examples

To help you get started, we’ve selected a few node-opcua-service-history examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github node-opcua / node-opcua / packages / node-opcua-server / source / server_engine.ts View on Github external
assert(context instanceof SessionContext);
    assert(callback instanceof Function);

    const nodeId = nodeToRead.nodeId;
    const indexRange = nodeToRead.indexRange;
    const dataEncoding = nodeToRead.dataEncoding;
    const continuationPoint = nodeToRead.continuationPoint;

    timestampsToReturn = (_.isObject(timestampsToReturn)) ? timestampsToReturn : TimestampsToReturn.Neither;

    const obj = this.__findObject(nodeId) as UAVariable;

    if (!obj) {
      // may be return BadNodeIdUnknown in dataValue instead ?
      // Object Not Found
      callback(null, new HistoryReadResult({ statusCode: StatusCodes.BadNodeIdUnknown }));
      return;

    } else {

      if (!obj.historyRead) {
        // note : Object and View may also support historyRead to provide Event historical data
        //        todo implement historyRead for Object and View
        const msg = " this node doesn't provide historyRead! probably not a UAVariable\n "
          + obj.nodeId.toString() + " " + obj.browseName.toString() + "\n"
          + "with " + nodeToRead.toString() + "\n"
          + "HistoryReadDetails " + historyReadDetails.toString();
        if (doDebug) {
          console.log(chalk.cyan("ServerEngine#_historyReadSingleNode "),
            chalk.white.bold(msg));
        }
        const err = new Error(msg);
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
});
      return callback(null, result);
    }

  } else if (isMinDate(historyReadRawModifiedDetails.startTime!)) {
    // start time is not specified
    // end time is specified
    maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
    isReversed = true;
    reverseDataValue = false;

    if (historyReadRawModifiedDetails.numValuesPerNode === 0) {
      // when start time is not specified
      // and end time is specified
      // numValuesPerNode shall be greater than 0
      const result = new HistoryReadResult({
        statusCode: StatusCodes.BadHistoryOperationUnsupported // should be an error
      });
      return callback(null, result);
    }
  } else {
    // start time is specified
    // end time is specified
    if (historyReadRawModifiedDetails.endTime!.getTime() < historyReadRawModifiedDetails.startTime!.getTime()) {
      reverseDataValue = true;
      const tmp = historyReadRawModifiedDetails.endTime;
      historyReadRawModifiedDetails.endTime = historyReadRawModifiedDetails.startTime;
      historyReadRawModifiedDetails.startTime = tmp;
    }
  }

  node._historyReadRawAsync(
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
(err: Error | null, dataValues?: DataValue[]) => {

      if (err || !dataValues) {
        return callback(err);
      }

      // now make sure that only the requested number of value is returned
      if (historyReadRawModifiedDetails.numValuesPerNode >= 1) {
        if (dataValues.length === 0) {
          const result1 = new HistoryReadResult({
            historyData: new HistoryData({ dataValues: [] }),
            statusCode: StatusCodes.GoodNoData
          });
          return callback(null, result1);
        } else {
          const remaining = dataValues;
          dataValues = remaining.splice(0, historyReadRawModifiedDetails.numValuesPerNode);

          if (remaining.length > 0 && !isMinDate(historyReadRawModifiedDetails.endTime)) {
            continuationPoint = createContinuationPoint();
            context.continuationPoints = context.continuationPoints || {};
            context.continuationPoints[continuationPoint.toString("hex")] = {
              dataValues: remaining
            };
          }
        }
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
if (!cnt) {
      // invalid continuation point
      const result1 = new HistoryReadResult({
        historyData: new HistoryData({ dataValues: [] }),
        statusCode: StatusCodes.BadContinuationPointInvalid
      });
      return callback(null, result1);
    }
    const dataValues = cnt.dataValues.splice(0, historyReadRawModifiedDetails.numValuesPerNode);
    if (cnt.dataValues.length > 0) {
      //
    } else {
      context.continuationPoints[continuationPoint.toString("hex")] = null;
      continuationPoint = null;
    }
    const result2 = new HistoryReadResult({
      continuationPoint: continuationPoint || undefined,
      historyData: new HistoryData({ dataValues }),
      statusCode: StatusCodes.Good
    });
    return callback(null, result2);
  }

  // todo add special treatment for when startTime > endTime
  // ( in this case series must be return in reverse order )

  let maxNumberToExtract = 0;
  let isReversed = false;
  let reverseDataValue = false;
  if (isMinDate(historyReadRawModifiedDetails.endTime!)) {
    // end time is not specified
    maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
// values with the same timestamp should be from the most recent to oldest modification
  // timestamp, if startTime is less than or equal to endTime. If endTime is less than startTime,
  // then the order of the returned values will be from the oldest modification timestamp to the
  // most recent. It is Server dependent whether multiple modifications are kept or only the most
  // recent.
  // A Server does not have to create a modification record for data when it is first added to the
  // historical collection. If it does then it shall set the ExtraData bit and the Client can read the
  // modification record using a ReadModified call. If the data is subsequently modified the Server
  // shall create a second modification record which is returned along with the original
  // modification record whenever a Client uses the ReadModified call if the Server supports
  // multiple modification records per timestamp.
  // If the requested TimestampsToReturn is not supported for a Node then the operation shall
  // return the BadTimestampNotSupported StatusCode.

  // todo : provide correct implementation
  const result = new HistoryReadResult({
    historyData: new HistoryData({ dataValues: [] }),
    statusCode: StatusCodes.BadUnexpectedError
  });
  return callback(null, result);
}
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
// For cases where there are multiple values for a given timestamp, all but the most recent are
  // considered to be Modified values and the Server shall return the most recent value. If the
  // Server returns a value which hides other values at a timestamp then it shall set the ExtraData
  // bit in the StatusCode associated with that value. If the Server contains additional information
  // regarding a value then the ExtraData bit shall also be set. It indicates that ModifiedValues are
  // available for retrieval, see 6.4.3.3.
  //
  // If the requested TimestampsToReturn is not supported for a Node, the operation shall return
  // the Bad_TimestampNotSupported StatusCode.

  if (continuationPoint) {
    const cnt = context.continuationPoints
      ? context.continuationPoints[continuationPoint.toString("hex")] : null;
    if (!cnt) {
      // invalid continuation point
      const result1 = new HistoryReadResult({
        historyData: new HistoryData({ dataValues: [] }),
        statusCode: StatusCodes.BadContinuationPointInvalid
      });
      return callback(null, result1);
    }
    const dataValues = cnt.dataValues.splice(0, historyReadRawModifiedDetails.numValuesPerNode);
    if (cnt.dataValues.length > 0) {
      //
    } else {
      context.continuationPoints[continuationPoint.toString("hex")] = null;
      continuationPoint = null;
    }
    const result2 = new HistoryReadResult({
      continuationPoint: continuationPoint || undefined,
      historyData: new HistoryData({ dataValues }),
      statusCode: StatusCodes.Good
github node-opcua / node-opcua / packages / node-opcua-server / source / server_engine.ts View on Github external
(err: Error | null, result?: any) => {

            if (err && !result) {
              result = new HistoryReadResult({ statusCode: StatusCodes.BadInternalError });
            }
            historyData.push(result);
            async.setImmediate(cbNode);
            // it's not guaranteed that the historical read process is really asynchronous
          });
      }, (err?: Error | null) => {
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
// follow the same rules as the standard Interpolated Aggregate as outlined in Part 13.
    // If the useSimpleBounds flag is True and Interpolation is required then simple bounding values
    // will be used to calculate the data value. If useSimpleBounds is False and Interpolation is
    // required then interpolated bounding values will be used to calculate the data value. See
    // Part 13 for the definition of simple bounding values and interpolated bounding values.
    // If a value is found for the specified timestamp, then the Server will set the StatusCode
    // InfoBits to be Raw. If the value is Interpolated from the surrounding values, then the Server
    // will set the StatusCode InfoBits to be Interpolated.
    // If the read request is taking a long time to calculate then the Server may return zero results
    // with a ContinuationPoint that allows the Server to resume the calculation on the next Client
    // HistoryRead call.
    // If the requested TimestampsToReturn is not supported for a Node, then the operation shall
    // return the Bad_TimestampNotSupported StatusCode.

    // todo provide correct implementation
    const result = new HistoryReadResult({
      historyData: new HistoryData({ dataValues: [] }),
      statusCode: StatusCodes.BadHistoryOperationUnsupported
    });
    return callback(null, result);

  } else {
    const result = new HistoryReadResult({
      historyData: new HistoryData({ dataValues: [] }),
      statusCode: StatusCodes.BadHistoryOperationUnsupported
    });
    return callback(null, result);
  }
}
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
// that falls directly on the timestamp ending the interval. Thus, each value shall be included
    // only once in the calculation. If the time domain is in reverse order then we consider the later
    // timestamp to be the one beginning the sub interval, and the earlier timestamp to be the one
    // ending it. Note that this means that simply swapping the start and end times will not result in
    // getting the same values back in reverse order as the intervals being requested in the two
    // cases are not the same.
    // If an Aggregate is taking a long time to calculate then the Server can return partial results
    // with a continuation point. This might be done if the calculation is going to take more time th an
    // the Client timeout hint. In some cases it may take longer than the Client timeout hint to
    // calculate even one Aggregate result. Then the Server may return zero results with a
    // continuation point that allows the Server to resume the calculation on the next Client read
    // call.

    // todo provide correct implementation
    const result = new HistoryReadResult({
      historyData: new HistoryData({ dataValues: [] }),
      statusCode: StatusCodes.BadHistoryOperationUnsupported
    });
    return callback(null, result);

  } else if (historyReadDetails instanceof ReadAtTimeDetails) {

    // Release 1.03 28 OPC Unified Architecture, Part 11
    // The ReadAtTimeDetails structure reads the values and qualities from the history database for
    // the specified timestamps for one or more HistoricalDataNodes. This function is intended to
    // provide values to correlate with other values with a known timestamp. For example, a Client
    // may need to read the values of sensors when lab samples were collected.
    // The order of the values and qualities returned shall match the order of the timestamps
    // supplied in the request.
    // When no value exists for a specified timestamp, a value shall be Interpolated from the
    // surrounding values to represent the value at the specified timestamp. The interpolation will
    // follow the same rules as the standard Interpolated Aggregate as outlined in Part 13.
github node-opcua / node-opcua / packages / node-opcua-address-space / src / historical_access / address_space_historical_data_node.ts View on Github external
// considered to be Modified values and the Server shall return the most recent value. If the
  // Server returns a value which hides other values at a timestamp then it shall set the ExtraData
  // bit in the StatusCode associated with that value. If the Server contains additional information
  // regarding a value then the ExtraData bit shall also be set. It indicates that ModifiedValues are
  // available for retrieval, see 6.4.3.3.
  //
  // If the requested TimestampsToReturn is not supported for a Node, the operation shall return
  // the Bad_TimestampNotSupported StatusCode.

  if (continuationPoint) {
    const cnt = context.continuationPoints
      ? context.continuationPoints[continuationPoint.toString("hex")] : null;
    if (!cnt) {
      // invalid continuation point
      const result1 = new HistoryReadResult({
        historyData: new HistoryData({ dataValues: [] }),
        statusCode: StatusCodes.BadContinuationPointInvalid
      });
      return callback(null, result1);
    }
    const dataValues = cnt.dataValues.splice(0, historyReadRawModifiedDetails.numValuesPerNode);
    if (cnt.dataValues.length > 0) {
      //
    } else {
      context.continuationPoints[continuationPoint.toString("hex")] = null;
      continuationPoint = null;
    }
    const result2 = new HistoryReadResult({
      continuationPoint: continuationPoint || undefined,
      historyData: new HistoryData({ dataValues }),
      statusCode: StatusCodes.Good
    });