作为一种通信协议,文件传输是非常重要的。例如传输执行程序,图片,配置文件等等。文件传输的机制和类型在 OPC UA 中已经存在很长时间了。FileType (作为ObjectType)和ImageType长期以来一直是内置模型的一部分,并且也用于许多配套规范(例如;用于设备的 OPC UA、用于机器视觉的 OPC UA、OPC UA )用于数控)。
自版本 1.5.2 起,文件传输已从第 5 部分中删除,并给出了自己的部分(UA 第 20 部分:文件传输)。
在OPC UA DI中,该方法用于下载和上传软件。另一个成功的用例是Machinery 的ResultTransferType,它旨在为测量结果生成相应的报告并将其传输给客户端。
我计划使用Filetype 文件传输的方法来下载IEC61499 的功能块网络,功能块库。如此一来,将IEC61499 标准完全建立在opcua 的基础之上。而不采用其它自定义的协议。
FileType 是一个内置的对象类型,包含了一些特征变量和方法。
UA_NodeId fileID;
UA_ObjectAttributes fileAttr = UA_ObjectAttributes_default;
fileAttr.displayName = UA_LOCALIZEDTEXT((char *)"en-US", (char *)"File");
UA_Server_addObjectNode(server, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, (char *)"File"), UA_NODEID_NUMERIC(0, UA_NS0ID_FILETYPE),
fileAttr, NULL, &fileID);
不过,需要对Writable ,Useritable 设置为true。另一个重点是为其中的方法编写callback
FileType 中的方法包括:
这几个方法与C语言中的文件操作基本是一一对应的。
Open方法
输入参数:mode
输出参数:handle
其中:
mode 是文件打开的模式,与C++ 的对应关系如下
OPC统一协议 |
C++ |
说明 |
文件已存在时的操作 |
文件不存在时的操作 |
|||
附加 |
删除 |
写 |
读 |
||||
0 |
0 |
0 |
1 |
“r” |
打开文件进行读取 |
从头开始读 |
错误 |
0 |
1 |
1 |
0 |
“w” |
创建一个用于写入的文件 |
销毁内容 |
创建新的 |
1 |
0 |
1 |
0 |
“A” |
追加到文件以进行写入 |
写到最后 |
创建新的 |
0 |
0 |
1 |
1 |
“r+” |
打开文件进行读/写 |
从头开始读 |
C/C++ 中的错误[2] |
0 |
1 |
1 |
1 |
“w+” |
创建一个文件用于读/写 |
销毁内容 |
创建新的 |
1 |
0 |
1 |
1 |
“一个+” |
打开文件进行读/写 |
写到最后 |
创建新的 |
handle 是文件句柄,当打开文件后,返回一个文件句柄,后续的操作使用文件句柄。
写文件
输入参数:
1 文件句柄 handle
3 写入数据 ByteString
关闭文件
输入参数:文件句柄(handle)
国外有一些测试,结果如下:
Protocol |
Max. transfer time |
Min. transfer time |
Average transfer time |
HTTP |
36.96 [s] |
17.01 [s] |
22.27 [s] |
FTP |
34.73 [s] |
19.41 [s] |
22.99 [s] |
OPC UA |
23.88 [s] |
18.21 [s] |
20.53 [s] |
相比执行,opcua 文件传输的效率是不错的。
open61541 是开源opcua 项目,该项目中并没有对FileType 操作的支持,但是FileType 是一个普通的对象类型,完全可以使用基本的程序实现FileType 对象的建立。而方法回调函数和文件操作需要程序需要额外的代码。可惜的是open61541 项目中并没有FileType 的Example,网络上也没有相对完整的例子。于是我写了一个:
代码(支持WriteFile)
#include
#include
#include
#include
#include
#include
/* Build Instructions (Linux)
* - g++ server.cpp -lopen62541 -o server */
using namespace std;
char *UA_String2string(UA_String uaString)
{
char *convert = (char *)UA_malloc(sizeof(char) * uaString.length + 1);
memcpy(convert, uaString.data, uaString.length);
convert[uaString.length] = '\0';
return convert;
}
UA_StatusCode OpenFileCallback(UA_Server *server, const UA_NodeId *sessionId,
void *sessionContext, const UA_NodeId *methodId,
void *methodContext, const UA_NodeId *objectId,
void *objectContext, size_t inputSize,
const UA_Variant *input, size_t outputSize,
UA_Variant *output)
{
cout << "Open File Callback" << endl;
int FileMode=*(UA_Byte *)(input[0].data);
cout<<"mode:"<
代码有一些调试的痕迹,但是在ubuntu 上是能够运行的。
使用uaExpert 测试
在FileType 实例击右键
点击 Write from local file
希望能够帮到你。