Skip to content

Instantly share code, notes, and snippets.

@crummy
Created October 17, 2014 22:00
Show Gist options
  • Save crummy/6e3973695d7b8adb672f to your computer and use it in GitHub Desktop.
Save crummy/6e3973695d7b8adb672f to your computer and use it in GitHub Desktop.
Sonos Now Playing

Description

A Dashing widget that searches for a Sonos device that is currently playing music, and displays Now Playing information and album artwork.

Utilises soffe's Sonos controller.

Dependencies

Please add the following lines to your gemfile:

require 'rubygems'
require 'sonos'

Installation

Place sonos.rb in /jobs.

Edit your dashboard and add these widgets:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="nowplaying" data-view="Text" data-title="NOW PLAYING" data-text="Artist - Track"></div>
</li>

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="albumart" data-view="Image" data-title="Album Name"></div>
</li>

Screenshot

screenshot

require 'rubygems'
require 'sonos'
def send_transport_message(name, player, part = '<Speed>1</Speed>')
@transport_client ||= Savon.client endpoint: "http://#{player.ip}:#{Sonos::PORT}#{TRANSPORT_ENDPOINT}", namespace: Sonos::NAMESPACE, log: Sonos.logging_enabled
action = "#{TRANSPORT_XMLNS}##{name}"
message = %Q{<u:#{name} xmlns:u="#{TRANSPORT_XMLNS}"><InstanceID>0</InstanceID>#{part}</u:#{name}>}
@transport_client.call(name, soap_action: action, message: message)
end
# Get information about the currently playing track.
# @return [Hash] information about the current track.
def get_now_playing(player)
return nil if player == nil
response = send_transport_message('GetPositionInfo', player)
body = response.body[:get_position_info_response]
doc = Nokogiri::XML(body[:track_meta_data])
# No music
return nil if doc.children.length == 0
art_path = doc.xpath('//upnp:albumArtURI').inner_text
# TODO: No idea why this is necessary. Maybe its a Nokogiri thing
art_path.sub!('/getaa?s=1=x-sonos-http', '/getaa?s=1&u=x-sonos-http')
{
title: doc.xpath('//dc:title').inner_text,
artist: doc.xpath('//dc:creator').inner_text,
album: doc.xpath('//upnp:album').inner_text,
info: doc.xpath('//r:streamContent').inner_text,
queue_position: body[:track],
track_duration: body[:track_duration],
current_position: body[:rel_time],
uri: body[:track_uri],
album_art: "http://#{player.ip}:#{Sonos::PORT}#{art_path}"
}
end
TRANSPORT_ENDPOINT = '/MediaRenderer/AVTransport/Control'
TRANSPORT_XMLNS = 'urn:schemas-upnp-org:service:AVTransport:1'
system = Sonos::System.new
player = nil
system.speakers.each do |speaker|
if speaker.is_playing?
player = speaker
break
end
end
SCHEDULER.every '10s' do
metadata = get_now_playing(player)
if metadata and player
send_event("albumart", { image: metadata[:album_art] })
send_event("nowplaying", { text: metadata[:artist] + ' - ' + metadata[:title], moreinfo: player.name })
elsif player
send_event("albumart", { image: 'assets/sonoslogo.png' })
send_event("nowplaying", { text: "Nothing playing in " + player.name })
else
send_event("albumart", { image: 'assets/sonoslogo.png' })
send_event("nowplaying", { text: "Unable to connect to any player" })
end
end
@wpeterw
Copy link

wpeterw commented Nov 10, 2014

It does not display the albumart. When I look at the properties of the, broken, image I see that the url looks like: http://ipofthedasboard/assets/hhtp://sonosplayerip/etcetc/.. How do i strip the first part from this url ? (the part after /assets/ points to the correct location).

@crummy
Copy link
Author

crummy commented Nov 11, 2014

What service are you playing from?

@wpeterw
Copy link

wpeterw commented Nov 11, 2014

I'm playing from Deezer. The albumart url is correct but "somewhere" it is prefixed with the url to the dashing server: http://192.168.178.22/assets.

@crummy
Copy link
Author

crummy commented Nov 11, 2014

Ah, I forgot I tweaked the image widget. You can fix this by editing image.html and removing prepend '/assets' or adding another widget, identical to the existing image widget but for that change, and use that instead.

@fliptrocity
Copy link

Any insight on how I can get this to point to a specific bridge rather than it picking a random one on the network?

@stigert
Copy link

stigert commented Mar 7, 2019

This isn't working for me. The dashboard won't load at all after installing this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment