mqtt-rails 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 (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