基於項目需求,需要使用opc開發一個數據讀寫的小模塊,查找了很多決定使用open62541,主要是封裝的很好,開發效率很快,而且可以跨平臺,不需要對com做任何瞭解。搞的前期我還看了好久的com組件
我是直接官網拿的源碼編譯出來的 。c和。h文件,1.0版本不支持這種方法,還是建議用頭文件和動態庫的方式使用它。。。編譯的時候cmake指定下編譯選項就好了。如下:
We strongly recommend to not use UA_ENABLE_AMALGAMATION=ON for your installation. This will only generate a single open62541.h header file instead of the single header files. We encourage our users to use the non-amalgamated version to reduce the header size and simplify dependency management.
下載的源碼裏有很多example,下面是摘取的一部分。
因爲開發的是opc的server端,所以記錄下server的使用。,添加節點要在new完服務器之後,run之前,而且run是個阻塞接口,因爲我們是作爲一個模塊開發,所有扔到了子線程裏。。
創建服務端
UA_Server *server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server);
UA_ServerConfig_setDefault(config);
/* Disable anonymous logins, enable two user/password logins */
config->accessControl.clear(&config->accessControl);
UA_StatusCode retval = UA_AccessControl_default(config, false,
&config->securityPolicies[config->securityPoliciesSize-1].policyUri, 2, logins);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
/* Set accessControl functions for nodeManagement */
config->accessControl.allowAddNode = allowAddNode;
config->accessControl.allowAddReference = allowAddReference;
config->accessControl.allowDeleteNode = allowDeleteNode;
config->accessControl.allowDeleteReference = allowDeleteReference;
運行服務器
retval = UA_Server_run(server, &running);
cleanup:
UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
添加節點的時候很多,上面是通過設置屬性,把添加方法的接口設置到屬性裏,沒用過,我是直接調用,說實話用到了很少就實現了功能,這個庫的功能文檔很詳細。。目前暫時用到添加節點,修改節點,監聽節點改變等功能
修改節點添加節點都是server進行,然後client讀取,,監聽節點是client寫,然後server 讀取給底層模塊使用。。
如下是一個修改節點的方式,,
UA_Float value = 10;
UA_Variant vaData;
UA_Variant_setScalar(&vaData, &value, &UA_TYPES[UA_TYPES_FLOAT]);
UA_StatusCode res = UA_Server_writeValue(server, currentNodeId, vaData);
容易出現問題的地方就是創建完節點返回的nodeid 值保存到容器的時候,這個時候需要進行深拷貝,不能直接吧返回的nodeid放到容器裏,需要調用UA_NodeId_copy 進行深拷貝,因爲這個nodeid是個結構體,裏面有指針,有需要動態開闢內存的地方。。
如果直接放到容器裏,當你在其他函數使用的時候,會發現nodeid無效。 所有記得先申請一個變量,使用上述接口實現深拷貝,在放到容器裏。。。。