mqtt-rails 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE +210 -0
- data/README.md +323 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/mqtt-rails.rb +144 -0
- data/lib/mqtt_rails/client.rb +414 -0
- data/lib/mqtt_rails/connection_helper.rb +172 -0
- data/lib/mqtt_rails/exception.rb +52 -0
- data/lib/mqtt_rails/handler.rb +274 -0
- data/lib/mqtt_rails/packet.rb +33 -0
- data/lib/mqtt_rails/packet/base.rb +315 -0
- data/lib/mqtt_rails/packet/connack.rb +102 -0
- data/lib/mqtt_rails/packet/connect.rb +183 -0
- data/lib/mqtt_rails/packet/disconnect.rb +38 -0
- data/lib/mqtt_rails/packet/pingreq.rb +29 -0
- data/lib/mqtt_rails/packet/pingresp.rb +38 -0
- data/lib/mqtt_rails/packet/puback.rb +44 -0
- data/lib/mqtt_rails/packet/pubcomp.rb +44 -0
- data/lib/mqtt_rails/packet/publish.rb +148 -0
- data/lib/mqtt_rails/packet/pubrec.rb +44 -0
- data/lib/mqtt_rails/packet/pubrel.rb +62 -0
- data/lib/mqtt_rails/packet/suback.rb +75 -0
- data/lib/mqtt_rails/packet/subscribe.rb +124 -0
- data/lib/mqtt_rails/packet/unsuback.rb +49 -0
- data/lib/mqtt_rails/packet/unsubscribe.rb +84 -0
- data/lib/mqtt_rails/publisher.rb +181 -0
- data/lib/mqtt_rails/sender.rb +129 -0
- data/lib/mqtt_rails/ssl_helper.rb +61 -0
- data/lib/mqtt_rails/subscriber.rb +166 -0
- data/lib/mqtt_rails/version.rb +3 -0
- data/mqtt-rails.gemspec +33 -0
- data/samples/client_blocking(reading).rb +29 -0
- data/samples/client_blocking(writing).rb +18 -0
- data/samples/getting_started.rb +49 -0
- data/samples/test_client.rb +69 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '07387e175ea1e3133f15fb9bce534aab019799ebb6472bbe7d48479cb67b9405'
|
4
|
+
data.tar.gz: '0438ddc874e70a232032e23a461081e798d4528191fb821523abd8f5d9a586fb'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d83640e2f6fff6190fe3ab6232d1ab2fc6a6401c4d05cadb17cc6ad9304ea40cf7d80911ae018ddc749cba5436d8566d4278fe755651bd6d239dba6b2eaf44e3
|
7
|
+
data.tar.gz: f70787d2ebfa9bb889c7ec8b50103cc0b429e6cf1b736c9aee3290e6d0b0786e96d448cf8fa59896466051915f4ae32f72ee69614d0118dca73c2e9f0a862fd9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at p-goudet@ruby-dev.jp. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
Eclipse Public License - v 1.0
|
2
|
+
|
3
|
+
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
|
4
|
+
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
|
5
|
+
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
6
|
+
|
7
|
+
1. DEFINITIONS
|
8
|
+
|
9
|
+
"Contribution" means:
|
10
|
+
|
11
|
+
a) in the case of the initial Contributor, the initial code and documentation
|
12
|
+
distributed under this Agreement, and
|
13
|
+
|
14
|
+
b) in the case of each subsequent Contributor:
|
15
|
+
|
16
|
+
i) changes to the Program, and
|
17
|
+
|
18
|
+
ii) additions to the Program;
|
19
|
+
|
20
|
+
where such changes and/or additions to the Program originate from and are
|
21
|
+
distributed by that particular Contributor. A Contribution 'originates' from
|
22
|
+
a Contributor if it was added to the Program by such Contributor itself or
|
23
|
+
anyone acting on such Contributor's behalf. Contributions do not include additions
|
24
|
+
to the Program which: (i) are separate modules of software distributed in
|
25
|
+
conjunction with the Program under their own license agreement, and (ii) are
|
26
|
+
not derivative works of the Program.
|
27
|
+
|
28
|
+
"Contributor" means any person or entity that distributes the Program.
|
29
|
+
|
30
|
+
"Licensed Patents" mean patent claims licensable by a Contributor which are
|
31
|
+
necessarily infringed by the use or sale of its Contribution alone or when
|
32
|
+
combined with the Program.
|
33
|
+
|
34
|
+
"Program" means the Contributions distributed in accordance with this Agreement.
|
35
|
+
|
36
|
+
"Recipient" means anyone who receives the Program under this Agreement, including
|
37
|
+
all Contributors.
|
38
|
+
|
39
|
+
2. GRANT OF RIGHTS
|
40
|
+
|
41
|
+
a) Subject to the terms of this Agreement, each Contributor hereby grants
|
42
|
+
Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce,
|
43
|
+
prepare derivative works of, publicly display, publicly perform, distribute
|
44
|
+
and sublicense the Contribution of such Contributor, if any, and such derivative
|
45
|
+
works, in source code and object code form.
|
46
|
+
|
47
|
+
b) Subject to the terms of this Agreement, each Contributor hereby grants
|
48
|
+
Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
|
49
|
+
Patents to make, use, sell, offer to sell, import and otherwise transfer the
|
50
|
+
Contribution of such Contributor, if any, in source code and object code form.
|
51
|
+
This patent license shall apply to the combination of the Contribution and
|
52
|
+
the Program if, at the time the Contribution is added by the Contributor,
|
53
|
+
such addition of the Contribution causes such combination to be covered by
|
54
|
+
the Licensed Patents. The patent license shall not apply to any other combinations
|
55
|
+
which include the Contribution. No hardware per se is licensed hereunder.
|
56
|
+
|
57
|
+
c) Recipient understands that although each Contributor grants the licenses
|
58
|
+
to its Contributions set forth herein, no assurances are provided by any Contributor
|
59
|
+
that the Program does not infringe the patent or other intellectual property
|
60
|
+
rights of any other entity. Each Contributor disclaims any liability to Recipient
|
61
|
+
for claims brought by any other entity based on infringement of intellectual
|
62
|
+
property rights or otherwise. As a condition to exercising the rights and
|
63
|
+
licenses granted hereunder, each Recipient hereby assumes sole responsibility
|
64
|
+
to secure any other intellectual property rights needed, if any. For example,
|
65
|
+
if a third party patent license is required to allow Recipient to distribute
|
66
|
+
the Program, it is Recipient's responsibility to acquire that license before
|
67
|
+
distributing the Program.
|
68
|
+
|
69
|
+
d) Each Contributor represents that to its knowledge it has sufficient copyright
|
70
|
+
rights in its Contribution, if any, to grant the copyright license set forth
|
71
|
+
in this Agreement.
|
72
|
+
|
73
|
+
3. REQUIREMENTS
|
74
|
+
|
75
|
+
A Contributor may choose to distribute the Program in object code form under
|
76
|
+
its own license agreement, provided that:
|
77
|
+
|
78
|
+
a) it complies with the terms and conditions of this Agreement; and
|
79
|
+
|
80
|
+
b) its license agreement:
|
81
|
+
|
82
|
+
i) effectively disclaims on behalf of all Contributors all warranties and
|
83
|
+
conditions, express and implied, including warranties or conditions of title
|
84
|
+
and non-infringement, and implied warranties or conditions of merchantability
|
85
|
+
and fitness for a particular purpose;
|
86
|
+
|
87
|
+
ii) effectively excludes on behalf of all Contributors all liability for damages,
|
88
|
+
including direct, indirect, special, incidental and consequential damages,
|
89
|
+
such as lost profits;
|
90
|
+
|
91
|
+
iii) states that any provisions which differ from this Agreement are offered
|
92
|
+
by that Contributor alone and not by any other party; and
|
93
|
+
|
94
|
+
iv) states that source code for the Program is available from such Contributor,
|
95
|
+
and informs licensees how to obtain it in a reasonable manner on or through
|
96
|
+
a medium customarily used for software exchange.
|
97
|
+
|
98
|
+
When the Program is made available in source code form:
|
99
|
+
|
100
|
+
a) it must be made available under this Agreement; and
|
101
|
+
|
102
|
+
b) a copy of this Agreement must be included with each copy of the Program.
|
103
|
+
|
104
|
+
Contributors may not remove or alter any copyright notices contained within
|
105
|
+
the Program.
|
106
|
+
|
107
|
+
Each Contributor must identify itself as the originator of its Contribution,
|
108
|
+
if any, in a manner that reasonably allows subsequent Recipients to identify
|
109
|
+
the originator of the Contribution.
|
110
|
+
|
111
|
+
4. COMMERCIAL DISTRIBUTION
|
112
|
+
|
113
|
+
Commercial distributors of software may accept certain responsibilities with
|
114
|
+
respect to end users, business partners and the like. While this license is
|
115
|
+
intended to facilitate the commercial use of the Program, the Contributor
|
116
|
+
who includes the Program in a commercial product offering should do so in
|
117
|
+
a manner which does not create potential liability for other Contributors.
|
118
|
+
Therefore, if a Contributor includes the Program in a commercial product offering,
|
119
|
+
such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
|
120
|
+
every other Contributor ("Indemnified Contributor") against any losses, damages
|
121
|
+
and costs (collectively "Losses") arising from claims, lawsuits and other
|
122
|
+
legal actions brought by a third party against the Indemnified Contributor
|
123
|
+
to the extent caused by the acts or omissions of such Commercial Contributor
|
124
|
+
in connection with its distribution of the Program in a commercial product
|
125
|
+
offering. The obligations in this section do not apply to any claims or Losses
|
126
|
+
relating to any actual or alleged intellectual property infringement. In order
|
127
|
+
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
|
128
|
+
Contributor in writing of such claim, and b) allow the Commercial Contributor
|
129
|
+
to control, and cooperate with the Commercial Contributor in, the defense
|
130
|
+
and any related settlement negotiations. The Indemnified Contributor may participate
|
131
|
+
in any such claim at its own expense.
|
132
|
+
|
133
|
+
For example, a Contributor might include the Program in a commercial product
|
134
|
+
offering, Product X. That Contributor is then a Commercial Contributor. If
|
135
|
+
that Commercial Contributor then makes performance claims, or offers warranties
|
136
|
+
related to Product X, those performance claims and warranties are such Commercial
|
137
|
+
Contributor's responsibility alone. Under this section, the Commercial Contributor
|
138
|
+
would have to defend claims against the other Contributors related to those
|
139
|
+
performance claims and warranties, and if a court requires any other Contributor
|
140
|
+
to pay any damages as a result, the Commercial Contributor must pay those
|
141
|
+
damages.
|
142
|
+
|
143
|
+
5. NO WARRANTY
|
144
|
+
|
145
|
+
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
|
146
|
+
AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS
|
147
|
+
OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
|
148
|
+
TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
149
|
+
Each Recipient is solely responsible for determining the appropriateness of
|
150
|
+
using and distributing the Program and assumes all risks associated with its
|
151
|
+
exercise of rights under this Agreement, including but not limited to the
|
152
|
+
risks and costs of program errors, compliance with applicable laws, damage
|
153
|
+
to or loss of data, programs or equipment, and unavailability or interruption
|
154
|
+
of operations.
|
155
|
+
|
156
|
+
6. DISCLAIMER OF LIABILITY
|
157
|
+
|
158
|
+
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
|
159
|
+
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
160
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
|
161
|
+
LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
162
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
163
|
+
WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
|
164
|
+
GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
165
|
+
|
166
|
+
7. GENERAL
|
167
|
+
|
168
|
+
If any provision of this Agreement is invalid or unenforceable under applicable
|
169
|
+
law, it shall not affect the validity or enforceability of the remainder of
|
170
|
+
the terms of this Agreement, and without further action by the parties hereto,
|
171
|
+
such provision shall be reformed to the minimum extent necessary to make such
|
172
|
+
provision valid and enforceable.
|
173
|
+
|
174
|
+
If Recipient institutes patent litigation against any entity (including a
|
175
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Program itself
|
176
|
+
(excluding combinations of the Program with other software or hardware) infringes
|
177
|
+
such Recipient's patent(s), then such Recipient's rights granted under Section
|
178
|
+
2(b) shall terminate as of the date such litigation is filed.
|
179
|
+
|
180
|
+
All Recipient's rights under this Agreement shall terminate if it fails to
|
181
|
+
comply with any of the material terms or conditions of this Agreement and
|
182
|
+
does not cure such failure in a reasonable period of time after becoming aware
|
183
|
+
of such noncompliance. If all Recipient's rights under this Agreement terminate,
|
184
|
+
Recipient agrees to cease use and distribution of the Program as soon as reasonably
|
185
|
+
practicable. However, Recipient's obligations under this Agreement and any
|
186
|
+
licenses granted by Recipient relating to the Program shall continue and survive.
|
187
|
+
|
188
|
+
Everyone is permitted to copy and distribute copies of this Agreement, but
|
189
|
+
in order to avoid inconsistency the Agreement is copyrighted and may only
|
190
|
+
be modified in the following manner. The Agreement Steward reserves the right
|
191
|
+
to publish new versions (including revisions) of this Agreement from time
|
192
|
+
to time. No one other than the Agreement Steward has the right to modify this
|
193
|
+
Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse
|
194
|
+
Foundation may assign the responsibility to serve as the Agreement Steward
|
195
|
+
to a suitable separate entity. Each new version of the Agreement will be given
|
196
|
+
a distinguishing version number. The Program (including Contributions) may
|
197
|
+
always be distributed subject to the version of the Agreement under which
|
198
|
+
it was received. In addition, after a new version of the Agreement is published,
|
199
|
+
Contributor may elect to distribute the Program (including its Contributions)
|
200
|
+
under the new version. Except as expressly stated in Sections 2(a) and 2(b)
|
201
|
+
above, Recipient receives no rights or licenses to the intellectual property
|
202
|
+
of any Contributor under this Agreement, whether expressly, by implication,
|
203
|
+
estoppel or otherwise. All rights in the Program not expressly granted under
|
204
|
+
this Agreement are reserved.
|
205
|
+
|
206
|
+
This Agreement is governed by the laws of the State of New York and the intellectual
|
207
|
+
property laws of the United States of America. No party to this Agreement
|
208
|
+
will bring a legal action under this Agreement more than one year after the
|
209
|
+
cause of action arose. Each party waives its rights to a jury trial in any
|
210
|
+
resulting litigation.
|
data/README.md
ADDED
@@ -0,0 +1,323 @@
|
|
1
|
+
# MQTT RAILS
|
2
|
+
|
3
|
+
The following file describes the Paho Mqtt client API for the ruby programming language. It enables applications to connect to an MQTT message broker threw the [MQTT](http://mqtt.org/) protocol (versions 3.1.1). MQTT is a lightweight protocol designed for IoT/M2M. A Mqtt client can connect to a message broker in order to publish and received data contained in short messages. The messages are exchanged on topics where the client has to subscribe for receiving message.
|
4
|
+
|
5
|
+
Produced by Ruby development Inc.
|
6
|
+
## Contents
|
7
|
+
* [Installation](#installation)
|
8
|
+
* [Usage](#usage)
|
9
|
+
* [Getting started](#getting-started)
|
10
|
+
* [Client](#client)
|
11
|
+
* [Initialization](#initialization)
|
12
|
+
* [Client's parameters](#clients-parameter)
|
13
|
+
* [Subscription](#subscription)
|
14
|
+
* [Publishing](#publishing)
|
15
|
+
* [Connection configuration](#connection-configuration)
|
16
|
+
* [Unencrypted mode](#unencrypted-mode)
|
17
|
+
* [Encrypted mode](#encrypted-mode)
|
18
|
+
* [Persistence](#persistence)
|
19
|
+
* [Foreground and Daemon](#foreground-and-daemon)
|
20
|
+
* [Control loops](#control-loops)
|
21
|
+
* [Reading loop](#reading-loop)
|
22
|
+
* [Writing loop](#writing-loop)
|
23
|
+
* [Miscellaneous loop](#miscellaneous-loop)
|
24
|
+
* [Handlers and Callbacks](#handlers-and-callbacks)
|
25
|
+
* [Handlers](#handlers)
|
26
|
+
* [Callbacks](#callbacks)
|
27
|
+
* [Mosquitto (message broker)](#mosquitto-message-broker)
|
28
|
+
* [Thanks](#thanks)
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Add this line to your application's Gemfile:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
gem 'mqtt-rails'
|
36
|
+
```
|
37
|
+
|
38
|
+
And then execute:
|
39
|
+
|
40
|
+
$ bundle
|
41
|
+
|
42
|
+
Or install it yourself as:
|
43
|
+
|
44
|
+
$ gem install mqtt-rails
|
45
|
+
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
### Getting started
|
49
|
+
The following samples files cover the main features of the client:
|
50
|
+
```ruby
|
51
|
+
require 'mqtt-rails'
|
52
|
+
|
53
|
+
### Create a simple client with default attributes
|
54
|
+
client = MqttRails::Client.new
|
55
|
+
|
56
|
+
### Register a callback on message event to display messages
|
57
|
+
message_counter = 0
|
58
|
+
client.on_message do |message|
|
59
|
+
puts "Message recieved on topic: #{message.topic}\n>>> #{message.payload}"
|
60
|
+
message_counter += 1
|
61
|
+
end
|
62
|
+
|
63
|
+
### Register a callback on suback to assert the subcription
|
64
|
+
waiting_suback = true
|
65
|
+
client.on_suback do
|
66
|
+
waiting_suback = false
|
67
|
+
puts "Subscribed"
|
68
|
+
end
|
69
|
+
|
70
|
+
### Register a callback for puback event when receiving a puback
|
71
|
+
waiting_puback = true
|
72
|
+
client.on_puback do
|
73
|
+
waiting_puback = false
|
74
|
+
puts "Message Acknowledged"
|
75
|
+
end
|
76
|
+
|
77
|
+
### Connect to the eclipse test server on port 1883 (Unencrypted mode)
|
78
|
+
client.connect('iot.eclipse.org', 1883)
|
79
|
+
|
80
|
+
### Subscribe to a topic
|
81
|
+
client.subscribe(['/paho/ruby/test', 2])
|
82
|
+
|
83
|
+
### Waiting for the suback answer and excute the previously set on_suback callback
|
84
|
+
while waiting_suback do
|
85
|
+
sleep 0.001
|
86
|
+
end
|
87
|
+
|
88
|
+
### Publlish a message on the topic "/paho/ruby/test" with "retain == false" and "qos == 1"
|
89
|
+
client.publish("/paho/ruby/test", "Hello there!", false, 1)
|
90
|
+
|
91
|
+
while waiting_puback do
|
92
|
+
sleep 0.001
|
93
|
+
end
|
94
|
+
|
95
|
+
### Waiting to assert that the message is displayed by on_message callback
|
96
|
+
sleep 1
|
97
|
+
|
98
|
+
### Calling an explicit disconnect
|
99
|
+
client.disconnect
|
100
|
+
```
|
101
|
+
|
102
|
+
## Client
|
103
|
+
### Initialization
|
104
|
+
The client may be initialized without paramaeters or with a hash of parameters. The list of client's accessor is details in the next parts. A client id would be generated if not provided, a default port would be also set (8883 if ssl set, else 1883).
|
105
|
+
```ruby
|
106
|
+
client = MqttRails::Client.new
|
107
|
+
# Or
|
108
|
+
client = MqttRails::Client.new({host: "iot.eclispe.org", port: 1883, ssl: false})
|
109
|
+
```
|
110
|
+
|
111
|
+
### Client's parameters
|
112
|
+
The client has many accessors which help to configure the client depending on user's need. The different accessors could be splited in four roles, connection setup, last will setup, time-out setup and callback setup.
|
113
|
+
Connection setup:
|
114
|
+
```
|
115
|
+
* host : The endpoint where the client would try to connect (defaut "")
|
116
|
+
* port : The port on the remote host where the socket would try to connect (default 1883)
|
117
|
+
* mqtt_version : The version of MQTT protocol used to communication (default 3.1.1)
|
118
|
+
* clean_session : If set to false, ask the message broker to try to restore the previous session (default true)
|
119
|
+
* persistent : Keep the client connected even after keep alive timer run out, automatically try to reconnect on failure (default false)
|
120
|
+
* reconnect_limit : If persistent mode is enabled, the maximum reconnect attempt (default 3)
|
121
|
+
* reconnect_delay : If persistent mode is enabled, the delay between to reconnection attempt in second (default 5)
|
122
|
+
* client_id : The identifier of the client (default nil)
|
123
|
+
* username : The username if the server require authentication (default nil)
|
124
|
+
* password : The password of the user if authentication required (default nil)
|
125
|
+
* ssl : Requiring the encryption for the communication (default false)
|
126
|
+
```
|
127
|
+
|
128
|
+
Last Will:
|
129
|
+
```
|
130
|
+
* will_topic : The topic where to publish the last will (default nil)
|
131
|
+
* will_payload : The message of the last will (default "")
|
132
|
+
* will_qos : The qos of the last will (default 0)
|
133
|
+
* will_retain : The retain status of the last will (default false)
|
134
|
+
```
|
135
|
+
|
136
|
+
Timers:
|
137
|
+
```
|
138
|
+
* keep_alive : The reference timer after which the client should decide to keep the connection alive or not
|
139
|
+
* ack_timeout : The timer after which a non-acknowledged packet is considered as a failure
|
140
|
+
```
|
141
|
+
|
142
|
+
The description of the callback accessor is detailed in the section dedicated to the callbacks. The client also have three read only attributes which provide information on the client state.
|
143
|
+
```
|
144
|
+
* registered_callback : The list of topics where callback have been registred which the associated callback
|
145
|
+
* subscribed_topics : The list of the topics where the client is currentely receiving publish.
|
146
|
+
* connection_state : The current state of the connection between the message broker and the client
|
147
|
+
```
|
148
|
+
|
149
|
+
### Subscription
|
150
|
+
In order to read a message sent on a topic, the client should subscribe to this topic. The client enables to subscribe to several topics in the same subscribe request. The subscription could also be done by using a wild-card, see more details on [MQTT protocol specifications](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html). Each topic is subscribed with a maximum qos level, only message with a qos level lower or equal to this value would be forwarded to the client. The subscribe command accepts one or several pair, each pair is composed by the topic (or wild-card) and the maximum qos level.
|
151
|
+
```ruby
|
152
|
+
### Subscribe to two topics with maximum qos associated
|
153
|
+
client.subscribe(["/foo/bar", 1], ["/foo/foo/", 2])
|
154
|
+
```
|
155
|
+
|
156
|
+
The subscription is persistent, in case of an unexpected disconnecting, the current subscription state is saved and a new subscribe request is sent to the message broker.
|
157
|
+
|
158
|
+
### Publishing
|
159
|
+
User data could be sent to the message broker with the publish operation. A publish operation requires a topic, and payload (user data), two other parameters may be configured, retain and qos. The retain flag tell to the message broker to keep the current publish packet, see the [MQTT protocol specifications](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) for more details about retain. The qos enable different levels of control on the transmission of publish package. The MqttRails client supports the three levels of qos (0, 1 and 2), see the [MQTT protocol specifications](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) for qos level details. The default retain value is False and the qos level is 0.
|
160
|
+
```ruby
|
161
|
+
### Publish to the topics "/foo/bar", with qos = 1 and no retain
|
162
|
+
client.publish("/foo/bar", "Hello Wourld!", false, 1)
|
163
|
+
```
|
164
|
+
|
165
|
+
## Connection configuration
|
166
|
+
### Unencrypted mode
|
167
|
+
The most simple connection way is the unencrypted mode. All data would be sent clearly to the message broker, also it might not be safe for sensitive data. The connect method may set up or override some parameters of the client, the host, the port, the keep_alive timer, the persistence mode and blocking mode.
|
168
|
+
```ruby
|
169
|
+
### Simply connect to the message broker with default value or pre-set value
|
170
|
+
client.connect
|
171
|
+
# Or
|
172
|
+
### Connect to the message broker with all parameter
|
173
|
+
client.connect("iot.eclipse.org", 1883, client.keep_alive, client.persistent, client.blocking)
|
174
|
+
```
|
175
|
+
|
176
|
+
### Encrypted mode
|
177
|
+
The client supports the encrypted connection threw tls-ssl socket. In order to use encrypted mode, the ssl flag of the client should be set to True.
|
178
|
+
``` ruby
|
179
|
+
### Set the encryption mode to True
|
180
|
+
client.ssl = true
|
181
|
+
### Configure the user SSL key and the certificate
|
182
|
+
client.config_ssl_context(certificate_path, key_path)
|
183
|
+
client.connect("test.mosquitto.org", 8883)
|
184
|
+
### Or if rootCA is needed
|
185
|
+
client.config_ssl_context(certificate_path, key_path, rootCA_path)
|
186
|
+
client.connect("test.mosquitto.org", 8884)
|
187
|
+
```
|
188
|
+
|
189
|
+
### Persistence
|
190
|
+
The client holds a keep_alive timer is the reference time that the connection should be held. The timer is reset every time a new valid packet is received from the message broker. The persistence flag, when set to True, enables the client to be more independent from the keep_alive timer. Just before the keep_alive run out, the client sends a ping request to tell to the message broker that the connection should be kept. The persistent mode also enables the client to automatically reconnect to the message broker after an unexpected failure.
|
191
|
+
When the client's persistence flag is set to False, it just simply disconnects when the keep_alive timer runs out.
|
192
|
+
```ruby
|
193
|
+
### This will connect to the message broker, keep connected and automatically reconnect on failure
|
194
|
+
client.connect('iot.eclipse.org', 1883, client.keep_alive, true, client.blocking)
|
195
|
+
#Or
|
196
|
+
### This only connect to the message broker, disconnect after keep_alive or on failure
|
197
|
+
client.connect('iot.eclipse.org', 1883, client.keep_alive, false, client.blocking)
|
198
|
+
```
|
199
|
+
The client has two attributes `@reconnect_limit` and `@reconnect_delay` which configure the reconnection process. `@reconnection_limit` is the maximum reconnection attempt that a client could try and `@reconnection_delay` is the delay that the client waits between two reconnection attempt. Setting the `@reconnect_limit` to -1 would run the reconnection process forever.
|
200
|
+
|
201
|
+
### Foreground and Daemon
|
202
|
+
The client could be connected to the message broker using the main thread in foreground or as a daemon in a separate thread. The default mode is daemon mode, the daemon would run in the background the read/write operation as well as the control of the timers. If the client is connected using the main thread, all control operations are left to the user, using the different control loops. There are four different loop roles is detailed in the next part.
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
### Connect to the message broker executing the mqtt_loop (socket reading/writing) in the background
|
206
|
+
client.connect('iot.eclipse.org', 1883, client.keep_alive, client.persistence, true)
|
207
|
+
#Or
|
208
|
+
### This only connect to the message broker, nothing more
|
209
|
+
client.connect('iot.eclipse.org', 1883, client.keep_alive, client.persistence, false)
|
210
|
+
```
|
211
|
+
|
212
|
+
## Control loops
|
213
|
+
/!\ The control loops should not be used in a daemon mode.
|
214
|
+
They are automatically run in separate thread and execute the necessary operations for reading, writing and checking the connection state.
|
215
|
+
|
216
|
+
### Reading loop
|
217
|
+
The reading loop provides access to the socket in a reading mode. Periodically, the socket would be inspected to try to find a mqtt packet. The read loop accepts a parameter, which is the number of loop's turn. The default value is five turns.
|
218
|
+
The default value is defined in the MqttRails module as the constant MqttRails::MAX_READ, another module constant could be modified to control the socket inspection period. The referring constant is SELECT_TIMEOUT (MqttRails::SELECT_TIMEOUT) and its default value is 0.
|
219
|
+
```ruby
|
220
|
+
### Trying to read 'max_packet' packets from the client socket
|
221
|
+
client.loop_read(max_packet)
|
222
|
+
```
|
223
|
+
|
224
|
+
### Writing loop
|
225
|
+
The writing loop send the packets which have previously been stacked by MQTT operations. This loop also accepts a parameter, which is the maximum packets number that could be written as the MAX_WRITING constant (MqttRails::MAX_WRITING). The writing loop exit if the maximum number of packet have been sent or if the waiting packet queue is empty.
|
226
|
+
```ruby
|
227
|
+
### Writing 'max_packet' packets to the client socket
|
228
|
+
client.loop_write(max_packet)
|
229
|
+
```
|
230
|
+
|
231
|
+
### Miscellaneous loop
|
232
|
+
The misc loop performs different control operations, modifying the packets states and the connection state. The misc loop parses the different queue of packet that are waiting for an acknowledgement. If the ack_timeout of a packet had run out, the packet is re-sent. The size of the different waiting queues is defined as module constants. This loop also asserts that the connection is still available by checking the keep_alive timer.
|
233
|
+
```ruby
|
234
|
+
### Perfom control operations on packets queues and connection
|
235
|
+
client.loop_misc
|
236
|
+
```
|
237
|
+
|
238
|
+
## Handlers and Callbacks
|
239
|
+
### Handlers
|
240
|
+
When a packet is received and inspected, an appropriate handler is called. The handler performs different control operation such as update the connection state, update the subscribed topics, and send publish control packets. Each packet has a specific handler, except the pingreq/pingresp packet. Before returning the handler executes a callback, if the user has configured one for this type of packet. The publish handler may execute sequentially two callbacks. One callback for the reception of a generic publish packet and another one, if the user has configured a callback for the topic where the publish packet has been received.
|
241
|
+
|
242
|
+
### Callbacks
|
243
|
+
The callbacks could be defined in a three different ways, as block, as Proc or as Lambda. The callback has access to the packet which triggered it.
|
244
|
+
```ruby
|
245
|
+
### Register a callback trigger on the reception of a CONNACK packet with return code 0x00
|
246
|
+
client.on_connack = proc { puts "Successfully Connected" }
|
247
|
+
|
248
|
+
### Register a callback trigger on the reception of PUBLISH packet
|
249
|
+
client.on_message do |packet|
|
250
|
+
puts "New message received on topic: #{packet.topic}\n>>>#{packet.payload}"
|
251
|
+
end
|
252
|
+
```
|
253
|
+
|
254
|
+
A callback could be configured for every specific topics. The list of topics where a callbacks have been registered could be read at any time, threw the registered_callback variable. The following example details how to manage callbacks for specific topics.
|
255
|
+
```ruby
|
256
|
+
### Add a callback for every message received on /foo/bar
|
257
|
+
specific_callback = lambda { |packet| puts "Specific callback for #{packet.topic}" }
|
258
|
+
client.add_topic_callback("/foo/bar", specific_callback)
|
259
|
+
# Or
|
260
|
+
client.add_topic_callback("/foo/bar") do |packet|
|
261
|
+
puts "Specific callback for #{packet.topic}"
|
262
|
+
end
|
263
|
+
|
264
|
+
### To remove a callback form a topic
|
265
|
+
client.remove_topic_callback("/foo/bar")
|
266
|
+
```
|
267
|
+
|
268
|
+
## Mosquitto (message broker)
|
269
|
+
Mosquitto is a message broker support by Eclipse, which is quite easy-going. In order to run spec or samples files, a message broker is needed. Mosquitto enable to run locally a message broker, it could be configured with the mosquitto.conf files.
|
270
|
+
### Install mosquitto
|
271
|
+
#### OSX (homebrew)
|
272
|
+
```
|
273
|
+
$ brew install mosquitto
|
274
|
+
```
|
275
|
+
### Run mosquitto
|
276
|
+
#### Default mode
|
277
|
+
The default mode of mosquitto is unencrypted, listening on the port 1883.
|
278
|
+
```
|
279
|
+
$ mosquitto
|
280
|
+
```
|
281
|
+
|
282
|
+
#### Encrypted mode
|
283
|
+
In order to successfully pass the spec, or for testing in encrypted mode, some configurations are needed on mosquitto. Private keys and certificates should be set on both client side and server side. The [mosquitto-tls](https://mosquitto.org/man/mosquitto-tls-7.html) page might help you create all the required credentials. Once the credentials are created, the mosquitto's config files should be updated as following.
|
284
|
+
|
285
|
+
```
|
286
|
+
$ cp mosquitto.conf samples-mosquitto.conf
|
287
|
+
$ nano mosquitto.conf
|
288
|
+
```
|
289
|
+
|
290
|
+
The following file enables the broker to support the unencrypted mode (default) on port 1883, and the encrypted mode on port 8883. Update the path variable with the file's location on your environment.
|
291
|
+
```
|
292
|
+
### mosquitto.conf
|
293
|
+
# =================================================================
|
294
|
+
# General configuration
|
295
|
+
# =================================================================
|
296
|
+
.
|
297
|
+
.
|
298
|
+
.
|
299
|
+
# =================================================================
|
300
|
+
# Extra listeners
|
301
|
+
# =================================================================
|
302
|
+
.
|
303
|
+
.
|
304
|
+
listener 8883
|
305
|
+
.
|
306
|
+
.
|
307
|
+
cafile "Path to the certificate authorithy certificate file"
|
308
|
+
certfile "Path to the server certificate file"
|
309
|
+
keyfile "Path to the server private keys file"
|
310
|
+
.
|
311
|
+
.
|
312
|
+
.
|
313
|
+
```
|
314
|
+
Finally run the server with the updated configuration file.
|
315
|
+
|
316
|
+
```
|
317
|
+
$ mosquitto -c mosquitto.conf
|
318
|
+
```
|
319
|
+
|
320
|
+
See [Mosquitto message broker page](https://mosquitto.org/) for more details.
|
321
|
+
|
322
|
+
## Thanks
|
323
|
+
Special thanks to [Nicholas Humfrey](https://github.com/njh) for providing a great help with the packet serializer/deserializer.
|