nutella_lib 0.2.2 → 0.3.0

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
  SHA1:
3
- metadata.gz: 607bc8f43c55bdddc4a0496c48cde8f7ff26aa50
4
- data.tar.gz: 075da6ca64d50df6ac3b49e48eb818618483c96a
3
+ metadata.gz: 452fc30366c7f02a64fb608208189e791be03b59
4
+ data.tar.gz: 9707d639e096aa37f9d34fefba639b198309ddb6
5
5
  SHA512:
6
- metadata.gz: fd598f8a12fa7d9ed398a5458d7c9ea642506a3376b968363ca9abcbcfedb18ad22d8f58353b4eab3174dc1bfe11db10c2d7454dbc013b052d464640450384d7
7
- data.tar.gz: 83fa75629fe26f0358b6d369d33d3566589cacdf5ffe64be982450ebc537f97329ebdb9acd3cd9b6db5c13cf92828c9a6b551337d26703357d475740ec1c53f8
6
+ metadata.gz: 23a92b1be185d721717535403503bba4eb316ac7a771d2b927329b1748e4a60e81334423bda05aa0d1872188b36e3c2ea88bdd21752b7326963ec21b0fe4fe8f
7
+ data.tar.gz: 98788b6730515f32623ce4ca3fb785221d1d7454117c4fe4eb577b950c667a2d07b7d6cb4ec89fb5ab8ab71e5401207fd43cf52f9ce5230cb252d4def4663c30
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'simple_ruby_mqtt_client', '~> 0.3.1', '>= 0.3.1'
3
+ gem 'mqtt', '~> 0.3', '>= 0.3'
4
4
 
5
5
  group :development do
6
6
  gem 'shoulda', '~> 3', '>= 3'
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
- # nutella_lib.rb [![Build Status](https://travis-ci.org/nutella-framework/nutella_lib.rb.svg)](https://travis-ci.org/nutella-framework/nutella_lib.rb)
2
- nutella protocol library for ruby
1
+ [![Gem Version](https://badge.fury.io/rb/nutella_lib.svg)](http://badge.fury.io/rb/nutella_lib)
2
+ [![Build Status](https://travis-ci.org/nutella-framework/nutella_lib.rb.svg)](https://travis-ci.org/nutella-framework/nutella_lib.rb)
3
+
4
+ # nutella_lib.rb
5
+ nutella library for Ruby
3
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
data/lib/nutella_lib.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require 'nutella_lib/core'
2
2
  require 'nutella_lib/net'
3
3
  require 'nutella_lib/persist'
4
+ require 'simple_mqtt_client/simple_mqtt_client'
4
5
 
5
6
  # Gems used across the whole library
6
- require 'simple_ruby_mqtt_client'
7
7
  require 'json'
8
8
  require 'set'
9
9
 
@@ -1,37 +1,57 @@
1
1
  # This module is the wrapper around the whole nutella library.
2
2
  module Nutella
3
3
 
4
+
4
5
  # Initializes the nutella library
5
- def Nutella.init(args)
6
- if args.length < 2
7
- STDERR.puts "Couldn't read run_id and broker address from the command line, impossible to initialize library!"
8
- return
9
- end
10
- @run_id = args[0]
11
- @actor_name = Nutella.config_actor_name
12
- @mqtt = SimpleMQTTClient.new(args[1])
6
+ # @param [String] run_id
7
+ # @param [String] broker_hostname
8
+ # @param [String] component_id
9
+ def self.init(run_id, broker_hostname, component_id)
10
+ @run_id = run_id
11
+ @component_id = component_id
12
+ @resource_id = nil
13
+ @mqtt = SimpleMQTTClient.new broker_hostname
13
14
  end
14
15
 
15
16
 
16
17
  # Accessors for module instance variables
17
- def Nutella.run_id; @run_id end
18
- def Nutella.actor_name; @actor_name end
19
- def Nutella.mqtt; @mqtt end
18
+ def self.run_id; @run_id end
19
+ def self.component_id; @component_id end
20
+ def self.resource_id; @resource_id end
21
+ def self.mqtt; @mqtt end
22
+
20
23
 
21
24
 
22
25
  # Nutella library modules loading
23
- def Nutella.net; Nutella::Net end
24
- def Nutella.persist; Nutella::Persist end
26
+ def self.net; Nutella::Net end
27
+ def self.persist; Nutella::Persist end
28
+
25
29
 
30
+ # Utility functions
31
+
32
+
33
+ # Parse command line arguments
34
+ def self.parse_args(args)
35
+ if args.length < 2
36
+ STDERR.puts "Couldn't read run_id and broker address from the command line, impossible to initialize library!"
37
+ return
38
+ end
39
+ return args[0], args[1]
40
+ end
26
41
 
27
- private
28
42
 
29
43
  # Extracts the actor name based on the the folder where we are executing
30
- def Nutella.config_actor_name
44
+ def self.extract_component_id
31
45
  path = Dir.pwd
32
46
  path[path.rindex('/')+1..path.length-1]
33
47
  end
34
48
 
49
+
50
+ # Sets the resource id
51
+ def self.set_resource_id( resource_id )
52
+ @resource_id = resource_id
53
+ end
54
+
35
55
  end
36
56
 
37
57
 
@@ -1,62 +1,79 @@
1
1
  module Nutella
2
2
 
3
- # This class implements the pub/sub nutella protocol
3
+ # This class implements the pub/sub and request/response nutella protocol
4
4
  # @author Alessandro Gnoli <tebemis@gmail.com>
5
5
  module Net
6
6
 
7
- # Subscribe to a channel
8
- # The callback takes one parameter and that is the message that is received.
9
- # Messages that are not JSON are discarded.
7
+ # Store the subscriptions and the relative callbacks
8
+ @subscriptions = []
9
+ @callbacks = []
10
+
11
+ # Subscribe to a channel or to a set of channels if using wildcards
12
+ #
13
+ # @param [String] channel the channel we are subscribing to, can be wildcard
14
+ # @param [Proc] callback a lambda expression that takes as parameters:
15
+ # - the received message. Messages that are not JSON are discarded.
16
+ # - the channel the message was received on (in case of wildcard subscription)
17
+ # - the sender's component_id
18
+ # - the sender's resource_id (if set by the sender)
10
19
  def Net.subscribe (channel, callback)
20
+ # Maintain unique subscriptions
21
+ raise 'You can`t subscribe twice to the same channel`' if @subscriptions.include? channel
11
22
  # Pad the channel
12
- new_channel = Nutella.run_id + '/' + channel
13
- # Subscribe
23
+ new_channel = "#{Nutella.run_id}/#{channel}"
14
24
  # Depending on what type of channel we are subscribing to (wildcard or simple)
15
25
  # register a different kind of callback
16
26
  if Nutella.mqtt.is_channel_wildcard?(channel)
17
- Nutella.mqtt.subscribe(
18
- new_channel,
19
- lambda do |message, channel|
20
- # Make sure the message is JSON, if not drop the message
21
- begin
22
- message_hash = JSON.parse(message)
23
- callback.call(message_hash, channel)
24
- rescue
25
- return
26
- end
27
- end
28
- )
27
+ mqtt_cb = lambda do |mqtt_message, mqtt_channel|
28
+ # Make sure the message is JSON, if not drop the message
29
+ begin
30
+ mqtt_channel.slice!("#{Nutella.run_id}/")
31
+ type, payload, component_id, resource_id = extract_fields_from_message mqtt_message
32
+ callback.call(payload, mqtt_channel, component_id, resource_id) if type=='publish'
33
+ rescue
34
+ return
35
+ end
36
+ end
29
37
  else
30
- Nutella.mqtt.subscribe(
31
- new_channel,
32
- lambda do |message|
33
- # Make sure the message is JSON, if not drop the message
34
- begin
35
- message_hash = JSON.parse(message)
36
- callback.call(message_hash)
37
- rescue
38
- return
39
- end
40
- end
41
- )
38
+ mqtt_cb = lambda do |message|
39
+ # Make sure the message is JSON, if not drop the message
40
+ begin
41
+ type, payload, component_id, resource_id = extract_fields_from_message message
42
+ callback.call(payload, component_id, resource_id) if type=='publish'
43
+ rescue
44
+ return
45
+ end
46
+ end
42
47
  end
48
+ # Subscribe
49
+ @subscriptions.push channel
50
+ @callbacks.push mqtt_cb
51
+ Nutella.mqtt.subscribe(new_channel, mqtt_cb)
43
52
  end
44
53
 
54
+
45
55
  # Unsubscribe from a channel
46
56
  def Net.unsubscribe(channel)
57
+ idx = @subscriptions.index channel
58
+ # If we are not subscribed to this channel, return (no error is given)
59
+ return if idx.nil?
47
60
  # Pad the channel
61
+ mqtt_cb = @callbacks[idx]
48
62
  new_channel = Nutella.run_id + '/' + channel
49
63
  # Unsubscribe
50
- Nutella.mqtt.unsubscribe(new_channel)
64
+ @subscriptions.delete_at idx
65
+ @callbacks.delete_at idx
66
+ Nutella.mqtt.unsubscribe( new_channel, mqtt_cb )
51
67
  end
52
68
 
69
+
53
70
  # Publishes a message to a channel
54
71
  # Message can be:
55
72
  # empty (equivalent of a GET)
56
73
  # string (the string will be wrapped into a JSON string automatically. Format: {"payload":"<message>"})
57
74
  # hash (the hash will be converted into a JSON string automatically)
58
75
  # json string (the JSON string will be sent as is)
59
- def Net.publish(channel, message)
76
+ def Net.publish(channel, message=nil)
60
77
  # Pad the channel
61
78
  new_channel = Nutella.run_id + '/' + channel
62
79
  # Publish
@@ -68,105 +85,92 @@ module Nutella
68
85
  end
69
86
  end
70
87
 
88
+
71
89
  # Performs a synchronous request
72
90
  # Message can be:
73
91
  # empty (equivalent of a GET)
74
92
  # string (the string will be wrapped into a JSON string automatically. Format: {"payload":"<message>"})
75
93
  # hash (the hash will be converted into a JSON string automatically)
76
94
  # json string (the JSON string will be sent as is)
77
- def Net.sync_req (channel, message="")
78
- # Generate message unique id
79
- id = message.hash
80
- # Attach id
81
- begin
82
- payload = Net.attach_message_id(message, id)
83
- rescue
84
- STDERR.puts $!
85
- return
86
- end
87
- # Initialize response and response counter
88
- ready_to_go = 2
95
+ def Net.sync_req (channel, message=nil)
96
+ # Pad channel
97
+ new_channel = "#{Nutella.run_id}/#{channel}"
98
+ # Prepare message
99
+ m, id = prepare_message_for_request message
100
+ # Initialize response
89
101
  response = nil
90
- # Subscribe to same channel to collect response
91
- Net.subscribe(channel, lambda do |res|
92
- if (res["id"]==id)
93
- ready_to_go -= 1
94
- if ready_to_go==0
95
- Net.unsubscribe(channel)
96
- response = res
97
- end
102
+ # Prepare callback
103
+ mqtt_cb = lambda do |mqtt_message|
104
+ m_id = extract_id_from_message mqtt_message
105
+ type, payload = extract_fields_from_response mqtt_message
106
+ if m_id==id && type=='response'
107
+ response = payload
108
+ Nutella.mqtt.unsubscribe( new_channel, mqtt_cb )
98
109
  end
99
- end)
100
- # Send message the message
101
- Net.publish(channel, payload)
110
+ end
111
+ # Subscribe
112
+ Nutella.mqtt.subscribe( new_channel, mqtt_cb )
113
+ # Publish message
114
+ Nutella.mqtt.publish( new_channel, m )
102
115
  # Wait for the response to come back
103
- sleep(0.5) until ready_to_go==0
116
+ sleep(0.1) while response.nil?
104
117
  response
105
118
  end
106
119
 
107
- # Performs an asynchronosus request
120
+
121
+ # Performs an asynchronous request
108
122
  # Message can be:
109
123
  # empty (equivalent of a GET)
110
124
  # string (the string will be wrapped into a JSON string automatically. Format: {"payload":"<message>"})
111
125
  # hash (the hash will be converted into a JSON string automatically)
112
126
  # json string (the JSON string will be sent as is)
113
- def Net.async_req (channel, message="", callback)
114
- # Generate message unique id
115
- id = message.hash
116
- # Attach id
117
- begin
118
- payload = Net.attach_message_id(message, id)
119
- rescue
120
- STDERR.puts $!
121
- return
122
- end
123
- # Initialize flag that prevents handling of our own messages
124
- ready_to_go = false
125
- # Register callback to handle data the request response whenever it comes
126
- Net.subscribe(channel, lambda do |res|
127
- # Check that the message we receive is not the one we are sending ourselves.
128
- if res["id"]==id
129
- if ready_to_go
130
- Net.unsubscribe(channel)
131
- callback.call(res)
132
- else
133
- ready_to_go = true
134
- end
127
+ def Net.async_req (channel, message=nil, callback)
128
+ # Pad channel
129
+ new_channel = "#{Nutella.run_id}/#{channel}"
130
+ # Prepare message
131
+ m, id = prepare_message_for_request message
132
+ # Initialize response
133
+ # Prepare callback
134
+ mqtt_cb = lambda do |message|
135
+ m_id = extract_id_from_message message
136
+ type, payload = extract_fields_from_response message
137
+ if m_id==id && type=='response'
138
+ callback.call(payload)
139
+ Nutella.mqtt.unsubscribe( new_channel, mqtt_cb )
135
140
  end
136
- end)
137
- # Send message
138
- Net.publish(channel, payload)
141
+ end
142
+ # Subscribe
143
+ Nutella.mqtt.subscribe( new_channel, mqtt_cb )
144
+ # Publish message
145
+ Nutella.mqtt.publish( new_channel, m )
139
146
  end
140
147
 
141
- # Handles requests on a certain channel
142
- def Net.handle_requests (channel, &handler)
143
- Net.subscribe(channel, lambda do |req|
144
- # Ignore anything that doesn't have an id (i.e. not requests)
145
- id = req["id"]
146
- if id.nil?
147
- return
148
- end
149
- # Ignore recently processed requests
150
- if @last_requests.nil?
151
- @last_requests = Set.new
152
- end
153
- if @last_requests.include?(id)
154
- @last_requests.delete(id)
155
- return
156
- end
157
- @last_requests.add(id)
158
- req.delete("id")
159
- res = handler.call(req)
148
+
149
+
150
+ # Handle requests
151
+ def Net.handle_requests( channel, callback)
152
+ # Pad the channel
153
+ new_channel = "#{Nutella.run_id}/#{channel}"
154
+ mqtt_cb = lambda do |request|
160
155
  begin
161
- res_and_id = attach_message_id(res, id)
162
- Net.publish(channel, res_and_id)
156
+ # Extract nutella fields
157
+ type, payload, component_id, resource_id = extract_fields_from_message request
158
+ id = extract_id_from_message request
159
+ # Only handle requests that have proper id set
160
+ return if type!='request' || id.nil?
161
+ m = Net.prepare_message_for_response( callback.call( payload, component_id, resource_id ), id )
162
+ Nutella.mqtt.publish( new_channel, m )
163
+ # Assemble the response and check that it's proper JSON
163
164
  rescue
164
- STDERR.puts 'When handling a request you need to return JSON'
165
+ return
165
166
  end
166
- end)
167
+ end
168
+ # Subscribe to the channel
169
+ Nutella.mqtt.subscribe(new_channel, mqtt_cb)
167
170
  end
168
171
 
169
172
 
173
+ # Listens for incoming messages
170
174
  def Net.listen
171
175
  begin
172
176
  sleep
@@ -178,37 +182,47 @@ module Nutella
178
182
 
179
183
  private
180
184
 
181
- def Net.attach_message_id (message, id)
182
- if message.is_a?(Hash)
183
- message[:id] = id
184
- payload = message.to_json
185
- elsif message.is_json?
186
- p = JSON.parse(message)
187
- p[:id] = id
188
- payload = p.to_json
189
- elsif message.is_a?(String)
190
- payload = { :payload => message, :id => id }.to_json
191
- else
192
- raise 'Your request is not JSON!'
185
+ def Net.extract_fields_from_message(message)
186
+ mh = JSON.parse(message)
187
+ from = mh['from'].split('/')
188
+ r_id = from.length==1 ? nil : from[1]
189
+ return mh['type'], mh['payload'], from[0], r_id
190
+ end
191
+
192
+ def Net.extract_id_from_message( message )
193
+ mh = JSON.parse(message)
194
+ mh['id']
195
+ end
196
+
197
+ def Net.extract_fields_from_response( message )
198
+ mh = JSON.parse(message)
199
+ return mh['type'], mh['payload']
200
+ end
201
+
202
+ def Net.prepare_message_for_publish( message )
203
+ from = Nutella.resource_id.nil? ? Nutella.component_id : "#{Nutella.component_id}/#{Nutella.resource_id}"
204
+ if message.nil?
205
+ return {type: 'publish', from: from}.to_json
193
206
  end
194
- payload
207
+ {type: 'publish', from: from, payload: message}.to_json
195
208
  end
196
209
 
197
- def Net.prepare_message_for_publish (message)
198
- if message.is_a?(Hash)
199
- message[:from] = Nutella.actor_name
200
- payload = message.to_json
201
- elsif message.is_json?
202
- p = JSON.parse(message)
203
- p[:from] = Nutella.actor_name
204
- payload = p.to_json
205
- elsif message.is_a?(String)
206
- payload = { :payload => message, :from => Nutella.actor_name }.to_json
207
- else
208
- raise 'You are trying to publish something that is not JSON!'
210
+ def Net.prepare_message_for_response( message, id )
211
+ from = Nutella.resource_id.nil? ? Nutella.component_id : "#{Nutella.component_id}/#{Nutella.resource_id}"
212
+ if message.nil?
213
+ return {id: id, type: 'response', from: from}.to_json
214
+ end
215
+ {id: id, type: 'response', from: from, payload: message}.to_json
216
+ end
217
+
218
+ def Net.prepare_message_for_request( message )
219
+ from = Nutella.resource_id.nil? ? Nutella.component_id : "#{Nutella.component_id}/#{Nutella.resource_id}"
220
+ if message.nil?
221
+ return {id: message.hash, type: 'request', from: from}.to_json, message.hash
209
222
  end
210
- payload
223
+ return {id: message.hash, type: 'request', from: from, payload: message}.to_json, message.hash
211
224
  end
212
225
 
226
+
213
227
  end
214
228
  end
@@ -0,0 +1,118 @@
1
+ require 'mqtt'
2
+
3
+ # Simple asynchronous MQTT client
4
+ # @author Alessandro Gnoli <tebemis@gmail.com>
5
+ class SimpleMQTTClient
6
+
7
+ # Creates a new MQTT client
8
+ # @param [String] host the hostname of the MQTT broker we are connecting to
9
+ # @param [String] client_id the **unique** client identifier
10
+ def initialize(host, client_id=nil)
11
+ @host = host
12
+ @channels = Hash.new
13
+ @client = client_id.nil? ? MQTT::Client.connect(:host => host) : MQTT::Client.connect(host: host, client_id: client_id)
14
+ @thread = Thread.new('mqtt') do
15
+ @client.get do |channel, message|
16
+ cbs = get_callbacks channel
17
+ # If there is no callback (cb=nil) do nothing, otherwise call the right callback:
18
+ # single channel callback with one parameter, wildcard channel callback with two.
19
+ unless cbs.nil?
20
+ (@channels.has_key? channel) ? cbs.each { |cb| cb.call(message) } : cbs.each { |cb| cb.call(message, channel) }
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # Subscribes to a channel and registers a callback
27
+ # Single channel callbacks take only one parameter: the received message
28
+ # Wildcard callbacks take two parameters: the received message and the channel the message was sent to
29
+ # @param [String] channel the channel or filter we are subscribing to
30
+ # @param [Proc] callback the callback that gets called
31
+ # whenever a messages is received
32
+ def subscribe(channel, callback)
33
+ if @channels.include?(channel)
34
+ @channels[channel] << callback
35
+ else
36
+ @channels[channel]=[callback]
37
+ @client.subscribe channel
38
+ end
39
+ end
40
+
41
+ # Un-subscribes a specific callback from a channel
42
+ # @param [String] channel the channel we are un-subscribing from
43
+ # @param [Proc] callback the specific callback we want to remove
44
+ def unsubscribe(channel, callback)
45
+ if @channels.include? channel
46
+ @channels[channel].delete(callback)
47
+ end
48
+ if @channels[channel].empty?
49
+ @client.unsubscribe channel
50
+ @channels.delete(channel)
51
+ end
52
+ end
53
+
54
+ # Returns the a hash of all the channels this client is currently subscribed to
55
+ # with relative callbacks
56
+ # @return [Hash] the hash of all the channels this client is currently subscribed to and relative callbacks
57
+ def get_subscribed_channels
58
+ @channels
59
+ end
60
+
61
+ # Returns true
62
+ # @return [Boolean] true if the channel is a wildcard channel. See MQTT specification for wildcard channels
63
+ # {http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718106 here}
64
+ # @param [String] channel the channel we are testing for wildcard
65
+ def is_channel_wildcard?( channel )
66
+ channel.include?('#') || channel.include?('+')
67
+ end
68
+
69
+ # Publishes a message to a channel
70
+ # @param [String] channel the channel we are publishing to
71
+ # @param [String] message the message we are publishing
72
+ def publish(channel, message)
73
+ @client.publish(channel, message)
74
+ end
75
+
76
+ # Disconnects this simple MQTT client instance from the broker
77
+ def disconnect
78
+ @client.disconnect
79
+ end
80
+
81
+ private
82
+
83
+ # Gets the right callback associated to a channel
84
+ # Specific callback gets precedence over wildcards
85
+ def get_callbacks(channel)
86
+ # First try to see if a callback for the exact channel exists
87
+ return @channels[channel] if @channels.has_key? channel
88
+ # If it doesn't then let's try to find a wildcard match
89
+ pattern = wildcard_match channel
90
+ return @channels[pattern] unless pattern.nil?
91
+ # If there's no exact match or wildcard we have to return nil
92
+ nil
93
+ end
94
+
95
+ # Returns the wildcard pattern, among the ones we subscribed to, that matches the channel.
96
+ # This IGNORES exact matches!!!
97
+ # It returns nil if the channel doesn't match any of the channels/filers we are subscribed to.
98
+ def wildcard_match(channel)
99
+ @channels.keys.each do |pattern|
100
+ return pattern if matches_generic_pattern(channel, pattern)
101
+ end
102
+ # If we go through the whole list of channels and there is no generic pattern then return nil
103
+ nil
104
+ end
105
+
106
+ # Returns true if the string matches a pattern (including the exact pattern)
107
+ def matches_generic_pattern(str, pattern)
108
+ # If multi-level wildcard is the only character in pattern, then any string will match
109
+ return true if pattern=='#'
110
+ # Handle all other multi-level wildcards
111
+ p_wo_wildcard = pattern[0..-2]
112
+ str_wo_details = str[0..pattern.length-2]
113
+ return true if pattern[-1, 1]=='#' && p_wo_wildcard==str_wo_details
114
+ # TODO Handle single-level wildcards (+)
115
+ false
116
+ end
117
+
118
+ end
data/nutella_lib.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: nutella_lib 0.2.2 ruby lib
5
+ # stub: nutella_lib 0.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "nutella_lib"
9
- s.version = "0.2.2"
9
+ s.version = "0.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Alessandro Gnoli"]
14
- s.date = "2014-11-17"
14
+ s.date = "2015-02-17"
15
15
  s.description = "Implements the nutella protocol and exposes it natively to ruby developers"
16
16
  s.email = "tebemis@gmail.com"
17
17
  s.extra_rdoc_files = [
@@ -32,9 +32,11 @@ Gem::Specification.new do |s|
32
32
  "lib/nutella_lib/net.rb",
33
33
  "lib/nutella_lib/noext.rb",
34
34
  "lib/nutella_lib/persist.rb",
35
+ "lib/simple_mqtt_client/simple_mqtt_client.rb",
35
36
  "nutella_lib.gemspec",
36
37
  "test/helper.rb",
37
- "test/test_nutella_lib.rb"
38
+ "test/test_nutella_lib.rb",
39
+ "test/test_simple_mqtt_client.rb"
38
40
  ]
39
41
  s.homepage = "https://github.com/nutella-framework/nutella_lib.rb"
40
42
  s.licenses = ["MIT"]
@@ -45,7 +47,7 @@ Gem::Specification.new do |s|
45
47
  s.specification_version = 4
46
48
 
47
49
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
- s.add_runtime_dependency(%q<simple_ruby_mqtt_client>, [">= 0.3.1", "~> 0.3.1"])
50
+ s.add_runtime_dependency(%q<mqtt>, [">= 0.3", "~> 0.3"])
49
51
  s.add_development_dependency(%q<shoulda>, [">= 3", "~> 3"])
50
52
  s.add_development_dependency(%q<minitest>, [">= 5", "~> 5.4"])
51
53
  s.add_development_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
@@ -54,7 +56,7 @@ Gem::Specification.new do |s|
54
56
  s.add_development_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0.1"])
55
57
  s.add_development_dependency(%q<simplecov>, [">= 0", "~> 0"])
56
58
  else
57
- s.add_dependency(%q<simple_ruby_mqtt_client>, [">= 0.3.1", "~> 0.3.1"])
59
+ s.add_dependency(%q<mqtt>, [">= 0.3", "~> 0.3"])
58
60
  s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
59
61
  s.add_dependency(%q<minitest>, [">= 5", "~> 5.4"])
60
62
  s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
@@ -64,7 +66,7 @@ Gem::Specification.new do |s|
64
66
  s.add_dependency(%q<simplecov>, [">= 0", "~> 0"])
65
67
  end
66
68
  else
67
- s.add_dependency(%q<simple_ruby_mqtt_client>, [">= 0.3.1", "~> 0.3.1"])
69
+ s.add_dependency(%q<mqtt>, [">= 0.3", "~> 0.3"])
68
70
  s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
69
71
  s.add_dependency(%q<minitest>, [">= 5", "~> 5.4"])
70
72
  s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
@@ -2,21 +2,77 @@ require 'helper'
2
2
 
3
3
  class TestNutellaLib < MiniTest::Test
4
4
 
5
- # def test_that_kernel_extension_works
6
- # assert_instance_of Nutella::Core, nutella
5
+
6
+ # def test_connect_and_send_receive_messages_correctly
7
+ # cb_executed = false
8
+ # nutella.init('my_run_id', 'ltg.evl.uic.edu', 'my_bot_component')
9
+ # nutella.set_resource_id 'my_resource_id'
10
+ # cb = lambda do |message, component_id, resource_id|
11
+ # cb_executed = true
12
+ # puts "Received message from #{component_id}/#{resource_id}. Message: #{message}"
13
+ # end
14
+ # nutella.net.subscribe('demo1', cb)
15
+ # sleep 1
16
+ # nutella.net.publish('demo1', 'test_message')
17
+ # # Make sure we wait for the message to be delivered
18
+ # sleep 1
19
+ # assert cb_executed
20
+ # end
21
+ #
22
+ #
23
+ # def test_connect_and_send_receive_wildcard_messages_correctly
24
+ # cb_executed = false
25
+ # nutella.init('my_run_id', 'ltg.evl.uic.edu', 'my_bot_component')
26
+ # nutella.set_resource_id 'my_resource_id'
27
+ # cb = lambda do |message, channel, component_id, resource_id|
28
+ # cb_executed = true
29
+ # puts "Received message on #{channel} from #{component_id}/#{resource_id}. Message: #{message}"
30
+ # end
31
+ # nutella.net.subscribe('demo1/#', cb)
32
+ # sleep 1
33
+ # nutella.net.publish('demo1/demo', 'test_message')
34
+ # # Make sure we wait for the message to be delivered
35
+ # sleep 1
36
+ # assert cb_executed
7
37
  # end
8
38
 
9
- # def test_core_module_method_call
10
- # nutella.hello "Ruby"
39
+
40
+ # def test_multiple_subscriptions
41
+ # nutella.init('my_run_id', 'ltg.evl.uic.edu', 'my_bot_component')
42
+ # nutella.set_resource_id 'my_resource_id'
43
+ # cb = lambda do |message, component_id, resource_id|
44
+ # puts "Received message #{component_id}/#{resource_id}. Message: #{message}"
45
+ # end
46
+ # nutella.net.subscribe('demo1', cb)
47
+ # nutella.net.subscribe('demo1', cb) # This must raise an error
11
48
  # end
12
49
 
13
50
 
14
- # tests for sync/asynch_Req
15
- # v = nutella.net.sync_req("quakes_schedule", '{"stringa":"json"}')
16
- # v = nutella.net.sync_req("quakes_schedule", "messaggio")
17
- # v = nutella.net.sync_req("quakes_schedule", {})
18
- # v = nutella.net.sync_req("quakes_schedule", {:cane => "dio"})
19
- # v = nutella.net.sync_req("quakes_schedule")
51
+ # def test_request_response
52
+ # nutella.init('my_run_id', 'ltg.evl.uic.edu', 'my_bot_component')
53
+ # nutella.set_resource_id 'my_resource_id'
54
+ #
55
+ # nutella.net.subscribe('demo1', lambda do |message, component_id, resource_id|
56
+ # puts "Received a message from #{component_id}/#{resource_id}. Message: #{message}"
57
+ # end)
58
+ #
59
+ # nutella.net.handle_requests( 'demo1', lambda do |message, component_id, resource_id|
60
+ # puts "We received a request: message #{message}, from #{component_id}/#{resource_id}"
61
+ # #Then we are going to return some JSON
62
+ # {my:'json'}
63
+ # end)
64
+ #
65
+ # response = nutella.net.sync_req( 'demo1', 'my request is a string' )
66
+ # puts 'Response to sync'
67
+ # p response
68
+ #
69
+ # nutella.net.async_req( 'demo1', 'my request is a string', lambda do |response|
70
+ # puts 'Response to async'
71
+ # p response
72
+ # end)
73
+ #
74
+ # nutella.net.listen
75
+ # end
20
76
 
21
77
 
22
78
  end
@@ -0,0 +1,55 @@
1
+ require 'helper'
2
+
3
+ class TestSimpleRubyMqttClient < MiniTest::Test
4
+
5
+ # def test_connect_and_send_receive_messages_correctly
6
+ # cb_executed = false
7
+ # sc1 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
8
+ # cb1 = lambda do |message|
9
+ # cb_executed = true
10
+ # assert_equal 'test-message-1', message
11
+ # sc1.unsubscribe 'demo1', cb1
12
+ # end
13
+ # sc1.subscribe('demo1', cb1)
14
+ #
15
+ # sc2 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
16
+ # sc2.publish('demo1', 'test-message-1')
17
+ # # Make sure we wait for the message to be delivered
18
+ # sleep(1)
19
+ # assert cb_executed
20
+ # end
21
+ #
22
+ # def test_list_current_subscriptions_correctly
23
+ # sc3 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
24
+ # cb2 = lambda {|message| puts message}
25
+ # cb3 = lambda {|message| puts message}
26
+ # sc3.subscribe( 'channel_1', cb2 )
27
+ # sc3.subscribe( 'channel_2', cb2 )
28
+ # sc3.subscribe( 'channel_3', cb2 )
29
+ # sc3.subscribe( 'channel_3', cb3 )
30
+ # assert_equal sc3.get_subscribed_channels['channel_3'].length, 2
31
+ # sc3.unsubscribe( 'channel_3', cb2 )
32
+ # assert_equal sc3.get_subscribed_channels['channel_3'].length, 1
33
+ # end
34
+ #
35
+ # def test_recognize_wildcard_patters_correctly
36
+ # sc4 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
37
+ # sc4.subscribe('run_id/#', lambda {|m| puts m})
38
+ # refute_nil sc4.send(:get_callbacks, 'run_id/one')
39
+ # refute_nil sc4.send(:get_callbacks, 'run_id/one/two')
40
+ # end
41
+ #
42
+ # def test_multiple_subscriptions
43
+ # sc5 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
44
+ # total = 0
45
+ # cb1 = lambda { |message| total += 3; puts "CB1: #{message}"}
46
+ # cb2 = lambda { |message| total += 1; puts "CB2: #{message}"}
47
+ # sc5.subscribe('demo2', cb1)
48
+ # sc5.subscribe('demo2', cb2)
49
+ # sc6 = SimpleMQTTClient.new 'ltg.evl.uic.edu'
50
+ # sc6.publish('demo2', 'test-message-2')
51
+ # # Make sure we wait for the message to be delivered
52
+ # sleep(1)
53
+ # assert_equal total, 4
54
+ # end
55
+ end
metadata CHANGED
@@ -1,35 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nutella_lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Gnoli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-17 00:00:00.000000000 Z
11
+ date: 2015-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: simple_ruby_mqtt_client
14
+ name: mqtt
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.1
19
+ version: '0.3'
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.3.1
22
+ version: '0.3'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.3.1
29
+ version: '0.3'
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.3.1
32
+ version: '0.3'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: shoulda
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -191,9 +191,11 @@ files:
191
191
  - lib/nutella_lib/net.rb
192
192
  - lib/nutella_lib/noext.rb
193
193
  - lib/nutella_lib/persist.rb
194
+ - lib/simple_mqtt_client/simple_mqtt_client.rb
194
195
  - nutella_lib.gemspec
195
196
  - test/helper.rb
196
197
  - test/test_nutella_lib.rb
198
+ - test/test_simple_mqtt_client.rb
197
199
  homepage: https://github.com/nutella-framework/nutella_lib.rb
198
200
  licenses:
199
201
  - MIT