Make connect(), abort() and reconnect() work
[slixmpp.git] / tests / test_stream_xep_0323.py
blob3f54d861f310df47afdfba408fe5b1337458a783
1 # -*- coding: utf-8 -*-
3 import sys
4 import datetime
5 import time
6 import threading
8 from slixmpp.test import *
9 from slixmpp.xmlstream import ElementBase
10 from slixmpp.plugins.xep_0323.device import Device
13 class TestStreamSensorData(SlixTest):
15 """
16 Test using the XEP-0323 plugin.
17 """
18 def setUp(self):
19 pass
21 def _time_now(self):
22 return datetime.datetime.now().replace(microsecond=0).isoformat();
24 def tearDown(self):
25 self.stream_close()
27 def testRequestAccept(self):
28 self.stream_start(mode='component',
29 plugins=['xep_0030',
30 'xep_0323'])
32 myDevice = Device("Device22");
33 myDevice._add_field(name="Temperature", typename="numeric", unit="°C");
34 myDevice._set_momentary_timestamp("2013-03-07T16:24:30")
35 myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"});
37 self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5);
39 self.recv("""
40 <iq type='get'
41 from='master@clayster.com/amr'
42 to='device@clayster.com'
43 id='1'>
44 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'/>
45 </iq>
46 """)
48 self.send("""
49 <iq type='result'
50 from='device@clayster.com'
51 to='master@clayster.com/amr'
52 id='1'>
53 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
54 </iq>
55 """)
57 self.send("""
58 <message from='device@clayster.com'
59 to='master@clayster.com/amr'>
60 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'>
61 <node nodeId='Device22'>
62 <timestamp value='2013-03-07T16:24:30'>
63 <numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
64 </timestamp>
65 </node>
66 </fields>
67 </message>
68 """)
70 def testRequestRejectAuth(self):
72 self.stream_start(mode='component',
73 plugins=['xep_0030',
74 'xep_0323'])
76 self.xmpp['xep_0323']._set_authenticated("darth@deathstar.com");
78 self.recv("""
79 <iq type='get'
80 from='master@clayster.com/amr'
81 to='device@clayster.com'
82 id='4'>
83 <req xmlns='urn:xmpp:iot:sensordata' seqnr='5' momentary='true'/>
84 </iq>
85 """)
87 self.send("""
88 <iq type='error'
89 from='device@clayster.com'
90 to='master@clayster.com/amr'
91 id='4'>
92 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='5'>
93 <error>Access denied</error>
94 </rejected>
95 </iq>
96 """)
98 def testRequestNode(self):
100 self.stream_start(mode='component',
101 plugins=['xep_0030',
102 'xep_0323'])
104 myDevice = Device("Device44");
105 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
107 print("."),
109 self.recv("""
110 <iq type='get'
111 from='master@clayster.com/amr'
112 to='device@clayster.com'
113 id='77'>
114 <req xmlns='urn:xmpp:iot:sensordata' seqnr='66' momentary='true'>
115 <node nodeId='Device33'/>
116 </req>
117 </iq>
118 """)
120 self.send("""
121 <iq type='error'
122 from='device@clayster.com'
123 to='master@clayster.com/amr'
124 id='77'>
125 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='66'>
126 <error>Invalid nodeId Device33</error>
127 </rejected>
128 </iq>
129 """)
131 print("."),
133 self.recv("""
134 <iq type='get'
135 from='master@clayster.com/amr'
136 to='device@clayster.com'
137 id='8'>
138 <req xmlns='urn:xmpp:iot:sensordata' seqnr='7' momentary='true'>
139 <node nodeId='Device44'/>
140 </req>
141 </iq>
142 """)
144 self.send("""
145 <iq type='result'
146 from='device@clayster.com'
147 to='master@clayster.com/amr'
148 id='8'>
149 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/>
150 </iq>
151 """)
154 def testRequestField(self):
156 self.stream_start(mode='component',
157 plugins=['xep_0030',
158 'xep_0323'])
160 myDevice = Device("Device44");
161 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
162 myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
164 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
166 print("."),
168 self.recv("""
169 <iq type='get'
170 from='master@clayster.com/amr'
171 to='device@clayster.com'
172 id='7'>
173 <req xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
174 <field name='Current'/>
175 </req>
176 </iq>
177 """)
179 self.send("""
180 <iq type='error'
181 from='device@clayster.com'
182 to='master@clayster.com/amr'
183 id='7'>
184 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
185 <error>Invalid field Current</error>
186 </rejected>
187 </iq>
188 """)
190 print("."),
192 self.recv("""
193 <iq type='get'
194 from='master@clayster.com/amr'
195 to='device@clayster.com'
196 id='8'>
197 <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
198 <field name='Voltage'/>
199 </req>
200 </iq>
201 """)
203 self.send("""
204 <iq type='result'
205 from='device@clayster.com'
206 to='master@clayster.com/amr'
207 id='8'>
208 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/>
209 </iq>
210 """)
212 self.send("""
213 <message from='device@clayster.com'
214 to='master@clayster.com/amr'>
215 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
216 <node nodeId='Device44'>
217 <timestamp value='2000-01-01T00:01:02'>
218 <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/>
219 </timestamp>
220 </node>
221 </fields>
222 </message>
223 """)
225 self.send("""
226 <message from='device@clayster.com'
227 to='master@clayster.com/amr'>
228 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'>
229 </fields>
230 </message>
231 """)
233 def testRequestMultiTimestampSingleField(self):
235 self.stream_start(mode='component',
236 plugins=['xep_0030',
237 'xep_0323'])
239 myDevice = Device("Device44");
240 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
241 myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
242 myDevice._add_field(name='Current', typename="numeric", unit="A");
243 myDevice._add_field(name='Height', typename="string");
244 myDevice._add_field_timestamp_data(name="Voltage", value="230.6", timestamp="2000-01-01T01:01:02");
245 myDevice._add_field_timestamp_data(name="Height", value="115 m", timestamp="2000-01-01T01:01:02", flags={"invoiced": "true"});
247 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
249 print("."),
251 self.recv("""
252 <iq type='get'
253 from='master@clayster.com/amr'
254 to='device@clayster.com'
255 id='8'>
256 <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
257 <field name='Voltage'/>
258 </req>
259 </iq>
260 """)
262 self.send("""
263 <iq type='result'
264 from='device@clayster.com'
265 to='master@clayster.com/amr'
266 id='8'>
267 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/>
268 </iq>
269 """)
271 self.send("""
272 <message from='device@clayster.com'
273 to='master@clayster.com/amr'>
274 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
275 <node nodeId='Device44'>
276 <timestamp value='2000-01-01T00:01:02'>
277 <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/>
278 </timestamp>
279 </node>
280 </fields>
281 </message>
282 """)
284 self.send("""
285 <message from='device@clayster.com'
286 to='master@clayster.com/amr'>
287 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
288 <node nodeId='Device44'>
289 <timestamp value='2000-01-01T01:01:02'>
290 <numeric name='Voltage' value='230.6' unit='V'/>
291 </timestamp>
292 </node>
293 </fields>
294 </message>
295 """)
297 self.send("""
298 <message from='device@clayster.com'
299 to='master@clayster.com/amr'>
300 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'>
301 </fields>
302 </message>
303 """)
305 def testRequestMultiTimestampAllFields(self):
307 self.stream_start(mode='component',
308 plugins=['xep_0030',
309 'xep_0323'])
311 myDevice = Device("Device44");
312 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
313 myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
314 myDevice._add_field(name='Current', typename="numeric", unit="A");
315 myDevice._add_field(name='Height', typename="string");
316 myDevice._add_field_timestamp_data(name="Voltage", value="230.6", timestamp="2000-01-01T01:01:02");
317 myDevice._add_field_timestamp_data(name="Height", value="115 m", timestamp="2000-01-01T01:01:02", flags={"invoiced": "true"});
319 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
321 print("."),
323 self.recv("""
324 <iq type='get'
325 from='master@clayster.com/amr'
326 to='device@clayster.com'
327 id='8'>
328 <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'/>
329 </iq>
330 """)
332 self.send("""
333 <iq type='result'
334 from='device@clayster.com'
335 to='master@clayster.com/amr'
336 id='8'>
337 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/>
338 </iq>
339 """)
341 self.send("""
342 <message from='device@clayster.com'
343 to='master@clayster.com/amr'>
344 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
345 <node nodeId='Device44'>
346 <timestamp value='2000-01-01T00:01:02'>
347 <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/>
348 </timestamp>
349 </node>
350 </fields>
351 </message>
352 """)
354 self.send("""
355 <message from='device@clayster.com'
356 to='master@clayster.com/amr'>
357 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'>
358 <node nodeId='Device44'>
359 <timestamp value='2000-01-01T01:01:02'>
360 <numeric name='Voltage' value='230.6' unit='V'/>
361 <string name='Height' invoiced='true' value='115 m'/>
362 </timestamp>
363 </node>
364 </fields>
365 </message>
366 """)
368 self.send("""
369 <message from='device@clayster.com'
370 to='master@clayster.com/amr'>
371 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'>
372 </fields>
373 </message>
374 """)
376 def testRequestAPI(self):
378 self.stream_start(mode='client',
379 plugins=['xep_0030',
380 'xep_0323'])
382 self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", callback=None);
384 self.send("""
385 <iq type='get'
386 from='tester@localhost'
387 to='you@google.com'
388 id='1'>
389 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
390 </iq>
391 """)
393 self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=None);
395 self.send("""
396 <iq type='get'
397 from='tester@localhost'
398 to='you@google.com'
399 id='2'>
400 <req xmlns='urn:xmpp:iot:sensordata' seqnr='2'>
401 <node nodeId="Device33"/>
402 <node nodeId="Device22"/>
403 </req>
404 </iq>
405 """)
407 self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", fields=['Temperature', 'Voltage'], callback=None);
409 self.send("""
410 <iq type='get'
411 from='tester@localhost'
412 to='you@google.com'
413 id='3'>
414 <req xmlns='urn:xmpp:iot:sensordata' seqnr='3'>
415 <field name="Temperature"/>
416 <field name="Voltage"/>
417 </req>
418 </iq>
419 """)
421 def testRequestRejectAPI(self):
423 self.stream_start(mode='client',
424 plugins=['xep_0030',
425 'xep_0323'])
427 results = [];
429 def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None):
430 if (result == "rejected") and (error_msg == "Invalid device Device22"):
431 results.append("rejected");
433 self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=my_callback);
435 self.send("""
436 <iq type='get'
437 from='tester@localhost'
438 to='you@google.com'
439 id='1'>
440 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
441 <node nodeId="Device33"/>
442 <node nodeId="Device22"/>
443 </req>
444 </iq>
445 """)
447 self.recv("""
448 <iq type='error'
449 from='you@google.com'
450 to='tester@localhost'
451 id='1'>
452 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
453 <error>Invalid device Device22</error>
454 </rejected>
455 </iq>
456 """)
458 time.sleep(.1)
460 self.failUnless(results == ["rejected"],
461 "Rejected callback was not properly executed");
463 def testRequestAcceptedAPI(self):
465 self.stream_start(mode='client',
466 plugins=['xep_0030',
467 'xep_0323'])
469 results = [];
471 def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None):
472 results.append(result);
474 self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=my_callback);
476 self.send("""
477 <iq type='get'
478 from='tester@localhost'
479 to='you@google.com'
480 id='1'>
481 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
482 <node nodeId="Device33"/>
483 <node nodeId="Device22"/>
484 </req>
485 </iq>
486 """)
488 self.recv("""
489 <iq type='result'
490 from='you@google.com'
491 to='tester@localhost'
492 id='1'>
493 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
494 </iq>
495 """)
497 time.sleep(.1)
499 self.failUnless(results == ["accepted"],
500 "Accepted callback was not properly executed");
502 def testRequestFieldsAPI(self):
504 self.stream_start(mode='client',
505 plugins=['xep_0030',
506 'xep_0323'])
508 results = [];
509 callback_data = {};
511 def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None):
512 results.append(result);
513 if result == "fields":
514 callback_data["nodeId"] = nodeId;
515 callback_data["timestamp"] = timestamp;
516 callback_data["error_msg"] = error_msg;
517 for f in fields:
518 callback_data["field_" + f['name']] = f;
520 t1= threading.Thread(name="request_data",
521 target=self.xmpp['xep_0323'].request_data,
522 kwargs={"from_jid": "tester@localhost",
523 "to_jid": "you@google.com",
524 "nodeIds": ['Device33'],
525 "callback": my_callback});
526 t1.start();
527 #self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback);
529 self.send("""
530 <iq type='get'
531 from='tester@localhost'
532 to='you@google.com'
533 id='1'>
534 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
535 <node nodeId="Device33"/>
536 </req>
537 </iq>
538 """)
540 self.recv("""
541 <iq type='result'
542 from='you@google.com'
543 to='tester@localhost'
544 id='1'>
545 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
546 </iq>
547 """)
549 self.recv("""
550 <message from='you@google.com'
551 to='tester@localhost'>
552 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
553 <node nodeId='Device33'>
554 <timestamp value='2000-01-01T00:01:02'>
555 <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/>
556 <boolean name='TestBool' value='true'/>
557 </timestamp>
558 </node>
559 </fields>
560 </message>
561 """)
563 self.recv("""
564 <message from='you@google.com'
565 to='tester@localhost'>
566 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'/>
567 </message>
568 """)
570 t1.join();
571 time.sleep(.5)
573 self.failUnlessEqual(results, ["accepted","fields","done"]);
574 # self.assertIn("nodeId", callback_data);
575 self.assertTrue("nodeId" in callback_data)
576 self.failUnlessEqual(callback_data["nodeId"], "Device33");
577 # self.assertIn("timestamp", callback_data);
578 self.assertTrue("timestamp" in callback_data);
579 self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02");
580 #self.assertIn("field_Voltage", callback_data);
581 self.assertTrue("field_Voltage" in callback_data);
582 self.failUnlessEqual(callback_data["field_Voltage"], {"name": "Voltage", "value": "230.4", "typename": "numeric", "unit": "V", "flags": {"invoiced": "true"}});
583 #self.assertIn("field_TestBool", callback_data);
584 self.assertTrue("field_TestBool" in callback_data);
585 self.failUnlessEqual(callback_data["field_TestBool"], {"name": "TestBool", "value": "true", "typename": "boolean" });
587 def testServiceDiscoveryClient(self):
588 self.stream_start(mode='client',
589 plugins=['xep_0030',
590 'xep_0323']);
592 self.recv("""
593 <iq type='get'
594 from='master@clayster.com/amr'
595 to='tester@localhost'
596 id='disco1'>
597 <query xmlns='http://jabber.org/protocol/disco#info'/>
598 </iq>
599 """)
601 self.send("""
602 <iq type='result'
603 to='master@clayster.com/amr'
604 id='disco1'>
605 <query xmlns='http://jabber.org/protocol/disco#info'>
606 <identity category='client' type='bot'/>
607 <feature var='urn:xmpp:iot:sensordata'/>
608 </query>
609 </iq>
610 """)
612 def testServiceDiscoveryComponent(self):
613 self.stream_start(mode='component',
614 plugins=['xep_0030',
615 'xep_0323']);
617 self.recv("""
618 <iq type='get'
619 from='master@clayster.com/amr'
620 to='tester@localhost'
621 id='disco1'>
622 <query xmlns='http://jabber.org/protocol/disco#info'/>
623 </iq>
624 """)
626 self.send("""
627 <iq type='result'
628 from='tester@localhost'
629 to='master@clayster.com/amr'
630 id='disco1'>
631 <query xmlns='http://jabber.org/protocol/disco#info'>
632 <identity category='component' type='generic'/>
633 <feature var='urn:xmpp:iot:sensordata'/>
634 </query>
635 </iq>
636 """)
638 def testRequestTimeout(self):
640 self.stream_start(mode='client',
641 plugins=['xep_0030',
642 'xep_0323'])
644 results = [];
645 callback_data = {};
647 def my_callback(from_jid, result, nodeId=None, timestamp=None, error_msg=None):
648 results.append(result);
649 if result == "failure":
650 callback_data["nodeId"] = nodeId;
651 callback_data["timestamp"] = timestamp;
652 callback_data["error_msg"] = error_msg;
654 t1= threading.Thread(name="request_data",
655 target=self.xmpp['xep_0323'].request_data,
656 kwargs={"from_jid": "tester@localhost",
657 "to_jid": "you@google.com",
658 "nodeIds": ['Device33'],
659 "callback": my_callback});
660 t1.start();
662 self.send("""
663 <iq type='get'
664 from='tester@localhost'
665 to='you@google.com'
666 id='1'>
667 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
668 <node nodeId="Device33"/>
669 </req>
670 </iq>
671 """)
673 self.recv("""
674 <iq type='result'
675 from='you@google.com'
676 to='tester@localhost'
677 id='1'>
678 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
679 </iq>
680 """)
682 self.recv("""
683 <message from='you@google.com'
684 to='tester@localhost'>
685 <failure xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'>
686 <error nodeId='Device33' timestamp='2013-03-07T17:13:30'>Timeout.</error>
687 </failure>
688 </message>
689 """)
691 t1.join();
692 time.sleep(.5)
694 self.failUnlessEqual(results, ["accepted","failure"]);
695 # self.assertIn("nodeId", callback_data);
696 self.assertTrue("nodeId" in callback_data);
697 self.failUnlessEqual(callback_data["nodeId"], "Device33");
698 # self.assertIn("timestamp", callback_data);
699 self.assertTrue("timestamp" in callback_data);
700 self.failUnlessEqual(callback_data["timestamp"], "2013-03-07T17:13:30");
701 # self.assertIn("error_msg", callback_data);
702 self.assertTrue("error_msg" in callback_data);
703 self.failUnlessEqual(callback_data["error_msg"], "Timeout.");
705 def testDelayedRequest(self):
706 self.stream_start(mode='component',
707 plugins=['xep_0030',
708 'xep_0323'])
710 myDevice = Device("Device22");
711 myDevice._add_field(name="Temperature", typename="numeric", unit="°C");
712 myDevice._set_momentary_timestamp("2013-03-07T16:24:30")
713 myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"});
715 self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5);
717 dtnow = datetime.datetime.now()
718 ts_2sec = datetime.timedelta(0,2)
719 dtnow_plus_2sec = dtnow + ts_2sec
720 when_flag = dtnow_plus_2sec.replace(microsecond=0).isoformat()
722 self.recv("""
723 <iq type='get'
724 from='master@clayster.com/amr'
725 to='device@clayster.com'
726 id='1'>
727 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/>
728 </iq>
729 """)
731 self.send("""
732 <iq type='result'
733 from='device@clayster.com'
734 to='master@clayster.com/amr'
735 id='1'>
736 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true' />
737 </iq>
738 """)
740 time.sleep(2)
742 self.send("""
743 <message from='device@clayster.com'
744 to='master@clayster.com/amr'>
745 <started xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
746 </message>
747 """)
749 self.send("""
750 <message from='device@clayster.com'
751 to='master@clayster.com/amr'>
752 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'>
753 <node nodeId='Device22'>
754 <timestamp value='2013-03-07T16:24:30'>
755 <numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
756 </timestamp>
757 </node>
758 </fields>
759 </message>
760 """)
762 def testDelayedRequestFail(self):
763 self.stream_start(mode='component',
764 plugins=['xep_0030',
765 'xep_0323'])
767 myDevice = Device("Device22");
768 myDevice._add_field(name="Temperature", typename="numeric", unit="°C");
769 myDevice._set_momentary_timestamp("2013-03-07T16:24:30")
770 myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"});
772 self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5);
774 dtnow = datetime.datetime.now()
775 ts_2sec = datetime.timedelta(0,2)
776 dtnow_minus_2sec = dtnow - ts_2sec
777 when_flag = dtnow_minus_2sec.replace(microsecond=0).isoformat()
779 self.recv("""
780 <iq type='get'
781 from='master@clayster.com/amr'
782 to='device@clayster.com'
783 id='1'>
784 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/>
785 </iq>
786 """)
788 # Remove the returned datetime to allow predictable test
789 xml_stanza = self._filtered_stanza_prepare()
790 error_text = xml_stanza['rejected']['error'] #['text']
791 error_text = error_text[:error_text.find(':')]
792 xml_stanza['rejected']['error'] = error_text
794 self._filtered_stanza_check("""
795 <iq type='error'
796 from='device@clayster.com'
797 to='master@clayster.com/amr'
798 id='1'>
799 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
800 <error>Invalid datetime in 'when' flag, cannot set a time in the past. Current time</error>
801 </rejected>
802 </iq>
803 """, xml_stanza)
806 def _filtered_stanza_prepare(self, timeout=.5):
807 sent = self.xmpp.socket.next_sent(timeout)
808 if sent is None:
809 self.fail("No stanza was sent.")
811 xml = self.parse_xml(sent)
812 self.fix_namespaces(xml, 'jabber:client')
813 sent = self.xmpp._build_stanza(xml, 'jabber:client')
814 return sent
816 def _filtered_stanza_check(self, data, filtered, defaults=None, use_values=True, method='exact'):
817 self.check(filtered, data,
818 method=method,
819 defaults=defaults,
820 use_values=use_values)
822 def testRequestFieldFrom(self):
824 self.stream_start(mode='component',
825 plugins=['xep_0030',
826 'xep_0323'])
828 myDevice = Device("Device44");
829 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
830 myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
831 myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"});
832 myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"});
834 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
836 print("."),
838 self.recv("""
839 <iq type='get'
840 from='master@clayster.com/amr'
841 to='device@clayster.com'
842 id='6'>
843 <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' from='2000-01-02T00:00:01'>
844 <field name='Voltage'/>
845 </req>
846 </iq>
847 """)
849 self.send("""
850 <iq type='result'
851 from='device@clayster.com'
852 to='master@clayster.com/amr'
853 id='6'>
854 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/>
855 </iq>
856 """)
858 self.send("""
859 <message from='device@clayster.com'
860 to='master@clayster.com/amr'>
861 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
862 <node nodeId='Device44'>
863 <timestamp value='2000-02-01T00:01:02'>
864 <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/>
865 </timestamp>
866 </node>
867 </fields>
868 </message>
869 """)
871 self.send("""
872 <message from='device@clayster.com'
873 to='master@clayster.com/amr'>
874 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
875 <node nodeId='Device44'>
876 <timestamp value='2000-03-01T00:01:02'>
877 <numeric name='Voltage' invoiced='true' value='230.3' unit='V'/>
878 </timestamp>
879 </node>
880 </fields>
881 </message>
882 """)
884 self.send("""
885 <message from='device@clayster.com'
886 to='master@clayster.com/amr'>
887 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'>
888 </fields>
889 </message>
890 """)
892 def testRequestFieldTo(self):
894 self.stream_start(mode='component',
895 plugins=['xep_0030',
896 'xep_0323'])
898 myDevice = Device("Device44");
899 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
900 myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
901 myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"});
902 myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"});
904 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
906 print("."),
908 self.recv("""
909 <iq type='get'
910 from='master@clayster.com/amr'
911 to='device@clayster.com'
912 id='6'>
913 <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' to='2000-02-02T00:00:01'>
914 <field name='Voltage'/>
915 </req>
916 </iq>
917 """)
919 self.send("""
920 <iq type='result'
921 from='device@clayster.com'
922 to='master@clayster.com/amr'
923 id='6'>
924 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/>
925 </iq>
926 """)
928 self.send("""
929 <message from='device@clayster.com'
930 to='master@clayster.com/amr'>
931 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
932 <node nodeId='Device44'>
933 <timestamp value='2000-01-01T00:01:02'>
934 <numeric name='Voltage' invoiced='true' value='230.1' unit='V'/>
935 </timestamp>
936 </node>
937 </fields>
938 </message>
939 """)
941 self.send("""
942 <message from='device@clayster.com'
943 to='master@clayster.com/amr'>
944 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
945 <node nodeId='Device44'>
946 <timestamp value='2000-02-01T00:01:02'>
947 <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/>
948 </timestamp>
949 </node>
950 </fields>
951 </message>
952 """)
954 self.send("""
955 <message from='device@clayster.com'
956 to='master@clayster.com/amr'>
957 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'>
958 </fields>
959 </message>
960 """)
962 def testRequestFieldFromTo(self):
964 self.stream_start(mode='component',
965 plugins=['xep_0030',
966 'xep_0323'])
968 myDevice = Device("Device44");
969 myDevice._add_field(name='Voltage', typename="numeric", unit="V");
970 myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"});
971 myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"});
972 myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"});
974 self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5);
976 print("."),
978 self.recv("""
979 <iq type='get'
980 from='master@clayster.com/amr'
981 to='device@clayster.com'
982 id='6'>
983 <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' from='2000-01-01T00:01:03' to='2000-02-02T00:00:01'>
984 <field name='Voltage'/>
985 </req>
986 </iq>
987 """)
989 self.send("""
990 <iq type='result'
991 from='device@clayster.com'
992 to='master@clayster.com/amr'
993 id='6'>
994 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/>
995 </iq>
996 """)
998 self.send("""
999 <message from='device@clayster.com'
1000 to='master@clayster.com/amr'>
1001 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'>
1002 <node nodeId='Device44'>
1003 <timestamp value='2000-02-01T00:01:02'>
1004 <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/>
1005 </timestamp>
1006 </node>
1007 </fields>
1008 </message>
1009 """)
1011 self.send("""
1012 <message from='device@clayster.com'
1013 to='master@clayster.com/amr'>
1014 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'>
1015 </fields>
1016 </message>
1017 """)
1019 def testDelayedRequestClient(self):
1020 self.stream_start(mode='client',
1021 plugins=['xep_0030',
1022 'xep_0323'])
1024 results = [];
1025 callback_data = {};
1027 def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None):
1028 results.append(result);
1029 if result == "fields":
1030 callback_data["nodeId"] = nodeId;
1031 callback_data["timestamp"] = timestamp;
1032 callback_data["error_msg"] = error_msg;
1033 for f in fields:
1034 callback_data["field_" + f['name']] = f;
1036 t1= threading.Thread(name="request_data",
1037 target=self.xmpp['xep_0323'].request_data,
1038 kwargs={"from_jid": "tester@localhost",
1039 "to_jid": "you@google.com",
1040 "nodeIds": ['Device33'],
1041 "callback": my_callback});
1042 t1.start();
1043 #self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback);
1045 self.send("""
1046 <iq type='get'
1047 from='tester@localhost'
1048 to='you@google.com'
1049 id='1'>
1050 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
1051 <node nodeId="Device33"/>
1052 </req>
1053 </iq>
1054 """)
1056 self.recv("""
1057 <iq type='result'
1058 from='you@google.com'
1059 to='tester@localhost'
1060 id='1'>
1061 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true'/>
1062 </iq>
1063 """)
1065 self.recv("""
1066 <message from='device@clayster.com'
1067 to='master@clayster.com/amr'>
1068 <started xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1069 </message>
1070 """)
1072 self.recv("""
1073 <message from='you@google.com'
1074 to='tester@localhost'>
1075 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
1076 <node nodeId='Device33'>
1077 <timestamp value='2000-01-01T00:01:02'>
1078 <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/>
1079 <boolean name='TestBool' value='true'/>
1080 </timestamp>
1081 </node>
1082 </fields>
1083 </message>
1084 """)
1086 self.recv("""
1087 <message from='you@google.com'
1088 to='tester@localhost'>
1089 <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'/>
1090 </message>
1091 """)
1093 t1.join();
1094 time.sleep(.5)
1096 self.failUnlessEqual(results, ["queued","started","fields","done"]);
1097 # self.assertIn("nodeId", callback_data);
1098 self.assertTrue("nodeId" in callback_data);
1099 self.failUnlessEqual(callback_data["nodeId"], "Device33");
1100 # self.assertIn("timestamp", callback_data);
1101 self.assertTrue("timestamp" in callback_data);
1102 self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02");
1103 # self.assertIn("field_Voltage", callback_data);
1104 self.assertTrue("field_Voltage" in callback_data);
1105 self.failUnlessEqual(callback_data["field_Voltage"], {"name": "Voltage", "value": "230.4", "typename": "numeric", "unit": "V", "flags": {"invoiced": "true"}});
1106 # self.assertIn("field_TestBool", callback_data);
1107 self.assertTrue("field_TestBool" in callback_data);
1108 self.failUnlessEqual(callback_data["field_TestBool"], {"name": "TestBool", "value": "true", "typename": "boolean" });
1111 def testRequestFieldsCancelAPI(self):
1113 self.stream_start(mode='client',
1114 plugins=['xep_0030',
1115 'xep_0323'])
1117 results = [];
1119 def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None):
1120 results.append(result);
1122 session = self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback);
1124 self.send("""
1125 <iq type='get'
1126 from='tester@localhost'
1127 to='you@google.com'
1128 id='1'>
1129 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
1130 <node nodeId="Device33"/>
1131 </req>
1132 </iq>
1133 """)
1135 self.recv("""
1136 <iq type='result'
1137 from='you@google.com'
1138 to='tester@localhost'
1139 id='1'>
1140 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/>
1141 </iq>
1142 """)
1144 self.xmpp['xep_0323'].cancel_request(session=session);
1146 self.send("""
1147 <iq type='get'
1148 from='tester@localhost'
1149 to='you@google.com'
1150 id='1'>
1151 <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1152 </iq>
1153 """)
1155 self.recv("""
1156 <iq type='result'
1157 from='tester@localhost'
1158 to='you@google.com'
1159 id='1'>
1160 <cancelled xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1161 </iq>
1162 """)
1164 time.sleep(.5)
1166 self.failUnlessEqual(results, ["accepted","cancelled"]);
1168 def testDelayedRequestCancel(self):
1169 self.stream_start(mode='component',
1170 plugins=['xep_0030',
1171 'xep_0323'])
1173 myDevice = Device("Device22");
1174 myDevice._add_field(name="Temperature", typename="numeric", unit="°C");
1175 myDevice._set_momentary_timestamp("2013-03-07T16:24:30")
1176 myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"});
1178 self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5);
1180 dtnow = datetime.datetime.now()
1181 ts_2sec = datetime.timedelta(0,2)
1182 dtnow_plus_2sec = dtnow + ts_2sec
1183 when_flag = dtnow_plus_2sec.replace(microsecond=0).isoformat()
1185 self.recv("""
1186 <iq type='get'
1187 from='master@clayster.com/amr'
1188 to='device@clayster.com'
1189 id='1'>
1190 <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/>
1191 </iq>
1192 """)
1194 self.send("""
1195 <iq type='result'
1196 from='device@clayster.com'
1197 to='master@clayster.com/amr'
1198 id='1'>
1199 <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true' />
1200 </iq>
1201 """)
1203 self.recv("""
1204 <iq type='get'
1205 from='master@clayster.com/amr'
1206 to='device@clayster.com'
1207 id='1'>
1208 <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1209 </iq>
1210 """)
1212 self.send("""
1213 <iq type='result'
1214 from='device@clayster.com'
1215 to='master@clayster.com/amr'
1216 id='1'>
1217 <cancelled xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1218 </iq>
1219 """)
1221 # Test cancel of non-existing request
1222 self.recv("""
1223 <iq type='get'
1224 from='tester@localhost'
1225 to='you@google.com'
1226 id='1'>
1227 <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' />
1228 </iq>
1229 """)
1231 self.send("""
1232 <iq type='error'
1233 from='you@google.com'
1234 to='tester@localhost'
1235 id='1'>
1236 <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'>
1237 <error>Cancel request received, no matching request is active.</error>
1238 </rejected>
1239 </iq>
1240 """)
1242 time.sleep(2)
1244 # Ensure we don't get anything after cancellation
1245 self.send(None)
1249 suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamSensorData)