Home Manual Reference Source Test

src/lib/server/CreateNodeStream.js

import { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';
import { DataType } from 'node-opcua/lib/datamodel/variant';
import { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';
import Logger from 'gulplog';
import NodeId from '../model/opcua/NodeId';
import { ReferenceTypeIds, ReferenceTypeNames } from '../model/Node';
import CallScriptStream from './scripts/CallScriptStream';

/**
 * A stream that creates OPC-UA nodes for the passed {@link AtviseFiles}s.
 */
export default class CreateNodeStream extends CallScriptStream {
  /**
   * Id of the *CreateNode* script added with `atscm import`.
   * @type {NodeId}
   */
  get scriptId() {
    return new NodeId(
      NodeId.NodeIdType.STRING,
      'SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.CreateNode',
      1
    );
  }

  /**
   * The options required to create a node for the given file.
   * @param {AtviseFile} file The processed file.
   * @return {Object} The options passed to the *CreateNode* script.
   */
  scriptParameters(file) {
    const options = {
      nodeId: file.nodeId,
      parentNodeId: file.parent ? file.parent.nodeId : 85,
      nodeClass: file.nodeClass.value,
      typeDefinition: file.typeDefinition,
      browseName: file.idName,
    };

    const toParentRefs = file.references.get(ReferenceTypeIds.toParent);
    if (toParentRefs) {
      options.reference = ReferenceTypeNames[[...toParentRefs][0]];
    }

    const rules = file.references.get(ReferenceTypeIds.HasModellingRule);
    if (rules) {
      options.modellingRule = [...rules][0];
    }

    if (file.nodeClass.value === NodeClass.Variable.value) {
      options.dataType = file.variantValue.dataType.value;
      options.valueRank = file.variantValue.arrayType.value;
      options.value = file.variantValue.value;
    }

    return {
      paramObjString: {
        dataType: DataType.String,
        value: JSON.stringify(options),
      },
    };
  }

  /**
   * Prints an error message telling that creating a node failed.
   * @param {AtviseFile} file The file who's node could not be created.
   * @return {string} The resulting error message.
   */
  processErrorMessage(file) {
    return `Error creating node ${file.nodeId}`;
  }

  /**
   * Handles the results of a script call.
   * @param {AtviseFile} file The file the script was called with.
   * @param {node-opcua~Variant[]} outArgs The raw method results.
   * @param {function(err: Error)} callback Called once finished.
   */
  handleOutputArguments(file, outArgs, callback) {
    if (outArgs[0].value !== StatusCodes.Good) {
      callback(new Error(outArgs[1].value));
    } else {
      const [{ value: createdNode }, { value: createFailed }] = outArgs[3].value;

      if (createFailed) {
        Logger.warn('Failed to create node', file.nodeId.toString());
      } else if (createdNode) {
        Logger.debug('Created node', file.nodeId.toString());
        this.push(file);
      } else {
        Logger.debug('Node', file.nodeId.toString(), 'already exists');
        this.push(file);
      }

      callback(null);
    }
  }
}