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
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 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