iohub 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Rakefile +35 -0
- data/env.env +1 -0
- data/iohub/model/app.rb +32 -0
- data/iohub/model/app_value.rb +31 -0
- data/iohub/model/message.rb +105 -0
- data/iohub/model/message_value.rb +46 -0
- data/iohub/properties/application_properties.rb +34 -0
- data/iohub/socket/base_web_socket.rb +162 -0
- data/iohub/socket/client_web_socket.rb +19 -0
- data/test/units/application_properties_test.rb +11 -0
- data/test/units/io_hub_test.rb +9 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NjFiMGU2NTFjZGY2ZWUzZDFhNWQxYmMwNzg2ZmE4ZWEzZTkyMjg2YQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NWY1YjkxODdmNDU3YjY5ODY4ZmRhMzJhNmRlNmYzMjQ0NmQyNzg0ZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTczM2VkZjkzYzFmNjBiZmY5ZmM1ZmY0MmU1YWNjMmQ1YTNkNWJhY2QzOWZh
|
10
|
+
MzNiZmMzMzEyOTBjMDRiNDE3ZmUzNzAyY2I5ZTdmYTEzNzMzZjRjOWZmODdi
|
11
|
+
YjJjMjc3YWU1MzcxYmRlMjg5Yjc0ZWE4YmJlZjRjMTUyMDlhNzM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzZmMWM4ZDdmODlkMzkwYmYzMzQ2N2Q3ZGY5ZGFiZGY1YzJlNmE4OThmZDQ0
|
14
|
+
MjE4MDRlNmJhZDQwNTRhMjNiODliZjdjNzMyZDA5NDBmMThkNTg2N2ViMGU5
|
15
|
+
OTA3YTM5MzY5ZDY5ZTllYWUxYjYyNWU1Mjg3MTRlOWY1YmM5Y2E=
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/clean'
|
3
|
+
|
4
|
+
|
5
|
+
namespace :gem do
|
6
|
+
task :create_prod do
|
7
|
+
create_file("env=prod", "env.env")
|
8
|
+
system("gem build iohub.gemspec")
|
9
|
+
end
|
10
|
+
|
11
|
+
task :create_dev do
|
12
|
+
create_file("env=dev", "env.env")
|
13
|
+
system("gem build iohub.gemspec")
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_file(content, file_name)
|
17
|
+
dir = "#{File.dirname(__FILE__)}/iohub/properties/" + file_name.to_s
|
18
|
+
File.delete(dir)
|
19
|
+
file = File.new(dir, "w")
|
20
|
+
file.puts content
|
21
|
+
file.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
task :test do
|
27
|
+
#sh 'ruby -I"lib:test" "test/units/application_properties_test.rb"'
|
28
|
+
#sh 'ruby -I"lib:test" "test/units/message_test.rb"'
|
29
|
+
sh 'ruby -I"lib:test" "test/units/base_web_socket_test.rb"'
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
data/env.env
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
env=prod
|
data/iohub/model/app.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'json'
|
3
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/app_value.rb"
|
4
|
+
|
5
|
+
|
6
|
+
class App < AppValue
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(app_id, app_secret, app_secret_word, account_id, app_type)
|
10
|
+
super(app_id, app_secret, app_secret_word, account_id, app_type)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def is_no_retry_msg
|
15
|
+
self.get_no_retry_msg == get_app_type
|
16
|
+
end
|
17
|
+
|
18
|
+
def is_retry_no_order_msg
|
19
|
+
|
20
|
+
self.get_retry_msg_no_order == get_app_type
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_retry_msg_order
|
24
|
+
self.get_retry_msg_order == get_app_type
|
25
|
+
end
|
26
|
+
|
27
|
+
def does_msg_order_matter
|
28
|
+
return is_retry_no_order_msg || is_retry_msg_order
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class AppValue
|
2
|
+
@@NO_RETRY_MSG = "NO_RETRY_MSG"
|
3
|
+
@@RETRY_MSG_NO_ORDER = "RETRY_MSG_NO_ORDER"
|
4
|
+
@@RETRY_MSG_ORDER = "RETRY_MSG_ORDER"
|
5
|
+
@app_type = @@NO_RETRY_MSG
|
6
|
+
|
7
|
+
def initialize(app_id, app_secret, app_secret_word, account_id, app_type)
|
8
|
+
@app_id = app_id
|
9
|
+
@app_secret = app_secret
|
10
|
+
@app_secret_word = app_secret_word
|
11
|
+
@account_id = account_id
|
12
|
+
@app_type = app_type
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_app_type
|
16
|
+
@app_type
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.get_no_retry_msg
|
20
|
+
@@NO_RETRY_MSG
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.get_retry_msg_no_order
|
24
|
+
@@RETRY_MSG_NO_ORDER
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get_retry_msg_order
|
28
|
+
@@RETRY_MSG_ORDER
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'json'
|
3
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/message_value.rb"
|
4
|
+
|
5
|
+
|
6
|
+
class Message < MessageValue
|
7
|
+
|
8
|
+
CONNECT_ACTION = "CONNECT"
|
9
|
+
BROADCAST_ACTION = "BROADCAST"
|
10
|
+
JOIN_ACTION = "JOIN"
|
11
|
+
RELAY_BROADCAST_ACTION = "RELAY_BROADCAST"
|
12
|
+
CONNECT_HUB_ACTION = "CONNECT_HUB"
|
13
|
+
SEND_ACTION = "SEND"
|
14
|
+
DRIP_ACTION = "DRIP"
|
15
|
+
MISSING_MSG_ACTION = "MISSING_MSG"
|
16
|
+
APP_TYPE_MSG_ACTION = "APP_TYPE_MSG"
|
17
|
+
|
18
|
+
|
19
|
+
def self.create_connect_msg(username, token, app_id)
|
20
|
+
msg = Message.new("0", "", "", CONNECT_ACTION, username, token, app_id)
|
21
|
+
msg
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create_join_msg(channel_code, username, app_id)
|
25
|
+
msg = Message.new("0", "", channel_code, JOIN_ACTION, username, "", app_id)
|
26
|
+
msg
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.create_broadcast_msg(channel_code, username, token, app_id)
|
30
|
+
msg = Message.new("0", "", channel_code, BROADCAST_ACTION, username, token, app_id)
|
31
|
+
msg
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.create_missing_msg(channel_code, username, token, app_id, msg_set)
|
35
|
+
msg = self.create_missing_msg_value(msg_set)
|
36
|
+
msg_to_return = Message.new("0", msg, channel_code, MISSING_MSG_ACTION, username, token, app_id)
|
37
|
+
msg_to_return
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def self.create_drip
|
42
|
+
msg = Message.new("0", "", "", DRIP_ACTION, "", "", "")
|
43
|
+
msg
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json
|
47
|
+
hash = {}
|
48
|
+
self.instance_variables.each do |var|
|
49
|
+
var_for_hash = var.to_s.delete "@"
|
50
|
+
hash[var_for_hash] = self.instance_variable_get var
|
51
|
+
end
|
52
|
+
hash.to_json
|
53
|
+
end
|
54
|
+
|
55
|
+
def do_you_own_message
|
56
|
+
@doYouOwnMessage
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_broadcast
|
60
|
+
return BROADCAST_ACTION == @action
|
61
|
+
end
|
62
|
+
|
63
|
+
def is_send
|
64
|
+
return SEND_ACTION == @action
|
65
|
+
end
|
66
|
+
|
67
|
+
def is_connect_hub
|
68
|
+
return CONNECT_HUB_ACTION == @action
|
69
|
+
end
|
70
|
+
|
71
|
+
def is_connect
|
72
|
+
return CONNECT_ACTION == @action
|
73
|
+
end
|
74
|
+
|
75
|
+
def is_join
|
76
|
+
return JOIN_ACTION == @action
|
77
|
+
end
|
78
|
+
|
79
|
+
def is_Relay_Broadcast
|
80
|
+
return RELAY_BROADCAST_ACTION == @action
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_missing_msg
|
84
|
+
return MISSING_MSG_ACTION == @action
|
85
|
+
end
|
86
|
+
|
87
|
+
def is_app_type
|
88
|
+
return APP_TYPE_MSG_ACTION == @action
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def self.create_missing_msg_value(msg_set)
|
94
|
+
msg_to_return = ""
|
95
|
+
number_of_elements = msg_set.size
|
96
|
+
item_length = 0
|
97
|
+
msg_set.each do |msg|
|
98
|
+
item_length = item_length + 1
|
99
|
+
if (number_of_elements != item_length)
|
100
|
+
msg_to_return << msg << ","
|
101
|
+
end
|
102
|
+
end
|
103
|
+
msg_to_return
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class MessageValue
|
2
|
+
|
3
|
+
def initialize(rtc, message, channel_code, action, username, token, app_id)
|
4
|
+
@rtc = rtc
|
5
|
+
@message = message
|
6
|
+
@channelCode = channel_code
|
7
|
+
@action = action
|
8
|
+
@username = username
|
9
|
+
@fromIp = ""
|
10
|
+
@toIp = ""
|
11
|
+
@token = token
|
12
|
+
@appId = app_id
|
13
|
+
@toKey = ""
|
14
|
+
@timeKey = 0
|
15
|
+
@totalNumberOfMessages = 0
|
16
|
+
@fromMissedMessage = false
|
17
|
+
@fromBroadcast = false
|
18
|
+
@doYouOwnMessage = false
|
19
|
+
@class = "io.iohub.socket.model.Message"
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_msg
|
23
|
+
@message
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_time_key
|
27
|
+
@timeKey
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_total_number_of_messages
|
31
|
+
@totalNumberOfMessages
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_from_missed_message
|
35
|
+
@fromMissedMessage
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_message(message)
|
39
|
+
@message = message
|
40
|
+
end
|
41
|
+
|
42
|
+
def do_you_own_message
|
43
|
+
@doYouOwnMessage
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class ApplicationProperties
|
4
|
+
def initialize(yml_file_name)
|
5
|
+
@yml_file = YAML.load_file("#{File.join(File.dirname(__FILE__), '../../')}/config/" + yml_file_name.to_s)
|
6
|
+
@@ENV = read_env
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
def get_env
|
11
|
+
@@ENV
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_property(property_name)
|
15
|
+
property = ""
|
16
|
+
if @yml_file[@@ENV]
|
17
|
+
property = @yml_file[@@ENV][property_name]
|
18
|
+
end
|
19
|
+
property
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def read_env
|
25
|
+
f = File.open("#{File.dirname(__FILE__)}/env.env", "r")
|
26
|
+
f.each_line do |line|
|
27
|
+
@line = line
|
28
|
+
end
|
29
|
+
f.close
|
30
|
+
items = @line.split("=")
|
31
|
+
items[1].chop!
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'eventmachine'
|
3
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/properties/application_properties.rb"
|
4
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/socket/base_web_socket.rb"
|
5
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/message.rb"
|
6
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/message_value.rb"
|
7
|
+
require 'thread'
|
8
|
+
require 'rubygems'
|
9
|
+
require 'json'
|
10
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/app.rb"
|
11
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/model/app_value.rb"
|
12
|
+
|
13
|
+
class BaseWebSocket
|
14
|
+
@@SOCKET_PROPERTIES = ApplicationProperties.new("socket.yml")
|
15
|
+
@@APP_URL = @@SOCKET_PROPERTIES.get_property("app_uri")
|
16
|
+
|
17
|
+
@@ALL_MESSAGES = Hash.new()
|
18
|
+
@@GENERATED_MESSAGES = Array.new()
|
19
|
+
@@SEMAPHORE = Mutex.new
|
20
|
+
@@APP_TYPE = "";
|
21
|
+
|
22
|
+
def initialize(usernameIn, appIdIn, tokenIn, channel)
|
23
|
+
@username = usernameIn
|
24
|
+
@appId = appIdIn
|
25
|
+
@token = tokenIn
|
26
|
+
@channel = channel
|
27
|
+
init
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def broadcast(message)
|
32
|
+
if (@channel == nil)
|
33
|
+
raise 'Please join a channel before calling broadcast'
|
34
|
+
end
|
35
|
+
msg = Message.create_broadcast_msg(@channel, @username, @token, @appId)
|
36
|
+
msg.set_message(message);
|
37
|
+
json_msg = msg.to_json
|
38
|
+
send_msg(json_msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
def join(channel)
|
42
|
+
if (channel == nil)
|
43
|
+
raise 'Please join a channel'
|
44
|
+
end
|
45
|
+
|
46
|
+
@channel = channel
|
47
|
+
msg = Message.create_join_msg(@channel, @username, @appId)
|
48
|
+
json_msg = msg.to_json
|
49
|
+
send_msg(json_msg)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def connect
|
55
|
+
message = Message.create_connect_msg(@username, @token, @appId)
|
56
|
+
msg_json = message.to_json
|
57
|
+
send_msg(msg_json)
|
58
|
+
|
59
|
+
if (@channel != nil)
|
60
|
+
join(@channel)
|
61
|
+
end
|
62
|
+
|
63
|
+
#todo create a drip thread
|
64
|
+
|
65
|
+
@@ALL_MESSAGES.clear
|
66
|
+
end
|
67
|
+
|
68
|
+
def process_message(msg)
|
69
|
+
puts(msg)
|
70
|
+
message = JSON.parse(msg)
|
71
|
+
if message == nil
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
if (message.is_app_type)
|
76
|
+
@@APP_TYPE = message.get_msg()
|
77
|
+
end
|
78
|
+
|
79
|
+
if (message.is_broadcast && (AppValue.get_retry_msg_no_order == @@APP_TYPE || AppValue.get_retry_msg_order == @@APP_TYPE))
|
80
|
+
if (message.do_you_own_message)
|
81
|
+
time_key = message.get_time_key
|
82
|
+
@@ALL_MESSAGES[time_key.to_sym] = msg
|
83
|
+
else
|
84
|
+
time_key = message.get_time_key
|
85
|
+
@@ALL_MESSAGES[time_key.to_sym] = msg
|
86
|
+
has_missing_messages = has_missing_messages(message)
|
87
|
+
from_missed_message = message.get_from_missed_message()
|
88
|
+
|
89
|
+
if (has_missing_messages && !from_missed_message)
|
90
|
+
keys = @@ALL_MESSAGES.keys
|
91
|
+
if (keys != null && keys.length() > 0)
|
92
|
+
getMissingMessages = Message.create_missing_msg(@channel, @username, @token, @appId, keys)
|
93
|
+
json = getMissingMessages.to_json
|
94
|
+
send_msg(json)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def has_missing_messages (message)
|
102
|
+
total = message.get_total_number_of_messages
|
103
|
+
number_of_inbound_messages = @@ALL_MESSAGES.length()
|
104
|
+
return (total > number_of_inbound_messages)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def is_consumable_message(msg)
|
109
|
+
message = JSON.parse(msg)
|
110
|
+
return message.is_broadcast && !message.do_you_own_message
|
111
|
+
end
|
112
|
+
|
113
|
+
def can_process_message(message)
|
114
|
+
!message.do_you_own_message
|
115
|
+
end
|
116
|
+
|
117
|
+
def join_on_connect()
|
118
|
+
end
|
119
|
+
|
120
|
+
def send_msg(msgIn)
|
121
|
+
|
122
|
+
if (AppValue.get_no_retry_msg != @@APP_TYPE)
|
123
|
+
@@SEMAPHORE.synchronize do
|
124
|
+
@@GENERATED_MESSAGES.push(msgIn)
|
125
|
+
items_to_remove = Array.new
|
126
|
+
|
127
|
+
@@GENERATED_MESSAGES.length.times do |i|
|
128
|
+
msg_json = @@GENERATED_MESSAGES[i]
|
129
|
+
@ws.send(msg_json)
|
130
|
+
items_to_remove.push(msg_json)
|
131
|
+
end
|
132
|
+
if (items_to_remove.length == @@GENERATED_MESSAGES.length)
|
133
|
+
@@GENERATED_MESSAGES.clear
|
134
|
+
end
|
135
|
+
end
|
136
|
+
else
|
137
|
+
@ws.send(msgIn)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def init
|
142
|
+
EM.run {
|
143
|
+
@ws = Faye::WebSocket::Client.new(@@APP_URL)
|
144
|
+
|
145
|
+
@ws.on :open do |event|
|
146
|
+
p [:open]
|
147
|
+
connect()
|
148
|
+
join_on_connect()
|
149
|
+
end
|
150
|
+
|
151
|
+
@ws.on :message do |event|
|
152
|
+
process_message(event.data)
|
153
|
+
end
|
154
|
+
|
155
|
+
@ws.on :close do |event|
|
156
|
+
@ws = nil
|
157
|
+
end
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'eventmachine'
|
3
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/properties/application_properties.rb"
|
4
|
+
require "#{File.join(File.dirname(__FILE__), '../../')}/iohub/socket/base_web_socket.rb"
|
5
|
+
require 'thread'
|
6
|
+
|
7
|
+
class ClientWebSocket < BaseWebSocket
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(usernameIn, appIdIn, tokenIn, channel)
|
11
|
+
super(usernameIn, appIdIn, tokenIn, channel)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def process_message(msg)
|
16
|
+
puts("sub class " + msg.to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "#{File.expand_path(File.join(File.dirname(__FILE__), '../../'))}/iohub/properties/application_properties.rb"
|
3
|
+
|
4
|
+
class ApplicationPropertiesTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_properties_socket
|
7
|
+
properties = ApplicationProperties.new("socket.yml")
|
8
|
+
assert_equal("ws://54.221.194.107:80", properties.get_property("app_uri"))
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iohub
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Rodrigues
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: a ruby client for iohub.io
|
14
|
+
email: rodriguesd@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- env.env
|
20
|
+
- Rakefile
|
21
|
+
- iohub/model/app.rb
|
22
|
+
- iohub/model/app_value.rb
|
23
|
+
- iohub/model/message.rb
|
24
|
+
- iohub/model/message_value.rb
|
25
|
+
- iohub/properties/application_properties.rb
|
26
|
+
- iohub/socket/base_web_socket.rb
|
27
|
+
- iohub/socket/client_web_socket.rb
|
28
|
+
- test/units/io_hub_test.rb
|
29
|
+
- test/units/application_properties_test.rb
|
30
|
+
homepage: http://rubygems.org/gems/iohub
|
31
|
+
licenses: []
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- iohub
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.1.4
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: io hub client for iohub.io
|
53
|
+
test_files:
|
54
|
+
- test/units/io_hub_test.rb
|
55
|
+
- test/units/application_properties_test.rb
|