- "use strict";
-
- /**
- * @module opcua.address_space
- */
- const assert = require("node-opcua-assert").assert;
- const util = require("util");
- const _ = require("underscore");
-
-
-
- const NodeClass = require("node-opcua-data-model").NodeClass;
- const AttributeIds = require("node-opcua-data-model").AttributeIds;
-
- const DataValue = require("node-opcua-data-value").DataValue;
-
- const DataType = require("node-opcua-variant").DataType;
- const Variant = require("node-opcua-variant").Variant;
-
- const StatusCodes = require("node-opcua-status-code").StatusCodes;
-
- const BaseNode = require("./base_node").BaseNode;
- const UAVariable = require("./ua_variable").UAVariable;
- const SessionContext = require("./session_context").SessionContext;
-
-
- function UAMethod(options) {
-
- BaseNode.apply(this, arguments);
- // assert(this.typeDefinition.value === resolveNodeId("MethodType").value);
- this.value = options.value;
- this.methodDeclarationId = options.methodDeclarationId;
-
- }
- util.inherits(UAMethod, BaseNode);
- UAMethod.prototype.nodeClass = NodeClass.Method;
-
-
- UAMethod.prototype.getExecutableFlag = function (context) {
- assert(context instanceof SessionContext);
- if (!_.isFunction(this._asyncExecutionFunction)) {
- return false;
- }
- if (this._getExecutableFlag) {
- return this._getExecutableFlag(context);
- }
- return true;
- };
-
- UAMethod.prototype.readAttribute = function (context, attributeId) {
-
- assert(context instanceof SessionContext);
-
- const self = this;
- const options = {};
- switch (attributeId) {
- case AttributeIds.Executable:
- options.value = {dataType: DataType.Boolean, value: self.getExecutableFlag(context)};
- options.statusCode = StatusCodes.Good;
- break;
- case AttributeIds.UserExecutable:
- options.value = {dataType: DataType.Boolean, value: self.getExecutableFlag(context)};
- options.statusCode = StatusCodes.Good;
- break;
- default:
- return BaseNode.prototype.readAttribute.call(this, context, attributeId);
- }
- return new DataValue(options);
- };
-
-
-
-
- function default_check_valid_argument(arg) {
- return arg.constructor.name === "Argument";
- /*
- var Argument = require("./_generated_/_auto_generated_Argument").Argument;
- return arg instanceof Argument
- */
- }
-
- UAMethod.checkValidArgument = default_check_valid_argument;
-
- UAMethod.prototype._getArguments = function (name) {
-
- assert(name === "InputArguments" || name === "OutputArguments");
- const argsVariable = this.getPropertyByName(name);
- if (!argsVariable) { return [];}
-
- assert(argsVariable instanceof UAVariable);
-
- const args = argsVariable.readValue().value.value;
-
- // a list of extension object
- assert(_.isArray(args));
- assert(args.length === 0 || UAMethod.checkValidArgument(args[0]) );
- return args;
-
- };
-
- UAMethod.prototype.getInputArguments = function () {
- return this._getArguments("InputArguments");
- };
-
- UAMethod.prototype.getOutputArguments = function () {
- return this._getArguments("OutputArguments");
-
- };
-
- /**
- * @method bindMethod
- * @param async_func {Function}
- * @param async_func.inputArguments
- * @param async_func.context
- * @param async_func.callback {Function}
- * @param async_func.callback.err {Error|null}
- * @param async_func.callback.callMethodResponse.statusCode {StatusCode}
- * @param async_func.callback.callMethodResponse.outputArguments {Variant[]}
- */
- UAMethod.prototype.bindMethod = function (async_func) {
- assert(_.isFunction(async_func));
- const self = this;
- self._asyncExecutionFunction = async_func;
- };
-
-
- /**
- * @method execute
- * @async
- * @param context {SessionContext}
- * @param inputArguments {null|Variant[]} input arguments as array of variant
- * @param callback
- * @async
- */
- UAMethod.prototype.execute = function (inputArguments, context, callback) {
- assert(inputArguments === null || _.isArray(inputArguments));
- assert(context instanceof SessionContext);
- inputArguments = inputArguments ||[];
- inputArguments = inputArguments.map(Variant.coerce);
- assert(inputArguments.length === 0 || inputArguments[0] instanceof Variant);
- assert(_.isObject(context));
- assert(_.isFunction(callback));
- const self = this;
-
- // a context object must be provided
- if (!context.object) {
- context.object = self.parent;
- }
-
- assert(context.object instanceof BaseNode);
-
- //xx inputArguments = inputArguments.map(function(a) { return Variant.coerce(a); });
- //xx inputArguments.forEach(function(arg){ assert(arg instanceof Variant); });
-
- if (!self._asyncExecutionFunction) {
- console.log("Method " + self.nodeId.toString() + " " + self.browseName.toString() + "_ has not been bound");
-
- return callback(null, {statusCode: StatusCodes.BadInternalError});
- }
-
- if (!self.getExecutableFlag(context)) {
- console.log("Method " + self.nodeId.toString() + " " + self.browseName.toString() + "_ is not executable");
- // todo : find the correct Status code to return here
- return callback(null, {statusCode: StatusCodes.BadMethodInvalid});
- }
- // verify that input arguments are correct
- // todo :
- const inputArgumentResults = [];
- const inputArgumentDiagnosticInfos = [];
-
- try {
- self._asyncExecutionFunction(inputArguments, context, function (err, callMethodResponse) {
-
- callMethodResponse = callMethodResponse || {};
-
- callMethodResponse.statusCode = callMethodResponse.statusCode || StatusCodes.Good;
- callMethodResponse.outputArguments = callMethodResponse.outputArguments || [];
-
- callMethodResponse.inputArgumentResults = inputArgumentResults;
- callMethodResponse.inputArgumentDiagnosticInfos = inputArgumentDiagnosticInfos;
-
- // verify that output arguments are correct according to schema
- // Todo : ...
- const outputArgsDef = self.getOutputArguments();
-
- //xx assert(outputArgsDef.length === callMethodResponse.outputArguments.length,
- //xx "_asyncExecutionFunction did not provide the expected number of output arguments");
- // to be continued ...
-
-
- callback(err, callMethodResponse);
-
- });
-
- } catch(err){
- console.log("ERR in method handler".red,err.message);
- console.error(err.stack);
- const callMethodResponse = { statusCode: StatusCodes.BadInternalError};
- callback(err, callMethodResponse);
-
- }
-
- };
-
-
-
- UAMethod.prototype.clone = function (options,optionalFilter,extraInfo) {
-
- const Namespace = require("./namespace").Namespace;
-
- assert(!options.componentOf || options.componentOf,"trying to create an orphan method ?");
-
- const self = this;
- options = options || {};
- options = _.extend(_.clone(options),{
- methodDeclarationId: self.nodeId
- });
- options.references = options.references||[];
-
- const addressSpace = self.addressSpace;
- Namespace._handle_hierarchy_parent(addressSpace,options.references,options);
-
- const clonedMethod = self._clone(UAMethod,options, optionalFilter, extraInfo);
- clonedMethod._asyncExecutionFunction = self._asyncExecutionFunction;
- clonedMethod._getExecutableFlag = self._getExecutableFlag;
-
- if (options.componentOf) {
- //Xx console.log("Options ",options.componentOf.browseName.toString());
- const m = options.componentOf.getMethodByName(clonedMethod.browseName.name);
- assert(m);
- }
-
-
- return clonedMethod;
- };
- exports.UAMethod = UAMethod;
-
-
-