paho-mqtt 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/paho-mqtt.rb +72 -1
- data/lib/paho_mqtt/client.rb +182 -708
- data/lib/paho_mqtt/connection_helper.rb +167 -0
- data/lib/paho_mqtt/handler.rb +271 -0
- data/lib/paho_mqtt/packet.rb +14 -0
- data/lib/paho_mqtt/packet/base.rb +17 -0
- data/lib/paho_mqtt/packet/connack.rb +19 -3
- data/lib/paho_mqtt/packet/connect.rb +50 -21
- data/lib/paho_mqtt/packet/disconnect.rb +18 -1
- data/lib/paho_mqtt/packet/pingreq.rb +17 -0
- data/lib/paho_mqtt/packet/pingresp.rb +17 -0
- data/lib/paho_mqtt/packet/puback.rb +17 -1
- data/lib/paho_mqtt/packet/pubcomp.rb +17 -0
- data/lib/paho_mqtt/packet/publish.rb +17 -0
- data/lib/paho_mqtt/packet/pubrec.rb +17 -0
- data/lib/paho_mqtt/packet/pubrel.rb +17 -0
- data/lib/paho_mqtt/packet/suback.rb +17 -0
- data/lib/paho_mqtt/packet/subscribe.rb +17 -0
- data/lib/paho_mqtt/packet/unsuback.rb +17 -0
- data/lib/paho_mqtt/packet/unsubscribe.rb +17 -0
- data/lib/paho_mqtt/publisher.rb +180 -0
- data/lib/paho_mqtt/sender.rb +90 -0
- data/lib/paho_mqtt/ssl_helper.rb +42 -0
- data/lib/paho_mqtt/subscriber.rb +195 -0
- data/lib/paho_mqtt/version.rb +1 -1
- metadata +8 -3
- data/LICENSE.txt +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81783208a50d429eede136e757bddf982ed2fd83
|
4
|
+
data.tar.gz: 4d1c34982623e35713e8af79da00cc6bf14d91eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02f36654df8e3f0ae3a3e47f64708ca0f770076766c7e593755d8d55dc14950e40b1eab91631f4aab7815e83653f83e2ca05dd02f8565820a3d2b089a2652cee
|
7
|
+
data.tar.gz: 50456a5604f7318622cd1809b8859db2845c7c5a0b7b4bae15d09333d957248c40cced139c7c54ac6efff9efda6985aad4c84b50de33880491ad4a369a247ff4
|
data/lib/paho-mqtt.rb
CHANGED
@@ -1,8 +1,27 @@
|
|
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
|
+
|
1
15
|
require "paho_mqtt/version"
|
2
16
|
require "paho_mqtt/client"
|
3
17
|
require "paho_mqtt/packet"
|
18
|
+
require 'logger'
|
4
19
|
|
5
20
|
module PahoMqtt
|
21
|
+
extend self
|
22
|
+
|
23
|
+
attr_accessor :logger
|
24
|
+
|
6
25
|
# Default connection setup
|
7
26
|
DEFAULT_SSL_PORT = 8883
|
8
27
|
DEFAULT_PORT = 1883
|
@@ -47,15 +66,67 @@ module PahoMqtt
|
|
47
66
|
nil
|
48
67
|
]
|
49
68
|
|
69
|
+
CONNACK_ERROR_MESSAGE = {
|
70
|
+
0x02 => "Client Identifier is correct but not allowed by remote server.",
|
71
|
+
0x03 => "Connection established but MQTT service unvailable on remote server.",
|
72
|
+
0x04 => "User name or user password is malformed.",
|
73
|
+
0x05 => "Client is not authorized to connect to the server."
|
74
|
+
}
|
75
|
+
|
76
|
+
CLIENT_ATTR_DEFAULTS = {
|
77
|
+
:host => "",
|
78
|
+
:port => nil,
|
79
|
+
:mqtt_version => '3.1.1',
|
80
|
+
:clean_session => true,
|
81
|
+
:persistent => false,
|
82
|
+
:blocking => false,
|
83
|
+
:client_id => nil,
|
84
|
+
:username => nil,
|
85
|
+
:password => nil,
|
86
|
+
:ssl => false,
|
87
|
+
:will_topic => nil,
|
88
|
+
:will_payload => nil,
|
89
|
+
:will_qos => 0,
|
90
|
+
:will_retain => false,
|
91
|
+
:keep_alive => 60,
|
92
|
+
:ack_timeout => 5,
|
93
|
+
:on_connack => nil,
|
94
|
+
:on_suback => nil,
|
95
|
+
:on_unsuback => nil,
|
96
|
+
:on_puback => nil,
|
97
|
+
:on_pubrel => nil,
|
98
|
+
:on_pubrec => nil,
|
99
|
+
:on_pubcomp => nil,
|
100
|
+
:on_message => nil,
|
101
|
+
}
|
102
|
+
|
50
103
|
Thread.abort_on_exception = true
|
51
104
|
|
105
|
+
def logger=(logger_path)
|
106
|
+
file = File.open(logger_path, "a+")
|
107
|
+
log_file = Logger.new(file)
|
108
|
+
log_file.level = Logger::DEBUG
|
109
|
+
@action_manager.logger = log_file
|
110
|
+
end
|
111
|
+
|
112
|
+
def logger
|
113
|
+
@logger
|
114
|
+
end
|
115
|
+
|
116
|
+
def logger?
|
117
|
+
@logger.is_a?(Logger)
|
118
|
+
end
|
119
|
+
|
52
120
|
class Exception < ::Exception
|
53
121
|
end
|
54
122
|
|
55
123
|
class ProtocolViolation < PahoMqtt::Exception
|
56
124
|
end
|
57
125
|
|
58
|
-
class
|
126
|
+
class WritingException < PahoMqtt::Exception
|
127
|
+
end
|
128
|
+
|
129
|
+
class ReadingException < PahoMqtt::Exception
|
59
130
|
end
|
60
131
|
|
61
132
|
class PacketException < PahoMqtt::Exception
|
data/lib/paho_mqtt/client.rb
CHANGED
@@ -1,12 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
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
|
+
require 'paho_mqtt/handler'
|
16
|
+
require 'paho_mqtt/connection_helper'
|
17
|
+
require 'paho_mqtt/sender'
|
18
|
+
require 'paho_mqtt/publisher'
|
19
|
+
require 'paho_mqtt/subscriber'
|
20
|
+
require 'paho_mqtt/ssl_helper'
|
4
21
|
|
5
22
|
module PahoMqtt
|
6
|
-
class Client
|
7
|
-
# Log file
|
8
|
-
attr_accessor :logger
|
9
|
-
|
23
|
+
class Client
|
10
24
|
# Connection related attributes:
|
11
25
|
attr_accessor :host
|
12
26
|
attr_accessor :port
|
@@ -18,7 +32,7 @@ module PahoMqtt
|
|
18
32
|
attr_accessor :username
|
19
33
|
attr_accessor :password
|
20
34
|
attr_accessor :ssl
|
21
|
-
|
35
|
+
|
22
36
|
# Last will attributes:
|
23
37
|
attr_accessor :will_topic
|
24
38
|
attr_accessor :will_payload
|
@@ -29,100 +43,45 @@ module PahoMqtt
|
|
29
43
|
attr_accessor :keep_alive
|
30
44
|
attr_accessor :ack_timeout
|
31
45
|
|
32
|
-
#Callback attributes
|
33
|
-
attr_accessor :on_message
|
34
|
-
attr_accessor :on_connack
|
35
|
-
attr_accessor :on_suback
|
36
|
-
attr_accessor :on_unsuback
|
37
|
-
attr_accessor :on_puback
|
38
|
-
attr_accessor :on_pubrel
|
39
|
-
attr_accessor :on_pubrec
|
40
|
-
attr_accessor :on_pubcomp
|
41
|
-
|
42
46
|
#Read Only attribute
|
43
|
-
attr_reader :registered_callback
|
44
|
-
attr_reader :subscribed_topics
|
45
47
|
attr_reader :connection_state
|
48
|
+
attr_reader :ssl_context
|
46
49
|
|
47
|
-
ATTR_DEFAULTS = {
|
48
|
-
:logger => nil,
|
49
|
-
:host => "",
|
50
|
-
:port => nil,
|
51
|
-
:mqtt_version => '3.1.1',
|
52
|
-
:clean_session => true,
|
53
|
-
:persistent => false,
|
54
|
-
:blocking => false,
|
55
|
-
:client_id => nil,
|
56
|
-
:username => nil,
|
57
|
-
:password => nil,
|
58
|
-
:ssl => false,
|
59
|
-
:will_topic => nil,
|
60
|
-
:will_payload => nil,
|
61
|
-
:will_qos => 0,
|
62
|
-
:will_retain => false,
|
63
|
-
:keep_alive => 60,
|
64
|
-
:ack_timeout => 5,
|
65
|
-
:on_connack => nil,
|
66
|
-
:on_suback => nil,
|
67
|
-
:on_unsuback => nil,
|
68
|
-
:on_puback => nil,
|
69
|
-
:on_pubrel => nil,
|
70
|
-
:on_pubrec => nil,
|
71
|
-
:on_pubcomp => nil,
|
72
|
-
:on_message => nil,
|
73
|
-
}
|
74
|
-
|
75
50
|
def initialize(*args)
|
51
|
+
@last_ping_resp = Time.now
|
52
|
+
@last_packet_id = 0
|
53
|
+
@ssl_context = nil
|
54
|
+
@sender = nil
|
55
|
+
@handler = Handler.new
|
56
|
+
@connection_helper = nil
|
57
|
+
@connection_state = MQTT_CS_DISCONNECT
|
58
|
+
@connection_state_mutex = Mutex.new
|
59
|
+
@mqtt_thread = nil
|
60
|
+
@reconnect_thread = nil
|
61
|
+
@id_mutex = Mutex.new
|
62
|
+
|
76
63
|
if args.last.is_a?(Hash)
|
77
64
|
attr = args.pop
|
78
65
|
else
|
79
66
|
attr = {}
|
80
67
|
end
|
81
68
|
|
82
|
-
|
69
|
+
CLIENT_ATTR_DEFAULTS.merge(attr).each_pair do |k,v|
|
83
70
|
self.send("#{k}=", v)
|
84
71
|
end
|
85
72
|
|
86
73
|
if @port.nil?
|
87
74
|
@port
|
88
75
|
if @ssl
|
89
|
-
@port =
|
76
|
+
@port = DEFAULT_SSL_PORT
|
90
77
|
else
|
91
|
-
@port =
|
78
|
+
@port = DEFAULT_PORT
|
92
79
|
end
|
93
80
|
end
|
94
81
|
|
95
82
|
if @client_id.nil? || @client_id == ""
|
96
83
|
@client_id = generate_client_id
|
97
84
|
end
|
98
|
-
|
99
|
-
@last_ping_req = Time.now
|
100
|
-
@last_ping_resp = Time.now
|
101
|
-
@last_packet_id = 0
|
102
|
-
@socket = nil
|
103
|
-
@ssl_context = nil
|
104
|
-
@writing_mutex = Mutex.new
|
105
|
-
@writing_queue = []
|
106
|
-
@connection_state = MQTT_CS_DISCONNECT
|
107
|
-
@connection_state_mutex = Mutex.new
|
108
|
-
@subscribed_mutex = Mutex.new
|
109
|
-
@subscribed_topics = []
|
110
|
-
@registered_callback = []
|
111
|
-
@waiting_suback = []
|
112
|
-
@suback_mutex = Mutex.new
|
113
|
-
@waiting_unsuback = []
|
114
|
-
@unsuback_mutex = Mutex.new
|
115
|
-
@mqtt_thread = nil
|
116
|
-
@reconnect_thread = nil
|
117
|
-
|
118
|
-
@puback_mutex = Mutex.new
|
119
|
-
@pubrec_mutex = Mutex.new
|
120
|
-
@pubrel_mutex = Mutex.new
|
121
|
-
@pubcomp_mutex = Mutex.new
|
122
|
-
@waiting_puback = []
|
123
|
-
@waiting_pubrec = []
|
124
|
-
@waiting_pubrel = []
|
125
|
-
@waiting_pubcomp = []
|
126
85
|
end
|
127
86
|
|
128
87
|
def generate_client_id(prefix='paho_ruby', lenght=16)
|
@@ -130,25 +89,11 @@ module PahoMqtt
|
|
130
89
|
@client_id = prefix << Array.new(lenght) { charset.sample }.join
|
131
90
|
end
|
132
91
|
|
133
|
-
def ssl_context
|
134
|
-
@ssl_context ||= OpenSSL::SSL::SSLContext.new
|
135
|
-
end
|
136
|
-
|
137
92
|
def config_ssl_context(cert_path, key_path, ca_path=nil)
|
138
93
|
@ssl ||= true
|
139
|
-
@ssl_context =
|
140
|
-
self.cert = cert_path
|
141
|
-
self.key = key_path
|
142
|
-
self.root_ca = ca_path
|
94
|
+
@ssl_context = SSLHelper.config_ssl_context(cert_path, key_path, ca_path)
|
143
95
|
end
|
144
96
|
|
145
|
-
def config_will(topic, payload="", retain=false, qos=0)
|
146
|
-
@will_topic = topic
|
147
|
-
@will_payload = payload
|
148
|
-
@will_retain = retain
|
149
|
-
@will_qos = qos
|
150
|
-
end
|
151
|
-
|
152
97
|
def connect(host=@host, port=@port, keep_alive=@keep_alive, persistent=@persistent, blocking=@blocking)
|
153
98
|
@persistent = persistent
|
154
99
|
@blocking = blocking
|
@@ -158,11 +103,19 @@ module PahoMqtt
|
|
158
103
|
@connection_state_mutex.synchronize {
|
159
104
|
@connection_state = MQTT_CS_NEW
|
160
105
|
}
|
161
|
-
|
162
|
-
|
106
|
+
@mqtt_thread.kill unless @mqtt_thread.nil?
|
107
|
+
init_connection
|
108
|
+
@connection_helper.send_connect(session_params)
|
109
|
+
begin
|
110
|
+
@connection_state = @connection_helper.do_connect(reconnect?)
|
111
|
+
rescue LowVersionException
|
112
|
+
downgrade_version
|
113
|
+
end
|
114
|
+
build_pubsub
|
115
|
+
daemon_mode unless @blocking || !connected?
|
163
116
|
end
|
164
117
|
|
165
|
-
def
|
118
|
+
def daemon_mode
|
166
119
|
@mqtt_thread = Thread.new do
|
167
120
|
@reconnect_thread.kill unless @reconnect_thread.nil? || !@reconnect_thread.alive?
|
168
121
|
while connected? do
|
@@ -174,20 +127,34 @@ module PahoMqtt
|
|
174
127
|
def connected?
|
175
128
|
@connection_state == MQTT_CS_CONNECTED
|
176
129
|
end
|
177
|
-
|
130
|
+
|
131
|
+
def reconnect?
|
132
|
+
Thread.current == @reconnect_thread
|
133
|
+
end
|
134
|
+
|
178
135
|
def loop_write(max_packet=MAX_WRITING)
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
136
|
+
begin
|
137
|
+
@sender.writing_loop(max_packet)
|
138
|
+
rescue WritingException
|
139
|
+
if check_persistence
|
140
|
+
reconnect
|
141
|
+
else
|
142
|
+
raise WritingException
|
184
143
|
end
|
185
|
-
|
144
|
+
end
|
186
145
|
end
|
187
146
|
|
188
147
|
def loop_read(max_packet=MAX_READ)
|
189
148
|
max_packet.times do
|
190
|
-
|
149
|
+
begin
|
150
|
+
@handler.receive_packet
|
151
|
+
rescue ReadingException
|
152
|
+
if check_persistence
|
153
|
+
reconnect
|
154
|
+
else
|
155
|
+
raise ReadingException
|
156
|
+
end
|
157
|
+
end
|
191
158
|
end
|
192
159
|
end
|
193
160
|
|
@@ -199,19 +166,17 @@ module PahoMqtt
|
|
199
166
|
end
|
200
167
|
|
201
168
|
def loop_misc
|
202
|
-
check_keep_alive
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
check_ack_alive(@waiting_suback, @suback_mutex, @waiting_suback.length)
|
208
|
-
check_ack_alive(@waiting_unsuback, @unsuback_mutex, @waiting_unsuback.length)
|
169
|
+
if @connection_helper.check_keep_alive(@persistent, @handler.last_ping_resp, @keep_alive) == MQTT_CS_DISCONNECT
|
170
|
+
reconnect if check_persistence
|
171
|
+
end
|
172
|
+
@publisher.check_waiting_publisher
|
173
|
+
@subscriber.check_waiting_subscriber
|
209
174
|
end
|
210
175
|
|
211
176
|
def reconnect(retry_time=RECONNECT_RETRY_TIME, retry_tempo=RECONNECT_RETRY_TEMPO)
|
212
177
|
@reconnect_thread = Thread.new do
|
213
178
|
retry_time.times do
|
214
|
-
|
179
|
+
PahoMqtt.logger.debug("New reconnect atempt...") if PahoMqtt.logger?
|
215
180
|
connect
|
216
181
|
if connected?
|
217
182
|
break
|
@@ -220,7 +185,7 @@ module PahoMqtt
|
|
220
185
|
end
|
221
186
|
end
|
222
187
|
unless connected?
|
223
|
-
|
188
|
+
PahoMqtt.logger.error("Reconnection atempt counter is over.(#{RECONNECT_RETRY_TIME} times)") if PahoMqtt.logger?
|
224
189
|
disconnect(false)
|
225
190
|
exit
|
226
191
|
end
|
@@ -228,38 +193,8 @@ module PahoMqtt
|
|
228
193
|
end
|
229
194
|
|
230
195
|
def disconnect(explicit=true)
|
231
|
-
@
|
232
|
-
|
233
|
-
if explicit
|
234
|
-
send_disconnect
|
235
|
-
@mqtt_thread.kill if @mqtt_thread && @mqtt_thread.alive?
|
236
|
-
@mqtt_thread.kill if @mqtt_thread.alive?
|
237
|
-
@last_packet_id = 0
|
238
|
-
|
239
|
-
@writing_mutex.synchronize {
|
240
|
-
@writing_queue = []
|
241
|
-
}
|
242
|
-
|
243
|
-
@puback_mutex.synchronize {
|
244
|
-
@waiting_puback = []
|
245
|
-
}
|
246
|
-
|
247
|
-
@pubrec_mutex.synchronize {
|
248
|
-
@waiting_pubrec = []
|
249
|
-
}
|
250
|
-
|
251
|
-
@pubrel_mutex.synchronize {
|
252
|
-
@waiting_pubrel = []
|
253
|
-
}
|
254
|
-
|
255
|
-
@pubcomp_mutex.synchronize {
|
256
|
-
@waiting_pubcomp = []
|
257
|
-
}
|
258
|
-
end
|
259
|
-
|
260
|
-
@socket.close unless @socket.nil? || @socket.closed?
|
261
|
-
@socket = nil
|
262
|
-
|
196
|
+
@last_packet_id = 0 if explicit
|
197
|
+
@connection_helper.do_disconnect(@publisher, explicit, @mqtt_thread)
|
263
198
|
@connection_state_mutex.synchronize {
|
264
199
|
@connection_state = MQTT_CS_DISCONNECT
|
265
200
|
}
|
@@ -268,656 +203,195 @@ module PahoMqtt
|
|
268
203
|
|
269
204
|
def publish(topic, payload="", retain=false, qos=0)
|
270
205
|
if topic == "" || !topic.is_a?(String)
|
271
|
-
|
272
|
-
raise
|
206
|
+
PahoMqtt.logger.error("Publish topics is invalid, not a string or empty.") if PahoMqtt.logger?
|
207
|
+
raise ArgumentError
|
273
208
|
end
|
274
|
-
|
209
|
+
id = next_packet_id
|
210
|
+
@publisher.send_publish(topic, payload, retain, qos, id)
|
211
|
+
MQTT_ERR_SUCCESS
|
275
212
|
end
|
276
213
|
|
277
214
|
def subscribe(*topics)
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
215
|
+
begin
|
216
|
+
id = next_packet_id
|
217
|
+
unless @subscriber.send_subscribe(topics, id) == PahoMqtt::MQTT_ERR_SUCCESS
|
218
|
+
reconnect if check_persistence
|
219
|
+
end
|
220
|
+
MQTT_ERR_SUCCESS
|
221
|
+
rescue ProtocolViolation
|
222
|
+
PahoMqtt.logger.error("Subscribe topics need one topic or a list of topics.") if PahoMqtt.logger?
|
282
223
|
disconnect(false)
|
283
224
|
raise ProtocolViolation
|
284
225
|
end
|
285
226
|
end
|
286
227
|
|
287
228
|
def unsubscribe(*topics)
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
229
|
+
begin
|
230
|
+
id = next_packet_id
|
231
|
+
unless @subscriber.send_unsubscribe(topics, id) == MQTT_ERR_SUCCESS
|
232
|
+
reconnect if check_persistence
|
233
|
+
end
|
234
|
+
MQTT_ERR_SUCCESS
|
235
|
+
rescue ProtocolViolation
|
236
|
+
PahoMqtt.logger.error("Unsubscribe need at least one topics.") if PahoMqtt.logger?
|
292
237
|
disconnect(false)
|
293
238
|
raise ProtocolViolation
|
294
239
|
end
|
295
240
|
end
|
296
241
|
|
297
242
|
def ping_host
|
298
|
-
send_pingreq
|
243
|
+
@sender.send_pingreq
|
299
244
|
end
|
300
245
|
|
301
246
|
def add_topic_callback(topic, callback=nil, &block)
|
302
|
-
|
303
|
-
@logger.error("The topics where the callback is trying to be registered have been found nil.") if @logger.is_a?(Logger)
|
304
|
-
raise ParameterException
|
305
|
-
end
|
306
|
-
remove_topic_callback(topic)
|
307
|
-
|
308
|
-
if block_given?
|
309
|
-
@registered_callback.push([topic, block])
|
310
|
-
elsif !(callback.nil?) && callback.class == Proc
|
311
|
-
@registered_callback.push([topic, callback])
|
312
|
-
end
|
313
|
-
MQTT_ERR_SUCCESS
|
247
|
+
@handler.register_topic_callback(topic, callback, &block)
|
314
248
|
end
|
315
249
|
|
316
250
|
def remove_topic_callback(topic)
|
317
|
-
|
318
|
-
@logger.error("The topics where the callback is trying to be unregistered have been found nil.") if @logger.is_a?(Logger)
|
319
|
-
raise ParameterException
|
320
|
-
end
|
321
|
-
@registered_callback.delete_if {|pair| pair.first == topic}
|
322
|
-
MQTT_ERR_SUCCESS
|
251
|
+
@handler.clear_topic_callback(topic)
|
323
252
|
end
|
324
253
|
|
325
254
|
def on_connack(&block)
|
326
|
-
@on_connack = block if block_given?
|
327
|
-
@on_connack
|
255
|
+
@handler.on_connack = block if block_given?
|
256
|
+
@handler.on_connack
|
328
257
|
end
|
329
258
|
|
330
259
|
def on_suback(&block)
|
331
|
-
@on_suback = block if block_given?
|
332
|
-
@on_suback
|
260
|
+
@handler.on_suback = block if block_given?
|
261
|
+
@handler.on_suback
|
333
262
|
end
|
334
263
|
|
335
264
|
def on_unsuback(&block)
|
336
|
-
@on_unsuback = block if block_given?
|
337
|
-
@on_unsuback
|
265
|
+
@handler.on_unsuback = block if block_given?
|
266
|
+
@handler.on_unsuback
|
338
267
|
end
|
339
268
|
|
340
269
|
def on_puback(&block)
|
341
|
-
@on_puback = block if block_given?
|
342
|
-
@on_puback
|
270
|
+
@handler.on_puback = block if block_given?
|
271
|
+
@handler.on_puback
|
343
272
|
end
|
344
273
|
|
345
274
|
def on_pubrec(&block)
|
346
|
-
@on_pubrec = block if block_given?
|
347
|
-
@on_pubrec
|
275
|
+
@handler.on_pubrec = block if block_given?
|
276
|
+
@handler.on_pubrec
|
348
277
|
end
|
349
278
|
|
350
279
|
def on_pubrel(&block)
|
351
|
-
@on_pubrel = block if block_given?
|
352
|
-
@on_pubrel
|
280
|
+
@handler.on_pubrel = block if block_given?
|
281
|
+
@handler.on_pubrel
|
353
282
|
end
|
354
283
|
|
355
284
|
def on_pubcomp(&block)
|
356
|
-
@on_pubcomp = block if block_given?
|
357
|
-
@on_pubcomp
|
285
|
+
@handler.on_pubcomp = block if block_given?
|
286
|
+
@handler.on_pubcomp
|
358
287
|
end
|
359
288
|
|
360
289
|
def on_message(&block)
|
361
|
-
@on_message = block if block_given?
|
362
|
-
@on_message
|
363
|
-
end
|
364
|
-
|
365
|
-
private
|
366
|
-
|
367
|
-
def next_packet_id
|
368
|
-
@last_packet_id = ( @last_packet_id || 0 ).next
|
369
|
-
end
|
370
|
-
|
371
|
-
def config_subscription
|
372
|
-
unless @subscribed_topics == []
|
373
|
-
new_id = next_packet_id
|
374
|
-
packet = PahoMqtt::Packet::Subscribe.new(
|
375
|
-
:id => new_id,
|
376
|
-
:topics => @subscribed_topics
|
377
|
-
)
|
378
|
-
@subscribed_mutex.synchronize {
|
379
|
-
@subscribed_topics = []
|
380
|
-
}
|
381
|
-
@suback_mutex.synchronize {
|
382
|
-
@waiting_suback.push({ :id => new_id, :packet => packet, :timestamp => Time.now })
|
383
|
-
}
|
384
|
-
send_packet(packet)
|
385
|
-
end
|
386
|
-
MQTT_ERR_SUCCESS
|
387
|
-
end
|
388
|
-
|
389
|
-
def config_all_message_queue
|
390
|
-
config_message_queue(@waiting_puback, @puback_mutex, MAX_PUBACK)
|
391
|
-
config_message_queue(@waiting_pubrec, @pubrec_mutex, MAX_PUBREC)
|
392
|
-
config_message_queue(@waiting_pubrel, @pubrel_mutex, MAX_PUBREL)
|
393
|
-
config_message_queue(@waiting_pubcomp, @pubcomp_mutex, MAX_PUBCOMP)
|
394
|
-
end
|
395
|
-
|
396
|
-
def config_message_queue(queue, mutex, max_packet)
|
397
|
-
mutex.synchronize {
|
398
|
-
cnt = 0
|
399
|
-
queue.each do |pck|
|
400
|
-
pck[:packet].dup ||= true
|
401
|
-
if cnt <= max_packet
|
402
|
-
append_to_writing(pck[:packet])
|
403
|
-
cnt += 1
|
404
|
-
end
|
405
|
-
end
|
406
|
-
}
|
407
|
-
end
|
408
|
-
|
409
|
-
def config_socket
|
410
|
-
unless @socket.nil?
|
411
|
-
@socket.close unless @socket.closed?
|
412
|
-
@socket = nil
|
413
|
-
end
|
414
|
-
|
415
|
-
unless @host.nil? || @port < 0
|
416
|
-
begin
|
417
|
-
tcp_socket = TCPSocket.new(@host, @port)
|
418
|
-
rescue ::Exception => exp
|
419
|
-
@logger.warn("Could not open a socket with #{@host} on port #{@port}") if @logger.is_a?(Logger)
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
if @ssl
|
424
|
-
unless @ssl_context.nil?
|
425
|
-
@socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, @ssl_context)
|
426
|
-
@socket.sync_close = true
|
427
|
-
@socket.connect
|
428
|
-
else
|
429
|
-
@logger.error("The ssl context was found as nil while the socket's opening.") if @logger.is_a?(Logger)
|
430
|
-
raise Exception
|
431
|
-
end
|
432
|
-
else
|
433
|
-
@socket = tcp_socket
|
434
|
-
end
|
290
|
+
@handler.on_message = block if block_given?
|
291
|
+
@handler.on_message
|
435
292
|
end
|
436
293
|
|
437
|
-
def
|
438
|
-
|
294
|
+
def on_connack=(callback)
|
295
|
+
@handler.on_connack = callback if callback.is_a?(Proc)
|
439
296
|
end
|
440
297
|
|
441
|
-
def
|
442
|
-
|
298
|
+
def on_suback=(callback)
|
299
|
+
@handler.on_suback = callback if callback.is_a?(Proc)
|
443
300
|
end
|
444
301
|
|
445
|
-
def
|
446
|
-
|
447
|
-
unless @ca_path.nil?
|
448
|
-
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
449
|
-
end
|
302
|
+
def on_unsuback=(callback)
|
303
|
+
@handler.on_unsuback = callback if callback.is_a?(Proc)
|
450
304
|
end
|
451
305
|
|
452
|
-
def
|
453
|
-
@
|
454
|
-
if @host.nil? || @host == ""
|
455
|
-
@logger.error("The host was found as nil while the connection setup.") if @logger.is_a?(Logger)
|
456
|
-
raise ParameterException
|
457
|
-
end
|
458
|
-
|
459
|
-
if @port.to_i <= 0
|
460
|
-
@logger.error("The port value is invalid (<= 0). Could not setup the connection.") if @logger.is_a?(Logger)
|
461
|
-
raise ParameterException
|
462
|
-
end
|
463
|
-
|
464
|
-
@socket.close unless @socket.nil? || @socket.closed?
|
465
|
-
@socket = nil
|
466
|
-
|
467
|
-
@last_ping_req = Time.now
|
468
|
-
@last_ping_resp = Time.now
|
469
|
-
|
470
|
-
@logger.debug("Atempt to connect to host: #{@host}") if @logger.is_a?(Logger)
|
471
|
-
config_socket
|
472
|
-
|
473
|
-
unless @socket.nil?
|
474
|
-
send_connect
|
475
|
-
|
476
|
-
# Waiting a Connack packet for "ack_timeout" second from the remote
|
477
|
-
connect_timeout = Time.now + @ack_timeout
|
478
|
-
while (Time.now <= connect_timeout) && (!connected?) do
|
479
|
-
receive_packet
|
480
|
-
sleep 0.0001
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
unless connected?
|
485
|
-
@logger.warn("Connection failed. Couldn't recieve a Connack packet from: #{@host}, socket is \"#{@socket}\".") if @logger.is_a?(Logger)
|
486
|
-
unless Thread.current == @reconnect_thread
|
487
|
-
raise Exception.new("Connection failed. Check log for more details.")
|
488
|
-
end
|
489
|
-
else
|
490
|
-
config_subscription if Thread.current == @reconnect_thread
|
491
|
-
end
|
306
|
+
def on_puback=(callback)
|
307
|
+
@handler.on_puback = callback if callback.is_a?(Proc)
|
492
308
|
end
|
493
309
|
|
494
|
-
def
|
495
|
-
|
496
|
-
now = Time.now
|
497
|
-
timeout_req = (@last_ping_req + (@keep_alive * 0.7).ceil)
|
498
|
-
|
499
|
-
if timeout_req <= now && @persistent
|
500
|
-
send_pingreq
|
501
|
-
@last_ping_req = now
|
502
|
-
end
|
503
|
-
|
504
|
-
timeout_resp = @last_ping_resp + (@keep_alive * 1.1).ceil
|
505
|
-
if timeout_resp <= now
|
506
|
-
@logger.debug("No activity period over timeout, disconnecting from #{@host}") if @logger.is_a?(Logger)
|
507
|
-
disconnect(false)
|
508
|
-
reconnect if @persistent
|
509
|
-
end
|
510
|
-
end
|
310
|
+
def on_pubrec=(callback)
|
311
|
+
@handler.on_pubrec = callback if callback.is_a?(Proc)
|
511
312
|
end
|
512
313
|
|
513
|
-
def
|
514
|
-
|
515
|
-
now = Time.now
|
516
|
-
cnt = 0
|
517
|
-
queue.each do |pck|
|
518
|
-
if now >= pck[:timestamp] + @ack_timeout
|
519
|
-
pck[:packet].dup ||= true unless pck[:packet].class == PahoMqtt::Packet::Subscribe || pck[:packet].class == PahoMqtt::Packet::Unsubscribe
|
520
|
-
unless cnt > max_packet
|
521
|
-
append_to_writing(pck[:packet])
|
522
|
-
pck[:timestamp] = now
|
523
|
-
cnt += 1
|
524
|
-
end
|
525
|
-
end
|
526
|
-
end
|
527
|
-
}
|
314
|
+
def on_pubrel=(callback)
|
315
|
+
@handler.on_pubrel = callback if callback.is_a?(Proc)
|
528
316
|
end
|
529
317
|
|
530
|
-
def
|
531
|
-
|
532
|
-
result = IO.select([@socket], [], [], SELECT_TIMEOUT) unless @socket.nil? || @socket.closed?
|
533
|
-
unless result.nil?
|
534
|
-
packet = PahoMqtt::Packet::Base.read(@socket)
|
535
|
-
unless packet.nil?
|
536
|
-
handle_packet packet
|
537
|
-
@last_ping_resp = Time.now
|
538
|
-
end
|
539
|
-
end
|
540
|
-
rescue ::Exception => exp
|
541
|
-
disconnect(false)
|
542
|
-
if @persistent
|
543
|
-
reconnect
|
544
|
-
else
|
545
|
-
@logger.error("The packet reading have failed.") if @logger.is_a?(Logger)
|
546
|
-
raise(exp)
|
547
|
-
end
|
548
|
-
end
|
318
|
+
def on_pubcomp=(callback)
|
319
|
+
@handler.on_pubcomp = callback if callback.is_a?(Proc)
|
549
320
|
end
|
550
321
|
|
551
|
-
def
|
552
|
-
@
|
553
|
-
if packet.class == PahoMqtt::Packet::Connack
|
554
|
-
handle_connack(packet)
|
555
|
-
elsif packet.class == PahoMqtt::Packet::Suback
|
556
|
-
handle_suback(packet)
|
557
|
-
elsif packet.class == PahoMqtt::Packet::Unsuback
|
558
|
-
handle_unsuback(packet)
|
559
|
-
elsif packet.class == PahoMqtt::Packet::Publish
|
560
|
-
handle_publish(packet)
|
561
|
-
elsif packet.class == PahoMqtt::Packet::Puback
|
562
|
-
handle_puback(packet)
|
563
|
-
elsif packet.class == PahoMqtt::Packet::Pubrec
|
564
|
-
handle_pubrec(packet)
|
565
|
-
elsif packet.class == PahoMqtt::Packet::Pubrel
|
566
|
-
handle_pubrel(packet)
|
567
|
-
elsif packet.class == PahoMqtt::Packet::Pubcomp
|
568
|
-
handle_pubcomp(packet)
|
569
|
-
elsif packet.class == PahoMqtt::Packet::Pingresp
|
570
|
-
handle_pingresp
|
571
|
-
else
|
572
|
-
@logger.error("The packets header is invalid for packet: #{packet}") if @logger.is_a?(Logger)
|
573
|
-
raise PacketException
|
574
|
-
end
|
322
|
+
def on_message=(callback)
|
323
|
+
@handler.on_message = callback if callback.is_a?(Proc)
|
575
324
|
end
|
576
325
|
|
577
|
-
def
|
578
|
-
|
579
|
-
@logger.debug("Connack receive and connection accepted.") if @logger.is_a?(Logger)
|
580
|
-
if @clean_session && !packet.session_present
|
581
|
-
@logger.debug("New session created for the client") if @logger.is_a?(Logger)
|
582
|
-
elsif !@clean_session && !packet.session_present
|
583
|
-
@logger.debug("No previous session found by server, starting a new one.") if @logger.is_a?(Logger)
|
584
|
-
elsif !@clean_session && packet.session_present
|
585
|
-
@logger.debug("Previous session restored by the server.") if @logger.is_a?(Logger)
|
586
|
-
end
|
587
|
-
@connection_state_mutex.synchronize{
|
588
|
-
@connection_state = MQTT_CS_CONNECTED
|
589
|
-
}
|
590
|
-
else
|
591
|
-
disconnect(false)
|
592
|
-
handle_connack_error(packet.return_code)
|
593
|
-
end
|
594
|
-
config_all_message_queue
|
595
|
-
@writing_mutex.synchronize {
|
596
|
-
@writing_queue.each do |m|
|
597
|
-
send_packet(m)
|
598
|
-
end
|
599
|
-
}
|
600
|
-
@on_connack.call(packet) unless @on_connack.nil?
|
326
|
+
def registered_callback
|
327
|
+
@handler.registered_callback
|
601
328
|
end
|
602
329
|
|
603
|
-
def
|
604
|
-
@
|
330
|
+
def subscribed_topics
|
331
|
+
@subscriber.subscribed_topics
|
605
332
|
end
|
606
333
|
|
607
|
-
def handle_suback(packet)
|
608
|
-
adjust_qos = []
|
609
|
-
max_qos = packet.return_codes
|
610
|
-
@suback_mutex.synchronize {
|
611
|
-
adjust_qos, @waiting_suback = @waiting_suback.partition { |pck| pck[:id] == packet.id }
|
612
|
-
}
|
613
|
-
if adjust_qos.length == 1
|
614
|
-
adjust_qos = adjust_qos.first[:packet].topics
|
615
|
-
adjust_qos.each do |t|
|
616
|
-
if [0, 1, 2].include?(max_qos[0])
|
617
|
-
t[1] = max_qos.shift
|
618
|
-
elsif max_qos[0] == 128
|
619
|
-
adjust_qos.delete(t)
|
620
|
-
else
|
621
|
-
@logger.error("The qos value is invalid in subscribe.") if @logger.is_a?(Logger)
|
622
|
-
raise PacketException
|
623
|
-
end
|
624
|
-
end
|
625
|
-
else
|
626
|
-
@logger.error("The packet id is invalid, already used.") if @logger.is_a?(Logger)
|
627
|
-
raise PacketException
|
628
|
-
end
|
629
|
-
@subscribed_mutex.synchronize {
|
630
|
-
@subscribed_topics.concat(adjust_qos)
|
631
|
-
}
|
632
|
-
@on_suback.call(adjust_qos) unless @on_suback.nil?
|
633
|
-
end
|
634
334
|
|
635
|
-
|
636
|
-
to_unsub = nil
|
637
|
-
@unsuback_mutex.synchronize {
|
638
|
-
to_unsub, @waiting_unsuback = @waiting_unsuback.partition { |pck| pck[:id] == packet.id }
|
639
|
-
}
|
640
|
-
|
641
|
-
if to_unsub.length == 1
|
642
|
-
to_unsub = to_unsub.first[:packet].topics
|
643
|
-
else
|
644
|
-
@logger.error("The packet id is invalid, already used.") if @logger.is_a?(Logger)
|
645
|
-
raise PacketException
|
646
|
-
end
|
335
|
+
private
|
647
336
|
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
end
|
337
|
+
def next_packet_id
|
338
|
+
@id_mutex.synchronize {
|
339
|
+
@last_packet_id = ( @last_packet_id || 0 ).next
|
652
340
|
}
|
653
|
-
@on_unsuback.call(to_unsub) unless @on_unsuback.nil?
|
654
341
|
end
|
655
342
|
|
656
|
-
def
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
when 2
|
662
|
-
send_pubrec(packet.id)
|
343
|
+
def downgrade_version
|
344
|
+
PahoMqtt.logger.debug("Unable to connect to the server with the version #{@mqtt_version}, trying 3.1") if PahoMqtt.logger?
|
345
|
+
if @mqtt_version != "3.1"
|
346
|
+
@mqtt_version = "3.1"
|
347
|
+
connect(@host, @port, @keep_alive)
|
663
348
|
else
|
664
|
-
|
665
|
-
raise PacketException
|
349
|
+
raise "Unsupported MQTT version"
|
666
350
|
end
|
667
|
-
|
668
|
-
@on_message.call(packet) unless @on_message.nil?
|
669
|
-
@registered_callback.assoc(packet.topic).last.call(packet) if @registered_callback.any? { |pair| pair.first == packet.topic}
|
670
|
-
end
|
671
|
-
|
672
|
-
def handle_puback(packet)
|
673
|
-
@puback_mutex.synchronize{
|
674
|
-
@waiting_puback.delete_if { |pck| pck[:id] == packet.id }
|
675
|
-
}
|
676
|
-
@on_puback.call(packet) unless @on_puback.nil?
|
677
|
-
end
|
678
|
-
|
679
|
-
def handle_pubrec(packet)
|
680
|
-
@pubrec_mutex.synchronize {
|
681
|
-
@waiting_pubrec.delete_if { |pck| pck[:id] == packet.id }
|
682
|
-
}
|
683
|
-
send_pubrel(packet.id)
|
684
|
-
@on_pubrec.call(packet) unless @on_pubrec.nil?
|
685
351
|
end
|
686
352
|
|
687
|
-
def
|
688
|
-
@
|
689
|
-
@
|
690
|
-
}
|
691
|
-
send_pubcomp(packet.id)
|
692
|
-
@on_pubrel.call(packet) unless @on_pubrel.nil?
|
693
|
-
end
|
694
|
-
|
695
|
-
def handle_pubcomp(packet)
|
696
|
-
@pubcomp_mutex.synchronize {
|
697
|
-
@waiting_pubcomp.delete_if { |pck| pck[:id] == packet.id }
|
698
|
-
}
|
699
|
-
@on_pubcomp.call(packet) unless @on_pubcomp.nil?
|
700
|
-
end
|
701
|
-
|
702
|
-
def handle_connack_error(return_code)
|
703
|
-
case return_code
|
704
|
-
when 0x01
|
705
|
-
@logger.debug("Unable to connect to the server with the version #{@mqtt_version}, trying 3.1") if @logger.is_a?(Logger)
|
706
|
-
if @mqtt_version != "3.1"
|
707
|
-
@mqtt_version = "3.1"
|
708
|
-
connect(@host, @port, @keep_alive)
|
709
|
-
end
|
710
|
-
when 0x02
|
711
|
-
@logger.warn("Client Identifier is correct but not allowed by remote server.") if @logger.is_a?(Logger)
|
712
|
-
MQTT_ERR_FAIL
|
713
|
-
when 0x03
|
714
|
-
@logger.warn("Connection established but MQTT service unvailable on remote server.") if @logger.is_a?(Logger)
|
715
|
-
MQTT_ERR_FAIL
|
716
|
-
when 0x04
|
717
|
-
@logger.warn("User name or user password is malformed.") if @logger.is_a?(Logger)
|
718
|
-
MQTT_ERR_FAIL
|
719
|
-
when 0x05
|
720
|
-
@logger.warn("Client is not authorized to connect to the server.") if @logger.is_a?(Logger)
|
721
|
-
MQTT_ERR_FAIL
|
722
|
-
end
|
723
|
-
end
|
724
|
-
|
725
|
-
def send_packet(packet)
|
726
|
-
begin
|
727
|
-
@socket.write(packet.to_s) unless @socket.nil? || @socket.closed?
|
728
|
-
@logger.info("A packet #{packet.class} have been sent.") if @logger.is_a?(Logger)
|
729
|
-
@last_ping_req = Time.now
|
730
|
-
MQTT_ERR_SUCCESS
|
731
|
-
rescue ::Exception => exp
|
732
|
-
disconnect(false)
|
733
|
-
if @persistent
|
734
|
-
reconnect
|
735
|
-
else
|
736
|
-
@logger.error("Trying to right a packet on a nil socket.") if @logger.is_a?(Logger)
|
737
|
-
raise(exp)
|
738
|
-
end
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
def append_to_writing(packet)
|
743
|
-
@writing_mutex.synchronize {
|
744
|
-
@writing_queue.push(packet)
|
745
|
-
}
|
746
|
-
MQTT_ERR_SUCCESS
|
747
|
-
end
|
748
|
-
|
749
|
-
def send_connect
|
750
|
-
packet = PahoMqtt::Packet::Connect.new(
|
751
|
-
:version => @mqtt_version,
|
752
|
-
:clean_session => @clean_session,
|
753
|
-
:keep_alive => @keep_alive,
|
754
|
-
:client_id => @client_id,
|
755
|
-
:username => @username,
|
756
|
-
:password => @password,
|
757
|
-
:will_topic => @will_topic,
|
758
|
-
:will_payload => @will_payload,
|
759
|
-
:will_qos => @will_qos,
|
760
|
-
:will_retain => @will_retain
|
761
|
-
)
|
762
|
-
send_packet(packet)
|
763
|
-
MQTT_ERR_SUCCESS
|
764
|
-
end
|
765
|
-
|
766
|
-
def send_disconnect
|
767
|
-
packet = PahoMqtt::Packet::Disconnect.new
|
768
|
-
send_packet(packet)
|
769
|
-
MQTT_ERR_SUCCESS
|
770
|
-
end
|
771
|
-
|
772
|
-
def send_pingreq
|
773
|
-
packet = PahoMqtt::Packet::Pingreq.new
|
774
|
-
@logger.debug("Checking if server is still alive.") if @logger.is_a?(Logger)
|
775
|
-
send_packet(packet)
|
776
|
-
MQTT_ERR_SUCCESS
|
777
|
-
end
|
778
|
-
|
779
|
-
def send_subscribe(topics)
|
780
|
-
unless valid_topics?(topics) == MQTT_ERR_FAIL
|
781
|
-
new_id = next_packet_id
|
782
|
-
packet = PahoMqtt::Packet::Subscribe.new(
|
783
|
-
:id => new_id,
|
784
|
-
:topics => topics
|
785
|
-
)
|
786
|
-
append_to_writing(packet)
|
787
|
-
@suback_mutex.synchronize {
|
788
|
-
@waiting_suback.push({ :id => new_id, :packet => packet, :timestamp => Time.now })
|
789
|
-
}
|
790
|
-
MQTT_ERR_SUCCESS
|
353
|
+
def build_pubsub
|
354
|
+
if @subscriber.nil?
|
355
|
+
@subscriber = Subscriber.new(@sender)
|
791
356
|
else
|
792
|
-
|
793
|
-
|
357
|
+
@subscriber.sender = @sender
|
358
|
+
@subscriber.config_subscription(next_packet_id)
|
794
359
|
end
|
795
|
-
|
796
|
-
|
797
|
-
def send_unsubscribe(topics)
|
798
|
-
unless valid_topics?(topics) == MQTT_ERR_FAIL
|
799
|
-
new_id = next_packet_id
|
800
|
-
packet = PahoMqtt::Packet::Unsubscribe.new(
|
801
|
-
:id => new_id,
|
802
|
-
:topics => topics
|
803
|
-
)
|
804
|
-
|
805
|
-
append_to_writing(packet)
|
806
|
-
@unsuback_mutex.synchronize {
|
807
|
-
@waiting_unsuback.push({:id => new_id, :packet => packet, :timestamp => Time.now})
|
808
|
-
}
|
809
|
-
MQTT_ERR_SUCCESS
|
360
|
+
if @publisher.nil?
|
361
|
+
@publisher = Publisher.new(@sender)
|
810
362
|
else
|
811
|
-
|
812
|
-
|
363
|
+
@publisher.sender = @sender
|
364
|
+
@publisher.config_all_message_queue
|
813
365
|
end
|
366
|
+
@handler.config_pubsub(@publisher, @subscriber)
|
367
|
+
@sender.flush_waiting_packet(true)
|
814
368
|
end
|
815
369
|
|
816
|
-
def
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
:payload => payload,
|
822
|
-
:retain => retain,
|
823
|
-
:qos => qos
|
824
|
-
)
|
825
|
-
|
826
|
-
append_to_writing(packet)
|
827
|
-
|
828
|
-
case qos
|
829
|
-
when 1
|
830
|
-
@puback_mutex.synchronize{
|
831
|
-
@waiting_puback.push({:id => new_id, :packet => packet, :timestamp => Time.now})
|
832
|
-
}
|
833
|
-
when 2
|
834
|
-
@pubrec_mutex.synchronize{
|
835
|
-
@waiting_pubrec.push({:id => new_id, :packet => packet, :timestamp => Time.now})
|
836
|
-
}
|
370
|
+
def init_connection
|
371
|
+
unless reconnect?
|
372
|
+
@connection_helper = ConnectionHelper.new(@host, @port, @ssl, @ssl_context, @ack_timeout)
|
373
|
+
@connection_helper.handler = @handler
|
374
|
+
@sender = @connection_helper.sender
|
837
375
|
end
|
838
|
-
|
376
|
+
@connection_helper.setup_connection
|
839
377
|
end
|
840
378
|
|
841
|
-
def
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
:id => packet_id
|
853
|
-
)
|
854
|
-
|
855
|
-
append_to_writing(packet)
|
856
|
-
|
857
|
-
@pubrel_mutex.synchronize{
|
858
|
-
@waiting_pubrel.push({:id => packet_id , :packet => packet, :timestamp => Time.now})
|
859
|
-
}
|
860
|
-
MQTT_ERR_SUCCESS
|
379
|
+
def session_params
|
380
|
+
{:version => @mqtt_version,
|
381
|
+
:clean_session => @clean_session,
|
382
|
+
:keep_alive => @keep_alive,
|
383
|
+
:client_id => @client_id,
|
384
|
+
:username => @username,
|
385
|
+
:password => @password,
|
386
|
+
:will_topic => @will_topic,
|
387
|
+
:will_payload => @will_payload,
|
388
|
+
:will_qos => @will_qos,
|
389
|
+
:will_retain => @will_retain}
|
861
390
|
end
|
862
|
-
|
863
|
-
def send_pubrel(packet_id)
|
864
|
-
packet = PahoMqtt::Packet::Pubrel.new(
|
865
|
-
:id => packet_id
|
866
|
-
)
|
867
|
-
|
868
|
-
append_to_writing(packet)
|
869
|
-
|
870
|
-
@pubcomp_mutex.synchronize{
|
871
|
-
@waiting_pubcomp.push({:id => packet_id, :packet => packet, :timestamp => Time.now})
|
872
|
-
}
|
873
|
-
MQTT_ERR_SUCCESS
|
874
|
-
end
|
875
|
-
|
876
|
-
def send_pubcomp(packet_id)
|
877
|
-
packet = PahoMqtt::Packet::Pubcomp.new(
|
878
|
-
:id => packet_id
|
879
|
-
)
|
880
391
|
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
def valid_topics?(topics)
|
886
|
-
unless topics.length == 0
|
887
|
-
topics.map do |topic|
|
888
|
-
return MQTT_ERR_FAIL if topic.first == ""
|
889
|
-
end
|
890
|
-
else
|
891
|
-
MQTT_ERR_FAIL
|
892
|
-
end
|
893
|
-
MQTT_ERR_SUCCESS
|
894
|
-
end
|
895
|
-
|
896
|
-
def match_filter(topics, filters)
|
897
|
-
if topics.is_a?(String) && filters.is_a?(String)
|
898
|
-
topic = topics.split('/')
|
899
|
-
filter = filters.split('/')
|
900
|
-
else
|
901
|
-
@logger.error("Topics and filters are not found as String while matching topics to filter.") if @logger.is_a?(Logger)
|
902
|
-
raise ParameterException
|
903
|
-
end
|
904
|
-
|
905
|
-
rc = false
|
906
|
-
index = 0
|
907
|
-
|
908
|
-
while index < [topic.length, filter.length].max do
|
909
|
-
if topic[index].nil? || filter[index].nil?
|
910
|
-
break
|
911
|
-
elsif filter[index] == '#' && index == (filter.length - 1)
|
912
|
-
rc = true
|
913
|
-
break
|
914
|
-
elsif filter[index] == topic[index] || filter[index] == '+'
|
915
|
-
index = index + 1
|
916
|
-
else
|
917
|
-
break
|
918
|
-
end
|
919
|
-
end
|
920
|
-
rc ||= (index == [topic.length, filter.length].max)
|
392
|
+
def check_persistence
|
393
|
+
disconnect(false)
|
394
|
+
@persistent
|
921
395
|
end
|
922
396
|
end
|
923
397
|
end
|