UNPKG

node-red-contrib-iiot-opcua

Version:

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

734 lines (724 loc) 40.3 kB
/* 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 */ 'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const underscore_1 = __importDefault(require("underscore")); const opcua_iiot_core_listener_1 = __importDefault(require("./core/opcua-iiot-core-listener")); const opcua_iiot_core_1 = require("./core/opcua-iiot-core"); const node_opcua_1 = require("node-opcua"); const opcua_iiot_core_client_1 = __importDefault(require("./core/opcua-iiot-core-client")); const assertion_1 = require("./types/assertion"); /** * Listener Node-RED node. * * @param RED */ module.exports = (RED) => { // SOURCE-MAP-REQUIRED function OPCUAIIoTListener(config) { RED.nodes.createNode(this, config); this.action = config.action; this.queueSize = config.queueSize || 1; this.name = config.name; this.topic = config.topic; this.justValue = config.justValue; this.useGroupItems = config.useGroupItems; this.showStatusActivities = config.showStatusActivities; this.showErrors = config.showErrors; this.connector = RED.nodes.getNode(config.connector); let self = this; self.iiot = opcua_iiot_core_listener_1.default.initListenerNode(); /* ######### FSM EVENTS ######### */ const fsmEventHandlerFunction = function (state) { if (!state.changed) return; switch (state.value) { case opcua_iiot_core_1.FsmListenerStates.StateStarted: opcua_iiot_core_listener_1.default.detailDebugLog('Listener STARTED Event FSM'); switch (self.action) { case 'subscribe': while (self.iiot.messageQueue.length > 0) { subscribeMonitoredItem(self.iiot.messageQueue.shift()); } break; case 'events': while (self.iiot.messageQueue.length > 0) { subscribeMonitoredEvent(self.iiot.messageQueue.shift()); } break; default: opcua_iiot_core_listener_1.default.internalDebugLog('Unknown Action Type ' + self.action); } break; case opcua_iiot_core_1.FsmListenerStates.StateIdle: opcua_iiot_core_listener_1.default.detailDebugLog('Listener IDLE Event FSM'); break; case opcua_iiot_core_1.FsmListenerStates.StateRequested: opcua_iiot_core_listener_1.default.detailDebugLog('Listener REQUESTED Event FSM'); break; case opcua_iiot_core_1.FsmListenerStates.StateInit: opcua_iiot_core_listener_1.default.detailDebugLog('Listener INIT Event FSM'); break; case opcua_iiot_core_1.FsmListenerStates.StateTerminated: opcua_iiot_core_listener_1.default.detailDebugLog('Listener TERMINATED Event FSM'); break; case opcua_iiot_core_1.FsmListenerStates.StateError: opcua_iiot_core_listener_1.default.detailDebugLog('Listener ERROR Event FSM'); break; case opcua_iiot_core_1.FsmListenerStates.StateEnd: opcua_iiot_core_listener_1.default.detailDebugLog('Listener END Event FSM'); break; default: opcua_iiot_core_listener_1.default.detailDebugLog('Listener NO VALID FSM EVENT'); } }; self.iiot.stateMachine = opcua_iiot_core_listener_1.default.createListenerStateMachine(); self.iiot.stateService = opcua_iiot_core_listener_1.default.startListenerMachineService(self.iiot.stateMachine); self.iiot.stateSubscription = opcua_iiot_core_listener_1.default.subscribeListenerFSMService(self.iiot.stateService, fsmEventHandlerFunction); opcua_iiot_core_listener_1.default.internalDebugLog('Start FSM: ' + self.iiot.stateService.state.value); const createSubscription = (msg) => { var _a; if (self.iiot.stateService.state.value !== opcua_iiot_core_1.FsmListenerStates.StateIdle) { opcua_iiot_core_listener_1.default.internalDebugLog('New Subscription Request On State ' + self.iiot.stateService.state.value); return; } opcua_iiot_core_listener_1.default.internalDebugLog('Create Subscription On State ' + self.iiot.stateService.state.value); if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } self.iiot.stateService.send('REQUESTINIT'); const timeMilliseconds = (typeof msg.payload.value === 'number') ? msg.payload.value : null; const dynamicOptions = (msg.payload.listenerParameters) ? msg.payload.listenerParameters.options : msg.payload.options; opcua_iiot_core_listener_1.default.internalDebugLog('create subscription, type: ' + self.action); const options = dynamicOptions || self.action === 'events' ? opcua_iiot_core_listener_1.default.getEventSubscriptionParameters(timeMilliseconds) : opcua_iiot_core_listener_1.default.getSubscriptionParameters(timeMilliseconds); makeSubscription(options); }; const setSubscriptionEvents = (subscription) => { subscription.on('started', () => { opcua_iiot_core_listener_1.default.internalDebugLog('Subscription started'); self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(this, 'started', self.oldStatusParameter, self.showStatusActivities, statusHandler); self.iiot.monitoredItems.clear(); self.iiot.stateService.send('START'); }); subscription.on('terminated', () => { opcua_iiot_core_listener_1.default.internalDebugLog('Subscription terminated'); self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(this, 'terminated', self.oldStatusParameter, self.showStatusActivities, statusHandler); self.iiot.stateService.send('TERMINATE'); self.iiot.stateService.send('IDLE'); resetSubscription(); }); subscription.on('internal_error', (err) => { opcua_iiot_core_listener_1.default.internalDebugLog('internal_error: ' + err.message); if (self.showErrors) { this.error(err, { payload: 'Internal Error' }); } self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(this, 'error', self.oldStatusParameter, self.showStatusActivities, statusHandler); self.iiot.stateService.send('ERROR'); resetSubscription(); }); subscription.on('item_added', (monitoredItem) => { setMonitoring(monitoredItem); updateSubscriptionStatus(); }); }; const makeSubscription = function (parameters) { if ((0, opcua_iiot_core_1.checkSessionNotValid)(self.connector.iiot.opcuaSession, 'ListenerSubscription')) { return; } if (!parameters) { opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Parameters Not Valid'); return; } else { opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Parameters: ' + JSON.stringify(parameters)); } self.iiot.opcuaSubscription = node_opcua_1.ClientSubscription.create(self.connector.iiot.opcuaSession, parameters); opcua_iiot_core_listener_1.default.internalDebugLog('New Subscription Created'); if (self.connector) { self.iiot.hasOpcUaSubscriptions = true; } setSubscriptionEvents(self.iiot.opcuaSubscription); self.iiot.stateService.send('INIT'); }; const resetSubscription = function () { sendAllMonitoredItems('SUBSCRIPTION TERMINATED'); }; const sendAllMonitoredItems = (payload) => { let addressSpaceItems = []; self.iiot.monitoredASO.forEach(function (key) { addressSpaceItems.push({ name: '', nodeId: key, datatypeName: '' }); }); this.send({ payload: payload, addressSpaceItems: addressSpaceItems }); self.iiot.monitoredItems.clear(); self.iiot.monitoredASO.clear(); }; const subscribeActionInput = function (msg) { if (self.iiot.stateService.state.value !== opcua_iiot_core_listener_1.default.RUNNING_STATE) { self.iiot.messageQueue.push(msg); } else { subscribeMonitoredItem(msg); } }; const subscribeEventsInput = function (msg) { if (self.iiot.stateService.state.value !== opcua_iiot_core_listener_1.default.RUNNING_STATE) { self.iiot.messageQueue.push(msg); } else { subscribeMonitoredEvent(msg); } }; const updateSubscriptionStatus = () => { opcua_iiot_core_listener_1.default.internalDebugLog('listening' + ' (' + self.iiot.monitoredItems.size + ')'); self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(this, 'listening' + ' (' + self.iiot.monitoredItems.size + ')', self.oldStatusParameter, self.showStatusActivities, statusHandler); }; const handleMonitoringOfGroupedItems = (msg) => { if (self.iiot.monitoredItemGroup && self.iiot.monitoredItemGroup.groupId !== null) { self.iiot.monitoredItemGroup.terminate(function (err) { if (err) { opcua_iiot_core_listener_1.default.internalDebugLog('Monitoring Terminate Error'); opcua_iiot_core_listener_1.default.internalDebugLog(err); } self.iiot.monitoredItems.clear(); self.iiot.monitoredASO.clear(); self.iiot.monitoredItemGroup.groupId = null; updateSubscriptionStatus(); }); } else { opcua_iiot_core_listener_1.default.buildNewMonitoredItemGroup(this, msg, msg.payload.addressSpaceItems, self.iiot.opcuaSubscription) .then((result) => { if (!result.monitoredItemGroup) { this.error(new Error('No Monitored Item Group In Result Of NodeOPCUA')); } else { result.monitoredItemGroup.groupId = underscore_1.default.uniqueId('group_'); self.iiot.monitoredItemGroup = result.monitoredItemGroup; } }).catch((err) => { opcua_iiot_core_listener_1.default.subscribeDebugLog('Monitoring Build Item Group Error'); opcua_iiot_core_listener_1.default.subscribeDebugLog(err); if (self.showErrors) { this.error(err, msg); } }); } }; const handleMonitoringOfItems = (msg) => { const itemsToMonitor = msg.payload.addressSpaceItems.filter((addressSpaceItem) => { const nodeIdToMonitor = (typeof addressSpaceItem.nodeId === 'string') ? addressSpaceItem.nodeId : addressSpaceItem.nodeId.toString(); return typeof self.iiot.monitoredASO.get(nodeIdToMonitor) === 'undefined'; }); const itemsToTerminate = msg.payload.addressSpaceItems.filter((addressSpaceItem) => { const nodeIdToMonitor = (typeof addressSpaceItem.nodeId === 'string') ? addressSpaceItem.nodeId : addressSpaceItem.nodeId.toString(); return typeof self.iiot.monitoredASO.get(nodeIdToMonitor) !== 'undefined'; }); if (itemsToMonitor.length > 0) { const monitorMessage = Object.assign({}, msg); monitorMessage.addressSpaceItems = itemsToMonitor; opcua_iiot_core_listener_1.default.subscribeDebugLog('itemsToMonitor ' + itemsToMonitor.length); opcua_iiot_core_listener_1.default.monitorItems(this, monitorMessage, self.iiot.opcuaSubscription); } if (itemsToTerminate.length > 0) { opcua_iiot_core_listener_1.default.subscribeDebugLog('itemsToTerminate ' + itemsToTerminate.length); itemsToTerminate.forEach((addressSpaceItem) => { const nodeIdToMonitor = (typeof addressSpaceItem.nodeId === 'string') ? addressSpaceItem.nodeId : addressSpaceItem.nodeId.toString(); const item = self.iiot.monitoredASO.get(nodeIdToMonitor); if (item && item.monitoredItem) { opcua_iiot_core_listener_1.default.subscribeDebugLog('Monitored Item Unsubscribe ' + nodeIdToMonitor); item.monitoredItem.terminate(function (err) { opcua_iiot_core_listener_1.default.subscribeDebugLog('Terminated Monitored Item ' + item.monitoredItem.itemToMonitor.nodeId); monitoredItemTerminated(msg, item.monitoredItem, nodeIdToMonitor, err); }); } else { opcua_iiot_core_listener_1.default.subscribeDebugLog('Monitored Item Was Not Monitoring ' + nodeIdToMonitor); } }); } }; const subscribeMonitoredItem = (msg) => { var _a, _b, _c, _d; if ((0, opcua_iiot_core_1.checkSessionNotValid)((_b = (_a = self === null || self === void 0 ? void 0 : self.connector) === null || _a === void 0 ? void 0 : _a.iiot) === null || _b === void 0 ? void 0 : _b.opcuaSession, 'MonitorListener')) { return; } if (!opcua_iiot_core_listener_1.default.checkState(this, msg, 'Monitoring')) { return; } if (!((_c = msg.payload.addressSpaceItems) === null || _c === void 0 ? void 0 : _c.length)) { msg.payload.addressSpaceItems = msg.payload.browseResults; } if ((_d = msg.payload.addressSpaceItems) === null || _d === void 0 ? void 0 : _d.length) { if (self.useGroupItems) { handleMonitoringOfGroupedItems(msg); } else { handleMonitoringOfItems(msg); } } else { self.oldStatusParameter = (0, opcua_iiot_core_1.setNodeStatusTo)(self, 'error', self.oldStatusParameter, true, statusHandler); this.send(Object.assign(Object.assign({}, msg), { payload: { status: 'error', message: 'No address space items to monitor' } })); } }; const handleEventSubscriptions = (msg) => { msg.payload.addressSpaceItems.forEach((addressSpaceItem) => { if (!addressSpaceItem.nodeId) { opcua_iiot_core_listener_1.default.eventDebugLog('Address Space Item Not Valid to Monitor Event Of ' + addressSpaceItem); return; } if (addressSpaceItem.datatypeName === 'ns=0;i=0') { opcua_iiot_core_listener_1.default.subscribeDebugLog('Address Space Item Not Allowed to Monitor ' + addressSpaceItem); return; } let nodeIdToMonitor; if (typeof addressSpaceItem.nodeId === 'string') { nodeIdToMonitor = addressSpaceItem.nodeId; } else { nodeIdToMonitor = addressSpaceItem.nodeId.toString(); } const item = self.iiot.monitoredASO.get(nodeIdToMonitor); if (!item) { opcua_iiot_core_listener_1.default.eventDebugLog('Register Event Item ' + nodeIdToMonitor); opcua_iiot_core_listener_1.default.buildNewEventItem(nodeIdToMonitor, msg, self.iiot.opcuaSubscription) .then(function (result) { var _a; if (result.monitoredItem.itemToMonitor.nodeId) { opcua_iiot_core_listener_1.default.eventDebugLog('Event Item Registered ' + result.monitoredItem.itemToMonitor.nodeId + ' to ' + result.nodeId); self.iiot.monitoredASO.set((_a = result === null || result === void 0 ? void 0 : result.nodeId) === null || _a === void 0 ? void 0 : _a.toString(), { monitoredItem: result.monitoredItem, topic: msg.topic || self.topic }); } }).catch((err) => { opcua_iiot_core_listener_1.default.eventDebugLog('Build Event Error'); opcua_iiot_core_listener_1.default.eventDebugLog(err); if (self.showErrors) { this.error(err, msg); } }); } else { opcua_iiot_core_listener_1.default.eventDebugLog('Terminate Event Item' + nodeIdToMonitor); const eventMessage = Object.assign({}, msg); item.monitoredItem.terminate(function (err) { opcua_iiot_core_listener_1.default.eventDebugLog('Terminated Monitored Item ' + item.monitoredItem.itemToMonitor.nodeId); monitoredItemTerminated(eventMessage, item.monitoredItem, nodeIdToMonitor, err); }); } }); }; const subscribeMonitoredEvent = (msg) => { if ((0, opcua_iiot_core_1.checkSessionNotValid)(self.connector.iiot.opcuaSession, 'EventListener')) { return; } if (!opcua_iiot_core_listener_1.default.checkState(this, msg, 'Event')) { return; } handleEventSubscriptions(msg); }; const monitoredItemTerminated = (msg, monitoredItem, nodeId, err) => { if (err) { if (monitoredItem && monitoredItem.itemToMonitor.nodeId) { opcua_iiot_core_listener_1.default.internalDebugLog(err.message + ' on ' + monitoredItem.itemToMonitor.nodeId); } else { opcua_iiot_core_listener_1.default.internalDebugLog(err.message + ' on monitoredItem'); } if (self.showErrors) { this.error(err, msg); } } updateMonitoredItemLists(monitoredItem, nodeId); }; const updateMonitoredItemLists = function (monitoredItem, nodeId) { var _a, _b, _c, _d; opcua_iiot_core_listener_1.default.internalDebugLog('updateMonitoredItemLists = UMIL'); if (monitoredItem && monitoredItem.itemToMonitor) { if (self.iiot.monitoredItems.has((_b = (_a = monitoredItem === null || monitoredItem === void 0 ? void 0 : monitoredItem.itemToMonitor) === null || _a === void 0 ? void 0 : _a.nodeId) === null || _b === void 0 ? void 0 : _b.toString())) { self.iiot.monitoredItems.delete((_d = (_c = monitoredItem === null || monitoredItem === void 0 ? void 0 : monitoredItem.itemToMonitor) === null || _c === void 0 ? void 0 : _c.nodeId) === null || _d === void 0 ? void 0 : _d.toString()); } if ((0, opcua_iiot_core_1.isNodeId)(monitoredItem.itemToMonitor.nodeId)) { opcua_iiot_core_listener_1.default.internalDebugLog('UMIL Terminate Monitored Item ' + monitoredItem.itemToMonitor.nodeId); if (self.iiot.monitoredASO.has(nodeId)) { self.iiot.monitoredASO.delete(nodeId); } } else { opcua_iiot_core_listener_1.default.internalDebugLog('UMIL monitoredItem NodeId is not valid Id:' + monitoredItem.itemToMonitor.nodeId); self.iiot.monitoredASO.forEach(function (value, key, map) { opcua_iiot_core_listener_1.default.internalDebugLog('UMIL monitoredItem removing from ASO list key:' + key + ' value ' + value.monitoredItem.itemToMonitor.nodeId); if (value.monitoredItem.itemToMonitor.nodeId && value.monitoredItem.itemToMonitor.nodeId === monitoredItem.itemToMonitor.nodeId) { opcua_iiot_core_listener_1.default.internalDebugLog('UMIL monitoredItem removed from ASO list' + key); map.delete(key); } }); } updateSubscriptionStatus(); } }; const setMonitoring = (monitoredItemToSet) => { var _a, _b, _c; const monitoredItem = monitoredItemToSet; if (!monitoredItem || !monitoredItem.on) { opcua_iiot_core_listener_1.default.internalDebugLog('monitoredItem Id from server is not valid Id: ' + monitoredItem); return; } if (!(0, opcua_iiot_core_1.isNodeId)((_a = monitoredItem.itemToMonitor) === null || _a === void 0 ? void 0 : _a.nodeId)) { opcua_iiot_core_listener_1.default.internalDebugLog('monitoredItem NodeId is not valid Id:' + monitoredItem.itemToMonitor.nodeId); } opcua_iiot_core_listener_1.default.internalDebugLog('add monitoredItem to list Id:' + monitoredItem.itemToMonitor.nodeId + ' nodeId: ' + monitoredItem.itemToMonitor.nodeId); self.iiot.monitoredItems.set((_c = (_b = monitoredItem === null || monitoredItem === void 0 ? void 0 : monitoredItem.itemToMonitor) === null || _b === void 0 ? void 0 : _b.nodeId) === null || _c === void 0 ? void 0 : _c.toString(), monitoredItem); monitoredItem.on('initialized', function () { opcua_iiot_core_listener_1.default.internalDebugLog('monitoredItem ' + monitoredItem.itemToMonitor.nodeId + ' initialized on ' + monitoredItem.itemToMonitor.nodeId); }); monitoredItem.on('changed', (dataValue) => { opcua_iiot_core_listener_1.default.detailDebugLog('data changed for item: ' + monitoredItem.itemToMonitor.nodeId + ' with Id ' + monitoredItem.itemToMonitor.nodeId); if (!monitoredItem.monitoringParameters.filter) { sendDataFromMonitoredItem(monitoredItem, dataValue); } else { sendDataFromEvent(monitoredItem, dataValue); } }); // @ts-ignore monitoredItem.on('err', (err) => { const error = new Error(monitoredItem.itemToMonitor.nodeId.toString() + ': ' + ((err === null || err === void 0 ? void 0 : err.message) || err)); opcua_iiot_core_listener_1.default.internalDebugLog('monitoredItem Error: ' + error + ' on ' + monitoredItem.itemToMonitor.nodeId); if (self.showErrors) { this.error(error, { payload: 'Monitored Item Error', monitoredItem: monitoredItem }); } updateMonitoredItemLists(monitoredItem, monitoredItem.itemToMonitor.nodeId); if ((0, opcua_iiot_core_1.isSessionBad)(error)) { sendAllMonitoredItems('BAD SESSION'); terminateSubscription(() => { this.emit('opcua_client_not_ready'); }); } }); // @ts-ignore monitoredItem.on('terminated', (err) => { monitoredItem.removeAllListeners(); opcua_iiot_core_listener_1.default.internalDebugLog('Terminated For ' + monitoredItem.itemToMonitor.nodeId); updateMonitoredItemLists(monitoredItem, monitoredItem.itemToMonitor.nodeId); }); }; const sendDataFromMonitoredItem = (monitoredItem, dataValue) => { var _a, _b; if (!monitoredItem) { opcua_iiot_core_listener_1.default.internalDebugLog('Monitored Item Is Not Valid On Change Event While Monitoring'); return; } const nodeId = ((0, opcua_iiot_core_1.isNodeId)(monitoredItem.itemToMonitor.nodeId)) ? (_b = (_a = monitoredItem === null || monitoredItem === void 0 ? void 0 : monitoredItem.itemToMonitor) === null || _a === void 0 ? void 0 : _a.nodeId) === null || _b === void 0 ? void 0 : _b.toString() : 'invalid'; const item = self.iiot.monitoredASO.get(nodeId); const topic = (item) ? item.topic : self.topic; let msg = { payload: { addressSpaceItems: [{ name: '', nodeId, datatypeName: '' }], nodeId, nodetype: 'listen', injectType: 'subscribe' }, topic: topic, }; opcua_iiot_core_listener_1.default.internalDebugLog('sendDataFromMonitoredItem: ' + msg.payload.addressSpaceItems[0].nodeId); let dataValuesString; msg.justValue = self.justValue; if (self.justValue) { dataValuesString = JSON.stringify(dataValue, null, 2); try { RED.util.setMessageProperty(msg.payload, 'value', JSON.parse(dataValuesString)); } catch (err) { if (self.showErrors) { this.warn('JSON not to parse from string for monitored item'); this.error(err, msg); } msg.payload.value = dataValuesString; msg.error = err.message; } } else { msg.payload = Object.assign(Object.assign({}, msg.payload), { value: dataValue, statusCode: monitoredItem.statusCode, itemToMonitor: monitoredItem.itemToMonitor, monitoredItemId: monitoredItem.itemToMonitor }); } this.send(msg); }; const handleEventResults = (msg, dataValue, eventResults, monitoredItem) => { opcua_iiot_core_listener_1.default.eventDetailDebugLog('Monitored Event Results ' + eventResults); let dataValuesString; if (self.justValue) { dataValuesString = JSON.stringify(dataValue, null, 2); try { RED.util.setMessageProperty(msg.payload, 'value', JSON.parse(dataValuesString)); } catch (err) { if (self.showErrors) { this.warn('JSON not to parse from string for monitored item'); this.error(err, msg); } msg.payload.value = dataValuesString; msg.error = err.message; } } else { msg.payload = Object.assign(Object.assign({}, msg.payload), { value: dataValue, eventResults, monitoredItem }); } this.send(msg); }; const sendDataFromEvent = (monitoredItem, dataValue) => { var _a, _b; // @ts-ignore if (!(0, assertion_1.isArray)(dataValue)) { dataValue = [dataValue]; } if (!monitoredItem) { opcua_iiot_core_listener_1.default.internalDebugLog('Monitored Item Is Not Valid On Change Event While Monitoring'); return; } const nodeId = ((0, opcua_iiot_core_1.isNodeId)(monitoredItem.itemToMonitor.nodeId)) ? (_b = (_a = monitoredItem === null || monitoredItem === void 0 ? void 0 : monitoredItem.itemToMonitor) === null || _a === void 0 ? void 0 : _a.nodeId) === null || _b === void 0 ? void 0 : _b.toString() : 'invalid'; const item = self.iiot.monitoredASO.get(nodeId); const topic = (item) ? item.topic : self.topic; let msg = { payload: { addressSpaceItems: [{ name: '', nodeId: nodeId, datatypeName: '' }], nodeId, nodetype: 'listen', injectType: 'event' }, topic: topic || self.topic, // default if item.topic is empty }; opcua_iiot_core_listener_1.default.analyzeEvent(self.connector.iiot.opcuaSession, getBrowseName, dataValue) .then((eventResults) => { handleEventResults(msg, dataValue, eventResults, monitoredItem); }).catch((err) => { ((0, opcua_iiot_core_1.isInitializedIIoTNode)(this)) ? errorHandling(err) : opcua_iiot_core_listener_1.default.internalDebugLog(err.message); }); }; const errorHandling = (err) => { opcua_iiot_core_listener_1.default.internalDebugLog('Basic Error Handling'); opcua_iiot_core_listener_1.default.internalDebugLog(err); if (self.showErrors) { this.error(err, { payload: 'Error Handling' }); } if (err) { if ((0, opcua_iiot_core_1.isSessionBad)(err)) { sendAllMonitoredItems('BAD SESSION'); terminateSubscription(() => { this.emit('opcua_client_not_ready'); }); } } }; const getBrowseName = function (session, nodeId, callback) { opcua_iiot_core_client_1.default.read(session, [{ nodeId: nodeId, attributeId: node_opcua_1.AttributeIds.BrowseName }], 12, function (err, org, readValue) { if (!err) { if (readValue[0].statusCode === node_opcua_1.StatusCodes.Good) { let browseName = readValue[0].value.value.name; return callback(null, browseName); } } callback(err, 'Unknown'); }); }; const handleListenerInput = (msg) => { switch (self.action) { case 'subscribe': subscribeMonitoredItem(msg); break; case 'events': subscribeMonitoredEvent(msg); break; default: this.error(new Error('Type Of Action To Listener Is Not Valid'), msg); } }; const errorHandler = (err, msg) => { this.error(err, msg); }; const emitHandler = (msg) => { this.emit(msg); }; const statusHandler = (status) => { this.status(status); }; this.on('input', (msg) => { if (!(0, opcua_iiot_core_1.checkConnectorState)(self, msg, 'Listener', errorHandler, emitHandler, statusHandler)) { return; } const payload = msg.payload; const outputPayload = Object.assign(Object.assign({}, payload), { nodetype: payload.nodetype === 'browse' ? 'inject' : payload.nodetype, injectType: payload.nodetype === 'browse' ? 'listen' : payload.injectType, addressSpaceItems: (0, opcua_iiot_core_1.buildNodeListFromClient)(payload) }); const outputMessage = Object.assign(Object.assign({}, msg), { payload: outputPayload }); if (!outputPayload.addressSpaceItems || !outputPayload.addressSpaceItems.length) { opcua_iiot_core_listener_1.default.subscribeDebugLog('Address-Space-Item Set Not Valid'); if (self.showErrors) { this.error(new Error('Address-Space-Item Set Not Valid'), msg); } return; } if (self.iiot.stateService.state.value === opcua_iiot_core_1.FsmListenerStates.StateIdle) { self.iiot.messageQueue.push(outputMessage); createSubscription(outputMessage); } else { if (!opcua_iiot_core_listener_1.default.checkState(self, outputMessage, 'Input')) { self.iiot.messageQueue.push(outputMessage); return; } handleListenerInput(outputMessage); } }); const onAlias = (event, callback) => { // @ts-ignore this.on(event, callback); }; (0, opcua_iiot_core_1.registerToConnector)(this, statusHandler, onAlias, errorHandler); if (self.connector) { self.connector.on('connector_init', () => { var _a; opcua_iiot_core_listener_1.default.internalDebugLog('Reset Subscription On Connector Init'); if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } self.iiot.monitoredItems = new Map(); self.iiot.monitoredASO = new Map(); self.iiot.stateMachine = opcua_iiot_core_listener_1.default.createListenerStateMachine(); self.iiot.monitoredItemGroup = null; }); self.connector.on('connection_stopped', () => { terminateSubscription(() => { var _a; if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) self.iiot.opcuaSubscription = null; opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Was Terminated On Connector Event -> connection stopped'); }); }); self.connector.on('connection_end', () => { terminateSubscription(() => { var _a; if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Was Terminated On Connector Event -> connection ends'); }); }); self.connector.on('connection_reconfigure', () => { terminateSubscription(() => { var _a; if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Was Terminated On Connector Event -> connection reconfigure'); }); }); self.connector.on('connection_renew', () => { terminateSubscription(() => { var _a; if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } opcua_iiot_core_listener_1.default.internalDebugLog('Subscription Was Terminated On Connector Event -> connection renew'); }); }); } const terminateSubscription = function (done) { var _a, _b; if (((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) && ((_b = self.iiot) === null || _b === void 0 ? void 0 : _b.stateService.state.value) === opcua_iiot_core_listener_1.default.RUNNING_STATE) { self.iiot.stateService.send('TERMINATE'); self.iiot.opcuaSubscription.terminate(() => { self.iiot.opcuaSubscription.removeAllListeners(); self.iiot.stateService.send('IDLE'); done(); }); } else { self.iiot.stateService.send('IDLE'); done(); } }; if (process.env.TEST === 'true') { self.functions = { createSubscription, subscribeActionInput, subscribeMonitoredItem, monitoredItemTerminated, errorHandling, setMonitoring }; } this.on('close', (done) => { opcua_iiot_core_listener_1.default.internalDebugLog('Close Listener Node - start with terminate of the OPC UA subscription'); self.removeAllListeners(); terminateSubscription(() => { var _a; if ((_a = self.iiot) === null || _a === void 0 ? void 0 : _a.opcuaSubscription) { self.iiot.opcuaSubscription = null; } opcua_iiot_core_listener_1.default.internalDebugLog('Close Listener Node - start with signal to deregister in the connector'); (0, opcua_iiot_core_1.deregisterToConnector)(self, () => { (0, opcua_iiot_core_1.resetIiotNode)(self); done(); opcua_iiot_core_listener_1.default.internalDebugLog('Close of Listener Node done'); }); opcua_iiot_core_listener_1.default.internalDebugLog('Close Listener Node'); }); }); /* self.iiot.stateMachine.onIDLE = function () { coreListener.detailDebugLog('Listener IDLE Event FSM') } self.iiot.stateMachine.onREQUESTED = function () { coreListener.detailDebugLog('Listener REQUESTED Event FSM') } self.iiot.stateMachine.onINIT = function () { coreListener.detailDebugLog('Listener INIT Event FSM') } self.iiot.stateMachine.onSTARTED = function () { coreListener.detailDebugLog('Listener STARTED Event FSM') switch (self.action) { case 'subscribe': while (self.iiot.messageQueue.length > 0) { subscribeMonitoredItem(self.iiot.messageQueue.shift()) } break case 'events': while (self.iiot.messageQueue.length > 0) { subscribeMonitoredEvent(self.iiot.messageQueue.shift()) } break default: coreListener.internalDebugLog('Unknown Action Type ' + self.action) } } self.iiot.stateMachine.onTERMINATED = function () { coreListener.detailDebugLog('Listener TERMINATED Event FSM') } self.iiot.stateMachine.onERROR = function () { coreListener.detailDebugLog('Listener ERROR Event FSM') } self.iiot.stateMachine.onEND = function () { coreListener.detailDebugLog('Listener END Event FSM') } */ } RED.nodes.registerType('OPCUA-IIoT-Listener', OPCUAIIoTListener); }; //# sourceMappingURL=opcua-iiot-listener.js.map