artoo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/.gitignore +25 -0
  2. data/Gemfile +26 -0
  3. data/Gemfile.lock +144 -0
  4. data/Guardfile +15 -0
  5. data/LICENSE +13 -0
  6. data/README.md +97 -0
  7. data/Rakefile +11 -0
  8. data/api/assets/compass.rb +25 -0
  9. data/api/assets/javascripts/artoo/controllers/robot.js.coffee +27 -0
  10. data/api/assets/javascripts/artoo/routes.js.coffee +23 -0
  11. data/api/assets/javascripts/core.js.coffee +6 -0
  12. data/api/assets/javascripts/vendor/angular.min.js +161 -0
  13. data/api/assets/javascripts/vendor/bootstrap.min.js +6 -0
  14. data/api/assets/javascripts/vendor/jquery.min.js +5 -0
  15. data/api/assets/stylesheets/artoo/_core.css.scss +3 -0
  16. data/api/assets/stylesheets/artoo/_font-awesome.scss +534 -0
  17. data/api/assets/stylesheets/artoo/_variables.scss +8 -0
  18. data/api/assets/stylesheets/core.scss +70 -0
  19. data/api/public/core.css +9848 -0
  20. data/api/public/core.js +259 -0
  21. data/api/public/favicon.ico +0 -0
  22. data/api/public/font/FontAwesome.otf +0 -0
  23. data/api/public/font/fontawesome-webfont.eot +0 -0
  24. data/api/public/font/fontawesome-webfont.svg +284 -0
  25. data/api/public/font/fontawesome-webfont.ttf +0 -0
  26. data/api/public/font/fontawesome-webfont.woff +0 -0
  27. data/api/public/html5shiv.js +8 -0
  28. data/api/public/images/devices/ardrone.jpg +0 -0
  29. data/api/public/images/devices/arduino.jpg +0 -0
  30. data/api/public/images/devices/sphero.png +0 -0
  31. data/api/public/images/glyphicons-halflings-white.png +0 -0
  32. data/api/public/images/glyphicons-halflings.png +0 -0
  33. data/api/public/index.html +36 -0
  34. data/api/public/partials/robot-detail.html +111 -0
  35. data/api/public/partials/robot-device-detail.html +0 -0
  36. data/api/public/partials/robot-index.html +26 -0
  37. data/artoo.gemspec +21 -0
  38. data/bin/retry.sh +8 -0
  39. data/bin/sphero.sh +8 -0
  40. data/examples/ardrone.rb +12 -0
  41. data/examples/ardrone_nav.rb +22 -0
  42. data/examples/ardrone_nav_video.rb +33 -0
  43. data/examples/ardrone_video.rb +22 -0
  44. data/examples/conway_sphero.rb +65 -0
  45. data/examples/firmata.rb +13 -0
  46. data/examples/firmata_button.rb +9 -0
  47. data/examples/hello.rb +12 -0
  48. data/examples/hello_api.rb +9 -0
  49. data/examples/hello_api_multiple.rb +25 -0
  50. data/examples/hello_modular.rb +16 -0
  51. data/examples/hello_multiple.rb +22 -0
  52. data/examples/notifications.rb +9 -0
  53. data/examples/sphero.rb +11 -0
  54. data/examples/sphero_color.rb +13 -0
  55. data/examples/sphero_firmata.rb +17 -0
  56. data/examples/sphero_messages.rb +22 -0
  57. data/examples/sphero_multiple.rb +33 -0
  58. data/examples/wiiclassic.rb +94 -0
  59. data/lib/artoo.rb +3 -0
  60. data/lib/artoo/adaptors/adaptor.rb +54 -0
  61. data/lib/artoo/adaptors/ardrone.rb +32 -0
  62. data/lib/artoo/adaptors/ardrone_navigation.rb +26 -0
  63. data/lib/artoo/adaptors/ardrone_video.rb +27 -0
  64. data/lib/artoo/adaptors/firmata.rb +25 -0
  65. data/lib/artoo/adaptors/loopback.rb +8 -0
  66. data/lib/artoo/adaptors/sphero.rb +46 -0
  67. data/lib/artoo/api.rb +48 -0
  68. data/lib/artoo/api_route_helpers.rb +197 -0
  69. data/lib/artoo/connection.rb +70 -0
  70. data/lib/artoo/delegator.rb +49 -0
  71. data/lib/artoo/device.rb +61 -0
  72. data/lib/artoo/device_event_client.rb +27 -0
  73. data/lib/artoo/drivers/ardrone.rb +9 -0
  74. data/lib/artoo/drivers/ardrone_navigation.rb +21 -0
  75. data/lib/artoo/drivers/ardrone_video.rb +22 -0
  76. data/lib/artoo/drivers/button.rb +40 -0
  77. data/lib/artoo/drivers/driver.rb +48 -0
  78. data/lib/artoo/drivers/led.rb +37 -0
  79. data/lib/artoo/drivers/passthru.rb +9 -0
  80. data/lib/artoo/drivers/pinger.rb +19 -0
  81. data/lib/artoo/drivers/pinger2.rb +18 -0
  82. data/lib/artoo/drivers/sphero.rb +57 -0
  83. data/lib/artoo/drivers/wiichuck.rb +29 -0
  84. data/lib/artoo/drivers/wiiclassic.rb +137 -0
  85. data/lib/artoo/main.rb +32 -0
  86. data/lib/artoo/master.rb +16 -0
  87. data/lib/artoo/port.rb +51 -0
  88. data/lib/artoo/robot.rb +299 -0
  89. data/lib/artoo/utility.rb +39 -0
  90. data/lib/artoo/version.rb +5 -0
  91. data/test/adaptors/adaptor_test.rb +18 -0
  92. data/test/adaptors/ardrone_test.rb +24 -0
  93. data/test/adaptors/firmata_test.rb +25 -0
  94. data/test/adaptors/loopback_test.rb +18 -0
  95. data/test/adaptors/sphero_test.rb +24 -0
  96. data/test/api_test.rb +61 -0
  97. data/test/artoo_test.rb +12 -0
  98. data/test/connection_test.rb +28 -0
  99. data/test/delegator_test.rb +71 -0
  100. data/test/device_test.rb +41 -0
  101. data/test/drivers/ardrone_navigation_test.rb +11 -0
  102. data/test/drivers/ardrone_test.rb +11 -0
  103. data/test/drivers/ardrone_video_test.rb +11 -0
  104. data/test/drivers/driver_test.rb +21 -0
  105. data/test/drivers/led_test.rb +52 -0
  106. data/test/drivers/sphero_test.rb +54 -0
  107. data/test/drivers/wiichuck_test.rb +11 -0
  108. data/test/port_test.rb +33 -0
  109. data/test/robot_test.rb +96 -0
  110. data/test/test_helper.rb +8 -0
  111. data/test/utility_test.rb +27 -0
  112. metadata +185 -0
@@ -0,0 +1,8 @@
1
+ /*
2
+ HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
3
+ */
4
+ (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
5
+ a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
6
+ c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
7
+ "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
8
+ for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
@@ -0,0 +1,36 @@
1
+ <!DOCTYPE html>
2
+ <html ng-app="artoo">
3
+ <head>
4
+ <title>Artoo</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <!-- Bootstrap -->
7
+ <script type="text/javascript" src="core.js"></script>
8
+ <link rel="stylesheet" href="core.css" rel="stylesheet" media="screen">
9
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
10
+ <!--[if lt IE 9]>
11
+ <script src="html5shiv.js"></script>
12
+ <![endif]-->
13
+ </head>
14
+ <body>
15
+ <div class="navbar navbar-inverse navbar-fixed-top">
16
+ <div class="navbar-inner">
17
+ <div class="container">
18
+ <a class="brand" href="/">Artoo</a>
19
+
20
+ <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
21
+ <span class="icon-bar"></span>
22
+ <span class="icon-bar"></span>
23
+ <span class="icon-bar"></span>
24
+ </button>
25
+ <div class="nav-collapse collapse">
26
+ <ul class="nav" ng-app="link">
27
+ <li active-link="active"><a href="#/robots">Robots</a></li>
28
+ </ul>
29
+ </div><!--/.nav-collapse -->
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <div ng-view></div>
35
+ </body>
36
+ </html>
@@ -0,0 +1,111 @@
1
+ <div class="container">
2
+ <div class="container device">
3
+ <div class="row-fluid">
4
+ <div class="span2">
5
+ <div class="display">
6
+ {{robot.type || "Robot"}}
7
+ </div>
8
+ </div>
9
+ <div class="span10">
10
+ <b>
11
+ <span class="name">{{robot.name}}</span>
12
+ <dl class="controls">
13
+ <dt><i class="icon-fighter-jet"></i> devices: </dt>
14
+ <dd>{{robot.connections.length}}</dd>
15
+ <dt><i class="icon-exchange"></i> connections: </dt>
16
+ <dd>{{robot.connections.length}}</dd>
17
+ </dl>
18
+ </b>
19
+ </div>
20
+ </div>
21
+ </div>
22
+
23
+ <div class="container device details" ng-show='deviceDetail'>
24
+ <div class="row-fluid">
25
+ <div class="span12">
26
+ <!--<div class="display">Pending</div>-->
27
+ <b>
28
+ <span class="name">{{deviceDetail.name}}</span>
29
+ {{device}}
30
+ <dl class="controls">
31
+ <span ng-show='deviceDetail.pin'>
32
+ <dt><i class="icon-fighter-jet"></i> </dt>
33
+ <dd>{{ deviceDetail.pin }}</dd>
34
+ </span>
35
+ <span ng-show='deviceDetail.driver'>
36
+ <dt><i class="icon-exchange"></i></dt>
37
+ <dd>{{ deviceDetail.driver }}</dd>
38
+ </span>
39
+ <span ng-show='deviceDetail.adaptor'>
40
+ <dt><i class="icon-exchange"></i></dt>
41
+ <dd>{{ deviceDetail.adaptor }}</dd>
42
+ </span>
43
+ <span ng-show='deviceDetail.connection'>
44
+ <dt><i class="icon-circle" ng-class="isConnected(deviceDetail.connection)"></i> </dt>
45
+ <dd ng-show="deviceDetail.connection.name">{{deviceDetail.connection.name}}</dd>
46
+ </span>
47
+ </dl>
48
+ </b>
49
+ </div>
50
+ </div>
51
+ <div class="row-fluid content">
52
+ <div class="console">
53
+ <code></code>
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+
59
+ <div class="row">
60
+
61
+ <div class="span6">
62
+ <div class="device" ng-repeat="device in robot.devices" ng-click="getDeviceDetail(device.name)">
63
+ <div class="row-fluid">
64
+ <div class="span2">
65
+ <div class="display">
66
+ D
67
+ </div>
68
+ </div>
69
+ <div class="span10">
70
+ <b>
71
+ <span class="name">{{device.name}}</span>
72
+ <dl class="controls">
73
+ <span ng-show="device.pin">
74
+ <dt ><i class="icon-bolt"></i> pin: </dt>
75
+ <dd>{{device.pin}}</dd>
76
+ </span>
77
+ <dt><i class="icon-exchange"></i> </dt>
78
+ <dd>{{device.connection.name}}</dd>
79
+ </dl>
80
+ </b>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+
86
+
87
+ <div class="span6">
88
+ <div class="device" ng-repeat="connection in robot.connections">
89
+ <div class="row-fluid">
90
+ <div class="span2">
91
+ <div class="display">
92
+ <i class="icon-exchange"></i>
93
+ </div>
94
+ </div>
95
+ <div class="span10">
96
+ <b>
97
+ <span class="name">{{connection.name}}</span>
98
+ <dl class="controls">
99
+ <dt><i class="icon-circle" ng-class="isConnected(connection)"></i> </dt>
100
+ <dd ng-show="connection.port">{{connection.port}}</dd>
101
+ </dl>
102
+ </b>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+
108
+ </div>
109
+
110
+
111
+ </div>
@@ -0,0 +1,26 @@
1
+ <div class="container">
2
+
3
+ <h1>Listing all Robots</h1>
4
+
5
+ <div class="container device clickable" ng-repeat="robot in robots" ng-click="robotDetail(robot.name)">
6
+ <div class="row-fluid">
7
+ <div class="span2">
8
+ <div class="display sphero">
9
+ {{robot.type || "Robot"}}
10
+ </div>
11
+ </div>
12
+ <div class="span10">
13
+ <b>
14
+ <span class="name">{{robot.name}}</span>
15
+ <dl class="controls">
16
+ <dt><i class="icon-fighter-jet"></i> Devices: </dt>
17
+ <dd>{{robot.connections.length}}</dd>
18
+ <dt><i class="icon-exchange"></i> Connections: </dt>
19
+ <dd>{{robot.connections.length}}</dd>
20
+ </dl>
21
+ </b>
22
+ </div>
23
+ </div>
24
+ </div>
25
+
26
+ </div>
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "artoo/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "artoo"
7
+ s.version = Artoo::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ron Evans", "Adrian Zankich", "Ari Lerner", "Mario Ricalde", "Daniel Fischer"]
10
+ s.email = ["artoo@hybridgroup.com"]
11
+ s.homepage = "https://github.com/hybridgroup/artoo"
12
+ s.summary = %q{Ruby-based microframework for robotics}
13
+ s.description = %q{Ruby-based microframework for robotics}
14
+
15
+ s.rubyforge_project = "artoo"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+
3
+ NEXT_WAIT_TIME=0
4
+ COMMAND="socat PIPE:/dev/tty.Sphero-$1-RN-SPP,nonblock TCP-LISTEN:$2,fork"
5
+ until $COMMAND || [ $NEXT_WAIT_TIME -eq 4 ]; do
6
+ echo "retry..."
7
+ sleep $(( NEXT_WAIT_TIME++ ))
8
+ done
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+
3
+ NEXT_WAIT_TIME=0
4
+ COMMAND="socat PIPE:/dev/tty.Sphero-$1-RN-SPP,nonblock TCP-LISTEN:$2,fork"
5
+ until $COMMAND || [ $NEXT_WAIT_TIME -eq 4 ]; do
6
+ echo "retry..."
7
+ sleep $(( NEXT_WAIT_TIME++ ))
8
+ done
@@ -0,0 +1,12 @@
1
+ require 'artoo'
2
+
3
+ connection :ardrone, :adaptor => :ardrone
4
+ device :drone, :driver => :ardrone
5
+
6
+ work do
7
+ drone.start
8
+ drone.take_off
9
+
10
+ after(25.seconds) { drone.hover.land }
11
+ after(30.seconds) { drone.stop }
12
+ end
@@ -0,0 +1,22 @@
1
+ require 'artoo'
2
+
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
+ device :drone, :driver => :ardrone, :connection => :ardrone
5
+
6
+ connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.1:5554'
7
+ device :nav, :driver => :ardrone_navigation, :connection => :navigation
8
+
9
+ work do
10
+ on nav, :update => :nav_update
11
+ drone.start
12
+ drone.take_off
13
+
14
+ after(25.seconds) { drone.hover.land }
15
+ after(30.seconds) { drone.stop }
16
+ end
17
+
18
+ def nav_update(*data)
19
+ data[1].drone_state.each do |name, val|
20
+ p "#{name}: #{val}"
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ require 'artoo'
2
+
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
+ device :drone, :driver => :ardrone, :connection => :ardrone
5
+
6
+ connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.1:5554'
7
+ device :nav, :driver => :ardrone_navigation, :connection => :navigation
8
+
9
+ connection :videodrone, :adaptor => :ardrone_video, :port => '192.168.1.1:5555'
10
+ device :video, :driver => :ardrone_video, :connection => :videodrone
11
+
12
+ work do
13
+ on nav, :update => :nav_update
14
+ on video, :frame => :v_frame
15
+
16
+ drone.start
17
+ drone.take_off
18
+
19
+ after(25.seconds) { drone.hover.land }
20
+ after(30.seconds) { drone.stop }
21
+ end
22
+
23
+ def v_frame(*data)
24
+ @count ||= 0
25
+ @count += 1
26
+ puts "Frame# #{@count} #{data[1].size} bytes"
27
+ end
28
+
29
+ def nav_update(*data)
30
+ data[1].drone_state.each do |name, val|
31
+ p "#{name}: #{val}"
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'artoo'
2
+
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
+ device :drone, :driver => :ardrone, :connection => :ardrone
5
+
6
+ connection :videodrone, :adaptor => :ardrone_video, :port => '192.168.1.1:5555'
7
+ device :video, :driver => :ardrone_video, :connection => :videodrone
8
+
9
+ work do
10
+ on video, :frame => :v_frame
11
+ drone.start
12
+ drone.take_off
13
+
14
+ after(25.seconds) { drone.hover.land }
15
+ after(30.seconds) { drone.stop }
16
+ end
17
+
18
+ def v_frame(*data)
19
+ @count ||= 0
20
+ @count += 1
21
+ puts "Frame# #{@count} #{data[1].size} bytes"
22
+ end
@@ -0,0 +1,65 @@
1
+ require 'artoo/robot'
2
+
3
+ class SpheroRobot < Artoo::Robot
4
+ connection :sphero, :adaptor => :sphero
5
+ device :sphero, :driver => :sphero
6
+
7
+ work do
8
+ birth
9
+
10
+ every(3.seconds) { movement if alive? }
11
+ every(10.seconds) { birthday if alive? }
12
+ end
13
+
14
+ def alive?; (@alive == true); end
15
+
16
+ def birth
17
+ sphero.detect_collisions
18
+ @age = 0
19
+ life
20
+ movement
21
+ end
22
+
23
+ def life
24
+ @alive = true
25
+ sphero.set_color :green
26
+ end
27
+
28
+ def death
29
+ puts "Death."
30
+ @alive = false
31
+ sphero.set_color :red
32
+ sphero.stop
33
+ terminate
34
+ end
35
+
36
+ def birthday
37
+ @age += 1
38
+ contacts = sphero.collisions.size
39
+ sphero.clear_collisions
40
+
41
+ puts "Happy birthday, #{name}, you are #{@age} and had #{contacts} contacts."
42
+ #return if @age <= 3
43
+ death unless contacts >= 3 && contacts < 5
44
+ end
45
+
46
+ def movement
47
+ sphero.roll 90, rand(360)
48
+ end
49
+ end
50
+
51
+ SPHEROS = {"4560" => "/dev/tty.Sphero-BRG-RN-SPP",
52
+ "4561" => "/dev/tty.Sphero-YBW-RN-SPP",
53
+ "4562" => "/dev/tty.Sphero-BWY-RN-SPP",
54
+ "4563" => "/dev/tty.Sphero-YRR-RN-SPP",
55
+ "4564" => "/dev/tty.Sphero-OBG-RN-SPP",
56
+ "4565" => "/dev/tty.Sphero-GOB-RN-SPP",
57
+ "4566" => "/dev/tty.Sphero-PYG-RN-SPP"}
58
+ robots = []
59
+ SPHEROS.each_key {|p|
60
+ robots << SpheroRobot.new(:connections =>
61
+ {:sphero =>
62
+ {:port => p}})
63
+ }
64
+
65
+ SpheroRobot.work!(robots)
@@ -0,0 +1,13 @@
1
+ require 'artoo'
2
+
3
+ connection :firmata, :adaptor => :firmata, :port => '4567' #/dev/tty.usbserial-A700636n'
4
+ device :board
5
+ device :led, :driver => :led, :pin => 13
6
+
7
+ work do
8
+ puts "Firmware name #{board.firmware_name}"
9
+ puts "Firmata version #{board.version}"
10
+ every 1.second do
11
+ led.toggle
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'artoo'
2
+
3
+ connection :arduino, :adaptor => :firmata, :port => '4567'
4
+ device :led, :driver => :led, :pin => 13
5
+ device :button, :driver => :button, :pin => 2
6
+
7
+ work do
8
+ on button, :push => proc {led.toggle}
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'artoo'
2
+
3
+ connection :loop
4
+
5
+ work do
6
+ every(3.seconds) do
7
+ puts "hello"
8
+ end
9
+ after(10.seconds) do
10
+ puts "wow"
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require 'artoo'
2
+
3
+ connection :loop
4
+ device :passthru
5
+ api :host => '127.0.0.1', :port => '4321'
6
+
7
+ work do
8
+ puts "Hello from the API running at #{api_host}:#{api_port}..."
9
+ end