1919__status__ = "Developement"
2020
2121import sys
22+ import array
23+ import base64
2224
25+ try :
26+ import urllib .parse as quote
27+ except ImportError :
28+ import urllib as quote
2329
2430class EntityAttribute ():
2531 """ Here the actual Conversion to the correct JSON-Format happens
@@ -30,59 +36,72 @@ class EntityAttribute():
3036 """
3137 python_version = sys .version_info
3238
33- def __init__ (self , _object , ipmd , concreteDataType = None ):
39+ def __init__ (self , _object , ipmd , concreteDataType = None , baseEntity = False ):
3440 self .value = _object
3541 self .type = ""
3642 self .metadata = dict ()
43+ if baseEntity :
44+ self .setConcreteMetaData (concreteDataType )
3745 objectType = type (_object )
3846
39-
4047 # Simply if-then-else to the Json fromat
4148 if (objectType is type (None )):
4249 pass
4350 elif objectType is bool :
4451 self .type = "boolean"
4552 self .value = bool (_object )
53+ # self.setConcreteMetaData(concreteDataType)
4654 elif objectType is int :
4755 self .type = "number"
4856 self .value = int (_object )
4957 self .setPythonMetaData (ipmd , "int" )
58+ # self.setConcreteMetaData(concreteDataType)
5059 elif objectType is float :
5160 self .type = "number"
5261 self .value = float (_object )
5362 self .setPythonMetaData (ipmd , "float" )
63+ # self.setConcreteMetaData(concreteDataType)
5464 elif self .python_version < (3 ,0 ) and objectType is long : # Check explicitly if Python 2 is used
5565 self .type = "number"
5666 self .value = long (_object )
5767 self .setPythonMetaData (ipmd , "long" )
68+ # self.setConcreteMetaData(concreteDataType)
5869 elif objectType is complex :
5970 self .type = "array"
6071 t = complex (_object )
6172 self .value = [EntityAttribute (t .real , ipmd ), EntityAttribute (t .imag , ipmd )]
6273 self .setPythonMetaData (ipmd , "complex" )
74+ # self.setConcreteMetaData(concreteDataType)
6375 elif objectType is str :
6476 self .type = "string"
6577 self .value = str (_object )
78+ # self.setConcreteMetaData(concreteDataType)
6679 elif self .python_version < (3 ,0 ) and objectType is unicode : # Check explicitly if Python 2 is used
6780 self .type = "string"
6881 self .value = unicode (_object )
82+ # self.setConcreteMetaData(concreteDataType)
6983 self .setPythonMetaData (ipmd , "unicode" )
7084 elif objectType is tuple :
7185 self .type = "array"
7286 self .value = []
7387 self .setPythonMetaData (ipmd , "tuple" )
88+ self .setConcreteMetaData (concreteDataType )
7489 for item in _object :
7590 self .value .append (EntityAttribute (item , ipmd ))
7691 elif objectType is list :
7792 self .type = "array"
7893 self .value = []
94+ self .setConcreteMetaData (concreteDataType )
7995 for item in _object :
8096 self .value .append (EntityAttribute (item , ipmd ))
8197 elif objectType is dict :
8298 self .type = "object"
8399 tempDict = {}
84100 for key , value in _object .items ():
85- tempDict [key ] = EntityAttribute (value ,ipmd )
101+ innerConcreteMetaData = None
102+ if concreteDataType is not None and key in concreteDataType :
103+ innerConcreteMetaData = concreteDataType [key ]
104+ tempDict [key ] = EntityAttribute (value , ipmd , innerConcreteMetaData )
86105 self .value = tempDict
87106 else :
88107 # Case it is a Class
@@ -94,22 +113,54 @@ def __init__(self, _object, ipmd, concreteDataType=None):
94113 else :
95114 raise ValueError ("Cannot get attrs from {}" .format (str (_object )))
96115
97- if hasattr (_object , '_type' ): # ROS-Specific Type-Declaration
116+ if hasattr (_object , '_type' ) and hasattr (_object , '_slot_types' ) and hasattr (_object , '__slots__' ): # ROS-Specific Type-Declaration
117+ ### This is a special Class from ROS!
98118 self .type = _object ._type .replace ("/" , "." ) # Needs to be replaced Fiware does not allow a '/'
99- else :
100- self .type = _object .__class__ .__name__
101- self .setPythonMetaData (ipmd , "class" )
102- tempDict = {}
103- for key in iterL :
104- if key .startswith ('_' ):
105- continue
106- tempDict [key ] = EntityAttribute (getattr (_object , key ), ipmd )
107- self .value = tempDict
119+ self .setPythonMetaData (ipmd , "class" )
120+ # Special Case 'Image-like'-Data in ROS (very long 'int8[]'- and 'uint8[]' - arrays)
121+ # These are converted into Base64 (escaped)
122+ tempDict = {}
123+ for key , key_type in zip (_object .__slots__ , _object ._slot_types ):
124+ if key .startswith ('_' ):
125+ continue
126+ if (key_type == 'int8[]' or key_type == 'uint8[]' ) and len (getattr (_object , key )) >= 256 :
127+ # TODO DL 256 -> Threshold?
128+ # Generate Base64 String of the Array:
129+ tempDict [key ] = EntityAttribute (None , ipmd )
130+ tempDict [key ].type = "base64"
108131
132+ # Either generate unsigned or signed byte-array
133+ if key_type == 'int8[]' :
134+ tempDict [key ].value = array .array ('b' , getattr (_object , key )).tostring ()
135+ else :
136+ tempDict [key ].value = array .array ('B' , getattr (_object , key )).tostring ()
137+
138+ # Form that Byte-Array: generate Base64 String
139+ tempDict [key ].value = base64 .b64encode (tempDict [key ].value )
109140
110- if concreteDataType is not None :
111- self .metadata ["dataType" ] = dict (type = "dataType" , value = concreteDataType )
112- pass
141+ # Escape Special Characters:
142+ tempDict [key ].value = quote .quote (tempDict [key ].value )
143+ tempDict [key ].metadata = dict ()
144+ self .setConcreteMetaData (concreteDataType [key ], tempDict [key ])
145+ else :
146+ innerConcreteMetaData = None
147+ if concreteDataType is not None and key in concreteDataType :
148+ innerConcreteMetaData = concreteDataType [key ]
149+ tempDict [key ] = EntityAttribute (getattr (_object , key ), ipmd , innerConcreteMetaData )
150+ self .value = tempDict
151+ else :
152+ # Simple Class. Recursively retrieve the other values
153+ self .type = _object .__class__ .__name__
154+ self .setPythonMetaData (ipmd , "class" )
155+ tempDict = {}
156+ for key in iterL :
157+ if key .startswith ('_' ):
158+ continue
159+ innerConcreteMetaData = None
160+ if concreteDataType is not None and key in concreteDataType :
161+ innerConcreteMetaData = concreteDataType [key ]
162+ tempDict [key ] = EntityAttribute (getattr (_object , key ), ipmd , innerConcreteMetaData )
163+ self .value = tempDict
113164
114165 # Remove metadata-Attribute if it is empty (minimizing the JSON)
115166 if self .metadata == {} :
@@ -118,4 +169,9 @@ def __init__(self, _object, ipmd, concreteDataType=None):
118169 def setPythonMetaData (self , ignorePythonMetaData , val ):
119170 if not ignorePythonMetaData :
120171 self .metadata ["python" ] = dict (type = "dataType" , value = val )
121-
172+
173+ def setConcreteMetaData (self , val , obj = None ):
174+ if val is not None and obj is None :
175+ self .metadata ["dataType" ] = dict (type = "dataType" , value = val )
176+ elif val is not None :
177+ obj .metadata ["dataType" ] = dict (type = "dataType" , value = val )
0 commit comments