2 Slixmpp: The Slick XMPP Library
3 Implementation of xeps for Internet of Things
4 http://wiki.xmpp.org/web/Tech_pages/IoT_systems
5 Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se, bjorn.westrom@consoden.se
6 This file is part of Slixmpp.
8 See the file LICENSE for copying permission.
11 from slixmpp
import Iq
, Message
12 from slixmpp
.xmlstream
import register_stanza_plugin
, ElementBase
, ET
, JID
15 class Control(ElementBase
):
16 """ Placeholder for the namespace, not used as a stanza """
17 namespace
= 'urn:xmpp:iot:control'
20 interfaces
= set(tuple())
22 class ControlSet(ElementBase
):
23 namespace
= 'urn:xmpp:iot:control'
26 interfaces
= set(['nodes','datas'])
28 def __init__(self
, xml
=None, parent
=None):
29 ElementBase
.__init
__(self
, xml
, parent
);
33 def setup(self
, xml
=None):
35 Populate the stanza object using an optional XML object.
37 Overrides ElementBase.setup
39 Caches item information.
42 xml -- Use an existing XML object for the stanza's values.
44 ElementBase
.setup(self
, xml
)
45 self
._nodes
= set([node
['nodeId'] for node
in self
['nodes']])
46 self
._datas
= set([data
['name'] for data
in self
['datas']])
48 def add_node(self
, nodeId
, sourceId
=None, cacheType
=None):
50 Add a new node element. Each item is required to have a
51 nodeId, but may also specify a sourceId value and cacheType.
54 nodeId -- The ID for the node.
55 sourceId -- [optional] identifying the data source controlling the device
56 cacheType -- [optional] narrowing down the search to a specific kind of node
58 if nodeId
not in self
._nodes
:
59 self
._nodes
.add((nodeId
))
60 node
= RequestNode(parent
=self
)
61 node
['nodeId'] = nodeId
62 node
['sourceId'] = sourceId
63 node
['cacheType'] = cacheType
64 self
.iterables
.append(node
)
68 def del_node(self
, nodeId
):
73 nodeId -- Node ID of the item to remove.
75 if nodeId
in self
._nodes
:
76 nodes
= [i
for i
in self
.iterables
if isinstance(i
, RequestNode
)]
78 if node
['nodeId'] == nodeId
:
79 self
.xml
.remove(node
.xml
)
80 self
.iterables
.remove(node
)
85 """Return all nodes."""
87 for node
in self
['substanzas']:
88 if isinstance(node
, RequestNode
):
92 def set_nodes(self
, nodes
):
94 Set or replace all nodes. The given nodes must be in a
95 list or set where each item is a tuple of the form:
96 (nodeId, sourceId, cacheType)
99 nodes -- A series of nodes in tuple format.
103 if isinstance(node
, RequestNode
):
104 self
.add_node(node
['nodeId'], node
['sourceId'], node
['cacheType'])
106 nodeId
, sourceId
, cacheType
= node
107 self
.add_node(nodeId
, sourceId
, cacheType
)
110 """Remove all nodes."""
112 nodes
= [i
for i
in self
.iterables
if isinstance(i
, RequestNode
)]
114 self
.xml
.remove(node
.xml
)
115 self
.iterables
.remove(node
)
118 def add_data(self
, name
, typename
, value
):
120 Add a new data element.
123 name -- The name of the data element
124 typename -- The type of data element
125 (boolean, color, string, date, dateTime,
126 double, duration, int, long, time)
127 value -- The value of the data element
129 if name
not in self
._datas
:
131 if typename
== "boolean":
132 dataObj
= BooleanParameter(parent
=self
);
133 elif typename
== "color":
134 dataObj
= ColorParameter(parent
=self
);
135 elif typename
== "string":
136 dataObj
= StringParameter(parent
=self
);
137 elif typename
== "date":
138 dataObj
= DateParameter(parent
=self
);
139 elif typename
== "dateTime":
140 dataObj
= DateTimeParameter(parent
=self
);
141 elif typename
== "double":
142 dataObj
= DoubleParameter(parent
=self
);
143 elif typename
== "duration":
144 dataObj
= DurationParameter(parent
=self
);
145 elif typename
== "int":
146 dataObj
= IntParameter(parent
=self
);
147 elif typename
== "long":
148 dataObj
= LongParameter(parent
=self
);
149 elif typename
== "time":
150 dataObj
= TimeParameter(parent
=self
);
152 dataObj
['name'] = name
;
153 dataObj
['value'] = value
;
155 self
._datas
.add(name
)
156 self
.iterables
.append(dataObj
)
160 def del_data(self
, name
):
162 Remove a single data element.
165 data_name -- The data element name to remove.
167 if name
in self
._datas
:
168 datas
= [i
for i
in self
.iterables
if isinstance(i
, BaseParameter
)]
170 if data
['name'] == name
:
171 self
.xml
.remove(data
.xml
)
172 self
.iterables
.remove(data
)
177 """ Return all data elements. """
179 for data
in self
['substanzas']:
180 if isinstance(data
, BaseParameter
):
184 def set_datas(self
, datas
):
186 Set or replace all data elements. The given elements must be in a
187 list or set where each item is a data element (numeric, string, boolean, dateTime, timeSpan or enum)
190 datas -- A series of data elements.
194 self
.add_data(name
=data
['name'], typename
=data
._get
_typename
(), value
=data
['value'])
197 """Remove all data elements."""
199 datas
= [i
for i
in self
.iterables
if isinstance(i
, BaseParameter
)]
201 self
.xml
.remove(data
.xml
)
202 self
.iterables
.remove(data
)
205 class RequestNode(ElementBase
):
206 """ Node element in a request """
207 namespace
= 'urn:xmpp:iot:control'
210 interfaces
= set(['nodeId','sourceId','cacheType'])
213 class ControlSetResponse(ElementBase
):
214 namespace
= 'urn:xmpp:iot:control'
217 interfaces
= set(['responseCode'])
219 def __init__(self
, xml
=None, parent
=None):
220 ElementBase
.__init
__(self
, xml
, parent
);
224 def setup(self
, xml
=None):
226 Populate the stanza object using an optional XML object.
228 Overrides ElementBase.setup
230 Caches item information.
233 xml -- Use an existing XML object for the stanza's values.
235 ElementBase
.setup(self
, xml
)
236 self
._nodes
= set([node
['nodeId'] for node
in self
['nodes']])
237 self
._datas
= set([data
['name'] for data
in self
['datas']])
239 def add_node(self
, nodeId
, sourceId
=None, cacheType
=None):
241 Add a new node element. Each item is required to have a
242 nodeId, but may also specify a sourceId value and cacheType.
245 nodeId -- The ID for the node.
246 sourceId -- [optional] identifying the data source controlling the device
247 cacheType -- [optional] narrowing down the search to a specific kind of node
249 if nodeId
not in self
._nodes
:
250 self
._nodes
.add(nodeId
)
251 node
= RequestNode(parent
=self
)
252 node
['nodeId'] = nodeId
253 node
['sourceId'] = sourceId
254 node
['cacheType'] = cacheType
255 self
.iterables
.append(node
)
259 def del_node(self
, nodeId
):
261 Remove a single node.
264 nodeId -- Node ID of the item to remove.
266 if nodeId
in self
._nodes
:
267 nodes
= [i
for i
in self
.iterables
if isinstance(i
, RequestNode
)]
269 if node
['nodeId'] == nodeId
:
270 self
.xml
.remove(node
.xml
)
271 self
.iterables
.remove(node
)
276 """Return all nodes."""
278 for node
in self
['substanzas']:
279 if isinstance(node
, RequestNode
):
283 def set_nodes(self
, nodes
):
285 Set or replace all nodes. The given nodes must be in a
286 list or set where each item is a tuple of the form:
287 (nodeId, sourceId, cacheType)
290 nodes -- A series of nodes in tuple format.
294 if isinstance(node
, RequestNode
):
295 self
.add_node(node
['nodeId'], node
['sourceId'], node
['cacheType'])
297 nodeId
, sourceId
, cacheType
= node
298 self
.add_node(nodeId
, sourceId
, cacheType
)
301 """Remove all nodes."""
303 nodes
= [i
for i
in self
.iterables
if isinstance(i
, RequestNode
)]
305 self
.xml
.remove(node
.xml
)
306 self
.iterables
.remove(node
)
309 def add_data(self
, name
):
311 Add a new ResponseParameter element.
314 name -- Name of the parameter
316 if name
not in self
._datas
:
317 self
._datas
.add(name
)
318 data
= ResponseParameter(parent
=self
)
320 self
.iterables
.append(data
)
324 def del_data(self
, name
):
326 Remove a single ResponseParameter element.
329 name -- The data element name to remove.
331 if name
in self
._datas
:
332 datas
= [i
for i
in self
.iterables
if isinstance(i
, ResponseParameter
)]
334 if data
['name'] == name
:
335 self
.xml
.remove(data
.xml
)
336 self
.iterables
.remove(data
)
341 """ Return all ResponseParameter elements. """
343 for data
in self
['substanzas']:
344 if isinstance(data
, ResponseParameter
):
348 def set_datas(self
, datas
):
350 Set or replace all data elements. The given elements must be in a
351 list or set of ResponseParameter elements
354 datas -- A series of data element names.
358 self
.add_data(name
=data
['name'])
361 """Remove all ResponseParameter elements."""
363 datas
= [i
for i
in self
.iterables
if isinstance(i
, ResponseParameter
)]
365 self
.xml
.remove(data
.xml
)
366 self
.iterables
.remove(data
)
369 class Error(ElementBase
):
370 namespace
= 'urn:xmpp:iot:control'
373 interfaces
= set(['var','text'])
376 """Return then contents inside the XML tag."""
379 def set_text(self
, value
):
380 """Set then contents inside the XML tag.
386 self
.xml
.text
= value
;
390 """Remove the contents inside the XML tag."""
394 class ResponseParameter(ElementBase
):
396 Parameter element in ControlSetResponse.
398 namespace
= 'urn:xmpp:iot:control'
401 interfaces
= set(['name']);
404 class BaseParameter(ElementBase
):
406 Parameter element in SetCommand. This is a base class,
407 all instances of parameters added to SetCommand must be of types:
419 namespace
= 'urn:xmpp:iot:control'
420 name
= 'baseParameter'
422 interfaces
= set(['name','value']);
424 def _get_typename(self
):
427 class BooleanParameter(BaseParameter
):
429 Field data of type boolean.
430 Note that the value is expressed as a string.
435 class ColorParameter(BaseParameter
):
437 Field data of type color.
438 Note that the value is expressed as a string.
443 class StringParameter(BaseParameter
):
445 Field data of type string.
450 class DateParameter(BaseParameter
):
452 Field data of type date.
453 Note that the value is expressed as a string.
458 class DateTimeParameter(BaseParameter
):
460 Field data of type dateTime.
461 Note that the value is expressed as a string.
466 class DoubleParameter(BaseParameter
):
468 Field data of type double.
469 Note that the value is expressed as a string.
474 class DurationParameter(BaseParameter
):
476 Field data of type duration.
477 Note that the value is expressed as a string.
482 class IntParameter(BaseParameter
):
484 Field data of type int.
485 Note that the value is expressed as a string.
490 class LongParameter(BaseParameter
):
492 Field data of type long (64-bit int).
493 Note that the value is expressed as a string.
498 class TimeParameter(BaseParameter
):
500 Field data of type time.
501 Note that the value is expressed as a string.
506 register_stanza_plugin(Iq
, ControlSet
)
507 register_stanza_plugin(Message
, ControlSet
)
509 register_stanza_plugin(ControlSet
, RequestNode
, iterable
=True)
511 register_stanza_plugin(ControlSet
, BooleanParameter
, iterable
=True)
512 register_stanza_plugin(ControlSet
, ColorParameter
, iterable
=True)
513 register_stanza_plugin(ControlSet
, StringParameter
, iterable
=True)
514 register_stanza_plugin(ControlSet
, DateParameter
, iterable
=True)
515 register_stanza_plugin(ControlSet
, DateTimeParameter
, iterable
=True)
516 register_stanza_plugin(ControlSet
, DoubleParameter
, iterable
=True)
517 register_stanza_plugin(ControlSet
, DurationParameter
, iterable
=True)
518 register_stanza_plugin(ControlSet
, IntParameter
, iterable
=True)
519 register_stanza_plugin(ControlSet
, LongParameter
, iterable
=True)
520 register_stanza_plugin(ControlSet
, TimeParameter
, iterable
=True)
522 register_stanza_plugin(Iq
, ControlSetResponse
)
523 register_stanza_plugin(ControlSetResponse
, Error
)
524 register_stanza_plugin(ControlSetResponse
, RequestNode
, iterable
=True)
525 register_stanza_plugin(ControlSetResponse
, ResponseParameter
, iterable
=True)