paho-mqtt 1.0.7 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af6f895ced3d30a8d24b38852cd3057dbeb25a483ace1d57d5b4ed02b0d0c863
4
- data.tar.gz: 61e56c02727c3bfac306e23615cc94bdd549e920ab49fd53cea4c06d1815ca67
3
+ metadata.gz: f39a0f32404a6bd397f11413d0ac5630ac629dca3821bde3a8213e59f2f458ac
4
+ data.tar.gz: a3a47027e5ff76e97dfc3ea32479b0149eb7be1683e901b80b6021a2478d5d4d
5
5
  SHA512:
6
- metadata.gz: ebe282a5693db9866c5397d75b4d1a39b142b61566ac09d61fa1820db33af4bf36489c55d93c9abe11cbd8ee9c79466bfbdba9ab6225e5ed55e21858b7e011b7
7
- data.tar.gz: '0854c7eec6abf060a0e3334874da9587c28c404d861abe424d7d33fa4cbda8b4cf32908396d0c0c8fa3038bff28cedceb937fa9ed19db8e1539e954c2616cfdd'
6
+ metadata.gz: 926e0d70043c9cc1b60fbaceec3c354c3d48f632aac6d92d22b7662d220f90ca4a1bc1a753cb16e9571128201de253a69388f86ca224caae0f5ac09709de97a9
7
+ data.tar.gz: cf753442885c0005ededac63b1517ebe51b10e74725429f834ab4a65cb0710fdf8e83ba9cec4272e7e91c79a470080eba26a31c09e05f838743f978d1b056b42
data/README.md CHANGED
@@ -111,15 +111,17 @@ client = PahoMqtt::Client.new({host: "iot.eclispe.org", port: 1883, ssl: false})
111
111
  The client has many accessors which help to configure the client depending on user's need. The different accessors could be splited in four roles, connection setup, last will setup, time-out setup and callback setup.
112
112
  Connection setup:
113
113
  ```
114
- * host : The endpoint where the client would try to connect (defaut "")
115
- * port : The port on the remote host where the socket would try to connect (default 1883)
116
- * mqtt_version : The version of MQTT protocol used to communication (default 3.1.1)
117
- * clean_session : If set to false, ask the message broker to try to restore the previous session (default true)
118
- * persistent : Keep the client connected even after keep alive timer run out, automatically try to reconnect on failure (default false)
119
- * client_id : The identifier of the client (default nil)
120
- * username : The username if the server require authentication (default nil)
121
- * password : The password of the user if authentication required (default nil)
122
- * ssl : Requiring the encryption for the communication (default false)
114
+ * host : The endpoint where the client would try to connect (defaut "")
115
+ * port : The port on the remote host where the socket would try to connect (default 1883)
116
+ * mqtt_version : The version of MQTT protocol used to communication (default 3.1.1)
117
+ * clean_session : If set to false, ask the message broker to try to restore the previous session (default true)
118
+ * persistent : Keep the client connected even after keep alive timer run out, automatically try to reconnect on failure (default false)
119
+ * reconnect_limit : If persistent mode is enabled, the maximum reconnect attempt (default 3)
120
+ * reconnect_delay : If persistent mode is enabled, the delay between to reconnection attempt in second (default 5)
121
+ * client_id : The identifier of the client (default nil)
122
+ * username : The username if the server require authentication (default nil)
123
+ * password : The password of the user if authentication required (default nil)
124
+ * ssl : Requiring the encryption for the communication (default false)
123
125
  ```
124
126
 
125
127
  Last Will:
@@ -186,7 +188,6 @@ client.connect("test.mosquitto.org", 8884)
186
188
  ### Persistence
187
189
  The client holds a keep_alive timer is the reference time that the connection should be held. The timer is reset every time a new valid packet is received from the message broker. The persistence flag, when set to True, enables the client to be more independent from the keep_alive timer. Just before the keep_alive run out, the client sends a ping request to tell to the message broker that the connection should be kept. The persistent mode also enables the client to automatically reconnect to the message broker after an unexpected failure.
188
190
  When the client's persistence flag is set to False, it just simply disconnects when the keep_alive timer runs out.
189
-
190
191
  ```ruby
191
192
  ### This will connect to the message broker, keep connected and automatically reconnect on failure
192
193
  client.connect('iot.eclipse.org', 1883, client.keep_alive, true, client.blocking)
@@ -194,6 +195,7 @@ client.connect('iot.eclipse.org', 1883, client.keep_alive, true, client.blocking
194
195
  ### This only connect to the message broker, disconnect after keep_alive or on failure
195
196
  client.connect('iot.eclipse.org', 1883, client.keep_alive, false, client.blocking)
196
197
  ```
198
+ The client has two attributes `@reconnect_limit` and `@reconnect_delay` which configure the reconnection process. `@reconnection_limit` is the maximum reconnection attempt that a client could try and `@reconnection_delay` is the delay that the client waits between two reconnection attempt. Setting the `@reconnect_limit` to -1 would run the reconnection process forever.
197
199
 
198
200
  ### Foreground and Daemon
199
201
  The client could be connected to the message broker using the main thread in foreground or as a daemon in a separate thread. The default mode is daemon mode, the daemon would run in the background the read/write operation as well as the control of the timers. If the client is connected using the main thread, all control operations are left to the user, using the different control loops. There are four different loop roles is detailed in the next part.
data/lib/paho-mqtt.rb CHANGED
@@ -14,38 +14,38 @@
14
14
 
15
15
  require "paho_mqtt/version"
16
16
  require "paho_mqtt/client"
17
+ require "paho_mqtt/exception"
17
18
  require "paho_mqtt/packet"
18
19
  require 'logger'
19
20
 
20
21
  module PahoMqtt
21
22
  extend self
22
-
23
23
  attr_accessor :logger
24
24
 
25
25
  # Default connection setup
26
- DEFAULT_SSL_PORT = 8883
27
- DEFAULT_PORT = 1883
28
- SELECT_TIMEOUT = 0
29
- LOOP_TEMPO = 0.005
30
- RECONNECT_RETRY_TIME = 3
31
- RECONNECT_RETRY_TEMPO = 5
26
+ DEFAULT_SSL_PORT = 8883
27
+ DEFAULT_PORT = 1883
28
+ SELECT_TIMEOUT = 0
29
+ LOOP_TEMPO = 0.005
32
30
 
33
31
  # MAX size of queue
34
- MAX_READ = 10
35
- MAX_PUBACK = 20
36
- MAX_PUBREC = 20
37
- MAX_PUBREL = 20
38
- MAX_PUBCOMP = 20
39
- MAX_WRITING = MAX_PUBACK + MAX_PUBREC + MAX_PUBREL + MAX_PUBCOMP
32
+ MAX_SUBACK = 10
33
+ MAX_UNSUBACK = 10
34
+ MAX_READ = 50
35
+ MAX_PUBACK = 100
36
+ MAX_PUBREC = 100
37
+ MAX_PUBREL = 100
38
+ MAX_PUBCOMP = 100
39
+ MAX_WRITING = MAX_PUBACK + MAX_PUBREC + MAX_PUBREL + MAX_PUBCOMP
40
40
 
41
41
  # Connection states values
42
- MQTT_CS_NEW = 0
43
- MQTT_CS_CONNECTED = 1
42
+ MQTT_CS_NEW = 0
43
+ MQTT_CS_CONNECTED = 1
44
44
  MQTT_CS_DISCONNECT = 2
45
45
 
46
46
  # Error values
47
47
  MQTT_ERR_SUCCESS = 0
48
- MQTT_ERR_FAIL = 1
48
+ MQTT_ERR_FAIL = 1
49
49
 
50
50
  PACKET_TYPES = [
51
51
  nil,
@@ -74,40 +74,40 @@ module PahoMqtt
74
74
  }
75
75
 
76
76
  CLIENT_ATTR_DEFAULTS = {
77
- :host => "",
78
- :port => nil,
79
- :mqtt_version => '3.1.1',
77
+ :host => "",
78
+ :port => nil,
79
+ :mqtt_version => '3.1.1',
80
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,
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
101
  }
102
-
102
+
103
103
  Thread.abort_on_exception = true
104
104
 
105
105
  def logger=(logger_path)
106
- file = File.open(logger_path, "a+")
107
- file.sync = true
108
- log_file = Logger.new(file)
106
+ file = File.open(logger_path, "a+")
107
+ file.sync = true
108
+ log_file = Logger.new(file)
109
109
  log_file.level = Logger::DEBUG
110
- @logger = log_file
110
+ @logger = log_file
111
111
  end
112
112
 
113
113
  def logger
@@ -162,22 +162,4 @@ module PahoMqtt
162
162
  raise ArgumentError
163
163
  end
164
164
  end
165
-
166
- class Exception < ::Exception
167
- end
168
-
169
- class ProtocolViolation < PahoMqtt::Exception
170
- end
171
-
172
- class WritingException < PahoMqtt::Exception
173
- end
174
-
175
- class ReadingException < PahoMqtt::Exception
176
- end
177
-
178
- class PacketException < PahoMqtt::Exception
179
- end
180
-
181
- class LowVersionException < PahoMqtt::Exception
182
- end
183
165
  end
@@ -27,6 +27,8 @@ module PahoMqtt
27
27
  attr_accessor :mqtt_version
28
28
  attr_accessor :clean_session
29
29
  attr_accessor :persistent
30
+ attr_accessor :reconnect_limit
31
+ attr_accessor :reconnect_delay
30
32
  attr_accessor :blocking
31
33
  attr_accessor :client_id
32
34
  attr_accessor :username
@@ -48,17 +50,19 @@ module PahoMqtt
48
50
  attr_reader :ssl_context
49
51
 
50
52
  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
53
+ @last_ping_resp = Time.now
54
+ @last_packet_id = 0
55
+ @ssl_context = nil
56
+ @sender = nil
57
+ @handler = Handler.new
58
+ @connection_helper = nil
59
+ @connection_state = MQTT_CS_DISCONNECT
58
60
  @connection_state_mutex = Mutex.new
59
- @mqtt_thread = nil
60
- @reconnect_thread = nil
61
- @id_mutex = Mutex.new
61
+ @mqtt_thread = nil
62
+ @reconnect_thread = nil
63
+ @id_mutex = Mutex.new
64
+ @reconnect_limit = 3
65
+ @reconnect_delay = 5
62
66
 
63
67
  if args.last.is_a?(Hash)
64
68
  attr = args.pop
@@ -99,14 +103,15 @@ module PahoMqtt
99
103
 
100
104
  def connect(host=@host, port=@port, keep_alive=@keep_alive, persistent=@persistent, blocking=@blocking)
101
105
  @persistent = persistent
102
- @blocking = blocking
103
- @host = host
104
- @port = port.to_i
106
+ @blocking = blocking
107
+ @host = host
108
+ @port = port.to_i
105
109
  @keep_alive = keep_alive
106
- @connection_state_mutex.synchronize {
110
+ @connection_state_mutex.synchronize do
107
111
  @connection_state = MQTT_CS_NEW
108
- }
112
+ end
109
113
  @mqtt_thread.kill unless @mqtt_thread.nil?
114
+
110
115
  init_connection
111
116
  @connection_helper.send_connect(session_params)
112
117
  begin
@@ -129,7 +134,7 @@ module PahoMqtt
129
134
  end
130
135
  rescue SystemCallError => e
131
136
  if @persistent
132
- reconnect()
137
+ reconnect
133
138
  else
134
139
  raise e
135
140
  end
@@ -188,17 +193,19 @@ module PahoMqtt
188
193
 
189
194
  def reconnect
190
195
  @reconnect_thread = Thread.new do
191
- RECONNECT_RETRY_TIME.times do
192
- PahoMqtt.logger.debug("New reconnect atempt...") if PahoMqtt.logger?
196
+ counter = 0
197
+ while (@reconnect_limit >= counter || @reconnect_limit == -1) do
198
+ counter += 1
199
+ PahoMqtt.logger.debug("New reconnect attempt...") if PahoMqtt.logger?
193
200
  connect
194
201
  if connected?
195
202
  break
196
203
  else
197
- sleep RECONNECT_RETRY_TIME
204
+ sleep @reconnect_delay
198
205
  end
199
206
  end
200
207
  unless connected?
201
- PahoMqtt.logger.error("Reconnection atempt counter is over.(#{RECONNECT_RETRY_TIME} times)") if PahoMqtt.logger?
208
+ PahoMqtt.logger.error("Reconnection attempt counter is over. (#{@reconnect_limit} times)") if PahoMqtt.logger?
202
209
  disconnect(false)
203
210
  end
204
211
  end
@@ -207,9 +214,9 @@ module PahoMqtt
207
214
  def disconnect(explicit=true)
208
215
  @last_packet_id = 0 if explicit
209
216
  @connection_helper.do_disconnect(@publisher, explicit, @mqtt_thread)
210
- @connection_state_mutex.synchronize {
217
+ @connection_state_mutex.synchronize do
211
218
  @connection_state = MQTT_CS_DISCONNECT
212
- }
219
+ end
213
220
  MQTT_ERR_SUCCESS
214
221
  end
215
222
 
@@ -220,7 +227,6 @@ module PahoMqtt
220
227
  end
221
228
  id = next_packet_id
222
229
  @publisher.send_publish(topic, payload, retain, qos, id)
223
- MQTT_ERR_SUCCESS
224
230
  end
225
231
 
226
232
  def subscribe(*topics)
@@ -245,7 +251,7 @@ module PahoMqtt
245
251
  end
246
252
  MQTT_ERR_SUCCESS
247
253
  rescue ProtocolViolation
248
- PahoMqtt.logger.error("Unsubscribe need at least one topics.") if PahoMqtt.logger?
254
+ PahoMqtt.logger.error("Unsubscribe need at least one topic.") if PahoMqtt.logger?
249
255
  disconnect(false)
250
256
  raise ProtocolViolation
251
257
  end
@@ -347,18 +353,18 @@ module PahoMqtt
347
353
  private
348
354
 
349
355
  def next_packet_id
350
- @id_mutex.synchronize {
351
- @last_packet_id = ( @last_packet_id || 0 ).next
352
- }
356
+ @id_mutex.synchronize do
357
+ @last_packet_id = (@last_packet_id || 0).next
358
+ end
353
359
  end
354
360
 
355
361
  def downgrade_version
356
- PahoMqtt.logger.debug("Unable to connect to the server with the version #{@mqtt_version}, trying 3.1") if PahoMqtt.logger?
362
+ PahoMqtt.logger.debug("Connection refused: unacceptable protocol version #{@mqtt_version}, trying 3.1") if PahoMqtt.logger?
357
363
  if @mqtt_version != "3.1"
358
364
  @mqtt_version = "3.1"
359
365
  connect(@host, @port, @keep_alive)
360
366
  else
361
- raise "Unsupported MQTT version"
367
+ raise ProtocolVersionException.new("Unsupported MQTT version")
362
368
  end
363
369
  end
364
370
 
@@ -373,32 +379,34 @@ module PahoMqtt
373
379
  @publisher = Publisher.new(@sender)
374
380
  else
375
381
  @publisher.sender = @sender
382
+ @sender.flush_waiting_packet
376
383
  @publisher.config_all_message_queue
377
384
  end
378
385
  @handler.config_pubsub(@publisher, @subscriber)
379
- @sender.flush_waiting_packet(true)
380
386
  end
381
387
 
382
388
  def init_connection
383
389
  unless reconnect?
384
- @connection_helper = ConnectionHelper.new(@host, @port, @ssl, @ssl_context, @ack_timeout)
390
+ @connection_helper = ConnectionHelper.new(@host, @port, @ssl, @ssl_context, @ack_timeout)
385
391
  @connection_helper.handler = @handler
386
- @sender = @connection_helper.sender
392
+ @sender = @connection_helper.sender
387
393
  end
388
- @connection_helper.setup_connection
394
+ @connection_helper.setup_connection
389
395
  end
390
396
 
391
397
  def session_params
392
- {:version => @mqtt_version,
393
- :clean_session => @clean_session,
394
- :keep_alive => @keep_alive,
395
- :client_id => @client_id,
396
- :username => @username,
397
- :password => @password,
398
- :will_topic => @will_topic,
399
- :will_payload => @will_payload,
400
- :will_qos => @will_qos,
401
- :will_retain => @will_retain}
398
+ {
399
+ :version => @mqtt_version,
400
+ :clean_session => @clean_session,
401
+ :keep_alive => @keep_alive,
402
+ :client_id => @client_id,
403
+ :username => @username,
404
+ :password => @password,
405
+ :will_topic => @will_topic,
406
+ :will_payload => @will_payload,
407
+ :will_qos => @will_qos,
408
+ :will_retain => @will_retain
409
+ }
402
410
  end
403
411
 
404
412
  def check_persistence
@@ -20,14 +20,14 @@ module PahoMqtt
20
20
  attr_accessor :sender
21
21
 
22
22
  def initialize(host, port, ssl, ssl_context, ack_timeout)
23
- @cs = MQTT_CS_DISCONNECT
24
- @socket = nil
25
- @host = host
26
- @port = port
27
- @ssl = ssl
23
+ @cs = MQTT_CS_DISCONNECT
24
+ @socket = nil
25
+ @host = host
26
+ @port = port
27
+ @ssl = ssl
28
28
  @ssl_context = ssl_context
29
29
  @ack_timeout = ack_timeout
30
- @sender = Sender.new(ack_timeout)
30
+ @sender = Sender.new(ack_timeout)
31
31
  end
32
32
 
33
33
  def handler=(handler)
@@ -39,12 +39,12 @@ module PahoMqtt
39
39
  @handler.socket = @socket
40
40
  # Waiting a Connack packet for "ack_timeout" second from the remote
41
41
  connect_timeout = Time.now + @ack_timeout
42
- while (Time.now <= connect_timeout) && (!is_connected?) do
42
+ while (Time.now <= connect_timeout) && !is_connected? do
43
43
  @cs = @handler.receive_packet
44
44
  sleep 0.0001
45
45
  end
46
46
  unless is_connected?
47
- PahoMqtt.logger.warn("Connection failed. Couldn't recieve a Connack packet from: #{@host}, socket is \"#{@socket}\".") if PahoMqtt.logger?
47
+ PahoMqtt.logger.warn("Connection failed. Couldn't recieve a Connack packet from: #{@host}.") if PahoMqtt.logger?
48
48
  raise Exception.new("Connection failed. Check log for more details.") unless reconnection
49
49
  end
50
50
  @cs
@@ -55,7 +55,7 @@ module PahoMqtt
55
55
  end
56
56
 
57
57
  def do_disconnect(publisher, explicit, mqtt_thread)
58
- PahoMqtt.logger.debug("Disconnecting from #{@host}") if PahoMqtt.logger?
58
+ PahoMqtt.logger.debug("Disconnecting from #{@host}.") if PahoMqtt.logger?
59
59
  if explicit
60
60
  explicit_disconnect(publisher, mqtt_thread)
61
61
  end
@@ -79,11 +79,11 @@ module PahoMqtt
79
79
  end
80
80
 
81
81
  def config_socket
82
- PahoMqtt.logger.debug("Atempt to connect to host: #{@host}") if PahoMqtt.logger?
82
+ PahoMqtt.logger.debug("Attempt to connect to host: #{@host}...") if PahoMqtt.logger?
83
83
  begin
84
84
  tcp_socket = TCPSocket.new(@host, @port)
85
85
  rescue StandardError
86
- PahoMqtt.logger.warn("Could not open a socket with #{@host} on port #{@port}") if PahoMqtt.logger?
86
+ PahoMqtt.logger.warn("Could not open a socket with #{@host} on port #{@port}.") if PahoMqtt.logger?
87
87
  end
88
88
  if @ssl
89
89
  encrypted_socket(tcp_socket, @ssl_context)
@@ -98,7 +98,7 @@ module PahoMqtt
98
98
  @socket.sync_close = true
99
99
  @socket.connect
100
100
  else
101
- PahoMqtt.logger.error("The ssl context was found as nil while the socket's opening.") if PahoMqtt.logger?
101
+ PahoMqtt.logger.error("The SSL context was found as nil while the socket's opening.") if PahoMqtt.logger?
102
102
  raise Exception
103
103
  end
104
104
  end
@@ -149,17 +149,17 @@ module PahoMqtt
149
149
  @sender.send_packet(packet)
150
150
  MQTT_ERR_SUCCESS
151
151
  end
152
-
152
+
153
153
  def check_keep_alive(persistent, last_ping_resp, keep_alive)
154
154
  now = Time.now
155
155
  timeout_req = (@sender.last_ping_req + (keep_alive * 0.7).ceil)
156
156
  if timeout_req <= now && persistent
157
- PahoMqtt.logger.debug("Checking if server is still alive.") if PahoMqtt.logger?
157
+ PahoMqtt.logger.debug("Checking if server is still alive...") if PahoMqtt.logger?
158
158
  send_pingreq
159
159
  end
160
160
  timeout_resp = last_ping_resp + (keep_alive * 1.1).ceil
161
161
  if timeout_resp <= now
162
- PahoMqtt.logger.debug("No activity period over timeout, disconnecting from #{@host}") if PahoMqtt.logger?
162
+ PahoMqtt.logger.debug("No activity period over timeout, disconnecting from #{@host}.") if PahoMqtt.logger?
163
163
  @cs = MQTT_CS_DISCONNECT
164
164
  end
165
165
  @cs