Skip to content

Instantly share code, notes, and snippets.

@crummy crummy/README.md

Created Oct 17, 2014
Embed
What would you like to do?
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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Owner Author

crummy commented Nov 11, 2014

What service are you playing from?

@wpeterw

This comment has been minimized.

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

This comment has been minimized.

Copy link
Owner 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

This comment has been minimized.

Copy link

fliptrocity commented Sep 3, 2015

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

This comment has been minimized.

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
You can’t perform that action at this time.