Rename to slixmpp
[slixmpp.git] / slixmpp / plugins / xep_0325 / stanza / control.py
blobd3d6a2571864458dd35167ea3eafbf9cc3f88dec
1 """
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.
9 """
11 from slixmpp import Iq, Message
12 from slixmpp.xmlstream import register_stanza_plugin, ElementBase, ET, JID
13 from re import match
15 class Control(ElementBase):
16 """ Placeholder for the namespace, not used as a stanza """
17 namespace = 'urn:xmpp:iot:control'
18 name = 'control'
19 plugin_attrib = name
20 interfaces = set(tuple())
22 class ControlSet(ElementBase):
23 namespace = 'urn:xmpp:iot:control'
24 name = 'set'
25 plugin_attrib = name
26 interfaces = set(['nodes','datas'])
28 def __init__(self, xml=None, parent=None):
29 ElementBase.__init__(self, xml, parent);
30 self._nodes = set()
31 self._datas = set()
33 def setup(self, xml=None):
34 """
35 Populate the stanza object using an optional XML object.
37 Overrides ElementBase.setup
39 Caches item information.
41 Arguments:
42 xml -- Use an existing XML object for the stanza's values.
43 """
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):
49 """
50 Add a new node element. Each item is required to have a
51 nodeId, but may also specify a sourceId value and cacheType.
53 Arguments:
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
57 """
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)
65 return node
66 return None
68 def del_node(self, nodeId):
69 """
70 Remove a single node.
72 Arguments:
73 nodeId -- Node ID of the item to remove.
74 """
75 if nodeId in self._nodes:
76 nodes = [i for i in self.iterables if isinstance(i, RequestNode)]
77 for node in nodes:
78 if node['nodeId'] == nodeId:
79 self.xml.remove(node.xml)
80 self.iterables.remove(node)
81 return True
82 return False
84 def get_nodes(self):
85 """Return all nodes."""
86 nodes = []
87 for node in self['substanzas']:
88 if isinstance(node, RequestNode):
89 nodes.append(node)
90 return nodes
92 def set_nodes(self, nodes):
93 """
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)
98 Arguments:
99 nodes -- A series of nodes in tuple format.
101 self.del_nodes()
102 for node in nodes:
103 if isinstance(node, RequestNode):
104 self.add_node(node['nodeId'], node['sourceId'], node['cacheType'])
105 else:
106 nodeId, sourceId, cacheType = node
107 self.add_node(nodeId, sourceId, cacheType)
109 def del_nodes(self):
110 """Remove all nodes."""
111 self._nodes = set()
112 nodes = [i for i in self.iterables if isinstance(i, RequestNode)]
113 for node in nodes:
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.
122 Arguments:
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:
130 dataObj = None;
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)
157 return dataObj
158 return None
160 def del_data(self, name):
162 Remove a single data element.
164 Arguments:
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)]
169 for data in datas:
170 if data['name'] == name:
171 self.xml.remove(data.xml)
172 self.iterables.remove(data)
173 return True
174 return False
176 def get_datas(self):
177 """ Return all data elements. """
178 datas = []
179 for data in self['substanzas']:
180 if isinstance(data, BaseParameter):
181 datas.append(data)
182 return datas
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)
189 Arguments:
190 datas -- A series of data elements.
192 self.del_datas()
193 for data in datas:
194 self.add_data(name=data['name'], typename=data._get_typename(), value=data['value'])
196 def del_datas(self):
197 """Remove all data elements."""
198 self._datas = set()
199 datas = [i for i in self.iterables if isinstance(i, BaseParameter)]
200 for data in datas:
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'
208 name = 'node'
209 plugin_attrib = name
210 interfaces = set(['nodeId','sourceId','cacheType'])
213 class ControlSetResponse(ElementBase):
214 namespace = 'urn:xmpp:iot:control'
215 name = 'setResponse'
216 plugin_attrib = name
217 interfaces = set(['responseCode'])
219 def __init__(self, xml=None, parent=None):
220 ElementBase.__init__(self, xml, parent);
221 self._nodes = set()
222 self._datas = set()
224 def setup(self, xml=None):
226 Populate the stanza object using an optional XML object.
228 Overrides ElementBase.setup
230 Caches item information.
232 Arguments:
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.
244 Arguments:
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)
256 return node
257 return None
259 def del_node(self, nodeId):
261 Remove a single node.
263 Arguments:
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)]
268 for node in nodes:
269 if node['nodeId'] == nodeId:
270 self.xml.remove(node.xml)
271 self.iterables.remove(node)
272 return True
273 return False
275 def get_nodes(self):
276 """Return all nodes."""
277 nodes = []
278 for node in self['substanzas']:
279 if isinstance(node, RequestNode):
280 nodes.append(node)
281 return nodes
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)
289 Arguments:
290 nodes -- A series of nodes in tuple format.
292 self.del_nodes()
293 for node in nodes:
294 if isinstance(node, RequestNode):
295 self.add_node(node['nodeId'], node['sourceId'], node['cacheType'])
296 else:
297 nodeId, sourceId, cacheType = node
298 self.add_node(nodeId, sourceId, cacheType)
300 def del_nodes(self):
301 """Remove all nodes."""
302 self._nodes = set()
303 nodes = [i for i in self.iterables if isinstance(i, RequestNode)]
304 for node in nodes:
305 self.xml.remove(node.xml)
306 self.iterables.remove(node)
309 def add_data(self, name):
311 Add a new ResponseParameter element.
313 Arguments:
314 name -- Name of the parameter
316 if name not in self._datas:
317 self._datas.add(name)
318 data = ResponseParameter(parent=self)
319 data['name'] = name;
320 self.iterables.append(data)
321 return data
322 return None
324 def del_data(self, name):
326 Remove a single ResponseParameter element.
328 Arguments:
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)]
333 for data in datas:
334 if data['name'] == name:
335 self.xml.remove(data.xml)
336 self.iterables.remove(data)
337 return True
338 return False
340 def get_datas(self):
341 """ Return all ResponseParameter elements. """
342 datas = set()
343 for data in self['substanzas']:
344 if isinstance(data, ResponseParameter):
345 datas.add(data)
346 return datas
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
353 Arguments:
354 datas -- A series of data element names.
356 self.del_datas()
357 for data in datas:
358 self.add_data(name=data['name'])
360 def del_datas(self):
361 """Remove all ResponseParameter elements."""
362 self._datas = set()
363 datas = [i for i in self.iterables if isinstance(i, ResponseParameter)]
364 for data in datas:
365 self.xml.remove(data.xml)
366 self.iterables.remove(data)
369 class Error(ElementBase):
370 namespace = 'urn:xmpp:iot:control'
371 name = 'error'
372 plugin_attrib = name
373 interfaces = set(['var','text'])
375 def get_text(self):
376 """Return then contents inside the XML tag."""
377 return self.xml.text
379 def set_text(self, value):
380 """Set then contents inside the XML tag.
382 Arguments:
383 value -- string
386 self.xml.text = value;
387 return self
389 def del_text(self):
390 """Remove the contents inside the XML tag."""
391 self.xml.text = ""
392 return self
394 class ResponseParameter(ElementBase):
395 """
396 Parameter element in ControlSetResponse.
397 """
398 namespace = 'urn:xmpp:iot:control'
399 name = 'parameter'
400 plugin_attrib = name
401 interfaces = set(['name']);
404 class BaseParameter(ElementBase):
405 """
406 Parameter element in SetCommand. This is a base class,
407 all instances of parameters added to SetCommand must be of types:
408 BooleanParameter
409 ColorParameter
410 StringParameter
411 DateParameter
412 DateTimeParameter
413 DoubleParameter
414 DurationParameter
415 IntParameter
416 LongParameter
417 TimeParameter
418 """
419 namespace = 'urn:xmpp:iot:control'
420 name = 'baseParameter'
421 plugin_attrib = name
422 interfaces = set(['name','value']);
424 def _get_typename(self):
425 return self.name;
427 class BooleanParameter(BaseParameter):
428 """
429 Field data of type boolean.
430 Note that the value is expressed as a string.
432 name = 'boolean'
433 plugin_attrib = name
435 class ColorParameter(BaseParameter):
436 """
437 Field data of type color.
438 Note that the value is expressed as a string.
440 name = 'color'
441 plugin_attrib = name
443 class StringParameter(BaseParameter):
444 """
445 Field data of type string.
447 name = 'string'
448 plugin_attrib = name
450 class DateParameter(BaseParameter):
451 """
452 Field data of type date.
453 Note that the value is expressed as a string.
455 name = 'date'
456 plugin_attrib = name
458 class DateTimeParameter(BaseParameter):
459 """
460 Field data of type dateTime.
461 Note that the value is expressed as a string.
463 name = 'dateTime'
464 plugin_attrib = name
466 class DoubleParameter(BaseParameter):
467 """
468 Field data of type double.
469 Note that the value is expressed as a string.
471 name = 'double'
472 plugin_attrib = name
474 class DurationParameter(BaseParameter):
475 """
476 Field data of type duration.
477 Note that the value is expressed as a string.
479 name = 'duration'
480 plugin_attrib = name
482 class IntParameter(BaseParameter):
483 """
484 Field data of type int.
485 Note that the value is expressed as a string.
487 name = 'int'
488 plugin_attrib = name
490 class LongParameter(BaseParameter):
491 """
492 Field data of type long (64-bit int).
493 Note that the value is expressed as a string.
495 name = 'long'
496 plugin_attrib = name
498 class TimeParameter(BaseParameter):
499 """
500 Field data of type time.
501 Note that the value is expressed as a string.
503 name = 'time'
504 plugin_attrib = name
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)