zoukankan      html  css  js  c++  java
  • 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客户端方法服务的调用

  • 相关阅读:
    利用递归分割(Split)字符串
    SQL Server2012 T-SQL基础教程--读书笔记(1-4章)
    kindeditor编辑器的使用
    echarts绘制四川地图
    Windows下搭建PHP开发环境(Apache+PHP+MySQL)+调试工具Xdebug的配置
    给搜索关键字添加高亮,加以颜色区分
    SQL 生成6位随机数并MD5加密输出
    微信小程序登录 .net 后端实现
    钉钉小程序http post 请求
    浅谈Web Api配合SignalR的跨域支持
  • 原文地址:https://www.cnblogs.com/retry/p/11679332.html
Copyright © 2011-2022 走看看