node-red-contrib-iiot-opcua
Version:
An Industrial IoT OPC UA toolbox contribution package for Node-RED based on node-opcua.
203 lines (200 loc) • 8.84 kB
JavaScript
/*
The BSD 3-Clause License
Copyright 2022 - DATATRONiQ GmbH (https://datatroniq.com)
Copyright (c) 2018-2022 Klaus Landsdorf (http://node-red.plus/)
Copyright 2015,2016 - Mika Karaila, Valmet Automation Inc. (node-red-contrib-opcua)
All rights reserved.
node-red-contrib-iiot-opcua
*/
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const opcua_iiot_core_server_1 = __importDefault(require("./core/opcua-iiot-core-server"));
const opcua_iiot_core_1 = require("./core/opcua-iiot-core");
const vm2_1 = require("vm2");
/**
* Server Node-RED node.
*
* @param RED
*/
module.exports = (RED) => {
// SOURCE-MAP-REQUIRED
let scriptObjects = {};
function OPCUAIIoTFlexServer(config) {
RED.nodes.createNode(this, config);
opcua_iiot_core_server_1.default.flexInternalDebugLog('Open Server Node');
let self = this;
opcua_iiot_core_server_1.default.readConfigOfServerNode(self, config);
opcua_iiot_core_server_1.default.initServerNode(self);
opcua_iiot_core_server_1.default.loadNodeSets(self, __dirname);
// node = coreServer.loadCertificates(node)
self.context = this.context;
const vm = new vm2_1.VM({
allowAsync: false,
sandbox: {
// allow the node-opcua library to be accessed in user-submitted scripts as 'opcua'
opcua: require('node-opcua'),
node: self,
coreServer: opcua_iiot_core_server_1.default,
scriptObjects,
RED,
sandboxNodeContext: {
set: function () {
self.context().set.apply(self, arguments);
},
get: function () {
return self.context().get.apply(self, arguments);
},
keys: function () {
return self.context().keys.apply(self, arguments);
},
get global() {
return self.context().global;
},
get flow() {
return self.context().flow;
}
},
sandboxFlowContext: {
set: function () {
self.context().flow.set.apply(self, arguments);
},
get: function () {
return self.context().flow.get.apply(self, arguments);
},
keys: function () {
return self.context().flow.keys.apply(self, arguments);
}
},
sandboxGlobalContext: {
set: function () {
self.context().global.set.apply(self, arguments);
},
get: function () {
return self.context().global.get.apply(self, arguments);
},
keys: function () {
return self.context().global.keys.apply(self, arguments);
}
},
sandboxEnv: {
get: function (envVar) {
let flow = self._flow;
return flow.getSetting(envVar);
}
}
}
});
// Use the vm2 library to make the submitted script executable:
// vm.run returns construcAddressSpaceScript as a function
const constructAddressSpaceScript = vm.run('constructAddressSpaceScript = ' + config.addressSpaceScript);
const statusHandler = (status) => {
this.status(status);
};
const initNewServer = () => {
self = opcua_iiot_core_server_1.default.initRegisterServerMethod(self);
let serverOptions = opcua_iiot_core_server_1.default.buildGeneralServerOptions(self, 'Flex');
// serverOptions = coreServer.setDiscoveryOptions(node, serverOptions)
try {
opcua_iiot_core_server_1.default.createServer(self, serverOptions, postInitialize, statusHandler, RED.settings.verbose);
}
catch (err) {
/* istanbul ignore next */
this.emit('server_create_error');
opcua_iiot_core_server_1.default.flexInternalDebugLog(err.message);
handleServerError(err, { payload: 'Flex Server Failure! Please, check the server settings!' });
}
};
const handleServerError = (err, msg) => {
opcua_iiot_core_server_1.default.internalDebugLog(err);
if (self.showErrors) {
this.error(err, msg);
}
};
const postInitialize = () => {
self.iiot.eventObjects = {}; // event objects should stay in memory
opcua_iiot_core_server_1.default.constructAddressSpaceFromScript(self.iiot.opcuaServer, constructAddressSpaceScript, self.iiot.eventObjects)
.then(() => {
opcua_iiot_core_server_1.default.start(self.iiot.opcuaServer, self).then(() => {
self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(self, 'active', self.oldStatusParameter, self.showStatusActivities, statusHandler);
this.emit('server_running');
}).catch((err) => {
/* istanbul ignore next */
this.emit('server_start_error');
self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(self, 'errors', self.oldStatusParameter, self.showStatusActivities, statusHandler);
handleServerError(err, { payload: 'Server Start Failure' });
});
}).catch(function (err) {
/* istanbul ignore next */
handleServerError(err, { payload: 'Server Address Space Failure' });
});
};
initNewServer();
this.on('input', function (msg) {
if (!self.iiot.opcuaServer || !self.iiot.initialized) {
handleServerError(new Error('Server Not Ready For Inputs'), msg);
return;
}
if (msg.payload.injectType === 'CMD') {
executeOpcuaCommand(msg);
}
else {
handleServerError(new Error('Unknown Flex Inject Type ' + msg.payload.injectType), msg);
}
});
const executeOpcuaCommand = (msg) => {
if (msg.payload.commandType === 'restart') {
restartServer();
this.send(msg);
}
else {
handleServerError(new Error('Unknown Flex OPC UA Command'), msg);
}
};
const sendHandler = (msg) => {
this.send(msg);
};
const emitHandler = (eventName, ...args) => {
this.emit(eventName, ...args);
};
const restartServer = function () {
opcua_iiot_core_server_1.default.flexInternalDebugLog('Restart OPC UA Server');
opcua_iiot_core_server_1.default.restartServer(self, statusHandler, emitHandler, sendHandler);
if (self.iiot.opcuaServer) {
opcua_iiot_core_server_1.default.flexInternalDebugLog('OPC UA Server restarted');
}
else {
opcua_iiot_core_server_1.default.flexInternalDebugLog('Can not restart OPC UA Server');
}
};
this.on('close', function (done) {
self.removeAllListeners();
closeServer(() => {
opcua_iiot_core_server_1.default.flexInternalDebugLog('Close Server Node');
(0, opcua_iiot_core_1.resetIiotNode)(self);
done();
});
});
this.on('shutdown', () => {
self.iiot.opcuaServer = null;
initNewServer();
});
const closeServer = function (done) {
if (opcua_iiot_core_server_1.default.simulatorInterval) {
clearInterval(opcua_iiot_core_server_1.default.simulatorInterval);
opcua_iiot_core_server_1.default.simulatorInterval = null;
}
if (self.iiot.opcuaServer) {
self.iiot.opcuaServer.removeAllListeners();
self.iiot.opcuaServer.shutdown(self.delayToClose, done);
}
else {
done();
}
};
}
RED.nodes.registerType('OPCUA-IIoT-Flex-Server', OPCUAIIoTFlexServer);
};
//# sourceMappingURL=opcua-iiot-flex-server.js.map