赞
踩
上期博文【Node-RED】node-red-contrib-opcua-server模块使用(1)中,我们主要介绍了,模块安装过程中遇到的相关问题。本期博文,我们介绍node-red-contrib-opcua-server模块的使用,并以官方示例中server-with-context.json流程为例展开介绍,主要涉及地址空间的配置和加密设置。
博文所提示例已经上传资源中,期间设置的所有相关设置都保留在流程中,可以下载使用。
示例主要由变量产生和opcuaServe配置 两部分组成。
变量产生用到了注入中定时器,周期性的实现变量的生成和变化,变量主要有2部分,isoInput2-isoInput8,isoOutput2-isoOutput8,这个可以自定义,通过函数组件将变量保存到流程的上下文数据中,方便后续的使用。
通过点击注入,在上下文数据中可以进行数据查看,点击右上角的圆圈进行刷新,可以实时更新数据。
node-red-contrib-opcua-server模块中实现opcuaServe配置,主要采用opcua-compact-server组件,在前期测试中,主要以匿名形式设置,加密可以直接跳转到后面加密设置。
opc.tcp://localhost:54840
,54840为默认端口,可以自定义更改;如果Resource Path配置了,Endpoint Url设置为opc.tcp://localhost:54840/UA/NodeRED/Compact
,UA/NodeRED/Compact为默认的资源地址。然后点击部署,当显示active 即表示成功。
const opcua = coreServer.choreCompact.opcua;
const namespace = addressSpace.getOwnNamespace();
const Variant = opcua.Variant;
const DataType = opcua.DataType;
const DataValue = opcua.DataValue;
var flexServerInternals = this;
this.sandboxFlowContext.set("isoInput1", 0);
this.setInterval(() => {
flexServerInternals.sandboxFlowContext.set(
"isoInput1",
Math.random() + 50.0
);
}, 500);
this.sandboxFlowContext.set("isoInput2", 0);
this.sandboxFlowContext.set("isoInput3", 0);
...
coreServer.debugLog("init dynamic address space");
const rootFolder = addressSpace.findNode("RootFolder");
node.warn("construct new address space for OPC UA");
const myDevice = namespace.addFolder(rootFolder.objects, {
"browseName": "RaspberryPI-Zero-WLAN"
});
const gpioFolder = namespace.addFolder(myDevice, { "browseName": "GPIO" });
const isoInputs = namespace.addFolder(gpioFolder, {
"browseName": "Inputs"
});
const isoOutputs = namespace.addFolder(gpioFolder, {
"browseName": "Outputs"
});
const gpioDI1 = namespace.addVariable({
"organizedBy": isoInputs,
"browseName": "I1",
"nodeId": "ns=1;s=Isolated_Input1",
"dataType": "Double",
"value": {
"get": function() {
return new Variant({
"dataType": DataType.Double,
"value": flexServerInternals.sandboxFlowContext.get("isoInput1")
});
},
"set": function(variant) {
flexServerInternals.sandboxFlowContext.set(
"isoInput1",
parseFloat(variant.value)
);
return opcua.StatusCodes.Good;
}
}
});
const gpioDI2 = namespace.addVariable({
"organizedBy": isoInputs,
"browseName": "I2",
"nodeId": "ns=1;s=Isolated_Input2",
"dataType": "Double",
"value": {
"get": function() {
return new Variant({
"dataType": DataType.Double,
"value": flexServerInternals.sandboxFlowContext.get("isoInput2")
});
},
"set": function(variant) {
flexServerInternals.sandboxFlowContext.set(
"isoInput2",
parseFloat(variant.value)
);
return opcua.StatusCodes.Good;
}
}
});
...
const viewDI = namespace.addView({
"organizedBy": rootFolder.views,
"browseName": "RPIW0-Digital-Ins"
});
const viewDO = namespace.addView({
"organizedBy": rootFolder.views,
"browseName": "RPIW0-Digital-Outs"
});
viewDI.addReference({
"referenceType": "Organizes",
"nodeId": gpioDI1.nodeId
});
viewDI.addReference({
"referenceType": "Organizes",
"nodeId": gpioDI2.nodeId
});
..\certificates
,不太对,依旧报没有路径下没有文件。C:\Users\11003189\.node-red\node_modules\node-red-contrib-opcua-server\opcua-certificate-2048\server_selfsigned_cert_2048.pem
C:\Users\11003189\.node-red\node_modules\node-red-contrib-opcua-server\opcua-certificate-2048\server_key_2048.pem
openssl x509 -in server_selfsigned_cert_2048.pem -out server_selfsigned_cert_2048.der -outform DER
这里有一个问题,官网博文中说加密模式选Aes128Sha256RsaOaep,但是opcuaServe组件并不支持这个算法模式,所以最后也就没有连接成功,但是官网博文中一样的配置居然连接成功了,很迷。
How to Deploy a Basic OPC-UA Server in Node-RED - Part 1
How to Build a Secure OPC-UA Server for PLCs in Node-RED
对node-red-contrib-opcua-server模块的研究就先到这里了,原以为该模块的函数部分编辑可以实现二次开发,结果只能是地址空间的配置,而且该模块也没有输出。
又测试了node-red-contrib-opcua,它主要是输出连接状态、收到的写入信息,不能在服务器中对输出信息进行二次处理。
基于以上的情况,需求依旧无法实现,上周的喜悦戛然而止,不过热情依旧,继续探索Opcua 的魅力,目前也看了c++中实现Opcua的底层函数,严重怀疑估计得改底层代码,庆幸NodeRed是开源的,因此继续研究。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。