mqtt 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,177 +1,174 @@
1
1
  # encoding: BINARY
2
2
 
3
- module MQTT::SN
3
+ module MQTT
4
+ module SN
5
+ # Class representing a MQTT::SN Packet
6
+ # Performs binary encoding and decoding of headers
7
+ class Packet
8
+ attr_accessor :duplicate # Duplicate delivery flag
9
+ attr_accessor :qos # Quality of Service level
10
+ attr_accessor :retain # Retain flag
11
+ attr_accessor :request_will # Request that gateway prompts for Will
12
+ attr_accessor :clean_session # When true, subscriptions are deleted after disconnect
13
+ attr_accessor :topic_id_type # One of :normal, :predefined or :short
14
+
15
+ DEFAULTS = {}
16
+
17
+ # Parse buffer into new packet object
18
+ def self.parse(buffer)
19
+ # Parse the fixed header (length and type)
20
+ length, type_id, body = buffer.unpack('CCa*')
21
+ length, type_id, body = buffer.unpack('xnCa*') if length == 1
22
+
23
+ # Double-check the length
24
+ if buffer.length != length
25
+ raise ProtocolException, 'Length of packet is not the same as the length header'
26
+ end
4
27
 
5
- # Class representing a MQTT::SN Packet
6
- # Performs binary encoding and decoding of headers
7
- class Packet
8
- attr_accessor :duplicate # Duplicate delivery flag
9
- attr_accessor :qos # Quality of Service level
10
- attr_accessor :retain # Retain flag
11
- attr_accessor :request_will # Request that gateway prompts for Will
12
- attr_accessor :clean_session # When true, subscriptions are deleted after disconnect
13
- attr_accessor :topic_id_type # One of :normal, :predefined or :short
28
+ packet_class = PACKET_TYPES[type_id]
29
+ if packet_class.nil?
30
+ raise ProtocolException, "Invalid packet type identifier: #{type_id}"
31
+ end
14
32
 
15
- DEFAULTS = {}
33
+ # Create a new packet object
34
+ packet = packet_class.new
35
+ packet.parse_body(body)
16
36
 
17
- # Parse buffer into new packet object
18
- def self.parse(buffer)
19
- # Parse the fixed header (length and type)
20
- length,type_id,body = buffer.unpack('CCa*')
21
- if length == 1
22
- length,type_id,body = buffer.unpack('xnCa*')
37
+ packet
23
38
  end
24
39
 
25
- # Double-check the length
26
- if buffer.length != length
27
- raise ProtocolException.new("Length of packet is not the same as the length header")
40
+ # Create a new empty packet
41
+ def initialize(args = {})
42
+ update_attributes(self.class::DEFAULTS.merge(args))
28
43
  end
29
44
 
30
- packet_class = PACKET_TYPES[type_id]
31
- if packet_class.nil?
32
- raise ProtocolException.new("Invalid packet type identifier: #{type_id}")
45
+ def update_attributes(attr = {})
46
+ attr.each_pair do |k, v|
47
+ send("#{k}=", v)
48
+ end
33
49
  end
34
50
 
35
- # Create a new packet object
36
- packet = packet_class.new
37
- packet.parse_body(body)
51
+ # Get the identifer for this packet type
52
+ def type_id
53
+ PACKET_TYPES.each_pair do |key, value|
54
+ return key if self.class == value
55
+ end
56
+ raise "Invalid packet type: #{self.class}"
57
+ end
38
58
 
39
- return packet
40
- end
59
+ # Serialise the packet
60
+ def to_s
61
+ # Get the packet's variable header and payload
62
+ body = encode_body
41
63
 
42
- # Create a new empty packet
43
- def initialize(args={})
44
- update_attributes(self.class::DEFAULTS.merge(args))
45
- end
64
+ # Build up the body length field bytes
65
+ body_length = body.length
66
+ raise 'MQTT-SN Packet is too big, maximum packet body size is 65531' if body_length > 65_531
46
67
 
47
- def update_attributes(attr={})
48
- attr.each_pair do |k,v|
49
- send("#{k}=", v)
68
+ if body_length > 253
69
+ [0x01, body_length + 4, type_id].pack('CnC') + body
70
+ else
71
+ [body_length + 2, type_id].pack('CC') + body
72
+ end
50
73
  end
51
- end
52
74
 
53
- # Get the identifer for this packet type
54
- def type_id
55
- PACKET_TYPES.each_pair do |key, value|
56
- return key if self.class == value
57
- end
58
- raise "Invalid packet type: #{self.class}"
59
- end
75
+ def parse_body(buffer); end
60
76
 
61
- # Serialise the packet
62
- def to_s
63
- # Get the packet's variable header and payload
64
- body = self.encode_body
77
+ protected
65
78
 
66
- # Build up the body length field bytes
67
- body_length = body.length
68
- if body_length > 65531
69
- raise "MQTT-SN Packet is too big, maximum packet body size is 65531"
70
- elsif body_length > 253
71
- [0x01, body_length + 4, type_id].pack('CnC') + body
72
- else
73
- [body_length + 2, type_id].pack('CC') + body
74
- end
75
- end
76
-
77
- def parse_body(buffer)
78
- end
79
+ def parse_flags(flags)
80
+ self.duplicate = ((flags & 0x80) >> 7) == 0x01
81
+ self.qos = (flags & 0x60) >> 5
82
+ self.qos = -1 if qos == 3
83
+ self.retain = ((flags & 0x10) >> 4) == 0x01
84
+ self.request_will = ((flags & 0x08) >> 3) == 0x01
85
+ self.clean_session = ((flags & 0x04) >> 2) == 0x01
79
86
 
80
- protected
81
-
82
- def parse_flags(flags)
83
- self.duplicate = ((flags & 0x80) >> 7) == 0x01
84
- self.qos = (flags & 0x60) >> 5
85
- self.qos = -1 if self.qos == 3
86
- self.retain = ((flags & 0x10) >> 4) == 0x01
87
- self.request_will = ((flags & 0x08) >> 3) == 0x01
88
- self.clean_session = ((flags & 0x04) >> 2) == 0x01
89
- case (flags & 0x03)
90
- when 0x0
91
- self.topic_id_type = :normal
92
- when 0x1
93
- self.topic_id_type = :predefined
94
- when 0x2
95
- self.topic_id_type = :short
96
- else
97
- self.topic_id_type = nil
87
+ self.topic_id_type =
88
+ case (flags & 0x03)
89
+ when 0x0
90
+ :normal
91
+ when 0x1
92
+ :predefined
93
+ when 0x2
94
+ :short
95
+ end
98
96
  end
99
- end
100
97
 
101
- # Get serialisation of packet's body (variable header and payload)
102
- def encode_body
103
- '' # No body by default
104
- end
98
+ # Get serialisation of packet's body (variable header and payload)
99
+ def encode_body
100
+ '' # No body by default
101
+ end
105
102
 
106
- def encode_flags
107
- flags = 0x00
108
- flags += 0x80 if duplicate
109
- case qos
103
+ def encode_flags
104
+ flags = 0x00
105
+ flags += 0x80 if duplicate
106
+ case qos
110
107
  when -1
111
108
  flags += 0x60
112
109
  when 1
113
110
  flags += 0x20
114
111
  when 2
115
112
  flags += 0x40
116
- end
117
- flags += 0x10 if retain
118
- flags += 0x08 if request_will
119
- flags += 0x04 if clean_session
120
- case topic_id_type
113
+ end
114
+ flags += 0x10 if retain
115
+ flags += 0x08 if request_will
116
+ flags += 0x04 if clean_session
117
+ case topic_id_type
121
118
  when :normal
122
119
  flags += 0x0
123
120
  when :predefined
124
121
  flags += 0x1
125
122
  when :short
126
123
  flags += 0x2
124
+ end
125
+ flags
127
126
  end
128
- return flags
129
- end
130
127
 
131
- def encode_topic_id
132
- if topic_id_type == :short
133
- unless topic_id.is_a?(String)
134
- raise "topic_id must be an String for type #{topic_id_type}"
135
- end
136
- (topic_id[0].ord << 8) + topic_id[1].ord
137
- else
138
- unless topic_id.is_a?(Integer)
139
- raise "topic_id must be an Integer for type #{topic_id_type}"
128
+ def encode_topic_id
129
+ if topic_id_type == :short
130
+ unless topic_id.is_a?(String)
131
+ raise "topic_id must be an String for type #{topic_id_type}"
132
+ end
133
+ (topic_id[0].ord << 8) + topic_id[1].ord
134
+ else
135
+ unless topic_id.is_a?(Integer)
136
+ raise "topic_id must be an Integer for type #{topic_id_type}"
137
+ end
138
+ topic_id
140
139
  end
141
- topic_id
142
140
  end
143
- end
144
141
 
145
- def parse_topic_id(topic_id)
146
- if topic_id_type == :short
147
- int = topic_id.to_i
148
- self.topic_id = [(int >> 8) & 0xFF, int & 0xFF].pack('CC')
149
- else
150
- self.topic_id = topic_id
142
+ def parse_topic_id(topic_id)
143
+ if topic_id_type == :short
144
+ int = topic_id.to_i
145
+ self.topic_id = [(int >> 8) & 0xFF, int & 0xFF].pack('CC')
146
+ else
147
+ self.topic_id = topic_id
148
+ end
151
149
  end
152
- end
153
150
 
154
- # Used where a field can either be a Topic Id or a Topic Name
155
- # (the Subscribe and Unsubscribe packet types)
156
- def encode_topic
157
- case topic_id_type
151
+ # Used where a field can either be a Topic Id or a Topic Name
152
+ # (the Subscribe and Unsubscribe packet types)
153
+ def encode_topic
154
+ case topic_id_type
158
155
  when :normal
159
156
  topic_name
160
157
  when :short
161
- unless topic_name.nil?
162
- topic_name
163
- else
158
+ if topic_name.nil?
164
159
  topic_id
160
+ else
161
+ topic_name
165
162
  end
166
163
  when :predefined
167
164
  [topic_id].pack('n')
165
+ end
168
166
  end
169
- end
170
167
 
171
- # Used where a field can either be a Topic Id or a Topic Name
172
- # (the Subscribe and Unsubscribe packet types)
173
- def parse_topic(topic)
174
- case topic_id_type
168
+ # Used where a field can either be a Topic Id or a Topic Name
169
+ # (the Subscribe and Unsubscribe packet types)
170
+ def parse_topic(topic)
171
+ case topic_id_type
175
172
  when :normal
176
173
  self.topic_name = topic
177
174
  when :short
@@ -179,558 +176,518 @@ module MQTT::SN
179
176
  self.topic_id = topic
180
177
  when :predefined
181
178
  self.topic_id = topic.unpack('n').first
179
+ end
182
180
  end
183
- end
184
181
 
185
- class Advertise < Packet
186
- attr_accessor :gateway_id
187
- attr_accessor :duration
182
+ class Advertise < Packet
183
+ attr_accessor :gateway_id
184
+ attr_accessor :duration
188
185
 
189
- DEFAULTS = {
190
- :gateway_id => 0x00,
191
- :duration => 0
192
- }
186
+ DEFAULTS = {
187
+ :gateway_id => 0x00,
188
+ :duration => 0
189
+ }
193
190
 
194
- def encode_body
195
- [gateway_id, duration].pack('Cn')
196
- end
191
+ def encode_body
192
+ [gateway_id, duration].pack('Cn')
193
+ end
197
194
 
198
- def parse_body(buffer)
199
- self.gateway_id, self.duration = buffer.unpack('Cn')
195
+ def parse_body(buffer)
196
+ self.gateway_id, self.duration = buffer.unpack('Cn')
197
+ end
200
198
  end
201
- end
202
199
 
203
- class Searchgw < Packet
204
- attr_accessor :radius
205
- DEFAULTS = {
206
- :radius => 1
207
- }
200
+ class Searchgw < Packet
201
+ attr_accessor :radius
202
+ DEFAULTS = {
203
+ :radius => 1
204
+ }
208
205
 
209
- def encode_body
210
- [radius].pack('C')
211
- end
206
+ def encode_body
207
+ [radius].pack('C')
208
+ end
212
209
 
213
- def parse_body(buffer)
214
- self.radius, _ignore = buffer.unpack('C')
210
+ def parse_body(buffer)
211
+ self.radius, _ignore = buffer.unpack('C')
212
+ end
215
213
  end
216
- end
217
214
 
218
- class Gwinfo < Packet
219
- attr_accessor :gateway_id
220
- attr_accessor :gateway_address
221
- DEFAULTS = {
222
- :gateway_id => 0,
223
- :gateway_address => nil
224
- }
215
+ class Gwinfo < Packet
216
+ attr_accessor :gateway_id
217
+ attr_accessor :gateway_address
218
+ DEFAULTS = {
219
+ :gateway_id => 0,
220
+ :gateway_address => nil
221
+ }
225
222
 
226
- def encode_body
227
- [gateway_id,gateway_address].pack('Ca*')
228
- end
223
+ def encode_body
224
+ [gateway_id, gateway_address].pack('Ca*')
225
+ end
229
226
 
230
- def parse_body(buffer)
231
- if buffer.length > 1
232
- self.gateway_id, self.gateway_address = buffer.unpack('Ca*')
233
- else
234
- self.gateway_id, _ignore = buffer.unpack('C')
235
- self.gateway_address = nil
227
+ def parse_body(buffer)
228
+ if buffer.length > 1
229
+ self.gateway_id, self.gateway_address = buffer.unpack('Ca*')
230
+ else
231
+ self.gateway_id, _ignore = buffer.unpack('C')
232
+ self.gateway_address = nil
233
+ end
236
234
  end
237
235
  end
238
- end
239
236
 
240
- class Connect < Packet
241
- attr_accessor :keep_alive
242
- attr_accessor :client_id
237
+ class Connect < Packet
238
+ attr_accessor :keep_alive
239
+ attr_accessor :client_id
243
240
 
244
- DEFAULTS = {
245
- :request_will => false,
246
- :clean_session => true,
247
- :keep_alive => 15
248
- }
241
+ DEFAULTS = {
242
+ :request_will => false,
243
+ :clean_session => true,
244
+ :keep_alive => 15
245
+ }
249
246
 
250
- # Get serialisation of packet's body
251
- def encode_body
252
- if @client_id.nil? or @client_id.length < 1 or @client_id.length > 23
253
- raise "Invalid client identifier when serialising packet"
247
+ # Get serialisation of packet's body
248
+ def encode_body
249
+ if @client_id.nil? || @client_id.empty? || @client_id.length > 23
250
+ raise 'Invalid client identifier when serialising packet'
251
+ end
252
+
253
+ [encode_flags, 0x01, keep_alive, client_id].pack('CCna*')
254
254
  end
255
255
 
256
- [encode_flags, 0x01, keep_alive, client_id].pack('CCna*')
257
- end
256
+ def parse_body(buffer)
257
+ flags, protocol_id, self.keep_alive, self.client_id = buffer.unpack('CCna*')
258
258
 
259
- def parse_body(buffer)
260
- flags, protocol_id, self.keep_alive, self.client_id = buffer.unpack('CCna*')
259
+ if protocol_id != 0x01
260
+ raise ProtocolException, "Unsupported protocol ID number: #{protocol_id}"
261
+ end
261
262
 
262
- if protocol_id != 0x01
263
- raise ProtocolException.new("Unsupported protocol ID number: #{protocol_id}")
263
+ parse_flags(flags)
264
264
  end
265
-
266
- parse_flags(flags)
267
265
  end
268
- end
269
266
 
270
- class Connack < Packet
271
- attr_accessor :return_code
267
+ class Connack < Packet
268
+ attr_accessor :return_code
272
269
 
273
- # Get a string message corresponding to a return code
274
- def return_msg
275
- case return_code
270
+ # Get a string message corresponding to a return code
271
+ def return_msg
272
+ case return_code
276
273
  when 0x00
277
- "Accepted"
274
+ 'Accepted'
278
275
  when 0x01
279
- "Rejected: congestion"
276
+ 'Rejected: congestion'
280
277
  when 0x02
281
- "Rejected: invalid topic ID"
278
+ 'Rejected: invalid topic ID'
282
279
  when 0x03
283
- "Rejected: not supported"
280
+ 'Rejected: not supported'
284
281
  else
285
282
  "Rejected: error code #{return_code}"
283
+ end
286
284
  end
287
- end
288
285
 
289
- def encode_body
290
- unless return_code.is_a?(Integer)
291
- raise "return_code must be an Integer"
286
+ def encode_body
287
+ raise 'return_code must be an Integer' unless return_code.is_a?(Integer)
288
+
289
+ [return_code].pack('C')
292
290
  end
293
291
 
294
- [return_code].pack('C')
292
+ def parse_body(buffer)
293
+ self.return_code = buffer.unpack('C')[0]
294
+ end
295
295
  end
296
296
 
297
- def parse_body(buffer)
298
- self.return_code = buffer.unpack('C')[0]
297
+ class Willtopicreq < Packet
298
+ # No attributes
299
299
  end
300
- end
301
300
 
302
- class Willtopicreq < Packet
303
- # No attributes
304
- end
301
+ class Willtopic < Packet
302
+ attr_accessor :topic_name
305
303
 
306
- class Willtopic < Packet
307
- attr_accessor :topic_name
304
+ DEFAULTS = {
305
+ :qos => 0,
306
+ :retain => false,
307
+ :topic_name => nil
308
+ }
308
309
 
309
- DEFAULTS = {
310
- :qos => 0,
311
- :retain => false,
312
- :topic_name => nil
313
- }
310
+ def encode_body
311
+ if topic_name.nil? || topic_name.empty?
312
+ ''
313
+ else
314
+ [encode_flags, topic_name].pack('Ca*')
315
+ end
316
+ end
314
317
 
315
- def encode_body
316
- if topic_name.nil? or topic_name.empty?
317
- ''
318
- else
319
- [encode_flags, topic_name].pack('Ca*')
318
+ def parse_body(buffer)
319
+ if buffer.length > 1
320
+ flags, self.topic_name = buffer.unpack('Ca*')
321
+ else
322
+ flags, _ignore = buffer.unpack('C')
323
+ self.topic_name = nil
324
+ end
325
+ parse_flags(flags)
320
326
  end
321
327
  end
322
328
 
323
- def parse_body(buffer)
324
- if buffer.length > 1
325
- flags, self.topic_name = buffer.unpack('Ca*')
326
- else
327
- flags, _ignore = buffer.unpack('C')
328
- self.topic_name = nil
329
- end
330
- parse_flags(flags)
329
+ class Willmsgreq < Packet
330
+ # No attributes
331
331
  end
332
- end
333
332
 
334
- class Willmsgreq < Packet
335
- # No attributes
336
- end
333
+ class Willmsg < Packet
334
+ attr_accessor :data
337
335
 
338
- class Willmsg < Packet
339
- attr_accessor :data
336
+ def encode_body
337
+ data
338
+ end
340
339
 
341
- def encode_body
342
- data
340
+ def parse_body(buffer)
341
+ self.data = buffer
342
+ end
343
343
  end
344
344
 
345
- def parse_body(buffer)
346
- self.data = buffer
347
- end
348
- end
345
+ class Register < Packet
346
+ attr_accessor :id
347
+ attr_accessor :topic_id
348
+ attr_accessor :topic_name
349
349
 
350
- class Register < Packet
351
- attr_accessor :id
352
- attr_accessor :topic_id
353
- attr_accessor :topic_name
350
+ DEFAULTS = {
351
+ :id => 0x00,
352
+ :topic_id_type => :normal
353
+ }
354
354
 
355
- DEFAULTS = {
356
- :id => 0x00,
357
- :topic_id_type => :normal
358
- }
355
+ def encode_body
356
+ raise 'id must be an Integer' unless id.is_a?(Integer)
359
357
 
360
- def encode_body
361
- unless id.is_a?(Integer)
362
- raise "id must be an Integer"
363
- end
358
+ raise 'topic_id must be an Integer' unless topic_id.is_a?(Integer)
364
359
 
365
- unless topic_id.is_a?(Integer)
366
- raise "topic_id must be an Integer"
360
+ [topic_id, id, topic_name].pack('nna*')
367
361
  end
368
362
 
369
- [topic_id, id, topic_name].pack('nna*')
363
+ def parse_body(buffer)
364
+ self.topic_id, self.id, self.topic_name = buffer.unpack('nna*')
365
+ end
370
366
  end
371
367
 
372
- def parse_body(buffer)
373
- self.topic_id, self.id, self.topic_name = buffer.unpack('nna*')
374
- end
375
- end
368
+ class Regack < Packet
369
+ attr_accessor :id
370
+ attr_accessor :topic_id
371
+ attr_accessor :return_code
376
372
 
377
- class Regack < Packet
378
- attr_accessor :id
379
- attr_accessor :topic_id
380
- attr_accessor :return_code
373
+ DEFAULTS = {
374
+ :id => 0x00,
375
+ :topic_id => 0x00,
376
+ :topic_id_type => :normal
377
+ }
381
378
 
382
- DEFAULTS = {
383
- :id => 0x00,
384
- :topic_id => 0x00,
385
- :topic_id_type => :normal
386
- }
379
+ def encode_body
380
+ raise 'id must be an Integer' unless id.is_a?(Integer)
387
381
 
388
- def encode_body
389
- unless id.is_a?(Integer)
390
- raise "id must be an Integer"
391
- end
382
+ raise 'topic_id must be an Integer' unless topic_id.is_a?(Integer)
392
383
 
393
- unless topic_id.is_a?(Integer)
394
- raise "topic_id must be an Integer"
384
+ [topic_id, id, return_code].pack('nnC')
395
385
  end
396
386
 
397
- [topic_id, id, return_code].pack('nnC')
387
+ def parse_body(buffer)
388
+ self.topic_id, self.id, self.return_code = buffer.unpack('nnC')
389
+ end
398
390
  end
399
391
 
400
- def parse_body(buffer)
401
- self.topic_id, self.id, self.return_code = buffer.unpack('nnC')
402
- end
403
- end
392
+ class Publish < Packet
393
+ attr_accessor :topic_id
394
+ attr_accessor :id
395
+ attr_accessor :data
404
396
 
405
- class Publish < Packet
406
- attr_accessor :topic_id
407
- attr_accessor :id
408
- attr_accessor :data
397
+ DEFAULTS = {
398
+ :id => 0x00,
399
+ :duplicate => false,
400
+ :qos => 0,
401
+ :retain => false,
402
+ :topic_id_type => :normal
403
+ }
409
404
 
410
- DEFAULTS = {
411
- :id => 0x00,
412
- :duplicate => false,
413
- :qos => 0,
414
- :retain => false,
415
- :topic_id_type => :normal
416
- }
405
+ def encode_body
406
+ raise 'id must be an Integer' unless id.is_a?(Integer)
417
407
 
418
- def encode_body
419
- unless id.is_a?(Integer)
420
- raise "id must be an Integer"
408
+ [encode_flags, encode_topic_id, id, data].pack('Cnna*')
421
409
  end
422
410
 
423
- [encode_flags, encode_topic_id, id, data].pack('Cnna*')
411
+ def parse_body(buffer)
412
+ flags, topic_id, self.id, self.data = buffer.unpack('Cnna*')
413
+ parse_flags(flags)
414
+ parse_topic_id(topic_id)
415
+ end
424
416
  end
425
417
 
426
- def parse_body(buffer)
427
- flags, topic_id, self.id, self.data = buffer.unpack('Cnna*')
428
- parse_flags(flags)
429
- parse_topic_id(topic_id)
430
- end
431
- end
418
+ class Puback < Packet
419
+ attr_accessor :topic_id
420
+ attr_accessor :id
421
+ attr_accessor :return_code
432
422
 
433
- class Puback < Packet
434
- attr_accessor :topic_id
435
- attr_accessor :id
436
- attr_accessor :return_code
423
+ DEFAULTS = {
424
+ :id => 0x00,
425
+ :topic_id => nil,
426
+ :return_code => 0x00
427
+ }
437
428
 
438
- DEFAULTS = {
439
- :id => 0x00,
440
- :topic_id => nil,
441
- :return_code => 0x00,
442
- }
429
+ def encode_body
430
+ raise 'id must be an Integer' unless id.is_a?(Integer)
443
431
 
444
- def encode_body
445
- unless id.is_a?(Integer)
446
- raise "id must be an Integer"
447
- end
432
+ raise 'topic_id must be an Integer' unless topic_id.is_a?(Integer)
448
433
 
449
- unless topic_id.is_a?(Integer)
450
- raise "topic_id must be an Integer"
434
+ [topic_id, id, return_code].pack('nnC')
451
435
  end
452
436
 
453
- [topic_id, id, return_code].pack('nnC')
437
+ def parse_body(buffer)
438
+ self.topic_id, self.id, self.return_code = buffer.unpack('nnC')
439
+ end
454
440
  end
455
441
 
456
- def parse_body(buffer)
457
- self.topic_id, self.id, self.return_code = buffer.unpack('nnC')
458
- end
459
- end
442
+ class Pubcomp < Packet
443
+ attr_accessor :id
460
444
 
461
- class Pubcomp < Packet
462
- attr_accessor :id
445
+ DEFAULTS = {
446
+ :id => 0x00
447
+ }
463
448
 
464
- DEFAULTS = {
465
- :id => 0x00
466
- }
449
+ def encode_body
450
+ raise 'id must be an Integer' unless id.is_a?(Integer)
467
451
 
468
- def encode_body
469
- unless id.is_a?(Integer)
470
- raise "id must be an Integer"
452
+ [id].pack('n')
471
453
  end
472
454
 
473
- [id].pack('n')
455
+ def parse_body(buffer)
456
+ self.id, _ignore = buffer.unpack('n')
457
+ end
474
458
  end
475
459
 
476
- def parse_body(buffer)
477
- self.id, _ignore = buffer.unpack('n')
478
- end
479
- end
460
+ class Pubrec < Packet
461
+ attr_accessor :id
480
462
 
481
- class Pubrec < Packet
482
- attr_accessor :id
463
+ DEFAULTS = {
464
+ :id => 0x00
465
+ }
483
466
 
484
- DEFAULTS = {
485
- :id => 0x00
486
- }
467
+ def encode_body
468
+ raise 'id must be an Integer' unless id.is_a?(Integer)
487
469
 
488
- def encode_body
489
- unless id.is_a?(Integer)
490
- raise "id must be an Integer"
470
+ [id].pack('n')
491
471
  end
492
472
 
493
- [id].pack('n')
473
+ def parse_body(buffer)
474
+ self.id, _ignore = buffer.unpack('n')
475
+ end
494
476
  end
495
477
 
496
- def parse_body(buffer)
497
- self.id, _ignore = buffer.unpack('n')
498
- end
499
- end
478
+ class Pubrel < Packet
479
+ attr_accessor :id
500
480
 
501
- class Pubrel < Packet
502
- attr_accessor :id
481
+ DEFAULTS = {
482
+ :id => 0x00
483
+ }
503
484
 
504
- DEFAULTS = {
505
- :id => 0x00
506
- }
485
+ def encode_body
486
+ raise 'id must be an Integer' unless id.is_a?(Integer)
507
487
 
508
- def encode_body
509
- unless id.is_a?(Integer)
510
- raise "id must be an Integer"
488
+ [id].pack('n')
511
489
  end
512
490
 
513
- [id].pack('n')
491
+ def parse_body(buffer)
492
+ self.id, _ignore = buffer.unpack('n')
493
+ end
514
494
  end
515
495
 
516
- def parse_body(buffer)
517
- self.id, _ignore = buffer.unpack('n')
518
- end
519
- end
496
+ class Subscribe < Packet
497
+ attr_accessor :id
498
+ attr_accessor :topic_id
499
+ attr_accessor :topic_name
520
500
 
521
- class Subscribe < Packet
522
- attr_accessor :id
523
- attr_accessor :topic_id
524
- attr_accessor :topic_name
501
+ DEFAULTS = {
502
+ :id => 0x00,
503
+ :topic_id_type => :normal
504
+ }
525
505
 
526
- DEFAULTS = {
527
- :id => 0x00,
528
- :topic_id_type => :normal
529
- }
506
+ def encode_body
507
+ raise 'id must be an Integer' unless id.is_a?(Integer)
530
508
 
531
- def encode_body
532
- unless id.is_a?(Integer)
533
- raise "id must be an Integer"
509
+ [encode_flags, id, encode_topic].pack('Cna*')
534
510
  end
535
511
 
536
- [encode_flags, id, encode_topic].pack('Cna*')
512
+ def parse_body(buffer)
513
+ flags, self.id, topic = buffer.unpack('Cna*')
514
+ parse_flags(flags)
515
+ parse_topic(topic)
516
+ end
537
517
  end
538
518
 
539
- def parse_body(buffer)
540
- flags, self.id, topic = buffer.unpack('Cna*')
541
- parse_flags(flags)
542
- parse_topic(topic)
543
- end
544
- end
519
+ class Suback < Packet
520
+ attr_accessor :id
521
+ attr_accessor :topic_id
522
+ attr_accessor :return_code
545
523
 
546
- class Suback < Packet
547
- attr_accessor :id
548
- attr_accessor :topic_id
549
- attr_accessor :return_code
524
+ DEFAULTS = {
525
+ :qos => 0,
526
+ :id => 0x00,
527
+ :topic_id => 0x00,
528
+ :topic_id_type => :normal
529
+ }
550
530
 
551
- DEFAULTS = {
552
- :qos => 0,
553
- :id => 0x00,
554
- :topic_id => 0x00,
555
- :topic_id_type => :normal
556
- }
531
+ def encode_body
532
+ raise 'id must be an Integer' unless id.is_a?(Integer)
557
533
 
558
- def encode_body
559
- unless id.is_a?(Integer)
560
- raise "id must be an Integer"
534
+ [encode_flags, encode_topic_id, id, return_code].pack('CnnC')
561
535
  end
562
536
 
563
- [encode_flags, encode_topic_id, id, return_code].pack('CnnC')
537
+ def parse_body(buffer)
538
+ flags, topic_id, self.id, self.return_code = buffer.unpack('CnnC')
539
+ parse_flags(flags)
540
+ parse_topic_id(topic_id)
541
+ end
564
542
  end
565
543
 
566
- def parse_body(buffer)
567
- flags, topic_id, self.id, self.return_code = buffer.unpack('CnnC')
568
- parse_flags(flags)
569
- parse_topic_id(topic_id)
570
- end
571
- end
544
+ class Unsubscribe < Packet
545
+ attr_accessor :id
546
+ attr_accessor :topic_id
547
+ attr_accessor :topic_name
572
548
 
573
- class Unsubscribe < Packet
574
- attr_accessor :id
575
- attr_accessor :topic_id
576
- attr_accessor :topic_name
549
+ DEFAULTS = {
550
+ :id => 0x00,
551
+ :topic_id_type => :normal
552
+ }
577
553
 
578
- DEFAULTS = {
579
- :id => 0x00,
580
- :topic_id_type => :normal
581
- }
554
+ def encode_body
555
+ raise 'id must be an Integer' unless id.is_a?(Integer)
582
556
 
583
- def encode_body
584
- unless id.is_a?(Integer)
585
- raise "id must be an Integer"
557
+ [encode_flags, id, encode_topic].pack('Cna*')
586
558
  end
587
559
 
588
- [encode_flags, id, encode_topic].pack('Cna*')
560
+ def parse_body(buffer)
561
+ flags, self.id, topic = buffer.unpack('Cna*')
562
+ parse_flags(flags)
563
+ parse_topic(topic)
564
+ end
589
565
  end
590
566
 
591
- def parse_body(buffer)
592
- flags, self.id, topic = buffer.unpack('Cna*')
593
- parse_flags(flags)
594
- parse_topic(topic)
595
- end
596
- end
567
+ class Unsuback < Packet
568
+ attr_accessor :id
597
569
 
598
- class Unsuback < Packet
599
- attr_accessor :id
570
+ DEFAULTS = {
571
+ :id => 0x00
572
+ }
600
573
 
601
- DEFAULTS = {
602
- :id => 0x00,
603
- }
574
+ def encode_body
575
+ raise 'id must be an Integer' unless id.is_a?(Integer)
604
576
 
605
- def encode_body
606
- unless id.is_a?(Integer)
607
- raise "id must be an Integer"
577
+ [id].pack('n')
608
578
  end
609
579
 
610
- [id].pack('n')
580
+ def parse_body(buffer)
581
+ self.id = buffer.unpack('n').first
582
+ end
611
583
  end
612
584
 
613
- def parse_body(buffer)
614
- self.id = buffer.unpack('n').first
585
+ class Pingreq < Packet
586
+ # No attributes
615
587
  end
616
- end
617
-
618
- class Pingreq < Packet
619
- # No attributes
620
- end
621
588
 
622
- class Pingresp < Packet
623
- # No attributes
624
- end
589
+ class Pingresp < Packet
590
+ # No attributes
591
+ end
625
592
 
626
- class Disconnect < Packet
627
- attr_accessor :duration
593
+ class Disconnect < Packet
594
+ attr_accessor :duration
628
595
 
629
- DEFAULTS = {
630
- :duration => nil
631
- }
596
+ DEFAULTS = {
597
+ :duration => nil
598
+ }
632
599
 
633
- def encode_body
634
- if duration.nil? or duration == 0
635
- ''
636
- else
637
- [duration].pack('n')
600
+ def encode_body
601
+ if duration.nil? || duration.zero?
602
+ ''
603
+ else
604
+ [duration].pack('n')
605
+ end
638
606
  end
639
- end
640
607
 
641
- def parse_body(buffer)
642
- if buffer.length == 2
643
- self.duration = buffer.unpack('n').first
644
- else
645
- self.duration = nil
608
+ def parse_body(buffer)
609
+ self.duration = buffer.length == 2 ? buffer.unpack('n').first : nil
646
610
  end
647
611
  end
648
- end
649
612
 
650
- class Willtopicupd < Packet
651
- attr_accessor :topic_name
613
+ class Willtopicupd < Packet
614
+ attr_accessor :topic_name
652
615
 
653
- DEFAULTS = {
654
- :qos => 0,
655
- :retain => false,
656
- :topic_name => nil
657
- }
616
+ DEFAULTS = {
617
+ :qos => 0,
618
+ :retain => false,
619
+ :topic_name => nil
620
+ }
658
621
 
659
- def encode_body
660
- if topic_name.nil? or topic_name.empty?
661
- ''
662
- else
663
- [encode_flags, topic_name].pack('Ca*')
622
+ def encode_body
623
+ if topic_name.nil? || topic_name.empty?
624
+ ''
625
+ else
626
+ [encode_flags, topic_name].pack('Ca*')
627
+ end
664
628
  end
665
- end
666
629
 
667
- def parse_body(buffer)
668
- if buffer.length > 1
669
- flags, self.topic_name = buffer.unpack('Ca*')
670
- parse_flags(flags)
671
- else
672
- self.topic_name = nil
630
+ def parse_body(buffer)
631
+ if buffer.length > 1
632
+ flags, self.topic_name = buffer.unpack('Ca*')
633
+ parse_flags(flags)
634
+ else
635
+ self.topic_name = nil
636
+ end
673
637
  end
674
638
  end
675
- end
676
639
 
677
- class Willtopicresp < Packet
678
- attr_accessor :return_code
640
+ class Willtopicresp < Packet
641
+ attr_accessor :return_code
679
642
 
680
- DEFAULTS = {
681
- :return_code => 0x00
682
- }
643
+ DEFAULTS = {
644
+ :return_code => 0x00
645
+ }
683
646
 
684
- def encode_body
685
- unless return_code.is_a?(Integer)
686
- raise "return_code must be an Integer"
647
+ def encode_body
648
+ raise 'return_code must be an Integer' unless return_code.is_a?(Integer)
649
+
650
+ [return_code].pack('C')
687
651
  end
688
652
 
689
- [return_code].pack('C')
653
+ def parse_body(buffer)
654
+ self.return_code, _ignore = buffer.unpack('C')
655
+ end
690
656
  end
691
657
 
692
- def parse_body(buffer)
693
- self.return_code, _ignore = buffer.unpack('C')
694
- end
695
- end
658
+ class Willmsgupd < Packet
659
+ attr_accessor :data
696
660
 
697
- class Willmsgupd < Packet
698
- attr_accessor :data
661
+ def encode_body
662
+ data
663
+ end
699
664
 
700
- def encode_body
701
- data
665
+ def parse_body(buffer)
666
+ self.data = buffer
667
+ end
702
668
  end
703
669
 
704
- def parse_body(buffer)
705
- self.data = buffer
706
- end
707
- end
670
+ class Willmsgresp < Packet
671
+ attr_accessor :return_code
708
672
 
709
- class Willmsgresp < Packet
710
- attr_accessor :return_code
673
+ DEFAULTS = {
674
+ :return_code => 0x00
675
+ }
711
676
 
712
- DEFAULTS = {
713
- :return_code => 0x00
714
- }
677
+ def encode_body
678
+ raise 'return_code must be an Integer' unless return_code.is_a?(Integer)
715
679
 
716
- def encode_body
717
- unless return_code.is_a?(Integer)
718
- raise "return_code must be an Integer"
680
+ [return_code].pack('C')
719
681
  end
720
682
 
721
- [return_code].pack('C')
722
- end
723
-
724
- def parse_body(buffer)
725
- self.return_code, _ignore = buffer.unpack('C')
683
+ def parse_body(buffer)
684
+ self.return_code, _ignore = buffer.unpack('C')
685
+ end
726
686
  end
727
687
  end
728
688
 
729
- end
730
-
731
-
732
- # An enumeration of the MQTT-SN packet types
733
- PACKET_TYPES = {
689
+ # An enumeration of the MQTT-SN packet types
690
+ PACKET_TYPES = {
734
691
  0x00 => MQTT::SN::Packet::Advertise,
735
692
  0x01 => MQTT::SN::Packet::Searchgw,
736
693
  0x02 => MQTT::SN::Packet::Gwinfo,
@@ -757,7 +714,7 @@ module MQTT::SN
757
714
  0x1a => MQTT::SN::Packet::Willtopicupd,
758
715
  0x1b => MQTT::SN::Packet::Willtopicresp,
759
716
  0x1c => MQTT::SN::Packet::Willmsgupd,
760
- 0x1d => MQTT::SN::Packet::Willmsgresp,
761
- }
762
-
717
+ 0x1d => MQTT::SN::Packet::Willmsgresp
718
+ }
719
+ end
763
720
  end