{"id":4063,"date":"2020-09-09T15:28:22","date_gmt":"2020-09-09T06:28:22","guid":{"rendered":"https:\/\/now0930.pe.kr\/wordpress\/?p=4063"},"modified":"2020-09-09T15:32:03","modified_gmt":"2020-09-09T06:32:03","slug":"open62531-server-plc-%ec%8b%9c%eb%ae%ac%eb%a0%88%ec%9d%b4%ec%85%98","status":"publish","type":"post","link":"https:\/\/now0930.pe.kr\/wordpress\/open62531-server-plc-%ec%8b%9c%eb%ae%ac%eb%a0%88%ec%9d%b4%ec%85%98\/","title":{"rendered":"open62531 server plc \uc2dc\ubbac\ub808\uc774\uc158"},"content":{"rendered":"\n<p>\uc784\uc758 \uc124\ube44\uc5d0 latch, clamp, pin, robot\uc744 \uc124\uce58\ud588\ub2e4. \ub300\ubd80\ubd84 \ub798\ub354\ub85c \ub3d9\uc791\ud558\uace0, PLC \uba54\uc774\ucee4\uac00 cpu\uc5d0  opc ua \uc11c\ubc84 \uae30\ub2a5\uc744 \uad6c\ud604\ud558\uc5ec \uc8fc\uae30\uc801\uc73c\ub85c plc \uba54\ubaa8\ub9ac \ub370\uc774\ud130\ub97c server\ub85c \uc5c5\ub370\uc774\ud2b8 \ud55c\ub2e4.(\uace0 \uc0dd\uac01\ud558\uc790.) \uc9d1\uc5d0 PLC\uac00 \uc5c6\uace0, \uc544\uc9c1 \uc774\ub97c \uc81c\ub300\ub85c \uad6c\ud604\ud560\uc9c0 \ubaa8\ub974\uaca0\uc5b4 \ub300\ucda9 \uc9dc\uc9d1\uae30\ub85c \ub9cc\ub4e4\uc5c8\ub2e4.<\/p>\n\n\n\n<p>object\ub85c \uac01 \uc124\ube44\ub97c \ub4f1\ub85d\ud558\uace0 Value \ubcc0\uc218\ub85c staus\ub97c bool \ud0c0\uc785\uc73c\ub85c \ub4f1\ub85d\ud588\ub2e4. OPC UA \ubb38\uc11c\ub97c \uc77d\uc9c0 \ubabb\ud574 \uc774\ub807\uac8c \ud558\ub294\uac8c \ub9de\ub294\uc9c0 \ubaa8\ub974\uaca0\ub2e4. \uc554\ud2bc 4\uac1c(pin, latch, clamp, robot) \ub97c \ub4f1\ub85d\ud558\uace0 \uc21c\uc11c\ub300\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud588\ub2e4.<\/p>\n\n\n\n<p>\ucc98\uc74c\uc5d0\ub294 thread\ub85c \ub3cc\ub824 UA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\ub85c \uc368 \uc8fc\ub824\ud588\uc73c\ub098, \uc720\ud22c\ube0c\uc5d0 <a href=\"https:\/\/youtu.be\/abDnBv5u6bU\">\uc88b\uc740 \ub3d9\uc601\uc0c1<\/a>\uc744 \ucc3e\uc544 \uadf8\ub300\ub85c \ub530\ub77c\ud588\ub2e4. \uc11c\ubc84 \uc911\uac04\uc5d0 sleep\uc744 \ub123\uc5b4 \ubc84\ub9ac\uba74 client \ucabd \uc5f0\uacb0\ub3c4 \uc751\ub2f5\ud558\uc9c0 \ubabb\ud55c\ub2e4. timestamp\ub97c \ucc0d\uc5b4 \uc77c\uc815 \uc870\uac74\uc744 \ub118\uc5b4\uac00\uba74 update \ud558\ub3c4\ub85d (\ub530\ub77c)\ud588\ub2e4. \ud56d\uc0c1 cycle  time\uc774 \ub611\uac19\uc744 \uc218 \uc5c6\uc73c\ub2c8, random \uac12\uc73c\ub85c \uc870\uc815 \ud574\uc57c\uaca0\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"open62541.h\"\n\n#include &lt;signal.h>\n#include &lt;stdlib.h>\n#include &lt;time.h>\n\nstatic volatile UA_Boolean running = true;\nstatic void stopHandler(int sig) {\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"received ctrl-c\");\n\trunning = false;\n}\n\n\n\n\nstatic void\nbeforeReadVal(UA_Server *server,\n\t\tconst UA_NodeId *sessionId, void *sessionContext,\n\t\tconst UA_NodeId *nodeid, void *nodeContext,\n\t\tconst UA_NumericRange *range, const UA_DataValue *data) {\n\t\/\/updateCurrentTime(server);\n\tint tmpVal = rand()%1000;\n\tUA_Variant value;\n\tUA_Variant_setScalar(&amp;value, &amp;tmpVal, &amp;UA_TYPES[UA_TYPES_INT32]);\n\tUA_NodeId currentNodeId = UA_NODEID_STRING(1, \"Test Var:Me\");\n\t\/\/UA_Server_writeValue(server, currentNodeId, value);\n\n\n}\n\n\/* predefined identifier for later use *\/\nUA_NodeId pumpTypeId = {1, UA_NODEIDTYPE_NUMERIC, {1001}};\nUA_NodeId cylTypeId = {1, UA_NODEIDTYPE_NUMERIC, {2001}};\nUA_NodeId robotTypeId = {1, UA_NODEIDTYPE_NUMERIC, {3001}};\n\n\nstatic void\ndefineObjectTypes(UA_Server *server) {\n\t\/* Define the object type for \"Device\" *\/\n\tUA_NodeId deviceTypeId; \/* get the nodeid assigned by the server *\/\n\tUA_ObjectTypeAttributes dtAttr = UA_ObjectTypeAttributes_default;\n\tdtAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"DeviceType\");\n\tUA_Server_addObjectTypeNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"DeviceType\"), dtAttr,\n\t\t\tNULL, &amp;deviceTypeId);\n\n\tUA_VariableAttributes mnAttr = UA_VariableAttributes_default;\n\tmnAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"ManufacturerName\");\n\tUA_NodeId manufacturerNameId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"ManufacturerName\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, &amp;manufacturerNameId);\n\t\/* Make the manufacturer name mandatory *\/\n\tUA_Server_addReference(server, manufacturerNameId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n\n\n\tUA_VariableAttributes modelAttr = UA_VariableAttributes_default;\n\tmodelAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"ModelName\");\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"ModelName\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, NULL);\n\n\t\/* Define the object type for \"Pump\" *\/\n\tUA_ObjectTypeAttributes ptAttr = UA_ObjectTypeAttributes_default;\n\tptAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"PumpType\");\n\tUA_Server_addObjectTypeNode(server, pumpTypeId,\n\t\t\tdeviceTypeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"PumpType\"), ptAttr,\n\t\t\tNULL, NULL);\n\n\tUA_VariableAttributes statusAttr = UA_VariableAttributes_default;\n\tstatusAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Status\");\n\tstatusAttr.valueRank = UA_VALUERANK_SCALAR;\n\tUA_NodeId statusId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, pumpTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Status\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, &amp;statusId);\n\t\/* Make the status variable mandatory *\/\n\tUA_Server_addReference(server, statusId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n\n\tUA_VariableAttributes rpmAttr = UA_VariableAttributes_default;\n\trpmAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"MotorRPM\");\n\trpmAttr.valueRank = UA_VALUERANK_SCALAR;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, pumpTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"MotorRPMs\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), rpmAttr, NULL, NULL);\n}\n\nstatic void\ndefineCylTypes(UA_Server *server) {\n\t\/* Define the object type for \"Device\" *\/\n\tUA_NodeId deviceTypeId; \/* get the nodeid assigned by the server *\/\n\tUA_ObjectTypeAttributes dtAttr = UA_ObjectTypeAttributes_default;\n\tdtAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Cylinder Type\");\n\tUA_Server_addObjectTypeNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"Cylinder Type\"), dtAttr,\n\t\t\tNULL, &amp;deviceTypeId);\n\n\tUA_VariableAttributes mnAttr = UA_VariableAttributes_default;\n\tmnAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Manufacturer Name\");\n\tUA_NodeId manufacturerNameId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Cylinder\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, &amp;manufacturerNameId);\n\n\tUA_VariableAttributes modelAttr = UA_VariableAttributes_default;\n\tUA_NodeId modelNameId;\n\tmodelAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Cyl Model Name\");\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Cyl Model Name\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, &amp;modelNameId);\n\n\tUA_Server_addReference(server,modelNameId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n\n\t\/* Define the object type for \"Pump\" *\/\n\tUA_ObjectTypeAttributes ptAttr = UA_ObjectTypeAttributes_default;\n\tptAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Running State\");\n\tUA_Server_addObjectTypeNode(server, cylTypeId,\n\t\t\tdeviceTypeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"Running State\"), ptAttr,\n\t\t\tNULL, NULL);\n\n\n\tUA_VariableAttributes statusAttr = UA_VariableAttributes_default;\n\tstatusAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Status\");\n\tstatusAttr.valueRank = UA_VALUERANK_SCALAR;\n\tUA_NodeId statusId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, cylTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Status\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, &amp;statusId);\n\t\/* Make the manufacturer name mandatory *\/\n\t\/\/ UA_Server_addReference()\ub97c \uc5b4\ub5bb\uac8c \ud558\ub0d0\uc5d0 \ub530\ub77c  statusId\n\t\/\/ instance \ub9cc\ub4e4\uacbd\uc6b0 \ud45c\uc2dc\n\tUA_Server_addReference(server, statusId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n}\n\n\n\nstatic void\ndefineRobotTypes(UA_Server *server) {\n\t\/* Define the object type for \"Device\" *\/\n\tUA_NodeId deviceTypeId; \/* get the nodeid assigned by the server *\/\n\tUA_ObjectTypeAttributes dtAttr = UA_ObjectTypeAttributes_default;\n\tdtAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Robot Type\");\n\tUA_Server_addObjectTypeNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"Robot Type\"), dtAttr,\n\t\t\tNULL, &amp;deviceTypeId);\n\n\tUA_VariableAttributes mnAttr = UA_VariableAttributes_default;\n\tmnAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Manufacturer Name\");\n\tUA_NodeId manufacturerNameId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Robot\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, &amp;manufacturerNameId);\n\n\tUA_VariableAttributes modelAttr = UA_VariableAttributes_default;\n\tUA_NodeId modelNameId;\n\tmodelAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Robot Model Name\");\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Robot Model Name\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, &amp;modelNameId);\n\n\tUA_Server_addReference(server,modelNameId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n\n\t\/* Define the object type for \"Pump\" *\/\n\tUA_ObjectTypeAttributes ptAttr = UA_ObjectTypeAttributes_default;\n\tptAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Interlock\");\n\tUA_Server_addObjectTypeNode(server, robotTypeId,\n\t\t\tdeviceTypeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),\n\t\t\tUA_QUALIFIEDNAME(1, \"Interlock\"), ptAttr,\n\t\t\tNULL, NULL);\n\n\n\tUA_VariableAttributes statusAttr = UA_VariableAttributes_default;\n\tstatusAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", \"Status\");\n\tstatusAttr.valueRank = UA_VALUERANK_SCALAR;\n\tUA_NodeId statusId;\n\tUA_Server_addVariableNode(server, UA_NODEID_NULL, robotTypeId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"Status\"),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, &amp;statusId);\n\t\/* Make the manufacturer name mandatory *\/\n\t\/\/ UA_Server_addReference()\ub97c \uc5b4\ub5bb\uac8c \ud558\ub0d0\uc5d0 \ub530\ub77c  statusId\n\t\/\/ instance \ub9cc\ub4e4\uacbd\uc6b0 \ud45c\uc2dc\n\tUA_Server_addReference(server, statusId,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),\n\t\t\tUA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);\n}\n\n\n\nstatic void\naddPumpObjectInstance(UA_Server *server, char *name) {\n\tUA_ObjectAttributes oAttr = UA_ObjectAttributes_default;\n\toAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", name);\n\tUA_Server_addObjectNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),\n\t\t\tUA_QUALIFIEDNAME(1, name),\n\t\t\tpumpTypeId, \/* this refers to the object type\n\t\t\t\t\t\t   identifier *\/\n\t\t\toAttr, NULL, NULL);\n}\n\nstatic void\naddCylObjectInstance(UA_Server *server, char *name) {\n\tUA_ObjectAttributes oAttr = UA_ObjectAttributes_default;\n\toAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", name);\n\t\/*\n\t   UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,\n\t   const UA_NodeId parentNodeId,\n\t   const UA_NodeId referenceTypeId,\n\t   const UA_QualifiedName browseName,\n\t   const UA_NodeId typeDefinition,\n\t   const UA_ObjectAttributes attr,\n\t   void *nodeContext, UA_NodeId *outNewNodeId) {\n\t *\/\n\n\tUA_Server_addObjectNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),\n\t\t\tUA_QUALIFIEDNAME(1, name),\n\t\t\tcylTypeId, \/* this refers to the object type\n\t\t\t\t\t\t  identifier *\/\n\t\t\toAttr, NULL, NULL);\n}\n\n\n\nstatic void\naddRbtObjectInstance(UA_Server *server, char *name) {\n\tUA_ObjectAttributes oAttr = UA_ObjectAttributes_default;\n\toAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\", name);\n\t\/*\n\t   UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,\n\t   const UA_NodeId parentNodeId,\n\t   const UA_NodeId referenceTypeId,\n\t   const UA_QualifiedName browseName,\n\t   const UA_NodeId typeDefinition,\n\t   const UA_ObjectAttributes attr,\n\t   void *nodeContext, UA_NodeId *outNewNodeId) {\n\t *\/\n\n\tUA_Server_addObjectNode(server, UA_NODEID_NULL,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),\n\t\t\tUA_QUALIFIEDNAME(1, name),\n\t\t\trobotTypeId, \/* this refers to the object type\n\t\t\t\t\t\t\tidentifier *\/\n\t\t\toAttr, NULL, NULL);\n}\n\n\nstatic UA_StatusCode\npumpTypeConstructor(UA_Server *server,\n\t\tconst UA_NodeId *sessionId, void *sessionContext,\n\t\tconst UA_NodeId *typeId, void *typeContext,\n\t\tconst UA_NodeId *nodeId, void **nodeContext) {\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"New pump created\");\n\n\t\/* Find the NodeId of the status child variable *\/\n\tUA_RelativePathElement rpe;\n\tUA_RelativePathElement_init(&amp;rpe);\n\trpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);\n\trpe.isInverse = false;\n\trpe.includeSubtypes = false;\n\trpe.targetName = UA_QUALIFIEDNAME(1, \"Status\");\n\n\tUA_BrowsePath bp;\n\tUA_BrowsePath_init(&amp;bp);\n\tbp.startingNode = *nodeId;\n\tbp.relativePath.elementsSize = 1;\n\tbp.relativePath.elements = &rpe;\n\n\tUA_BrowsePathResult bpr =\n\t\tUA_Server_translateBrowsePathToNodeIds(server, &amp;bp);\n\tif(bpr.statusCode != UA_STATUSCODE_GOOD ||\n\t\t\tbpr.targetsSize &lt; 1)\n\t\treturn bpr.statusCode;\n\n\t\/* Set the status value *\/\n\tUA_Boolean status = true;\n\tUA_Variant value;\n\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\tUA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value);\n\tUA_BrowsePathResult_clear(&amp;bpr);\n\n\t\/* At this point we could replace the node context .. *\/\n\n\treturn UA_STATUSCODE_GOOD;\n}\n\nstatic void\naddPumpTypeConstructor(UA_Server *server) {\n\tUA_NodeTypeLifecycle lifecycle;\n\tlifecycle.constructor = pumpTypeConstructor;\n\tlifecycle.destructor = NULL;\n\tUA_Server_setNodeTypeLifecycle(server, pumpTypeId, lifecycle);\n}\n\n\n\n\n\/\/method \ucd94\uac00\nstatic UA_StatusCode\nhelloWorldMethodCallback(UA_Server *server,\n\t\tconst UA_NodeId *sessionId, void *sessionHandle,\n\t\tconst UA_NodeId *methodId, void *methodContext,\n\t\tconst UA_NodeId *objectId, void *objectContext,\n\t\tsize_t inputSize, const UA_Variant *input,\n\t\tsize_t outputSize, UA_Variant *output) {\n\tUA_String *inputStr = (UA_String*)input->data;\n\tUA_String tmp = UA_STRING_ALLOC(\"Hello \");\n\tif(inputStr->length > 0) {\n\t\ttmp.data = (UA_Byte *)UA_realloc(tmp.data, tmp.length + inputStr->length);\n\t\tmemcpy(&amp;tmp.data[tmp.length], inputStr->data, inputStr->length);\n\t\ttmp.length += inputStr->length;\n\t}\n\tUA_Variant_setScalarCopy(output, &amp;tmp, &amp;UA_TYPES[UA_TYPES_STRING]);\n\tUA_String_clear(&amp;tmp);\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, \"Hello World was called\");\n\treturn UA_STATUSCODE_GOOD;\n}\n\nstatic void\naddHellWorldMethod(UA_Server *server) {\n\tUA_Argument inputArgument;\n\tUA_Argument_init(&amp;inputArgument);\n\tinputArgument.description = UA_LOCALIZEDTEXT(\"en-US\", \"A String\");\n\tinputArgument.name = UA_STRING(\"MyInput\");\n\tinputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;\n\tinputArgument.valueRank = UA_VALUERANK_SCALAR;\n\n\tUA_Argument outputArgument;\n\tUA_Argument_init(&amp;outputArgument);\n\toutputArgument.description = UA_LOCALIZEDTEXT(\"en-US\", \"A String\");\n\toutputArgument.name = UA_STRING(\"MyOutput\");\n\toutputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;\n\toutputArgument.valueRank = UA_VALUERANK_SCALAR;\n\n\tUA_MethodAttributes helloAttr = UA_MethodAttributes_default;\n\thelloAttr.description = UA_LOCALIZEDTEXT(\"en-US\",\"Say `Hello World`\");\n\thelloAttr.displayName = UA_LOCALIZEDTEXT(\"en-US\",\"Hello World\");\n\thelloAttr.executable = true;\n\thelloAttr.userExecutable = true;\n\tUA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1,62541),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),\n\t\t\tUA_QUALIFIEDNAME(1, \"hello world\"),\n\t\t\thelloAttr, &amp;helloWorldMethodCallback,\n\t\t\t1, &amp;inputArgument, 1, &amp;outputArgument, NULL, NULL);\n}\n\n\n\/\/\uc774\ub984\uc73c\ub85c nodeId\ub97c \ucc3e\ub294 \ud568\uc218.\nUA_StatusCode\nfindNodeIdWithName(UA_Server *server, UA_NodeId *startNodeId, char *name, UA_NodeId **retNodeId){\n\n\t\/* Find the NodeId of the status child variable *\/\n\tUA_RelativePathElement rpe;\n\tUA_RelativePathElement_init(&amp;rpe);\n\trpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);\n\trpe.isInverse = false;\n\trpe.includeSubtypes = false;\n\trpe.targetName = UA_QUALIFIEDNAME(1,name); \n\n\tUA_BrowsePath bp;\n\tUA_BrowsePath_init(&amp;bp);\n\n\n\tbp.startingNode = *startNodeId;\n\tbp.relativePath.elementsSize = 1;\n\tbp.relativePath.elements = &rpe;\n\n\tUA_BrowsePathResult bpr =\n\t\tUA_Server_translateBrowsePathToNodeIds(server, &amp;bp);\n\tif(bpr.statusCode != UA_STATUSCODE_GOOD ||\n\t\t\tbpr.targetsSize &lt; 1)\n\t\treturn bpr.statusCode;\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"found target is %d\", bpr.targets->targetId.nodeId.identifier.numeric);\n\t**retNodeId = bpr.targets->targetId.nodeId;\n\n}\n\n\n\nint main(void) {\n\tsignal(SIGINT, stopHandler);\n\tsignal(SIGTERM, stopHandler);\n\n\tUA_Server *server = UA_Server_new();\n\tUA_ServerConfig_setDefault(UA_Server_getConfig(server));\n\tUA_ServerConfig* config = UA_Server_getConfig(server);\n\tconfig->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;\n\n\t\/\/addVariable(server);\n\t\/\/writeVariable(server);\n\t\/\/writeWrongVariable(server);\n\n\n\t\/\/vendor, serial, variable \uc21c\uc73c\ub85c \ucd94\uac00.\n\n\t\/\/\uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9\ud560 \ubd80\ubd84 \uc124\uc815.\n\tUA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\tUA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);\n\t\/\/variable \ucd94\uac00.\n\tUA_VariableAttributes varAttr = UA_VariableAttributes_default;\n\tUA_Int32 varName = 10;\n\tUA_Variant_setScalar(&amp;varAttr.value, &amp;varName, &amp;UA_TYPES[UA_TYPES_INT32]);\n\tUA_NodeId varNodeId = UA_NODEID_STRING(1, \"Test Var:Me\");\n\tUA_QualifiedName myVarName = UA_QUALIFIEDNAME(1, \"variable\");\n\tUA_Server_addVariableNode(server, varNodeId, parentNodeId,\n\t\t\tparentReferenceNodeId, myVarName,\n\t\t\tUA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), varAttr, NULL, NULL);\n\n\t\/\/add callback\n\tUA_ValueCallback callback ;\n\tcallback.onRead = beforeReadVal;\n\tcallback.onWrite = NULL;\n\tUA_NodeId currentNodeId = UA_NODEID_STRING(1, \"Test Var:Me\");\n\tUA_Server_setVariableNode_valueCallback(server, currentNodeId, callback);\n\n\t\/\/\uc124\ube44 \uc815\uc758\n\n\tdefineCylTypes(server);\n\taddCylObjectInstance(server, \"pin\");\n\taddCylObjectInstance(server, \"latch\");\n\taddCylObjectInstance(server, \"clamp\");\n\tdefineRobotTypes(server);\n\taddRbtObjectInstance(server, \"Loading Robot\");\n\n\t\/*\n\t   defineObjectTypes(server);\n\t   addPumpTypeConstructor(server);\n\t   addPumpObjectInstance(server, \"pump4\");\n\t *\/\n\n\n\t\/\/method\n\taddHellWorldMethod(server);\n\n\n\t\/\/ladder\ub97c \uc2dc\ubbac\ub798\uc774\uc158\ud558\ub294 \ubd80\ubd84.\n\t\/\/thread\ub85c latch fwd -> clamp fwd -> pin fwd -> robot in -> pin bwd: \uacf5\uc815 \uc791\uc5c5\uc2dc\uac04\n\t\/\/         robot in off -> clamp bwd -> latch bwd \uc21c\uc73c\ub85c \uc2e4\ud589\n\n#undef TESe\n#ifdef TEST\n\n\t\/\/\ud14c\uc2a4\ud2b8\n\t\/\/\uac01 \uc124\ube44\uac12\uc744 \uc124\uc815\ud558\ub294 \ubd80\ubd84\n\tUA_Variant tmp_value;\n\tbool bitoff = 0;\n\tUA_Variant_setScalar(&amp;tmp_value, &amp;bitoff, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\tUA_NodeId tmpNodeId = UA_NODEID_STRING(1, \"Status\");\n\tUA_Server_writeValue(server, tmpNodeId, tmp_value);\n\n\t\/* Find the NodeId of the status child variable *\/\n\tUA_RelativePathElement rpe;\n\tUA_RelativePathElement_init(&amp;rpe);\n\trpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);\n\trpe.isInverse = false;\n\trpe.includeSubtypes = true;\n\t\/\/rpe.targetName = UA_QUALIFIEDNAME(1, \"Status\");\n\trpe.targetName = UA_QUALIFIEDNAME(1, \"latch\");\n\t\/\/rpe.targetName = UA_QUALIFIEDNAME(1, \"variable\");\n\n\n\tUA_BrowsePath bp;\n\tUA_BrowsePath_init(&amp;bp);\n\tUA_NodeId *nodeId  = UA_NodeId_new();\n\t*nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\t\/\/UA_NodeId tmp = {0, UA_NODEIDTYPE_NUMERIC, {50238}};\n\t\/\/printf(\"\\nNode id is %d\\n\", tmp);\n\t\/\/UA_NodeId *nodeId = &tmp;\n\tbp.startingNode = *nodeId;\n\tbp.relativePath.elementsSize = 1;\n\tbp.relativePath.elements = &rpe;\n\n\tUA_BrowsePathResult bpr =\n\t\tUA_Server_translateBrowsePathToNodeIds(server, &amp;bp);\n\tif(bpr.statusCode != UA_STATUSCODE_GOOD ||\n\t\t\tbpr.targetsSize &lt; 1)\n\t\treturn bpr.statusCode;\n\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"found target is %d\", bpr.targets->targetId.nodeId.identifier.numeric);\n\t\/\/print\ub85c structure\ub97c \ucd9c\ub825\ud560 \uc218 \uc5c6\uc74c.\n\t\/\/printf(\"\\nnode id is %d\\n\", (UA_NodeId)bpr.targets->targetId.nodeId);\n\t\/\/* Set the status value *\/\n\tUA_Boolean status = true;\n\tUA_Variant value;\n\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\tUA_Server_writeValue(server, bpr.targets->targetId.nodeId, value);\n\t\/\/UA_Server_writeValue(server, tmp, value);\n\n\t\/\/\ub2e4\uc2dc \uc544\ub798\ub85c \ub0b4\ub9bc.\n\tbp.startingNode = bpr.targets->targetId.nodeId;\n\trpe.targetName = UA_QUALIFIEDNAME(1, \"Status\");\n\tUA_BrowsePathResult bpr2 =\n\t\tUA_Server_translateBrowsePathToNodeIds(server, &amp;bp);\n\tif(bpr2.statusCode != UA_STATUSCODE_GOOD ||\n\t\t\tbpr2.targetsSize &lt; 1)\n\t\treturn bpr.statusCode;\n\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"found target is %d\", bpr2.targets->targetId.nodeId.identifier.numeric);\n\tUA_Server_writeValue(server, bpr2.targets->targetId.nodeId, value);\n\tUA_BrowsePathResult_clear(&amp;bpr);\n#endif\n\n\t\/\/NodeId\ub97c \uc800\uc7a5\ud560 structure \uc0dd\uc131\n\tstruct eqiupNodeId{\n\t\tUA_NodeId latchNodeId;\n\t\tUA_NodeId clampNodeId;\n\t\tUA_NodeId pinNodeId;\n\t\tUA_NodeId robotNodeId;\n\t};\n\n\tstruct eqiupNodeId myEquipNodeId;\n\n\tUA_NodeId **nodeIdtmp;\n\tUA_NodeId *nodeIdtmp2 = UA_NodeId_new();\n\tnodeIdtmp = &nodeIdtmp2;\n\tUA_NodeId *nodeId  = UA_NodeId_new();\n\t*nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\n\tif(\tfindNodeIdWithName(server, nodeId, \"latch\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\tnodeId = *nodeIdtmp;\n\t\tif( findNodeIdWithName(server, nodeId, \"Status\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\t\tnodeId = *nodeIdtmp;\n\t\t\tmyEquipNodeId.latchNodeId = *nodeId;\n\t\t\t\/\/printf(\"Variable \ubcc0\uacbd\\n\");\n\t\t\t\/\/* Set the status value *\/\n\t\t\t\/\/\t\t\tUA_Boolean status = false;\n\t\t\t\/\/\t\t\tUA_Variant value;\n\t\t\t\/\/\t\t\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\/\/\t\t\tUA_Server_writeValue(server, *nodeId, value);\n\t\t\t\/\/\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"node id %d value was written\", nodeId->identifier.numeric);\n\t\t}\n\t}\n\t*nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\tif(\tfindNodeIdWithName(server, nodeId, \"clamp\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\tnodeId = *nodeIdtmp;\n\t\tif( findNodeIdWithName(server, nodeId, \"Status\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\t\tnodeId = *nodeIdtmp;\n\t\t\tmyEquipNodeId.clampNodeId = *nodeId;\n\n\t\t\t\/\/printf(\"Variable \ubcc0\uacbd\\n\");\n\t\t\t\/\/* Set the status value *\/\n\t\t\t\/\/\t\t\tUA_Boolean status = false;\n\t\t\t\/\/\t\t\tUA_Variant value;\n\t\t\t\/\/\t\t\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\/\/\t\t\tUA_Server_writeValue(server, *nodeId, value);\n\t\t\t\/\/\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"node id %d value was written\", nodeId->identifier.numeric);\n\t\t}\n\t}\n\n\t*nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\tif(\tfindNodeIdWithName(server, nodeId, \"pin\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\tnodeId = *nodeIdtmp;\n\t\tif( findNodeIdWithName(server, nodeId, \"Status\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\t\tnodeId = *nodeIdtmp;\n\t\t\tmyEquipNodeId.pinNodeId = *nodeId;\n\t\t\t\/\/printf(\"Variable \ubcc0\uacbd\\n\");\n\t\t\t\/\/* Set the status value *\/\n\t\t\t\/\/\t\t\tUA_Boolean status = false;\n\t\t\t\/\/\t\t\tUA_Variant value;\n\t\t\t\/\/\t\t\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\/\/\t\t\tUA_Server_writeValue(server, *nodeId, value);\n\t\t\t\/\/\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"node id %d value was written\", nodeId->identifier.numeric);\n\t\t}\n\t}\n\n\t*nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n\tif(\tfindNodeIdWithName(server, nodeId, \"Loading Robot\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\tnodeId = *nodeIdtmp;\n\t\tif( findNodeIdWithName(server, nodeId, \"Status\", nodeIdtmp) == UA_STATUSCODE_GOOD){\n\t\t\tnodeId = *nodeIdtmp;\n\t\t\tmyEquipNodeId.robotNodeId = *nodeId;\n\t\t\t\/\/printf(\"Variable \ubcc0\uacbd\\n\");\n\t\t\t\/\/* Set the status value *\/\n\t\t\t\/\/\t\t\tUA_Boolean status = false;\n\t\t\t\/\/\t\t\tUA_Variant value;\n\t\t\t\/\/\t\t\tUA_Variant_setScalar(&amp;value, &amp;status, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\/\/\t\t\tUA_Server_writeValue(server, *nodeId, value);\n\t\t\t\/\/\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"node id %d value was written\", nodeId->identifier.numeric);\n\t\t}\n\t}\n\n\n\t\/\/\uad6c\uc870\uccb4 \ucd9c\ub825.\n\t\/\/printf(\"\ud604\uc7ac \ub178\ub4dc\ub294 %d \\n\", myEquipNodeId.latchNodeId.identifier.numeric);\n\t\/\/printf(\"\ud604\uc7ac \ub178\ub4dc\ub294 %d \\n\", myEquipNodeId.clampNodeId.identifier.numeric);\n\t\/\/printf(\"\ud604\uc7ac \ub178\ub4dc\ub294 %d \\n\", myEquipNodeId.pinNodeId.identifier.numeric);\n\t\/\/printf(\"\ud604\uc7ac \ub178\ub4dc\ub294 %d \\n\", myEquipNodeId.robotNodeId.identifier.numeric);\n\n\t\/\/\ud55c\ubc88\uc5d0 \uc5c5\ub370\uc774\ud2b8\n\tUA_Boolean statusTrue = true;\n\tUA_Boolean statusFalse = false;\n\tUA_Variant value;\n\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\n\t\/\/\ucd08\uae30\uc0c1\ud0dc\n\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"\ubaa8\ub4e0 \ub178\ub4dc\uac00 \ucd08\uae30\ud654(\ubaa8\ub4e0 Value\uac00 0) \ub428.\");\n\n\n\n\t\/\/\uc11c\ubc84 \uad6c\ub3d9.\n\t\/\/\uc8fc\uae30\uc801\uc73c\ub85c \uc5c5\ub370\uc774\ud2b8\ub85c \uc218\uc815\n\t\/\/https:\/\/youtu.be\/abDnBv5u6bU\/\/\n\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"Starting server...every 5 secs\");\n\tUA_StatusCode retval = UA_Server_run_startup(server);\n\n\tif(retval != UA_STATUSCODE_GOOD){\n\t\tUA_Server_delete(server);\n\t\treturn retval;\n\t}\n\n\n\tint timestamp = time(0)+5;\n\tint equipStates = 0;\n\n\twhile(running == true){\n\t\t\/\/ Handle Server\n\t\tUA_Server_run_iterate(server, true);\n\n\t\t\/\/Update Status Variable\n\t\tif(time(0) > timestamp)\n\t\t{\n\t\t\ttimestamp = time(0) + 5;\n\t\t\tswitch(equipStates)\n\t\t\t{\n\t\t\t\tcase 0: \/\/\ucd08\uae30\uc0c1\ud0dc\n\t\t\t\t\tequipStates = 1;\n\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"\ubaa8\ub4e0 \ub178\ub4dc\uac00 \ucd08\uae30\ud654(\ubaa8\ub4e0 Value\uac00 0) \ub428.\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 1: \/\/1\ub2e8\uacc4, latch fwd\n\t\t\t\t\tequipStates = 2;\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusTrue, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"1\ub2e8\uacc4 \ub3d9\uc791 \uc644\ub8cc..latch \uc804\uc9c4\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 2: \/\/2\ub2e8\uacc4, clamp fwd\n\t\t\t\t\tequipStates = 3;\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusTrue, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"2\ub2e8\uacc4 \ub3d9\uc791 \uc644\ub8cc..calmp \uc804\uc9c4(latch, clamp \uc804\uc9c4\uc0c1\ud0dc)\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 3: \/\/3\ub2e8\uacc4, pin fwd\n\t\t\t\t\tequipStates = 4;\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusTrue, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"3\ub2e8\uacc4 \ub3d9\uc791 \uc644\ub8cc..pin \uc804\uc9c4(latch, clamp, pin \uc804\uc9c4\uc0c1\ud0dc)\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 4: \/\/4\ub2e8\uacc4, robot in\n\t\t\t\t\tequipStates = 5;\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusTrue, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"4\ub2e8\uacc4 \ub3d9\uc791 \uc644\ub8cc..robot in (latch, clamp, pin \uc804\uc9c4\uc0c1\ud0dc, robot \uc9c4\uc785)\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 5: \/\/5\ub2e8\uacc4, robot in\n\t\t\t\t\t\/\/\ub2e4\uc2dc \ucd08\uae30\uc0c1\ud0dc\ub85c \uc774\ub3d9\n\t\t\t\t\tequipStates = 0;\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusTrue, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.robotNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.latchNodeId, value);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.clampNodeId, value);\n\n\t\t\t\t\tUA_Variant_setScalar(&amp;value, &amp;statusFalse, &amp;UA_TYPES[UA_TYPES_BOOLEAN]);\n\t\t\t\t\tUA_Server_writeValue(server, myEquipNodeId.pinNodeId, value);\n\n\t\t\t\t\tUA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"5\ub2e8\uacc4 \ub3d9\uc791 \uc644\ub8cc..pin bwd(latch, clamp, \uc804\uc9c4\uc0c1\ud0dc, robot \uc9c4\uc785, pin \ud6c4\uc9c4)\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tequipStates = 0;\n\t\t\t\t\tbreak;\n\n\t\t\t} \/\/switch\n\n\n\t\t}\t\/\/if\n\n\n\t} \/\/while\n\n\tretval = UA_Server_run_shutdown(server);\n\t\/\/UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"Starting server...\");\n\t\/\/UA_StatusCode retval = UA_Server_run(server, &amp;running);\n\t\/\/UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, \"Shutdown server...\");\n\n\tUA_Server_delete(server);\n\treturn retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;\n} \/\/ main<\/pre>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls src=\"https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2020\/09\/OPC_UA_server_small.webm\"><\/video><\/figure>\n\n\n\n<p>\uc774\ub807\uac8c \ud558\ub294\uac8c \ub9de\ub294\uc9c0 \ubaa8\ub974\uaca0\ub2e4. \ub098\uc911\uc5d0 client\uc5d0\uc11c \uc811\uc18d\ud558\uba74 \uc548\ub418\ub294\uac74 \uc544\ub2c8\uaca0\uc9c0. \ub2e4\uc74c \ub2e8\uacc4\ub294 client\uc5d0\uc11c node\ub97c \uc544\ub2c8 \ubc1b\uc544\uc11c mysql\uc5d0 \uc5c5\ub85c\ub4dc\ud558\uba74 \ub41c\ub2e4. \uc774\uc81c \ub77c\uc988\ubca0\ub9ac \ud30c\uc774\ub85c \uc785\ub825 8, \ucd9c\ub825 4\uc810 PLC + OPC UA \uc11c\ubc84\ub97c \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \uc2e0\ub8b0\uc131\uc740 0\uc774\uc5b4\uc11c \uc758\ubbf8 \uc5c6\uaca0\uc9c0\ub9cc.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc784\uc758 \uc124\ube44\uc5d0 latch, clamp, pin, robot\uc744 \uc124\uce58\ud588\ub2e4. \ub300\ubd80\ubd84 \ub798\ub354\ub85c \ub3d9\uc791\ud558\uace0, PLC \uba54\uc774\ucee4\uac00 cpu\uc5d0 opc ua \uc11c\ubc84 \uae30\ub2a5\uc744 \uad6c\ud604\ud558\uc5ec \uc8fc\uae30\uc801\uc73c\ub85c plc [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[12],"tags":[807,808,745,798],"class_list":["post-4063","post","type-post","status-publish","format-standard","hentry","category-12","tag-opcua","tag-open62541","tag-plc","tag-raspberry"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4063","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/comments?post=4063"}],"version-history":[{"count":4,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4063\/revisions"}],"predecessor-version":[{"id":4069,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4063\/revisions\/4069"}],"wp:attachment":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/media?parent=4063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/categories?post=4063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/tags?post=4063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}