ChimeraTK-ControlSystemAdapter-OPCUAAdapter 04.00.05
Loading...
Searching...
No Matches
open62541_MacroHelper.py
Go to the documentation of this file.
1#!/usr/bin/env/python
2# -*- coding: utf-8 -*-
3
4# This Source Code Form is subject to the terms of the Mozilla Public
5# License, v. 2.0. If a copy of the MPL was not distributed with this
6# file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8
22
23import logging
24from ua_constants import *
25import string
26
27
28logger = logging.getLogger(__name__)
29
30__unique_item_id = 0
31
32defined_typealiases = []
33
35 def __init__(self, supressGenerationOfAttribute=[]):
36 self.supressGenerationOfAttribute = supressGenerationOfAttribute
37
39 if node.id().i != None:
40 return "UA_EXPANDEDNODEID_NUMERIC(" + str(node.id().ns) + ", " + str(node.id().i) + ")"
41 elif node.id().s != None:
42 return "UA_EXPANDEDNODEID_STRING(" + str(node.id().ns) + ", " + node.id().s + ")"
43 elif node.id().b != None:
44 logger.debug("NodeID Generation macro for bytestrings has not been implemented.")
45 return ""
46 elif node.id().g != None:
47 logger.debug("NodeID Generation macro for guids has not been implemented.")
48 return ""
49 else:
50 return ""
51
53 ''' substitutePunctuationCharacters
54
55 Replace punctuation characters in input. Part of this class because it is used by
56 ua_namespace on occasion.
57
58 returns: C-printable string representation of input
59 '''
60 # No punctuation characters <>!$
61 for illegal_char in list(string.punctuation):
62 if illegal_char == '_': # underscore is allowed
63 continue
64 input = input.replace(illegal_char, "_") # map to underscore
65 return input
66
67 def getNodeIdDefineString(self, node):
68 code = []
69 extrNs = node.browseName().split(":")
70 symbolic_name = ""
71 # strip all characters that would be illegal in C-Code
72 if len(extrNs) > 1:
73 nodename = extrNs[1]
74 else:
75 nodename = extrNs[0]
76
77 symbolic_name = self.substitutePunctuationCharacters(nodename)
78 if symbolic_name != nodename :
79 logger.warn("Subsituted characters in browsename for nodeid " + str(node.id().i) + " while generating C-Code ")
80
81 if symbolic_name in defined_typealiases:
82 logger.warn(self, "Typealias definition of " + str(node.id().i) + " is non unique!")
83 extendedN = 1
84 while (symbolic_name+"_"+str(extendedN) in defined_typealiases):
85 logger.warn("Typealias definition of " + str(node.id().i) + " is non unique!")
86 extendedN+=1
87 symbolic_name = symbolic_name+"_"+str(extendedN)
88
89 defined_typealiases.append(symbolic_name)
90
91 code.append("#define UA_NS" + str(node.id().ns) + "ID_" + symbolic_name.upper() + " " + str(node.id().i))
92 return code
93
94 def getCreateNodeIDMacro(self, node):
95 if node.id().i != None:
96 return "UA_NODEID_NUMERIC(" + str(node.id().ns) + ", " + str(node.id().i) + ")"
97 elif node.id().s != None:
98 return "UA_NODEID_STRING(" + str(node.id().ns) + ", " + node.id().s + ")"
99 elif node.id().b != None:
100 logger.debug("NodeID Generation macro for bytestrings has not been implemented.")
101 return ""
102 elif node.id().g != None:
103 logger.debug("NodeID Generation macro for guids has not been implemented.")
104 return ""
105 else:
106 return ""
107
108 def getCreateStandaloneReference(self, sourcenode, reference):
109 code = []
110
111 if reference.isForward():
112 code.append("UA_Server_addReference(server, " + self.getCreateNodeIDMacro(sourcenode) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", " + self.getCreateExpandedNodeIDMacro(reference.target()) + ", true);")
113 else:
114 code.append("UA_Server_addReference(server, " + self.getCreateNodeIDMacro(sourcenode) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", " + self.getCreateExpandedNodeIDMacro(reference.target()) + ", false);")
115 return code
116
117 def getCreateNodeNoBootstrap(self, node, parentNode, parentReference, unprintedNodes):
118 code = []
119 code.append("// Node: " + str(node) + ", " + str(node.browseName()))
120
121 if node.nodeClass() == NODE_CLASS_OBJECT:
122 nodetype = "Object"
123 elif node.nodeClass() == NODE_CLASS_VARIABLE:
124 nodetype = "Variable"
125 elif node.nodeClass() == NODE_CLASS_METHOD:
126 nodetype = "Method"
127 elif node.nodeClass() == NODE_CLASS_OBJECTTYPE:
128 nodetype = "ObjectType"
129 elif node.nodeClass() == NODE_CLASS_REFERENCETYPE:
130 nodetype = "ReferenceType"
131 elif node.nodeClass() == NODE_CLASS_VARIABLETYPE:
132 nodetype = "VariableType"
133 elif node.nodeClass() == NODE_CLASS_DATATYPE:
134 nodetype = "DataType"
135 elif node.nodeClass() == NODE_CLASS_VIEW:
136 nodetype = "View"
137 else:
138 code.append("/* undefined nodeclass */")
139 return code;
140
141 # If this is a method, construct in/outargs for addMethod
142 #inputArguments.arrayDimensionsSize = 0;
143 #inputArguments.arrayDimensions = NULL;
144 #inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
145
146 # Node ordering should have made sure that arguments, if they exist, have not been printed yet
147 if node.nodeClass() == NODE_CLASS_METHOD:
148 inArgVal = []
149 outArgVal = []
150 code.append("UA_Argument *inputArguments = NULL;")
151 code.append("UA_Argument *outputArguments = NULL;")
152 for r in node.getReferences():
153 if r.isForward():
154 if r.target() != None and r.target().nodeClass() == NODE_CLASS_VARIABLE and r.target().browseName() == 'InputArguments':
155 while r.target() in unprintedNodes:
156 unprintedNodes.remove(r.target())
157 if r.target().value() != None:
158 inArgVal = r.target().value().value
159 elif r.target() != None and r.target().nodeClass() == NODE_CLASS_VARIABLE and r.target().browseName() == 'OutputArguments':
160 while r.target() in unprintedNodes:
161 unprintedNodes.remove(r.target())
162 if r.target().value() != None:
163 outArgVal = r.target().value().value
164 if len(inArgVal)>0:
165 code.append("")
166 code.append("inputArguments = (UA_Argument *) malloc(sizeof(UA_Argument) * " + str(len(inArgVal)) + ");")
167 code.append("int inputArgumentCnt;")
168 code.append("for (inputArgumentCnt=0; inputArgumentCnt<" + str(len(inArgVal)) + "; ++inputArgumentCnt) UA_Argument_init(&inputArguments[inputArgumentCnt]); ")
169 argumentCnt = 0
170 for inArg in inArgVal:
171 if inArg.getValueFieldByAlias("Description") != None:
172 code.append("inputArguments[" + str(argumentCnt) + "].description = UA_LOCALIZEDTEXT(\"" + str(inArg.getValueFieldByAlias("Description")[0]) + "\",\"" + str(inArg.getValueFieldByAlias("Description")[1]) + "\");")
173 if inArg.getValueFieldByAlias("Name") != None:
174 code.append("inputArguments[" + str(argumentCnt) + "].name = UA_STRING(\"" + str(inArg.getValueFieldByAlias("Name")) + "\");")
175 if inArg.getValueFieldByAlias("ValueRank") != None:
176 code.append("inputArguments[" + str(argumentCnt) + "].valueRank = " + str(inArg.getValueFieldByAlias("ValueRank")) + ";")
177 if inArg.getValueFieldByAlias("DataType") != None:
178 code.append("inputArguments[" + str(argumentCnt) + "].dataType = " + str(self.getCreateNodeIDMacro(inArg.getValueFieldByAlias("DataType"))) + ";")
179 #if inArg.getValueFieldByAlias("ArrayDimensions") != None:
180 # code.append("inputArguments[" + str(argumentCnt) + "].arrayDimensions = " + str(inArg.getValueFieldByAlias("ArrayDimensions")) + ";")
181 argumentCnt += 1
182 if len(outArgVal)>0:
183 code.append("")
184 code.append("outputArguments = (UA_Argument *) malloc(sizeof(UA_Argument) * " + str(len(outArgVal)) + ");")
185 code.append("int outputArgumentCnt;")
186 code.append("for (outputArgumentCnt=0; outputArgumentCnt<" + str(len(outArgVal)) + "; ++outputArgumentCnt) UA_Argument_init(&outputArguments[outputArgumentCnt]); ")
187 argumentCnt = 0
188 for outArg in outArgVal:
189 if outArg.getValueFieldByAlias("Description") != None:
190 code.append("outputArguments[" + str(argumentCnt) + "].description = UA_LOCALIZEDTEXT(\"" + str(outArg.getValueFieldByAlias("Description")[0]) + "\",\"" + str(outArg.getValueFieldByAlias("Description")[1]) + "\");")
191 if outArg.getValueFieldByAlias("Name") != None:
192 code.append("outputArguments[" + str(argumentCnt) + "].name = UA_STRING(\"" + str(outArg.getValueFieldByAlias("Name")) + "\");")
193 if outArg.getValueFieldByAlias("ValueRank") != None:
194 code.append("outputArguments[" + str(argumentCnt) + "].valueRank = " + str(outArg.getValueFieldByAlias("ValueRank")) + ";")
195 if outArg.getValueFieldByAlias("DataType") != None:
196 code.append("outputArguments[" + str(argumentCnt) + "].dataType = " + str(self.getCreateNodeIDMacro(outArg.getValueFieldByAlias("DataType"))) + ";")
197 #if outArg.getValueFieldByAlias("ArrayDimensions") != None:
198 # code.append("outputArguments[" + str(argumentCnt) + "].arrayDimensions = " + str(outArg.getValueFieldByAlias("ArrayDimensions")) + ";")
199 argumentCnt += 1
200
201 # print the attributes struct
202 code.append("UA_%sAttributes attr;" % nodetype)
203 code.append("UA_%sAttributes_init(&attr);" % nodetype);
204 code.append("attr.displayName = UA_LOCALIZEDTEXT(\"\", \"" + str(node.displayName()) + "\");")
205 code.append("attr.description = UA_LOCALIZEDTEXT(\"\", \"" + str(node.description()) + "\");")
206
207 if nodetype == "Variable":
208 code.append("attr.accessLevel = %s;" % str(node.accessLevel()))
209 code.append("attr.userAccessLevel = %s;" % str(node.userAccessLevel()))
210 if nodetype in ["Variable", "VariableType"]:
211 code.append("attr.valueRank = %s;" % str(node.valueRank()))
212
213 if nodetype in ["Variable", "VariableType"]:
214 code = code + node.printOpen62541CCode_SubtypeEarly(bootstrapping = False)
215 elif nodetype == "Method":
216 if node.executable():
217 code.append("attr.executable = true;")
218 if node.userExecutable():
219 code.append("attr.userExecutable = true;")
220
221 code.append("UA_NodeId nodeId = " + str(self.getCreateNodeIDMacro(node)) + ";")
222 if nodetype in ["Object", "Variable", "VariableType"]:
223 typeDefinition = None
224 for r in node.getReferences():
225 if r.isForward() and r.referenceType().id().ns == 0 and r.referenceType().id().i == 40:
226 typeDefinition = r.target()
227 if typeDefinition == None:
228 # FIXME: We might want to resort to BaseXYTTypes here?
229 code.append("UA_NodeId typeDefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);")
230 else:
231 code.append("UA_NodeId typeDefinition = " + str(self.getCreateNodeIDMacro(typeDefinition)) + ";")
232 code.append("UA_NodeId parentNodeId = " + str(self.getCreateNodeIDMacro(parentNode)) + ";")
233 code.append("UA_NodeId parentReferenceNodeId = " + str(self.getCreateNodeIDMacro(parentReference.referenceType())) + ";")
234 extrNs = node.browseName().split(":")
235 if len(extrNs) > 1:
236 code.append("UA_QualifiedName nodeName = UA_QUALIFIEDNAME(" + str(extrNs[0]) + ", \"" + extrNs[1] + "\");")
237 else:
238 code.append("UA_QualifiedName nodeName = UA_QUALIFIEDNAME(0, \"" + str(node.browseName()) + "\");")
239
240 # In case of a MethodNode: Add in|outArg struct generation here. Mandates that namespace reordering was done using
241 # Djikstra (check that arguments have not been printed). (@ichrispa)
242 code.append("UA_Server_add%sNode(server, nodeId, parentNodeId, parentReferenceNodeId, nodeName" % nodetype)
243
244 if nodetype in ["Object", "Variable", "VariableType"]:
245 code.append(" , typeDefinition")
246 if nodetype != "Method":
247 code.append(" , attr, NULL, NULL);")
248 else:
249 code.append(" , attr, (UA_MethodCallback) NULL, NULL, " + str(len(inArgVal)) + ", inputArguments, " + str(len(outArgVal)) + ", outputArguments, NULL);")
250
251 #Adding a Node with typeDefinition = UA_NODEID_NULL will create a HasTypeDefinition reference to BaseDataType - remove it since
252 #a real Reference will be add in a later step (a single HasTypeDefinition reference is assumed here)
253 #The current API does not let us specify IDs of Object's subelements.
254 if nodetype is "Object":
255 code.append("UA_Server_deleteReference(server, nodeId, UA_NODEID_NUMERIC(0, 40), true, UA_EXPANDEDNODEID_NUMERIC(0, 58), true); //remove HasTypeDefinition refs generated by addObjectNode");
256 if nodetype is "Variable":
257 code.append("UA_Server_deleteReference(server, nodeId, UA_NODEID_NUMERIC(0, 40), true, UA_EXPANDEDNODEID_NUMERIC(0, 62), true); //remove HasTypeDefinition refs generated by addVariableNode");
258 return code
259
260 def getCreateNodeBootstrap(self, node):
261 nodetype = ""
262 code = []
263
264 code.append("// Node: " + str(node) + ", " + str(node.browseName()))
265
266 if node.nodeClass() == NODE_CLASS_OBJECT:
267 nodetype = "Object"
268 elif node.nodeClass() == NODE_CLASS_VARIABLE:
269 nodetype = "Variable"
270 elif node.nodeClass() == NODE_CLASS_METHOD:
271 nodetype = "Method"
272 elif node.nodeClass() == NODE_CLASS_OBJECTTYPE:
273 nodetype = "ObjectType"
274 elif node.nodeClass() == NODE_CLASS_REFERENCETYPE:
275 nodetype = "ReferenceType"
276 elif node.nodeClass() == NODE_CLASS_VARIABLETYPE:
277 nodetype = "VariableType"
278 elif node.nodeClass() == NODE_CLASS_DATATYPE:
279 nodetype = "DataType"
280 elif node.nodeClass() == NODE_CLASS_VIEW:
281 nodetype = "View"
282 else:
283 code.append("/* undefined nodeclass */")
284 return;
285
286 code.append("UA_" + nodetype + "Node *" + node.getCodePrintableID() + " = UA_NodeStore_new" + nodetype + "Node();")
287 if not "browsename" in self.supressGenerationOfAttribute:
288 extrNs = node.browseName().split(":")
289 if len(extrNs) > 1:
290 code.append(node.getCodePrintableID() + "->browseName = UA_QUALIFIEDNAME_ALLOC(" + str(extrNs[0]) + ", \"" + extrNs[1] + "\");")
291 else:
292 code.append(node.getCodePrintableID() + "->browseName = UA_QUALIFIEDNAME_ALLOC(0, \"" + node.browseName() + "\");")
293 if not "displayname" in self.supressGenerationOfAttribute:
294 code.append(node.getCodePrintableID() + "->displayName = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + node.displayName() + "\");")
295 if not "description" in self.supressGenerationOfAttribute:
296 code.append(node.getCodePrintableID() + "->description = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + node.description() + "\");")
297
298 if not "writemask" in self.supressGenerationOfAttribute:
299 if node.__node_writeMask__ != 0:
300 code.append(node.getCodePrintableID() + "->writeMask = (UA_Int32) " + str(node.__node_writeMask__) + ";")
301 if not "userwritemask" in self.supressGenerationOfAttribute:
302 if node.__node_userWriteMask__ != 0:
303 code.append(node.getCodePrintableID() + "->userWriteMask = (UA_Int32) " + str(node.__node_userWriteMask__) + ";")
304 if not "nodeid" in self.supressGenerationOfAttribute:
305 if node.id().ns != 0:
306 code.append(node.getCodePrintableID() + "->nodeId.namespaceIndex = " + str(node.id().ns) + ";")
307 if node.id().i != None:
308 code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = " + str(node.id().i) + ";")
309 elif node.id().b != None:
310 code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_BYTESTRING;")
311 logger.error("ByteString IDs for nodes has not been implemented yet.")
312 return []
313 elif node.id().g != None:
314 #<jpfr> the string is sth like { .length = 111, .data = <ptr> }
315 #<jpfr> there you _may_ alloc the <ptr> on the heap
316 #<jpfr> for the guid, just set it to {.data1 = 111, .data2 = 2222, ....
317 code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_GUID;")
318 logger.error(self, "GUIDs for nodes has not been implemented yet.")
319 return []
320 elif node.id().s != None:
321 code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_STRING;")
322 code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = UA_STRING_ALLOC(\"" + str(node.id().i) + "\");")
323 else:
324 logger.error("Node ID is not numeric, bytestring, guid or string. I do not know how to create c code for that...")
325 return []
326
327 return code
__init__(self, supressGenerationOfAttribute=[])
getCreateStandaloneReference(self, sourcenode, reference)
getCreateNodeNoBootstrap(self, node, parentNode, parentReference, unprintedNodes)
#define str(a)