node-red-contrib-opcua-server-refresh
Version:
Fork of the original 'node-red-contrib-opcua-server' package that is no longer maintained. This has been refactored to support the latest version of node-opcua and fixes incomplete/non-working features.
293 lines (292 loc) • 14.4 kB
JavaScript
;
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;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = __importStar(require("path"));
const debug_1 = __importDefault(require("debug"));
const node_opcua_1 = require("node-opcua");
const nodeOPCUANodesets = __importStar(require("node-opcua-nodesets"));
const requireResolve = require.resolve("node-opcua-server");
const opcuaServerDebug = (0, debug_1.default)("opcuaCompact:server");
const opcuaServerDetailsDebug = (0, debug_1.default)("opcuaCompact:server:details");
const opcuaErrorDebug = (0, debug_1.default)("opcuaCompact:error");
const listenForErrors = (node) => {
node.on("error", (err) => {
opcuaErrorDebug(err);
});
};
const setNodeStatus = (node, options) => {
node.status(options);
};
const isWindows = () => process.platform === "win32";
const checkUserLogon = () => true;
const getPackagePathFromIndex = () => {
if (isWindows()) {
return requireResolve.replace("\\index.js", "");
}
else {
return requireResolve.replace("/index.js", "");
}
};
const serverCertificateFile = (keybits) => {
return path.join(__dirname, "../../certificates/server_selfsigned_cert_" + keybits + ".pem");
};
const serverKeyFile = (keybits) => {
return path.join(__dirname, "../../certificates/server_key_" + keybits + ".pem");
};
const coreServerModule = {
nodeOpcuaServer: require("node-opcua-server/dist/opcua_server"),
opcua: require("node-opcua"),
debugLog: opcuaServerDebug,
detailLog: opcuaServerDetailsDebug,
errorLog: opcuaErrorDebug,
readConfigOfServerNode: (node, config) => {
node.port = config.port;
node.endpoint = config.endpoint;
node.productUri = config.productUri;
node.alternateHostname = config.alternateHostname;
node.maxAllowedSessionNumber = config.maxAllowedSessionNumber;
node.maxConnectionsPerEndpoint = config.maxConnectionsPerEndpoint;
node.maxAllowedSubscriptionNumber = config.maxAllowedSubscriptionNumber;
node.maxNodesPerRead = config.maxNodesPerRead;
node.maxNodesPerWrite = config.maxNodesPerWrite;
node.maxNodesPerHistoryReadData = config.maxNodesPerHistoryReadData;
node.maxNodesPerBrowse = config.maxNodesPerBrowse;
node.maxBrowseContinuationPoints = config.maxBrowseContinuationPoints;
node.maxHistoryContinuationPoints = config.maxHistoryContinuationPoints;
node.delayToInit = config.delayToInit;
node.delayToClose = config.delayToClose;
node.serverShutdownTimeout = config.serverShutdownTimeout;
node.showStatusActivities = config.showStatusActivities;
node.showErrors = config.showErrors;
node.publicCertificateFile = config.publicCertificateFile;
node.privateCertificateFile = config.privateCertificateFile;
node.allowAnonymous = config.allowAnonymous;
node.opcuaUsers = config.users;
node.xmlsetsOPCUA = config.xmlsetsOPCUA;
node.isAuditing = config.isAuditing;
node.disableDiscovery = !config.serverDiscovery;
node.registerServerMethod = config.registerServerMethod;
node.discoveryServerEndpointUrl = config.discoveryServerEndpointUrl;
node.capabilitiesForMDNS = config.capabilitiesForMDNS
? config.capabilitiesForMDNS.split(",")
: [config.capabilitiesForMDNS];
return node;
},
initialize: (node, options) => {
return new node_opcua_1.OPCUAServer(options);
},
stop: (node, server, done) => {
server.shutdown(node.serverShutdownTimeout || 1000, done);
},
getRegisterServerMethod: (id) => {
return node_opcua_1.RegisterServerMethod[id];
},
loadOPCUANodeSets: (node, dirname) => {
const xmlFiles = [
nodeOPCUANodesets.nodesets.standard,
nodeOPCUANodesets.nodesets.di,
];
if (Array.isArray(node.xmlsetsOPCUA)) {
node.xmlsetsOPCUA.forEach((xmlsetFileName) => {
if (xmlsetFileName.path) {
if (xmlsetFileName.path.startsWith("public/vendor/")) {
xmlFiles.push(path.join(dirname, xmlsetFileName.path));
}
else {
xmlFiles.push(xmlsetFileName.path);
}
}
});
opcuaServerDetailsDebug("appending xmlFiles: " + xmlFiles.toString());
}
opcuaServerDetailsDebug("node sets:" + xmlFiles.toString());
return xmlFiles;
},
defaultServerOptions: (node) => {
const certificateFile = node.publicCertificateFile || serverCertificateFile("2048");
const privateKeyFile = node.privateCertificateFile || serverKeyFile("2048");
const registerServerMethod = 1;
return {
port: typeof node.port === "string" ? parseInt(node.port) : node.port || 4334,
resourcePath: node.endpoint || "/UA/NodeRED/Compact",
buildInfo: {
productName: "Node-RED OPC UA Compact Server",
buildNumber: "20240927",
buildDate: new Date(2022, 9, 27),
},
serverCapabilities: {
maxSessions: node.maxAllowedSessionNumber || 10,
maxBrowseContinuationPoints: node.maxBrowseContinuationPoints || 10,
maxHistoryContinuationPoints: node.maxHistoryContinuationPoints || 10,
operationLimits: {
maxNodesPerRead: node.maxNodesPerRead || 1000,
maxNodesPerWrite: node.maxNodesPerWrite || 1000,
maxNodesPerHistoryReadData: node.maxNodesPerHistoryReadData || 100,
maxNodesPerBrowse: node.maxNodesPerBrowse || 1000,
},
},
serverInfo: {
productUri: node.productUri || "NodeOPCUA-Server-" + node.port,
applicationName: { text: "NodeRED-Compact", locale: "en" },
gatewayServerUri: null,
discoveryProfileUri: null,
discoveryUrls: [],
},
alternateHostname: node.alternateHostname,
maxConnectionsPerEndpoint: node.maxConnectionsPerEndpoint || 10,
allowAnonymous: node.allowAnonymous !== false,
certificateFile,
privateKeyFile,
userManager: {
isValidUser: checkUserLogon,
},
isAuditing: node.isAuditing || false,
disableDiscovery: node.disableDiscovery || false,
registerServerMethod,
securityPolicies: [node_opcua_1.SecurityPolicy.None, node_opcua_1.SecurityPolicy.Basic256Sha256],
securityModes: [
node_opcua_1.MessageSecurityMode.None,
node_opcua_1.MessageSecurityMode.Sign,
node_opcua_1.MessageSecurityMode.SignAndEncrypt,
],
};
},
constructAddressSpaceFromScript: (server, constructAddressSpaceScript, opcua, eventObjects, done) => {
return new Promise((resolve, reject) => {
try {
const addressSpace = server.engine.addressSpace;
if (!addressSpace) {
reject(new Error("Address space not available"));
return;
}
constructAddressSpaceScript(server, addressSpace, opcua, eventObjects, resolve);
}
catch (err) {
reject(err);
}
});
},
postInitialize: (node, opcuaServer) => {
if (!node.contribOPCUACompact) {
node.contribOPCUACompact = {};
}
node.contribOPCUACompact.eventObjects = {};
const addressSpace = opcuaServer.engine?.addressSpace || null;
if (addressSpace) {
addressSpace.getOwnNamespace();
}
if (node.contribOPCUACompact.constructAddressSpaceScript) {
coreServerModule
.constructAddressSpaceFromScript(opcuaServer, node.contribOPCUACompact.constructAddressSpaceScript, coreServerModule.opcua, node.contribOPCUACompact.eventObjects, () => { })
.then(() => {
setNodeStatus(node, { fill: "green", shape: "dot", text: "active" });
node.emit("server_running");
})
.catch((err) => {
setNodeStatus(node, { fill: "red", shape: "dot", text: err.message });
node.emit("server_start_error");
});
}
},
run: (node, server) => {
return new Promise((resolve, reject) => {
server.start((err) => {
if (err) {
opcuaErrorDebug("Server failed to start:", err);
reject(err);
}
else {
if (server.endpoints && server.endpoints.length) {
server.endpoints.forEach((endpoint) => {
endpoint.endpointDescriptions().forEach((endpointDescription) => {
opcuaServerDebug("Server endpointUrl: " +
endpointDescription.endpointUrl +
" securityMode: " +
endpointDescription.securityMode.toString() +
" securityPolicyUri: " +
(endpointDescription.securityPolicyUri
? endpointDescription.securityPolicyUri.toString()
: "None Security Policy Uri"));
});
});
const endpointUrl = server.endpoints[0].endpointDescriptions()[0].endpointUrl;
opcuaServerDebug("Primary Server Endpoint URL " + endpointUrl);
}
server.on("newChannel", (channel) => {
opcuaServerDebug(`Client connected with address = ${channel.remoteAddress} port = ${channel.remotePort}`);
});
server.on("closeChannel", (channel) => {
opcuaServerDebug(`Client disconnected with address = ${channel.remoteAddress} port = ${channel.remotePort}`);
});
server.on("create_session", (session) => {
opcuaServerDebug("############## SESSION CREATED ##############");
if (session.clientDescription) {
opcuaServerDetailsDebug(`Client application URI: ${session.clientDescription.applicationUri}`);
opcuaServerDetailsDebug(`Client product URI: ${session.clientDescription.productUri}`);
opcuaServerDetailsDebug(`Client application name: ${session.clientDescription.applicationName
? session.clientDescription.applicationName.toString()
: "none application name"}`);
opcuaServerDetailsDebug(`Client application type: ${session.clientDescription.applicationType
? session.clientDescription.applicationType.toString()
: "none application type"}`);
}
opcuaServerDebug(`Session name: ${session.sessionName
? session.sessionName.toString()
: "none session name"}`);
opcuaServerDebug(`Session timeout: ${session.sessionTimeout}`);
opcuaServerDebug(`Session id: ${session.getSessionId()}`);
});
server.on("session_closed", (session, reason) => {
opcuaServerDebug("############## SESSION CLOSED ##############");
opcuaServerDetailsDebug(`reason: ${reason}`);
opcuaServerDetailsDebug(`Session name: ${session.sessionName
? session.sessionName.toString()
: "none session name"}`);
});
opcuaServerDebug("Server Initialized");
if (server.serverInfo) {
opcuaServerDetailsDebug(`Server Info: ${JSON.stringify(server.serverInfo)}`);
}
resolve();
}
});
});
},
listenForErrors,
setStatusPending: (node) => setNodeStatus(node, { fill: "yellow", shape: "ring", text: "pending" }),
setStatusInit: (node) => setNodeStatus(node, { fill: "yellow", shape: "dot", text: "init" }),
setStatusActive: (node) => setNodeStatus(node, { fill: "green", shape: "dot", text: "active" }),
setStatusClosed: (node) => setNodeStatus(node, { fill: "yellow", shape: "ring", text: "closed" }),
setStatusError: (node, text) => setNodeStatus(node, { fill: "red", shape: "dot", text }),
isWindows,
checkUserLogon,
getPackagePathFromIndex,
serverCertificateFile,
serverKeyFile,
};
exports.default = coreServerModule;