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)[email protected]_;
 $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)[email protected]_;
 $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');

Using Ambient Light Sensor in SB-Radio and SB-Touch

Both the SB Radio and SB Touch have an internal sensor to detect the ambient light level and dim the display when the room is darker or to brighten it when it's light. It's possible to install a background-running script on the player that will regularly update Domoticz with this measured light level (don't worry - it still operates when the player is in standby). This only works meaningfully for a player located in a normally-dark room such as a bathroom with no windows. It can then be used to check if the bathroom is occupied because the light will usually be on when somebody is in there. Use this info e.g. to change the colour of a Hue lamp downstairs so you know when the toilet is occupied upstairs, to start a ventilator if the light in the bathroom is on for a while, or even to autoplay music on the player when somebody turns on the light in the room.

First of all, you should enable SSH login on the SB in question. On the player's own UI, go to:

'Settings --> Advanced --> Remote Login' and make sure 'Enable SSH' is ticked/selected.

Now use a program such as putty or smarTTY to SSH into the player, using username 'root' and default password '1234'. This will log you into the '/root' home directory on the SB. Use smarTTY or a program like Cyberduck to upload the following shell script to that /root directory (full-blown bash is not installed on the SB). Call this file 'domosb.sh' and make sure you have Unix file-endings in it (LF) if you copy/paste from here. When it's copied to the SB, don't forget to 'chmod +x' to make it executable.

 #!/bin/sh
 # script to read the ambient light sensor on a Squeezebox Radio or Touch and send the data to Domoticz
 # it returns a value of 100000 in near darkness and a value of typically ~100-500 when illuminated
 
 # author: philchillbill, 2017. Inspired by https://github.com/luebbers/bathroomd
 
 DOMO="192.168.178.12:8080" 	# IP and port of your Domoticz instance
 PLAYER="Bathroom" 		# Name of the player to appear in the Domoticz log
 LEVEL=395			# idx of the Domoticz 'lux' device to update with the ambient light level
 SWITCH=399			# idx of the on/off switch used to indicate presence
 
 # for the SB Radio use this as the path to the SENSOR data
 SENSOR="/sys/class/i2c-adapter/i2c-1/1-0010/ambient"
 # Note: for the SB Touch use the following instead 
 # SENSOR="/sys/class/i2c-adapter/i2c-0/0-0039/lux"
 
 # say Hello World to the Domoticz Log after waiting a bit for network to be up
 sleep 20
 wget -O /dev/null -q "http://"$DOMO"/json.htm?type=command&param=addlogmessage&message=SB%20"$PLAYER"%20commenced%20ambient%20light%20monitoring."
 
 # read out the sensor every 2 seconds in an infinite loop
 # we only update Domoticz when a meaningful change in Lux occurs (but at least once every 30 minutes to keep the sensor active)
 PREV=0; LOOPS=0; SET=0
 while /bin/true; do
  LOOPS=$(( $LOOPS + 1 )); if [ "$LOOPS" -gt 1000000 ]; then LOOPS=0; fi
  VAL=`cat $SENSOR | tr -d "\n"`
  DELTA=$(($VAL - $PREV))
  if [ "$DELTA" -ge 0 ]; then
   STEP=$DELTA
  else				
   STEP=$((0 - $DELTA))	# step is the absolute-value of the delta in lux
  fi 
  # this updates the sensor-level value shown in the Domoticz 'Lux' meter
  if [ "$STEP" -gt 20 ] || [ $(($LOOPS % 900)) -eq 0 ]; then
   wget -O /dev/null -q "http://"$DOMO"/json.htm?type=command&param=udevice&idx="$LEVEL"&svalue="$VAL""
  fi
  # this sets the on/off switch in Domoticz, with a little hysteresis to prevent the switch 'chattering'
  if [ "$VAL" -lt 400 ] && [ "$SET" -eq 0 ]; then
   wget -O /dev/null -q "http://"$DOMO"/json.htm?type=command&param=switchlight&idx="$SWITCH"&switchcmd=On"
   SET=1
  else
   if [ "$VAL" -gt 500 ] && [ "$SET" -eq 1 ]; then
    wget -O /dev/null -q "http://"$DOMO"/json.htm?type=command&param=switchlight&idx="$SWITCH"&switchcmd=Off"
    SET=0
   fi
  fi
  PREV=$VAL
  sleep 2
 done

The i2c sensor in the SB-Radio produces a value of 100,000 in (almost) darkness and a value of ~100-500 when the lights in the room are on. This script makes sure that Domoticz only gets updated if there is a meaningful change in light level (>20) to mask tiny fluctuations and keep network traffic down. It sends something at least every 30 minutes just to make sure Domoticz doesn't mark it as an offline sensor if it hears nothing for too long.

After transferring the script into the /root folder on the SB you can play around with it first interactively (command: './domosb.sh') to make sure you got it all set up right and also that the thresholds work for you. I created a 'Lux' sensor-type in Domoticz (via Setup-->Hardware-->Dummy-->Create Virtual Sensors) to display the raw sensor data (in the example above it had an idx of 395) and also an on/off switch (with idx of 399) to act as a toggled occupancy-sensor. When you are satisfied that the script works ok you can get it to autostart upon booting of the SB by adding a line to the very end of the '/etc/init.d/rcS' file (vi was the only editor on my SB - there was no nano editor).

 # Add the following to the very end of the file '/etc/init.d/rcS':

 # Start Domoticz Script
 echo "Starting Domoticz script"
 /root/domosb.sh &

Don't forget that '&' at the end or things will hang. The load of running this script makes the SB user interface a tiny bit laggy but does not affect audio playback. You can type 'reboot' to restart the player and get the script auto-running. Of course the data produced by this script is not really a lux value (due to the inversion and high non-linearity) but for our purposes here that's actually irrelevant.