nutella_lib 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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