ardtweeno 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +37 -0
  3. data/Gemfile.lock +26 -16
  4. data/README.md +15 -11
  5. data/lib/ardtweeno/configreader.rb +1 -1
  6. data/lib/ardtweeno/dispatcher.rb +253 -31
  7. data/lib/ardtweeno/exceptions.rb +6 -0
  8. data/lib/ardtweeno/nodemanager.rb +13 -7
  9. data/lib/ardtweeno/restapi.rb +68 -21
  10. data/lib/ardtweeno/serialparser.rb +57 -105
  11. data/lib/ardtweeno.rb +15 -9
  12. data/public/bootstrap.min.js +6 -0
  13. data/public/highcharts.js +270 -0
  14. data/public/jquery-1.8.2.min.js +2 -0
  15. data/public/jquery-2.0.1.min.js +6 -0
  16. data/public/main.css +338 -3
  17. data/public/main.js +30 -0
  18. data/resources/conf.yaml +2 -13
  19. data/resources/posts.yaml +7 -0
  20. data/test/api_test.rb +29 -7
  21. data/test/{run_mock → debug/run_mock} +0 -0
  22. data/test/{run_packet_push → debug/run_packet_push} +3 -3
  23. data/test/debug/run_post_watch +12 -0
  24. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/AUTHORS +0 -0
  25. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/COPYING +0 -0
  26. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/INSTALL +0 -0
  27. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/README +0 -0
  28. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/THANKS +0 -0
  29. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/TODO +0 -0
  30. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/VERSION +0 -0
  31. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/Makefile +0 -0
  32. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/Module.symvers +0 -0
  33. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/modules.order +0 -0
  34. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/tty0tty.c +0 -0
  35. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/tty0tty.ko +0 -0
  36. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/tty0tty.mod.c +0 -0
  37. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/tty0tty.mod.o +0 -0
  38. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/module/tty0tty.o +0 -0
  39. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/pts/Makefile +0 -0
  40. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/pts/tty0tty +0 -0
  41. data/test/{tty0tty-1.1 → debug/tty0tty-1.1}/pts/tty0tty.c +0 -0
  42. data/test/dispatcher_test.rb +116 -2
  43. data/test/nodemanager_test.rb +9 -0
  44. data/test/parser_test.rb +35 -92
  45. data/test/rest_api_test.rb +45 -15
  46. data/test/serialport_mock.rb +4 -4
  47. data/test/test_helper.rb +9 -3
  48. data/views/createpost.erb +48 -39
  49. data/views/home.erb +25 -57
  50. data/views/index.erb +54 -0
  51. data/views/status.erb +158 -0
  52. metadata +144 -28
  53. data/public/glossy_green_button.svg +0 -123
  54. data/public/glossy_red_button.svg +0 -75
  55. data/public/raspberrypi.jpg +0 -0
  56. data/resources/serialparser.js +0 -84
  57. data/test/post_watch +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63968507920512729a01dd5e5952ce70b427bf99
4
- data.tar.gz: 00a74be7f57bded6c488096b3c49bc3b4ee8eb82
3
+ metadata.gz: 3abb91d978d43c56436afbc005878c6cb591018a
4
+ data.tar.gz: cbb7970eebe1b05f14343ae2f0440415797a9451
5
5
  SHA512:
6
- metadata.gz: b781f4581fb7f475cfbb219f53ae547a8e618115c6e01bf922396d34143fdbfbc7955e9f3a0f6c3a9af42df5dc5e55f4eecb6855a854a7639ce24a474cc6a6d9
7
- data.tar.gz: 54ecc4d3c96a512f42d04c89e92a594b87f8b337ca089781b9fe7390972d151080cb26187b1853c54f8f3a35776b1bcc61c949099026b17bfa307387cd0444ec
6
+ metadata.gz: 3b31b31ff928b0a7583291bbffdee3807206e39d04b84598d71a5e297fb187e705c9322a343cf3ea35ed9c30f85e5fb627f6c846d1c2d6cbe2d94867454253cf
7
+ data.tar.gz: 3cddee84a5acd4cf36fdd9cf879b16fd5e4e6119389c3d815a1dc19ce32ffc7d39d3ebca65fae7d75c083ef6689581b2dabb6e8a88e622911bda7a9fbcb3e036
data/CHANGELOG CHANGED
@@ -1,3 +1,40 @@
1
+ ## Version 0.3.0
2
+ - Incorrectly assert_true against method which does not return true or false - Refs #16
3
+ - System now passes mock confdata into the options hash should the ENV['RACK_ENV'] == 'test' - Fixes #16
4
+ - The URI to the form which can add news posts to the front page is now configurable in the ~/.ardtweeno/conf.yaml file
5
+ - The system reads the variable newsURI and exposes the URI like eg: /b97cb9ae44747ee263363463b7e56/create/post - Refs #3
6
+ - Front page news posts are now serialised to ~/.ardtweeno/posts.yaml - Refs #3
7
+ - RESTAPI test fixtures were not correctly reading the mock configuration data - Fixes #15
8
+ - Refactored RESTAPI test fixtures to now use mock configuration data as intended - Fixes #15
9
+ - Fleshed out implementation for adding nodes to a watchlist
10
+ - Added test fixtures for Ardtweeno::Dispatcher#addWatch and the Ardtweeno::NodeManager#addWatch
11
+ - Added exceptions Ardtweeno::InvalidWatch and Ardtweeno::AlreadyWatched - Fixes #12
12
+ - Fixed bug in the skeleton implementation for the /api/v1/watch/node it now respects the parameters passed to it - Refs #12
13
+ - Updated README and ardtweeno-gem/README with latest changes
14
+ - Finished basic implementation and integration of the Ardtweeno::SerialParser subsystem
15
+ - Added test fixtures for Ardtweeno::SerialParser subsystem - Fixes #9
16
+ - Updated test/test_helper.rb to no longer ignore the parser_test.rb
17
+ - Removed node.js SerialParser subsystem
18
+ - Updated minimum Ruby version to 2.0.0p0 in the gemspec
19
+ - Added Twitter Bootstrap CSS and JS libraries
20
+ - Added skeleton implementation of the Ardtweeno::SerialParser subsystem
21
+ - Modified Ardtweeno::Dispatcher #start and #stop to interface with the SerialParser
22
+ - Refactored the Ardtweeno::Dispatcher#status? to be cleaner and easier to maintain in future
23
+ - Added runtime dependencies to the gemspec. Fixes #14
24
+ - Added tests to cover Ardtweeno::Dispatcher#status?
25
+ - While running tests, Ardtweeno::Dispatcher#status? now returns mock data
26
+ - Refactored the gateway front end to allow tabbed content. fixes #11 - Implemented front end news story serialisation. Will be finished alongside refs #3 - Fleshed out functionality of /api/v1/system/status to include system load information. fixes #8 - Removed need for authentication to access /api/v1/system/status - Added a status tab on the front end which contains a highcharts graph showing gateway system load
27
+ - Fixes #7 Added check for packets containing empty data, now correctly raises Ardtweeno::InvalidData
28
+ - Updated main README.md
29
+ - Updated README.md for the tech-demo
30
+ - Broke out Ardtweeno Gateway port for the tech-demo to this config file
31
+ - fixes #1 - breaks out hard coded URI's to a configuration file bundled with the tech-demo application
32
+ - Added README.md for tech-demo directory
33
+ - Added README.md for the arduino-fio-code directory
34
+ - Added README.md to eaglecad directory
35
+ - Added eagle-cad schematics for two sample Ardtweeno Sample Mesh Network Nodes
36
+ - Typo in blog URI on Ardtweeno Gateway home view
37
+
1
38
  ## Version 0.2.5 Engineering Release 2 RC5
2
39
  - Updated gemspec in preparation for release of ER 2
3
40
  - Updated REST API to be more robust when printing news posts
data/Gemfile.lock CHANGED
@@ -1,27 +1,37 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- ardtweeno (0.2.1)
4
+ ardtweeno (0.2.5)
5
+ bson_ext (>= 1.6.2)
5
6
  bundler (>= 1.2.3)
6
- bson (1.8.5)
7
- bson_ext (1.8.5)
8
- bson (~> 1.8.5)
7
+ foreman (>= 0.63.0)
8
+ mongo (>= 1.6.2)
9
+ rufus-scheduler (>= 2.0.0)
10
+ sinatra (>= 1.3.3)
11
+ sinatra (>= 1.3.3)
12
+ thin (>= 1.5.0)
13
+ typhoeus (>= 0.6.3)
14
+ bson (1.9.0)
15
+ bson_ext (1.9.0)
16
+ bson (~> 1.9.0)
9
17
  daemons (1.1.9)
10
18
  diff-lcs (1.2.4)
11
- dotenv (0.7.0)
19
+ dotenv (0.8.0)
12
20
  ethon (0.5.12)
13
21
  ffi (>= 1.3.0)
14
22
  mime-types (~> 1.18)
15
23
  eventmachine (1.0.3)
16
- ffi (1.8.1)
24
+ ffi (1.9.0)
17
25
  foreman (0.63.0)
18
26
  dotenv (>= 0.7)
19
27
  thor (>= 0.13.6)
20
- json (1.7.7)
28
+ json (1.8.0)
21
29
  mime-types (1.23)
22
- mongo (1.8.5)
23
- bson (~> 1.8.5)
24
- nokogiri (1.5.9)
30
+ mini_portile (0.5.0)
31
+ mongo (1.9.0)
32
+ bson (~> 1.9.0)
33
+ nokogiri (1.6.0)
34
+ mini_portile (~> 0.5.0)
25
35
  rack (1.5.2)
26
36
  rack-protection (1.5.0)
27
37
  rack
@@ -36,23 +46,23 @@ GEM
36
46
  rspec-expectations (2.13.0)
37
47
  diff-lcs (>= 1.1.3, < 2.0)
38
48
  rspec-mocks (2.13.1)
39
- rufus-scheduler (2.0.18)
49
+ rufus-scheduler (2.0.19)
40
50
  tzinfo (>= 0.3.23)
41
51
  serialport (1.1.0)
42
- sinatra (1.4.2)
43
- rack (~> 1.5, >= 1.5.2)
52
+ sinatra (1.4.3)
53
+ rack (~> 1.4)
44
54
  rack-protection (~> 1.4)
45
55
  tilt (~> 1.3, >= 1.3.4)
46
- test-unit (2.5.4)
56
+ test-unit (2.5.5)
47
57
  thin (1.5.1)
48
58
  daemons (>= 1.0.9)
49
59
  eventmachine (>= 0.12.6)
50
60
  rack (>= 1.0.0)
51
61
  thor (0.18.1)
52
- tilt (1.3.7)
62
+ tilt (1.4.1)
53
63
  typhoeus (0.6.3)
54
64
  ethon (~> 0.5.11)
55
- tzinfo (0.3.37)
65
+ tzinfo (1.0.0)
56
66
 
57
67
  PLATFORMS
58
68
  ruby
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # Ardtweeno
2
- Ardtweeno is a distributed sensor mesh network gateway which bridges devices connected through an XBee Mesh
3
- Network link to those on the internet over IP. The system is modular in nature with the interface to the
4
- gateway from the mesh network accessible through a HTTP REST API. This allows many different mesh networks
5
- potentially at multiple sites to communicate with the centeral gateway over the internet or to a serial
2
+ Ardtweeno is a distributed sensor mesh network gateway which bridges devices connected through a serial
3
+ link to those on the internet over IP. The system is modular in nature with the interface to the
4
+ gateway from the serial link being accessible through a HTTP REST API. This allows many different devices
5
+ potentially at multiple sites to communicate with the central gateway over the internet or to a serial
6
6
  device connected locally as would be the case with a directly connected XBee Coordinator.
7
7
 
8
8
  All data is logged to a local database to allow statistical analysis and graphs to be generated for
9
9
  inclusion in hourly/daily reports which can be attached to the systems twitter feed.
10
10
 
11
- The core system is wrapped in a Ruby Sinatra webbapp which exposes a HTTP REST API and allows interaction
11
+ The core system is wrapped in a Ruby Sinatra webapp which exposes a HTTP REST API and allows interaction
12
12
  with the gateway over RESTful HTTP calls on the IP network. This has been designed with a Raspberry Pi in
13
13
  mind and has been tested to work correctly on the Raspbian distribution.
14
14
 
@@ -18,18 +18,22 @@ on Rails web application to act as an end user front end to the system and displ
18
18
  graphs from data recieved on the mesh network, while also extending the feature set of the HTTP REST API
19
19
  and eventually offer the means to manage and upload updated firmwares to the mesh network nodes.
20
20
 
21
- This is a work in progress! The Wiki associated will soon contain the instructions for accessing the REST
22
- API and installation instructions shortly. Any bugs encountered can be raised on the issue tracker.
21
+ This is a work in progress! The Wiki associated now contains the instructions for accessing the REST
22
+ API and installation instructions. Any bugs encountered can be raised on the issue tracker.
23
+
24
+ If you would like to collaborate with me on this project please fork the repository and send any changes
25
+ through a pull request! I gladly welcome constructive input!
23
26
 
24
27
 
25
28
 
26
29
  # COPYING / Licence
27
- This software is released under the creative commons attribution-sharealike 3.0 unported (cc by-sa 3.0) licence.
28
- for more information see: http://creativecommons.org/licenses/by-sa/3.0/
30
+ This software is released under the Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)
31
+ for more information see the full details of this licence here: http://creativecommons.org/licenses/by-nc/3.0/
32
+
29
33
  For information regarding commercial use of the Ardtweeno Gateway, please contact the author at:
30
- davidkirwanirl (_at_) gmail dot com
34
+ davidkirwanirl (_at_) gmail dot com or through Twitter at @kirwan\_david
31
35
 
32
36
 
33
37
  # DISCLAIMER
34
38
  All code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
35
- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
39
+ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -37,7 +37,7 @@ module Ardtweeno
37
37
  # Saves the database to disk
38
38
  def save(newData, path, options={})
39
39
  @log = options[:log] ||= Logger.new(STDOUT)
40
- @log.level = Logger::DEBUG
40
+ @log.level = options[:level] ||= Logger::DEBUG
41
41
 
42
42
  @data = newData
43
43
 
@@ -1,8 +1,8 @@
1
1
  ####################################################################################################
2
- # @author David Kirwan <davidkirwanirl@gmail.com>
3
- # @description Dispatcher system for the Ardtweeno Mesh Network
2
+ # @author David Kirwan https://github.com/davidkirwan/ardtweeno
3
+ # @description Ardtweeno dispatcher system
4
4
  #
5
- # @date 30-03-2013
5
+ # @date 14-06-2013
6
6
  ####################################################################################################
7
7
 
8
8
  # Imports
@@ -24,7 +24,7 @@ module Ardtweeno
24
24
 
25
25
  include Singleton
26
26
 
27
- attr_accessor :nodeManager, :parser, :confdata, :nodedata, :db, :auth, :coll, :log, :running
27
+ attr_accessor :nodeManager, :parser, :confdata, :nodedata, :db, :auth, :coll, :log, :running, :posts
28
28
 
29
29
 
30
30
  ##
@@ -43,7 +43,9 @@ module Ardtweeno
43
43
  @running = false
44
44
  @parser = nil
45
45
 
46
- unless Ardtweeno.options[:test] ||= false
46
+ if Ardtweeno.options[:test]
47
+ @confdata = Ardtweeno.options[:confdata]
48
+ else
47
49
  @log.debug "Calling bootstrap()"
48
50
  bootstrap()
49
51
  end
@@ -201,28 +203,45 @@ module Ardtweeno
201
203
  # Ardtweeno::Dispatcher#addWatch method to add a watch on a node
202
204
  #
203
205
  # * *Args* :
204
- # - ++ -> params Hash
206
+ # - ++ -> params Hash containing: {:node String name of the node,
207
+ # :notifyURL String URL to post a push notification to
208
+ # :method String either GET or PUSH to indicate HTTP methods
209
+ # :timeout Fixnum the timeout in seconds between push notifications }
205
210
  # * *Returns* :
206
211
  # -
207
212
  # * *Raises* :
208
- #
213
+ # Ardtweeno::InvalidWatch if params do not adhere to specification
214
+ # Ardtweeno::AlreadyWatched if node is already on a watchlist
215
+ #
209
216
  def addWatch(params)
210
217
  begin
211
218
  apitimer = Time.now
212
219
 
213
- if params.has_key? "node" and
214
- params.has_key? "notifyURL" and
215
- params.has_key? "method" and
216
- params.has_key? "timeout"
217
-
220
+ if params.has_key? :node and
221
+ params.has_key? :notifyURL and
222
+ params.has_key? :method and
223
+ params.has_key? :timeout
224
+
225
+
226
+ unless params[:method] == "GET" or params[:method] == "POST"
227
+ raise Ardtweeno::InvalidWatch, "Invalid Parameters"
228
+ end
229
+
230
+ unless params[:timeout] >= 0
231
+ raise Ardtweeno::InvalidWatch, "Invalid Parameters"
232
+ end
233
+
218
234
  @log.debug "Watch API call seems valid, passing to NodeManager"
219
235
  @nodeManager.addWatch(params)
220
236
  else
221
- raise Exception, "Invalid Parameters"
237
+ raise Ardtweeno::InvalidWatch, "Invalid Parameters"
222
238
  end
223
239
 
224
240
  @log.debug "Duration: #{Time.now - apitimer} seconds"
225
- rescue Exception => e
241
+
242
+ rescue Ardtweeno::AlreadyWatched => e
243
+ raise e, "This node already has a watch associated with it"
244
+ rescue Ardtweeno::InvalidWatch => e
226
245
  raise e
227
246
  end
228
247
  end
@@ -243,9 +262,11 @@ module Ardtweeno
243
262
  @log.debug "Payload recieved, processing.."
244
263
  payload = JSON.parse(origionalPayload)
245
264
 
246
- if payload["data"].nil? then raise Ardtweeno::InvalidData, "Packet missing data" end
265
+ if payload["data"].nil? then raise Ardtweeno::InvalidData, "Packet missing data"; end
247
266
  @log.debug "Payload contains a :data key, continuing.."
248
- if payload["key"].nil? then raise Ardtweeno::InvalidData, "Packet missing key" end
267
+ if payload["data"].empty? then raise Ardtweeno::InvalidData, "Packet data empty"; end
268
+ @log.debug "Payload data is not empty, continuing.."
269
+ if payload["key"].nil? then raise Ardtweeno::InvalidData, "Packet missing key"; end
249
270
  @log.debug "Payload contains a :key key, continuing.."
250
271
 
251
272
  @log.debug "Searching for the corresponding Ardtweeno::Node in the system.."
@@ -301,11 +322,29 @@ module Ardtweeno
301
322
  speed = @confdata["speed"]
302
323
  key = @confdata["adminkey"]
303
324
 
304
- cmd = "/bin/bash -c '/usr/local/bin/node resources/serialparser.js #{dev} #{speed} #{key}'"
305
-
306
- @parser = fork do
307
- Signal.trap("SIGTERM") { `killall node`; exit }
308
- `#{cmd}`
325
+ begin
326
+ serialparser = Ardtweeno::SerialParser.new(dev, speed, 100, {:log=>@log, :level=>@log.level})
327
+ rescue Exception => e
328
+ @log.fatal "Ardtweeno::Dispatcher#start Fatal Error constructing the SerialParser:"
329
+ @running = false
330
+ return false
331
+ end
332
+
333
+ @parser = Thread.new do
334
+
335
+ begin
336
+ loop do
337
+ serialparser.listen(key)
338
+ end
339
+
340
+ rescue Exception => e
341
+ @log.debug e.message
342
+ serialparser.close
343
+ @running = false
344
+ @parser.kill
345
+ @parser = nil
346
+
347
+ end
309
348
  end
310
349
 
311
350
  @log.debug "Dispatcher#start has been called starting the system up.."
@@ -321,7 +360,8 @@ module Ardtweeno
321
360
  end
322
361
  end
323
362
  rescue Exception => e
324
- `killall node`
363
+ @parser.kill
364
+ @parser = nil
325
365
  raise e
326
366
  end
327
367
 
@@ -346,13 +386,12 @@ module Ardtweeno
346
386
  unless Ardtweeno.options[:test]
347
387
  unless @running == false
348
388
 
349
- @log.debug "Dispatcher#stop has been called shutting system down.."
350
-
351
- Process.kill("SIGTERM", @parser)
352
- Process.wait
389
+ @parser.kill
353
390
  @parser = nil
354
391
 
355
392
  @running = false
393
+ @log.debug "Dispatcher#stop has been called shutting system down.."
394
+
356
395
  return true
357
396
 
358
397
  end
@@ -363,7 +402,7 @@ module Ardtweeno
363
402
  end
364
403
  end
365
404
  rescue Exception => e
366
- `killall node`
405
+ @parser.kill
367
406
  @parser = nil
368
407
  raise e
369
408
  end
@@ -393,6 +432,57 @@ module Ardtweeno
393
432
  end
394
433
  end
395
434
 
435
+
436
+ ##
437
+ # Ardtweeno::Dispatcher#status? returns the system status of the Ardtweeno Gateway host
438
+ #
439
+ # * *Args* :
440
+ # - ++ ->
441
+ # * *Returns* :
442
+ # - Hash theResponse containing: bool running, String cpuload, String memload
443
+ # * *Raises* :
444
+ #
445
+ def status?()
446
+ @log.debug "Ardtweeno::Dispatcher#status? executing"
447
+ begin
448
+ unless Ardtweeno.options[:test] ||= false
449
+ # Get CPU
450
+ maxLoad = calculateCPUCores()
451
+
452
+ # Get Avgload
453
+ currentLoadPercentage = calculateAvgLoad(maxLoad)
454
+
455
+ # Get MEM Usage
456
+ usedMem, totalMem = calculateMemLoad()
457
+
458
+
459
+ thecpuload = '%.2f' % currentLoadPercentage
460
+ thememload = '%.2f' % ((usedMem / totalMem.to_f) * 100)
461
+
462
+ theResponse = {:running=>@running,
463
+ :cpuload=>thecpuload,
464
+ :memload=>thememload}
465
+
466
+ @log.debug theResponse.inspect
467
+
468
+ return theResponse
469
+
470
+ else # When in testing mode, return blank data
471
+ theResponse = {:running=>@running,
472
+ :cpuload=>0.0,
473
+ :memload=>0.0}
474
+
475
+ @log.debug theResponse.inspect
476
+
477
+ return theResponse
478
+ end
479
+
480
+ rescue Exception => e
481
+
482
+ end
483
+ end
484
+
485
+
396
486
 
397
487
  ##
398
488
  # Ardtweeno::Dispatcher#running? checks to see if the SerialParser is running
@@ -434,7 +524,56 @@ module Ardtweeno
434
524
 
435
525
 
436
526
  ##
437
- # Ardtweeno::Dispatcher#config returns the configuration as read in from the DB
527
+ # Ardtweeno::Dispatcher#getPostsURI returns the front page news URI ~/.ardtweeno/conf.yaml
528
+ #
529
+ # * *Args* :
530
+ # - ++ ->
531
+ # * *Returns* :
532
+ # - String which makes up the news post URI ie "/randomhash/create/post"
533
+ # * *Raises* :
534
+ #
535
+ def getPostsURI()
536
+ return @confdata["newsURI"]
537
+ end
538
+
539
+
540
+
541
+ ##
542
+ # Ardtweeno::Dispatcher#getPosts returns the front page news posts loaded from ~/.ardtweeno/posts.yaml
543
+ #
544
+ # * *Args* :
545
+ # - ++ ->
546
+ # * *Returns* :
547
+ # - Array of Hash containing post data
548
+ # * *Raises* :
549
+ #
550
+ def getPosts()
551
+ unless @posts.nil? or @posts.empty?
552
+ return @posts["posts"]
553
+ else
554
+ return Array.new
555
+ end
556
+ end
557
+
558
+
559
+ ##
560
+ # Ardtweeno::Dispatcher#savePosts saves a post to ~/.ardtweeno/posts.yaml
561
+ #
562
+ # * *Args* :
563
+ # - ++ ->
564
+ # * *Returns* :
565
+ # -
566
+ # * *Raises* :
567
+ #
568
+ def savePosts(newPosts)
569
+ @posts["posts"] = newPosts
570
+ Ardtweeno::ConfigReader.save(@posts, Ardtweeno::POSTPATH)
571
+ end
572
+
573
+
574
+ ##
575
+ # Ardtweeno::Dispatcher#config returns the configuration as read in from the confg.yaml configuration
576
+ # file
438
577
  #
439
578
  # * *Args* :
440
579
  # - ++ ->
@@ -456,8 +595,7 @@ module Ardtweeno
456
595
  # -
457
596
  # * *Raises* :
458
597
  #
459
- private
460
- def bootstrap()
598
+ def bootstrap
461
599
 
462
600
  # Read in the configuration files
463
601
  begin
@@ -465,6 +603,7 @@ module Ardtweeno
465
603
 
466
604
  @confdata = Ardtweeno::ConfigReader.load(Ardtweeno::DBPATH)
467
605
  @nodedata = Ardtweeno::ConfigReader.load(Ardtweeno::NODEPATH)
606
+ @posts = Ardtweeno::ConfigReader.load(Ardtweeno::POSTPATH)
468
607
 
469
608
  rescue Exception => e
470
609
  @log.fatal e.message
@@ -500,7 +639,7 @@ module Ardtweeno
500
639
  @log.debug e.message
501
640
  @log.debug e.backtrace
502
641
  raise e
503
- end
642
+ end
504
643
 
505
644
 
506
645
  # Create the MongoDB connector instance
@@ -532,7 +671,90 @@ module Ardtweeno
532
671
 
533
672
 
534
673
  end # End of the bootstrap()
674
+
675
+
676
+ def calculateMemLoad()
677
+ begin
678
+ memhash = Hash.new
679
+ meminfo = File.read('/proc/meminfo')
680
+ meminfo.each_line do |i|
681
+ key, val = i.split(':')
682
+ if val.include?('kB') then val = val.gsub(/\s+kB/, ''); end
683
+ memhash["#{key}"] = val.strip
684
+ end
685
+
686
+ totalMem = memhash["MemTotal"].to_i
687
+ freeMem = memhash["MemFree"].to_i + memhash["Buffers"].to_i + memhash["Cached"].to_i
688
+ usedMem = totalMem - freeMem
689
+
690
+ @log.debug "Total Memory: #{totalMem} (100%)"
691
+ @log.debug "Used Memory: #{usedMem} (#{'%.2f' % ((usedMem / totalMem.to_f) * 100)}%)"
692
+ @log.debug "Free Memory: #{freeMem} (#{'%.2f' % ((freeMem / totalMem.to_f) * 100)}%)"
693
+
694
+ return usedMem, totalMem
695
+
696
+ rescue Exception => e
697
+ @log.debug "Some issue accessing /proc/meminfo"
698
+ usedMem, totalMem = 0, 0
699
+
700
+ return usedMem, totalMem
701
+ end
702
+ end
703
+
704
+ def calculateAvgLoad(maxLoad)
705
+ begin
706
+ loadavg = File.read('/proc/loadavg')
707
+ loads = loadavg.scan(/\d+.\d+/)
708
+ onemin = loads[0]
709
+ fivemin = loads[1]
710
+ fifteenmin = loads[2]
711
+
712
+ @log.debug "LoadAvg are as follows: 1min #{onemin}, 5min #{fivemin}, 15min #{fifteenmin}"
713
+
714
+ loadval = (onemin.to_f / maxLoad)
715
+ currentLoadPercentage = loadval * 100
716
+
717
+ @log.debug "Currently running at #{'%.2f' % currentLoadPercentage}% of max load"
718
+
719
+ return currentLoadPercentage
720
+
721
+ rescue Exception => e
722
+ @log.debug "Some issue accessing /proc/loadavg"
723
+ onemin, fivemin, fifteenmin = 0, 0, 0
724
+
725
+ loadval = (onemin.to_f / maxLoad)
726
+ currentLoadPercentage = loadval * 100
727
+
728
+ return currentLoadPercentage
729
+ end
730
+ end
731
+
732
+
733
+ def calculateCPUCores()
734
+ begin # Checking for multi-core CPU
735
+ cpuinfo = File.read('/proc/cpuinfo')
736
+ coreinfo = cpuinfo.scan(/cpu cores\s+:\s+\d+/)
737
+
738
+ tempVal = coreinfo[0]
739
+ numOfCores = tempVal.scan(/\d+/)[0].to_i
740
+ numOfThreadsPerCore = coreinfo.size / numOfCores
741
+ maxLoad = (numOfThreadsPerCore * numOfCores).to_f
742
+
743
+ @log.debug "Found #{numOfCores} cores with #{numOfThreadsPerCore} threads per core"
744
+ @log.debug "Max desirable cpu load: #{maxLoad}"
745
+
746
+ return maxLoad
747
+
748
+ rescue Exception => e
749
+ @log.debug "Unable to find cpu core info in /proc/cpuinfo, assuming system has a single core"
750
+ maxLoad = 1.0
751
+
752
+ return maxLoad
753
+ end
754
+ end
755
+
535
756
 
757
+ private :bootstrap, :calculateMemLoad, :calculateAvgLoad, :calculateCPUCores
536
758
 
537
759
  end
538
760
  end
@@ -30,4 +30,10 @@ module Ardtweeno
30
30
  class SerialDeviceNotFound < Exception
31
31
  end
32
32
 
33
+ class InvalidWatch < Exception
34
+ end
35
+
36
+ class AlreadyWatched < Exception
37
+ end
38
+
33
39
  end
@@ -178,8 +178,8 @@ module Ardtweeno
178
178
 
179
179
  @watchlist.each do |i|
180
180
 
181
- @log.debug "Comparing " + i[:node].node + " and " + node.node
182
- if i[:node].node == node.node
181
+ @log.debug "Comparing " + i[:node] + " and " + node.node
182
+ if i[:node] == node.node
183
183
  return true
184
184
  end
185
185
  end
@@ -205,16 +205,22 @@ module Ardtweeno
205
205
  node = search({:node=>params[:node]})
206
206
  @log.debug "Found Node: " + node.inspect
207
207
 
208
- watch = { :node=>node,
208
+ if watched?(node)
209
+ raise Ardtweeno::AlreadyWatched
210
+ end
211
+
212
+ watch = { :node=>params[:node],
209
213
  :notifyURL=> params[:notifyURL],
210
- :method=>"POST",
211
- :timeout=>"60"
214
+ :method=>params[:method],
215
+ :timeout=>params[:timeout]
212
216
  }
213
217
 
214
218
  @log.debug "Adding watch: " + watch.inspect
215
219
 
216
220
  @watchlist << watch
217
-
221
+
222
+ rescue Ardtweeno::AlreadyWatched => e
223
+ raise e
218
224
  rescue Ardtweeno::NotInNodeList => e
219
225
  raise e
220
226
  rescue Exception => e
@@ -238,7 +244,7 @@ module Ardtweeno
238
244
  node = search({:node=>node})
239
245
 
240
246
  @watchlist.each do |i|
241
- if i[:node] == node
247
+ if i[:node] == node.node
242
248
  @watchlist.delete(i)
243
249
  end
244
250
  end