Browse Source

added missing files, still wip

Leon Urbas 11 years ago
parent
commit
3faca5574c
4 changed files with 1782 additions and 0 deletions
  1. 235 0
      tool/generate_builtin.py
  2. 43 0
      tool/main.c
  3. 1201 0
      tool/opcua_basictypes.c
  4. 303 0
      tool/opcua_basictypes.h

+ 235 - 0
tool/generate_builtin.py

@@ -0,0 +1,235 @@
+from __future__ import print_function
+import sys
+from collections import OrderedDict
+import re
+from lxml import etree
+
+if len(sys.argv) != 3:
+    print("Usage: python generate_builtin.py <path/to/Opc.Ua.Types.bsd> <outfile w/o extension>", file=sys.stdout)
+    exit(0)
+
+# types that are coded manually
+exclude_types = set(["Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32",
+                    "Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid",
+                    "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "StatusCode", 
+                    "QualifiedName", "LocalizedText", "ExtensionObject", "DataValue",
+                     "Variant", "DiagnosticInfo", "RequestHeader", "ResponseHeader", "NodeIdType"])
+
+elementary_size = dict()
+elementary_size["Boolean"] = 1;
+elementary_size["SByte"] = 1;
+elementary_size["Byte"] = 1;
+elementary_size["Int16"] = 2;
+elementary_size["UInt16"] = 2;
+elementary_size["Int32"] = 4;
+elementary_size["UInt32"] = 4;
+elementary_size["Int64"] = 8;
+elementary_size["UInt64"] = 8;
+elementary_size["Float"] = 4;
+elementary_size["Double"] = 8;
+elementary_size["DateTime"] = 8;
+elementary_size["StatusCode"] = 4;
+
+# indefinite_types = ["NodeId", "ExpandedNodeId", "QualifiedName", "LocalizedText", "ExtensionObject", "DataValue", "Variant", "DiagnosticInfo"]
+indefinite_types = ["ExpandedNodeId", "QualifiedName", "ExtensionObject", "DataValue", "Variant", "DiagnosticInfo"]
+enum_types = []
+                   
+# indefinite types cannot be directly contained in a record as they don't have a definite size
+printed_types = exclude_types # types that were already printed and which we can use in the structures to come
+
+# types we do not want to autogenerate
+def skipType(name):
+    if name in exclude_types:
+        return True
+    if re.search("NodeId$", name) != None:
+        return True
+    return False
+
+def stripTypename(tn):
+    return tn[tn.find(":")+1:]
+
+def camlCase2AdaCase(item):
+    (newitem, n) = re.subn("(?<!^)(?<![A-Z])([A-Z])", "_\\1", item)
+    return newitem
+
+# are the prerequisites in place? if not, postpone.
+def printableStructuredType(element):
+    for child in element:
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
+            typename = stripTypename(child.get("TypeName"))
+            if typename not in printed_types:
+                return False
+    return True
+
+# There three types of types in the bsd file:
+# StructuredType, EnumeratedType OpaqueType
+
+def createEnumerated(element):
+    valuemap = OrderedDict()
+    name = "UA_" + element.get("Name")
+    enum_types.append(name)
+    print("// " + name, end='\n', file=fh)
+    for child in element:
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
+            print("// " + child.text, end='\n', file=fh)
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedValue":
+            valuemap[name + "_" + child.get("Name")] = child.get("Value")
+    valuemap = OrderedDict(sorted(valuemap.iteritems(), key=lambda (k,v): int(v)))
+    print("typedef UA_UInt32 " + name + ";", end='\n', file=fh);
+    print("enum " + name + "_enum { \n" + ",\n\t".join(map(lambda (key, value) : key + " = " + value, valuemap.iteritems())) + "\n};\n", end='\n', file=fh)
+    return
+    
+def createStructured(element):
+    valuemap = OrderedDict()
+    name = "UA_" + element.get("Name")
+    print("// " + name, end='\n', file=fh)
+
+    lengthfields = set()
+    for child in element:
+        if child.get("LengthField"):
+            lengthfields.add(child.get("LengthField"))
+    
+    for child in element:
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
+            print("// " + child.text, end='\n', file=fh)
+        elif child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
+            if child.get("Name") in lengthfields:
+                continue
+            childname = camlCase2AdaCase(child.get("Name"))
+            if childname in printed_types:
+                childname = childname + "_Value" # attributes may not have the name of a type
+            typename = stripTypename(child.get("TypeName"))
+            if childname == "Response_Header" or childname == "Request_Header":
+                continue
+            if typename in indefinite_types:
+                valuemap[childname] = typename + "*"
+            elif child.get("LengthField"):
+                valuemap[childname] = typename + "**"
+            else:
+                valuemap[childname] = typename
+
+    # if "Response" in name[len(name)-9:]:
+    #    print("type " + name + " is new Response_Base with "),
+    # elif "Request" in name[len(name)-9:]:
+    #    print ("type " + name + " is new Request_Base with "),
+    # else:
+    #    print ("type " + name + " is new UA_Builtin with "),
+    print("typedef struct T_" + name + " {", end='\n', file=fh)
+    if len(valuemap) > 0:
+        for n,t in valuemap.iteritems():
+            if t.find("**") != -1:
+	        print("\t" + "UInt32 " + n + "_size;", end='\n', file=fh)
+            print("\t" + "UA_" + t + " " + n + ";", end='\n', file=fh)
+    else:
+        print("// null record", end='\n', file=fh)
+    print("} " + name + ";", end='\n', file=fh)
+
+    print("Int32 " + name + "_calcSize(" + name + " const * ptr);", end='\n', file=fh)
+    print("Int32 " + name + "_encode(" + name + " const * src, Int32* pos, char* dst);", end='\n', file=fh)
+    print("Int32 " + name + "_decode(char const * src, UInt32* pos, " + name + "* dst);", end='\n', file=fh)
+
+    if "Response" in name[len(name)-9:]:
+        print("Int32 "  + name + "_calcSize(" + name + " const * ptr) {\n\treturn UA_ResponseHeader_getSize()", end='', file=fc) 
+    elif "Request" in name[len(name)-9:]:
+        print("Int32 "  + name + "_calcSize(" + name + " const * ptr) {\n\treturn UA_RequestHeader_getSize()", end='', file=fc) 
+    else:
+	# code 
+        print("Int32 "  + name + "_calcSize(" + name + " const * ptr) {\n\treturn 0", end='', file=fc)
+
+    # code _calcSize
+    for n,t in valuemap.iteritems():
+        if t in elementary_size:
+            print('\n\t + sizeof(UA_' + t + ") // " + n, end='', file=fc)
+        else:
+            if t in enum_types:
+                print('\n\t + 4 //' + n, end='', file=fc) # enums are all 32 bit
+            elif t.find("**") != -1:
+		print("\n\t + 4 //" + n + "_size", end='', file=fc),
+		print("\n\t + UA_Array_calcSize(ptr->" + n + "_size, UA_" + t[0:t.find("*")].upper() + ", (void**) ptr->" + n +")", end='', file=fc)
+            elif t.find("*") != -1:
+                print('\n\t + ' + "UA_" + t[0:t.find("*")] + "_calcSize(ptr->" + n + ')', end='', file=fc)
+            else:
+                print('\n\t + ' + "UA_" + t + "_calcSize(&(ptr->" + n + '))', end='', file=fc)
+
+    print("\n\t;\n};\n", end='\n', file=fc)
+
+    print("Int32 "+name+"_encode("+name+" const * src, Int32* pos, char* dst) {\n\tInt32 retval=0;", end='\n', file=fc)
+    # code _encode
+    for n,t in valuemap.iteritems():
+        if t in elementary_size:
+            print('\tretval |= UA_'+t+'_encode(&(src->'+n+'),pos,dst);', end='\n', file=fc)
+        else:
+            if t in enum_types:
+                print('\tretval |= UA_'+t+'_encode(&(src->'+n+'));', end='\n', file=fc)
+            elif t.find("**") != -1:
+                print('\tretval |= UA_Int32_encode(&(src->'+n+'_size)); // encode size', end='\n', file=fc)
+		print("\tretval |= UA_Array_encode((void**) (src->"+n+"),src->"+n+"_size, UA_" + t[0:t.find("*")].upper()+",pos,dst);", end='\n', file=fc)
+            elif t.find("*") != -1:
+                print('\tretval |= UA_' + t[0:t.find("*")] + "_encode(src->" + n + ',pos,dst);', end='\n', file=fc)
+            else:
+                print('\tretval |= UA_'+t+"_encode(&(src->"+n+"),pos,dst);", end='\n', file=fc)
+    print("\treturn retval;\n};\n", end='\n', file=fc)
+        
+def createOpaque(element):
+    name = "UA_" + element.get("Name")
+    print("// " + name , end='\n', file=fh)
+    for child in element:
+        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
+            print("// " + child.text, end='\n', file=fh)
+
+    print("typedef void* " + name + ";\n", end='\n', file=fh)
+    return
+
+ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
+tree = etree.parse(sys.argv[1])
+types = tree.xpath("/opc:TypeDictionary/*[not(self::opc:Import)]", namespaces=ns)
+
+fh = open(sys.argv[2] + ".h",'w');
+fc = open(sys.argv[2] + ".c",'w');
+print('#include "' + sys.argv[2] + '.h"', end='\n', file=fc);
+
+# types for which we create a vector type
+arraytypes = set()
+fields = tree.xpath("//opc:Field", namespaces=ns)
+for field in fields:
+    if field.get("LengthField"):
+        arraytypes.add(stripTypename(field.get("TypeName")))
+
+deferred_types = OrderedDict()
+
+print('#ifndef OPCUA_H_', end='\n', file=fh)
+print('#define OPCUA_H_', end='\n', file=fh)
+print('#include "opcua_basictypes.h"', end='\n', file=fh)
+print('#include "opcua_namespace_0.h"', end='\n', file=fh);
+
+for element in types:
+    name = element.get("Name")
+    if skipType(name):
+        continue
+        
+    if element.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedType":
+        createEnumerated(element)
+        printed_types.add(name)
+    elif element.tag == "{http://opcfoundation.org/BinarySchema/}StructuredType":
+        if printableStructuredType(element):
+            createStructured(element)
+            printed_types.add(name)
+        else: # the record contains types that were not yet detailed
+            deferred_types[name] = element
+            continue
+    elif element.tag == "{http://opcfoundation.org/BinarySchema/}OpaqueType":
+        createOpaque(element)
+        printed_types.add(name)
+
+    #if name in arraytypes:
+    #    print "package ListOf" + name + " is new Types.Arrays.UA_Builtin_Arrays(" + name + ");\n"
+
+for name, element in deferred_types.iteritems():
+    createStructured(element)
+    # if name in arraytypes:
+    #    print "package ListOf" + name + " is new Types.Arrays.UA_Builtin_Arrays(" + name + ");\n"
+
+print('#endif /* OPCUA_H_ */', end='\n', file=fh)
+fh.close()
+fc.close()
+

+ 43 - 0
tool/main.c

@@ -0,0 +1,43 @@
+/*
+ * main.c
+ *
+ *  Created on: 07.03.2014
+ *      Author: mrt
+ */
+#include <stdio.h>
+
+#include "opcua.h"
+
+#define UA_NO_ERROR ((Int32) 0)
+
+Int32 decodeInt32(char const * buf, Int32* pos, Int32* dst) {
+	Int32 t1 = (Int32) (((SByte) (buf[*pos]) & 0xFF));
+	Int32 t2 = (Int32) (((SByte) (buf[*pos + 1]) & 0xFF) << 8);
+	Int32 t3 = (Int32) (((SByte) (buf[*pos + 2]) & 0xFF) << 16);
+	Int32 t4 = (Int32) (((SByte) (buf[*pos + 3]) & 0xFF) << 24);
+	*pos += sizeof(Int32);
+	*dst = t1 + t2 + t3 + t4;
+	return UA_NO_ERROR;
+}
+
+typedef union Integer {
+	Int32 i;
+	SByte b[4];
+} Integer;
+
+int main() {
+	Integer a = { UA_IdType_Guid };
+	Integer b;
+	int pos = 0;
+
+	a.i = 0;
+	a.b[3] = 1;
+
+	printf("%d, {%d,%d,%d,%d}\n", a.i, a.b[0], a.b[1], a.b[2], a.b[3]);
+
+	decodeInt32((char *) &a.b[0], &pos, &(b.i));
+	printf("%d, {%d,%d,%d,%d}\n", b.i, b.b[0], b.b[1], b.b[2], b.b[3]);
+
+	return 0;
+}
+

File diff suppressed because it is too large
+ 1201 - 0
tool/opcua_basictypes.c


+ 303 - 0
tool/opcua_basictypes.h

@@ -0,0 +1,303 @@
+/*
+ * opcua_basictypes.h
+ *
+ *  Created on: 13.03.2014
+ *      Author: mrt
+ */
+
+#ifndef OPCUA_BASICTYPES_H_
+#define OPCUA_BASICTYPES_H_
+
+#include <stdint.h>
+
+typedef uint8_t Byte;
+typedef int8_t SByte;
+typedef int16_t Int16;
+typedef int32_t Int32;
+typedef uint16_t UInt16;
+typedef uint32_t UInt32;
+
+typedef _Bool UA_Boolean;
+typedef int8_t UA_SByte;
+typedef uint8_t UA_Byte;
+typedef int16_t UA_Int16;
+typedef uint16_t UA_UInt16;
+typedef int32_t UA_Int32;
+typedef uint32_t UA_UInt32;
+typedef int64_t UA_Int64;
+typedef uint64_t UA_UInt64;
+typedef float UA_Float;
+typedef double UA_Double;
+
+#define UA_SUCCESS 0
+#define UA_TRUE (42==42)
+#define UA_FALSE (!UA_TRUE)
+
+Int32 UA_Boolean_calcSize(UA_Boolean const * ptr);
+Int32 UA_Boolean_encode(UA_Boolean const * src, Int32* pos, char * dst);
+Int32 UA_Boolean_decode(char const * src, Int32* pos, UA_Boolean * dst);
+
+/**
+* StatusCodeBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.11
+* Page: 20
+*/
+typedef UA_Int32 UA_StatusCode;
+enum UA_StatusCode_enum
+{
+	// Some Values are called the same as previous Enumerations so we need
+	//names that are unique
+	SC_Good 			= 			0x00
+};
+UInt32 UA_StatusCode_calcSize(UA_StatusCode const * ptr);
+
+/**
+* VariantBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.16
+* Page: 22
+*/
+typedef struct _UA_Variant {
+	Byte EncodingMask; //Type of Enum UA_VariantTypeEncodingMaskType
+	UA_Int32 size;
+	void** data;
+} UA_Variant;
+UInt32 UA_Variant_calcSize(UA_Variant const * ptr);
+
+/**
+* String
+* Part: 6
+* Chapter: 5.2.2.4
+* Page: 16
+*/
+typedef struct UA_String
+{
+	UA_Int32 	length;
+	UA_Byte*	data;
+}
+UA_String;
+Int32 UA_String_calcSize(UA_String const * ptr);
+
+/*
+* ByteString
+* Part: 6
+* Chapter: 5.2.2.7
+* Page: 17
+*/
+typedef struct UA_ByteString
+{
+	UA_Int32 	length;
+	UA_Byte*	data;
+}
+UA_ByteString;
+Int32 UA_ByteString_calcSize(UA_ByteString const * ptr);
+
+/**
+* LocalizedTextBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.14
+* Page: 21
+*/
+typedef struct UA_LocalizedText
+{
+	UA_Byte EncodingMask;
+	UA_String Locale;
+	UA_String Text;
+}
+UA_LocalizedText;
+Int32 UA_LocalizedText_calcSize(UA_LocalizedText const * ptr);
+
+
+/* GuidType
+* Part: 6
+* Chapter: 5.2.2.6
+* Page: 17
+*/
+typedef struct UA_Guid
+{
+	UA_UInt32 Data1;
+	UA_UInt16 Data2;
+	UA_UInt16 Data3;
+	UA_ByteString Data4;
+
+}
+UA_Guid;
+Int32 UA_Guid_calcSize(UA_Guid const * ptr);
+
+/**
+* DateTime
+* Part: 6
+* Chapter: 5.2.2.5
+* Page: 16
+*/
+typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
+Int32 UA_DataTime_calcSize(UA_DateTime const * ptr);
+
+
+
+/**
+* XmlElement
+* Part: 6
+* Chapter: 5.2.2.8
+* Page: 17
+*/
+//Überlegung ob man es direkt als ByteString speichert oder als String
+typedef struct UA_XmlElement
+{
+	UA_ByteString Data;
+}
+UA_XmlElement;
+
+
+typedef struct UA_XmlElementEncoded
+{
+	UA_UInt32 Length;
+	UA_Byte StartTag[3];
+	UA_Byte *Message;
+	UA_UInt32 EndTag[4];
+}
+UA_XmlElementEncoded;
+
+
+typedef struct _UA_NodeId
+{
+	UA_Byte   EncodingByte; //enum BID_NodeIdEncodingValuesType
+	UA_UInt16 Namespace;
+
+    union
+    {
+        UA_UInt32 Numeric;
+        UA_String String;
+        UA_Guid Guid;
+        UA_ByteString ByteString;
+    }
+    Identifier;
+} UA_NodeId;
+/**
+ * NodeIds
+* Part: 6
+* Chapter: 5.2.2.9
+* Table 5
+*/
+enum UA_NodeIdEncodingValuesType_enum
+{
+	// Some Values are called the same as previous Enumerations so we need
+	// names that are unique
+	NIEVT_TWO_BYTE = 	0x00,
+	NIEVT_FOUR_BYTE = 	0x01,
+	NIEVT_NUMERIC = 	0x02,
+	NIEVT_STRING = 		0x03,
+	NIEVT_GUID = 		0x04,
+	NIEVT_BYTESTRING = 	0x05,
+	NIEVT_NAMESPACE_URI_FLAG = 	0x80, 	//Is only for ExpandedNodeId required
+	NIEVT_SERVERINDEX_FLAG = 	0x40 	//Is only for ExpandedNodeId required
+};
+
+
+/**
+* ExpandedNodeId
+* Part: 6
+* Chapter: 5.2.2.10
+* Page: 19
+*/
+typedef struct UA_ExpandedNodeId
+{
+	UA_NodeId NodeId;
+	UA_Int32 EncodingByte; //enum BID_NodeIdEncodingValuesType
+	UA_String NamespaceUri;
+	UA_UInt32 ServerIndex;
+}
+UA_ExpandedNodeId;
+
+
+
+/**
+ * NodeIds
+* Part: 6
+* Chapter: 5.2.2.9
+* Page: 17
+*/
+typedef enum UA_IdentifierType
+{
+	// Some Values are called the same as previouse Enumerations so we need
+	//names that are unique
+	IT_NUMERIC = 0,
+	IT_STRING = 1,
+	IT_GUID = 2,
+	IT_OPAQUE = 3
+}
+UA_IdentifierType;
+
+/**
+* ExtensionObjectBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.15
+* Page: 21
+*/
+typedef struct _UA_ExtensionObject {
+	UA_NodeId TypeId;
+	UA_Byte Encoding; //Type of the enum UA_ExtensionObjectEncodingMaskType
+	UA_ByteString Body;
+} UA_ExtensionObject;
+
+/**
+* QualifiedNameBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.13
+* Page: 20
+*/
+typedef struct _UA_QualifiedName {
+	UInt16 NamespaceIndex;
+	UInt16 Reserved;
+	UA_String Name;
+} UA_QualifiedName;
+
+/**
+* DataValueBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.17
+* Page: 23
+*/
+typedef struct UA_DataValue {
+	UA_Byte EncodingMask;
+	UA_Variant Value;
+	UA_StatusCode Status;
+	UA_DateTime SourceTimestamp;
+	UA_Int16 SourcePicoseconds;
+	UA_DateTime ServerTimestamp;
+	UA_Int16 ServerPicoseconds;
+} UA_DataValue;
+
+/**
+* DiagnoticInfoBinaryEncoding
+* Part: 6
+* Chapter: 5.2.2.12
+* Page: 20
+*/
+typedef struct _UA_DiagnosticInfo {
+	Byte EncodingMask; //Type of the Enum UA_DiagnosticInfoEncodingMaskType
+	UA_Int32 SymbolicId;
+	UA_Int32 NamespaceUri;
+	UA_Int32 LocalizedText;
+	UA_Int32 Locale;
+	UA_String AdditionalInfo;
+	UA_StatusCode InnerStatusCode;
+	struct _UA_DiagnosticInfo* InnerDiagnosticInfo;
+} UA_DiagnosticInfo;
+
+enum UA_DiagnosticInfoEncodingMaskType_enum
+{
+	// Some Values are called the same as previous Enumerations so we need
+	//names that are unique
+	DIEMT_SYMBOLIC_ID = 			0x01,
+	DIEMT_NAMESPACE = 				0x02,
+	DIEMT_LOCALIZED_TEXT = 			0x04,
+	DIEMT_LOCALE = 					0x08,
+	DIEMT_ADDITIONAL_INFO = 		0x10,
+	DIEMT_INNER_STATUS_CODE = 		0x20,
+	DIEMT_INNER_DIAGNOSTIC_INFO = 	0x40
+};
+
+Int32 UA_Array_calcSize(Int32 noElements, Int32 type, void const ** ptr);
+#endif /* OPCUA_BASICTYPES_H_ */