mqtt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,56 @@
1
+ ruby-mqtt is copyrighted free software by Nicholas J Humfrey <njh@aelius.com>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ version 2 (see the file GPL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/NEWS ADDED
@@ -0,0 +1,5 @@
1
+ = Ruby MQTT NEWS
2
+
3
+ == Ruby MQTT Version 0.0.1 (2009-01-??)
4
+
5
+ Initial Release.
data/README ADDED
@@ -0,0 +1,47 @@
1
+ = ruby-mqtt
2
+
3
+ Pure Ruby gem that implements the MQTT (Message Queue Telemetry Transport) protocol, a lightweight protocol for publish/subscribe messaging.
4
+
5
+ RubyForge Project Page http://rubyforge.org/projects/mqtt/
6
+
7
+ == Installing
8
+
9
+ You may get the latest stable version from Rubyforge. Source gems are also available.
10
+
11
+ $ gem install mqtt
12
+
13
+ == Synopsis
14
+
15
+ require 'rubygems'
16
+ require 'mqtt'
17
+
18
+ mqtt = MQTT::Client.new('mqtt.example.com')
19
+ mqtt.connect('clientid') do |c|
20
+ c.publish('topic','message')
21
+ end
22
+
23
+ == TODO
24
+
25
+ * Support payloads longer than 128 bytes
26
+ * Process acknowledgement packets
27
+ * Create classes for each type of packet?
28
+ * More validations of data/parameters
29
+ * Implement exception throwing
30
+ * Implement Will and Testament
31
+ * Add unit tests
32
+ * More examples
33
+ * Refactor to add callbacks that are called from seperate thread
34
+ * Implement QOS Level 1
35
+ * Implement QOS Level 2
36
+ * Add support for binding socket to specific local address
37
+
38
+ == Resources
39
+
40
+ http://mqtt.org
41
+
42
+ == Contact
43
+
44
+ Author:: Nicholas J Humfrey
45
+ Email:: njh@aelius.com
46
+ Home Page:: http://www.aelius.com/njh/
47
+ License:: Distributes under the same terms as Ruby
data/Rakefile ADDED
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+ require 'spec/rake/verify_rcov'
8
+
9
+
10
+ NAME = "mqtt"
11
+ VERS = "0.0.1"
12
+ CLEAN.include ['pkg', 'rdoc']
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = NAME
16
+ s.version = VERS
17
+ s.author = "Nicholas J Humfrey"
18
+ s.email = "njh@aelius.com"
19
+ s.homepage = "http://mqtt.rubyforge.org"
20
+ s.platform = Gem::Platform::RUBY
21
+ s.summary = "Implementation of the MQTT (Message Queue Telemetry Transport) protocol"
22
+ s.rubyforge_project = "mqtt"
23
+ s.description = "Pure Ruby gem that implements the MQTT (Message Queue Telemetry Transport) protocol, a lightweight protocol for publish/subscribe messaging."
24
+ s.files = FileList["Rakefile", "lib/*.rb", "lib/mqtt/*.rb", "examples/*"]
25
+ s.require_path = "lib"
26
+
27
+ # rdoc
28
+ s.has_rdoc = true
29
+ s.extra_rdoc_files = ["README", "NEWS", "COPYING"]
30
+
31
+ # Build Dependencies
32
+ #s.add_dependency 'rake' '~> 0.8'
33
+ #s.add_dependency 'rspec', '~> 1.1'
34
+ #s.add_dependency 'rcov', '~> 0.8'
35
+ #s.add_dependency 'mocha', '~> 0.9'
36
+ end
37
+
38
+ desc "Default: test the gem."
39
+ task :default => [:check_syntax, :rdoc]
40
+
41
+ task :build_package => [:repackage]
42
+ Rake::GemPackageTask.new(spec) do |pkg|
43
+ pkg.need_zip = false
44
+ pkg.need_tar = true
45
+ pkg.gem_spec = spec
46
+ end
47
+
48
+ desc "Run :package and install the resulting .gem"
49
+ task :install => :package do
50
+ sh %{sudo gem install --local pkg/#{NAME}-#{VERS}.gem}
51
+ end
52
+
53
+ desc "Run :clean and uninstall the .gem"
54
+ task :uninstall => :clean do
55
+ sh %{sudo gem uninstall #{NAME}}
56
+ end
57
+
58
+
59
+
60
+ ## Testing
61
+ desc "Run all the specification tests"
62
+ Spec::Rake::SpecTask.new(:spec) do |t|
63
+ t.spec_files = FileList['spec/*_spec.rb']
64
+ t.spec_opts = ["--colour"]
65
+ end
66
+
67
+ desc "Check the syntax of all ruby files"
68
+ task :check_syntax do
69
+ `find . -name "*.rb" |xargs -n1 ruby -c |grep -v "Syntax OK"`
70
+ puts "* Done"
71
+ end
72
+
73
+ namespace :spec do
74
+ desc "Generate RCov report"
75
+ Spec::Rake::SpecTask.new(:rcov) do |t|
76
+ t.spec_files = FileList['spec/*_spec.rb']
77
+ t.rcov = true
78
+ t.rcov_dir = 'coverage'
79
+ t.rcov_opts = ['--text-report', '--exclude', "spec/"]
80
+ end
81
+
82
+ desc "Generate specdoc"
83
+ Spec::Rake::SpecTask.new(:doc) do |t|
84
+ t.spec_files = FileList['spec/*_spec.rb']
85
+ t.spec_opts = ["--format", "specdoc"]
86
+ end
87
+
88
+ namespace :doc do
89
+ desc "Generate html specdoc"
90
+ Spec::Rake::SpecTask.new(:html) do |t|
91
+ t.spec_files = FileList['spec/*_spec.rb']
92
+ t.spec_opts = ["--format", "html:rspec_report.html", "--diff"]
93
+ end
94
+ end
95
+ end
96
+
97
+
98
+
99
+ ## Documentation
100
+ desc "Generate documentation for the library"
101
+ Rake::RDocTask.new("rdoc") { |rdoc|
102
+ rdoc.rdoc_dir = 'rdoc'
103
+ rdoc.title = "mqtt Documentation"
104
+ rdoc.options << '--line-numbers' << '--inline-source'
105
+ rdoc.main = "README"
106
+ rdoc.rdoc_files.include("README", "NEWS", "COPYING", "lib/*.rb", "lib/mqtt/*.rb")
107
+ }
108
+
109
+ desc "Upload rdoc to rubyforge"
110
+ task :upload_rdoc => [:rdoc] do
111
+ sh %{/usr/bin/scp -r -p rdoc/* mqtt.rubyforge.org:/var/www/gforge-projects/mqtt}
112
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__)+'/../lib'
4
+
5
+ require 'mqtt'
6
+
7
+
8
+ client = MQTT::Client.new('mqtt.example.com')
9
+ client.connect('simple_get')
10
+
11
+ client.subscribe('$SYS/#')
12
+
13
+ loop do
14
+ topic,message = client.get
15
+ puts "#{topic}: #{message}"
16
+ end
17
+
18
+ client.disconnect
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__)+'/../lib'
4
+
5
+ require 'mqtt'
6
+
7
+ client = MQTT::Client.new('mqtt.example.com')
8
+ client.connect('simple_publish_example') do |c|
9
+
10
+ c.publish('test', "The time is: #{Time.now}")
11
+
12
+ end
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mqtt'
4
+ require 'mqtt/packet'
5
+ require 'thread'
6
+ require 'socket'
7
+
8
+
9
+ module MQTT
10
+
11
+ # Client class for talking to an MQTT broker
12
+ class Client
13
+ attr_reader :remote_host # Hostname of the remote broker
14
+ attr_reader :remote_port # Port number of the remote broker
15
+ attr_accessor :keep_alive # Time between pings to remote broker
16
+ attr_accessor :clean_start # Set the 'Clean Start' flag when connecting?
17
+
18
+ # Timeout between select polls (in seconds)
19
+ SELECT_TIMEOUT = 0.5
20
+
21
+ # Create a new MQTT Client instance
22
+ def initialize(remote_host='localhost', remote_port=1883)
23
+ @remote_host = remote_host
24
+ @remote_port = remote_port
25
+ @message_id = 0
26
+ @keep_alive = 10
27
+ @clean_start = true
28
+ @last_pingreq = Time.now
29
+ @last_pingresp = Time.now
30
+ @socket = nil
31
+ @read_queue = Queue.new
32
+ @read_thread = nil
33
+ @write_semaphore = Mutex.new
34
+ end
35
+
36
+ # Connect to the MQTT broker
37
+ # If a block is given, then yield to that block and then disconnect again.
38
+ def connect(clientid)
39
+ if not connected?
40
+ # Create network socket
41
+ @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
+ # Protocol name and version
50
+ packet = MQTT::Packet.new(:type => :connect)
51
+ packet.add_string('MQIsdp')
52
+ packet.add_bytes(0x03)
53
+
54
+ # Connect flags
55
+ connect_flags = 0x00
56
+ connect_flags ||= 0x02 if @clean_start
57
+ # FIXME: implement Will and Testament
58
+ packet.add_bytes(connect_flags)
59
+
60
+ # Keep Alive timer: 10 seconds
61
+ packet.add_short(@keep_alive)
62
+
63
+ # Add the client identifier
64
+ packet.add_string(clientid)
65
+
66
+ # Send packet
67
+ send_packet(packet)
68
+ end
69
+
70
+ # If a block is given, then yield and disconnect
71
+ if block_given?
72
+ yield(self)
73
+ disconnect
74
+ end
75
+ end
76
+
77
+ # Disconnect from the MQTT broker.
78
+ # If you don't want to say goodbye to the broker, set send_msg to false.
79
+ def disconnect(send_msg=true)
80
+ if connected?
81
+ if send_msg
82
+ packet = MQTT::Packet.new(:type => :disconnect)
83
+ send_packet(packet)
84
+ end
85
+ @read_thread.kill unless @read_thread.nil?
86
+ @read_thread = nil
87
+ @socket.close unless @socket.nil?
88
+ @socket = nil
89
+ end
90
+ end
91
+
92
+ # Checks whether the client is connected to the broker.
93
+ def connected?
94
+ not @socket.nil?
95
+ end
96
+
97
+ # Send a MQTT ping message to indicate that the MQTT client is alive.
98
+ def ping
99
+ packet = MQTT::Packet.new(:type => :pingreq)
100
+ send_packet(packet)
101
+ @last_pingreq = Time.now
102
+ end
103
+
104
+ # Publish a message on a particular topic to the MQTT broker.
105
+ def publish(topic, payload, retain=false, qos=0)
106
+ packet = MQTT::Packet.new(
107
+ :type => :publish,
108
+ :qos => qos,
109
+ :retain => retain
110
+ )
111
+
112
+ # Add the topic name
113
+ packet.add_string(topic)
114
+
115
+ # Add Message ID for qos1 and qos2
116
+ unless qos == 0
117
+ packet.add_short(@message_id.next)
118
+ end
119
+
120
+ # Add the packet payload
121
+ packet.add_data(payload)
122
+
123
+ # Send the packet
124
+ send_packet(packet)
125
+ end
126
+
127
+ # Send a subscribe message for one or more topics on the MQTT broker.
128
+ # The topics parameter should be one of the following:
129
+ # * String: subscribe to one topic with QOS 0
130
+ # * Array: subscribe to multiple topics with QOS 0
131
+ # * Hash: subscribe to multiple topics where the key is the topic and the value is the QOS level
132
+ #
133
+ # For example:
134
+ # client.subscribe( 'a/b' )
135
+ # client.subscribe( 'a/b', 'c/d' )
136
+ # client.subscribe( ['a/b',0], ['c/d',1] )
137
+ # client.subscribe( 'a/b' => 0, 'c/d' => 1 )
138
+ #
139
+ def subscribe(*topics)
140
+ array = []
141
+ topics.each do |item|
142
+ if item.is_a?(Hash)
143
+ # Convert hash into an ordered array of arrays
144
+ array += item.sort
145
+ elsif item.is_a?(Array)
146
+ # Already in [topic,qos] format
147
+ array.push item
148
+ else
149
+ # Default to QOS 0
150
+ array.push [item.to_s,0]
151
+ end
152
+ end
153
+
154
+ # Create the packet
155
+ packet = MQTT::Packet.new(:type => :subscribe, :qos => 1)
156
+ packet.add_short(@message_id.next)
157
+ array.each do |item|
158
+ packet.add_string(item[0])
159
+ packet.add_bytes(item[1])
160
+ end
161
+ send_packet(packet)
162
+ end
163
+
164
+ # Return the next message recieved from the MQTT broker.
165
+ # This method blocks until a message is available.
166
+ #
167
+ # The method returns the topic and message as an array:
168
+ # topic,message = client.get
169
+ #
170
+ def get
171
+ # Wait for a packet to be available
172
+ packet = @read_queue.pop
173
+
174
+ # Parse the variable header
175
+ topic = packet.shift_string
176
+ msg_id = packet.shift_short unless (packet.qos == 0)
177
+ return topic,packet.body
178
+ end
179
+
180
+ # Send a unsubscribe message for one or more topics on the MQTT broker
181
+ def unsubscribe(*topics)
182
+ packet = MQTT::Packet.new(:type => :unsubscribe, :qos => 1)
183
+ topics.each { |topic| packet.add_string(topic) }
184
+ send_packet(packet)
185
+ end
186
+
187
+ private
188
+
189
+ # Try to read a packet from the broker
190
+ # Also sends keep-alive ping packets.
191
+ def receive_packet
192
+ begin
193
+ # Poll socket - is there data waiting?
194
+ result = IO.select([@socket], nil, nil, SELECT_TIMEOUT)
195
+ unless result.nil?
196
+ # Yes - read in the packet
197
+ packet = MQTT::Packet.read(@socket)
198
+ if packet.type == :publish
199
+ # Add to queue
200
+ @read_queue.push(packet)
201
+ else
202
+ # Ignore all other packets
203
+ nil
204
+ # FIXME: implement responses for QOS 1 and 2
205
+ end
206
+ end
207
+
208
+ # Time to send a keep-alive ping request?
209
+ if Time.now > @last_pingreq + @keep_alive
210
+ ping
211
+ end
212
+
213
+ # FIXME: check we received a ping response recently?
214
+
215
+ # Pass exceptions up to parent thread
216
+ rescue Exception => exp
217
+ unless @socket.nil?
218
+ @socket.close
219
+ @socket = nil
220
+ end
221
+ Thread.current[:parent].raise(exp)
222
+ end
223
+ end
224
+
225
+ # Send a packet to broker
226
+ def send_packet(data)
227
+ # Throw exception if we aren't connected
228
+ raise MQTT::NotConnectedException if not connected?
229
+
230
+ # Only allow one thread to write to socket at a time
231
+ @write_semaphore.synchronize do
232
+ @socket.write(data)
233
+ end
234
+ end
235
+
236
+ end
237
+
238
+ end
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mqtt'
4
+
5
+ module MQTT
6
+
7
+ # Class representing a MQTT Packet
8
+ # Performs binary encoding and decoding of headers
9
+ class Packet #:nodoc: all
10
+ attr_reader :type # The packet type
11
+ attr_reader :dup # Duplicate delivery flag
12
+ attr_reader :retain # Retain flag
13
+ attr_reader :qos # Quality of Service level
14
+ attr_reader :body # Packet's body (everything after fixed header)
15
+
16
+ # Read in a packet from a socket
17
+ def self.read(sock)
18
+ header = sock.read(2)
19
+ raise MQTT::ProtocolException if header.nil?
20
+ byte1,byte2 = header.unpack('C*')
21
+
22
+ # FIXME: support decoding of multi-byte length header
23
+
24
+ packet = MQTT::Packet.new(
25
+ :type => ((byte1 & 0xF0) >> 4),
26
+ :dup => ((byte1 & 0x08) >> 3),
27
+ :qos => ((byte1 & 0x06) >> 1),
28
+ :retain => ((byte1 & 0x01) >> 0)
29
+ )
30
+ packet.body = sock.read(byte2)
31
+
32
+ return packet
33
+ end
34
+
35
+ # Create a new empty packet
36
+ def initialize(args={})
37
+ self.type = args[:type] || :invalid
38
+ self.dup = args[:dup] || false
39
+ self.qos = args[:qos] || 0
40
+ self.retain = args[:retain] || false
41
+ self.body = args[:body] || ''
42
+ end
43
+
44
+ def type=(arg)
45
+ if arg.kind_of?(Integer)
46
+ # Convert type identifier to symbol
47
+ @type = MQTT::PACKET_TYPES[arg]
48
+ else
49
+ @type = arg.to_sym
50
+ # FIXME: raise exception if packet type is invalid?
51
+ end
52
+ end
53
+
54
+ # Return the identifer for this packet type
55
+ def type_id
56
+ raise "No packet type set for this packet" if @type.nil?
57
+ index = MQTT::PACKET_TYPES.index(@type)
58
+ raise "Invalid packet type: #{@type}" if index.nil?
59
+ return index
60
+ end
61
+
62
+ def dup=(arg)
63
+ if arg.kind_of?(Integer)
64
+ @dup = (arg != 0 ? true : false)
65
+ else
66
+ @dup = arg
67
+ end
68
+ end
69
+
70
+ def retain=(arg)
71
+ if arg.kind_of?(Integer)
72
+ @retain = (arg != 0 ? true : false)
73
+ else
74
+ @retain = arg
75
+ end
76
+ end
77
+
78
+ def qos=(arg)
79
+ @qos = arg.to_i
80
+ end
81
+
82
+ def body=(arg)
83
+ @body = arg.to_s
84
+ end
85
+
86
+
87
+
88
+
89
+
90
+ # Add an array of bytes to the end of the packet's body
91
+ def add_bytes(*bytes)
92
+ @body += bytes.pack('C*')
93
+ end
94
+
95
+ # Add a 16-bit unsigned integer to the end of the packet's body
96
+ def add_short(val)
97
+ @body += [val.to_i].pack('n')
98
+ end
99
+
100
+ # Add some raw data to the end of the packet's body
101
+ def add_data(data)
102
+ data = data.to_s unless data.is_a?(String)
103
+ @body += data
104
+ end
105
+
106
+ # Add a string to the end of the packet's body
107
+ # (preceded by the length of the string)
108
+ def add_string(str)
109
+ str = str.to_s unless str.is_a?(String)
110
+ add_short(str.size)
111
+ add_data(str)
112
+ end
113
+
114
+
115
+ # Remove a 16-bit unsigned integer from the front on the body
116
+ def shift_short
117
+ bytes = @body.slice!(0..1)
118
+ bytes.unpack('n').first
119
+ end
120
+
121
+ # Remove n bytes from the front on the body
122
+ def shift_bytes(bytes)
123
+ @body.slice!(0...bytes).unpack('C*')
124
+ end
125
+
126
+ # Remove n bytes from the front on the body
127
+ def shift_data(bytes)
128
+ @body.slice!(0...bytes)
129
+ end
130
+
131
+ # Remove string from the front on the body
132
+ def shift_string
133
+ len = shift_short
134
+ shift_data(len)
135
+ end
136
+
137
+
138
+ # Serialise the packet
139
+ def to_s
140
+ # Encode the 2-byte fixed header
141
+ header = [
142
+ ((type_id.to_i & 0x0F) << 4) |
143
+ ((dup ? 0x1 : 0x0) << 3) |
144
+ ((qos.to_i & 0x03) << 1) |
145
+ (retain ? 0x1 : 0x0),
146
+ (@body.length & 0x7F)
147
+ ]
148
+ # FIXME: support multi-byte length header
149
+ header.pack('C*') + @body
150
+ end
151
+
152
+ def inspect
153
+ format("#<MQTT::Packet:0x%01x ", object_id)+
154
+ "type=#{@type}, dup=#{@dup}, retain=#{@retain}, "+
155
+ "qos=#{@qos}, body.size=#{@body.size}>"
156
+ end
157
+
158
+ end
159
+
160
+ end
data/lib/mqtt.rb ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mqtt/client'
4
+
5
+ # Pure-ruby implementation of the MQTT protocol
6
+ module MQTT
7
+
8
+ PACKET_TYPES = [
9
+ nil,
10
+ :connect, # Client request to connect to Broker
11
+ :connack, # Connect Acknowledgment
12
+ :publish, # Publish message
13
+ :puback, # Publish Acknowledgment
14
+ :pubrec, # Publish Received (assured delivery part 1)
15
+ :pubrel, # Publish Release (assured delivery part 2)
16
+ :pubcomp, # Publish Complete (assured delivery part 3)
17
+ :subscribe, # Client Subscribe request
18
+ :suback, # Subscribe Acknowledgment
19
+ :unsubscribe, # Client Unsubscribe request
20
+ :unsuback, # Unsubscribe Acknowledgment
21
+ :pingreq, # PING Request
22
+ :pingresp, # PING Response
23
+ :disconnect, # Client is Disconnecting
24
+ nil
25
+ ]
26
+
27
+ class Exception < Exception
28
+
29
+ end
30
+
31
+ class ProtocolException < MQTT::Exception
32
+
33
+ end
34
+
35
+ class NotConnectedException < MQTT::Exception
36
+
37
+ end
38
+
39
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mqtt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas J Humfrey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-01 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Pure Ruby gem that implements the MQTT (Message Queue Telemetry Transport) protocol, a lightweight protocol for publish/subscribe messaging.
17
+ email: njh@aelius.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - NEWS
25
+ - COPYING
26
+ files:
27
+ - Rakefile
28
+ - lib/mqtt.rb
29
+ - lib/mqtt/client.rb
30
+ - lib/mqtt/packet.rb
31
+ - examples/simple_get.rb
32
+ - examples/simple_publish.rb
33
+ - README
34
+ - NEWS
35
+ - COPYING
36
+ has_rdoc: true
37
+ homepage: http://mqtt.rubyforge.org
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project: mqtt
58
+ rubygems_version: 1.3.1
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: Implementation of the MQTT (Message Queue Telemetry Transport) protocol
62
+ test_files: []
63
+