node-red-contrib-iiot-opcua
Version:
An Industrial IoT OPC UA toolbox contribution package for Node-RED based on node-opcua.
220 lines (217 loc) • 10.2 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_client_1 = __importDefault(require("./core/opcua-iiot-core-client"));
const opcua_iiot_core_1 = require("./core/opcua-iiot-core");
/**
* Read Node-RED node.
*
* @param RED
*/
module.exports = (RED) => {
// SOURCE-MAP-REQUIRED
function OPCUAIIoTRead(config) {
RED.nodes.createNode(this, config);
this.attributeId = parseInt(config.attributeId) || 0;
this.maxAge = parseInt(config.maxAge) || 1;
this.depth = parseInt(config.depth) || 1;
this.name = config.name;
this.justValue = config.justValue;
this.showStatusActivities = config.showStatusActivities;
this.showErrors = config.showErrors;
this.parseStrings = config.parseStrings;
this.historyDays = parseInt(config.historyDays) || 1;
this.connector = RED.nodes.getNode(config.connector);
let self = this;
self.iiot = (0, opcua_iiot_core_1.initCoreNode)();
const handleReadError = (err, msg) => {
opcua_iiot_core_client_1.default.readDebugLog(err);
if (self.showErrors) {
this.error(err, msg);
}
if ((0, opcua_iiot_core_1.isSessionBad)(err)) {
this.emit('opcua_client_not_ready');
}
};
if (process.env.TEST === "true")
self.functions = {
handleReadError
};
const readAllFromNodeId = (session, itemsToRead, msg) => {
opcua_iiot_core_client_1.default.readAllAttributes(session, itemsToRead, msg)
.then((readResult) => {
try {
this.send(buildResultMessage('AllAttributes', readResult));
}
catch (err) {
/* istanbul ignore next */
self.iiot.handleReadError(err, readResult.msg);
}
}).catch(function (err) {
/* istanbul ignore next */
((0, opcua_iiot_core_1.isInitializedIIoTNode)(self)) ? handleReadError(err, msg) : opcua_iiot_core_client_1.default.internalDebugLog(err.message);
});
};
const readValueFromNodeId = (session, itemsToRead, msg) => {
opcua_iiot_core_client_1.default.readVariableValue(session, itemsToRead, msg)
.then((readResult) => {
let message = buildResultMessage('VariableValue', readResult);
this.send(message);
}).catch(function (err) {
/* istanbul ignore next */
((0, opcua_iiot_core_1.isInitializedIIoTNode)(self)) ? handleReadError(err, msg) : opcua_iiot_core_client_1.default.internalDebugLog(err.message);
});
};
const readHistoryDataFromNodeId = (session, itemsToRead, msg) => {
const startDate = new Date();
self.iiot.historyStart = new Date();
self.iiot.historyStart.setDate(startDate.getDate() - self.historyDays);
self.iiot.historyEnd = new Date();
opcua_iiot_core_client_1.default.readHistoryValue(session, itemsToRead, msg.payload.historyStart || self.iiot.historyStart, msg.payload.historyEnd || self.iiot.historyEnd, msg)
.then((readResult) => {
let message = buildResultMessage('HistoryValue', readResult);
message.payload.historyStart = readResult.startDate || self.iiot.historyStart;
message.payload.historyEnd = readResult.endDate || self.iiot.historyEnd;
this.send(message);
}).catch((err) => {
/* istanbul ignore next */
((0, opcua_iiot_core_1.isInitializedIIoTNode)(self)) ? handleReadError(err, msg) : opcua_iiot_core_client_1.default.internalDebugLog(err.message);
});
};
const readFromNodeId = (session, itemsToRead, msg) => {
const transformItem = (item) => {
return {
nodeId: item,
attributeId: Number(self.attributeId) || undefined
};
};
const transformedItemsToRead = itemsToRead.map(transformItem);
opcua_iiot_core_client_1.default.read(session, transformedItemsToRead, msg.payload.maxAge || self.maxAge, msg)
.then((readResult) => {
let message = buildResultMessage('Default', readResult);
message.payload.maxAge = self.maxAge;
this.send(message);
}).catch(function (err) {
/* istanbul ignore next */
((0, opcua_iiot_core_1.isInitializedIIoTNode)(self)) ? handleReadError(err, msg) : opcua_iiot_core_client_1.default.internalDebugLog(err.message);
});
};
const readFromSession = (session, itemsToRead, originMsg) => {
let msg = Object.assign({}, originMsg);
if ((0, opcua_iiot_core_1.checkSessionNotValid)(session, 'Reader')) {
return;
}
opcua_iiot_core_client_1.default.readDebugLog('Read With AttributeId ' + self.attributeId);
switch (parseInt(self.attributeId)) {
case opcua_iiot_core_client_1.default.READ_TYPE.ALL:
readAllFromNodeId(session, itemsToRead, msg);
break;
case opcua_iiot_core_client_1.default.READ_TYPE.VALUE:
readValueFromNodeId(session, itemsToRead, msg);
break;
case opcua_iiot_core_client_1.default.READ_TYPE.HISTORY:
readHistoryDataFromNodeId(session, itemsToRead, msg);
break;
default:
readFromNodeId(session, itemsToRead, msg);
}
};
const buildResultMessage = function (readType, readResult) {
let payload = Object.assign(Object.assign({}, readResult.msg.payload), { nodetype: 'read', readtype: readType, attributeId: self.attributeId, justValue: self.justValue, payloadType: 'read' });
let dataValuesString = extractDataValueString(readResult);
payload = setMessageProperties(payload, readResult, dataValuesString);
if (!self.justValue) {
payload = enhanceMessage(payload, readResult);
}
let message = Object.assign(Object.assign({}, readResult.msg), { payload });
return message;
};
const extractDataValueString = function (readResult) {
let dataValuesString;
if (self.justValue) {
dataValuesString = JSON.stringify(readResult.results, null, 2);
}
else {
dataValuesString = JSON.stringify(readResult, null, 2);
}
return dataValuesString;
};
const setMessageProperties = (payload, readResult, stringValue) => {
try {
RED.util.setMessageProperty(payload, 'value', JSON.parse(stringValue));
} /* istanbul ignore next */
catch (err) {
if (self.showErrors) {
this.warn('JSON not to parse from string for dataValues type ' + JSON.stringify(readResult, null, 2));
this.error(err, readResult.msg);
}
payload.value = stringValue;
payload.error = err.message;
}
return payload;
};
const enhanceMessage = (payload, readResult) => {
try {
payload.resultsConverted = {};
let dataValuesString = JSON.stringify(readResult.results, null, 2);
RED.util.setMessageProperty(payload, 'resultsConverted', JSON.parse(dataValuesString));
} /* istanbul ignore next */
catch (err) {
if (self.showErrors) {
this.warn('JSON not to parse from string for dataValues type ' + readResult.results);
this.error(err, readResult.msg);
}
payload.resultsConverted = null;
payload.error = err.message;
}
return payload;
};
const errorHandler = (err, msg) => {
this.error(err, msg);
};
const emitHandler = (msg) => {
this.emit(msg);
};
const statusHandler = (status) => {
this.status(status);
};
this.on('input', function (msg, send, done) {
if (!(0, opcua_iiot_core_1.checkConnectorState)(self, msg, 'Read', errorHandler, emitHandler, statusHandler)) {
return;
}
try {
readFromSession(self.connector.iiot.opcuaSession, (0, opcua_iiot_core_1.buildNodesToRead)(msg.payload), msg);
} /* istanbul ignore next */
catch (err) {
handleReadError(err, msg);
}
});
const onAlias = (event, callback) => {
// @ts-ignore
this.on(event, callback);
};
(0, opcua_iiot_core_1.registerToConnector)(self, statusHandler, onAlias, errorHandler);
this.on('close', (done) => {
self.removeAllListeners();
(0, opcua_iiot_core_1.deregisterToConnector)(self, () => {
(0, opcua_iiot_core_1.resetIiotNode)(self);
done();
});
});
if (process.env.isTest === 'TRUE') {
self.iiot = Object.assign(Object.assign({}, self.iiot), { handleReadError });
}
}
RED.nodes.registerType('OPCUA-IIoT-Read', OPCUAIIoTRead);
};
//# sourceMappingURL=opcua-iiot-read.js.map