nutella_framework 0.4.26 → 0.4.27

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f89eef345759b2bad968a96b2235e0005cc2d1bb
4
- data.tar.gz: 71813562c92983c08dc5dd2d5a8186ec59e73628
3
+ metadata.gz: bd43b4159011cf9c7da7d6e423bba452d0ca7905
4
+ data.tar.gz: 9070b825cd4f15c6d784e1c629012ad20145e9d7
5
5
  SHA512:
6
- metadata.gz: 690e266c7694378af4194929b02595a890fbb52c64740f8af155e1e454aebadce726ddf47ba5ee1ed23c4d103fa371e39f4101947ce802ccff8420bbbc769bc1
7
- data.tar.gz: ecf2381663d357b32fd1911eb4232e4286196ba67ba2daa4720c34f676f1508792e13abb9977116f43e5ac1dd408dd920d27bc2dcc902c348cde67c0ef71cf01
6
+ metadata.gz: fbfc7f5d5276ff36685863a88a707f7fee20794dfebed019d02b9c7c57c87ed0f53403515f1eee73fbd7a2d78b921d8a573b227cc9ae62bafd76d50d7ed45238
7
+ data.tar.gz: 9b806a9ac742b345146bcc724d0fe7cb2b8d240cb19d99e7a011f78600692f3e4aa23f8b78629ec8444e8404c765c5b39d934d61425c68ac9a992ce638fe96a5
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.26
1
+ 0.4.27
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .idea
3
+
4
+ Gemfile.lock
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'nutella_lib','~>0.4.11'
@@ -0,0 +1,66 @@
1
+ # room-places-bot
2
+ This is the RoomPlaces bot that keeps track of resource position in 2D or 3D space.
3
+
4
+ In order to interact with this bot you can use the library Nutella client library using the methods described below:
5
+
6
+ ## Publish - Subscribe channels
7
+
8
+ | Channel | Function | Direction | Content |
9
+ | --------------------------------------- | ---------------------------- | ----------------- | ---------------------------------------------- |
10
+ | /location/resource/add | Add a new resource | client -> server | {rid: '\<string\>', model: '\<model\>', type: '\<type\>'[, proximity_range: \<float\>]} |
11
+ | /location/resource/remove | Remove a resource | client -> server | {rid: '\<string\>'} |
12
+ | /location/resource/update | Update a resource | client -> server | \<resource_update\> |
13
+ | /location/resources/update | Update resources | client -> server | {resources: [\<resource_update\>*]} |
14
+ | /location/group/add | Add a group | client -> server | {group: '\<string\>'} |
15
+ | /location/group/remove | Remove a group | client -> server | {group: '\<string\>'} |
16
+ | /location/group/resource/add | Add resource to a group | client -> server | {rid: '\<string\>', group: '\<string\>'} |
17
+ | /location/group/resource/remove | Remove resource to a group | client -> server | {rid: '\<string\>', group: '\<string\>'} |
18
+ | /location/resources/added | Publish added resources | server -> client | {resources: [\<resource\>*]} |
19
+ | /location/resources/removed | Publish removed resources | server -> client | {resources: [\<resource\>*]} |
20
+ | /location/resources/updated | Update a resource | client -> server | {resources: [\<resource_updated\>*]} |
21
+ | /location/room/update | Update the room size | client -> server | {x: \<float\>, y: \<float\> [,z:\<float\>]} |
22
+ | /location/room/updated | Notify a room update | server -> client | {x: \<float\>, y: \<float\> [,z:\<float\>]} |
23
+ | /location/resource/static/\<rid\>/enter | Notify resource enter area | server -> client | {resources: ['\<resource\>'*]} |
24
+ | /location/resource/static/\<rid\>/exit | Notify resource exit area | server -> client | {resources: ['\<resource\>'*]} |
25
+ | /location/tracking/discrete/update | Update the discrete tracking | client -> server | {tracking: \<discrete_tracking\>|{}} |
26
+ | /location/tracking/discrete/updated | Notify discrete update | client -> server | {tracking: \<discrete_tracking\>|{}} |
27
+
28
+ \<type\> ::= STATIC | DYNAMIC
29
+
30
+ \<model\> ::= IMAC | IPHONE | IPAD | IBEACON
31
+
32
+ ## Request - Response channels
33
+
34
+ | Channel | Function | Request -> Response | Request | Response |
35
+ | -------------------------------------- | ----------------------------- | ------------------- | ----------------- | ------------------------------------------ |
36
+ | /location/resources | Request all the resources | client -> server | {} | {resources: [\<resource\>*]} |
37
+ | /location/estimote | Request all the iBeacons | client -> server | {} | {resources: [\<resource_estimote\>*]} |
38
+ | /location/room | Request the room size | client -> server | {} | {x: \<float\>, y: \<float\> [,z:\<float\>]}|
39
+ | /location/resource/static/<rid>/inside | Notify resource enter area | client -> server | {} | {resources: ['\<resource\>'*]} |
40
+ | /location/tracking/discrete | Request the discrete tracking | client -> server | {} | {tracking: \<discrete_tracking\>|{}} |
41
+
42
+ \<resource\> ::= {rid: '\<string\>', model: '\<model\>', type: '\<type\>'}
43
+
44
+ \<resource_update\> ::= {rid: '\<string\>', (\<continuous\> | \<discrete\> | \<proximity\> | \<parameters\>)}
45
+
46
+ \<resource_updated\> ::= {rid: '\<string\>', model: '\<model\>', type: '\<type\>', (\<continuous\> | \<discrete\> | \<proximity\>), \<parameters_updated\> [, proximity_range: \<float\>]}
47
+
48
+ \<continuous\> ::= continuous: {x: \<float\>, y: \<float\>}
49
+
50
+ \<discrete\> ::= discrete: {x: \<discrete_n\>, y: \<discrete_n\> [, z: \<discrete_n\>]}
51
+
52
+ \<discrete_n\> ::= \<int\> | \<uppercase_char\>
53
+
54
+ \<proximity\> ::= proximity: {[rid: '', distance: '\<float\>']}
55
+
56
+ \<parameters\> ::= parameters: [\<parameter>*]
57
+
58
+ \<parameters_updated\> ::= parameters: {(\<key\>: '\<string\>')*}
59
+
60
+ \<parameter\> ::= {key: '\<string\>' , (value: '\<string\>' | delete: true)}
61
+
62
+ \<resource_estimote\> ::= {name: '\<string\>'}
63
+
64
+ \<discrete_tracking\> ::= {x: \<float\>, y: \<float\>, width: \<float\>, height: \<float\>, n_x: \<float\>, n_y: \<float\>, t_x: \<discrete_type\>, t_y: \<discrete_type\>}
65
+
66
+ \<discrete_type\> ::= 'NUMBER' | 'LETTER'
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "room-places-bot",
3
+ "version": "0.0.1",
4
+ "type": "bot",
5
+ "description": "This bot keeps track of the location of physical resources in a 2D or 3D spcace"
6
+ }
@@ -0,0 +1,770 @@
1
+ require_relative '../../lib/config/runlist'
2
+ require_relative '../../lib/config/config'
3
+ require_relative '../../nutella_lib/framework_core'
4
+ require_relative '../../lib/commands/util/components_list'
5
+ require 'nutella_lib'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'uri'
9
+ require 'json'
10
+
11
+ # Initialize this bot as framework component
12
+ nutella.f.init(Nutella.config['broker'], 'room_places_bot')
13
+
14
+ # Buffer object that caches all the updates
15
+ class RoomPlacesCachePublish
16
+
17
+ def initialize
18
+ @resource_updated = {}
19
+ @resource_added = []
20
+ @resource_removed = []
21
+ @resource_entered = {}
22
+ @resource_exited = {}
23
+
24
+ # Semaphores for threads safety
25
+ @s1 = Mutex.new
26
+ @s2 = Mutex.new
27
+ @s3 = Mutex.new
28
+ @s4 = Mutex.new
29
+ @s5 = Mutex.new
30
+ @s6 = Mutex.new
31
+ @s7 = Mutex.new
32
+ @s8 = Mutex.new
33
+ @s9 = Mutex.new
34
+ @s10 = Mutex.new
35
+ end
36
+
37
+ def resources_update(resources)
38
+ @s1.synchronize {
39
+ resources.each do |resource|
40
+ @resource_updated[resource['rid']] = resource
41
+ end
42
+ }
43
+ end
44
+
45
+ def resources_add(resources)
46
+ @s2.synchronize {
47
+ @resource_added += resources
48
+ }
49
+ end
50
+
51
+ def resources_remove(resources)
52
+ @s3.synchronize {
53
+ @resource_removed += resources
54
+ }
55
+ end
56
+
57
+ def resources_enter(resources, baseStationRid)
58
+ @s4.synchronize {
59
+ if @resource_entered[baseStationRid] == nil
60
+ @resource_entered[baseStationRid] = []
61
+ end
62
+ @resource_entered[baseStationRid] += resources
63
+ }
64
+ end
65
+
66
+ def resources_exit(resources, baseStationRid)
67
+ @s5.synchronize {
68
+ if @resource_exited[baseStationRid] == nil
69
+ @resource_exited[baseStationRid] = []
70
+ end
71
+ @resource_exited[baseStationRid] += resources
72
+ }
73
+ end
74
+
75
+ def publish_update(app_id, run_id)
76
+ @s6.synchronize {
77
+ if @resource_updated.length > 0
78
+ nutella.f.net.publish_to_run(app_id, run_id, 'location/resources/updated', {:resources => @resource_updated.values})
79
+ @resource_updated = {}
80
+ end
81
+ }
82
+ end
83
+
84
+ def publish_add(app_id, run_id)
85
+ @s7.synchronize {
86
+ if @resource_added.length > 0
87
+ nutella.f.net.publish_to_run(app_id, run_id, 'location/resources/added', {:resources => @resource_added})
88
+ @resource_added = []
89
+ end
90
+ }
91
+ end
92
+
93
+ def publish_remove(app_id, run_id)
94
+ @s8.synchronize {
95
+ if @resource_removed.length > 0
96
+ nutella.f.net.publish_to_run(app_id, run_id, 'location/resources/removed', {:resources => @resource_removed})
97
+ @resource_removed = []
98
+ end
99
+ }
100
+ end
101
+
102
+ def publish_enter(app_id, run_id)
103
+ @s9.synchronize {
104
+ @resource_entered.each do |baseStationRid, resources|
105
+ nutella.f.net.publish_to_run(app_id, run_id, "location/resource/static/#{baseStationRid}/enter", {'resources' => resources})
106
+ end
107
+ @resource_entered = {}
108
+ }
109
+ end
110
+
111
+ def publish_exit(app_id, run_id)
112
+ @s10.synchronize {
113
+ @resource_exited.each do |baseStationRid, resources|
114
+ nutella.f.net.publish_to_run(app_id, run_id, "location/resource/static/#{baseStationRid}/exit", {'resources' => resources})
115
+ end
116
+ @resource_exited = {}
117
+ }
118
+ end
119
+
120
+ end
121
+
122
+ $cache = RoomPlacesCachePublish.new
123
+
124
+ puts 'Room places initialization'
125
+
126
+ # Open the resources database
127
+ #$resources = nutella.f.persist.get_mongo_object_store('resources')
128
+ #$groups = nutella.f.persist.get_mongo_object_store('groups')
129
+ #$room = nutella.f.persist.get_mongo_object_store('room')
130
+ #$discrete_tracking = nutella.f.persist.get_mongo_object_store('discrete_tracking')
131
+
132
+ # Create new resource
133
+ nutella.f.net.subscribe_to_all_runs('location/resource/add', lambda do |message, app_id, run_id, from|
134
+ # Persistent data
135
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
136
+
137
+ rid = message['rid']
138
+ type = message['type']
139
+ model = message['model']
140
+ proximity_range = message['proximity_range']
141
+
142
+ if proximity_range == nil
143
+ proximity_range = 0
144
+ end
145
+
146
+ if rid != nil && type != nil && model != nil
147
+ if resources[rid] == nil
148
+ if type == 'STATIC'
149
+ resources[rid]={:rid => rid,
150
+ :type => type,
151
+ :model => model,
152
+ :proximity_range => proximity_range,
153
+ :parameters => {}
154
+ };
155
+ elsif type == 'DYNAMIC'
156
+ resources[rid]={:rid => rid,
157
+ :type => type,
158
+ :model => model,
159
+ :parameters => {}
160
+ }
161
+ end
162
+ publishResourceAdd(resources[rid])
163
+ $cache.publish_add(app_id, run_id)
164
+ puts('Added resource')
165
+ end
166
+
167
+ end
168
+ end)
169
+
170
+ # Remove resource
171
+ nutella.f.net.subscribe_to_all_runs('location/resource/remove', lambda do |message, app_id, run_id, from|
172
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
173
+
174
+ rid = message['rid']
175
+ if rid != nil
176
+
177
+ resourceCopy = resources[rid]
178
+ resources.delete(rid)
179
+ publishResourceRemove(resourceCopy)
180
+ $cache.publish_remove(app_id, run_id)
181
+ puts('Removed resource')
182
+
183
+ end
184
+ end)
185
+
186
+
187
+ # Update the location of the resources
188
+ nutella.f.net.subscribe_to_all_runs('location/resource/update', lambda do |message, app_id, run_id, from|
189
+ updateResource(app_id, run_id, message)
190
+
191
+ $cache.publish_update(app_id, run_id)
192
+ $cache.publish_exit(app_id, run_id)
193
+ $cache.publish_enter(app_id, run_id)
194
+ end)
195
+
196
+ # Update the location of the resources
197
+ nutella.f.net.subscribe_to_all_runs('location/resources/update', lambda do |message, app_id, run_id, from|
198
+ resources = message['resources']
199
+ if resources != nil
200
+ resources.each do |resource|
201
+ updateResource(app_id, run_id, resource)
202
+ end
203
+ end
204
+
205
+ $cache.publish_update(app_id, run_id)
206
+ $cache.publish_exit(app_id, run_id)
207
+ $cache.publish_enter(app_id, run_id)
208
+ end)
209
+
210
+ def updateResource(app_id, run_id, updatedResource)
211
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
212
+ room = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'room')
213
+ discrete_tracking = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'discrete_tracking')
214
+
215
+ rid = updatedResource['rid']
216
+ type = updatedResource['type']
217
+ proximity = updatedResource['proximity']
218
+ discrete = updatedResource['discrete']
219
+ continuous = updatedResource['continuous']
220
+ parameters = updatedResource['parameters']
221
+ proximity_range = updatedResource['proximity_range']
222
+ resource = nil
223
+
224
+ # Retrieve $room data
225
+ r = {}
226
+
227
+ if room['x'] == nil || room['y'] == nil
228
+ r['x'] = 10
229
+ r['y'] = 7
230
+ else
231
+ r['x'] = room['x']
232
+ r['y'] = room['y']
233
+ end
234
+
235
+ if room['z'] != nil
236
+ r['z'] = room['z']
237
+ end
238
+
239
+
240
+ resource = resources[rid]
241
+
242
+ if resource == nil
243
+ return
244
+ end
245
+
246
+ if proximity != nil && proximity['rid'] != nil && proximity['distance'] != nil
247
+ baseStation = resources[proximity['rid']]
248
+
249
+ if baseStation != nil
250
+
251
+ if baseStation['proximity_range'] >= proximity['distance']
252
+ if resource['proximity'] != nil && resource['proximity']['rid'] && resource['proximity']['distance']
253
+ oldBaseStationRid = resource['proximity']['rid']
254
+ if resource['proximity']['rid'] != proximity['rid']
255
+ resource['proximity'] = proximity
256
+ resource['proximity']['timestamp'] = Time.now.to_f
257
+ publishResourceExit(resource, oldBaseStationRid)
258
+ publishResourceEnter(resource, resource['proximity']['rid'])
259
+ else
260
+ resource['proximity'] = proximity
261
+ resource['proximity']['timestamp'] = Time.now.to_f
262
+ end
263
+ computeResourceUpdate(app_id, run_id, oldBaseStationRid)
264
+ else
265
+ resource['proximity'] = proximity
266
+ resource['proximity']['timestamp'] = Time.now.to_f
267
+ publishResourceEnter(resource, resource['proximity']['rid'])
268
+ end
269
+ end
270
+ end
271
+ elsif proximity == nil
272
+ resource.delete('proximity')
273
+ else
274
+ resource['proximity'] = {}
275
+ end
276
+
277
+ if continuous != nil
278
+ if continuous['x'] > r['x']
279
+ continuous['x'] = r['x']
280
+ end
281
+ if continuous['x'] < 0
282
+ continuous['x'] = 0
283
+ end
284
+ if continuous['y'] > r['y']
285
+ continuous['y'] = r['y']
286
+ end
287
+ if continuous['y'] < 0
288
+ continuous['y'] = 0
289
+ end
290
+
291
+ resource['continuous'] = continuous
292
+ else
293
+ if resource != nil && resource['continuous'] != nil
294
+ resource.delete('continuous');
295
+ end
296
+ end
297
+
298
+ if discrete_tracking['x'] != nil
299
+ if discrete != nil
300
+
301
+ # Translate all coordinates in numbers
302
+ if discrete['x'].instance_of? String
303
+ discrete['x'] = discrete['x'].downcase.ord - 'a'.ord
304
+ end
305
+ if discrete['y'].instance_of? String
306
+ discrete['y'] = discrete['y'].downcase.ord - 'a'.ord
307
+ end
308
+
309
+
310
+ if discrete['x'] > discrete_tracking['n_x'] - 1
311
+ discrete['x'] = discrete_tracking['n_x'] - 1
312
+ end
313
+ if discrete['x'] < 0
314
+ discrete['x'] = 0
315
+ end
316
+ if discrete['y'] > discrete_tracking['n_y'] - 1
317
+ discrete['y'] = discrete_tracking['n_y'] - 1
318
+ end
319
+ if discrete['y'] < 0
320
+ discrete['y'] = 0
321
+ end
322
+
323
+ resource['discrete'] = discrete
324
+ else
325
+ if resource != nil && resource['discrete'] != nil
326
+ resource.delete('discrete');
327
+ end
328
+ end
329
+ end
330
+
331
+ if parameters != nil
332
+ ps = resource['parameters']
333
+ for parameter in parameters
334
+ if parameter['delete'] != nil
335
+ ps.delete(parameter['key'])
336
+ else
337
+ puts "--------"
338
+ puts parameter['key']
339
+ puts parameter['value']
340
+ ps[parameter['key']] = parameter['value']
341
+ end
342
+ end
343
+ resource['parameters'] = ps
344
+ end
345
+
346
+ if type != nil
347
+ puts 'Update type'
348
+
349
+ if type == 'STATIC'
350
+ resource['type'] = type
351
+ resource.delete('proximity')
352
+ if proximity_range == nil
353
+ resource['proximity_range'] = 1;
354
+ end
355
+ end
356
+
357
+ if type == 'DYNAMIC'
358
+ resource['type'] = type
359
+ resource.delete('proximity_range')
360
+ end
361
+
362
+ puts 'Stored resource'
363
+ end
364
+
365
+ if proximity_range != nil
366
+ puts 'Update proximity range'
367
+
368
+ if resource['type'] == 'STATIC'
369
+ resource['proximity_range'] = proximity_range
370
+ end
371
+
372
+ puts 'Stored resource'
373
+
374
+ end
375
+
376
+ if proximity == nil && discrete == nil && continuous == nil && parameters == nil
377
+
378
+ resource.delete('proximity')
379
+ resource.delete('continuous')
380
+ resource.delete('discrete')
381
+
382
+ puts 'Stored resource'
383
+
384
+ end
385
+
386
+ resources[rid]=resource
387
+ computeResourceUpdate(app_id, run_id, rid)
388
+
389
+ end
390
+
391
+ # Request the position of a single resource
392
+ nutella.f.net.handle_requests_on_all_runs('location/resources', lambda do |request, app_id, run_id, from|
393
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
394
+ groups = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'groups')
395
+
396
+ puts 'Send list of resources'
397
+
398
+ rid = request['rid']
399
+ group = request['group']
400
+ reply = nil
401
+ if rid != nil
402
+ reply = resources[rid]
403
+
404
+ reply
405
+ elsif group != nil
406
+ rs = []
407
+ reply = []
408
+ for resource in groups[group]['resources']
409
+ rs.push(resource)
410
+ end
411
+
412
+ for r in rs
413
+ resource = resources[resource]
414
+ # Translate discrete coordinate
415
+ if resource['discrete'] != nil
416
+ resource['discrete'] = translateDiscreteCoordinates(resource['discrete'])
417
+ end
418
+ reply.push(resource)
419
+
420
+ end
421
+ {:resources => reply}
422
+ else
423
+ resourceList = []
424
+
425
+ resources.to_h.each do |_, resource|
426
+ # Translate discrete coordinate
427
+ if resource['discrete'] != nil
428
+ resource['discrete'] = translateDiscreteCoordinates(resource['discrete'])
429
+ end
430
+ resourceList.push(resource)
431
+ end
432
+
433
+ {:resources => resourceList}
434
+ end
435
+ end)
436
+
437
+ # Update the room size
438
+ nutella.f.net.subscribe_to_all_runs('location/room/update', lambda do |message, app_id, run_id, from|
439
+ room = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'room')
440
+
441
+ x = message['x']
442
+ y = message['y']
443
+ z = message['z']
444
+
445
+ if x != nil && y != nil
446
+ r = {}
447
+ room['x'] = x
448
+ r['x'] = x
449
+
450
+ room['y'] = y
451
+ r['y'] = y
452
+
453
+ if z != nil
454
+ room['z'] = z
455
+ r['z'] = z
456
+ end
457
+
458
+ publishRoomUpdate(app_id, run_id, r)
459
+ puts 'Room updated'
460
+ end
461
+ end)
462
+
463
+ # Compute and publish resource
464
+ def computeResourceUpdate(app_id, run_id, rid)
465
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
466
+
467
+ resource = nil
468
+
469
+ resource = resources[rid]
470
+
471
+ if resource != nil
472
+ if resource['proximity'] != nil
473
+ puts 'Proximity resource detected: take coordinates base station'
474
+
475
+ if resource['proximity']['rid'] != nil
476
+ puts 'Search for base station ' + resource['proximity']['rid']
477
+ baseStation = nil
478
+ baseStation = resources[resource['proximity']['rid']]
479
+
480
+ if baseStation != nil && baseStation['continuous'] != nil
481
+ puts 'Copy continuous position base station'
482
+ resource['proximity']['continuous'] = baseStation['continuous']
483
+
484
+ # Update basic station
485
+ computeResourceUpdate(app_id, run_id, resource['proximity']['rid'])
486
+ else
487
+ puts 'Continuous position not present'
488
+ end
489
+
490
+ if baseStation != nil && baseStation['discrete'] != nil
491
+ puts 'Copy discrete position base station'
492
+ resource['proximity']['discrete'] = baseStation['discrete']
493
+ else
494
+ puts 'Discrete position not present'
495
+ end
496
+ end
497
+ end
498
+
499
+ resources[rid] = resource
500
+
501
+ =begin
502
+ if resource['continuous'] != nil
503
+ counter = 0 # Number of proximity beacons tracked from this station
504
+ for r in $resources.keys()
505
+ resource2 = $resources[r]
506
+ if resource2['proximity'] != nil && resource2['proximity']['rid'] == resource['rid']
507
+ counter += 1
508
+ resource2['proximity']['continuous'] = resource['continuous']
509
+ $resources[r] = resource2
510
+ publishResourceUpdate(resource2)
511
+ end
512
+ end
513
+ puts counter
514
+ resource['number_resources'] = counter
515
+ end
516
+ =end
517
+
518
+ # Translate discrete coordinate
519
+ if resource['discrete'] != nil
520
+ resource['discrete'] = translateDiscreteCoordinates(resource['discrete'])
521
+ end
522
+
523
+ # Send update
524
+ publishResourceUpdate(resource)
525
+ puts 'Sent update'
526
+
527
+ end
528
+ end
529
+
530
+ def translateDiscreteCoordinates(discrete)
531
+ discrete_tracking = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'discrete_tracking')
532
+
533
+ if discrete != nil && discrete_tracking['t_x'] != nil && discrete_tracking['t_y'] != nil
534
+ if discrete_tracking['t_x'] == 'LETTER'
535
+ discrete['x'] = (discrete['x'] + 'a'.ord).chr
536
+ end
537
+ if discrete_tracking['t_y'] == 'LETTER'
538
+ discrete['y'] = (discrete['y'] + 'a'.ord).chr
539
+ end
540
+ end
541
+ discrete
542
+ end
543
+
544
+ # Update the room size
545
+ nutella.f.net.subscribe_to_all_runs('location/tracking/discrete/update', lambda do |message, app_id, run_id, from|
546
+
547
+ discrete_tracking = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'discrete_tracking')
548
+ tracking = message['tracking']
549
+
550
+ if tracking != nil
551
+ x = tracking['x']
552
+ y = tracking['y']
553
+ width = tracking['width']
554
+ height = tracking['height']
555
+ n_x = tracking['n_x']
556
+ n_y = tracking['n_y']
557
+ t_x = tracking['t_x']
558
+ t_y = tracking['t_y']
559
+
560
+ if x != nil && y != nil && width != nil && height != nil && n_x != nil && n_y != nil && t_x != nil && t_y != nil
561
+ discrete_tracking['x'] = x
562
+ discrete_tracking['y'] = y
563
+ discrete_tracking['width'] = width
564
+ discrete_tracking['height'] = height
565
+ discrete_tracking['n_x'] = n_x
566
+ discrete_tracking['n_y'] = n_y
567
+ discrete_tracking['t_x'] = t_x
568
+ discrete_tracking['t_y'] = t_y
569
+ else
570
+ discrete_tracking['x'] = nil
571
+ discrete_tracking['y'] = nil
572
+ discrete_tracking['width'] = nil
573
+ discrete_tracking['height'] = nil
574
+ discrete_tracking['n_x'] = nil
575
+ discrete_tracking['n_y'] = nil
576
+ discrete_tracking['t_x'] = nil
577
+ discrete_tracking['t_y'] = nil
578
+ end
579
+
580
+ publishDiscreteUpdate(app_id, run_id)
581
+ end
582
+
583
+ end)
584
+
585
+
586
+ # Publish an added resource
587
+ def publishResourceAdd(resource)
588
+ $cache.resources_add([resource])
589
+ #nutella.net.publish('location/resources/added', {:resources => [resource]})
590
+ end
591
+
592
+ # Publish a removed resource
593
+ def publishResourceRemove(resource)
594
+ $cache.resources_remove([resource])
595
+ #nutella.net.publish('location/resources/removed', {:resources => [resource]})
596
+ end
597
+
598
+ # Publish an updated resource
599
+ def publishResourceUpdate(resource)
600
+ $cache.resources_update([resource])
601
+ #nutella.net.publish('location/resources/updated', {:resources => [resource]})
602
+ end
603
+
604
+ # Publish an updated room
605
+ def publishRoomUpdate(app_id, run_id, room)
606
+ nutella.f.net.publish_to_run(app_id, run_id, 'location/room/updated', room)
607
+ end
608
+
609
+ # Publish resources enter base station proximity area
610
+ def publishResourcesEnter(resources, baseStationRid)
611
+ #message = {:resources => resources}
612
+ #nutella.net.publish("location/resource/static/#{baseStationRid}/enter", message)
613
+ $cache.resources_enter(resources, baseStationRid)
614
+ end
615
+
616
+ # Publish resources exit base station proximity area
617
+ def publishResourcesExit(resources, baseStationRid)
618
+ #message = {:resources => resources}
619
+ #nutella.net.publish("location/resource/static/#{baseStationRid}/exit", message)
620
+ $cache.resources_exit(resources, baseStationRid)
621
+ end
622
+
623
+ # Publish resource enter base station proximity area
624
+ def publishResourceEnter(resource, baseStationRid)
625
+ publishResourcesEnter([resource], baseStationRid)
626
+ end
627
+
628
+ # Publish resource enter base station proximity area
629
+ def publishResourceExit(resource, baseStationRid)
630
+ publishResourcesExit([resource], baseStationRid)
631
+ end
632
+
633
+ # Publish tracking system update
634
+ def publishDiscreteUpdate(app_id, run_id)
635
+
636
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
637
+ discrete_tracking = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'discrete_tracking')
638
+
639
+ x = discrete_tracking['x']
640
+ y = discrete_tracking['y']
641
+ width = discrete_tracking['width']
642
+ height = discrete_tracking['height']
643
+ n_x = discrete_tracking['n_x']
644
+ n_y = discrete_tracking['n_y']
645
+ t_x = discrete_tracking['t_x']
646
+ t_y = discrete_tracking['t_y']
647
+
648
+ if x != nil && y != nil && width != nil && height != nil && n_x != nil && n_y != nil && t_x != nil && t_y != nil
649
+ message = {
650
+ :x => x,
651
+ :y => y,
652
+ :width => width,
653
+ :height => height,
654
+ :n_x => n_x,
655
+ :n_y => n_y,
656
+ :t_x => t_x,
657
+ :t_y => t_y
658
+ }
659
+ nutella.net.publish_to_run(app_id, run_id, 'location/tracking/discrete/updated', {:tracking => message})
660
+
661
+ # Update all the discrete resources
662
+ resources.to_h.each do |_, resource|
663
+ resource = resources[resource]
664
+ if resource['discrete'] != nil
665
+ computeResourceUpdate(app_id, run_id, resource)
666
+ end
667
+ end
668
+
669
+ else
670
+ nutella.net.publish_to_run(app_id, run_id, 'location/tracking/discrete/updated', {:tracking => {}})
671
+ end
672
+
673
+ end
674
+
675
+ # Request the size of the room
676
+ nutella.f.net.handle_requests_on_all_runs('location/room', lambda do |request, app_id, run_id, from|
677
+ room = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'room')
678
+ puts 'Send the room dimension'
679
+
680
+ r = {}
681
+
682
+ if room['x'] == nil || room['y'] == nil
683
+ r['x'] = 10
684
+ r['y'] = 7
685
+ else
686
+ r['x'] = room['x']
687
+ r['y'] = room['y']
688
+ end
689
+
690
+ if room['z'] != nil
691
+ r['z'] = room['z']
692
+ end
693
+
694
+ r
695
+ end)
696
+
697
+ # Request discrete tracking system
698
+ nutella.f.net.handle_requests_on_all_runs('location/tracking/discrete', lambda do |request, app_id, run_id, from|
699
+
700
+ discrete_tracking = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'discrete_tracking')
701
+
702
+ puts 'Send the discrete tracking system'
703
+
704
+ x = discrete_tracking['x']
705
+ y = discrete_tracking['y']
706
+ width = discrete_tracking['width']
707
+ height = discrete_tracking['height']
708
+ n_x = discrete_tracking['n_x']
709
+ n_y = discrete_tracking['n_y']
710
+ t_x = discrete_tracking['t_x']
711
+ t_y = discrete_tracking['t_y']
712
+
713
+ if x != nil && y != nil && width != nil && height != nil && n_x != nil && n_y != nil && t_x != nil && t_y != nil
714
+ tracking = {
715
+ :x => x,
716
+ :y => y,
717
+ :width => width,
718
+ :height => height,
719
+ :n_x => n_x,
720
+ :n_y => n_y,
721
+ :t_x => t_x,
722
+ :t_y => t_y
723
+ }
724
+ {:tracking => tracking}
725
+ else
726
+ {:tracking => {}}
727
+ end
728
+ end)
729
+
730
+ puts 'Initialization completed'
731
+
732
+ # Routine that delete old proximity beacons
733
+
734
+ while sleep 0.5
735
+
736
+ Nutella.runlist.all_apps.each do |app_id|
737
+ Nutella.runlist.runs_for_app(app_id).each do |run_id|
738
+ baseStations = []
739
+ resources = nutella.f.persist.get_run_mongo_object_store(app_id, run_id, 'resources')
740
+
741
+ resources.to_h.each do |_, resource|
742
+ if resource['proximity'] != nil && resource['proximity']['timestamp'] != nil
743
+ if Time.now.to_f - resource['proximity']['timestamp'] > 3.0
744
+ if resource['proximity']['rid'] != nil
745
+ baseStations.push(resource['proximity']['rid'])
746
+ publishResourceExit(resource, resource['proximity']['rid'])
747
+ end
748
+ resource['proximity'] = {}
749
+ resources[resource['rid']] = resource
750
+ puts 'Delete proximity resource'
751
+ publishResourceUpdate(resource)
752
+ end
753
+ end
754
+ end
755
+
756
+ # Update the counters of the base stations
757
+ for baseStation in baseStations
758
+ computeResourceUpdate(app_id, run_id, baseStation)
759
+ end
760
+
761
+ $cache.publish_update(app_id, run_id)
762
+ $cache.publish_exit(app_id, run_id)
763
+ $cache.publish_enter(app_id, run_id)
764
+ end
765
+ end
766
+
767
+ end
768
+
769
+ # Just sit there waiting for messages to come
770
+ nutella.net.listen
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+
3
+ BASEDIR=$(dirname $0)
4
+
5
+ ruby $BASEDIR/room_places_bot.rb > /dev/null 2>&1 &
6
+ echo $! > $BASEDIR/.pid
@@ -0,0 +1,124 @@
1
+ require 'nutella_lib'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'json'
6
+
7
+ # Parse command line arguments
8
+ run_id, broker = nutella.parse_args ARGV
9
+
10
+ baseStationRid = 'iPad2'
11
+ beaconRid = 'beacon1'
12
+
13
+ # Parse command line arguments
14
+ broker, app_id, run_id = nutella.parse_args ARGV
15
+ # Extract the component_id
16
+ component_id = nutella.extract_component_id
17
+ # Initialize nutella
18
+ nutella.init(broker, app_id, run_id, component_id)
19
+
20
+
21
+ puts 'Virtual beacon initialization'
22
+
23
+ # Publish an updated resource
24
+ def publishResourceUpdate(baseStationRid, beaconRid, distance)
25
+ nutella.net.publish('location/resource/update', {
26
+ 'rid' => beaconRid,
27
+ 'proximity' => {
28
+ 'rid' => baseStationRid,
29
+ 'distance' => distance
30
+ }
31
+ })
32
+ end
33
+
34
+ def publishResourcesUpdate(baseStationsRid, beaconsRid, distance)
35
+ resources = []
36
+
37
+ baseStationsRid.each_with_index do |baseStationRid, i|
38
+ resources << {
39
+ 'rid' => beaconsRid[i],
40
+ 'proximity' => {
41
+ 'rid' => baseStationRid,
42
+ 'distance' => distance
43
+ }
44
+ }
45
+ end
46
+
47
+ nutella.net.publish('location/resources/update', {'resources' => resources} )
48
+ end
49
+
50
+ d1 = ["vb1",
51
+ "vb2",
52
+ "vb3",
53
+ "vb4",
54
+ "vb5",
55
+ "vb6",
56
+ "vb7",
57
+ "vb8",
58
+ "vb9",
59
+ "vb10"
60
+ ]
61
+
62
+ d2 = ["vb11",
63
+ "vb12",
64
+ "vb13",
65
+ "vb14",
66
+ "vb15",
67
+ "vb16",
68
+ "vb17",
69
+ "vb18",
70
+ "vb19",
71
+ "vb20"
72
+ ]
73
+
74
+ d3 = ["vb21",
75
+ "vb22",
76
+ "vb23",
77
+ "vb24",
78
+ "vb25",
79
+ "vb26",
80
+ "vb27",
81
+ "vb28",
82
+ "vb29",
83
+ "vb30"
84
+ ]
85
+
86
+ d4 = ["vb31",
87
+ "vb32",
88
+ "vb33",
89
+ "vb34",
90
+ "vb35",
91
+ "vb36",
92
+ "vb37",
93
+ "vb38",
94
+ "vb39",
95
+ "vb40"
96
+ ]
97
+
98
+ # Routine that delete old proximity beacons
99
+ Thread.new do
100
+ i = 0
101
+ while true do
102
+ #publishResourceUpdate("Table1", "beacon1", 1.0);
103
+ puts ">"
104
+ if i % 2 == 0
105
+ puts "Table1"
106
+ publishResourcesUpdate(["Table1"]*10, d1, 0.5)
107
+ else
108
+ puts "Table2"
109
+ publishResourcesUpdate(["Table2"]*10, d1, 0.5)
110
+ end
111
+
112
+ i += 1
113
+
114
+ #publishResourcesUpdate(["Table2"]*10, d2, rand(10...100)/60);
115
+ #publishResourcesUpdate(["Table3"]*10, d3, rand(10...100)/60);
116
+ #publishResourcesUpdate(["Table4"]*10, d4, rand(10...100)/60);
117
+ sleep 1
118
+ end
119
+ end
120
+
121
+ puts "Initialization completed"
122
+
123
+ # Just sit there waiting for messages to come
124
+ nutella.net.listen
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: nutella_framework 0.4.25 ruby lib
5
+ # stub: nutella_framework 0.4.27 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "nutella_framework"
9
- s.version = "0.4.25"
9
+ s.version = "0.4.27"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Alessandro Gnoli"]
14
- s.date = "2015-05-16"
14
+ s.date = "2015-05-17"
15
15
  s.description = "utella is a framework to create and run RoomApps"
16
16
  s.email = "tebemis@gmail.com"
17
17
  s.executables = ["nutella"]
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  "README.md",
28
28
  "Rakefile",
29
29
  "VERSION",
30
+ "VERSION.orig",
30
31
  "bin/nutella",
31
32
  "data/index.html",
32
33
  "data/startup",
@@ -211,6 +212,13 @@ Gem::Specification.new do |s|
211
212
  "framework_components/monitoring-interface/js/view-controller/window-view-controller.js",
212
213
  "framework_components/monitoring-interface/nutella.json",
213
214
  "framework_components/order.json",
215
+ "framework_components/room-places-bot/.gitignore",
216
+ "framework_components/room-places-bot/Gemfile",
217
+ "framework_components/room-places-bot/README.md",
218
+ "framework_components/room-places-bot/nutella.json",
219
+ "framework_components/room-places-bot/room_places_bot.rb",
220
+ "framework_components/room-places-bot/startup",
221
+ "framework_components/room-places-bot/virtual_beacons.rb",
214
222
  "framework_components/roomcast-bot/data/default/channels.json",
215
223
  "framework_components/roomcast-bot/data/default/configs.json",
216
224
  "framework_components/roomcast-bot/roomcast_bot.rb",
@@ -440,6 +448,7 @@ Gem::Specification.new do |s|
440
448
  "lib/logging/nutella_logging.rb",
441
449
  "lib/nutella_framework.rb",
442
450
  "lib/tmux/tmux.rb",
451
+ "nutella_framework.gemspec",
443
452
  "nutella_lib/framework_core.rb",
444
453
  "nutella_lib/framework_log.rb",
445
454
  "nutella_lib/framework_net.rb",
@@ -470,7 +479,7 @@ Gem::Specification.new do |s|
470
479
  s.add_runtime_dependency(%q<thin>, ["~> 1.6"])
471
480
  s.add_runtime_dependency(%q<nokogiri>, ["~> 1.6"])
472
481
  s.add_runtime_dependency(%q<slop>, ["~> 4.0"])
473
- s.add_runtime_dependency(%q<nutella_lib>, [">= 0.4.12", "~> 0.4"])
482
+ s.add_runtime_dependency(%q<nutella_lib>, [">= 0.4.14", "~> 0.4"])
474
483
  s.add_runtime_dependency(%q<activesupport>, ["~> 4.2"])
475
484
  s.add_runtime_dependency(%q<mandrill-api>, [">= 1.0.53", "~> 1.0"])
476
485
  s.add_runtime_dependency(%q<bson>, ["~> 3.0"])
@@ -489,7 +498,7 @@ Gem::Specification.new do |s|
489
498
  s.add_dependency(%q<thin>, ["~> 1.6"])
490
499
  s.add_dependency(%q<nokogiri>, ["~> 1.6"])
491
500
  s.add_dependency(%q<slop>, ["~> 4.0"])
492
- s.add_dependency(%q<nutella_lib>, [">= 0.4.12", "~> 0.4"])
501
+ s.add_dependency(%q<nutella_lib>, [">= 0.4.14", "~> 0.4"])
493
502
  s.add_dependency(%q<activesupport>, ["~> 4.2"])
494
503
  s.add_dependency(%q<mandrill-api>, [">= 1.0.53", "~> 1.0"])
495
504
  s.add_dependency(%q<bson>, ["~> 3.0"])
@@ -509,7 +518,7 @@ Gem::Specification.new do |s|
509
518
  s.add_dependency(%q<thin>, ["~> 1.6"])
510
519
  s.add_dependency(%q<nokogiri>, ["~> 1.6"])
511
520
  s.add_dependency(%q<slop>, ["~> 4.0"])
512
- s.add_dependency(%q<nutella_lib>, [">= 0.4.12", "~> 0.4"])
521
+ s.add_dependency(%q<nutella_lib>, [">= 0.4.14", "~> 0.4"])
513
522
  s.add_dependency(%q<activesupport>, ["~> 4.2"])
514
523
  s.add_dependency(%q<mandrill-api>, [">= 1.0.53", "~> 1.0"])
515
524
  s.add_dependency(%q<bson>, ["~> 3.0"])
@@ -65,7 +65,13 @@ module Nutella
65
65
  # @param [String] name the name of the store
66
66
  # @return [MongoPersistedCollection] a MongoDB-backed collection store
67
67
  def self.get_run_mongo_collection_store( app_id, run_id, name )
68
- MongoPersistedCollection.new Nutella.mongo_host, app_id, "#{run_id}/#{name}"
68
+ if @run_stores.nil?
69
+ @run_stores = {}
70
+ end
71
+ unless @run_stores.include? [app_id, run_id, name]
72
+ @run_stores[[app_id, run_id, name]] = MongoPersistedCollection.new Nutella.mongo_host, app_id, "#{run_id}/#{name}"
73
+ end
74
+ @run_stores[[app_id, run_id, name]]
69
75
  end
70
76
 
71
77
  # This method returns a MongoDB-backed store
@@ -75,7 +81,13 @@ module Nutella
75
81
  # @param [String] name the name of the store
76
82
  # @return [MongoPersistedHash] a MongoDB-backed Hash store
77
83
  def self.get_run_mongo_object_store( app_id, run_id, name )
78
- MongoPersistedHash.new Nutella.mongo_host, app_id, 'run_persisted_hashes', "#{run_id}/#{name}"
84
+ if @run_stores.nil?
85
+ @run_stores = {}
86
+ end
87
+ unless @run_stores.include? [app_id, run_id, name]
88
+ @run_stores[[app_id, run_id, name]] = MongoPersistedHash.new Nutella.mongo_host, app_id, 'run_persisted_hashes', "#{run_id}/#{name}"
89
+ end
90
+ @run_stores[[app_id, run_id, name]]
79
91
  end
80
92
 
81
93
  # This method returns a JSON-file-backed store
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nutella_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.26
4
+ version: 0.4.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Gnoli
@@ -475,6 +475,13 @@ files:
475
475
  - framework_components/monitoring-interface/js/view-controller/window-view-controller.js
476
476
  - framework_components/monitoring-interface/nutella.json
477
477
  - framework_components/order.json
478
+ - framework_components/room-places-bot/.gitignore
479
+ - framework_components/room-places-bot/Gemfile
480
+ - framework_components/room-places-bot/README.md
481
+ - framework_components/room-places-bot/nutella.json
482
+ - framework_components/room-places-bot/room_places_bot.rb
483
+ - framework_components/room-places-bot/startup
484
+ - framework_components/room-places-bot/virtual_beacons.rb
478
485
  - framework_components/roomcast-bot/data/default/channels.json
479
486
  - framework_components/roomcast-bot/data/default/configs.json
480
487
  - framework_components/roomcast-bot/roomcast_bot.rb