mqtt-rails 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +210 -0
  8. data/README.md +323 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/mqtt-rails.rb +144 -0
  13. data/lib/mqtt_rails/client.rb +414 -0
  14. data/lib/mqtt_rails/connection_helper.rb +172 -0
  15. data/lib/mqtt_rails/exception.rb +52 -0
  16. data/lib/mqtt_rails/handler.rb +274 -0
  17. data/lib/mqtt_rails/packet.rb +33 -0
  18. data/lib/mqtt_rails/packet/base.rb +315 -0
  19. data/lib/mqtt_rails/packet/connack.rb +102 -0
  20. data/lib/mqtt_rails/packet/connect.rb +183 -0
  21. data/lib/mqtt_rails/packet/disconnect.rb +38 -0
  22. data/lib/mqtt_rails/packet/pingreq.rb +29 -0
  23. data/lib/mqtt_rails/packet/pingresp.rb +38 -0
  24. data/lib/mqtt_rails/packet/puback.rb +44 -0
  25. data/lib/mqtt_rails/packet/pubcomp.rb +44 -0
  26. data/lib/mqtt_rails/packet/publish.rb +148 -0
  27. data/lib/mqtt_rails/packet/pubrec.rb +44 -0
  28. data/lib/mqtt_rails/packet/pubrel.rb +62 -0
  29. data/lib/mqtt_rails/packet/suback.rb +75 -0
  30. data/lib/mqtt_rails/packet/subscribe.rb +124 -0
  31. data/lib/mqtt_rails/packet/unsuback.rb +49 -0
  32. data/lib/mqtt_rails/packet/unsubscribe.rb +84 -0
  33. data/lib/mqtt_rails/publisher.rb +181 -0
  34. data/lib/mqtt_rails/sender.rb +129 -0
  35. data/lib/mqtt_rails/ssl_helper.rb +61 -0
  36. data/lib/mqtt_rails/subscriber.rb +166 -0
  37. data/lib/mqtt_rails/version.rb +3 -0
  38. data/mqtt-rails.gemspec +33 -0
  39. data/samples/client_blocking(reading).rb +29 -0
  40. data/samples/client_blocking(writing).rb +18 -0
  41. data/samples/getting_started.rb +49 -0
  42. data/samples/test_client.rb +69 -0
  43. metadata +126 -0
@@ -0,0 +1,183 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Connect < MqttRails::Packet::Base
23
+ # The name of the protocol
24
+ attr_accessor :protocol_name
25
+
26
+ # The version number of the protocol
27
+ attr_accessor :protocol_level
28
+
29
+ # The client identifier string
30
+ attr_accessor :client_id
31
+
32
+ # Set to false to keep a persistent session with the server
33
+ attr_accessor :clean_session
34
+
35
+ # Period the server should keep connection open for between pings
36
+ attr_accessor :keep_alive
37
+
38
+ # The topic name to send the Will message to
39
+ attr_accessor :will_topic
40
+
41
+ # The QoS level to send the Will message as
42
+ attr_accessor :will_qos
43
+
44
+ # Set to true to make the Will message retained
45
+ attr_accessor :will_retain
46
+
47
+ # The payload of the Will message
48
+ attr_accessor :will_payload
49
+
50
+ # The username for authenticating with the server
51
+ attr_accessor :username
52
+
53
+ # The password for authenticating with the server
54
+ attr_accessor :password
55
+
56
+ # Default attribute values
57
+ ATTR_DEFAULTS = {
58
+ :client_id => nil,
59
+ :clean_session => true,
60
+ :keep_alive => 15,
61
+ :will_topic => nil,
62
+ :will_qos => 0,
63
+ :will_retain => false,
64
+ :will_payload => '',
65
+ :username => nil,
66
+ :password => nil,
67
+ }
68
+
69
+ # Create a new Client Connect packet
70
+ def initialize(args={})
71
+ super(ATTR_DEFAULTS.merge(args))
72
+
73
+ if version == '3.1.0' || version == '3.1'
74
+ self.protocol_name ||= 'MQIsdp'
75
+ self.protocol_level ||= 0x03
76
+ elsif version == '3.1.1'
77
+ self.protocol_name ||= 'MQTT'
78
+ self.protocol_level ||= 0x04
79
+ else
80
+ raise MqttRails::PacketFormatException.new(
81
+ "Unsupported protocol version: #{version}")
82
+ end
83
+ end
84
+
85
+ # Get serialisation of packet's body
86
+ def encode_body
87
+ body = ''
88
+ check_version
89
+ body += encode_string(@protocol_name)
90
+ body += encode_bytes(@protocol_level.to_i)
91
+ if @keep_alive < 0
92
+ raise MqttRails::PacketFormatException.new(
93
+ "Invalid keep-alive value: cannot be less than 0")
94
+ end
95
+
96
+ body += encode_flags(@connect_flags)
97
+ body += encode_short(@keep_alive)
98
+ body += encode_string(@client_id)
99
+ unless will_topic.nil?
100
+ body += encode_string(@will_topic)
101
+ # The MQTT v3.1 specification says that the payload is a UTF-8 string
102
+ body += encode_string(@will_payload)
103
+ end
104
+ body += encode_string(@username) unless @username.nil?
105
+ body += encode_string(@password) unless @password.nil?
106
+ body
107
+ end
108
+
109
+ def check_version
110
+ if @version == '3.1.0'
111
+ if @client_id.nil? || @client_id.bytesize < 1
112
+ raise MqttRails::PacketFormatException.new(
113
+ "Client identifier too short while serialising packet")
114
+ elsif @client_id.bytesize > 23
115
+ raise MqttRails::PacketFormatException.new(
116
+ "Client identifier too long when serialising packet")
117
+ end
118
+ end
119
+ end
120
+
121
+ def encode_flags(flags)
122
+ # Set the Connect flags
123
+ flags = 0
124
+ flags |= 0x02 if @clean_session
125
+ flags |= 0x04 unless @will_topic.nil?
126
+ flags |= ((@will_qos & 0x03) << 3)
127
+ flags |= 0x20 if @will_retain
128
+ flags |= 0x40 unless @password.nil?
129
+ flags |= 0x80 unless @username.nil?
130
+ encode_bytes(flags)
131
+ end
132
+
133
+ # Parse the body (variable header and payload) of a Connect packet
134
+ def parse_body(buffer)
135
+ super(buffer)
136
+ @protocol_name = shift_string(buffer)
137
+ @protocol_level = shift_byte(buffer).to_i
138
+ if @protocol_name == 'MQIsdp' && @protocol_level == 3
139
+ @version = '3.1.0'
140
+ elsif @protocol_name == 'MQTT' && @protocol_level == 4
141
+ @version = '3.1.1'
142
+ else
143
+ raise MqttRails::PacketFormatException.new(
144
+ "Unsupported protocol: #{@protocol_name}/#{@protocol_level}")
145
+ end
146
+
147
+ @connect_flags = shift_byte(buffer)
148
+ @keep_alive = shift_short(buffer)
149
+ @client_id = shift_string(buffer)
150
+ parse_connect_flags(@connect_flag, buffer)
151
+ end
152
+
153
+ def parse_connect_flags(flags, buffer)
154
+ @clean_session = ((@connect_flags & 0x02) >> 1) == 0x01
155
+ if ((flags & 0x04) >> 2) == 0x01
156
+ # Last Will and Testament
157
+ @will_qos = ((flags & 0x18) >> 3)
158
+ @will_retain = ((flags & 0x20) >> 5) == 0x01
159
+ @will_topic = shift_string(buffer)
160
+ # The MQTT v3.1 specification says that the payload is a UTF-8 string
161
+ @will_payload = shift_string(buffer)
162
+ end
163
+ if ((@connect_flags & 0x80) >> 7) == 0x01 && buffer.bytesize > 0
164
+ @username = shift_string(buffer)
165
+ end
166
+ if ((@connect_flags & 0x40) >> 6) == 0x01 && buffer.bytesize > 0
167
+ @password = shift_string(buffer)
168
+ end
169
+ end
170
+
171
+ # Returns a human readable string, summarising the properties of the packet
172
+ def inspect
173
+ str = "\#<#{self.class}: "
174
+ str += "keep_alive=#{keep_alive}"
175
+ str += ", clean" if clean_session
176
+ str += ", client_id='#{client_id}'"
177
+ str += ", username='#{username}'" unless username.nil?
178
+ str += ", password=..." unless password.nil?
179
+ str += ">"
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Disconnect < MqttRails::Packet::Base
23
+ # Create a new Client Disconnect packet
24
+ def initialize(args={})
25
+ super(args)
26
+ end
27
+
28
+ # Check the body
29
+ def parse_body(buffer)
30
+ super(buffer)
31
+ unless buffer.empty?
32
+ raise PacketFormatException.new(
33
+ "Extra bytes at the end of Disconnect packet")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Pingreq < MqttRails::Packet::Base
23
+ # Create a new Ping Request packet
24
+ def initialize(args={})
25
+ super(args)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Pingresp < MqttRails::Packet::Base
23
+ # Create a new Ping Response packet
24
+ def initialize(args={})
25
+ super(args)
26
+ end
27
+
28
+ # Check the body
29
+ def parse_body(buffer)
30
+ super(buffer)
31
+ unless buffer.empty?
32
+ raise MqttRails::PacketFormatException.new(
33
+ "Extra bytes at end of Ping Response packet")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Puback < MqttRails::Packet::Base
23
+ # Get serialisation of packet's body
24
+ def encode_body
25
+ encode_short(@id)
26
+ end
27
+
28
+ # Parse the body (variable header and payload) of a packet
29
+ def parse_body(buffer)
30
+ super(buffer)
31
+ @id = shift_short(buffer)
32
+ unless buffer.empty?
33
+ raise MqttRails::PacketFormatException.new(
34
+ "Extra bytes at end of Publish Acknowledgment packet")
35
+ end
36
+ end
37
+
38
+ # Returns a human readable string, summarising the properties of the packet
39
+ def inspect
40
+ "\#<#{self.class}: 0x%2.2X>" % id
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Pubcomp < MqttRails::Packet::Base
23
+ # Get serialisation of packet's body
24
+ def encode_body
25
+ encode_short(@id)
26
+ end
27
+
28
+ # Parse the body (variable header and payload) of a packet
29
+ def parse_body(buffer)
30
+ super(buffer)
31
+ @id = shift_short(buffer)
32
+ unless buffer.empty?
33
+ raise MqttRails::PacketFormatException.new(
34
+ "Extra bytes at end of Publish Complete packet")
35
+ end
36
+ end
37
+
38
+ # Returns a human readable string, summarising the properties of the packet
39
+ def inspect
40
+ "\#<#{self.class}: 0x%2.2X>" % id
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,148 @@
1
+ # encoding: BINARY
2
+ ### original file from the ruby-mqtt gem
3
+ ### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
4
+ ### Copyright (c) 2009-2013 Nicholas J Humfrey
5
+
6
+ # Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
7
+ #
8
+ # All rights reserved. This program and the accompanying materials
9
+ # are made available under the terms of the Eclipse Public License v1.0
10
+ # and Eclipse Distribution License v1.0 which accompany this distribution.
11
+ #
12
+ # The Eclipse Public License is available at
13
+ # https://eclipse.org/org/documents/epl-v10.php.
14
+ # and the Eclipse Distribution License is available at
15
+ # https://eclipse.org/org/documents/edl-v10.php.
16
+ #
17
+ # Contributors:
18
+ # Pierre Goudet - initial committer
19
+
20
+ module MqttRails
21
+ module Packet
22
+ class Publish < MqttRails::Packet::Base
23
+ # Duplicate delivery flag
24
+ attr_accessor :duplicate
25
+
26
+ # Retain flag
27
+ attr_accessor :retain
28
+
29
+ # Quality of Service level (0, 1, 2)
30
+ attr_accessor :qos
31
+
32
+ # The topic name to publish to
33
+ attr_accessor :topic
34
+
35
+ # The data to be published
36
+ attr_accessor :payload
37
+
38
+ # Default attribute values
39
+ ATTR_DEFAULTS = {
40
+ :topic => nil,
41
+ :payload => ''
42
+ }
43
+
44
+ # Create a new Publish packet
45
+ def initialize(args={})
46
+ super(ATTR_DEFAULTS.merge(args))
47
+ end
48
+
49
+ def duplicate
50
+ @flags[3]
51
+ end
52
+
53
+ # Set the DUP flag (true/false)
54
+ def duplicate=(arg)
55
+ if arg.kind_of?(Integer)
56
+ @flags[3] = (arg == 0x1)
57
+ else
58
+ @flags[3] = arg
59
+ end
60
+ end
61
+
62
+ def retain
63
+ @flags[0]
64
+ end
65
+
66
+ # Set the retain flag (true/false)
67
+ def retain=(arg)
68
+ if arg.kind_of?(Integer)
69
+ @flags[0] = (arg == 0x1)
70
+ else
71
+ @flags[0] = arg
72
+ end
73
+ end
74
+
75
+ def qos
76
+ (@flags[1] ? 0x01 : 0x00) | (@flags[2] ? 0x02 : 0x00)
77
+ end
78
+
79
+ # Set the Quality of Service level (0/1/2)
80
+ def qos=(arg)
81
+ @qos = arg.to_i
82
+ if @qos < 0 || @qos > 2
83
+ raise MqttRails::PacketFormatException.new(
84
+ "Invalid QoS value: #{@qos}")
85
+ else
86
+ @flags[1] = (arg & 0x01 == 0x01)
87
+ @flags[2] = (arg & 0x02 == 0x02)
88
+ end
89
+ end
90
+
91
+ # Get serialisation of packet's body
92
+ def encode_body
93
+ body = ''
94
+ if @topic.nil? || @topic.to_s.empty?
95
+ raise MqttRails::PacketFormatException.new(
96
+ "Invalid topic name when serialising packet")
97
+ end
98
+ body += encode_string(@topic)
99
+ body += encode_short(@id) unless qos == 0
100
+ body += payload.to_s.dup.force_encoding('ASCII-8BIT')
101
+ return body
102
+ end
103
+
104
+ # Parse the body (variable header and payload) of a Publish packet
105
+ def parse_body(buffer)
106
+ super(buffer)
107
+ @topic = shift_string(buffer)
108
+ @id = shift_short(buffer) unless qos == 0
109
+ @payload = buffer
110
+ end
111
+
112
+ # Check that fixed header flags are valid for this packet type
113
+ # @private
114
+ def validate_flags
115
+ if qos == 3
116
+ raise MqttRails::PacketFormatException.new(
117
+ "Invalid packet: QoS value of 3 is not allowed")
118
+ end
119
+ if qos == 0 && duplicate
120
+ raise MqttRails::PacketFormatException.new(
121
+ "Invalid packet: DUP cannot be set for QoS 0")
122
+ end
123
+ end
124
+
125
+ # Returns a human readable string, summarising the properties of the packet
126
+ def inspect
127
+ "\#<#{self.class}: " +
128
+ "d#{duplicate ? '1' : '0'}, " +
129
+ "q#{qos}, " +
130
+ "r#{retain ? '1' : '0'}, " +
131
+ "m#{id}, " +
132
+ "'#{topic}', " +
133
+ "#{inspect_payload}>"
134
+ end
135
+
136
+ protected
137
+
138
+ def inspect_payload
139
+ str = payload.to_s
140
+ if str.bytesize < 16 && str =~ /^[ -~]*$/
141
+ "'#{str}'"
142
+ else
143
+ "... (#{str.bytesize} bytes)"
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end