diff --git a/myServer b/myServer index e52624d..019e14a 100755 Binary files a/myServer and b/myServer differ diff --git a/myServer.c b/myServer.c new file mode 100644 index 0000000..fcb338a --- /dev/null +++ b/myServer.c @@ -0,0 +1,192 @@ +#include "open62541.h" +#include +#include +#include +#include + +static volatile UA_Boolean running = true; + +static void stopHandler(int sig) { + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Received Ctrl-C"); + running = false; +} + + +static UA_StatusCode +helloMethodCallback(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) +{ + UA_String *inputStr = (UA_String*)input[0].data; + const char *helloPrefix = "Hello "; + size_t helloLen = strlen(helloPrefix); + + // 分配内存用于存储输出字符串(前缀 + 输入字符串) + size_t resultLen = helloLen + inputStr->length; + UA_Byte *result = (UA_Byte*)UA_malloc(resultLen); + if (!result) { + return UA_STATUSCODE_BADOUTOFMEMORY; + } + + // 将 "Hello " 和输入字符串复制到结果中 + memcpy(result, helloPrefix, helloLen); + memcpy(result + helloLen, inputStr->data, inputStr->length); + + // 将输出 variant 设置为结果字符串 + UA_String resultStr; + resultStr.data = result; + resultStr.length = resultLen; + UA_Variant_setScalarCopy(output, &resultStr, &UA_TYPES[UA_TYPES_STRING]); + + // 清理结果缓冲区 + UA_String_clear(&resultStr); + + return UA_STATUSCODE_GOOD; +} + +static void manuallyDefinePump(UA_Server *server) +{ + //Add NameSpace + + const char *namespaceUri = "http://example.com/MyNamespace"; + UA_UInt16 namespaceIndex = UA_Server_addNamespace(server, namespaceUri); + + + // 声明并获取服务器分配的节点 ID + UA_NodeId pumpId; + + // 定义对象属性并设置显示名称 + UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Pump (Manual)"); + + // 添加泵对象节点 + UA_Server_addObjectNode(server, + UA_NODEID_NUMERIC(namespaceIndex, 1), + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_QUALIFIEDNAME(1, "Pump (Manual)"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), + oAttr, NULL, &pumpId); + + // 定义变量属性并添加“ManufacturerName”变量节点 + UA_VariableAttributes mnAttr = UA_VariableAttributes_default; + UA_String manufacturerName = UA_STRING("Pump King Ltd."); + UA_Variant_setScalar(&mnAttr.value, &manufacturerName, &UA_TYPES[UA_TYPES_STRING]); + mnAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ManufacturerName"); + + UA_Server_addVariableNode(server, + UA_NODEID_NULL, + pumpId, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "ManufacturerName"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + mnAttr, NULL, NULL); + + // 定义变量属性并添加“ModelName”变量节点 + UA_VariableAttributes modelAttr = UA_VariableAttributes_default; + UA_String modelName = UA_STRING("Mega Pump 3000"); + UA_Variant_setScalar(&modelAttr.value, &modelName, &UA_TYPES[UA_TYPES_STRING]); + modelAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ModelName"); + + UA_Server_addVariableNode(server, + UA_NODEID_NULL, + pumpId, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "ModelName"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + modelAttr, NULL, NULL); + + // 定义变量属性并添加“Status”变量节点 + UA_VariableAttributes statusAttr = UA_VariableAttributes_default; + UA_Boolean status = true; + UA_Variant_setScalar(&statusAttr.value, &status, &UA_TYPES[UA_TYPES_BOOLEAN]); + statusAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Status"); + + UA_Server_addVariableNode(server, + UA_NODEID_NULL, + pumpId, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "Status"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + statusAttr, NULL, NULL); + + // 定义变量属性并添加“MotorRPM”变量节点 + UA_VariableAttributes rpmAttr = UA_VariableAttributes_default; + UA_Double rpm = 50.0; + UA_Variant_setScalar(&rpmAttr.value, &rpm, &UA_TYPES[UA_TYPES_DOUBLE]); + rpmAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MotorRPM"); + + UA_Server_addVariableNode(server, + UA_NODEID_NULL, + pumpId, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "MotorRPM"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + rpmAttr, NULL, NULL); + + UA_ObjectAttributes ptAttr = UA_ObjectAttributes_default; + ptAttr.displayName = UA_LOCALIZEDTEXT("en-US", "PumpType"); + UA_NodeId pumpTypeId; + UA_Server_addObjectNode(server, UA_NODEID_NULL, + pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), + UA_QUALIFIEDNAME(1, "PumpType"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), + ptAttr, + NULL, &pumpTypeId); + + + UA_Argument inputArgument; + UA_Argument_init(&inputArgument); + inputArgument.description = UA_LOCALIZEDTEXT("zh-CN", "输入字符串"); + inputArgument.name = UA_STRING("InputString"); + inputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId; // 字符串类型 + inputArgument.valueRank = UA_VALUERANK_SCALAR; // 标量 + + // 定义方法的输出参数 + UA_Argument outputArgument; + UA_Argument_init(&outputArgument); + outputArgument.description = UA_LOCALIZEDTEXT("zh-CN", "输出字符串"); + outputArgument.name = UA_STRING("OutputString"); + outputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId; // 字符串类型 + outputArgument.valueRank = UA_VALUERANK_SCALAR; // 标量 + + // 添加方法节点 + UA_MethodAttributes helloAttr = UA_MethodAttributes_default; + helloAttr.description = UA_LOCALIZEDTEXT("zh-CN", "添加Hello前缀"); + helloAttr.displayName = UA_LOCALIZEDTEXT("zh-CN", "HelloMethod"); + helloAttr.executable = true; + helloAttr.userExecutable = true; + + UA_NodeId helloMethodNodeId; + UA_Server_addMethodNode(server, + UA_NODEID_NULL, // NodeId (自动生成) + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), // 父节点为 ObjectsFolder + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), // 引用类型 + UA_QUALIFIEDNAME(1, "HelloMethod"), // 浏览名称 + helloAttr, // 属性 + &helloMethodCallback, // 回调函数 + 1, &inputArgument, // 输入参数的数量和描述 + 1, &outputArgument, // 输出参数的数量和描述 + NULL,NULL); + + +} + + + +int main(void) { + signal(SIGINT, stopHandler); + signal(SIGTERM, stopHandler); + + UA_Server *server = UA_Server_new(); + UA_ServerConfig_setDefault(UA_Server_getConfig(server)); + + manuallyDefinePump(server); + + UA_StatusCode retval = UA_Server_run(server, &running); + UA_Server_delete(server); + return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; +}