easy_upnp 0.1.8 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 017b7021b1d9c35fab09ff9f670a660c96758443
4
- data.tar.gz: 793f938414da9e550a12b94aa90a05ba0de81480
3
+ metadata.gz: ff03da48709a543a35dbfe13a1ece864d9337db6
4
+ data.tar.gz: 61517d04933afc34e2465de2400c577d001b63fb
5
5
  SHA512:
6
- metadata.gz: 71e31a046b94b3e99cb6f79d87da6f2ee92fd06f209960ae67d0cb7457864bac839dfda9312ce8205b5fb4d8ac57d6c81f6673643343c6f84f044ff15b4e45ac
7
- data.tar.gz: 689804ce65c657638e8098403d7ea33571b0b6ca69bfc2cc16f63488fcc9d74b3639eb03d0da63facf86a1fc11bdfbf8f05871123e81ce048091f970a4ae561b
6
+ metadata.gz: 4dbf1e5b113b33fe94db16655421b17f22f72eb57f5deb80521a2f5d6c83e4b097384495370ace08124fdce9da5e1fef228d8b960fefa408a3cc15c0aefb83ff
7
+ data.tar.gz: 50a3d09bd2a1d2fb00f8afab09fca6a95db15c1118a424fdde175e5ab2ddecd537109ef789dc163effac4e1708490c8667342c2c2088a3824dc6474b3c973f75
data/README.md CHANGED
@@ -53,3 +53,22 @@ service.service_methods
53
53
  service.GetSystemUpdateID
54
54
  # => {:Id=>"207"}
55
55
  ```
56
+
57
+ ## Static client construction
58
+
59
+ After you've constructed a client (`DeviceControlPoint`), you probably don't want to have to use SSDP to construct it again the next time you use it. `DeviceControlPoint` is equipped with `#to_params` and `#from_params` methods to make this easy.
60
+
61
+ Say you have a client called `client`. To dump it into a hash, do the following:
62
+
63
+ ```ruby
64
+ params = client.to_params
65
+ #=> {:urn=>"urn:schemas-upnp-org:service:ContentDirectory:1", :service_endpoint=>"http://10.133.8.11:8200/ctl/ContentDir", :definition=>"<?xml version=\"1.0\"?>\r\n<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">( ... clipped ... )</scpd>", :options=>{}}
66
+ ```
67
+
68
+ We can then reconstruct a client from these params and use it normally:
69
+
70
+ ```ruby
71
+ client = EasyUpnp::DeviceControlPoint.from_params(params)
72
+ client.GetSystemUpdateID
73
+ => {:Id=>"258"}
74
+ ```
@@ -6,22 +6,80 @@ module EasyUpnp
6
6
  class DeviceControlPoint
7
7
  attr_reader :service_methods
8
8
 
9
- def initialize(client, service_type, definition_url, options)
10
- @client = client
11
- @service_type = service_type
9
+ def initialize(urn, service_endpoint, definition, options)
10
+ @urn = urn
11
+ @service_endpoint = service_endpoint
12
12
  @options = options
13
+ @definition = definition
13
14
 
14
- service_methods = []
15
- definition = Nokogiri::XML(open(definition_url))
16
- definition.remove_namespaces!
15
+ @client = Savon.client do |c|
16
+ c.endpoint service_endpoint
17
+ c.namespace urn
18
+
19
+ # I found this was necessary on some of my UPnP devices (namely, a Sony TV).
20
+ c.namespaces({:'s:encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"})
21
+
22
+ # This makes XML tags be like <ObjectID> instead of <objectID>.
23
+ c.convert_request_keys_to :camelcase
24
+
25
+ c.namespace_identifier :u
26
+ c.env_namespace :s
27
+ end
17
28
 
18
- definition.xpath('//actionList/action').map do |action|
29
+ definition_xml = Nokogiri::XML(definition)
30
+ definition_xml.remove_namespaces!
31
+
32
+ service_methods = []
33
+ definition_xml.xpath('//actionList/action').map do |action|
19
34
  service_methods.push define_action(action)
20
35
  end
21
36
 
22
37
  @service_methods = service_methods
23
38
  end
24
39
 
40
+ def to_params
41
+ {
42
+ urn: @urn,
43
+ service_endpoint: @service_endpoint,
44
+ definition: @definition,
45
+ options: @options
46
+ }
47
+ end
48
+
49
+ def self.from_params(params)
50
+ DeviceControlPoint.new(
51
+ params[:urn],
52
+ params[:service_endpoint],
53
+ params[:definition],
54
+ params[:options]
55
+ )
56
+ end
57
+
58
+ def self.from_service_definition(definition, options = {})
59
+ urn = definition[:st]
60
+ root_uri = definition[:location]
61
+
62
+ xml = Nokogiri::XML(open(root_uri))
63
+ xml.remove_namespaces!
64
+
65
+ service = xml.xpath("//device/serviceList/service[serviceType=\"#{urn}\"]").first
66
+
67
+ if service.nil?
68
+ raise RuntimeError.new "Couldn't find service with urn: #{urn}"
69
+ else
70
+ service = Nokogiri::XML(service.to_xml)
71
+ service_definition_uri = URI.join(root_uri, service.xpath('service/SCPDURL').text).to_s
72
+ service_definition = open(service_definition_uri) { |f| f.read }
73
+
74
+ DeviceControlPoint.new(
75
+ urn,
76
+ URI.join(root_uri, service.xpath('service/controlURL').text).to_s,
77
+ service_definition,
78
+ options
79
+ )
80
+ end
81
+ end
82
+
25
83
  private
26
84
 
27
85
  def define_action(action)
@@ -47,9 +105,9 @@ module EasyUpnp
47
105
  end
48
106
 
49
107
  attrs = {
50
- soap_action: "#{@service_type}##{action_name}",
108
+ soap_action: "#{@urn}##{action_name}",
51
109
  attributes: {
52
- :'xmlns:u' => @service_type
110
+ :'xmlns:u' => @urn
53
111
  },
54
112
  }.merge(@options)
55
113
 
@@ -86,4 +144,4 @@ module EasyUpnp
86
144
  downcase
87
145
  end
88
146
  end
89
- end
147
+ end
@@ -63,7 +63,7 @@ module EasyUpnp
63
63
  # and create UpnpDevices for them. This wrap the services advertized by the SSDP
64
64
  # results.
65
65
  parsed_messages.reject { |x| !x[:usn] }.group_by { |x| x[:usn].split('::').first }.map do |k, v|
66
- UpnpDevice.new k, v
66
+ UpnpDevice.from_ssdp_messages(k, v)
67
67
  end
68
68
  end
69
69
 
@@ -9,9 +9,13 @@ module EasyUpnp
9
9
  class UpnpDevice
10
10
  attr_reader :uuid, :name, :host
11
11
 
12
- def initialize uuid, messages
12
+ def initialize(uuid, service_definitions)
13
13
  @uuid = uuid
14
- @service_definitions = messages.
14
+ @service_definitions = service_definitions
15
+ end
16
+
17
+ def self.from_ssdp_messages(uuid, messages)
18
+ service_definitions = messages.
15
19
  # Filter out messages that aren't service definitions. These include
16
20
  # the root device and the root UUID
17
21
  reject { |message| not message[:st].include? ':service:' }.
@@ -26,18 +30,7 @@ module EasyUpnp
26
30
  }
27
31
  end
28
32
 
29
- # Download one of the definitions to get the name of this device
30
- if @service_definitions.any?
31
- service_location = @service_definitions.first[:location]
32
-
33
- xml = Nokogiri::XML(open(service_location))
34
- xml.remove_namespaces!
35
- @name = xml.xpath('//device/friendlyName').text
36
- @host = URI.parse(service_location).host
37
- else
38
- @name = 'UNKNOWN'
39
- @host = 'UNKNOWN'
40
- end
33
+ UpnpDevice.new(uuid, service_definitions)
41
34
  end
42
35
 
43
36
  def all_services
@@ -52,35 +45,7 @@ module EasyUpnp
52
45
  definition = service_definition(urn)
53
46
 
54
47
  if !definition.nil?
55
- root_uri = definition[:location]
56
- xml = Nokogiri::XML(open(root_uri))
57
- xml.remove_namespaces!
58
-
59
- service = xml.xpath("//device/serviceList/service[serviceType=\"#{urn}\"]").first
60
-
61
- if service.nil?
62
- raise RuntimeError.new "Couldn't find service with urn: #{urn}"
63
- else
64
- service = Nokogiri::XML(service.to_xml)
65
- wsdl = URI.join(root_uri, service.xpath('service/SCPDURL').text).to_s
66
-
67
- client = Savon.client do |c|
68
- c.endpoint URI.join(root_uri, service.xpath('service/controlURL').text).to_s
69
-
70
- c.namespace urn
71
-
72
- # I found this was necessary on some of my UPnP devices (namely, a Sony TV).
73
- c.namespaces({:'s:encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"})
74
-
75
- # This makes XML tags be like <ObjectID> instead of <objectID>.
76
- c.convert_request_keys_to :camelcase
77
-
78
- c.namespace_identifier :u
79
- c.env_namespace :s
80
- end
81
-
82
- DeviceControlPoint.new client, urn, wsdl, options
83
- end
48
+ DeviceControlPoint.from_service_definition(definition, options)
84
49
  end
85
50
  end
86
51
 
@@ -90,4 +55,4 @@ module EasyUpnp
90
55
  first
91
56
  end
92
57
  end
93
- end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module EasyUpnp
2
- VERSION = '0.1.8'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_upnp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Mullins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-11 00:00:00.000000000 Z
11
+ date: 2016-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
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
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: savon
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.11.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.11.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: nori
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 2.6.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.6.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: nokogiri
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 1.6.6.2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.6.6.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: 2.0.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: 2.0.0
83
83
  description:
@@ -86,7 +86,7 @@ executables: []
86
86
  extensions: []
87
87
  extra_rdoc_files: []
88
88
  files:
89
- - .gitignore
89
+ - ".gitignore"
90
90
  - Gemfile
91
91
  - LICENSE
92
92
  - README.md
@@ -105,17 +105,17 @@ require_paths:
105
105
  - lib
106
106
  required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - '>='
113
+ - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
117
  rubyforge_project:
118
- rubygems_version: 2.4.8
118
+ rubygems_version: 2.5.1
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: A super easy to use UPnP control point client