nutella_framework 0.4.26 → 0.4.27

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.
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