frisky 0.1.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 +7 -0
- data/.gemtest +0 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +23 -0
- data/History.md +3 -0
- data/LICENSE.md +23 -0
- data/README.md +185 -0
- data/Rakefile +16 -0
- data/features/device_discovery.feature +9 -0
- data/features/step_definitions/.gitkeep +0 -0
- data/features/support/env.rb +21 -0
- data/features/support/world_extensions.rb +7 -0
- data/frisky.gemspec +28 -0
- data/lib/core_ext/hash_patch.rb +5 -0
- data/lib/core_ext/socket_patch.rb +16 -0
- data/lib/core_ext/to_upnp_s.rb +65 -0
- data/lib/frisky.rb +5 -0
- data/lib/frisky/logger.rb +8 -0
- data/lib/frisky/ssdp.rb +188 -0
- data/lib/frisky/ssdp/broadcast_searcher.rb +114 -0
- data/lib/frisky/ssdp/error.rb +6 -0
- data/lib/frisky/ssdp/listener.rb +38 -0
- data/lib/frisky/ssdp/multicast_connection.rb +112 -0
- data/lib/frisky/ssdp/network_constants.rb +17 -0
- data/lib/frisky/ssdp/notifier.rb +41 -0
- data/lib/frisky/ssdp/searcher.rb +87 -0
- data/lib/frisky/version.rb +3 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/search_responses.rb +134 -0
- data/spec/unit/core_ext/to_upnp_s_spec.rb +105 -0
- data/spec/unit/frisky/ssdp/listener_spec.rb +29 -0
- data/spec/unit/frisky/ssdp/multicast_connection_spec.rb +157 -0
- data/spec/unit/frisky/ssdp/notifier_spec.rb +76 -0
- data/spec/unit/frisky/ssdp/searcher_spec.rb +110 -0
- data/spec/unit/frisky/ssdp_spec.rb +214 -0
- data/tasks/search.thor +35 -0
- metadata +181 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'frisky/ssdp/notifier'
|
3
|
+
|
4
|
+
|
5
|
+
describe Frisky::SSDP::Notifier do
|
6
|
+
around(:each) do |example|
|
7
|
+
EM.synchrony do
|
8
|
+
example.run
|
9
|
+
EM.stop
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:nt) { 'en tee' }
|
14
|
+
let(:usn) { 'you ess en' }
|
15
|
+
let(:ddf_url) { 'ddf url' }
|
16
|
+
let(:duration) { 567 }
|
17
|
+
|
18
|
+
subject do
|
19
|
+
Frisky::SSDP::Notifier.new(1, nt, usn, ddf_url, duration)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#initialize' do
|
23
|
+
it 'creates a notification' do
|
24
|
+
expect_any_instance_of(Frisky::SSDP::Notifier).to receive(:notification).
|
25
|
+
with(nt, usn, ddf_url, duration)
|
26
|
+
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#post_init' do
|
32
|
+
context 'send_datagram returns positive value' do
|
33
|
+
before do
|
34
|
+
expect(subject).to receive(:send_datagram).and_return 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'logs what was sent' do
|
38
|
+
expect(subject).to receive(:log).with /Sent notification/
|
39
|
+
|
40
|
+
subject.post_init
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'send_datagram returns 0' do
|
45
|
+
before do
|
46
|
+
expect(subject).to receive(:send_datagram).and_return 0
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not log what was sent' do
|
50
|
+
expect(subject).to_not receive(:log)
|
51
|
+
|
52
|
+
subject.post_init
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#notification' do
|
58
|
+
before do
|
59
|
+
subject.instance_variable_set(:@os, 'my OS')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'builds the notification message' do
|
63
|
+
expect(subject.notification(nt, usn, ddf_url, duration)).to eq <<-NOTE
|
64
|
+
NOTIFY * HTTP/1.1\r
|
65
|
+
HOST: 239.255.255.250:1900\r
|
66
|
+
CACHE-CONTROL: max-age=567\r
|
67
|
+
LOCATION: ddf url\r
|
68
|
+
NT: en tee\r
|
69
|
+
NTS: ssdp:alive\r
|
70
|
+
SERVER: my OS UPnP/1.0 Frisky/#{Frisky::VERSION}\r
|
71
|
+
USN: you ess en\r
|
72
|
+
\r
|
73
|
+
NOTE
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'frisky/ssdp/searcher'
|
3
|
+
|
4
|
+
|
5
|
+
describe Frisky::SSDP::Searcher do
|
6
|
+
around(:each) do |example|
|
7
|
+
EM.synchrony do
|
8
|
+
example.run
|
9
|
+
EM.stop
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
Frisky.logging_enabled = false
|
15
|
+
allow_any_instance_of(Frisky::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
|
16
|
+
end
|
17
|
+
|
18
|
+
subject do
|
19
|
+
Frisky::SSDP::Searcher.new(1, 'ssdp:all', {})
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'lets you read its responses' do
|
23
|
+
responses = double 'responses'
|
24
|
+
subject.instance_variable_set(:@discovery_responses, responses)
|
25
|
+
expect(subject.discovery_responses).to eq responses
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#initialize' do
|
29
|
+
it 'does an #m_search' do
|
30
|
+
expect_any_instance_of(Frisky::SSDP::Searcher).to receive(:m_search).and_return(<<-MSEARCH
|
31
|
+
M-SEARCH * HTTP/1.1\r
|
32
|
+
HOST: 239.255.255.250:1900\r
|
33
|
+
MAN: "ssdp:discover"\r
|
34
|
+
MX: 5\r
|
35
|
+
ST: ssdp:all\r
|
36
|
+
\r
|
37
|
+
MSEARCH
|
38
|
+
)
|
39
|
+
subject
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#receive_data' do
|
44
|
+
let(:parsed_response) do
|
45
|
+
parsed_response = double 'parsed response'
|
46
|
+
expect(parsed_response).to receive(:has_key?).with(:nts).and_return false
|
47
|
+
expect(parsed_response).to receive(:[]).and_return false
|
48
|
+
|
49
|
+
parsed_response
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'takes a response and adds it to the list of responses' do
|
53
|
+
response = double 'response'
|
54
|
+
allow(subject).to receive(:peer_info).and_return(['0.0.0.0', 4567])
|
55
|
+
|
56
|
+
expect(subject).to receive(:parse).with(response).exactly(1).times.
|
57
|
+
and_return(parsed_response)
|
58
|
+
expect(subject.instance_variable_get(:@discovery_responses)).to receive(:<<).
|
59
|
+
with(parsed_response)
|
60
|
+
|
61
|
+
subject.receive_data(response)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#post_init' do
|
66
|
+
before { allow_any_instance_of(Frisky::SSDP::Searcher).to receive(:m_search).and_return('hi') }
|
67
|
+
|
68
|
+
it 'sends an M-SEARCH as a datagram over 239.255.255.250:1900' do
|
69
|
+
m_search_count_times = subject.instance_variable_get(:@m_search_count)
|
70
|
+
expect(subject).to receive(:send_datagram).
|
71
|
+
with('hi', '239.255.255.250', 1900).
|
72
|
+
exactly(m_search_count_times).times.
|
73
|
+
and_return 0
|
74
|
+
subject.post_init
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#m_search' do
|
79
|
+
it 'builds the MSEARCH string using the given parameters' do
|
80
|
+
expect(subject.m_search('ssdp:all', 10)).to eq <<-MSEARCH
|
81
|
+
M-SEARCH * HTTP/1.1\r
|
82
|
+
HOST: 239.255.255.250:1900\r
|
83
|
+
MAN: "ssdp:discover"\r
|
84
|
+
MX: 10\r
|
85
|
+
ST: ssdp:all\r
|
86
|
+
\r
|
87
|
+
MSEARCH
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'uses 239.255.255.250 as the HOST IP' do
|
91
|
+
expect(subject.m_search('ssdp:all', 10)).to match(/HOST: 239.255.255.250/m)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'uses 1900 as the HOST port' do
|
95
|
+
expect(subject.m_search('ssdp:all', 10)).to match(/HOST:.*1900/m)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'lets you search for undefined search target types' do
|
99
|
+
expect(subject.m_search('spaceship', 10)).to eq <<-MSEARCH
|
100
|
+
M-SEARCH * HTTP/1.1\r
|
101
|
+
HOST: 239.255.255.250:1900\r
|
102
|
+
MAN: "ssdp:discover"\r
|
103
|
+
MX: 10\r
|
104
|
+
ST: spaceship\r
|
105
|
+
\r
|
106
|
+
MSEARCH
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'frisky/ssdp'
|
3
|
+
|
4
|
+
|
5
|
+
describe Frisky::SSDP do
|
6
|
+
subject { Frisky::SSDP }
|
7
|
+
|
8
|
+
describe '.listen' do
|
9
|
+
let(:listener) do
|
10
|
+
searcher = double 'Frisky::SSDP::Listener'
|
11
|
+
searcher.stub_chain(:alive_notifications, :pop).and_yield(%w[one two])
|
12
|
+
searcher.stub_chain(:byebye_notifications, :pop).and_yield(%w[three four])
|
13
|
+
|
14
|
+
searcher
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
allow(EM).to receive(:run).and_yield
|
19
|
+
allow(EM).to receive(:add_timer)
|
20
|
+
allow(EM).to receive(:open_datagram_socket).and_return listener
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'reactor is already running' do
|
24
|
+
it 'returns a Frisky::SSDP::Listener' do
|
25
|
+
allow(EM).to receive(:reactor_running?).and_return true
|
26
|
+
expect(subject.listen).to eq listener
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'reactor is not already running' do
|
31
|
+
it 'returns a Hash of available and byebye responses' do
|
32
|
+
allow(EM).to receive(:add_shutdown_hook).and_yield
|
33
|
+
expect(subject.listen).to eq({
|
34
|
+
alive_notifications: %w[one two],
|
35
|
+
byebye_notifications: %w[three four]
|
36
|
+
})
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'opens a UDP socket on 239.255.255.250, port 1900' do
|
40
|
+
allow(EM).to receive(:add_shutdown_hook)
|
41
|
+
expect(EM).to receive(:open_datagram_socket).with('239.255.255.250', 1900,
|
42
|
+
Frisky::SSDP::Listener, 4)
|
43
|
+
subject.listen
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '.search' do
|
49
|
+
let(:multicast_searcher) do
|
50
|
+
searcher = double 'Frisky::SSDP::Searcher'
|
51
|
+
searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[one two])
|
52
|
+
|
53
|
+
searcher
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:broadcast_searcher) do
|
57
|
+
searcher = double 'Frisky::SSDP::BroadcastSearcher'
|
58
|
+
searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[three four])
|
59
|
+
|
60
|
+
searcher
|
61
|
+
end
|
62
|
+
|
63
|
+
before do
|
64
|
+
allow(EM).to receive(:run).and_yield
|
65
|
+
allow(EM).to receive(:add_timer)
|
66
|
+
allow(EM).to receive(:open_datagram_socket).and_return multicast_searcher
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when search_target is not a String' do
|
70
|
+
it 'calls #to_upnp_s on search_target' do
|
71
|
+
search_target = double('search_target')
|
72
|
+
expect(search_target).to receive(:to_upnp_s)
|
73
|
+
subject.search(search_target)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when search_target is a String' do
|
78
|
+
it 'calls #to_upnp_s on search_target but does not alter it' do
|
79
|
+
search_target = "I'm a string"
|
80
|
+
expect(search_target).to receive(:to_upnp_s).and_call_original
|
81
|
+
|
82
|
+
expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0,
|
83
|
+
Frisky::SSDP::Searcher, "I'm a string", {})
|
84
|
+
subject.search(search_target)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'reactor is already running' do
|
89
|
+
it 'returns a Frisky::SSDP::Searcher' do
|
90
|
+
allow(EM).to receive(:reactor_running?).and_return true
|
91
|
+
expect(subject.search).to eq multicast_searcher
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'reactor is not already running' do
|
96
|
+
context 'options hash includes do_broadcast_search' do
|
97
|
+
before do
|
98
|
+
allow(EM).to receive(:open_datagram_socket).
|
99
|
+
and_return(multicast_searcher, broadcast_searcher)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns an Array of responses' do
|
103
|
+
allow(EM).to receive(:add_shutdown_hook).and_yield
|
104
|
+
expect(subject.search(:all, do_broadcast_search: true)).to eq %w[one two three four]
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'opens 2 UDP sockets on 0.0.0.0, port 0' do
|
108
|
+
allow(EM).to receive(:add_shutdown_hook)
|
109
|
+
expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Frisky::SSDP::Searcher,
|
110
|
+
'ssdp:all', {})
|
111
|
+
expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Frisky::SSDP::BroadcastSearcher,
|
112
|
+
'ssdp:all', 5, 4)
|
113
|
+
subject.search(:all, do_broadcast_search: true)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'options hash does not include do_broadcast_search' do
|
118
|
+
it 'returns an Array of responses' do
|
119
|
+
allow(EM).to receive(:add_shutdown_hook).and_yield
|
120
|
+
expect(subject.search).to eq %w[one two]
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'opens a UDP socket on 0.0.0.0, port 0' do
|
124
|
+
allow(EM).to receive(:add_shutdown_hook)
|
125
|
+
expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Frisky::SSDP::Searcher,
|
126
|
+
'ssdp:all', {})
|
127
|
+
subject.search
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '.notify' do
|
134
|
+
pending 'Implementation of UPnP Devices'
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '.send_notification' do
|
138
|
+
pending 'Implementation of UPnP Devices'
|
139
|
+
end
|
140
|
+
|
141
|
+
=begin
|
142
|
+
context 'by default' do
|
143
|
+
it "searches for 'ssdp:all'" do
|
144
|
+
pending
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'waits for 5 seconds for responses' do
|
148
|
+
before = Time.now
|
149
|
+
|
150
|
+
SSDP.search
|
151
|
+
|
152
|
+
after = Time.now
|
153
|
+
(after - before).should < 5.1
|
154
|
+
(after - before).should > 5.0
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "finds 'upnp:rootdevice's" do
|
159
|
+
it "by using the spec's string 'upnp:rootdevice'" do
|
160
|
+
SSDP.search('upnp:rootdevice').should == [
|
161
|
+
{
|
162
|
+
:cache_control=>'max-age=1200',
|
163
|
+
:date=>'Mon, 26 Sep 2011 06:40:19 GMT',
|
164
|
+
:location=>'http://192.168.10.3:5001/description/fetch',
|
165
|
+
:server=>'Linux-i386-2.6.38-10-generic-pae, UPnP/1.0, PMS/1.25.1',
|
166
|
+
:st=>'upnp:rootdevice',
|
167
|
+
:ext=>'',
|
168
|
+
:usn=>'uuid:3c202906-992d-3f0f-b94c-90e1902a136d::upnp:rootdevice',
|
169
|
+
:content_length=>'0'
|
170
|
+
}
|
171
|
+
]
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'by using :root' do
|
175
|
+
pending
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'can wait for user-defined seconds for responses' do
|
180
|
+
before = Time.now
|
181
|
+
|
182
|
+
SSDP.search(:all, 1)
|
183
|
+
|
184
|
+
after = Time.now
|
185
|
+
(after - before).should < 1.1
|
186
|
+
(after - before).should > 1.0
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'finds a device by its URN' do
|
190
|
+
pending
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'finds a device by its UUID' do
|
194
|
+
pending
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'finds a device by its UPnP device type' do
|
198
|
+
pending
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'finds a device by its UPnP device type using a non-standard domain name' do
|
202
|
+
pending
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'finds a service by its UPnP service type' do
|
206
|
+
pending
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'find a service by its UPnP service type using a non-standard domain name' do
|
210
|
+
pending
|
211
|
+
end
|
212
|
+
=end
|
213
|
+
end
|
214
|
+
|
data/tasks/search.thor
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require File.expand_path(File.dirname(__FILE__)+ '/../lib/frisky/ssdp')
|
3
|
+
require File.expand_path(File.dirname(__FILE__)+ '/../lib/frisky/logger')
|
4
|
+
|
5
|
+
module Frisky
|
6
|
+
class Ssdp < Thor
|
7
|
+
#---------------------------------------------------------------------------
|
8
|
+
# search
|
9
|
+
#---------------------------------------------------------------------------
|
10
|
+
desc 'search TARGET', 'Searches for devices of type TARGET'
|
11
|
+
method_option :response_wait_time, default: 5
|
12
|
+
method_option :ttl, default: 4
|
13
|
+
method_option :do_broadcast_search, type: :boolean
|
14
|
+
method_option :log, type: :boolean
|
15
|
+
def search(target='upnp:rootdevice')
|
16
|
+
::Frisky.logging_enabled = options[:log]
|
17
|
+
time_before = Time.now
|
18
|
+
results = ::Frisky::SSDP.search(target, options.dup)
|
19
|
+
.map { |r| r[:location] }
|
20
|
+
.sort
|
21
|
+
unique = results.uniq
|
22
|
+
time_after = Time.now
|
23
|
+
|
24
|
+
puts <<-RESULTS
|
25
|
+
size: #{results.size}
|
26
|
+
locations: #{results.join("\n ")}
|
27
|
+
unique size: #{unique.size}
|
28
|
+
unique locations: #{unique.join("\n ")}
|
29
|
+
search duration: #{time_after - time_before}
|
30
|
+
RESULTS
|
31
|
+
|
32
|
+
results
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: frisky
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Frisby
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: eventmachine
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: em-http-request
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: em-synchrony
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nori
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.2
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.0.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: log_switch
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: savon
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
description: |-
|
98
|
+
frisky provides the tools you need to build an app that runs
|
99
|
+
in a UPnP environment.
|
100
|
+
email: jfrisby@mrjoy.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files:
|
104
|
+
- History.md
|
105
|
+
- README.md
|
106
|
+
- LICENSE.md
|
107
|
+
files:
|
108
|
+
- ".gemtest"
|
109
|
+
- ".gitignore"
|
110
|
+
- ".rspec"
|
111
|
+
- ".travis.yml"
|
112
|
+
- Gemfile
|
113
|
+
- History.md
|
114
|
+
- LICENSE.md
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- features/device_discovery.feature
|
118
|
+
- features/step_definitions/.gitkeep
|
119
|
+
- features/support/env.rb
|
120
|
+
- features/support/world_extensions.rb
|
121
|
+
- frisky.gemspec
|
122
|
+
- lib/core_ext/hash_patch.rb
|
123
|
+
- lib/core_ext/socket_patch.rb
|
124
|
+
- lib/core_ext/to_upnp_s.rb
|
125
|
+
- lib/frisky.rb
|
126
|
+
- lib/frisky/logger.rb
|
127
|
+
- lib/frisky/ssdp.rb
|
128
|
+
- lib/frisky/ssdp/broadcast_searcher.rb
|
129
|
+
- lib/frisky/ssdp/error.rb
|
130
|
+
- lib/frisky/ssdp/listener.rb
|
131
|
+
- lib/frisky/ssdp/multicast_connection.rb
|
132
|
+
- lib/frisky/ssdp/network_constants.rb
|
133
|
+
- lib/frisky/ssdp/notifier.rb
|
134
|
+
- lib/frisky/ssdp/searcher.rb
|
135
|
+
- lib/frisky/version.rb
|
136
|
+
- spec/spec_helper.rb
|
137
|
+
- spec/support/search_responses.rb
|
138
|
+
- spec/unit/core_ext/to_upnp_s_spec.rb
|
139
|
+
- spec/unit/frisky/ssdp/listener_spec.rb
|
140
|
+
- spec/unit/frisky/ssdp/multicast_connection_spec.rb
|
141
|
+
- spec/unit/frisky/ssdp/notifier_spec.rb
|
142
|
+
- spec/unit/frisky/ssdp/searcher_spec.rb
|
143
|
+
- spec/unit/frisky/ssdp_spec.rb
|
144
|
+
- tasks/search.thor
|
145
|
+
homepage: http://github.com/MrJoy/frisky
|
146
|
+
licenses: []
|
147
|
+
metadata: {}
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 1.9.1
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.4.5.1
|
165
|
+
signing_key:
|
166
|
+
specification_version: 4
|
167
|
+
summary: Use me to build a UPnP app!
|
168
|
+
test_files:
|
169
|
+
- features/device_discovery.feature
|
170
|
+
- features/step_definitions/.gitkeep
|
171
|
+
- features/support/env.rb
|
172
|
+
- features/support/world_extensions.rb
|
173
|
+
- spec/spec_helper.rb
|
174
|
+
- spec/support/search_responses.rb
|
175
|
+
- spec/unit/core_ext/to_upnp_s_spec.rb
|
176
|
+
- spec/unit/frisky/ssdp/listener_spec.rb
|
177
|
+
- spec/unit/frisky/ssdp/multicast_connection_spec.rb
|
178
|
+
- spec/unit/frisky/ssdp/notifier_spec.rb
|
179
|
+
- spec/unit/frisky/ssdp/searcher_spec.rb
|
180
|
+
- spec/unit/frisky/ssdp_spec.rb
|
181
|
+
has_rdoc:
|