mqtt 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +5 -0
- data/README +20 -9
- data/Rakefile +1 -1
- data/examples/livetext.rb +7 -11
- data/examples/simple_get.rb +6 -10
- data/examples/simple_publish.rb +2 -2
- data/lib/mqtt/client.rb +64 -11
- metadata +2 -2
data/NEWS
CHANGED
data/README
CHANGED
@@ -12,24 +12,35 @@ You may get the latest stable version from Rubyforge. Source gems are also avail
|
|
12
12
|
|
13
13
|
== Synopsis
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
require 'rubygems'
|
16
|
+
require 'mqtt'
|
17
|
+
|
18
|
+
# Publish example
|
19
|
+
mqtt = MQTT::Client.new('mqtt.example.com')
|
20
|
+
mqtt.connect do |c|
|
21
|
+
c.publish('topic','message')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Subscribe example
|
25
|
+
mqtt = MQTT::Client.new('mqtt.example.com')
|
26
|
+
client.connect do
|
27
|
+
client.subscribe('test')
|
28
|
+
loop do
|
29
|
+
topic,message = client.get
|
30
|
+
puts "#{topic}: #{message}"
|
31
|
+
end
|
32
|
+
end
|
17
33
|
|
18
|
-
mqtt = MQTT::Client.new('mqtt.example.com')
|
19
|
-
mqtt.connect('clientid') do |c|
|
20
|
-
c.publish('topic','message')
|
21
|
-
end
|
22
34
|
|
23
35
|
== TODO
|
24
36
|
|
25
37
|
* Process acknowledgement packets
|
26
|
-
* Automatic uninque client identifier if none given
|
27
38
|
* Create classes for each type of packet?
|
28
39
|
* More validations of data/parameters
|
29
40
|
* Implement exception throwing
|
30
41
|
* Implement Will and Testament
|
31
|
-
* Add unit tests
|
32
42
|
* More examples
|
43
|
+
* Integration tests
|
33
44
|
* Refactor to add callbacks that are called from seperate thread
|
34
45
|
* Implement QOS Level 1
|
35
46
|
* Implement QOS Level 2
|
@@ -37,7 +48,7 @@ You may get the latest stable version from Rubyforge. Source gems are also avail
|
|
37
48
|
|
38
49
|
== Resources
|
39
50
|
|
40
|
-
http://mqtt.org
|
51
|
+
http://www.mqtt.org
|
41
52
|
|
42
53
|
== Contact
|
43
54
|
|
data/Rakefile
CHANGED
data/examples/livetext.rb
CHANGED
@@ -4,15 +4,11 @@ $:.unshift File.dirname(__FILE__)+'/../lib'
|
|
4
4
|
|
5
5
|
require 'mqtt'
|
6
6
|
|
7
|
-
|
8
7
|
client = MQTT::Client.new('hadrian.aelius.com')
|
9
|
-
client.connect
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
client.disconnect
|
8
|
+
client.connect do
|
9
|
+
client.subscribe('livetext/#')
|
10
|
+
loop do
|
11
|
+
topic,message = client.get
|
12
|
+
puts "#{topic}: #{message}"
|
13
|
+
end
|
14
|
+
end
|
data/examples/simple_get.rb
CHANGED
@@ -4,15 +4,11 @@ $:.unshift File.dirname(__FILE__)+'/../lib'
|
|
4
4
|
|
5
5
|
require 'mqtt'
|
6
6
|
|
7
|
-
|
8
7
|
client = MQTT::Client.new('mqtt.example.com')
|
9
|
-
client.connect
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
puts "#{topic}: #{message}"
|
8
|
+
client.connect do
|
9
|
+
client.subscribe('#')
|
10
|
+
loop do
|
11
|
+
topic,message = client.get
|
12
|
+
puts "#{topic}: #{message}"
|
13
|
+
end
|
16
14
|
end
|
17
|
-
|
18
|
-
client.disconnect
|
data/examples/simple_publish.rb
CHANGED
@@ -5,8 +5,8 @@ $:.unshift File.dirname(__FILE__)+'/../lib'
|
|
5
5
|
require 'mqtt'
|
6
6
|
|
7
7
|
client = MQTT::Client.new('mqtt.example.com')
|
8
|
-
client.connect
|
8
|
+
client.connect do |c|
|
9
9
|
|
10
|
-
c.publish('test',
|
10
|
+
c.publish('test', "The time is: #{Time.now}")
|
11
11
|
|
12
12
|
end
|
data/lib/mqtt/client.rb
CHANGED
@@ -4,6 +4,7 @@ require 'mqtt'
|
|
4
4
|
require 'mqtt/packet'
|
5
5
|
require 'thread'
|
6
6
|
require 'socket'
|
7
|
+
require 'timeout'
|
7
8
|
|
8
9
|
|
9
10
|
module MQTT
|
@@ -12,8 +13,10 @@ module MQTT
|
|
12
13
|
class Client
|
13
14
|
attr_reader :remote_host # Hostname of the remote broker
|
14
15
|
attr_reader :remote_port # Port number of the remote broker
|
15
|
-
attr_accessor :keep_alive # Time between pings to remote broker
|
16
|
+
attr_accessor :keep_alive # Time (in seconds) between pings to remote broker
|
16
17
|
attr_accessor :clean_start # Set the 'Clean Start' flag when connecting?
|
18
|
+
attr_accessor :client_id # Client Identifier
|
19
|
+
attr_accessor :ack_timeout # Number of seconds to wait for acknowledgement packets
|
17
20
|
|
18
21
|
# Timeout between select polls (in seconds)
|
19
22
|
SELECT_TIMEOUT = 0.5
|
@@ -22,9 +25,11 @@ module MQTT
|
|
22
25
|
def initialize(remote_host='localhost', remote_port=1883)
|
23
26
|
@remote_host = remote_host
|
24
27
|
@remote_port = remote_port
|
25
|
-
@message_id = 0
|
26
28
|
@keep_alive = 10
|
27
29
|
@clean_start = true
|
30
|
+
@client_id = random_letters(16)
|
31
|
+
@message_id = 0
|
32
|
+
@ack_timeout = 5
|
28
33
|
@last_pingreq = Time.now
|
29
34
|
@last_pingresp = Time.now
|
30
35
|
@socket = nil
|
@@ -35,16 +40,12 @@ module MQTT
|
|
35
40
|
|
36
41
|
# Connect to the MQTT broker
|
37
42
|
# If a block is given, then yield to that block and then disconnect again.
|
38
|
-
def connect(clientid)
|
43
|
+
def connect(clientid=nil)
|
44
|
+
@client_id = clientid unless clientid.nil?
|
45
|
+
|
39
46
|
if not connected?
|
40
47
|
# Create network socket
|
41
48
|
@socket = TCPSocket.new(@remote_host,@remote_port)
|
42
|
-
|
43
|
-
# Start packet reading thread
|
44
|
-
@read_thread = Thread.new(Thread.current) do |parent|
|
45
|
-
Thread.current[:parent] = parent
|
46
|
-
loop { receive_packet }
|
47
|
-
end
|
48
49
|
|
49
50
|
# Protocol name and version
|
50
51
|
packet = MQTT::Packet.new(:type => :connect)
|
@@ -61,10 +62,19 @@ module MQTT
|
|
61
62
|
packet.add_short(@keep_alive)
|
62
63
|
|
63
64
|
# Add the client identifier
|
64
|
-
packet.add_string(
|
65
|
+
packet.add_string(@client_id)
|
65
66
|
|
66
67
|
# Send packet
|
67
68
|
send_packet(packet)
|
69
|
+
|
70
|
+
# Receive response
|
71
|
+
receive_connack
|
72
|
+
|
73
|
+
# Start packet reading thread
|
74
|
+
@read_thread = Thread.new(Thread.current) do |parent|
|
75
|
+
Thread.current[:parent] = parent
|
76
|
+
loop { receive_packet }
|
77
|
+
end
|
68
78
|
end
|
69
79
|
|
70
80
|
# If a block is given, then yield and disconnect
|
@@ -82,7 +92,7 @@ module MQTT
|
|
82
92
|
packet = MQTT::Packet.new(:type => :disconnect)
|
83
93
|
send_packet(packet)
|
84
94
|
end
|
85
|
-
@read_thread.kill
|
95
|
+
@read_thread.kill if @read_thread and @read_thread.alive?
|
86
96
|
@read_thread = nil
|
87
97
|
@socket.close unless @socket.nil?
|
88
98
|
@socket = nil
|
@@ -222,6 +232,31 @@ module MQTT
|
|
222
232
|
end
|
223
233
|
end
|
224
234
|
|
235
|
+
# Read and check a connection acknowledgement packet
|
236
|
+
def receive_connack
|
237
|
+
Timeout.timeout(@ack_timeout) do
|
238
|
+
packet = MQTT::Packet.read(@socket)
|
239
|
+
if packet.type != :connack
|
240
|
+
raise MQTT::ProtocolException.new("Response wan't a connection acknowledgement: #{packet.type}")
|
241
|
+
end
|
242
|
+
|
243
|
+
# Read in the return code
|
244
|
+
byte1, return_code = packet.shift_bytes(2)
|
245
|
+
if return_code == 0x00
|
246
|
+
# Success
|
247
|
+
nil
|
248
|
+
elsif return_code == 0x01
|
249
|
+
raise MQTT::ProtocolException.new("Connection refused: unacceptable protocol version")
|
250
|
+
elsif return_code == 0x02
|
251
|
+
raise MQTT::ProtocolException.new("Connection refused: client identifier rejected")
|
252
|
+
elsif return_code == 0x03
|
253
|
+
raise MQTT::ProtocolException.new("Connection refused: broker unavailable")
|
254
|
+
else
|
255
|
+
raise MQTT::ProtocolException.new("Connection refused: #{return_code}")
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
225
260
|
# Send a packet to broker
|
226
261
|
def send_packet(data)
|
227
262
|
# Throw exception if we aren't connected
|
@@ -232,6 +267,24 @@ module MQTT
|
|
232
267
|
@socket.write(data)
|
233
268
|
end
|
234
269
|
end
|
270
|
+
|
271
|
+
# Generate a string of random letters (0-9,a-z)
|
272
|
+
def random_letters(count)
|
273
|
+
str = ''
|
274
|
+
count.times do
|
275
|
+
num = rand(36)
|
276
|
+
if (num<10)
|
277
|
+
# Number
|
278
|
+
num += 48
|
279
|
+
else
|
280
|
+
# Letter
|
281
|
+
num += 87
|
282
|
+
end
|
283
|
+
str += num.chr
|
284
|
+
end
|
285
|
+
return str
|
286
|
+
end
|
287
|
+
|
235
288
|
|
236
289
|
end
|
237
290
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mqtt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas J Humfrey
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-08 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|