UNPKG

node-red-contrib-iiot-opcua

Version:

An Industrial IoT OPC UA toolbox contribution package for Node-RED based on node-opcua.

272 lines (269 loc) 13.9 kB
/** The BSD 3-Clause License Copyright 2022 - DATATRONiQ GmbH (https://datatroniq.com) Copyright (c) 2018-2022 Klaus Landsdorf (http://node-red.plus/) All rights reserved. node-red-contrib-iiot-opcua */ 'use strict'; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = void 0; // SOURCE-MAP-REQUIRED const core = __importStar(require("./opcua-iiot-core")); const fsm_1 = require("@xstate/fsm"); const opcua_iiot_core_1 = require("./opcua-iiot-core"); var logger; (function (logger) { logger.internalDebugLog = core.Debug('opcuaIIoT:connector'); logger.detailDebugLog = core.Debug('opcuaIIoT:connector:details'); logger.libDebugLog = core.Debug('opcuaIIoT:connector:nodeopcua'); })(logger = exports.logger || (exports.logger = {})); // sets values within node.iiot (refactored to node.iiot) const initConnectorNode = () => { return Object.assign(Object.assign({}, core.initCoreNode()), { sessionNodeRequests: 0, endpoints: [], userIdentity: undefined, opcuaClient: undefined, opcuaSession: undefined, discoveryServer: undefined, serverCertificate: undefined, discoveryServerEndpointUrl: undefined, hasOpcUaSubscriptions: false }); }; const createConnectorFinalStateMachine = function () { return (0, fsm_1.createMachine)({ id: 'connector', initial: opcua_iiot_core_1.FsmConnectorStates.StateIdle, states: { idle: { on: { INITOPCUA: opcua_iiot_core_1.FsmConnectorStates.StateInit, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, init: { on: { OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, CLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, opened: { on: { SESSIONREQUEST: opcua_iiot_core_1.FsmConnectorStates.StateSessionRequested, CLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, sessionRequested: { on: { OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, SESSIONACTIVATE: opcua_iiot_core_1.FsmConnectorStates.StateSessionActive, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, sessionActive: { on: { OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, SESSIONCLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, sessionClosed: { on: { IDLE: opcua_iiot_core_1.FsmConnectorStates.StateIdle, OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, CLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, SESSIONRESTART: opcua_iiot_core_1.FsmConnectorStates.StateSessionRestart, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, UNLOCK: opcua_iiot_core_1.FsmConnectorStates.StateUnlocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, sessionRestart: { on: { IDLE: opcua_iiot_core_1.FsmConnectorStates.StateIdle, SESSIONCLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, CLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, closed: { on: { OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, UNLOCK: opcua_iiot_core_1.FsmConnectorStates.StateUnlocked, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd, IDLE: opcua_iiot_core_1.FsmConnectorStates.StateIdle } }, locked: { on: { SESSIONCLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, CLOSE: opcua_iiot_core_1.FsmConnectorStates.StateClosed, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked, UNLOCK: opcua_iiot_core_1.FsmConnectorStates.StateUnlocked, SESSIONRESTART: opcua_iiot_core_1.FsmConnectorStates.StateSessionRestart, RECONFIGURE: opcua_iiot_core_1.FsmConnectorStates.StateReconfigured, STOP: opcua_iiot_core_1.FsmConnectorStates.StateStopped, RENEW: opcua_iiot_core_1.FsmConnectorStates.StateRenewed, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd } }, unlocked: { on: { IDLE: opcua_iiot_core_1.FsmConnectorStates.StateIdle, OPEN: opcua_iiot_core_1.FsmConnectorStates.StateOpened, END: opcua_iiot_core_1.FsmConnectorStates.StateEnd, LOCK: opcua_iiot_core_1.FsmConnectorStates.StateLocked } }, stopped: { on: {} }, end: { on: {} }, reconfigured: { on: {} }, renewed: { on: {} } } }); }; const startConnectorMachineService = (toggleMachine) => { return (0, fsm_1.interpret)(toggleMachine).start(); }; const subscribeConnectorFSMService = (service, eventFn) => { if (service === undefined || eventFn === undefined) throw new Error('Service or event handler missing'); return service.subscribe(eventFn); }; function setListenerToClient(node) { if (!node.iiot.opcuaClient) { logger.internalDebugLog('Client Not Valid On Setting Events To Client'); if (node.showErrors) { node.error(new Error('Client Not Valid To Set Event Listeners'), { payload: 'No Client To Set Event Listeners' }); } return; } node.iiot.opcuaClient.on('close', function (err) { if (err) { logger.internalDebugLog('Connection Error On Close ' + err); } if (node.iiot.isInactiveOnOPCUA()) { logger.detailDebugLog('Connector Not Active On OPC UA Close Event'); } else { node.iiot.resetOPCUAConnection('Connector To Server Close'); } logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT CONNECTION CLOSED !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION CLOSED: ' + node.endpoint); node.emit('server_connection_close'); }); node.iiot.opcuaClient.on('backoff', function (number, delay) { logger.internalDebugLog('!!! CONNECTION FAILED (backoff) FOR #', number, ' retrying ', delay / 1000.0, ' sec. !!!'); logger.internalDebugLog('CONNECTION FAILED: ' + node.endpoint); node.iiot.stateService.send('LOCK'); }); node.iiot.opcuaClient.on('abort', function () { logger.internalDebugLog('!!! Abort backoff !!!'); logger.internalDebugLog('CONNECTION BROKEN: ' + node.endpoint); if (node.iiot.isInactiveOnOPCUA()) { logger.detailDebugLog('Connector Not Active On OPC UA Backoff Abort Event'); } else { node.iiot.resetOPCUAConnection('Connector To Server Backoff Abort'); } node.emit('server_connection_abort'); }); node.iiot.opcuaClient.on('connection_lost', function () { logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT CONNECTION LOST !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION LOST: ' + node.endpoint); node.iiot.stateService.send('LOCK'); node.emit('server_connection_lost'); }); node.iiot.opcuaClient.on('connection_reestablished', function () { logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT CONNECTION RE-ESTABLISHED !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION RE-ESTABLISHED: ' + node.endpoint); node.iiot.stateService.send('UNLOCK'); }); node.iiot.opcuaClient.on('start_reconnection', function () { logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT STARTING RECONNECTION !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION STARTING RECONNECTION: ' + node.endpoint); node.iiot.stateService.send('LOCK'); }); node.iiot.opcuaClient.on('timed_out_request', function () { logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT TIMED OUT REQUEST !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION TIMED OUT REQUEST: ' + node.endpoint); }); node.iiot.opcuaClient.on('security_token_renewed', function () { logger.detailDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT SECURITY TOKEN RENEWED !!!!!!!!!!!!!!!!!!!'); logger.detailDebugLog('CONNECTION SECURITY TOKEN RENEWED: ' + node.endpoint); }); node.iiot.opcuaClient.on('after_reconnection', function () { logger.internalDebugLog('!!!!!!!!!!!!!!!!!!!!!!!! CLIENT RECONNECTED !!!!!!!!!!!!!!!!!!!'); logger.internalDebugLog('CONNECTION RECONNECTED: ' + node.endpoint); node.emit('after_reconnection', node.iiot.opcuaClient); node.iiot.stateService.send('UNLOCK'); }); } function logSessionInformation(node) { var _a; if (!((_a = node.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSession)) { logger.detailDebugLog('Session Not Valid To Log Information'); return; } logger.internalDebugLog('Session ' + node.iiot.opcuaSession.name + ' Id: ' + node.iiot.opcuaSession.sessionId + ' Started On ' + node.endpoint); logger.detailDebugLog('name :' + node.iiot.opcuaSession.name); logger.detailDebugLog('sessionId :' + node.iiot.opcuaSession.sessionId); logger.detailDebugLog('authenticationToken :' + node.iiot.opcuaSession.authenticationToken); logger.internalDebugLog('timeout :' + node.iiot.opcuaSession.timeout); if (node.iiot.opcuaSession.serverNonce) { logger.detailDebugLog('serverNonce :' + node.iiot.opcuaSession.serverNonce ? node.iiot.opcuaSession.serverNonce.toString('hex') : 'none'); } if (node.iiot.opcuaSession.serverCertificate) { logger.detailDebugLog('serverCertificate :' + node.iiot.opcuaSession.serverCertificate ? node.iiot.opcuaSession.serverCertificate.toString('base64') : 'none'); } else { logger.detailDebugLog('serverCertificate : None'); } logger.detailDebugLog('serverSignature :' + node.iiot.opcuaSession.serverSignature ? node.iiot.opcuaSession.serverSignature : 'none'); if (node.iiot.opcuaSession.lastRequestSentTime) { logger.detailDebugLog('lastRequestSentTime : ' + node.iiot.opcuaSession.lastRequestSentTime); logger.internalDebugLog('lastRequestSentTime converted :' + node.iiot.opcuaSession.lastRequestSentTime ? new Date(node.iiot.opcuaSession.lastRequestSentTime).toISOString() : 'none'); } if (node.iiot.opcuaSession.lastResponseReceivedTime) { logger.detailDebugLog('lastResponseReceivedTime : ' + node.iiot.opcuaSession.lastResponseReceivedTime); logger.internalDebugLog('lastResponseReceivedTime converted :' + node.iiot.opcuaSession.lastResponseReceivedTime ? new Date(node.iiot.opcuaSession.lastResponseReceivedTime).toISOString() : 'none'); } } function checkEndpoint(endpoint, errorHandler) { if (endpoint && endpoint.includes('opc.tcp://') && endpoint.lastIndexOf(':') > 8) { return true; } else { logger.internalDebugLog('Endpoint Not Valid -> ' + endpoint); errorHandler(new Error('endpoint does not include opc.tcp://')); return false; } } const coreConnector = { initConnectorNode, createConnectorFinalStateMachine, startConnectorMachineService, subscribeConnectorFSMService, setListenerToClient, logSessionInformation, checkEndpoint, internalDebugLog: logger.internalDebugLog }; exports.default = coreConnector; //# sourceMappingURL=opcua-iiot-core-connector.js.map