ChimeraTK-ControlSystemAdapter-OPCUAAdapter  04.00.01
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 
23 import logging
24 from ua_constants import *
25 import string
26 
27 
28 logger = logging.getLogger(__name__)
29 
30 __unique_item_id = 0
31 
32 defined_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
open62541_MacroHelper.open62541_MacroHelper.getNodeIdDefineString
def getNodeIdDefineString(self, node)
Definition: open62541_MacroHelper.py:67
open62541_MacroHelper.open62541_MacroHelper.__init__
def __init__(self, supressGenerationOfAttribute=[])
Definition: open62541_MacroHelper.py:35
open62541_MacroHelper.open62541_MacroHelper.supressGenerationOfAttribute
supressGenerationOfAttribute
Definition: open62541_MacroHelper.py:36
open62541_MacroHelper.open62541_MacroHelper.getCreateNodeIDMacro
def getCreateNodeIDMacro(self, node)
Definition: open62541_MacroHelper.py:94
open62541_MacroHelper.open62541_MacroHelper.getCreateNodeBootstrap
def getCreateNodeBootstrap(self, node)
Definition: open62541_MacroHelper.py:260
open62541_MacroHelper.open62541_MacroHelper
Definition: open62541_MacroHelper.py:34
str
#define str(a)
Definition: ua_adapter.cpp:52
open62541_MacroHelper.open62541_MacroHelper.getCreateNodeNoBootstrap
def getCreateNodeNoBootstrap(self, node, parentNode, parentReference, unprintedNodes)
Definition: open62541_MacroHelper.py:117
open62541_MacroHelper.open62541_MacroHelper.substitutePunctuationCharacters
def substitutePunctuationCharacters(self, input)
Definition: open62541_MacroHelper.py:52
generate_open62541CCode.id
id
Definition: generate_open62541CCode.py:127
open62541_MacroHelper.open62541_MacroHelper.getCreateStandaloneReference
def getCreateStandaloneReference(self, sourcenode, reference)
Definition: open62541_MacroHelper.py:108
open62541_MacroHelper.open62541_MacroHelper.getCreateExpandedNodeIDMacro
def getCreateExpandedNodeIDMacro(self, node)
Definition: open62541_MacroHelper.py:38