turboladen / playful

A Ruby implementation of UPnP that works with Ruby >= 1.9.x
MIT License
127 stars 18 forks source link

lib/upnp/control_point/device.rb:345:in `extract_devices': undefined method `[]' for nil:NilClass (NoMethodError) #5

Open pini-gh opened 11 years ago

pini-gh commented 11 years ago

Hi,

I'm experimenting with this upnp module to interact with my Sonos devices [1].

[1] http://www.sonos.com/

Here is the first snippet I've tried:

#!/usr/bin/ruby

require 'upnp/ssdp'
require 'upnp/control_point'

EM.run do
  cp = UPnP::ControlPoint.new("upnp:rootdevice")
  cp.start do |new_device_channel, old_device_channel|
  end
end

Unfortunately it fails with the trace below:

Couldn't load HTTPI :em_http adapter.
D, [2012-12-27T13:01:15.782693 #19095] DEBUG -- : <UPnP::ControlPoint> Joining reactor...
D, [2012-12-27T13:01:15.790883 #19095] DEBUG -- : Sent datagram search:
D, [2012-12-27T13:01:15.791148 #19095] DEBUG -- : M-SEARCH * HTTP/1.1
D, [2012-12-27T13:01:15.791312 #19095] DEBUG -- : HOST: 239.255.255.250:1900
D, [2012-12-27T13:01:15.791473 #19095] DEBUG -- : MAN: "ssdp:discover"
D, [2012-12-27T13:01:15.791632 #19095] DEBUG -- : MX: 5
D, [2012-12-27T13:01:15.791794 #19095] DEBUG -- : ST: upnp:rootdevice
D, [2012-12-27T13:01:15.791954 #19095] DEBUG -- : 
D, [2012-12-27T13:01:15.792140 #19095] DEBUG -- : Sent datagram search:
D, [2012-12-27T13:01:15.792303 #19095] DEBUG -- : M-SEARCH * HTTP/1.1
D, [2012-12-27T13:01:15.792464 #19095] DEBUG -- : HOST: 239.255.255.250:1900
D, [2012-12-27T13:01:15.792624 #19095] DEBUG -- : MAN: "ssdp:discover"
D, [2012-12-27T13:01:15.792784 #19095] DEBUG -- : MX: 5
D, [2012-12-27T13:01:15.792942 #19095] DEBUG -- : ST: upnp:rootdevice
D, [2012-12-27T13:01:15.795383 #19095] DEBUG -- : 
D, [2012-12-27T13:01:16.288939 #19095] DEBUG -- : Response from 129.200.100.159:1026:
D, [2012-12-27T13:01:16.289076 #19095] DEBUG -- : HTTP/1.1 200 OK
D, [2012-12-27T13:01:16.289123 #19095] DEBUG -- : CACHE-CONTROL: max-age = 1800
D, [2012-12-27T13:01:16.289168 #19095] DEBUG -- : EXT:
D, [2012-12-27T13:01:16.289215 #19095] DEBUG -- : LOCATION: http://129.200.100.159:1400/xml/device_description.xml
D, [2012-12-27T13:01:16.289262 #19095] DEBUG -- : SERVER: Linux UPnP/1.0 Sonos/19.4-59140 (ZPS5)
D, [2012-12-27T13:01:16.289308 #19095] DEBUG -- : ST: upnp:rootdevice
D, [2012-12-27T13:01:16.289353 #19095] DEBUG -- : USN: uuid:RINCON_000E585CCFB801400::upnp:rootdevice
D, [2012-12-27T13:01:16.289399 #19095] DEBUG -- : X-RINCON-BOOTSEQ: 6
D, [2012-12-27T13:01:16.289444 #19095] DEBUG -- : X-RINCON-HOUSEHOLD: Sonos_kJH3HvaP6CMVM0Pa9LLJoAMtxz
D, [2012-12-27T13:01:16.289489 #19095] DEBUG -- : 
D, [2012-12-27T13:01:16.289532 #19095] DEBUG -- : 
D, [2012-12-27T13:01:16.289986 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Got device info: {:ssdp_notification=>{:cache_control=>"max-age = 1800", :ext=>"", :location=>"http://129.200.100.159:1400/xml/device_description.xml", :server=>"Linux UPnP/1.0 Sonos/19.4-59140 (ZPS5)", :st=>"upnp:rootdevice", :usn=>"uuid:RINCON_000E585CCFB801400::upnp:rootdevice", :x_rincon_bootseq=>"6", :x_rincon_household=>"Sonos_kJH3HvaP6CMVM0Pa9LLJoAMtxz"}}
D, [2012-12-27T13:01:16.290132 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Creating device from SSDP Notification info.
D, [2012-12-27T13:01:16.290250 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Getting description with getter ID 69221400 for: http://129.200.100.159:1400/xml/device_description.xml
D, [2012-12-27T13:01:16.302780 #19095] DEBUG -- : <UPnP::ControlPoint::Device> HTTP callback called for 69221400
D, [2012-12-27T13:01:16.334155 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Description received from 69221400
D, [2012-12-27T13:01:16.339807 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Set url_base to http://129.200.100.159:1400/
D, [2012-12-27T13:01:16.340106 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Extracting description for root device 69221400
D, [2012-12-27T13:01:16.340288 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Extracting basic attributes from description...
D, [2012-12-27T13:01:16.341461 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Icon list: {:icon=>{:id=>"0", :mimetype=>"image/png", :width=>"48", :height=>"48", :depth=>"24", :url=>"/img/icon-S5.png"}}
D, [2012-12-27T13:01:16.341717 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Basic attributes extracted.
D, [2012-12-27T13:01:16.341911 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Extracting child devices for 69224330 using 73927900
D, [2012-12-27T13:01:16.342088 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Description has a :root key...
D, [2012-12-27T13:01:16.342804 #19095] DEBUG -- : <UPnP::ControlPoint::Device> device list: [{:deviceType=>"urn:schemas-upnp-org:device:MediaServer:1", :friendlyName=>"129.200.100.159 - Sonos PLAY:5 Media Server", :manufacturer=>"Sonos, Inc.", :manufacturerURL=>"http://www.sonos.com", :modelNumber=>"S5", :modelDescription=>"Sonos PLAY:5 Media Server", :modelName=>"Sonos PLAY:5", :modelURL=>"http://www.sonos.com/products/zoneplayers/S5", :UDN=>"uuid:RINCON_000E585CCFB801400_MS", :serviceList=>{:service=>[{:serviceType=>"urn:schemas-upnp-org:service:ContentDirectory:1", :serviceId=>"urn:upnp-org:serviceId:ContentDirectory", :controlURL=>"/MediaServer/ContentDirectory/Control", :eventSubURL=>"/MediaServer/ContentDirectory/Event", :SCPDURL=>"/xml/ContentDirectory1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:ConnectionManager:1", :serviceId=>"urn:upnp-org:serviceId:ConnectionManager", :controlURL=>"/MediaServer/ConnectionManager/Control", :eventSubURL=>"/MediaServer/ConnectionManager/Event", :SCPDURL=>"/xml/ConnectionManager1.xml"}]}}, {:deviceType=>"urn:schemas-upnp-org:device:MediaRenderer:1", :friendlyName=>"Portable - Sonos PLAY:5 Media Renderer", :manufacturer=>"Sonos, Inc.", :manufacturerURL=>"http://www.sonos.com", :modelNumber=>"S5", :modelDescription=>"Sonos PLAY:5 Media Renderer", :modelName=>"Sonos PLAY:5", :modelURL=>"http://www.sonos.com/products/zoneplayers/S5", :UDN=>"uuid:RINCON_000E585CCFB801400_MR", :serviceList=>{:service=>[{:serviceType=>"urn:schemas-upnp-org:service:RenderingControl:1", :serviceId=>"urn:upnp-org:serviceId:RenderingControl", :controlURL=>"/MediaRenderer/RenderingControl/Control", :eventSubURL=>"/MediaRenderer/RenderingControl/Event", :SCPDURL=>"/xml/RenderingControl1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:ConnectionManager:1", :serviceId=>"urn:upnp-org:serviceId:ConnectionManager", :controlURL=>"/MediaRenderer/ConnectionManager/Control", :eventSubURL=>"/MediaRenderer/ConnectionManager/Event", :SCPDURL=>"/xml/ConnectionManager1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:AVTransport:1", :serviceId=>"urn:upnp-org:serviceId:AVTransport", :controlURL=>"/MediaRenderer/AVTransport/Control", :eventSubURL=>"/MediaRenderer/AVTransport/Event", :SCPDURL=>"/xml/AVTransport1.xml"}]}, :X_Rhapsody_Extension=>{:deviceID=>"urn:rhapsody-real-com:device-id-1-0:sonos_1:RINCON_000E585CCFB801400", :deviceCapabilities=>{:interactionPattern=>{:@type=>"real-rhapsody-upnp-1-0"}}, :@xmlns=>"http://www.real.com/rhapsody/xmlns/upnp-1-0"}, :iconList=>{:icon=>{:mimetype=>"image/png", :width=>"48", :height=>"48", :depth=>"24", :url=>"/img/icon-S5.png"}}}]
D, [2012-12-27T13:01:16.347254 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Extracting services from root device.
D, [2012-12-27T13:01:16.347516 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Extracting services...
D, [2012-12-27T13:01:16.348210 #19095] DEBUG -- : <UPnP::ControlPoint::Device> service list: {:service=>[{:serviceType=>"urn:schemas-upnp-org:service:AlarmClock:1", :serviceId=>"urn:upnp-org:serviceId:AlarmClock", :controlURL=>"/AlarmClock/Control", :eventSubURL=>"/AlarmClock/Event", :SCPDURL=>"/xml/AlarmClock1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:MusicServices:1", :serviceId=>"urn:upnp-org:serviceId:MusicServices", :controlURL=>"/MusicServices/Control", :eventSubURL=>"/MusicServices/Event", :SCPDURL=>"/xml/MusicServices1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:AudioIn:1", :serviceId=>"urn:upnp-org:serviceId:AudioIn", :controlURL=>"/AudioIn/Control", :eventSubURL=>"/AudioIn/Event", :SCPDURL=>"/xml/AudioIn1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:DeviceProperties:1", :serviceId=>"urn:upnp-org:serviceId:DeviceProperties", :controlURL=>"/DeviceProperties/Control", :eventSubURL=>"/DeviceProperties/Event", :SCPDURL=>"/xml/DeviceProperties1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:SystemProperties:1", :serviceId=>"urn:upnp-org:serviceId:SystemProperties", :controlURL=>"/SystemProperties/Control", :eventSubURL=>"/SystemProperties/Event", :SCPDURL=>"/xml/SystemProperties1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:ZoneGroupTopology:1", :serviceId=>"urn:upnp-org:serviceId:ZoneGroupTopology", :controlURL=>"/ZoneGroupTopology/Control", :eventSubURL=>"/ZoneGroupTopology/Event", :SCPDURL=>"/xml/ZoneGroupTopology1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:GroupManagement:1", :serviceId=>"urn:upnp-org:serviceId:GroupManagement", :controlURL=>"/GroupManagement/Control", :eventSubURL=>"/GroupManagement/Event", :SCPDURL=>"/xml/GroupManagement1.xml"}]}
D, [2012-12-27T13:01:16.349079 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Got device info: {:device_description=>{:deviceType=>"urn:schemas-upnp-org:device:MediaServer:1", :friendlyName=>"129.200.100.159 - Sonos PLAY:5 Media Server", :manufacturer=>"Sonos, Inc.", :manufacturerURL=>"http://www.sonos.com", :modelNumber=>"S5", :modelDescription=>"Sonos PLAY:5 Media Server", :modelName=>"Sonos PLAY:5", :modelURL=>"http://www.sonos.com/products/zoneplayers/S5", :UDN=>"uuid:RINCON_000E585CCFB801400_MS", :serviceList=>{:service=>[{:serviceType=>"urn:schemas-upnp-org:service:ContentDirectory:1", :serviceId=>"urn:upnp-org:serviceId:ContentDirectory", :controlURL=>"/MediaServer/ContentDirectory/Control", :eventSubURL=>"/MediaServer/ContentDirectory/Event", :SCPDURL=>"/xml/ContentDirectory1.xml"}, {:serviceType=>"urn:schemas-upnp-org:service:ConnectionManager:1", :serviceId=>"urn:upnp-org:serviceId:ConnectionManager", :controlURL=>"/MediaServer/ConnectionManager/Control", :eventSubURL=>"/MediaServer/ConnectionManager/Event", :SCPDURL=>"/xml/ConnectionManager1.xml"}]}}, :parent_base_url=>"http://129.200.100.159:1400/"}
D, [2012-12-27T13:01:16.349258 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Creating device from device description file info.
D, [2012-12-27T13:01:16.349343 #19095] DEBUG -- : <UPnP::ControlPoint::Device> Description received from 73110860
/home/pini/Sonos/upnp/lib/upnp/control_point/device.rb:257:in `extract_spec_version': undefined method `[]' for nil:NilClass (NoMethodError)
    from /home/pini/Sonos/upnp/lib/upnp/control_point/device.rb:154:in `block in fetch'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/deferrable.rb:48:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/deferrable.rb:48:in `callback'
    from /home/pini/Sonos/upnp/lib/upnp/control_point/device.rb:144:in `fetch'
    from /home/pini/Sonos/upnp/lib/upnp/control_point/device.rb:429:in `extract_device'
    from /home/pini/Sonos/upnp/lib/upnp/control_point/device.rb:383:in `block in extract_devices'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:169:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:169:in `block in map'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:203:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:203:in `block in inject'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:125:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:125:in `block in each'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:218:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/em/iterator.rb:218:in `block in spawn_workers'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:959:in `call'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:959:in `block in run_deferred_callbacks'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:956:in `times'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:956:in `run_deferred_callbacks'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:187:in `run_machine'
    from /var/lib/gems/1.9.1/gems/eventmachine-1.0.0/lib/eventmachine.rb:187:in `run'
    from ./sonos.rb:6:in `<main>'

Any help appreciated. Thanks in advance,

_g.

pini-gh commented 11 years ago

Hi again,

With this patch my snippet reports correctly the two Sonos devices on my network:

diff --git a/lib/upnp/control_point/device.rb b/lib/upnp/control_point/device.rb
index 0332867..d129ea5 100644
--- a/lib/upnp/control_point/device.rb
+++ b/lib/upnp/control_point/device.rb
@@ -254,7 +254,7 @@ module UPnP
       end

       def extract_spec_version
-        "#{@description[:root][:specVersion][:major]}.#{@description[:root][:specVersion][:minor]}"
+        @description[:root] ? "#{@description[:root][:specVersion][:major]}.#{@description[:root][:specVersion][:minor]}" : nil
       end

       def start_service_extraction
@@ -341,7 +341,7 @@ module UPnP
         device_list_hash = if @description.has_key? :root
           log "<#{self.class}> Description has a :root key..."

-          if @description[:root][:device].has_key? :deviceList
+          if @description[:root][:device][:deviceList]
             @description[:root][:device][:deviceList][:device]
           else
             log "<#{self.class}> No child devices to extract."
diff --git a/lib/upnp/control_point/service.rb b/lib/upnp/control_point/service.rb
index 9ca3c9b..19494e9 100644
--- a/lib/upnp/control_point/service.rb
+++ b/lib/upnp/control_point/service.rb
@@ -236,7 +236,8 @@ module UPnP
         end.size
 =end
             @action_list << action
-            define_method_from_action(action[:name].to_sym, action[:argumentList][:argument])
+            args = action[:argumentList] ? action[:argumentList][:argument] : {}
+            define_method_from_action(action[:name].to_sym, args)
           end
         else
           log "<#{self.class}> Got actionList that's not an Array or Hash."

Thanks,

_g.

turboladen commented 11 years ago

Thanks a ton for logging this and finding a solution. I pushed out the changes (although the first change isn't verbatim)--would you mind pulling it down and verifying?

pini-gh commented 11 years ago

Steve Loveless a écrit , Le 27/12/2012 23:16:

Thanks a ton for logging this and finding a solution. I pushed out the changes (although the first change isn't verbatim)--would you mind pulling it down and verifying?

It works, thanks!

_g.