spacebunny 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +190 -0
- data/Rakefile +6 -0
- data/assets/logo.png +0 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/examples/device/auto_config_publish.rb +87 -0
- data/examples/device/manual_config.rb +83 -0
- data/examples/device/publish_with_confirm.rb +85 -0
- data/examples/device/receive_messages.rb +109 -0
- data/examples/device/tls_connection.rb +65 -0
- data/examples/live_stream/receive_messages.rb +128 -0
- data/examples/live_stream/tls_connection.rb +22 -0
- data/lib/spacebunny.rb +23 -0
- data/lib/spacebunny/device/amqp.rb +158 -0
- data/lib/spacebunny/device/base.rb +229 -0
- data/lib/spacebunny/device/message.rb +56 -0
- data/lib/spacebunny/endpoint_connection.rb +128 -0
- data/lib/spacebunny/exceptions.rb +143 -0
- data/lib/spacebunny/live_stream/amqp.rb +124 -0
- data/lib/spacebunny/live_stream/base.rb +198 -0
- data/lib/spacebunny/live_stream/message.rb +38 -0
- data/lib/spacebunny/logger.rb +35 -0
- data/lib/spacebunny/utils.rb +185 -0
- data/lib/spacebunny/version.rb +3 -0
- data/spacebunny.gemspec +27 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6ec6a838a45e43d41f1af7b2b4689fb9cb239bbf
|
4
|
+
data.tar.gz: b45289c93365e82c60d325c7cf4a3d04787ac4bd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79e6ae369230e1e92a791a159f4c935b28f621c11970167b60dfd1511d442393b010bb0be00570b8b1774c20cca05b9177ec925783eb24380447f9cac76fab41
|
7
|
+
data.tar.gz: 0321121e0d08d1440392080c26625bcb1abd363b443300f324add3a73e717fc84d5571385954a7bf8687b6d3887c390c4b10bda2c6ab62a0085dab5406228df5
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Fancy Pixel S.r.l. All rights reserved.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
6
|
+
copy of this software and associated documentation files (the "Software"),
|
7
|
+
to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included
|
14
|
+
in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
17
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<img width="480" src="assets/logo.png"/>
|
3
|
+
</p>
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/space-bunny/ruby_sdk.svg)](https://travis-ci.org/space-bunny/ruby_sdk)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/spacebunny.svg)](https://badge.fury.io/rb/spacebunny)
|
7
|
+
|
8
|
+
[SpaceBunny](http://spacebunny.io) is the IoT platform that makes it easy for you and your devices to send and
|
9
|
+
exchange messages with a server or even with each other. You can store the data, receive timely event notifications,
|
10
|
+
monitor live streams and remotely control your devices. Easy to use, and ready to scale at any time.
|
11
|
+
|
12
|
+
This is the source code repository for Ruby SDK.
|
13
|
+
Please feel free to contribute!
|
14
|
+
|
15
|
+
### Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'spacebunny'
|
21
|
+
```
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install spacebunny
|
30
|
+
|
31
|
+
After you have signed up for a [SpaceBunny](http://spacebunny.io)'s account, follow the
|
32
|
+
[Getting Started](http://getting_started_link) guide for a one minute introduction to the platform concepts
|
33
|
+
and a super rapid setup.
|
34
|
+
|
35
|
+
This SDK provides Device and LiveStream clients and currently supports the AMQP protocol.
|
36
|
+
|
37
|
+
### Device - Basic usage
|
38
|
+
|
39
|
+
Pick a device, view its configurations and copy the Device Key. Instantiate a new `Spacebunny::Device` client,
|
40
|
+
providing the Device Key:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
dev = Spacebunny::Device.new 'device_key'
|
44
|
+
```
|
45
|
+
|
46
|
+
the SDK will auto-configure, contacting [SpaceBunny APIs](http://doc.spacebunny.io/api) endpoint, retrieving the
|
47
|
+
connection configurations and required parameters. Nothing remains but to connect:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
dev.connect
|
51
|
+
```
|
52
|
+
|
53
|
+
##### Publish
|
54
|
+
|
55
|
+
Ok, all set up! Let's publish some message:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# We're assuming you have created a 'data' channel and you have enabled it for your device
|
59
|
+
|
60
|
+
# Let's publish, for instance, some JSON. Payload can be everything you want,
|
61
|
+
# SpaceBunny does not impose any constraint on format or content.
|
62
|
+
|
63
|
+
require 'json' # to convert our payload to JSON
|
64
|
+
|
65
|
+
# Publish one message every second for a minute.
|
66
|
+
60.times do
|
67
|
+
# Generate some random data
|
68
|
+
payload = { greetings: 'Hello, World!', temp: rand(20.0..25.0), foo: rand(100..200) }.to_json
|
69
|
+
|
70
|
+
# Publish
|
71
|
+
dev.publish :data, payload
|
72
|
+
|
73
|
+
# Give feedback on what has been published
|
74
|
+
puts "Published: #{payload}"
|
75
|
+
|
76
|
+
# Take a nap...
|
77
|
+
sleep 1
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
Let's check out that our data is really being sent by going to our web dashboard: navigate to devices, select the
|
82
|
+
device and click on 'LIVE DATA'. Select the 'data' channel from the dropdown and click **Start**.
|
83
|
+
Having published data as JSON allows SpaceBunny's web UI to parse them and visualize a nice
|
84
|
+
realtime graph: On the **Chart** tab write `temp` in the input field and press enter.
|
85
|
+
You'll see the graph of the `temp` parameter being rendered. If you want to plot more parameters,
|
86
|
+
just use a comma as separator e.g: temp, pressure, voltage
|
87
|
+
On the **Messages** tab you'll see raw messages' payloads received on this channel.
|
88
|
+
|
89
|
+
##### Inbox
|
90
|
+
|
91
|
+
Waiting for and reading messages from the device's Inbox is trivial:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
dev.inbox(wait: true, ack: :auto) do |message|
|
95
|
+
puts "Received: #{message.payload}"
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
`wait` option (default false) causes the script to wait forever on the receive block
|
100
|
+
|
101
|
+
`ack` option can have two values: `:manual` (default) or `:auto`. When `:manual` you are responsible to ack the messages,
|
102
|
+
for instance:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
dev.inbox(block: true, ack: :manual) do |message|
|
106
|
+
puts "Received: #{message.payload}"
|
107
|
+
# Manually ack the message
|
108
|
+
message.ack
|
109
|
+
end
|
110
|
+
```
|
111
|
+
This permits to handle errors or other critical situations
|
112
|
+
|
113
|
+
### Live Stream - Basic usage
|
114
|
+
|
115
|
+
For accessing a Live Stream a Live Stream Key's is required. On SpaceBunny's Web UI, go to the Streams section,
|
116
|
+
click on "Live Stream Keys" and pick or create one.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
live = Spacebunny::LiveStream.new client: 'live_stream_key_client', secret: 'live_stream_key_secret'
|
120
|
+
```
|
121
|
+
|
122
|
+
Similarly to the Device client, the SDK will auto-configure itself, contacting [SpaceBunny APIs](http://doc.spacebunny.io/api)
|
123
|
+
endpoint, retrieving the connection configurations and required parameters. Nothing remains but to connect:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
live.connect
|
127
|
+
```
|
128
|
+
|
129
|
+
##### Reading live messages
|
130
|
+
|
131
|
+
Each LiveStream has its own cache that will keep always last 100 messages (FIFO, when there are more than 100 messages,
|
132
|
+
the oldest ones get discarded). If you want to consume messages in a parallel way, you shoul use the cache and connect
|
133
|
+
as many LiveStream clients as you need: this way messages will be equally distributed to clients.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
live.message_from_cache :some_live_stream, wait: true, ack: :auto do |message|
|
137
|
+
puts "Received from cache: #{message.payload}"
|
138
|
+
end
|
139
|
+
|
140
|
+
# An equivalent method is:
|
141
|
+
# live.message_from :some_live_stream, from_cache: true, wait: true, ack: :auto do |message|
|
142
|
+
# puts "Received from cache: #{message.payload}"
|
143
|
+
# end
|
144
|
+
```
|
145
|
+
|
146
|
+
Conversely, if you want that each client will receive a copy of each message, don't use the cache:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
live.message_from :some_live_stream, wait: true, ack: :auto do |message|
|
150
|
+
puts "Received a copy of: #{message.payload}"
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
Every client subscribed to the LiveStream in this way will receive a copy of the message.
|
155
|
+
|
156
|
+
### TLS
|
157
|
+
|
158
|
+
Instantiating a TLS-secured connection is trivial:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
# For a Device
|
162
|
+
|
163
|
+
dev = Spacebunny::Device.new key, tls: true
|
164
|
+
|
165
|
+
# Similarly, for a Live Stream
|
166
|
+
|
167
|
+
live = Spacebunny::LiveStream.new client, secret, tls: true
|
168
|
+
```
|
169
|
+
|
170
|
+
## More examples and options
|
171
|
+
|
172
|
+
Take a look at the ```examples``` directory for more code samples and further details about available options.
|
173
|
+
|
174
|
+
|
175
|
+
### Contributing
|
176
|
+
|
177
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/FancyPixel/spacebunny_ruby.
|
178
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere
|
179
|
+
to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
180
|
+
|
181
|
+
### Development
|
182
|
+
|
183
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests.
|
184
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
185
|
+
|
186
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
187
|
+
|
188
|
+
### License
|
189
|
+
|
190
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/assets/logo.png
ADDED
Binary file
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'spacebunny'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spacebunny'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
# Prerequisites: you have created a device through the SpaceBunny's web interface. You also have a 'data' channel (name
|
5
|
+
# is not mandatory, but we'll use this for our example). You have also enabled 'data' channel for the device. See our
|
6
|
+
# Getting Started [link] for a quick introduction to SpaceBunny's base concepts.
|
7
|
+
|
8
|
+
# Once everything is set up get your device's API key from SpaceBunny's web application: on the web interface,
|
9
|
+
# go to devices section and create or pick an existing device. Click on the 'SHOW CONFIGURATION' link, copy the API key
|
10
|
+
# and substitute it here:
|
11
|
+
|
12
|
+
device_key = 'your_awesome_device_key'
|
13
|
+
|
14
|
+
# Let's instantiate a SpaceBunny client, providing the device's API key, that's the fastest and simplest method
|
15
|
+
# to create a new client. If, for some reason, you need to customize the settings, take a look at
|
16
|
+
# examples/manual_config.rb for an example of connection settings customization.
|
17
|
+
|
18
|
+
dev = Spacebunny::Device.new device_key
|
19
|
+
|
20
|
+
# An equivalent method for providing the API key is through options: Spacebunny::Device.new(key: key)
|
21
|
+
|
22
|
+
# We need to call 'connect' in order to open the communication with SpaceBunny platform
|
23
|
+
|
24
|
+
dev.connect
|
25
|
+
|
26
|
+
# At this point the SDK is auto-configured and ready to use.
|
27
|
+
# Configurations are automatically lazy-fetched by the SDK itself when calling 'connect'.
|
28
|
+
|
29
|
+
# PUBLISHING MESSAGES
|
30
|
+
|
31
|
+
# As said in the prerequisites, we'll assume that 'data' channel is enabled for your device.
|
32
|
+
# If you're in doubt, please check that this is true through SpaceBunny's web interface, by clicking on the device
|
33
|
+
# 'edit' (pencil icon) and verifying that 'data' channel is present and enabled for this device. Take a look at Getting
|
34
|
+
# Started [link] for a quick introduction to SpaceBunny's base concepts.
|
35
|
+
|
36
|
+
# Let's publish, for instance, some JSON. Payload can be everything you want, SpaceBunny does not impose any constraint
|
37
|
+
# on format or content of payload.
|
38
|
+
|
39
|
+
# Publish one message every second for a minute.
|
40
|
+
count = 0
|
41
|
+
60.times do
|
42
|
+
# Generate some random data
|
43
|
+
payload = {
|
44
|
+
count: count,
|
45
|
+
greetings: "Hello from #{dev.name}!",
|
46
|
+
temp: rand(20.0..25.0),
|
47
|
+
foo: rand(100..200)
|
48
|
+
}.to_json
|
49
|
+
|
50
|
+
# Hint: the channel name can also be a string e.g: 'data'
|
51
|
+
dev.publish :data, payload
|
52
|
+
|
53
|
+
# 'publish' takes two mandatory arguments (channel's name and payload) and a variety of options: one of these options is
|
54
|
+
# the 'with_confirm' flag: when set to true this requires SpaceBunny's platform to confirm the receipt of the message.
|
55
|
+
# This is useful when message delivery assurance is mandatory for your use case.
|
56
|
+
# Take a look at SDK's documentation for further details.
|
57
|
+
|
58
|
+
# Give some feedback on what has been published
|
59
|
+
puts "Published #{payload}"
|
60
|
+
|
61
|
+
# Take a nap...
|
62
|
+
sleep 1
|
63
|
+
# Update counter
|
64
|
+
count += 1
|
65
|
+
end
|
66
|
+
|
67
|
+
# Let's check out that our data is really being sent by going to our web dashboard: navigate to devices, select the
|
68
|
+
# device and click on 'LIVE DATA'. Select 'data' channel from the dropdown and click 'START'.
|
69
|
+
# Having published data as JSON it's possible for SpaceBunny to parse them and visualize a nice
|
70
|
+
# realtime graph: On the 'Graphic' tab write 'temp' in the input field and press enter.
|
71
|
+
# You'll see the graph of the 'temp' going on. If you want to graph more params, just use a comma as separator
|
72
|
+
# e.g: temp, pressure, voltage
|
73
|
+
# On the 'Messages' you'll see raw messages' payloads received on this channel.
|
74
|
+
# On the 'Logs' tab are present various log messages useful for debugging purposes.
|
75
|
+
|
76
|
+
# Bonus points:
|
77
|
+
#
|
78
|
+
# SpaceBunny AMQP SDK uses "Bunny" [link] under the hoods so it supports all the features and attributes provided
|
79
|
+
# by the AMQP protocol. For instance, providing 'headers' or a 'timestamp' attribute is just a matter of adding it
|
80
|
+
# as options after the payload:
|
81
|
+
|
82
|
+
# dev.publish :data, payload,
|
83
|
+
# timestamp: Time.now.to_i,
|
84
|
+
# headers: { my_custom_header: 'value' }
|
85
|
+
#
|
86
|
+
# 'timestamp' property or 'Timestamp' header can be used to provide a 'captured at' timestamp to data persisted
|
87
|
+
# by 'Persistence' plugin. Learn more [link].
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spacebunny'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
# Prerequisites: you have created a device through the SpaceBunny's web interface. You also have a 'data' channel (name
|
5
|
+
# is not mandatory, but we'll use this for our example). You have also enabled 'data' channel for the device. See our
|
6
|
+
# Getting Started [link] for a quick introduction to SpaceBunny's base concepts.
|
7
|
+
|
8
|
+
# If for some reason or use case it's not possible or desirable to use auto-configuration, SpaceBunny's Ruby SDK
|
9
|
+
# permits to manually configure the connection with various methods.
|
10
|
+
|
11
|
+
# First of all go to SpaceBunny's web interface, go to the devices section and create or pick an existing device.
|
12
|
+
# Click on the 'SHOW CONFIGURATION' link and, from the 'Full configuration' section, copy the configuration from the
|
13
|
+
# "Ruby" section and customize it to your needs.
|
14
|
+
|
15
|
+
# Replace with device's Ruby configs hash copied from web inteface
|
16
|
+
configs = {
|
17
|
+
:connection => {
|
18
|
+
:host => "api.demo.spacebunny.io",
|
19
|
+
:protocols => {
|
20
|
+
:amqp => {
|
21
|
+
:port => 5672
|
22
|
+
},
|
23
|
+
:mqtt => {
|
24
|
+
:port => 1883
|
25
|
+
},
|
26
|
+
:stomp => {
|
27
|
+
:port => 61613
|
28
|
+
},
|
29
|
+
:web_stomp => {
|
30
|
+
:port => 15674
|
31
|
+
}
|
32
|
+
},
|
33
|
+
:device_name => "device_1",
|
34
|
+
:device_id => "your_dev_id",
|
35
|
+
:secret => "your_dev_secret",
|
36
|
+
:vhost => "your_vhost"
|
37
|
+
},
|
38
|
+
:channels => [
|
39
|
+
{
|
40
|
+
:id => "one_channel_id",
|
41
|
+
:name => "channel_name"
|
42
|
+
}
|
43
|
+
]
|
44
|
+
}
|
45
|
+
|
46
|
+
dev = Spacebunny::Device.new configs
|
47
|
+
|
48
|
+
# An alternative method is to create an 'empty' client instance and then fill connection params
|
49
|
+
# before calling 'connect':
|
50
|
+
#
|
51
|
+
# dev = Spacebunny::Device.new
|
52
|
+
# dev.connection_options = {
|
53
|
+
# connection: {
|
54
|
+
# device_id: '9999aa99-9999-9aaa-aa99-aa9a999a9999',
|
55
|
+
# secret: 'top_secret',
|
56
|
+
# host: 'spacebunny.io',
|
57
|
+
# protocols: {
|
58
|
+
# amqp: { port: 5672}
|
59
|
+
# },
|
60
|
+
# vhost: '11111bb1-1111-1bbb-bb11-11bb11bbbbbb'
|
61
|
+
# }
|
62
|
+
# }
|
63
|
+
#
|
64
|
+
# Set the channels at a later time
|
65
|
+
# dev.channels = [:data]
|
66
|
+
|
67
|
+
dev.connect
|
68
|
+
|
69
|
+
# At this point the client is ready to operate.
|
70
|
+
# Publish one message every second for a minute.
|
71
|
+
|
72
|
+
60.times do
|
73
|
+
# Generate some random data
|
74
|
+
payload = { greetings: 'Hello, World!', temp: rand(20.0..25.0), foo: rand(100..200) }.to_json
|
75
|
+
|
76
|
+
dev.publish :data, payload
|
77
|
+
|
78
|
+
# Give some feedback on what has been published
|
79
|
+
puts "Published #{payload}"
|
80
|
+
|
81
|
+
# Take a nap...
|
82
|
+
sleep 1
|
83
|
+
end
|