mqtt 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|