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