open62541-server編程


open62541--Server

1、服務構建

#include <signal.h>
#include "open62541.h"
UA_Boolean running = true; //服務器的啟停標志
static void stopHandler(int sig) 
{
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
    running = false;
}
int main(void) 
{
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);
    //server->config進行缺省化配置。(部分參數按照系統定義配置)
	UA_ServerConfig *config = UA_ServerConfig_new_default();
    /*
	 * 缺省配置后也可進行自定義修改。
	config->customHostname.data = "192.168.0.108";
    config->customHostname.length = 14;
	*/
	UA_Server *server = UA_Server_new(config); 
    UA_StatusCode retval = UA_Server_run(server, &running); //啟動server
    UA_Server_delete(server);
    UA_ServerConfig_delete(config);
    return (int)retval;
}

2、 變量類型(variable)節點的添加

static void addVariable(UA_Server *server)
{
    /*變量節點的屬性*/
    UA_VariableAttributes attr = UA_VariableAttributes_default;
    UA_Int32 myInteger = 1024;
	//節點數據的設置attr.value
	//P1:節點的數據屬性 P2:要設置的數據 P3:數據的數據類型
    UA_Variant_setScalar(&attr.value,&myInteger,&UA_TYPES[UA_TYPES_INT32]);
	//節點在用戶接口顯示的名字(本地化)
    attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
	//節點在自身本地化描述
    attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
    attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
	//變量節點的訪問權限:可讀可寫
    attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;

 
    /*定義1個節點:節點的命名空間 節點的ID標識符*/
    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1,"the.answer");
	//節點對外的瀏覽名稱(非本地化)
    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1,"the answer");
	
	//定義1個節點
    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_OBJECTSFOLDER);
	
	//定義1個節點
    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES);
    /*************************************************************
	UA_Server_addVariableNode(UA_Server *server,  // 服務
					      const UA_NodeId requestedNewNodeId, //請求添加的節點
                          const UA_NodeId parentNodeId,      //父節點
                          const UA_NodeId referenceTypeId,   //父節點引用類型節點	
                          const UA_QualifiedName browseName, //節點對外的瀏覽名稱(非本地化)
                          const UA_NodeId typeDefinition,	 //引用節點
                          const UA_VariableAttributes attr,
                          void *nodeContext, UA_NodeId *outNewNodeId)
	**************************************************************/
	
	UA_Server_addVariableNode(server,myIntegerNodeId,parentNodeId,\

                              parentReferenceNodeId,myIntegerName,\

                              UA_NODEID_NUMERIC(0,UA_NS0ID_BASEDATAVARIABLETYPE),\

                              attr,NULL,NULL);

}

2.1、變量節點數據的更新

2.1.1、手動更新

#include <signal.h>
#include "open62541.h"
static void
updateCurrentTime(UA_Server *server) {
    UA_DateTime now = UA_DateTime_now();
    UA_Variant value;
    UA_Variant_setScalar(&value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
    UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
    UA_Server_writeValue(server, currentNodeId, value);
}
static void
addCurrentTimeVariable(UA_Server *server) {
    UA_DateTime now = 0;
    UA_VariableAttributes attr = UA_VariableAttributes_default;
    attr.displayName = UA_LOCALIZEDTEXT("en-US", "Current time");
    attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
    UA_Variant_setScalar(&attr.value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
    UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
    UA_QualifiedName currentName = UA_QUALIFIEDNAME(1, "current-time");
    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
    UA_NodeId variableTypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
    UA_Server_addVariableNode(server, currentNodeId, parentNodeId,
                              parentReferenceNodeId, currentName,
                              variableTypeNodeId, attr, NULL, NULL);
    //手動更新變量值
	updateCurrentTime(server);
}

2.1.3、客戶端訪問時通過回調函數更新

//方法一:當值連續變化時,手動更新值將占用大量資源。值回調允許將變量值與外部進行同步,它們將回調附加到在每次讀取之前和每次寫入操作之后執行的變量。

static void
beforeReadTime(UA_Server *server,
               const UA_NodeId *sessionId, void *sessionContext,
               const UA_NodeId *nodeid, void *nodeContext,
               const UA_NumericRange *range, const UA_DataValue *data) {
    UA_DateTime now = UA_DateTime_now();
    UA_Variant value;
    UA_Variant_setScalar(&value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
    UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
    UA_Server_writeValue(server, currentNodeId, value);
}
//方法二:對於連續變化的數據,
static UA_StatusCode
readCurrentTime(UA_Server *server,
                const UA_NodeId *sessionId, void *sessionContext,
                const UA_NodeId *nodeId, void *nodeContext,
                UA_Boolean sourceTimeStamp, const UA_NumericRange *range,
                UA_DataValue *dataValue) {
    UA_DateTime now = UA_DateTime_now();
    UA_Variant_setScalarCopy(&dataValue->value, &now,
                             &UA_TYPES[UA_TYPES_DATETIME]);
    dataValue->hasValue = true;
    return UA_STATUSCODE_GOOD;
}

2.1.4、訂閱模式

對變量的當前值感興趣的客戶端不需要定期輪詢變量。相反,他可以使用訂閱機制來通知有關更改。

在Subscription中,客戶端添加了所謂的MonitoredItems。DataChange MonitoredItem定義監視更改的節點屬性(通常是值屬性)。服務器在內部讀取定義的時間間隔內的值並生成相應的通知。上面討論的更新節點值的三種方式都可以與通知結合使用。這是因為通知使用標准的讀取服務來查找值更改。

3、對象節點的添加

4、對象類型節點的使用

5、變量類型節點的使用

6、服務集的使用

6.1.1服務端方法服務集的集成

6.1.2客戶端方法服務的調用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM