Forráskód Böngészése

structure for JSON encoding

Julius Pfrommer 10 éve
szülő
commit
e3ea519cf5

+ 7 - 2
Makefile.am

@@ -22,18 +22,23 @@ if MULTITHREADING
 AM_LDADD += -lpthread -lurcu-cds -lurcu
 endif
 
+# additional encodings
 UA_ENCODING_AMOUNT = 1
 if UA_ENCODING_XML
-UA_ENCODING_AMOUNT := $$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
+UA_ENCODING_AMOUNT := 2 #$$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
+endif
+
+if UA_ENCODING_JSON
+UA_ENCODING_AMOUNT := 3 #$$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
 endif
 
 AM_CFLAGS += -D UA_ENCODING_AMOUNT=$(UA_ENCODING_AMOUNT)
 
+# export flags for sub-makefiles
 export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 export GLOBAL_AM_LDADD = $(AM_LDADD)
 
 SUBDIRS=src
-
 if HAVE_CHECK
 	SUBDIRS += tests
 endif

+ 8 - 1
configure.ac

@@ -50,22 +50,29 @@ AM_COND_IF([VERBOSE],
 # 100: nano
 # 200: embedded
 # 900: all available features
+# 1500: all including custom extensions to the standard
 AC_ARG_ENABLE(profile,
 AS_HELP_STRING([--enable-profile], [select supported features, default: all]),
 	[case "${enableval}" in
         	nano) profile=100;;
             embedded) profile=200;;
             all) profile=900;;
+			extended) profile=1500;;
             *) AC_MSG_ERROR([bad value ${enableval} for --enable-profile]);; 
 	esac],[profile=900])
 AC_DEFINE([PROFILE], [x"$profile"])
 
 #xml encoding
-AM_CONDITIONAL(UA_ENCODING_XML, test x"$profile" -ge 200)
+AM_CONDITIONAL(UA_ENCODING_XML, test "$profile" -ge 200)
 AM_COND_IF([UA_ENCODING_XML],
     AC_DEFINE([UA_ENCODING_XML], [1])
     AC_CHECK_LIB([expat],[XML_Parse],,AC_MSG_ERROR([Libexpat missing])))
 
+#json encoding
+AM_CONDITIONAL(UA_ENCODING_JSON, test "$profile" -ge 1500)
+AM_COND_IF([UA_ENCODING_JSON],
+    AC_DEFINE([UA_ENCODING_JSON], [2])) # if JSON without xml should allowed, the index needs to be computed dynamically
+
 #multithreading
 AC_ARG_ENABLE(multithreading,
 AS_HELP_STRING([--enable-multithreading],

+ 18 - 15
src/Makefile.am

@@ -1,17 +1,15 @@
 AM_CFLAGS = $(GLOBAL_AM_CFLAGS) -I$(top_builddir)/src -I. -I$(top_builddir)/src/util
 TOOL_DIR = $(top_builddir)/tools
 SCHEMA_DIR = $(top_builddir)/schema
+STRUCTURE_GENERATE_OPTIONS =
 lib_LTLIBRARIES = libopen62541.la
 lib_LTLIBRARIES: generate_types generate_namespace_0
 libopen62541_la_LDFLAGS = -avoid-version -no-undefined
 libopen62541_la_SOURCES = ua_types.c \
-						  ua_namespace_0.c \
 						  ua_types_encoding_binary.c \
 						  ua_types_generated.c \
-						  util/ua_util.c \
-						  util/ua_list.c \
-						  util/ua_indexedList.c \
-						  util/ua_base64.c \
+						  ua_application.c \
+						  ua_namespace_0.c \
 						  ua_transport.c \
 						  ua_transport_binary.c \
 						  ua_transport_binary_secure.c \
@@ -21,9 +19,12 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_services_securechannel.c \
 						  ua_services_nodemanagement.c \
 						  ua_services_view.c \
-						  ua_services_subscription.c\
-						  ua_services_monitoreditems.c\
-						  ua_application.c
+						  ua_services_subscription.c \
+						  ua_services_monitoreditems.c \
+						  util/ua_util.c \
+						  util/ua_list.c \
+						  util/ua_indexedList.c \
+						  util/ua_base64.c
 
 if MULTITHREADING
 libopen62541_la_SOURCES += ua_namespace_concurrent.c
@@ -31,22 +32,24 @@ else
 libopen62541_la_SOURCES += ua_namespace.c
 endif
 
-WITH_XML =
 if UA_ENCODING_XML
-libopen62541_la_SOURCES += ua_types_encoding_xml.c \
-						   ua_namespace_xml.c \
-						   ua_xml.c
-WITH_XML = --with-xml
+libopen62541_la_SOURCES += ua_types_encoding_xml.c ua_namespace_xml.c ua_xml.c
+STRUCTURE_GENERATE_OPTIONS += --with-xml
+endif
+
+if UA_ENCODING_JSON
+libopen62541_la_SOURCES += ua_types_encoding_json.c
+STRUCTURE_GENERATE_OPTIONS += --with-json
 endif
 
 ua_types.c: ua_namespace_0.h
 ua_namespace_0.h: ua_types_generated.h
 
 ua_types_generated.c ua_types_generated.h: $(SCHEMA_DIR)/Opc.Ua.Types.bsd $(TOOL_DIR)/generate_builtin.py
-	python $(TOOL_DIR)/generate_builtin.py $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated $(WITH_XML)
+	python $(TOOL_DIR)/generate_builtin.py $(STRUCTURE_GENERATE_OPTIONS) $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated
 
 ua_namespace_0.c ua_namespace_0.h: $(SCHEMA_DIR)/NodeIds.csv $(TOOL_DIR)/generate_namespace.py
-	python $(TOOL_DIR)/generate_namespace.py $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0 $(WITH_XML)
+	python $(TOOL_DIR)/generate_namespace.py $(STRUCTURE_GENERATE_OPTIONS) $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0
 
 .PHONY: convenience-link clean-convenience-link
 

+ 4 - 0
src/ua_types_encoding_json.c

@@ -0,0 +1,4 @@
+#include "ua_types_encoding_json.h"
+
+// TODO: Implement encoding of the builtin types (in ua_types.h). Then add JSON
+// encoding to the structure generation in tools/generate_builtin.py

+ 73 - 0
src/ua_types_encoding_json.h

@@ -0,0 +1,73 @@
+#ifndef UA_TYPES_ENCODING_JSON_H_
+#define UA_TYPES_ENCODING_JSON_H_
+
+#include "util/ua_util.h"
+#include "ua_types.h"
+
+/**
+ * @ingroup encoding
+ * @defgroup encoding_json JSON Encoding
+ *
+ * @brief Encoding of UA datatypes in JSON. This extends the IEC 62541 standard
+ * and is only included in the "extended" profile. The extension is intended to
+ * be used with a webserver that transmits JSON over HTTP.
+ *
+ * @{
+ */
+
+#define UA_TYPE_CALCSIZEJSON_AS(TYPE, TYPE_AS)       \
+    UA_Int32 TYPE##_calcSizeJSON(TYPE const *p) {    \
+		return TYPE_AS##_calcSizeJSON((TYPE_AS *)p); \
+	}
+
+#define UA_TYPE_ENCODEJSON_AS(TYPE, TYPE_AS)                                             \
+    UA_Int32 TYPE##_encodeJSON(TYPE const *src, UA_ByteString *dst, UA_UInt32 *offset) { \
+		return TYPE_AS##_encodeJSON((TYPE_AS *)src, dst, offset);                        \
+	}
+
+#define UA_TYPE_DECODEJSON_AS(TYPE, TYPE_AS)                                             \
+    UA_Int32 TYPE##_decodeJSON(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst) { \
+		return TYPE_AS##_decodeJSON(src, offset, (TYPE_AS *)dst);                        \
+	}
+#define UA_TYPE_JSON_ENCODING_AS(TYPE, TYPE_AS) \
+    UA_TYPE_CALCSIZEJSON_AS(TYPE, TYPE_AS)      \
+    UA_TYPE_ENCODEJSON_AS(TYPE, TYPE_AS)        \
+    UA_TYPE_DECODEJSON_AS(TYPE, TYPE_AS)
+
+#define UA_TYPE_JSON_ENCODING(TYPE)                                                     \
+    UA_Int32 TYPE##_calcSizeJSON(TYPE const *p);                                        \
+    UA_Int32 TYPE##_encodeJSON(TYPE const *src, UA_ByteString *dst, UA_UInt32 *offset); \
+    UA_Int32 TYPE##_decodeJSON(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst);
+
+UA_TYPE_JSON_ENCODING(UA_Boolean)
+UA_TYPE_JSON_ENCODING(UA_SByte)
+UA_TYPE_JSON_ENCODING(UA_Byte)
+UA_TYPE_JSON_ENCODING(UA_Int16)
+UA_TYPE_JSON_ENCODING(UA_UInt16)
+UA_TYPE_JSON_ENCODING(UA_Int32)
+UA_TYPE_JSON_ENCODING(UA_UInt32)
+UA_TYPE_JSON_ENCODING(UA_Int64)
+UA_TYPE_JSON_ENCODING(UA_UInt64)
+UA_TYPE_JSON_ENCODING(UA_Float)
+UA_TYPE_JSON_ENCODING(UA_Double)
+UA_TYPE_JSON_ENCODING(UA_String)
+UA_TYPE_JSON_ENCODING(UA_DateTime)
+UA_TYPE_JSON_ENCODING(UA_Guid)
+UA_TYPE_JSON_ENCODING(UA_ByteString)
+UA_TYPE_JSON_ENCODING(UA_XmlElement)
+UA_TYPE_JSON_ENCODING(UA_NodeId)
+UA_TYPE_JSON_ENCODING(UA_ExpandedNodeId)
+UA_TYPE_JSON_ENCODING(UA_StatusCode)
+UA_TYPE_JSON_ENCODING(UA_QualifiedName)
+UA_TYPE_JSON_ENCODING(UA_LocalizedText)
+UA_TYPE_JSON_ENCODING(UA_ExtensionObject)
+UA_TYPE_JSON_ENCODING(UA_DataValue)
+UA_TYPE_JSON_ENCODING(UA_Variant)
+UA_TYPE_JSON_ENCODING(UA_DiagnosticInfo)
+
+/* Not built-in types */
+UA_TYPE_JSON_ENCODING(UA_InvalidType)
+
+/// @} /* end of group */
+
+#endif /* UA_TYPES_ENCODING_JSON_H_ */

+ 2 - 3
src/ua_xml.c

@@ -67,7 +67,7 @@ UA_Int32 UA_NodeSetAliases_println(cstring label, UA_NodeSetAliases *p) {
 }
 
 UA_Int32 UA_NodeSet_init(UA_NodeSet *p, UA_UInt32 nsid) {
-	Namespace_new(&(p->ns), 100, nsid);
+	Namespace_new(&(p->ns), nsid);
 	p->aliases.size    = -1;
 	p->aliases.aliases = UA_NULL;
 	return UA_SUCCESS;
@@ -848,9 +848,8 @@ UA_Int32 UA_NodeSet_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_NodeSet
 		} else {
 			UA_Node* node = (UA_Node*) attr;
 			DBG(printf("UA_NodeSet_decodeXML - finished node: node=%p\n", (void* )node));
-			Namespace_insert(dst->ns, node);
+			Namespace_insert(dst->ns, &node, 0);
 			DBG(printf("UA_NodeSet_decodeXml - Inserting "));
-			DBG(print_node(node));
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
 	}

+ 6 - 5
tools/generate_builtin.py

@@ -10,10 +10,11 @@ import inspect
 import argparse
 
 parser = argparse.ArgumentParser()
-parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
-parser.add_argument('outfile', help='outfile w/o extension')
 parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+parser.add_argument('--with-json', action='store_true', help='generate json encoding')
 parser.add_argument('--only-nano', action='store_true', help='generate only the types for the nano profile')
+parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
+parser.add_argument('outfile', help='outfile w/o extension')
 args = parser.parse_args()
         
 ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
@@ -279,8 +280,8 @@ printh('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
 
-#ifndef ''' + sys.argv[2].upper() + '''_H_
-#define ''' + sys.argv[2].upper() + '''_H_
+#ifndef ''' + args.outfile.upper() + '''_H_
+#define ''' + args.outfile.upper() + '''_H_
 
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
@@ -296,7 +297,7 @@ printc('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
  
-#include "''' + sys.argv[2] + '.h"\n')
+#include "''' + args.outfile + '.h"\n')
 #include "ua_types_encoding_binary.h"
 #include "util/ua_util.h"
 

+ 2 - 1
tools/generate_namespace.py

@@ -8,9 +8,10 @@ import re
 import argparse
 
 parser = argparse.ArgumentParser()
+parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+parser.add_argument('--with-json', action='store_true', help='generate json encoding')
 parser.add_argument('nodeids', help='path/to/NodeIds.csv')
 parser.add_argument('outfile', help='outfile w/o extension')
-parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
 args = parser.parse_args()
 
 # types that are to be excluded