tempoiq 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,629 @@
1
+ require 'tempoiq/client'
2
+
3
+ module ClientTest
4
+ TEMPO_TEST_ATTR = 'tempoiq-ruby-test-device'
5
+
6
+ def setup
7
+ delete_devices
8
+ end
9
+
10
+ def teardown
11
+ delete_devices
12
+ end
13
+
14
+ def test_initialize
15
+ client = TempoIQ::Client.new("key", "secret", "backend.tempoiq.com")
16
+ assert_equal("key", client.key)
17
+ assert_equal("secret", client.secret)
18
+ assert_equal("backend.tempoiq.com", client.host)
19
+ assert(client.secure)
20
+ end
21
+
22
+ def test_create_device
23
+ client = get_client
24
+ stubbed_body = {
25
+ 'key' => 'stubbed_key',
26
+ 'name' => 'stubbed_name',
27
+ 'attributes' => {'attr1' => 'value1', TEMPO_TEST_ATTR => TEMPO_TEST_ATTR},
28
+ 'sensors' => []
29
+ }
30
+ client.remoter.stub(:post, "/v2/devices", 200, JSON.dump(stubbed_body))
31
+
32
+ device = client.create_device('stubbed_key', 'stubbed_name', 'attr1' => 'value1', TEMPO_TEST_ATTR => TEMPO_TEST_ATTR)
33
+
34
+ assert_equal('stubbed_key', device.key)
35
+ assert_equal('stubbed_name', device.name)
36
+ assert_equal({'attr1' => 'value1', TEMPO_TEST_ATTR => TEMPO_TEST_ATTR }, device.attributes)
37
+ assert_equal([], device.sensors)
38
+ end
39
+
40
+ def test_delete_devices
41
+ device = create_device
42
+ client = get_client
43
+ stubbed_body = {
44
+ 'deleted' => 1
45
+ }
46
+
47
+ client.remoter.stub(:delete, "/v2/devices", 200, JSON.dump(stubbed_body))
48
+
49
+ summary = client.delete_devices(:devices => {:key => device.key})
50
+ assert_equal(1, summary.deleted)
51
+ end
52
+
53
+ def test_update_device
54
+ device = create_device
55
+ client = get_client
56
+
57
+ original_name = device.name
58
+ device.name = "Updated"
59
+ assert_not_equal(original_name, device.name)
60
+
61
+ stubbed_body = device.to_hash
62
+ client.remoter.stub(:put, "/v2/devices/#{device.key}", 200, JSON.dump(stubbed_body))
63
+
64
+ updated_device = client.update_device(device)
65
+ assert_equal(device.name, updated_device.name)
66
+ end
67
+
68
+ def test_get_device
69
+ device = create_device
70
+ client = get_client
71
+
72
+ stubbed_body = device.to_hash
73
+ client.remoter.stub(:get, "/v2/devices/#{device.key}", 200, JSON.dump(stubbed_body))
74
+
75
+ found = client.get_device(device.key)
76
+
77
+ assert_equal(device.key, found.key)
78
+ end
79
+
80
+ def test_get_device_not_found
81
+ client = get_client
82
+
83
+ client.remoter.stub(:get, "/v2/devices/not_found", 404)
84
+
85
+ not_found = client.get_device("not_found")
86
+ assert_nil(not_found)
87
+ end
88
+
89
+ def test_list_devices
90
+ device = create_device
91
+ client = get_client
92
+
93
+ stubbed_body = {
94
+ "data" => [device.to_hash]
95
+ }
96
+ client.remoter.stub(:get, "/v2/devices", 200, JSON.dump(stubbed_body))
97
+
98
+ found = client.list_devices(:devices => {:key => device.key})
99
+ assert_equal(device.key, found.to_a.first.key)
100
+ end
101
+
102
+ def test_cursored_list_devices
103
+ device = create_device("device-cursored-1")
104
+ device2 = create_device("device-cursored-2")
105
+ client = get_client(true)
106
+
107
+ next_query = {
108
+ "search" => {
109
+ "select" => "devices",
110
+ "filters" => {"devices" => {"attribute_key" => TEMPO_TEST_ATTR}}
111
+ },
112
+ "find" => {
113
+ "quantifier" => "all"
114
+ },
115
+ }
116
+
117
+ stubbed_body = {
118
+ "data" => [device.to_hash],
119
+ "next_page" => {
120
+ "next_query" => next_query
121
+ }
122
+ }
123
+ client.remoter.stub(:get, "/v2/devices", 200, JSON.dump(stubbed_body))
124
+
125
+ next_list = stubbed_body
126
+ next_list.delete("next_page")
127
+ next_list["data"][0] = device2.to_hash
128
+
129
+ client.remoter.stub(:get, "/v2/devices", 200, JSON.dump(next_list))
130
+
131
+ found = client.list_devices({:devices => {:attribute_key => TEMPO_TEST_ATTR}}, :limit => 1)
132
+ assert_equal(2, found.to_a.size)
133
+ end
134
+
135
+ def test_write_bulk
136
+ device = create_device
137
+ client = get_client
138
+ ts = Time.utc(2012, 1, 1)
139
+
140
+ device_key = device.key
141
+ sensor_key = device.sensors.first.key
142
+
143
+ client.remoter.stub(:post, "/v2/write", 200)
144
+
145
+ status = client.write_bulk do |write|
146
+ write.add(device_key, sensor_key, TempoIQ::DataPoint.new(ts, 1.23))
147
+ end
148
+
149
+ assert(status.success?)
150
+ assert(!status.partial_success?)
151
+ end
152
+
153
+ def test_write_bulk_no_params
154
+ client = get_client
155
+
156
+ assert_raise(TempoIQ::ClientError) do
157
+ client.write_bulk
158
+ end
159
+ end
160
+
161
+ def test_write_with_partial_failure
162
+ device = create_device
163
+ client = get_client
164
+ ts = Time.utc(2012, 1, 1)
165
+
166
+ device_key = device.key
167
+ sensor_key = device.sensors.first.key
168
+
169
+ stubbed_body = {"device1" => {"success" => false, "message" => "error writing to storage: FERR_NO_SENSOR: No sensor with key found in device."}}
170
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
171
+
172
+ status = client.write_bulk do |write|
173
+ write.add(device_key, sensor_key, TempoIQ::DataPoint.new(ts, 1.23))
174
+ write.add(device_key, "not_here", TempoIQ::DataPoint.new(ts, 2.34))
175
+ end
176
+
177
+ assert(!status.success?)
178
+ assert(status.partial_success?)
179
+ assert_equal(1, status.failures.size)
180
+ end
181
+
182
+ def test_write_device
183
+ device = create_device
184
+ client = get_client
185
+ ts = Time.utc(2012, 1, 1)
186
+
187
+ device_key = device.key
188
+ sensor_key = device.sensors.first.key
189
+
190
+ client.remoter.stub(:post, "/v2/write", 200)
191
+
192
+ written = client.write_device(device_key, ts, sensor_key => 1.23)
193
+
194
+ assert_equal(true, written)
195
+ end
196
+
197
+ def test_read_with_pipeline
198
+ device = create_device
199
+ client = get_client
200
+ ts = Time.utc(2012, 1, 1, 1)
201
+ start = Time.utc(2012, 1, 1)
202
+ stop = Time.utc(2012, 1, 2)
203
+
204
+ device_key = device.key
205
+ sensor_key1 = device.sensors[0].key
206
+ sensor_key2 = device.sensors[1].key
207
+
208
+ client.remoter.stub(:post, "/v2/write", 200)
209
+
210
+ write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 1), sensor_key1 => 4.0, sensor_key2 => 2.0)
211
+ assert_equal(true, write_result)
212
+ write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 2), sensor_key1 => 4.0, sensor_key2 => 2.0)
213
+ assert_equal(true, write_result)
214
+
215
+ selection = {
216
+ :devices => {:key => device_key}
217
+ }
218
+
219
+ stubbed_read = {
220
+ "data" => [
221
+ {
222
+ "t" => ts.iso8601(3),
223
+ "data" => {
224
+ device_key => {
225
+ "mean" => 6.0
226
+ }
227
+ }
228
+ }
229
+ ]
230
+ }
231
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_read))
232
+
233
+ rows = client.read(selection, start, stop) do |pipeline|
234
+ pipeline.rollup("1day", :sum, start)
235
+ pipeline.aggregate(:mean)
236
+ end.to_a
237
+
238
+ assert_equal(1, rows.size)
239
+ assert_equal(6.0, rows[0].value(device.key, "mean"))
240
+ end
241
+
242
+ def test_read_with_interpolation
243
+ device = create_device
244
+ client = get_client
245
+ start = Time.utc(2012, 1, 1, 1, 0, 0, 0)
246
+ stop = Time.utc(2012, 1, 1, 1, 0, 20, 0)
247
+
248
+ device_key = device.key
249
+ sensor_key = device.sensors[0].key
250
+
251
+ client.remoter.stub(:post, "/v2/write", 200)
252
+
253
+ write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 1, 0, 5, 0), sensor_key => 4.0)
254
+ assert_equal(true, write_result)
255
+ write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 1, 0, 10, 0), sensor_key => 8.0)
256
+ assert_equal(true, write_result)
257
+
258
+ selection = {
259
+ :devices => {:key => device_key}
260
+ }
261
+
262
+ stubbed_read = {
263
+ "data" => [
264
+ {
265
+ "t" => Time.utc(2012, 1, 1, 1, 0, 5, 0),
266
+ "data" => {
267
+ device_key => {
268
+ sensor_key => 4.0
269
+ }
270
+ }
271
+ },
272
+ {
273
+ "t" => Time.utc(2012, 1, 1, 1, 0, 6, 0),
274
+ "data" => {
275
+ device_key => {
276
+ sensor_key => 4.8
277
+ }
278
+ }
279
+ },
280
+ {
281
+ "t" => Time.utc(2012, 1, 1, 1, 0, 7, 0),
282
+ "data" => {
283
+ device_key => {
284
+ sensor_key => 5.6
285
+ }
286
+ }
287
+ },
288
+ {
289
+ "t" => Time.utc(2012, 1, 1, 1, 0, 8, 0),
290
+ "data" => {
291
+ device_key => {
292
+ sensor_key => 6.4
293
+ }
294
+ }
295
+ },
296
+ {
297
+ "t" => Time.utc(2012, 1, 1, 1, 0, 9, 0),
298
+ "data" => {
299
+ device_key => {
300
+ sensor_key => 7.2
301
+ }
302
+ }
303
+ },
304
+ {
305
+ "t" => Time.utc(2012, 1, 1, 1, 0, 10, 0),
306
+ "data" => {
307
+ device_key => {
308
+ sensor_key => 8.0
309
+ }
310
+ }
311
+ }
312
+ ]
313
+ }
314
+
315
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_read))
316
+
317
+ rows = client.read(selection, start, stop) do |pipeline|
318
+ pipeline.interpolate("PT1S", :linear, start, stop)
319
+ end.to_a
320
+
321
+ assert_equal(6, rows.size)
322
+ end
323
+
324
+ def test_read_device_sensor
325
+ device = create_device
326
+ client = get_client
327
+ ts = Time.utc(2012, 1, 1, 1)
328
+ start = Time.utc(2012, 1, 1)
329
+ stop = Time.utc(2012, 1, 2)
330
+
331
+ device_key = device.key
332
+ sensor_key = device.sensors[0].key
333
+
334
+ client.remoter.stub(:post, "/v2/write", 200)
335
+
336
+ write_result = client.write_device(device_key, ts, sensor_key => 4.0)
337
+ assert_equal(true, write_result)
338
+
339
+ selection = {
340
+ :devices => {:key => device_key},
341
+ :sensors => {:key => sensor_key}
342
+ }
343
+
344
+ stubbed_read = {
345
+ "data" => [
346
+ {
347
+ "t" => ts.iso8601(3),
348
+ "data" => {
349
+ device_key => {
350
+ sensor_key => 4.0
351
+ }
352
+ }
353
+ }
354
+ ]
355
+ }
356
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_read))
357
+
358
+ points = client.read_device_sensor(device_key, sensor_key, start, stop).to_a
359
+
360
+ assert_equal(1, points.size)
361
+ assert_equal(4.0, points[0].value)
362
+ end
363
+
364
+ def test_read_without_pipeline
365
+ device = create_device
366
+ client = get_client
367
+ ts = Time.utc(2012, 1, 1, 1)
368
+ start = Time.utc(2012, 1, 1)
369
+ stop = Time.utc(2012, 1, 2)
370
+
371
+ device_key = device.key
372
+ sensor_key1 = device.sensors[0].key
373
+ sensor_key2 = device.sensors[1].key
374
+
375
+ client.remoter.stub(:post, "/v2/write", 200)
376
+
377
+ write_result = client.write_device(device_key, ts, sensor_key1 => 4.0, sensor_key2 => 2.0)
378
+ assert_equal(true, write_result)
379
+
380
+ selection = {
381
+ :devices => {:key => device_key}
382
+ }
383
+
384
+ stubbed_read = {
385
+ "data" => [
386
+ {
387
+ "t" => ts.iso8601(3),
388
+ "data" => {
389
+ device_key => {
390
+ sensor_key1 => 4.0,
391
+ sensor_key2 => 2.0
392
+ }
393
+ }
394
+ }
395
+ ]
396
+ }
397
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_read))
398
+
399
+ rows = client.read(selection, start, stop).to_a
400
+
401
+ assert_equal(1, rows.size)
402
+ assert_equal(4.0, rows[0].value(device.key, sensor_key1))
403
+ assert_equal(2.0, rows[0].value(device.key, sensor_key2))
404
+ end
405
+
406
+ def test_read_cursoring
407
+ device = create_device
408
+ client = get_client(true)
409
+ start = Time.utc(2012, 1, 1)
410
+ stop = Time.utc(2012, 1, 2)
411
+
412
+ ts = Time.utc(2012, 1, 1, 1)
413
+ ts2 = Time.utc(2012, 1, 1, 2)
414
+
415
+ device_key = device.key
416
+ sensor_key1 = device.sensors[0].key
417
+ sensor_key2 = device.sensors[1].key
418
+
419
+ client.remoter.stub(:post, "/v2/write", 200)
420
+ client.remoter.stub(:post, "/v2/write", 200)
421
+
422
+ assert_equal(true, client.write_device(device_key, ts, sensor_key1 => 4.0, sensor_key2 => 2.0))
423
+ assert_equal(true, client.write_device(device_key, ts2, sensor_key1 => 4.0, sensor_key2 => 2.0))
424
+
425
+ selection = {
426
+ :devices => {:key => device_key}
427
+ }
428
+
429
+ next_query = {
430
+ "search" => {
431
+ "select" => "devices",
432
+ "filters" => {"devices" => "all"}
433
+ },
434
+ "read" => {
435
+ "start" => ts.iso8601(3),
436
+ "stop" => stop.iso8601(3)
437
+ },
438
+ "fold" => {
439
+ "functions" => []
440
+ }
441
+ }
442
+
443
+ stubbed_read = {
444
+ "data" => [
445
+ {
446
+ "t" => ts.iso8601(3),
447
+ "data" => {
448
+ device_key => {
449
+ sensor_key1 => 4.0,
450
+ sensor_key2 => 2.0
451
+ }
452
+ }
453
+ }
454
+ ],
455
+ "next_page" => {
456
+ "next_query" => next_query
457
+ }
458
+ }
459
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_read))
460
+
461
+ next_read = stubbed_read
462
+ next_read.delete("next_page")
463
+ next_read["data"][0]["t"] = ts2.iso8601(3)
464
+
465
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(next_read))
466
+
467
+ rows = client.read(selection, start, stop, TempoIQ::Pipeline.new, :limit => 1).to_a
468
+
469
+ assert_equal(2, rows.size)
470
+
471
+ assert_equal(4.0, rows[0].value(device.key, sensor_key1))
472
+ assert_equal(2.0, rows[0].value(device.key, sensor_key2))
473
+
474
+ assert_equal(4.0, rows[1].value(device.key, sensor_key1))
475
+ assert_equal(2.0, rows[1].value(device.key, sensor_key2))
476
+ end
477
+
478
+ def test_delete_device
479
+ device = create_device
480
+ client = get_client
481
+
482
+ client.remoter.stub(:delete, "/v2/devices/#{device.key}", 200)
483
+
484
+ deleted = client.delete_device(device.key)
485
+ assert_equal(true, deleted)
486
+ end
487
+
488
+ def test_latest
489
+ device = create_device
490
+ client = get_client
491
+
492
+ device_key = device.key
493
+ sensor_key1 = device.sensors.first.key
494
+ sensor_key2 = device.sensors[1].key
495
+
496
+ ts = Time.utc(2012, 1, 1)
497
+
498
+ stubbed_single = {
499
+ "data" => [
500
+ {
501
+ "t" => ts.iso8601(3),
502
+ "data" => {
503
+ device_key => {
504
+ sensor_key1 => 4.0,
505
+ sensor_key2 => 2.0
506
+ }
507
+ }
508
+ }
509
+ ]
510
+ }
511
+
512
+ client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
513
+ client.remoter.stub(:post, "/v2/write", 200)
514
+
515
+ client.write_device(device_key, ts, sensor_key1 => 4.0)
516
+ client.write_device(device_key, ts, sensor_key2 => 2.0)
517
+
518
+ selection = {
519
+ :devices => {:key => device_key}
520
+ }
521
+
522
+ rows = client.latest(selection).to_a
523
+
524
+ assert_equal(1, rows.size)
525
+ assert_equal(4.0, rows[0].value(device.key, sensor_key1))
526
+ assert_equal(2.0, rows[0].value(device.key, sensor_key2))
527
+ end
528
+
529
+ def test_delete_points
530
+ device = create_device
531
+ client = get_client
532
+
533
+ device_key = device.key
534
+ sensor_key1 = device.sensors.first.key
535
+ sensor_key2 = device.sensors[1].key
536
+
537
+ ts = Time.utc(2012, 1, 1)
538
+
539
+ client.remoter.stub(:post, "/v2/write", 200)
540
+
541
+ client.write_device(device_key, ts, sensor_key1 => 4.0)
542
+ client.write_device(device_key, ts, sensor_key2 => 2.0)
543
+
544
+ selection = {
545
+ :devices => {:key => device_key}
546
+ }
547
+
548
+ client.remoter.stub(:delete, "/v2/devices/#{device_key}/sensors/#{sensor_key1}/datapoints", 200, JSON.dump(:deleted => 1))
549
+
550
+ start = Time.utc(2011, 1, 1)
551
+ stop = Time.utc(2013, 1, 1)
552
+ summary = client.delete_datapoints(device_key, sensor_key1, start, stop)
553
+
554
+ assert_equal(1, summary.deleted)
555
+
556
+ stubbed_after_delete = {
557
+ "data" => [
558
+ {
559
+ "t" => ts.iso8601(3),
560
+ "data" => {
561
+ device_key => {
562
+ sensor_key2 => 2.0
563
+ }
564
+ }
565
+ }
566
+ ]
567
+ }
568
+ client.remoter.stub(:get, "/v2/read", 200, JSON.dump(stubbed_after_delete))
569
+
570
+ rows = client.read(selection, start, stop).to_a
571
+ assert_nil(nil, rows[0].value(device.key, sensor_key1))
572
+ assert_equal(2.0, rows[0].value(device.key, sensor_key2))
573
+ end
574
+
575
+ def test_delete_datapoints_nonexistent_device
576
+ client = get_client
577
+ device_key = "not_found"
578
+ sensor_key = "also_not_found"
579
+
580
+ client.remoter.stub(:delete, "/v2/devices/#{device_key}/sensors/#{sensor_key}/datapoints", 404)
581
+
582
+ start = Time.utc(2011, 1, 1)
583
+ stop = Time.utc(2013, 1, 1)
584
+ assert_raise TempoIQ::HttpException do
585
+ client.delete_datapoints(device_key, sensor_key, start, stop)
586
+ end
587
+ end
588
+
589
+ private
590
+
591
+ def create_device(key = "device1")
592
+ client = get_client
593
+ stubbed_body = {
594
+ 'key' => key,
595
+ 'name' => 'My Awesome Device',
596
+ 'attributes' => {TEMPO_TEST_ATTR => TEMPO_TEST_ATTR, 'building' => '1234'},
597
+ 'sensors' => [
598
+ {
599
+ 'key' => 'sensor1',
600
+ 'name' => 'My Sensor',
601
+ 'attributes' => {
602
+ 'unit' => 'F'
603
+ },
604
+ },
605
+ {
606
+ 'key' => 'sensor2',
607
+ 'name' => 'My Sensor2',
608
+ 'attributes' => {
609
+ 'unit' => 'C'
610
+ }
611
+ }
612
+ ]
613
+ }
614
+ client.remoter.stub(:post, "/v2/devices", 200, JSON.dump(stubbed_body))
615
+ client.create_device(key, 'My Awesome Device', {TEMPO_TEST_ATTR => TEMPO_TEST_ATTR, 'building' => '1234'},
616
+ TempoIQ::Sensor.new('sensor1', 'My Sensor', 'unit' => 'F'),
617
+ TempoIQ::Sensor.new('sensor2', 'My Sensor2', 'unit' => 'C'))
618
+ end
619
+
620
+ def delete_devices
621
+ client = get_client
622
+ stubbed_body = {
623
+ 'deleted' => 1
624
+ }
625
+
626
+ client.remoter.stub(:delete, "/v2/devices", 200, JSON.dump(stubbed_body))
627
+ summary = client.delete_devices(:devices => {:attribute_key => TEMPO_TEST_ATTR})
628
+ end
629
+ end