druzy-upnp 1.0.0 → 2.0.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 +4 -4
- data/lib/druzy/upnp/ssdp.rb +52 -182
- data/lib/druzy/upnp/upnp_device.rb +73 -0
- data/lib/druzy/upnp/upnp_service.rb +74 -0
- data/lib/druzy/upnp/version.rb +2 -2
- metadata +17 -187
- data/lib/core_ext/hash_patch.rb +0 -5
- data/lib/core_ext/socket_patch.rb +0 -16
- data/lib/core_ext/to_upnp_s.rb +0 -65
- data/lib/druzy/upnp/control_point/base.rb +0 -70
- data/lib/druzy/upnp/control_point/device.rb +0 -465
- data/lib/druzy/upnp/control_point/error.rb +0 -15
- data/lib/druzy/upnp/control_point/service.rb +0 -387
- data/lib/druzy/upnp/control_point.rb +0 -161
- data/lib/druzy/upnp/device.rb +0 -31
- data/lib/druzy/upnp/ssdp/broadcast_searcher.rb +0 -110
- data/lib/druzy/upnp/ssdp/error.rb +0 -8
- data/lib/druzy/upnp/ssdp/listener.rb +0 -36
- data/lib/druzy/upnp/ssdp/multicast_connection.rb +0 -109
- data/lib/druzy/upnp/ssdp/network_constants.rb +0 -19
- data/lib/druzy/upnp/ssdp/notifier.rb +0 -39
- data/lib/druzy/upnp/ssdp/searcher.rb +0 -85
- data/lib/rack/upnp_control_point.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef31e12c2747c77a8519f682a898a87e9e6939c7
|
4
|
+
data.tar.gz: 63cb56202abc50e9d400c5d1089301ce0544a9dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f6592b21116bb309bfc171de869568f5f2dee96a9a6e674ca6c861ab3e9aa0899c5945f748680000ed81eb42dd6292b52e790364be6e6aa5bdcd1a54478bf99
|
7
|
+
data.tar.gz: 9edf72a244a19276b51cdbd00a0fb7e6e4ca3c1f0903e98d42c48bc9208645302a786ae41c87ce0589004df73e778ad020d5e1fae2f4bd3cd8ee43cd9244a473
|
data/lib/druzy/upnp/ssdp.rb
CHANGED
@@ -1,195 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'em-synchrony'
|
4
|
-
require 'core_ext/to_upnp_s'
|
5
|
-
require_relative 'ssdp/error'
|
6
|
-
require_relative 'ssdp/network_constants'
|
7
|
-
require_relative 'ssdp/listener'
|
8
|
-
require_relative 'ssdp/searcher'
|
9
|
-
require_relative 'ssdp/notifier'
|
1
|
+
require_relative 'upnp_device'
|
2
|
+
require_relative 'version'
|
10
3
|
|
11
|
-
|
4
|
+
require 'socket'
|
5
|
+
require 'timeout'
|
12
6
|
|
13
7
|
module Druzy
|
14
8
|
module Upnp
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# "discovery" step.
|
23
|
-
#
|
24
|
-
# Before you can do anything with any of the UPnP devices on your network, you
|
25
|
-
# need to +search+ your network to see what devices are available. Once you've
|
26
|
-
# found what's available, you can then decide device(s) you'd like to control
|
27
|
-
# (that's where Control Points come in; take a look at Playful::ControlPoint).
|
28
|
-
# After searching, you should then +listen+ to the activity on your network.
|
29
|
-
# New devices on your network may come online (via +ssdp:alive+) and devices
|
30
|
-
# that you care about may go offline (via +ssdp:byebye+), in which case you
|
31
|
-
# probably shouldn't try to talk to them anymore.
|
32
|
-
#
|
33
|
-
# @todo Add docs for Playful::Device perspective.
|
34
|
-
class SSDP
|
35
|
-
include NetworkConstants
|
36
|
-
|
37
|
-
# Opens a multicast UDP socket on 239.255.255.250:1900 and listens for
|
38
|
-
# alive and byebye notifications from devices.
|
39
|
-
#
|
40
|
-
# @param [Fixnum] ttl The TTL to use on the UDP socket.
|
41
|
-
#
|
42
|
-
# @return [Hash<Array>,Playful::SSDP::Listener] If the EventMachine reactor is
|
43
|
-
# _not_ running, it returns two key/value pairs--one for
|
44
|
-
# alive_notifications, one for byebye_notifications. If the reactor _is_
|
45
|
-
# running, it returns a Playful::SSDP::Listener so that that object can be
|
46
|
-
# used however desired. The latter method is used in Playful::ControlPoints
|
47
|
-
# so that an object of that type can keep track of devices it cares about.
|
48
|
-
def self.listen(ttl=TTL)
|
49
|
-
alive_notifications = Set.new
|
50
|
-
byebye_notifications = Set.new
|
51
|
-
|
52
|
-
listener = proc do
|
53
|
-
l = EM.open_datagram_socket(MULTICAST_IP, MULTICAST_PORT,
|
54
|
-
Playful::SSDP::Listener, ttl)
|
55
|
-
i = 0
|
56
|
-
EM.add_periodic_timer(5) { i += 5; Playful.log "Listening for #{i}\n" }
|
57
|
-
l
|
58
|
-
end
|
59
|
-
|
60
|
-
if EM.reactor_running?
|
61
|
-
return listener.call
|
62
|
-
else
|
63
|
-
EM.synchrony do
|
64
|
-
l = listener.call
|
65
|
-
|
66
|
-
alive_getter = Proc.new do |notification|
|
67
|
-
alive_notifications << notification
|
68
|
-
EM.next_tick { l.alive_notifications.pop(&live_getter) }
|
69
|
-
end
|
70
|
-
l.alive_notifications.pop(&alive_getter)
|
71
|
-
|
72
|
-
byebye_getter = Proc.new do |notification|
|
73
|
-
byebye_notifications << notification
|
74
|
-
EM.next_tick { l.byebye_notifications.pop(&byebye_getter) }
|
75
|
-
end
|
76
|
-
l.byebye_notifications.pop(&byebye_getter)
|
77
|
-
|
78
|
-
trap_signals
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
{
|
83
|
-
alive_notifications: alive_notifications.to_a.flatten,
|
84
|
-
byebye_notifications: byebye_notifications.to_a.flatten
|
85
|
-
}
|
9
|
+
|
10
|
+
class Ssdp
|
11
|
+
@@port = 1900
|
12
|
+
@@host = "239.255.255.250"
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
|
86
16
|
end
|
87
|
-
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
ttl = options[:ttl] || TTL
|
114
|
-
do_broadcast_search = options[:do_broadcast_search]
|
115
|
-
|
116
|
-
searcher_options = options
|
117
|
-
searcher_options.delete :do_broadcast_search
|
118
|
-
|
119
|
-
responses = []
|
120
|
-
search_target = search_target.to_upnp_s
|
121
|
-
|
122
|
-
multicast_searcher = proc do
|
123
|
-
EM.open_datagram_socket('0.0.0.0', 0, Druzy::Upnp::SSDP::Searcher,
|
124
|
-
search_target, searcher_options)
|
125
|
-
end
|
126
|
-
|
127
|
-
broadcast_searcher = proc do
|
128
|
-
EM.open_datagram_socket('0.0.0.0', 0, Druzy::Upnp::SSDP::BroadcastSearcher,
|
129
|
-
search_target, response_wait_time, ttl)
|
130
|
-
end
|
131
|
-
|
132
|
-
if EM.reactor_running?
|
133
|
-
return multicast_searcher.call
|
134
|
-
else
|
135
|
-
EM.synchrony do
|
136
|
-
ms = multicast_searcher.call
|
137
|
-
|
138
|
-
ms.discovery_responses.subscribe do |notification|
|
139
|
-
responses << notification
|
140
|
-
end
|
141
|
-
|
142
|
-
if do_broadcast_search
|
143
|
-
bs = broadcast_searcher.call
|
144
|
-
|
145
|
-
bs.discovery_responses.subscribe do |notification|
|
146
|
-
responses << notification
|
17
|
+
|
18
|
+
#search only device (not service)
|
19
|
+
def search(st = "ssdp:all", delay = 10)
|
20
|
+
message = <<-MESSAGE
|
21
|
+
M-SEARCH * HTTP/1.1\r
|
22
|
+
HOST: #{@@host}:#{@@port}\r
|
23
|
+
MAN: "ssdp:discover"\r
|
24
|
+
MX: #{delay}\r
|
25
|
+
ST: #{st}\r
|
26
|
+
USER-AGENT: #{RbConfig::CONFIG["host_os"]}/ UPnP/1.1 ruby-druzy-upnp/#{Druzy::Upnp::VERSION}\r
|
27
|
+
MESSAGE
|
28
|
+
|
29
|
+
s = UDPSocket.new
|
30
|
+
s.send(message,0,@@host,@@port)
|
31
|
+
devices = []
|
32
|
+
begin
|
33
|
+
Timeout::timeout(delay) do
|
34
|
+
loop do
|
35
|
+
message = s.recv(4196)
|
36
|
+
location = message.split("\n").reject{|line| line==nil || line["LOCATION"]==nil}.first
|
37
|
+
location = location[location.index(" ")+1..location.size-2]
|
38
|
+
if !devices.include?(location)
|
39
|
+
devices << location
|
40
|
+
if block_given?
|
41
|
+
yield UpnpDevice.new(:location => location)
|
42
|
+
end
|
147
43
|
end
|
148
44
|
end
|
149
|
-
|
150
|
-
EM.add_timer(response_wait_time) { EM.stop }
|
151
|
-
trap_signals
|
152
45
|
end
|
46
|
+
rescue
|
47
|
+
|
48
|
+
ensure
|
49
|
+
s.close
|
153
50
|
end
|
154
|
-
|
155
|
-
responses.flatten
|
156
|
-
end
|
157
|
-
|
158
|
-
# @todo This is for Playful::Devices, which aren't implemented yet, and thus
|
159
|
-
# this may not be working.
|
160
|
-
def self.notify(notification_type, usn, ddf_url, valid_for_duration=1800)
|
161
|
-
responses = []
|
162
|
-
notification_type = notification_type.to_upnp_s
|
163
|
-
|
164
|
-
EM.synchrony do
|
165
|
-
s = send_notification(notification_type, usn, ddf_url, valid_for_duration)
|
166
|
-
EM.add_shutdown_hook { responses = s.discovery_responses }
|
167
|
-
|
168
|
-
EM.add_periodic_timer(valid_for_duration) do
|
169
|
-
s = send_notification(notification_type, usn, ddf_url, valid_for_duration)
|
170
|
-
end
|
171
|
-
|
172
|
-
trap_signals
|
173
|
-
end
|
174
|
-
|
175
|
-
responses
|
176
|
-
end
|
177
|
-
|
178
|
-
# @todo This is for Playful::Devices, which aren't implemented yet, and thus
|
179
|
-
# this may not be working.
|
180
|
-
def self.send_notification(notification_type, usn, ddf_url, valid_for_duration)
|
181
|
-
EM.open_datagram_socket('0.0.0.0', 0, Druzy::Upnp::SSDP::Notifier, notification_type,
|
182
|
-
usn, ddf_url, valid_for_duration)
|
183
|
-
end
|
184
|
-
|
185
|
-
private
|
186
|
-
|
187
|
-
# Traps INT, TERM, and HUP signals and stops the reactor.
|
188
|
-
def self.trap_signals
|
189
|
-
trap('INT') { EM.stop }
|
190
|
-
trap('TERM') { EM.stop }
|
191
|
-
trap('HUP') { EM.stop } if RUBY_PLATFORM !~ /mswin|mingw/
|
51
|
+
|
192
52
|
end
|
53
|
+
|
193
54
|
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if $0 == __FILE__
|
60
|
+
Druzy::Upnp::Ssdp.new.search("urn:schemas-upnp-org:device:MediaRenderer:1") do |device|
|
61
|
+
puts device.device_type
|
62
|
+
connection_id, av_transport_id, rcs_id = device.ConnectionManager.PrepareForConnection("RemoteProtocolInfo" => "http-get:*:video/mp4:*", "PeerConnectionManager" => "/", "PeerConnectionID" => -1, "Direction" => "Output").values
|
63
|
+
puts av_transport_id.to_s
|
194
64
|
end
|
195
65
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'upnp_service'
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module Druzy
|
7
|
+
module Upnp
|
8
|
+
|
9
|
+
class UpnpDevice
|
10
|
+
|
11
|
+
attr_reader :url_base, :device_type, :friendly_name, :manufacturer, :manufacturer_url, :model_description
|
12
|
+
attr_reader :model_name, :model_number, :model_url, :serial_number, :udn, :upc, :icon_list, :service_list
|
13
|
+
attr_reader :device_list
|
14
|
+
|
15
|
+
def initialize(args)
|
16
|
+
|
17
|
+
if args[:ssdp_message] != nil
|
18
|
+
|
19
|
+
mess = args[:ssdp_message]
|
20
|
+
location=mess.split("\n").reject{|line| line==nil || line["LOCATION"]==nil}.first
|
21
|
+
initialize(:location => location[location.index(" ")+1..location.size-2])
|
22
|
+
|
23
|
+
elsif args[:location] != nil
|
24
|
+
|
25
|
+
uri = URI(args[:location])
|
26
|
+
xml=Net::HTTP.get(uri)
|
27
|
+
xml_nok = Nokogiri::XML(xml)
|
28
|
+
xml_nok.remove_namespaces!
|
29
|
+
initialize(:uri => uri, :xml => Nokogiri::XML(xml_nok.xpath('root/device').to_s))
|
30
|
+
|
31
|
+
else
|
32
|
+
|
33
|
+
uri = args[:uri]
|
34
|
+
xml_nok = args[:xml]
|
35
|
+
#puts xml_nok
|
36
|
+
@url_base = uri.scheme+'://'+uri.host+":"+uri.port.to_s
|
37
|
+
@device_type = xml_nok.xpath('device/deviceType').text
|
38
|
+
@friendly_name = xml_nok.xpath('device/friendlyName').text
|
39
|
+
@manufacturer = xml_nok.xpath('device/manufacturer').text
|
40
|
+
@manufacturer_url = xml_nok.xpath('device/manufacturerURL').text
|
41
|
+
@model_description = xml_nok.xpath('device/modelDescription').text
|
42
|
+
@model_name = xml_nok.xpath('device/modelName').text
|
43
|
+
@model_number = xml_nok.xpath('device/modelNumber').text
|
44
|
+
@model_url = xml_nok.xpath('device/modelURL').text
|
45
|
+
@serial_number = xml_nok.xpath('device/serialNumber').text
|
46
|
+
@udn = xml_nok.xpath('device/UDN').text
|
47
|
+
@upc = xml_nok.xpath('device/UPC').text
|
48
|
+
@icon_list = xml_nok.xpath('device/iconList/icon/url').to_a.collect{|el| @url_base+el.text}
|
49
|
+
@service_list = xml_nok.xpath('device/serviceList/service').to_a.collect{|el| UpnpService.new(
|
50
|
+
:service_type => el.xpath("serviceType").text,
|
51
|
+
:service_id => el.xpath("serviceId").text,
|
52
|
+
:location => @url_base+el.xpath("SCPDURL").text,
|
53
|
+
:control_url => @url_base+el.xpath("controlURL").text,
|
54
|
+
:event_sub_url => @url_base+el.xpath("eventSubURL").text
|
55
|
+
)}
|
56
|
+
@service_list.each do |service|
|
57
|
+
method_name = service.service_id[service.service_id.rindex(':')+1..-1]
|
58
|
+
define_singleton_method(method_name.to_sym) do
|
59
|
+
return service
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
@device_list = xml_nok.xpath('device/deviceList/device').to_a.collect{|el|
|
64
|
+
UpnpDevice.new(
|
65
|
+
:uri => uri,
|
66
|
+
:xml => Nokogiri::XML(el.to_s)
|
67
|
+
)}
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Druzy
|
6
|
+
module Upnp
|
7
|
+
class UpnpService
|
8
|
+
|
9
|
+
attr_reader :service_type, :service_id, :location, :control_url, :event_sub_url
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
|
13
|
+
@service_type = args[:service_type]
|
14
|
+
@service_id = args[:service_id]
|
15
|
+
@location = args[:location]
|
16
|
+
@control_url = args[:control_url]
|
17
|
+
@event_sub_url = args[:event_sub_url]
|
18
|
+
|
19
|
+
uri = URI(@location)
|
20
|
+
xml=Net::HTTP.get(uri)
|
21
|
+
xml_nok = Nokogiri::XML(xml)
|
22
|
+
xml_nok.remove_namespaces!
|
23
|
+
xml_nok.xpath('scpd/actionList/action').to_a.each do |el|
|
24
|
+
|
25
|
+
action_name = el.xpath('name').text
|
26
|
+
define_singleton_method(action_name.to_sym) do |arguments={}|
|
27
|
+
message = <<-MESSAGE
|
28
|
+
<?xml version="1.0"?>
|
29
|
+
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
30
|
+
<s:Body>
|
31
|
+
<u:#{action_name} xmlns:u="#{@service_type}">
|
32
|
+
MESSAGE
|
33
|
+
|
34
|
+
arguments.each do |cle, valeur|
|
35
|
+
message.concat <<-MESSAGE
|
36
|
+
<#{cle.to_s}>#{valeur.to_s}</#{cle.to_s}>
|
37
|
+
MESSAGE
|
38
|
+
end
|
39
|
+
|
40
|
+
message.concat <<-MESSAGE
|
41
|
+
</u:#{action_name}>
|
42
|
+
</s:Body>
|
43
|
+
</s:Envelope>
|
44
|
+
MESSAGE
|
45
|
+
|
46
|
+
header = {
|
47
|
+
"HOST" => uri.host.to_s+':'+uri.port.to_s,
|
48
|
+
"CONTENT-LENGTH" => message.size.to_s,
|
49
|
+
"CONTENT-TYPE" => 'text/xml; charset="utf-8"',
|
50
|
+
"SOAPACTION" => @service_type.to_s+"#"+action_name.to_s
|
51
|
+
}
|
52
|
+
|
53
|
+
http = Net::HTTP.new(uri.host,uri.port)
|
54
|
+
request = Net::HTTP::Post.new(uri.request_uri,header)
|
55
|
+
request.body = message
|
56
|
+
response = http.request(request)
|
57
|
+
xml = Nokogiri.XML(response.body)
|
58
|
+
xml.remove_namespaces!
|
59
|
+
|
60
|
+
result = {}
|
61
|
+
puts "avant hash"
|
62
|
+
xml.xpath("Envelope/Body/"+action_name.to_s+"Response").children.each do |child|
|
63
|
+
result[child.name.to_s] = child.text
|
64
|
+
end
|
65
|
+
|
66
|
+
return result
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/druzy/upnp/version.rb
CHANGED
metadata
CHANGED
@@ -1,239 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: druzy-upnp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Le Greneur
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.6.7.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
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: savon
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '2.0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '2.0'
|
26
|
+
version: 1.6.7.2
|
83
27
|
- !ruby/object:Gem::Dependency
|
84
28
|
name: bundler
|
85
29
|
requirement: !ruby/object:Gem::Requirement
|
86
30
|
requirements:
|
87
|
-
- - "
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: cucumber
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 1.0.0
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 1.0.0
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: em-websocket
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
31
|
+
- - "~>"
|
116
32
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
33
|
+
version: '1.11'
|
118
34
|
type: :development
|
119
35
|
prerelease: false
|
120
36
|
version_requirements: !ruby/object:Gem::Requirement
|
121
37
|
requirements:
|
122
|
-
- - "
|
38
|
+
- - "~>"
|
123
39
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
40
|
+
version: '1.11'
|
125
41
|
- !ruby/object:Gem::Dependency
|
126
42
|
name: rake
|
127
43
|
requirement: !ruby/object:Gem::Requirement
|
128
44
|
requirements:
|
129
|
-
- - "
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: rspec
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - ">="
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: 3.0.0.beta
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 3.0.0.beta
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: simplecov
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - ">="
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: 0.4.2
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - ">="
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: 0.4.2
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: thin
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - ">="
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '0'
|
174
|
-
type: :development
|
175
|
-
prerelease: false
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
177
|
-
requirements:
|
178
|
-
- - ">="
|
179
|
-
- !ruby/object:Gem::Version
|
180
|
-
version: '0'
|
181
|
-
- !ruby/object:Gem::Dependency
|
182
|
-
name: thor
|
183
|
-
requirement: !ruby/object:Gem::Requirement
|
184
|
-
requirements:
|
185
|
-
- - ">="
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
version: 0.1.6
|
188
|
-
type: :development
|
189
|
-
prerelease: false
|
190
|
-
version_requirements: !ruby/object:Gem::Requirement
|
191
|
-
requirements:
|
192
|
-
- - ">="
|
193
|
-
- !ruby/object:Gem::Version
|
194
|
-
version: 0.1.6
|
195
|
-
- !ruby/object:Gem::Dependency
|
196
|
-
name: yard
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
198
|
-
requirements:
|
199
|
-
- - ">="
|
45
|
+
- - "~>"
|
200
46
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
47
|
+
version: '10.0'
|
202
48
|
type: :development
|
203
49
|
prerelease: false
|
204
50
|
version_requirements: !ruby/object:Gem::Requirement
|
205
51
|
requirements:
|
206
|
-
- - "
|
52
|
+
- - "~>"
|
207
53
|
- !ruby/object:Gem::Version
|
208
|
-
version:
|
209
|
-
description:
|
210
|
-
that runs in a UPnP environment.
|
54
|
+
version: '10.0'
|
55
|
+
description: Discover and interact with upnp device
|
211
56
|
email:
|
212
57
|
- jonathan.legreneur@free.fr
|
213
58
|
executables: []
|
214
59
|
extensions: []
|
215
60
|
extra_rdoc_files: []
|
216
61
|
files:
|
217
|
-
- lib/core_ext/hash_patch.rb
|
218
|
-
- lib/core_ext/socket_patch.rb
|
219
|
-
- lib/core_ext/to_upnp_s.rb
|
220
62
|
- lib/druzy/upnp.rb
|
221
|
-
- lib/druzy/upnp/control_point.rb
|
222
|
-
- lib/druzy/upnp/control_point/base.rb
|
223
|
-
- lib/druzy/upnp/control_point/device.rb
|
224
|
-
- lib/druzy/upnp/control_point/error.rb
|
225
|
-
- lib/druzy/upnp/control_point/service.rb
|
226
|
-
- lib/druzy/upnp/device.rb
|
227
63
|
- lib/druzy/upnp/ssdp.rb
|
228
|
-
- lib/druzy/upnp/
|
229
|
-
- lib/druzy/upnp/
|
230
|
-
- lib/druzy/upnp/ssdp/listener.rb
|
231
|
-
- lib/druzy/upnp/ssdp/multicast_connection.rb
|
232
|
-
- lib/druzy/upnp/ssdp/network_constants.rb
|
233
|
-
- lib/druzy/upnp/ssdp/notifier.rb
|
234
|
-
- lib/druzy/upnp/ssdp/searcher.rb
|
64
|
+
- lib/druzy/upnp/upnp_device.rb
|
65
|
+
- lib/druzy/upnp/upnp_service.rb
|
235
66
|
- lib/druzy/upnp/version.rb
|
236
|
-
- lib/rack/upnp_control_point.rb
|
237
67
|
homepage: https://github.com/druzy/ruby-druzy-upnp
|
238
68
|
licenses:
|
239
69
|
- MIT
|
@@ -257,5 +87,5 @@ rubyforge_project:
|
|
257
87
|
rubygems_version: 2.5.1
|
258
88
|
signing_key:
|
259
89
|
specification_version: 4
|
260
|
-
summary:
|
90
|
+
summary: A control point UPNP
|
261
91
|
test_files: []
|