mqtt 0.0.9 → 0.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.
- data/LICENSE +21 -0
- data/NEWS +19 -0
- data/README +5 -1
- data/lib/mqtt.rb +6 -1
- data/lib/mqtt/client.rb +30 -2
- data/lib/mqtt/packet.rb +158 -45
- data/lib/mqtt/patches/string_encoding.rb +30 -0
- data/lib/mqtt/version.rb +1 -1
- data/spec/mqtt_client_spec.rb +79 -3
- data/spec/mqtt_packet_spec.rb +366 -10
- data/spec/zz_integration_spec.rb +145 -0
- metadata +23 -11
- data/COPYING +0 -56
- data/GPL +0 -340
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2009-2013 Nicholas J Humfrey
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/NEWS
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
Ruby MQTT NEWS
|
2
2
|
==============
|
3
3
|
|
4
|
+
Ruby MQTT Version 0.1.0 (2013-09-07)
|
5
|
+
------------------------------------
|
6
|
+
|
7
|
+
* Changed license to MIT, to simplify licensing concerns
|
8
|
+
* Improvements for UTF-8 handling under Ruby 1.9
|
9
|
+
* Added ```get_packet``` method
|
10
|
+
* Added support for a keep-alive value of 0
|
11
|
+
* Added a #inspect method to the Packet classes
|
12
|
+
* Added checks for the protocol name and version
|
13
|
+
* Added check to ensure that packet body isn't too big
|
14
|
+
* Added validation of QoS value
|
15
|
+
* Added example of using authentication
|
16
|
+
* Fixed 'unused variable' warnings
|
17
|
+
* Reduced duplicated code in packet parsing
|
18
|
+
* Improved testing
|
19
|
+
- Created fake server and integration tests
|
20
|
+
- Better test coverage
|
21
|
+
- Added more tests for error states
|
22
|
+
|
4
23
|
|
5
24
|
Ruby MQTT Version 0.0.9 (2012-12-21)
|
6
25
|
------------------------------------
|
data/README
CHANGED
@@ -46,6 +46,11 @@ Resources
|
|
46
46
|
* GitHub Project: http://github.com/njh/ruby-mqtt
|
47
47
|
* API Documentation: http://rubydoc.info/gems/mqtt/frames
|
48
48
|
|
49
|
+
License
|
50
|
+
-------
|
51
|
+
|
52
|
+
The ruby-mqtt gem is licensed under the terms of the MIT license.
|
53
|
+
See the file LICENSE for details.
|
49
54
|
|
50
55
|
Contact
|
51
56
|
-------
|
@@ -53,4 +58,3 @@ Contact
|
|
53
58
|
* Author: Nicholas J Humfrey
|
54
59
|
* Email: njh@aelius.com
|
55
60
|
* Home Page: http://www.aelius.com/njh/
|
56
|
-
* License: Distributes under the same terms as Ruby
|
data/lib/mqtt.rb
CHANGED
@@ -5,7 +5,12 @@ require 'socket'
|
|
5
5
|
require 'thread'
|
6
6
|
require 'timeout'
|
7
7
|
|
8
|
-
require
|
8
|
+
require 'mqtt/version'
|
9
|
+
|
10
|
+
# String encoding monkey patch for Ruby 1.8
|
11
|
+
unless String.method_defined?(:force_encoding)
|
12
|
+
require 'mqtt/patches/string_encoding.rb'
|
13
|
+
end
|
9
14
|
|
10
15
|
module MQTT
|
11
16
|
|
data/lib/mqtt/client.rb
CHANGED
@@ -220,7 +220,7 @@ class MQTT::Client
|
|
220
220
|
send_packet(packet)
|
221
221
|
end
|
222
222
|
|
223
|
-
# Return the next message
|
223
|
+
# Return the next message received from the MQTT broker.
|
224
224
|
# An optional topic can be given to subscribe to.
|
225
225
|
#
|
226
226
|
# The method either returns the topic and message as an array:
|
@@ -248,6 +248,34 @@ class MQTT::Client
|
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
251
|
+
# Return the next packet object received from the MQTT broker.
|
252
|
+
# An optional topic can be given to subscribe to.
|
253
|
+
#
|
254
|
+
# The method either returns a single packet:
|
255
|
+
# packet = client.get_packet
|
256
|
+
# puts packet.topic
|
257
|
+
#
|
258
|
+
# Or can be used with a block to keep processing messages:
|
259
|
+
# client.get_packet('test') do |packet|
|
260
|
+
# # Do stuff here
|
261
|
+
# puts packet.topic
|
262
|
+
# end
|
263
|
+
#
|
264
|
+
def get_packet(topic=nil)
|
265
|
+
# Subscribe to a topic, if an argument is given
|
266
|
+
subscribe(topic) unless topic.nil?
|
267
|
+
|
268
|
+
if block_given?
|
269
|
+
# Loop forever!
|
270
|
+
loop do
|
271
|
+
yield(@read_queue.pop)
|
272
|
+
end
|
273
|
+
else
|
274
|
+
# Wait for one packet to be available
|
275
|
+
return @read_queue.pop
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
251
279
|
# Returns true if the incoming message queue is empty.
|
252
280
|
def queue_empty?
|
253
281
|
@read_queue.empty?
|
@@ -289,7 +317,7 @@ private
|
|
289
317
|
end
|
290
318
|
|
291
319
|
# Time to send a keep-alive ping request?
|
292
|
-
if Time.now > @last_pingreq + @keep_alive
|
320
|
+
if @keep_alive > 0 and Time.now > @last_pingreq + @keep_alive
|
293
321
|
ping
|
294
322
|
end
|
295
323
|
|
data/lib/mqtt/packet.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
|
1
3
|
module MQTT
|
2
4
|
|
3
5
|
# Class representing a MQTT Packet
|
@@ -17,27 +19,21 @@ module MQTT
|
|
17
19
|
|
18
20
|
# Read in a packet from a socket
|
19
21
|
def self.read(socket)
|
20
|
-
# Read in the packet header and
|
21
|
-
|
22
|
-
|
23
|
-
packet_class = MQTT::PACKET_TYPES[type_id]
|
24
|
-
|
25
|
-
# Create a new packet object
|
26
|
-
packet = packet_class.new(
|
27
|
-
:duplicate => ((header & 0x08) >> 3),
|
28
|
-
:qos => ((header & 0x06) >> 1),
|
29
|
-
:retain => ((header & 0x01) >> 0)
|
22
|
+
# Read in the packet header and create a new packet object
|
23
|
+
packet = create_from_header(
|
24
|
+
read_byte(socket)
|
30
25
|
)
|
31
26
|
|
32
27
|
# Read in the packet length
|
33
28
|
multiplier = 1
|
34
29
|
body_length = 0
|
30
|
+
pos = 1
|
35
31
|
begin
|
36
32
|
digit = read_byte(socket)
|
37
33
|
body_length += ((digit & 0x7F) * multiplier)
|
38
34
|
multiplier *= 0x80
|
39
|
-
|
40
|
-
|
35
|
+
pos += 1
|
36
|
+
end while ((digit & 0x80) != 0x00) and pos <= 4
|
41
37
|
|
42
38
|
# Store the expected body length in the packet
|
43
39
|
packet.instance_variable_set('@body_length', body_length)
|
@@ -58,29 +54,24 @@ module MQTT
|
|
58
54
|
# Parse the header and create a new packet object of the correct type
|
59
55
|
# The header is removed from the buffer passed into this function
|
60
56
|
def self.parse_header(buffer)
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
if packet_class.nil?
|
65
|
-
raise ProtocolException.new("Invalid packet type identifier: #{type_id}")
|
57
|
+
# Check that the packet is a long as the minimum packet size
|
58
|
+
if buffer.bytesize < 2
|
59
|
+
raise ProtocolException.new("Invalid packet: less than 2 bytes long")
|
66
60
|
end
|
67
61
|
|
68
62
|
# Create a new packet object
|
69
|
-
|
70
|
-
|
71
|
-
:qos => ((buffer.unpack("C*")[0] & 0x06) >> 1),
|
72
|
-
:retain => ((buffer.unpack("C*")[0] & 0x01) >> 0) == 0x01
|
73
|
-
)
|
63
|
+
bytes = buffer.unpack("C5")
|
64
|
+
packet = create_from_header(bytes.first)
|
74
65
|
|
75
66
|
# Parse the packet length
|
76
67
|
body_length = 0
|
77
68
|
multiplier = 1
|
78
69
|
pos = 1
|
79
70
|
begin
|
80
|
-
if buffer.
|
71
|
+
if buffer.bytesize <= pos
|
81
72
|
raise ProtocolException.new("The packet length header is incomplete")
|
82
73
|
end
|
83
|
-
digit =
|
74
|
+
digit = bytes[pos]
|
84
75
|
body_length += ((digit & 0x7F) * multiplier)
|
85
76
|
multiplier *= 0x80
|
86
77
|
pos += 1
|
@@ -89,12 +80,28 @@ module MQTT
|
|
89
80
|
# Store the expected body length in the packet
|
90
81
|
packet.instance_variable_set('@body_length', body_length)
|
91
82
|
|
92
|
-
# Delete the
|
83
|
+
# Delete the fixed header from the raw packet passed in
|
93
84
|
buffer.slice!(0...pos)
|
94
85
|
|
95
86
|
return packet
|
96
87
|
end
|
97
88
|
|
89
|
+
# Create a new packet object from the first byte of a MQTT packet
|
90
|
+
def self.create_from_header(byte)
|
91
|
+
# Work out the class
|
92
|
+
type_id = ((byte & 0xF0) >> 4)
|
93
|
+
packet_class = MQTT::PACKET_TYPES[type_id]
|
94
|
+
if packet_class.nil?
|
95
|
+
raise ProtocolException.new("Invalid packet type identifier: #{type_id}")
|
96
|
+
end
|
97
|
+
|
98
|
+
# Create a new packet object
|
99
|
+
packet_class.new(
|
100
|
+
:duplicate => ((byte & 0x08) >> 3) == 0x01,
|
101
|
+
:qos => ((byte & 0x06) >> 1),
|
102
|
+
:retain => ((byte & 0x01) >> 0) == 0x01
|
103
|
+
)
|
104
|
+
end
|
98
105
|
|
99
106
|
# Create a new empty packet
|
100
107
|
def initialize(args={})
|
@@ -137,6 +144,9 @@ module MQTT
|
|
137
144
|
# Set the Quality of Service level (0/1/2)
|
138
145
|
def qos=(arg)
|
139
146
|
@qos = arg.to_i
|
147
|
+
if @qos < 0 or @qos > 2
|
148
|
+
raise "Invalid QoS value: #{@qos}"
|
149
|
+
end
|
140
150
|
end
|
141
151
|
|
142
152
|
# Set the length of the packet body
|
@@ -146,9 +156,9 @@ module MQTT
|
|
146
156
|
|
147
157
|
# Parse the body (variable header and payload) of a packet
|
148
158
|
def parse_body(buffer)
|
149
|
-
if buffer.
|
159
|
+
if buffer.bytesize != body_length
|
150
160
|
raise ProtocolException.new(
|
151
|
-
"Failed to parse packet - input buffer (#{buffer.
|
161
|
+
"Failed to parse packet - input buffer (#{buffer.bytesize}) is not the same as the body length header (#{body_length})"
|
152
162
|
)
|
153
163
|
end
|
154
164
|
end
|
@@ -172,8 +182,13 @@ module MQTT
|
|
172
182
|
# Get the packet's variable header and payload
|
173
183
|
body = self.encode_body
|
174
184
|
|
185
|
+
# Check that that packet isn't too big
|
186
|
+
body_length = body.bytesize
|
187
|
+
if body_length > 268435455
|
188
|
+
raise "Error serialising packet: body is more than 256MB"
|
189
|
+
end
|
190
|
+
|
175
191
|
# Build up the body length field bytes
|
176
|
-
body_length = body.length
|
177
192
|
begin
|
178
193
|
digit = (body_length % 128)
|
179
194
|
body_length = (body_length / 128)
|
@@ -186,6 +201,9 @@ module MQTT
|
|
186
201
|
header.pack('C*') + body
|
187
202
|
end
|
188
203
|
|
204
|
+
def inspect
|
205
|
+
"\#<#{self.class}>"
|
206
|
+
end
|
189
207
|
|
190
208
|
protected
|
191
209
|
|
@@ -199,11 +217,14 @@ module MQTT
|
|
199
217
|
[val.to_i].pack('n')
|
200
218
|
end
|
201
219
|
|
202
|
-
# Encode a string and return it
|
220
|
+
# Encode a UTF-8 string and return it
|
203
221
|
# (preceded by the length of the string)
|
204
222
|
def encode_string(str)
|
205
|
-
str = str.to_s
|
206
|
-
|
223
|
+
str = str.to_s.encode('UTF-8')
|
224
|
+
|
225
|
+
# Force to binary, when assembling the packet
|
226
|
+
str.force_encoding('ASCII-8BIT')
|
227
|
+
encode_short(str.bytesize) + str
|
207
228
|
end
|
208
229
|
|
209
230
|
# Remove a 16-bit unsigned integer from the front of buffer
|
@@ -225,7 +246,9 @@ module MQTT
|
|
225
246
|
# Remove string from the front of buffer
|
226
247
|
def shift_string(buffer)
|
227
248
|
len = shift_short(buffer)
|
228
|
-
shift_data(buffer,len)
|
249
|
+
str = shift_data(buffer,len)
|
250
|
+
# Strings in MQTT v3.1 are all UTF-8
|
251
|
+
str.force_encoding('UTF-8')
|
229
252
|
end
|
230
253
|
|
231
254
|
|
@@ -235,7 +258,7 @@ module MQTT
|
|
235
258
|
def self.read_byte(socket)
|
236
259
|
byte = socket.read(1)
|
237
260
|
if byte.nil?
|
238
|
-
raise ProtocolException
|
261
|
+
raise ProtocolException.new("Failed to read byte from socket")
|
239
262
|
end
|
240
263
|
byte.unpack('C').first
|
241
264
|
end
|
@@ -265,12 +288,12 @@ module MQTT
|
|
265
288
|
# Get serialisation of packet's body
|
266
289
|
def encode_body
|
267
290
|
body = ''
|
268
|
-
if @topic.nil?
|
291
|
+
if @topic.nil? or @topic.to_s.empty?
|
269
292
|
raise "Invalid topic name when serialising packet"
|
270
293
|
end
|
271
294
|
body += encode_string(@topic)
|
272
295
|
body += encode_short(@message_id) unless qos == 0
|
273
|
-
body += payload.to_s
|
296
|
+
body += payload.to_s.force_encoding('ASCII-8BIT')
|
274
297
|
return body
|
275
298
|
end
|
276
299
|
|
@@ -279,7 +302,27 @@ module MQTT
|
|
279
302
|
super(buffer)
|
280
303
|
@topic = shift_string(buffer)
|
281
304
|
@message_id = shift_short(buffer) unless qos == 0
|
282
|
-
@payload = buffer
|
305
|
+
@payload = buffer
|
306
|
+
end
|
307
|
+
|
308
|
+
def inspect
|
309
|
+
"\#<#{self.class}: " +
|
310
|
+
"d#{duplicate ? '1' : '0'}, " +
|
311
|
+
"q#{qos}, " +
|
312
|
+
"r#{retain ? '1' : '0'}, " +
|
313
|
+
"m#{message_id}, " +
|
314
|
+
"'#{topic}', " +
|
315
|
+
"#{inspect_payload}>"
|
316
|
+
end
|
317
|
+
|
318
|
+
protected
|
319
|
+
def inspect_payload
|
320
|
+
str = payload.to_s
|
321
|
+
if str.bytesize < 16
|
322
|
+
"'#{str}'"
|
323
|
+
else
|
324
|
+
"... (#{str.bytesize} bytes)"
|
325
|
+
end
|
283
326
|
end
|
284
327
|
end
|
285
328
|
|
@@ -323,12 +366,16 @@ module MQTT
|
|
323
366
|
# Get serialisation of packet's body
|
324
367
|
def encode_body
|
325
368
|
body = ''
|
326
|
-
if @client_id.nil? or @client_id.
|
369
|
+
if @client_id.nil? or @client_id.bytesize < 1 or @client_id.bytesize > 23
|
327
370
|
raise "Invalid client identifier when serialising packet"
|
328
371
|
end
|
329
372
|
body += encode_string(@protocol_name)
|
330
373
|
body += encode_bytes(@protocol_version.to_i)
|
331
374
|
|
375
|
+
if @keep_alive < 0
|
376
|
+
raise "Invalid keep-alive value: cannot be less than 0"
|
377
|
+
end
|
378
|
+
|
332
379
|
# Set the Connect flags
|
333
380
|
@connect_flags = 0
|
334
381
|
@connect_flags |= 0x02 if @clean_session
|
@@ -343,6 +390,7 @@ module MQTT
|
|
343
390
|
body += encode_string(@client_id)
|
344
391
|
unless will_topic.nil?
|
345
392
|
body += encode_string(@will_topic)
|
393
|
+
# The MQTT v3.1 specification says that the payload is a UTF-8 string
|
346
394
|
body += encode_string(@will_payload)
|
347
395
|
end
|
348
396
|
body += encode_string(@username) unless @username.nil?
|
@@ -354,7 +402,20 @@ module MQTT
|
|
354
402
|
def parse_body(buffer)
|
355
403
|
super(buffer)
|
356
404
|
@protocol_name = shift_string(buffer)
|
357
|
-
@protocol_version = shift_byte(buffer)
|
405
|
+
@protocol_version = shift_byte(buffer).to_i
|
406
|
+
|
407
|
+
if @protocol_name != 'MQIsdp'
|
408
|
+
raise ProtocolException.new(
|
409
|
+
"Unsupported protocol name: #{@protocol_name}"
|
410
|
+
)
|
411
|
+
end
|
412
|
+
|
413
|
+
if @protocol_version != 3
|
414
|
+
raise ProtocolException.new(
|
415
|
+
"Unsupported protocol version: #{@protocol_version}"
|
416
|
+
)
|
417
|
+
end
|
418
|
+
|
358
419
|
@connect_flags = shift_byte(buffer)
|
359
420
|
@clean_session = ((@connect_flags & 0x02) >> 1) == 0x01
|
360
421
|
@keep_alive = shift_short(buffer)
|
@@ -364,15 +425,26 @@ module MQTT
|
|
364
425
|
@will_qos = ((@connect_flags & 0x18) >> 3)
|
365
426
|
@will_retain = ((@connect_flags & 0x20) >> 5) == 0x01
|
366
427
|
@will_topic = shift_string(buffer)
|
428
|
+
# The MQTT v3.1 specification says that the payload is a UTF-8 string
|
367
429
|
@will_payload = shift_string(buffer)
|
368
430
|
end
|
369
|
-
if ((@connect_flags & 0x80) >> 7) == 0x01 and buffer.
|
431
|
+
if ((@connect_flags & 0x80) >> 7) == 0x01 and buffer.bytesize > 0
|
370
432
|
@username = shift_string(buffer)
|
371
433
|
end
|
372
|
-
if ((@connect_flags & 0x40) >> 6) == 0x01 and buffer.
|
434
|
+
if ((@connect_flags & 0x40) >> 6) == 0x01 and buffer.bytesize > 0
|
373
435
|
@password = shift_string(buffer)
|
374
436
|
end
|
375
437
|
end
|
438
|
+
|
439
|
+
def inspect
|
440
|
+
str = "\#<#{self.class}: "
|
441
|
+
str += "keep_alive=#{keep_alive}"
|
442
|
+
str += ", clean" if clean_session
|
443
|
+
str += ", client_id='#{client_id}'"
|
444
|
+
str += ", username='#{username}'" unless username.nil?
|
445
|
+
str += ", password=..." unless password.nil?
|
446
|
+
str += ">"
|
447
|
+
end
|
376
448
|
end
|
377
449
|
|
378
450
|
# Class representing an MQTT Connect Acknowledgment Packet
|
@@ -416,12 +488,16 @@ module MQTT
|
|
416
488
|
# Parse the body (variable header and payload) of a Connect Acknowledgment packet
|
417
489
|
def parse_body(buffer)
|
418
490
|
super(buffer)
|
419
|
-
|
491
|
+
_unused = shift_byte(buffer)
|
420
492
|
@return_code = shift_byte(buffer)
|
421
493
|
unless buffer.empty?
|
422
494
|
raise ProtocolException.new("Extra bytes at end of Connect Acknowledgment packet")
|
423
495
|
end
|
424
496
|
end
|
497
|
+
|
498
|
+
def inspect
|
499
|
+
"\#<#{self.class}: 0x%2.2X>" % return_code
|
500
|
+
end
|
425
501
|
end
|
426
502
|
|
427
503
|
# Class representing an MQTT Publish Acknowledgment packet
|
@@ -447,6 +523,10 @@ module MQTT
|
|
447
523
|
raise ProtocolException.new("Extra bytes at end of Publish Acknowledgment packet")
|
448
524
|
end
|
449
525
|
end
|
526
|
+
|
527
|
+
def inspect
|
528
|
+
"\#<#{self.class}: 0x%2.2X>" % message_id
|
529
|
+
end
|
450
530
|
end
|
451
531
|
|
452
532
|
# Class representing an MQTT Publish Received packet
|
@@ -472,6 +552,10 @@ module MQTT
|
|
472
552
|
raise ProtocolException.new("Extra bytes at end of Publish Received packet")
|
473
553
|
end
|
474
554
|
end
|
555
|
+
|
556
|
+
def inspect
|
557
|
+
"\#<#{self.class}: 0x%2.2X>" % message_id
|
558
|
+
end
|
475
559
|
end
|
476
560
|
|
477
561
|
# Class representing an MQTT Publish Release packet
|
@@ -497,6 +581,10 @@ module MQTT
|
|
497
581
|
raise ProtocolException.new("Extra bytes at end of Publish Release packet")
|
498
582
|
end
|
499
583
|
end
|
584
|
+
|
585
|
+
def inspect
|
586
|
+
"\#<#{self.class}: 0x%2.2X>" % message_id
|
587
|
+
end
|
500
588
|
end
|
501
589
|
|
502
590
|
# Class representing an MQTT Publish Complete packet
|
@@ -522,6 +610,10 @@ module MQTT
|
|
522
610
|
raise ProtocolException.new("Extra bytes at end of Publish Complete packet")
|
523
611
|
end
|
524
612
|
end
|
613
|
+
|
614
|
+
def inspect
|
615
|
+
"\#<#{self.class}: 0x%2.2X>" % message_id
|
616
|
+
end
|
525
617
|
end
|
526
618
|
|
527
619
|
# Class representing an MQTT Client Subscribe packet
|
@@ -597,12 +689,19 @@ module MQTT
|
|
597
689
|
super(buffer)
|
598
690
|
@message_id = shift_short(buffer)
|
599
691
|
@topics = []
|
600
|
-
while(buffer.
|
692
|
+
while(buffer.bytesize>0)
|
601
693
|
topic_name = shift_string(buffer)
|
602
694
|
topic_qos = shift_byte(buffer)
|
603
695
|
@topics << [topic_name,topic_qos]
|
604
696
|
end
|
605
697
|
end
|
698
|
+
|
699
|
+
def inspect
|
700
|
+
str = "\#<#{self.class}: 0x%2.2X, %s>" % [
|
701
|
+
message_id,
|
702
|
+
topics.map {|t| "'#{t[0]}':#{t[1]}"}.join(', ')
|
703
|
+
]
|
704
|
+
end
|
606
705
|
end
|
607
706
|
|
608
707
|
# Class representing an MQTT Subscribe Acknowledgment packet
|
@@ -643,10 +742,14 @@ module MQTT
|
|
643
742
|
def parse_body(buffer)
|
644
743
|
super(buffer)
|
645
744
|
@message_id = shift_short(buffer)
|
646
|
-
while(buffer.
|
745
|
+
while(buffer.bytesize>0)
|
647
746
|
@granted_qos << shift_byte(buffer)
|
648
747
|
end
|
649
748
|
end
|
749
|
+
|
750
|
+
def inspect
|
751
|
+
"\#<#{self.class}: 0x%2.2X, qos=%s>" % [message_id, granted_qos.join(',')]
|
752
|
+
end
|
650
753
|
end
|
651
754
|
|
652
755
|
# Class representing an MQTT Client Unsubscribe packet
|
@@ -684,10 +787,17 @@ module MQTT
|
|
684
787
|
def parse_body(buffer)
|
685
788
|
super(buffer)
|
686
789
|
@message_id = shift_short(buffer)
|
687
|
-
while(buffer.
|
790
|
+
while(buffer.bytesize>0)
|
688
791
|
@topics << shift_string(buffer)
|
689
792
|
end
|
690
793
|
end
|
794
|
+
|
795
|
+
def inspect
|
796
|
+
str = "\#<#{self.class}: 0x%2.2X, %s>" % [
|
797
|
+
message_id,
|
798
|
+
topics.map {|t| "'#{t}'"}.join(', ')
|
799
|
+
]
|
800
|
+
end
|
691
801
|
end
|
692
802
|
|
693
803
|
# Class representing an MQTT Unsubscribe Acknowledgment packet
|
@@ -713,6 +823,10 @@ module MQTT
|
|
713
823
|
raise ProtocolException.new("Extra bytes at end of Unsubscribe Acknowledgment packet")
|
714
824
|
end
|
715
825
|
end
|
826
|
+
|
827
|
+
def inspect
|
828
|
+
"\#<#{self.class}: 0x%2.2X>" % message_id
|
829
|
+
end
|
716
830
|
end
|
717
831
|
|
718
832
|
# Class representing an MQTT Ping Request packet
|
@@ -762,7 +876,6 @@ module MQTT
|
|
762
876
|
end
|
763
877
|
end
|
764
878
|
end
|
765
|
-
|
766
879
|
end
|
767
880
|
|
768
881
|
|