Logitech Media Server

From Domoticz
(Redirected from LMS)
Jump to: navigation, search

Documentation for Logitech Media Server

Introduction

Logitech Media Server (formerly SlimServer, SqueezeCenter and Squeezebox Server) is a streaming audio server supported by Logitech (formerly Slim Devices), developed in particular to support their Squeezebox range of digital audio receivers. Logitech EOL'd the product line in 2012 but the open-source LMS software is still actively developed in a so-called community effort. The latest version can be downloaded here - http://downloads.slimdevices.com/nightly or for Synology NAS devices here - http://server.pinkdot.nl/dsm6/

Logitech Media Server in Domoticz

Logitech Media Server Settings

Your Logitech Media Server must be configured to allow Domoticz to control the attached players. Default port for Web Server connections is 9000 or 9002.

LMS Server.png

Adding Hardware

Add the Logitech Media Server via the Hardware page under Settings. Fill in the IP of your Logitech Media Server and the port you specified.

LMS Hardware.png

Domoticz Settings

Click 'Setup' to see the detected/connected players.

  • Poll interval controls how often Domoticz will attempt to reconnect to the Logitech Media Server to poll the player's status.
  • Ping timeout controls how long Domoticz will try to contact the Logitech Media Server.

LMS Settings.png

Detected Players

If you entered the correct IP & port of your Logitech Media Server, your players will be detected and displayed under Devices. It displays names and MAC-addresses.

Supported Models

The supported models are:

  • Squeezebox 1
  • Squeezebox 2
  • Squeezebox 3
  • Squeezebox Receiver
  • Squeezebox Boom
  • Squeezebox Controller
  • SqueezePlay
  • Squeezebox Radio
  • Squeezebox Touch
  • iPeng iOS App (iPhone & iPad)
  • Max2Play SqueezePlug

Troubleshooting

If your player model is not supported, it will be reported in the logfile. The logfile also reports detected players when starting the Logitech Media Server hardware.

Events and Notifications

Domoticz device events work for Logitech Media Players using both Blockly and LUA.

Events and notifications are triggered for:

On
Off/Disconnected
Play
Pause
Stop

The following actions can be performed by using 'Set' on a Logitech Media Player.

On or Group On Will turn the device on.
Off or Group Off Will turn the device off.
Play Will send a Play command.
Pause Will toggle between Play and Pause.
Stop Will send a Stop command.
Set Volume <0-100> Will set the volume of the player-output.
Play Playlist <name> Will play the playlist with name <name>.
Play Favorites Will play the favorites.

Example:
commandArray['SqueezeBox']='On'
commandArray['SqueezeBox']='Play'
commandArray['SqueezeBox']='Set Volume 30'
commandArray['SqueezeBox']='Play Playlist WakeUpList1'
commandArray['SqueezeBox']='Play Favorites

On Screen Notifications

Domoticz can display notification messages on the screens of certain Logitech Media Players. This is configured via the Notifications tab on the Settings page as shown here:

LMS Notifications.png

Fill in the MAC-address (separated by a semicolon) and the duration that the message will be displayed on the screen (in seconds) The MAC-address of your player(s) can be found in the Hardware-settings of your Logitech Media Server hardware.

Known Issues

  • (Song-)Titles with special characters will show wrong symbols in the logfile.

Work in Progress

  • Add support for Timers (schedule your player to play playlists)

Audio Alerts via Squeezebox Players

The Squeezebox radio and boom players can be used to play audio alerts from Domoticz via the following example perl script. It will work with any type of player but the radio and boom are well-suited as they have their own amplifier and can therefore act autonomously. The script needs to be pre-configured with the MAC addresses of your players, the idx values of the switches corresponding to those players in Domoticz, the URL/port of your Domoticz instance, plus the URL/port where your Logitech Media Server resides.

The basic idea is to first retrieve and save several current parameters from the player: power state, play-mode, repeat-mode, current-playlist (if any), current time-position within currently-playing song (if any), plus the current volume setting. Next we play the desired audio clips (first a 'pre-chime' to get our attention, then the actual alert message audio file which was pre-generated by e.g. text-to-speech software). In doing this we power-on the player if needed (or else just pause the current song if currently playing something) and set the player to play our alerts at a defined volume with no-repeat selected. Finally, we return everything back the way it was prior to the alert(s).

Make sure the CPAN modules in the 'use' list are installed, and of course perl itself (install it first). If you have an issue installing JSON::RPC::Client then use 'cpan install JSON::RPC::Client' instead of the usual 'apt-get install'. Also make sure that a playlist folder is actually defined and not just left blank in your LMS configuration.

Tip: You can copy some of the audio clip files in a Windows /media folder over to your LMS server as pre-alert chimes (Ring06.wav is nice). The spoken messages alerting for things like 'Motion detected in Hallway' or 'Garage door has been left open longer than 10 minutes' can be saved to mp3 files using an online service like Amazon Polly (Note: The British-English voices are less synthetic than the US ones).


#!/usr/bin/perl
 
# Plays an alert sound on a Squeezebox player and subsequently puts everything back the way it was before the sound played.
# Also logs a message to Domoticz. Any offline players are skipped. Author: philchillbill, 2017.
 
use LWP::UserAgent;
use JSON::RPC::Client;
use JSON::XS;
use URI::Escape;
no warnings 'uninitialized';
 
# -------------------------------------------------------------
# Edit the values in these three hashes to match your situation 
 
%players = (
 bathroom 	=> { mac => "00:04:20:1a:ae:e9", idx => 20 },
 bedroom 	=> { mac => "00:04:20:17:04:91", idx => 18 },
 kitchen 	=> { mac => "00:04:20:28:1c:5f", idx => 19 },
 studio 	=> { mac => "00:04:20:2b:d3:84", idx => 17 }, 
 livingroom	=> { mac => "00:04:20:06:d8:3e", idx => 21 }
);
 
%url = (
 domo		=> 'http://192.168.2.12:8080',
 lms		=> 'http://192.168.2.3:9002/jsonrpc.js'
);
 
%dir = (
 alerts 	=> 'file:///volume1/music/alerts'
);
 
# -------------------------------------------------------------
 
sub logMessage {
 my $msg=shift;
 $message=uri_escape($msg);
 $msg_url=$url{domo}.'/json.htm?type=command&param=addlogmessage&message='.$message;
 $ua=LWP::UserAgent->new; $ua->timeout(5); $res=$ua->put($msg_url);
 unless ($res->is_success) { warn "logMessage: ", $res->status_line };
}
 
 
sub checkOnOffline {
 my ($idx, $checkfor)=@_;
 $ua=LWP::UserAgent->new; $ua->timeout(5);
 $retrieve=$ua->get($url{domo}.'/json.htm?type=devices&rid='.$idx);
 $res=$retrieve->decoded_content;
 if ($retrieve->is_success) { $jres = decode_json $res } else { warn "checkOnOffline: ", $retrieve->status_line };
 $state=$$jres{result}[0]->{Status}; # 'On', 'Off', 'Open', 'Closed', 'Disconnected' etc
 if ($state=~m/\b$checkfor\b/) { $status=1 } else { $status=0 };
 return $status;
}
 
 
sub squeezeAlert {
 my ($player, $prechime, $tts)=@_;
 $client=new JSON::RPC::Client;
 $playerid=$players{$player}{mac}; $idx=$players{$player}{idx};
 $offline=&checkOnOffline($idx, 'Disconnected'); if ($offline) { return };
 &logMessage("SQUEEZEALERT: played alert '$tts' on player $player");
 # Get current player state so it can be restored when alert is finished
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['power', '?'] ] });
 if ($res->is_error) { warn "squeezeAlert:", $client->status_line; return };
 $jres = $res->jsontext; $jdata=decode_json $jres; $power=$$jdata{result}{_power};
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mode', '?'] ] });
 $jres = $res->jsontext; $jdata=decode_json $jres; $mode=$$jdata{result}{_mode};
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mixer', 'volume', '?'] ] });
 $jres = $res->jsontext; $jdata=decode_json $jres; $volume=$$jdata{result}{_volume};
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'repeat', '?'] ] });
 $jres = $res->jsontext; $jdata=decode_json $jres; $repeat=$$jdata{result}{_repeat};
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['time', '?'] ] });
 $jres = $res->jsontext; $jdata=decode_json $jres; $time=$$jdata{result}{_time};
 # Pause if currently playing and save current playlist
 $noplay=1;
 if ($mode eq 'play') {
  $noplay=0; $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['pause'] ] });
 }
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'save', 'curplayer', 'silent:1'] ] });
 # Set our alert volume level and make sure repeat is switched off to avoid looping
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mixer', 'volume', '70'] ] });
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'repeat', '0'] ] });
 # Play our alert intro-chime and then the TTS-sound
 unless ($prechime eq 'none') {
  $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'play', $dir{alerts}."/$prechime" ] ] });
  do {
   sleep 1;
   $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mode', '?'] ] });
   $jres = $res->jsontext; $jdata=decode_json $jres; $mode=$$jdata{result}{_mode};
  } while ($mode ne 'stop'); 
 }
 unless ($tts eq 'none') {
  $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'play', $dir{alerts}."/$tts"] ] });
  do {
  sleep 1;
  $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mode', '?'] ] });
  $jres = $res->jsontext; $jdata=decode_json $jres; $mode=$$jdata{result}{_mode};
  } while ($mode ne 'stop');
 }
 # Restore player to previous state, wiping temp playlist in the process
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['mixer', 'volume', $volume] ] });
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'repeat', $repeat] ] });
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['playlist', 'resume', 'curplayer', "noplay:$noplay", 'wipePlaylist:1' ] ] });
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['time', $time ] ] });
 $res = $client->call( $url{lms}, { method => 'slim.request', params => [ $playerid, ['power', $power] ] });
}
 
 
# Now use these subroutines to actually play our notification messages:
 
&squeezeAlert('bathroom', 'Ring06.wav', 'downloadsReady.mp3');
&squeezeAlert('studio', 'Ring06.wav', 'idleDevicePoweredOff.mp3');