mqtt 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -1,6 +1,21 @@
1
1
  Ruby MQTT NEWS
2
2
  ==============
3
3
 
4
+ Ruby MQTT Version 0.2.0 (2014-04-02)
5
+ ------------------------------------
6
+
7
+ * Added SSL/TLS support
8
+ * Added support for passing connection details using a URI
9
+ * Added support for using the MQTT_BROKER environment variable
10
+ * Allow passing array of topics to Client#unsubscribe
11
+ * Allow more combinations of arguments to be passed to a new Client
12
+ * No longer defaults to ‘localhost’ if there is no broker configured
13
+ * Fixed more 'unused variable' warnings
14
+ * Documentation improvements
15
+ * Ruby 1.8 fixes
16
+ * Ruby 2 fixes
17
+
18
+
4
19
  Ruby MQTT Version 0.1.0 (2013-09-07)
5
20
  ------------------------------------
6
21
 
@@ -1,8 +1,7 @@
1
1
  ruby-mqtt
2
2
  =========
3
3
 
4
- Pure Ruby gem that implements the MQTT (Message Queue Telemetry Transport) protocol,
5
- a lightweight protocol for publish/subscribe messaging.
4
+ Pure Ruby gem that implements the MQTT protocol, a lightweight protocol for publish/subscribe messaging.
6
5
 
7
6
 
8
7
  Installing
@@ -46,12 +45,14 @@ Resources
46
45
  * GitHub Project: http://github.com/njh/ruby-mqtt
47
46
  * API Documentation: http://rubydoc.info/gems/mqtt/frames
48
47
 
48
+
49
49
  License
50
50
  -------
51
51
 
52
52
  The ruby-mqtt gem is licensed under the terms of the MIT license.
53
53
  See the file LICENSE for details.
54
54
 
55
+
55
56
  Contact
56
57
  -------
57
58
 
@@ -14,15 +14,24 @@ end
14
14
 
15
15
  module MQTT
16
16
 
17
- DEFAULT_HOST = 'localhost'
17
+ # Default port number for unencrypted connections
18
18
  DEFAULT_PORT = 1883
19
+
20
+ # Default port number for TLS/SSL encrypted connections
21
+ DEFAULT_SSL_PORT = 8883
19
22
 
23
+ # Super-class for other MQTT related exceptions
20
24
  class Exception < Exception
21
25
  end
22
26
 
27
+ # A ProtocolException will be raised if there is a
28
+ # problem with data received from a remote host
23
29
  class ProtocolException < MQTT::Exception
24
30
  end
25
31
 
32
+ # A NotConnectedException will be raised when trying to
33
+ # perform a function but no connection has been
34
+ # established
26
35
  class NotConnectedException < MQTT::Exception
27
36
  end
28
37
 
@@ -1,29 +1,63 @@
1
+ autoload :OpenSSL, 'openssl'
2
+ autoload :URI, 'uri'
3
+
4
+
1
5
  # Client class for talking to an MQTT broker
2
6
  class MQTT::Client
3
- attr_reader :remote_host # Hostname of the remote broker
4
- attr_reader :remote_port # Port number of the remote broker
5
- attr_accessor :keep_alive # Time (in seconds) between pings to remote broker
6
- attr_accessor :clean_session # Set the 'Clean Session' flag when connecting?
7
- attr_accessor :client_id # Client Identifier
8
- attr_accessor :ack_timeout # Number of seconds to wait for acknowledgement packets
9
- attr_accessor :username # Username to authenticate to the broker with
10
- attr_accessor :password # Password to authenticate to the broker with
11
- attr_accessor :will_topic # The topic that the Will message is published to
12
- attr_accessor :will_payload # Contents of message that is sent by broker when client disconnect
13
- attr_accessor :will_qos # The QoS level of the will message sent by the broker
14
- attr_accessor :will_retain # If the Will message should be retain by the broker after it is sent
15
-
16
- # OLD deprecated clean_start
17
- alias :clean_start :clean_session
18
- alias :clean_start= :clean_session=
7
+ # Hostname of the remote broker
8
+ attr_accessor :remote_host
9
+
10
+ # Port number of the remote broker
11
+ attr_accessor :remote_port
12
+
13
+ # Set to true to enable SSL/TLS encrypted communication
14
+ #
15
+ # Set to a symbol to use a specific variant of SSL/TLS.
16
+ # Allowed values include:
17
+ #
18
+ # @example Using TLS 1.0
19
+ # client = Client.new('mqtt.example.com', :ssl => :TLSv1)
20
+ # @see OpenSSL::SSL::SSLContext::METHODS
21
+ attr_accessor :ssl
22
+
23
+ # Time (in seconds) between pings to remote broker
24
+ attr_accessor :keep_alive
25
+
26
+ # Set the 'Clean Session' flag when connecting?
27
+ attr_accessor :clean_session
28
+
29
+ # Client Identifier
30
+ attr_accessor :client_id
31
+
32
+ # Number of seconds to wait for acknowledgement packets
33
+ attr_accessor :ack_timeout
34
+
35
+ # Username to authenticate to the broker with
36
+ attr_accessor :username
37
+
38
+ # Password to authenticate to the broker with
39
+ attr_accessor :password
40
+
41
+ # The topic that the Will message is published to
42
+ attr_accessor :will_topic
43
+
44
+ # Contents of message that is sent by broker when client disconnect
45
+ attr_accessor :will_payload
46
+
47
+ # The QoS level of the will message sent by the broker
48
+ attr_accessor :will_qos
49
+
50
+ # If the Will message should be retain by the broker after it is sent
51
+ attr_accessor :will_retain
52
+
19
53
 
20
54
  # Timeout between select polls (in seconds)
21
55
  SELECT_TIMEOUT = 0.5
22
56
 
23
57
  # Default attribute values
24
58
  ATTR_DEFAULTS = {
25
- :remote_host => MQTT::DEFAULT_HOST,
26
- :remote_port => MQTT::DEFAULT_PORT,
59
+ :remote_host => nil,
60
+ :remote_port => nil,
27
61
  :keep_alive => 15,
28
62
  :clean_session => true,
29
63
  :client_id => nil,
@@ -33,10 +67,12 @@ class MQTT::Client
33
67
  :will_topic => nil,
34
68
  :will_payload => nil,
35
69
  :will_qos => 0,
36
- :will_retain => false
70
+ :will_retain => false,
71
+ :ssl => false
37
72
  }
38
73
 
39
74
  # Create and connect a new MQTT Client
75
+ #
40
76
  # Accepts the same arguments as creating a new client.
41
77
  # If a block is given, then it will be executed before disconnecting again.
42
78
  #
@@ -71,28 +107,63 @@ class MQTT::Client
71
107
 
72
108
  # Create a new MQTT Client instance
73
109
  #
110
+ # Accepts one of the following:
111
+ # - a URI that uses the MQTT scheme
112
+ # - a hostname and port
113
+ # - a Hash containing attributes to be set on the new instance
114
+ #
115
+ # If no arguments are given then the method will look for a URI
116
+ # in the MQTT_BROKER environment variable.
117
+ #
74
118
  # Examples:
119
+ # client = MQTT::Client.new
120
+ # client = MQTT::Client.new('mqtt://myserver.example.com')
121
+ # client = MQTT::Client.new('mqtt://user:pass@myserver.example.com')
75
122
  # client = MQTT::Client.new('myserver.example.com')
76
123
  # client = MQTT::Client.new('myserver.example.com', 18830)
77
124
  # client = MQTT::Client.new(:remote_host => 'myserver.example.com')
78
125
  # client = MQTT::Client.new(:remote_host => 'myserver.example.com', :keep_alive => 30)
79
126
  #
80
127
  def initialize(*args)
81
- if args.count == 0
82
- args = {}
83
- elsif args.count == 1 and args[0].is_a?(Hash)
84
- args = args[0]
85
- elsif args.count == 1
86
- args = {:remote_host => args[0]}
87
- elsif args.count == 2
88
- args = {:remote_host => args[0], :remote_port => args[1]}
128
+ if args.last.is_a?(Hash)
129
+ attr = args.pop
89
130
  else
131
+ attr = {}
132
+ end
133
+
134
+ if args.length == 0
135
+ if ENV['MQTT_BROKER']
136
+ attr.merge!(parse_uri(ENV['MQTT_BROKER']))
137
+ end
138
+ end
139
+
140
+ if args.length >= 1
141
+ case args[0]
142
+ when URI
143
+ attr.merge!(parse_uri(args[0]))
144
+ when %r|^mqtts?://|
145
+ attr.merge!(parse_uri(args[0]))
146
+ else
147
+ attr.merge!(:remote_host => args[0])
148
+ end
149
+ end
150
+
151
+ if args.length >= 2
152
+ attr.merge!(:remote_port => args[1])
153
+ end
154
+
155
+ if args.length >= 3
90
156
  raise ArgumentError, "Unsupported number of arguments"
91
157
  end
92
158
 
93
159
  # Merge arguments with default values for attributes
94
- ATTR_DEFAULTS.merge(args).each_pair do |k,v|
95
- instance_variable_set("@#{k}", v)
160
+ ATTR_DEFAULTS.merge(attr).each_pair do |k,v|
161
+ self.send("#{k}=", v)
162
+ end
163
+
164
+ # Set a default port number
165
+ if @remote_port.nil?
166
+ @remote_port = @ssl ? MQTT::DEFAULT_SSL_PORT : MQTT::DEFAULT_PORT
96
167
  end
97
168
 
98
169
  # Initialise private instance variables
@@ -105,6 +176,33 @@ class MQTT::Client
105
176
  @write_semaphore = Mutex.new
106
177
  end
107
178
 
179
+ # Get the OpenSSL context, that is used if SSL/TLS is enabled
180
+ def ssl_context
181
+ @ssl_context ||= OpenSSL::SSL::SSLContext.new
182
+ end
183
+
184
+ # Set a path to a file containing a PEM-format client certificate
185
+ def cert_file=(path)
186
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.open(path))
187
+ end
188
+
189
+ # Set a path to a file containing a PEM-format client private key
190
+ def key_file=(path)
191
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.open(path))
192
+ end
193
+
194
+ # Set a path to a file containing a PEM-format CA certificate and enable peer verification
195
+ def ca_file=(path)
196
+ ssl_context.ca_file = path
197
+ unless path.nil?
198
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
199
+ end
200
+ end
201
+
202
+ # Set the Will for the client
203
+ #
204
+ # The will is a message that will be delivered by the broker when the client dies.
205
+ # The Will must be set before establishing a connection to the broker
108
206
  def set_will(topic, payload, retain=false, qos=0)
109
207
  self.will_topic = topic
110
208
  self.will_payload = payload
@@ -115,16 +213,38 @@ class MQTT::Client
115
213
  # Connect to the MQTT broker
116
214
  # If a block is given, then yield to that block and then disconnect again.
117
215
  def connect(clientid=nil)
118
- if !clientid.nil?
216
+ unless clientid.nil?
119
217
  @client_id = clientid
120
- elsif @client_id.nil?
121
- @client_id = MQTT::Client.generate_client_id
122
- @clean_session = true
218
+ end
219
+
220
+ if @client_id.nil? or @client_id.empty?
221
+ if @clean_session
222
+ @client_id = MQTT::Client.generate_client_id
223
+ else
224
+ raise 'Must provide a client_id if clean_session is set to false'
225
+ end
226
+ end
227
+
228
+ if @remote_host.nil?
229
+ raise 'No MQTT broker host set when attempting to connect'
123
230
  end
124
231
 
125
232
  if not connected?
126
233
  # Create network socket
127
- @socket = TCPSocket.new(@remote_host,@remote_port)
234
+ tcp_socket = TCPSocket.new(@remote_host, @remote_port)
235
+
236
+ if @ssl
237
+ # Set the protocol version
238
+ if @ssl.is_a?(Symbol)
239
+ ssl_context.ssl_version = @ssl
240
+ end
241
+
242
+ @socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
243
+ @socket.sync_close = true
244
+ @socket.connect
245
+ else
246
+ @socket = tcp_socket
247
+ end
128
248
 
129
249
  # Protocol name and version
130
250
  packet = MQTT::Packet::Connect.new(
@@ -148,7 +268,9 @@ class MQTT::Client
148
268
  # Start packet reading thread
149
269
  @read_thread = Thread.new(Thread.current) do |parent|
150
270
  Thread.current[:parent] = parent
151
- loop { receive_packet }
271
+ while connected? do
272
+ receive_packet
273
+ end
152
274
  end
153
275
  end
154
276
 
@@ -162,6 +284,11 @@ class MQTT::Client
162
284
  # Disconnect from the MQTT broker.
163
285
  # If you don't want to say goodbye to the broker, set send_msg to false.
164
286
  def disconnect(send_msg=true)
287
+ # Stop reading packets from the socket first
288
+ @read_thread.kill if @read_thread and @read_thread.alive?
289
+ @read_thread = nil
290
+
291
+ # Close the socket if it is open
165
292
  if connected?
166
293
  if send_msg
167
294
  packet = MQTT::Packet::Disconnect.new
@@ -170,16 +297,17 @@ class MQTT::Client
170
297
  @socket.close unless @socket.nil?
171
298
  @socket = nil
172
299
  end
173
- @read_thread.kill if @read_thread and @read_thread.alive?
174
- @read_thread = nil
175
300
  end
176
301
 
177
302
  # Checks whether the client is connected to the broker.
178
303
  def connected?
179
- not @socket.nil?
304
+ (not @socket.nil?) and (not @socket.closed?)
180
305
  end
181
306
 
182
307
  # Send a MQTT ping message to indicate that the MQTT client is alive.
308
+ #
309
+ # Note that you will not normally need to call this method
310
+ # as it is called automatically
183
311
  def ping
184
312
  packet = MQTT::Packet::Pingreq.new
185
313
  send_packet(packet)
@@ -288,6 +416,10 @@ class MQTT::Client
288
416
 
289
417
  # Send a unsubscribe message for one or more topics on the MQTT broker
290
418
  def unsubscribe(*topics)
419
+ if topics.is_a?(Enumerable) and topics.count == 1
420
+ topics = topics.first
421
+ end
422
+
291
423
  packet = MQTT::Packet::Unsubscribe.new(
292
424
  :topics => topics,
293
425
  :message_id => @message_id.next
@@ -302,7 +434,7 @@ private
302
434
  def receive_packet
303
435
  begin
304
436
  # Poll socket - is there data waiting?
305
- result = IO.select([@socket], nil, nil, SELECT_TIMEOUT)
437
+ result = IO.select([@socket], [], [], SELECT_TIMEOUT)
306
438
  unless result.nil?
307
439
  # Yes - read in the packet
308
440
  packet = MQTT::Packet.read(@socket)
@@ -355,8 +487,28 @@ private
355
487
 
356
488
  # Only allow one thread to write to socket at a time
357
489
  @write_semaphore.synchronize do
358
- @socket.write(data)
490
+ @socket.write(data.to_s)
491
+ end
492
+ end
493
+
494
+ private
495
+ def parse_uri(uri)
496
+ uri = URI.parse(uri) unless uri.is_a?(URI)
497
+ if uri.scheme == 'mqtt'
498
+ ssl = false
499
+ elsif uri.scheme == 'mqtts'
500
+ ssl = true
501
+ else
502
+ raise "Only the mqtt:// and mqtts:// schemes are supported"
359
503
  end
504
+
505
+ {
506
+ :remote_host => uri.host,
507
+ :remote_port => uri.port || nil,
508
+ :username => uri.user,
509
+ :password => uri.password,
510
+ :ssl => ssl
511
+ }
360
512
  end
361
513
 
362
514
  end
@@ -5,12 +5,20 @@ module MQTT
5
5
  # Class representing a MQTT Packet
6
6
  # Performs binary encoding and decoding of headers
7
7
  class MQTT::Packet
8
- attr_reader :duplicate # Duplicate delivery flag
9
- attr_reader :retain # Retain flag
10
- attr_reader :qos # Quality of Service level
11
- attr_reader :body_length # The length of the parsed packet body
8
+ # Duplicate delivery flag
9
+ attr_reader :duplicate
12
10
 
13
- DEFAULTS = {
11
+ # Retain flag
12
+ attr_reader :retain
13
+
14
+ # Quality of Service level (0, 1, 2)
15
+ attr_reader :qos
16
+
17
+ # The length of the parsed packet body
18
+ attr_reader :body_length
19
+
20
+ # Default attribute values
21
+ ATTR_DEFAULTS = {
14
22
  :duplicate => false,
15
23
  :qos => 0,
16
24
  :retain => false,
@@ -105,9 +113,10 @@ module MQTT
105
113
 
106
114
  # Create a new empty packet
107
115
  def initialize(args={})
108
- update_attributes(DEFAULTS.merge(args))
116
+ update_attributes(ATTR_DEFAULTS.merge(args))
109
117
  end
110
118
 
119
+ # Set packet attributes from a hash of attribute names and values
111
120
  def update_attributes(attr={})
112
121
  attr.each_pair do |k,v|
113
122
  send("#{k}=", v)
@@ -201,6 +210,7 @@ module MQTT
201
210
  header.pack('C*') + body
202
211
  end
203
212
 
213
+ # Returns a human readable string
204
214
  def inspect
205
215
  "\#<#{self.class}>"
206
216
  end
@@ -270,11 +280,18 @@ module MQTT
270
280
 
271
281
  # Class representing an MQTT Publish message
272
282
  class Publish < MQTT::Packet
283
+ # The topic name to publish to
273
284
  attr_accessor :topic
285
+
286
+ # Identifier for an individual publishing flow
287
+ # Only required in PUBLISH Packets where the QoS level is 1 or 2
274
288
  attr_accessor :message_id
289
+
290
+ # The data to be published
275
291
  attr_accessor :payload
276
292
 
277
- DEFAULTS = {
293
+ # Default attribute values
294
+ ATTR_DEFAULTS = {
278
295
  :topic => nil,
279
296
  :message_id => 0,
280
297
  :payload => ''
@@ -282,7 +299,7 @@ module MQTT
282
299
 
283
300
  # Create a new Publish packet
284
301
  def initialize(args={})
285
- super(DEFAULTS.merge(args))
302
+ super(ATTR_DEFAULTS.merge(args))
286
303
  end
287
304
 
288
305
  # Get serialisation of packet's body
@@ -305,6 +322,7 @@ module MQTT
305
322
  @payload = buffer
306
323
  end
307
324
 
325
+ # Returns a human readable string, summarising the properties of the packet
308
326
  def inspect
309
327
  "\#<#{self.class}: " +
310
328
  "d#{duplicate ? '1' : '0'}, " +
@@ -328,23 +346,41 @@ module MQTT
328
346
 
329
347
  # Class representing an MQTT Connect Packet
330
348
  class Connect < MQTT::Packet
349
+ # The name of the protocol (defaults to MQIsdp)
331
350
  attr_accessor :protocol_name
351
+
352
+ # The version number of the protocol (defaults to 3)
332
353
  attr_accessor :protocol_version
354
+
355
+ # The client identifier string
333
356
  attr_accessor :client_id
357
+
358
+ # Set to false to keep a persistent session with the broker
334
359
  attr_accessor :clean_session
360
+
361
+ # Period the broker should keep connection open for between pings
335
362
  attr_accessor :keep_alive
363
+
364
+ # The topic name to send the Will message to
336
365
  attr_accessor :will_topic
366
+
367
+ # The QoS level to send the Will message as
337
368
  attr_accessor :will_qos
369
+
370
+ # Set to true to make the Will message retained
338
371
  attr_accessor :will_retain
372
+
373
+ # The payload of the Will message
339
374
  attr_accessor :will_payload
375
+
376
+ # The username for authenticating with the broker
340
377
  attr_accessor :username
378
+
379
+ # The password for authenticating with the broker
341
380
  attr_accessor :password
342
381
 
343
- # OLD deprecated clean_start
344
- alias :clean_start :clean_session
345
- alias :clean_start= :clean_session=
346
-
347
- DEFAULTS = {
382
+ # Default attribute values
383
+ ATTR_DEFAULTS = {
348
384
  :protocol_name => 'MQIsdp',
349
385
  :protocol_version => 0x03,
350
386
  :client_id => nil,
@@ -360,7 +396,7 @@ module MQTT
360
396
 
361
397
  # Create a new Client Connect packet
362
398
  def initialize(args={})
363
- super(DEFAULTS.merge(args))
399
+ super(ATTR_DEFAULTS.merge(args))
364
400
  end
365
401
 
366
402
  # Get serialisation of packet's body
@@ -436,6 +472,7 @@ module MQTT
436
472
  end
437
473
  end
438
474
 
475
+ # Returns a human readable string, summarising the properties of the packet
439
476
  def inspect
440
477
  str = "\#<#{self.class}: "
441
478
  str += "keep_alive=#{keep_alive}"
@@ -449,12 +486,15 @@ module MQTT
449
486
 
450
487
  # Class representing an MQTT Connect Acknowledgment Packet
451
488
  class Connack < MQTT::Packet
489
+ # The return code (defaults to 0 for connection accepted)
452
490
  attr_accessor :return_code
453
- DEFAULTS = {:return_code => 0x00}
491
+
492
+ # Default attribute values
493
+ ATTR_DEFAULTS = {:return_code => 0x00}
454
494
 
455
495
  # Create a new Client Connect packet
456
496
  def initialize(args={})
457
- super(DEFAULTS.merge(args))
497
+ super(ATTR_DEFAULTS.merge(args))
458
498
  end
459
499
 
460
500
  # Get a string message corresponding to a return code
@@ -495,6 +535,7 @@ module MQTT
495
535
  end
496
536
  end
497
537
 
538
+ # Returns a human readable string, summarising the properties of the packet
498
539
  def inspect
499
540
  "\#<#{self.class}: 0x%2.2X>" % return_code
500
541
  end
@@ -502,12 +543,15 @@ module MQTT
502
543
 
503
544
  # Class representing an MQTT Publish Acknowledgment packet
504
545
  class Puback < MQTT::Packet
546
+ # Identifier for an individual publishing flow
505
547
  attr_accessor :message_id
506
- DEFAULTS = {:message_id => 0}
548
+
549
+ # Default attribute values
550
+ ATTR_DEFAULTS = {:message_id => 0}
507
551
 
508
552
  # Create a new Publish Acknowledgment packet
509
553
  def initialize(args={})
510
- super(DEFAULTS.merge(args))
554
+ super(ATTR_DEFAULTS.merge(args))
511
555
  end
512
556
 
513
557
  # Get serialisation of packet's body
@@ -524,6 +568,7 @@ module MQTT
524
568
  end
525
569
  end
526
570
 
571
+ # Returns a human readable string, summarising the properties of the packet
527
572
  def inspect
528
573
  "\#<#{self.class}: 0x%2.2X>" % message_id
529
574
  end
@@ -531,12 +576,15 @@ module MQTT
531
576
 
532
577
  # Class representing an MQTT Publish Received packet
533
578
  class Pubrec < MQTT::Packet
579
+ # Identifier for an individual publishing flow
534
580
  attr_accessor :message_id
535
- DEFAULTS = {:message_id => 0}
581
+
582
+ # Default attribute values
583
+ ATTR_DEFAULTS = {:message_id => 0}
536
584
 
537
585
  # Create a new Publish Recieved packet
538
586
  def initialize(args={})
539
- super(DEFAULTS.merge(args))
587
+ super(ATTR_DEFAULTS.merge(args))
540
588
  end
541
589
 
542
590
  # Get serialisation of packet's body
@@ -553,6 +601,7 @@ module MQTT
553
601
  end
554
602
  end
555
603
 
604
+ # Returns a human readable string, summarising the properties of the packet
556
605
  def inspect
557
606
  "\#<#{self.class}: 0x%2.2X>" % message_id
558
607
  end
@@ -560,12 +609,15 @@ module MQTT
560
609
 
561
610
  # Class representing an MQTT Publish Release packet
562
611
  class Pubrel < MQTT::Packet
612
+ # Identifier for an individual publishing flow
563
613
  attr_accessor :message_id
564
- DEFAULTS = {:message_id => 0}
614
+
615
+ # Default attribute values
616
+ ATTR_DEFAULTS = {:message_id => 0}
565
617
 
566
618
  # Create a new Publish Release packet
567
619
  def initialize(args={})
568
- super(DEFAULTS.merge(args))
620
+ super(ATTR_DEFAULTS.merge(args))
569
621
  end
570
622
 
571
623
  # Get serialisation of packet's body
@@ -582,6 +634,7 @@ module MQTT
582
634
  end
583
635
  end
584
636
 
637
+ # Returns a human readable string, summarising the properties of the packet
585
638
  def inspect
586
639
  "\#<#{self.class}: 0x%2.2X>" % message_id
587
640
  end
@@ -589,12 +642,15 @@ module MQTT
589
642
 
590
643
  # Class representing an MQTT Publish Complete packet
591
644
  class Pubcomp < MQTT::Packet
645
+ # Identifier for an individual publishing flow
592
646
  attr_accessor :message_id
593
- DEFAULTS = {:message_id => 0}
647
+
648
+ # Default attribute values
649
+ ATTR_DEFAULTS = {:message_id => 0}
594
650
 
595
651
  # Create a new Publish Complete packet
596
652
  def initialize(args={})
597
- super(DEFAULTS.merge(args))
653
+ super(ATTR_DEFAULTS.merge(args))
598
654
  end
599
655
 
600
656
  # Get serialisation of packet's body
@@ -611,6 +667,7 @@ module MQTT
611
667
  end
612
668
  end
613
669
 
670
+ # Returns a human readable string, summarising the properties of the packet
614
671
  def inspect
615
672
  "\#<#{self.class}: 0x%2.2X>" % message_id
616
673
  end
@@ -618,13 +675,18 @@ module MQTT
618
675
 
619
676
  # Class representing an MQTT Client Subscribe packet
620
677
  class Subscribe < MQTT::Packet
678
+ # Identifier for an individual publishing flow
621
679
  attr_accessor :message_id
680
+
681
+ # One or more topic names to subscribe to
622
682
  attr_reader :topics
623
- DEFAULTS = {:message_id => 0}
683
+
684
+ # Default attribute values
685
+ ATTR_DEFAULTS = {:message_id => 0}
624
686
 
625
687
  # Create a new Subscribe packet
626
688
  def initialize(args={})
627
- super(DEFAULTS.merge(args))
689
+ super(ATTR_DEFAULTS.merge(args))
628
690
  @topics ||= []
629
691
  @qos = 1 # Force a QOS of 1
630
692
  end
@@ -696,8 +758,9 @@ module MQTT
696
758
  end
697
759
  end
698
760
 
761
+ # Returns a human readable string, summarising the properties of the packet
699
762
  def inspect
700
- str = "\#<#{self.class}: 0x%2.2X, %s>" % [
763
+ _str = "\#<#{self.class}: 0x%2.2X, %s>" % [
701
764
  message_id,
702
765
  topics.map {|t| "'#{t[0]}':#{t[1]}"}.join(', ')
703
766
  ]
@@ -706,13 +769,18 @@ module MQTT
706
769
 
707
770
  # Class representing an MQTT Subscribe Acknowledgment packet
708
771
  class Suback < MQTT::Packet
772
+ # Identifier to tie the Subscribe request to the Suback response
709
773
  attr_accessor :message_id
774
+
775
+ # The QoS level that was granted for the subscribe request
710
776
  attr_reader :granted_qos
711
- DEFAULTS = {:message_id => 0}
777
+
778
+ # Default attribute values
779
+ ATTR_DEFAULTS = {:message_id => 0}
712
780
 
713
781
  # Create a new Subscribe Acknowledgment packet
714
782
  def initialize(args={})
715
- super(DEFAULTS.merge(args))
783
+ super(ATTR_DEFAULTS.merge(args))
716
784
  @granted_qos ||= []
717
785
  end
718
786
 
@@ -747,6 +815,7 @@ module MQTT
747
815
  end
748
816
  end
749
817
 
818
+ # Returns a human readable string, summarising the properties of the packet
750
819
  def inspect
751
820
  "\#<#{self.class}: 0x%2.2X, qos=%s>" % [message_id, granted_qos.join(',')]
752
821
  end
@@ -754,17 +823,23 @@ module MQTT
754
823
 
755
824
  # Class representing an MQTT Client Unsubscribe packet
756
825
  class Unsubscribe < MQTT::Packet
826
+ # One or more topics to unsubscribe from
757
827
  attr_reader :topics
828
+
829
+ # Identifier to tie the Unsubscribe request to the Unsuback response
758
830
  attr_accessor :message_id
759
- DEFAULTS = {:message_id => 0}
831
+
832
+ # Default attribute values
833
+ ATTR_DEFAULTS = {:message_id => 0}
760
834
 
761
835
  # Create a new Unsubscribe packet
762
836
  def initialize(args={})
763
- super(DEFAULTS.merge(args))
837
+ super(ATTR_DEFAULTS.merge(args))
764
838
  @topics ||= []
765
839
  @qos = 1 # Force a QOS of 1
766
840
  end
767
841
 
842
+ # Set one or more topics to unsubscribe from
768
843
  def topics=(value)
769
844
  if value.is_a?(Array)
770
845
  @topics = value
@@ -792,8 +867,9 @@ module MQTT
792
867
  end
793
868
  end
794
869
 
870
+ # Returns a human readable string, summarising the properties of the packet
795
871
  def inspect
796
- str = "\#<#{self.class}: 0x%2.2X, %s>" % [
872
+ "\#<#{self.class}: 0x%2.2X, %s>" % [
797
873
  message_id,
798
874
  topics.map {|t| "'#{t}'"}.join(', ')
799
875
  ]
@@ -802,12 +878,15 @@ module MQTT
802
878
 
803
879
  # Class representing an MQTT Unsubscribe Acknowledgment packet
804
880
  class Unsuback < MQTT::Packet
881
+ # Identifier to tie the Unsubscribe request to the Unsuback response
805
882
  attr_accessor :message_id
806
- DEFAULTS = {:message_id => 0}
883
+
884
+ # Default attribute values
885
+ ATTR_DEFAULTS = {:message_id => 0}
807
886
 
808
887
  # Create a new Unsubscribe Acknowledgment packet
809
888
  def initialize(args={})
810
- super(DEFAULTS.merge(args))
889
+ super(ATTR_DEFAULTS.merge(args))
811
890
  end
812
891
 
813
892
  # Get serialisation of packet's body
@@ -824,6 +903,7 @@ module MQTT
824
903
  end
825
904
  end
826
905
 
906
+ # Returns a human readable string, summarising the properties of the packet
827
907
  def inspect
828
908
  "\#<#{self.class}: 0x%2.2X>" % message_id
829
909
  end