mqtt-rails 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE +210 -0
- data/README.md +323 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/mqtt-rails.rb +144 -0
- data/lib/mqtt_rails/client.rb +414 -0
- data/lib/mqtt_rails/connection_helper.rb +172 -0
- data/lib/mqtt_rails/exception.rb +52 -0
- data/lib/mqtt_rails/handler.rb +274 -0
- data/lib/mqtt_rails/packet.rb +33 -0
- data/lib/mqtt_rails/packet/base.rb +315 -0
- data/lib/mqtt_rails/packet/connack.rb +102 -0
- data/lib/mqtt_rails/packet/connect.rb +183 -0
- data/lib/mqtt_rails/packet/disconnect.rb +38 -0
- data/lib/mqtt_rails/packet/pingreq.rb +29 -0
- data/lib/mqtt_rails/packet/pingresp.rb +38 -0
- data/lib/mqtt_rails/packet/puback.rb +44 -0
- data/lib/mqtt_rails/packet/pubcomp.rb +44 -0
- data/lib/mqtt_rails/packet/publish.rb +148 -0
- data/lib/mqtt_rails/packet/pubrec.rb +44 -0
- data/lib/mqtt_rails/packet/pubrel.rb +62 -0
- data/lib/mqtt_rails/packet/suback.rb +75 -0
- data/lib/mqtt_rails/packet/subscribe.rb +124 -0
- data/lib/mqtt_rails/packet/unsuback.rb +49 -0
- data/lib/mqtt_rails/packet/unsubscribe.rb +84 -0
- data/lib/mqtt_rails/publisher.rb +181 -0
- data/lib/mqtt_rails/sender.rb +129 -0
- data/lib/mqtt_rails/ssl_helper.rb +61 -0
- data/lib/mqtt_rails/subscriber.rb +166 -0
- data/lib/mqtt_rails/version.rb +3 -0
- data/mqtt-rails.gemspec +33 -0
- data/samples/client_blocking(reading).rb +29 -0
- data/samples/client_blocking(writing).rb +18 -0
- data/samples/getting_started.rb +49 -0
- data/samples/test_client.rb +69 -0
- metadata +126 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Pubrec < MqttRails::Packet::Base
|
23
|
+
# Get serialisation of packet's body
|
24
|
+
def encode_body
|
25
|
+
encode_short(@id)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Parse the body (variable header and payload) of a packet
|
29
|
+
def parse_body(buffer)
|
30
|
+
super(buffer)
|
31
|
+
@id = shift_short(buffer)
|
32
|
+
unless buffer.empty?
|
33
|
+
raise MqttRails::PacketFormatException.new(
|
34
|
+
"Extra bytes at end of Publish Received packet")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a human readable string, summarising the properties of the packet
|
39
|
+
def inspect
|
40
|
+
"\#<#{self.class}: 0x%2.2X>" % id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Pubrel < MqttRails::Packet::Base
|
23
|
+
# Default attribute values
|
24
|
+
ATTR_DEFAULTS = {
|
25
|
+
:flags => [false, true, false, false],
|
26
|
+
}
|
27
|
+
|
28
|
+
# Create a new Pubrel packet
|
29
|
+
def initialize(args={})
|
30
|
+
super(ATTR_DEFAULTS.merge(args))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get serialisation of packet's body
|
34
|
+
def encode_body
|
35
|
+
encode_short(@id)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Parse the body (variable header and payload) of a packet
|
39
|
+
def parse_body(buffer)
|
40
|
+
super(buffer)
|
41
|
+
@id = shift_short(buffer)
|
42
|
+
unless buffer.empty?
|
43
|
+
raise "Extra bytes at end of Publish Release packet"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Check that fixed header flags are valid for this packet type
|
48
|
+
# @private
|
49
|
+
def validate_flags
|
50
|
+
if @flags != [false, true, false, false]
|
51
|
+
raise MqttRails::PacketFormatException.new(
|
52
|
+
"Invalid flags in #{type_name} packet header")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns a human readable string, summarising the properties of the packet
|
57
|
+
def inspect
|
58
|
+
"\#<#{self.class}: 0x%2.2X>" % id
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Suback < MqttRails::Packet::Base
|
23
|
+
# An array of return codes, ordered by the topics that were subscribed to
|
24
|
+
attr_accessor :return_codes
|
25
|
+
|
26
|
+
# Default attribute values
|
27
|
+
ATTR_DEFAULTS = {
|
28
|
+
:return_codes => [],
|
29
|
+
}
|
30
|
+
|
31
|
+
# Create a new Subscribe Acknowledgment packet
|
32
|
+
def initialize(args={})
|
33
|
+
super(ATTR_DEFAULTS.merge(args))
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set the granted QoS value for each of the topics that were subscribed to
|
37
|
+
# Can either be an integer or an array or integers.
|
38
|
+
def return_codes=(value)
|
39
|
+
if value.is_a?(Array)
|
40
|
+
@return_codes = value
|
41
|
+
elsif value.is_a?(Integer)
|
42
|
+
@return_codes = [value]
|
43
|
+
else
|
44
|
+
raise MqttRails::PacketFormatException.new(
|
45
|
+
"return_codes should be an integer or an array of return codes")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get serialisation of packet's body
|
50
|
+
def encode_body
|
51
|
+
if @return_codes.empty?
|
52
|
+
raise MqttRails::PacketFormatException.new(
|
53
|
+
"No granted QoS given when serialising packet")
|
54
|
+
end
|
55
|
+
body = encode_short(@id)
|
56
|
+
return_codes.each { |qos| body += encode_bytes(qos) }
|
57
|
+
return body
|
58
|
+
end
|
59
|
+
|
60
|
+
# Parse the body (variable header and payload) of a packet
|
61
|
+
def parse_body(buffer)
|
62
|
+
super(buffer)
|
63
|
+
@id = shift_short(buffer)
|
64
|
+
while buffer.bytesize > 0
|
65
|
+
@return_codes << shift_byte(buffer)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns a human readable string, summarising the properties of the packet
|
70
|
+
def inspect
|
71
|
+
"\#<#{self.class}: 0x%2.2X, rc=%s>" % [id, return_codes.map { |rc| "0x%2.2X" % rc }.join(',')]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Subscribe < MqttRails::Packet::Base
|
23
|
+
# One or more topic filters to subscribe to
|
24
|
+
attr_accessor :topics
|
25
|
+
|
26
|
+
# Default attribute values
|
27
|
+
ATTR_DEFAULTS = {
|
28
|
+
:topics => [],
|
29
|
+
:flags => [false, true, false, false],
|
30
|
+
}
|
31
|
+
|
32
|
+
# Create a new Subscribe packet
|
33
|
+
def initialize(args={})
|
34
|
+
super(ATTR_DEFAULTS.merge(args))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set one or more topic filters for the Subscribe packet
|
38
|
+
# The topics parameter should be one of the following:
|
39
|
+
# * String: subscribe to one topic with QoS 0
|
40
|
+
# * Array: subscribe to multiple topics with QoS 0
|
41
|
+
# * Hash: subscribe to multiple topics where the key is the topic and the value is the QoS level
|
42
|
+
#
|
43
|
+
# For example:
|
44
|
+
# packet.topics = 'a/b'
|
45
|
+
# packet.topics = ['a/b', 'c/d']
|
46
|
+
# packet.topics = [['a/b',0], ['c/d',1]]
|
47
|
+
# packet.topics = {'a/b' => 0, 'c/d' => 1}
|
48
|
+
#
|
49
|
+
def topics=(value)
|
50
|
+
# Get input into a consistent state
|
51
|
+
if value.is_a?(Array)
|
52
|
+
input = value.flatten
|
53
|
+
else
|
54
|
+
input = [value]
|
55
|
+
end
|
56
|
+
|
57
|
+
@topics = []
|
58
|
+
while(input.length>0)
|
59
|
+
item = input.shift
|
60
|
+
if item.is_a?(Hash)
|
61
|
+
# Convert hash into an ordered array of arrays
|
62
|
+
@topics += item.sort
|
63
|
+
elsif item.is_a?(String)
|
64
|
+
# Peek at the next item in the array, and remove it if it is an integer
|
65
|
+
if input.first.is_a?(Integer)
|
66
|
+
qos = input.shift
|
67
|
+
@topics << [item, qos]
|
68
|
+
else
|
69
|
+
@topics << [item, 0]
|
70
|
+
end
|
71
|
+
else
|
72
|
+
# Meh?
|
73
|
+
raise MqttRails::PacketFormatException.new(
|
74
|
+
"Invalid topics input: #{value.inspect}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@topics
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get serialisation of packet's body
|
81
|
+
def encode_body
|
82
|
+
if @topics.empty?
|
83
|
+
raise MqttRails::PacketFormatException.new(
|
84
|
+
"No topics given when serialising packet")
|
85
|
+
end
|
86
|
+
body = encode_short(@id)
|
87
|
+
topics.each do |item|
|
88
|
+
body += encode_string(item[0])
|
89
|
+
body += encode_bytes(item[1])
|
90
|
+
end
|
91
|
+
return body
|
92
|
+
end
|
93
|
+
|
94
|
+
# Parse the body (variable header and payload) of a packet
|
95
|
+
def parse_body(buffer)
|
96
|
+
super(buffer)
|
97
|
+
@id = shift_short(buffer)
|
98
|
+
@topics = []
|
99
|
+
while(buffer.bytesize>0)
|
100
|
+
topic_name = shift_string(buffer)
|
101
|
+
topic_qos = shift_byte(buffer)
|
102
|
+
@topics << [topic_name, topic_qos]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Check that fixed header flags are valid for this packet type
|
107
|
+
# @private
|
108
|
+
def validate_flags
|
109
|
+
if @flags != [false, true, false, false]
|
110
|
+
raise MqttRails::PacketFormatException.new(
|
111
|
+
"Invalid flags in SUBSCRIBE packet header")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns a human readable string, summarising the properties of the packet
|
116
|
+
def inspect
|
117
|
+
_str = "\#<#{self.class}: 0x%2.2X, %s>" % [
|
118
|
+
id,
|
119
|
+
topics.map { |t| "'#{t[0]}':#{t[1]}" }.join(', ')
|
120
|
+
]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Unsuback < MqttRails::Packet::Base
|
23
|
+
# Create a new Unsubscribe Acknowledgment packet
|
24
|
+
def initialize(args={})
|
25
|
+
super(args)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get serialisation of packet's body
|
29
|
+
def encode_body
|
30
|
+
encode_short(@id)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Parse the body (variable header and payload) of a packet
|
34
|
+
def parse_body(buffer)
|
35
|
+
super(buffer)
|
36
|
+
@id = shift_short(buffer)
|
37
|
+
unless buffer.empty?
|
38
|
+
raise MqttRails::PacketFormatException.new(
|
39
|
+
"Extra bytes at end of Unsubscribe Acknowledgment packet")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns a human readable string, summarising the properties of the packet
|
44
|
+
def inspect
|
45
|
+
"\#<#{self.class}: 0x%2.2X>" % id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: BINARY
|
2
|
+
### original file from the ruby-mqtt gem
|
3
|
+
### located at https://github.com/njh/ruby-mqtt/blob/master/lib/mqtt/packet.rb
|
4
|
+
### Copyright (c) 2009-2013 Nicholas J Humfrey
|
5
|
+
|
6
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
7
|
+
#
|
8
|
+
# All rights reserved. This program and the accompanying materials
|
9
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
10
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
11
|
+
#
|
12
|
+
# The Eclipse Public License is available at
|
13
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
14
|
+
# and the Eclipse Distribution License is available at
|
15
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
16
|
+
#
|
17
|
+
# Contributors:
|
18
|
+
# Pierre Goudet - initial committer
|
19
|
+
|
20
|
+
module MqttRails
|
21
|
+
module Packet
|
22
|
+
class Unsubscribe < MqttRails::Packet::Base
|
23
|
+
# One or more topic paths to unsubscribe from
|
24
|
+
attr_accessor :topics
|
25
|
+
|
26
|
+
# Default attribute values
|
27
|
+
ATTR_DEFAULTS = {
|
28
|
+
:topics => [],
|
29
|
+
:flags => [false, true, false, false],
|
30
|
+
}
|
31
|
+
|
32
|
+
# Create a new Unsubscribe packet
|
33
|
+
def initialize(args={})
|
34
|
+
super(ATTR_DEFAULTS.merge(args))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set one or more topic paths to unsubscribe from
|
38
|
+
def topics=(value)
|
39
|
+
if value.is_a?(Array)
|
40
|
+
@topics = value
|
41
|
+
else
|
42
|
+
@topics = [value]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get serialisation of packet's body
|
47
|
+
def encode_body
|
48
|
+
if @topics.empty?
|
49
|
+
raise MqttRails::PacketFormatException.new(
|
50
|
+
"No topics given when serialising packet")
|
51
|
+
end
|
52
|
+
body = encode_short(@id)
|
53
|
+
topics.each { |topic| body += encode_string(topic) }
|
54
|
+
return body
|
55
|
+
end
|
56
|
+
|
57
|
+
# Parse the body (variable header and payload) of a packet
|
58
|
+
def parse_body(buffer)
|
59
|
+
super(buffer)
|
60
|
+
@id = shift_short(buffer)
|
61
|
+
while buffer.bytesize > 0
|
62
|
+
@topics << shift_string(buffer)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Check that fixed header flags are valid for this packet type
|
67
|
+
# @private
|
68
|
+
def validate_flags
|
69
|
+
if @flags != [false, true, false, false]
|
70
|
+
raise MqttRails::PacketFormatException.new(
|
71
|
+
"Invalid flags in UNSUBSCRIBE packet header")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns a human readable string, summarising the properties of the packet
|
76
|
+
def inspect
|
77
|
+
"\#<#{self.class}: 0x%2.2X, %s>" % [
|
78
|
+
id,
|
79
|
+
topics.map { |t| "'#{t}'" }.join(', ')
|
80
|
+
]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# Copyright (c) 2016-2017 Pierre Goudet <p-goudet@ruby-dev.jp>
|
2
|
+
#
|
3
|
+
# All rights reserved. This program and the accompanying materials
|
4
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
5
|
+
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
6
|
+
#
|
7
|
+
# The Eclipse Public License is available at
|
8
|
+
# https://eclipse.org/org/documents/epl-v10.php.
|
9
|
+
# and the Eclipse Distribution License is available at
|
10
|
+
# https://eclipse.org/org/documents/edl-v10.php.
|
11
|
+
#
|
12
|
+
# Contributors:
|
13
|
+
# Pierre Goudet - initial committer
|
14
|
+
|
15
|
+
module MqttRails
|
16
|
+
class Publisher
|
17
|
+
|
18
|
+
def initialize(sender)
|
19
|
+
@waiting_puback = []
|
20
|
+
@waiting_pubrec = []
|
21
|
+
@waiting_pubrel = []
|
22
|
+
@waiting_pubcomp = []
|
23
|
+
@puback_mutex = Mutex.new
|
24
|
+
@pubrec_mutex = Mutex.new
|
25
|
+
@pubrel_mutex = Mutex.new
|
26
|
+
@pubcomp_mutex = Mutex.new
|
27
|
+
@sender = sender
|
28
|
+
end
|
29
|
+
|
30
|
+
def sender=(sender)
|
31
|
+
@sender = sender
|
32
|
+
end
|
33
|
+
|
34
|
+
def send_publish(topic, payload, retain, qos, new_id)
|
35
|
+
packet = MqttRails::Packet::Publish.new(
|
36
|
+
:id => new_id,
|
37
|
+
:topic => topic,
|
38
|
+
:payload => payload,
|
39
|
+
:retain => retain,
|
40
|
+
:qos => qos
|
41
|
+
)
|
42
|
+
begin
|
43
|
+
case qos
|
44
|
+
when 1
|
45
|
+
push_queue(@waiting_puback, @puback_mutex, MAX_QUEUE, packet, new_id)
|
46
|
+
when 2
|
47
|
+
push_queue(@waiting_pubrec, @pubrec_mutex, MAX_QUEUE, packet, new_id)
|
48
|
+
end
|
49
|
+
rescue FullQueueException
|
50
|
+
Rails.logger.warn("PUBLISH queue is full, waiting for publishing #{packet.inspect}")
|
51
|
+
sleep SELECT_TIMEOUT
|
52
|
+
retry
|
53
|
+
end
|
54
|
+
@sender.append_to_writing(packet)
|
55
|
+
MQTT_ERR_SUCCESS
|
56
|
+
end
|
57
|
+
|
58
|
+
def push_queue(waiting_queue, queue_mutex, max_packet, packet, new_id)
|
59
|
+
if waiting_queue.length >= max_packet
|
60
|
+
raise FullQueueException
|
61
|
+
end
|
62
|
+
queue_mutex.synchronize do
|
63
|
+
waiting_queue.push(:id => new_id, :packet => packet, :timestamp => Time.now)
|
64
|
+
end
|
65
|
+
MQTT_ERR_SUCCESS
|
66
|
+
end
|
67
|
+
|
68
|
+
def do_publish(qos, packet_id)
|
69
|
+
case qos
|
70
|
+
when 0
|
71
|
+
when 1
|
72
|
+
send_puback(packet_id)
|
73
|
+
when 2
|
74
|
+
send_pubrec(packet_id)
|
75
|
+
else
|
76
|
+
Rails.logger.error("The packet QoS value is invalid in publish.")
|
77
|
+
raise PacketException.new('Invalid publish QoS value')
|
78
|
+
end
|
79
|
+
MQTT_ERR_SUCCESS
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_puback(packet_id)
|
83
|
+
packet = MqttRails::Packet::Puback.new(
|
84
|
+
:id => packet_id
|
85
|
+
)
|
86
|
+
@sender.append_to_writing(packet)
|
87
|
+
MQTT_ERR_SUCCESS
|
88
|
+
end
|
89
|
+
|
90
|
+
def do_puback(packet_id)
|
91
|
+
@puback_mutex.synchronize do
|
92
|
+
@waiting_puback.delete_if { |pck| pck[:id] == packet_id }
|
93
|
+
end
|
94
|
+
MQTT_ERR_SUCCESS
|
95
|
+
end
|
96
|
+
|
97
|
+
def send_pubrec(packet_id)
|
98
|
+
packet = MqttRails::Packet::Pubrec.new(
|
99
|
+
:id => packet_id
|
100
|
+
)
|
101
|
+
push_queue(@waiting_pubrel, @pubrel_mutex, MAX_QUEUE, packet, packet_id)
|
102
|
+
@sender.append_to_writing(packet)
|
103
|
+
MQTT_ERR_SUCCESS
|
104
|
+
end
|
105
|
+
|
106
|
+
def do_pubrec(packet_id)
|
107
|
+
@pubrec_mutex.synchronize do
|
108
|
+
@waiting_pubrec.delete_if { |pck| pck[:id] == packet_id }
|
109
|
+
end
|
110
|
+
send_pubrel(packet_id)
|
111
|
+
end
|
112
|
+
|
113
|
+
def send_pubrel(packet_id)
|
114
|
+
packet = MqttRails::Packet::Pubrel.new(
|
115
|
+
:id => packet_id
|
116
|
+
)
|
117
|
+
push_queue(@waiting_pubcomp, @pubcomp_mutex, MAX_QUEUE, packet, packet_id)
|
118
|
+
@sender.append_to_writing(packet)
|
119
|
+
MQTT_ERR_SUCCESS
|
120
|
+
end
|
121
|
+
|
122
|
+
def do_pubrel(packet_id)
|
123
|
+
@pubrel_mutex.synchronize do
|
124
|
+
@waiting_pubrel.delete_if { |pck| pck[:id] == packet_id }
|
125
|
+
end
|
126
|
+
send_pubcomp(packet_id)
|
127
|
+
end
|
128
|
+
|
129
|
+
def send_pubcomp(packet_id)
|
130
|
+
packet = MqttRails::Packet::Pubcomp.new(
|
131
|
+
:id => packet_id
|
132
|
+
)
|
133
|
+
@sender.append_to_writing(packet)
|
134
|
+
MQTT_ERR_SUCCESS
|
135
|
+
end
|
136
|
+
|
137
|
+
def do_pubcomp(packet_id)
|
138
|
+
@pubcomp_mutex.synchronize do
|
139
|
+
@waiting_pubcomp.delete_if { |pck| pck[:id] == packet_id }
|
140
|
+
end
|
141
|
+
MQTT_ERR_SUCCESS
|
142
|
+
end
|
143
|
+
|
144
|
+
def config_all_message_queue
|
145
|
+
config_message_queue(@waiting_puback, @puback_mutex)
|
146
|
+
config_message_queue(@waiting_pubrec, @pubrec_mutex)
|
147
|
+
config_message_queue(@waiting_pubrel, @pubrel_mutex)
|
148
|
+
config_message_queue(@waiting_pubcomp, @pubcomp_mutex)
|
149
|
+
end
|
150
|
+
|
151
|
+
def config_message_queue(queue, mutex)
|
152
|
+
mutex.synchronize do
|
153
|
+
queue.each do |pck|
|
154
|
+
pck[:timestamp] = Time.now
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def check_waiting_publisher
|
160
|
+
@sender.check_ack_alive(@waiting_puback, @puback_mutex)
|
161
|
+
@sender.check_ack_alive(@waiting_pubrec, @pubrec_mutex)
|
162
|
+
@sender.check_ack_alive(@waiting_pubrel, @pubrel_mutex)
|
163
|
+
@sender.check_ack_alive(@waiting_pubcomp, @pubcomp_mutex)
|
164
|
+
end
|
165
|
+
|
166
|
+
def flush_publisher
|
167
|
+
@puback_mutex.synchronize do
|
168
|
+
@waiting_puback = []
|
169
|
+
end
|
170
|
+
@pubrec_mutex.synchronize do
|
171
|
+
@waiting_pubrec = []
|
172
|
+
end
|
173
|
+
@pubrel_mutex.synchronize do
|
174
|
+
@waiting_pubrel = []
|
175
|
+
end
|
176
|
+
@pubcomp_mutex.synchronize do
|
177
|
+
@waiting_pubcomp = []
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|