Skip to content

Instantly share code, notes, and snippets.

@fhatz
Last active January 23, 2025 19:18
Show Gist options
  • Select an option

  • Save fhatz/f5645682f3f1d73583035980a921f59b to your computer and use it in GitHub Desktop.

Select an option

Save fhatz/f5645682f3f1d73583035980a921f59b to your computer and use it in GitHub Desktop.
Samsung Multiroom - Console client
#! /bin/bash
# Author: F. Hatz
# based on 'https://github.com/bacl/WAM_API_DOC'
# start with MultiRoom.sh search (search for speakers)
# or with MultiRoom.sh Speaker-IP UUID OBJECTID [OBJECTID OBJECTID ...] volume
# or with MultiRoom.sh Speaker-IP fav1/fav2/fav3/radio1/radio2/radio3 volume
# or with MultiRoom.sh Speaker-IP play/pause/stop (song: play/pause radio: stop)
# or with MultiRoom.sh Speaker-IP next/previous
# or with MultiRoom.sh Speaker-IP mute on/off
# or with MultiRoom.sh Speaker-IP volume
# or with MultiRoom.sh Speaker-IP show title/id (show information of played song)
# or with MultiRoom.sh Speaker-IP list (show uuid and objectid's of actual playlist)
# or with MultiRoom.sh Speaker-IP presets all/fav1/fav2/fav3/radio1/radio2/radio3
# or with MultiRoom.sh Speaker-IP name (speaker name)
# or with MultiRoom.sh Speaker-IP soundshare (set input to soundshare = TV-connect)
PATH=/sbin:/usr/sbin:/bin:/usr/bin
CURL="/usr/bin/curl"
PORT="55001"
COMMAND=".."
VOLUME=".."
SPEAKER=".."
declare -a OBJECTID
OBJ_NUM=0
VAR_NUM=0
for i in "$@"; do
VAR_NUM=$(($VAR_NUM+1))
if [ $VAR_NUM -eq 1 ] 2>/dev/null ; then
SPEAKER=$i
elif [ $VAR_NUM -eq 2 ] ; then
if [ "$i" -eq "$i" ] 2>/dev/null ; then
COMMAND="volume"
VOLUME=$i
elif [ $(echo ${#i}) -gt 10 ] 2>/dev/null ; then
COMMAND="song"
UUID=$i
else
COMMAND="$i"
fi
elif [ $VAR_NUM -eq $# ] 2>/dev/null ; then
if [ $(echo ${#i}) -lt 10 ] 2>/dev/null ; then
VOLUME="$i"
else
OBJECTID["$OBJ_NUM"]="$i"
OBJ_NUM=$(($OBJ_NUM+1))
fi
else
OBJECTID["$OBJ_NUM"]="$i"
OBJ_NUM=$(($OBJ_NUM+1))
fi
done
if [ $SPEAKER == "search" ] ; then
IP=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
IP=${IP%.*}
IP="$IP."
IFS_BACK=$IFS
IFS=$'\n'
for i in {1..254}; do
T_IP=$(echo "$IP$i")
MSG="</dev/tcp/$T_IP/55001"
timeout 0.2 bash -c $MSG 2>/dev/null
if [ $? -eq 0 ]; then
MSG="http://$T_IP:55001/UIC?cmd=%3Cname%3EGetSpkName%3C/name%3E"
SPK_NAME=$($CURL $MSG -s)
SPK_NAME=($(echo "$SPK_NAME" | grep -oP "(?<=<spkname>)[^/]+"))
SPK_NAME=${SPK_NAME##*[}
SPK_NAME=${SPK_NAME%%]*}
echo "$T_IP: $SPK_NAME"
fi
done
IFS=$IFS_BACK
exit 1
fi
if [ "$VOLUME" -eq "$VOLUME" ] 2>/dev/null
then
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3ESetVolume%3C/name%3E%3Cp%20type=%22dec%22%20name=%22volume%22%20val=%22$VOLUME%22/%3E"
$CURL $MSG -s >/dev/null
fi
case $COMMAND in
stop)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlaybackControl%3C/name%3E%3Cp%20type=%22str%22%20name=%22playbackcontrol%22%20val=%22stop%22/%3E"
$CURL $MSG -s >/dev/null
;;
pause)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cpwron%3Eon%3C/pwron%3E%3Cname%3ESetPlaybackControl%3C/name%3E%3Cp%20type=%22str%22%20name=%22playbackcontrol%22%20val=%22pause%22/%3E"
$CURL $MSG -s >/dev/null
;;
play)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cpwron%3Eon%3C/pwron%3E%3Cname%3ESetPlaybackControl%3C/name%3E%3Cp%20type=%22str%22%20name=%22playbackcontrol%22%20val=%22resume%22/%3E"
$CURL $MSG -s >/dev/null
;;
next)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cpwron%3Eon%3C/pwron%3E%3Cname%3ESetTrickMode%3C/name%3E%3Cp%20type=%22str%22%20name=%22trickmode%22%20val=%22next%22/%3E"
$CURL $MSG -s >/dev/null
;;
previous)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cpwron%3Eon%3C/pwron%3E%3Cname%3ESetTrickMode%3C/name%3E%3Cp%20type=%22str%22%20name=%22trickmode%22%20val=%22previous%22/%3E"
$CURL $MSG -s >/dev/null
;;
mute)
if [ "$VOLUME" == ".." ] 2>/dev/null ; then
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3EGetMute%3C/name%3E"
MUTE=$($CURL $MSG -s)
MUTE=($(echo "$MUTE" | grep -oP "(?<=<mute>)[^<]+"))
if [ $MUTE == "off" ]; then
VOLUME="on"
else
VOLUME="off"
fi
fi
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cpwron%3Eon%3C/pwron%3E%3Cname%3ESetMute%3C/name%3E%3Cp%20type=%22str%22%20name=%22mute%22%20val=%22$VOLUME%22/%3E"
$CURL $MSG -s >/dev/null
echo "Mute $VOLUME"
;;
fav1)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%220%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%221%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Favorite 1"
;;
fav2)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%221%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%221%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Favorite 2"
;;
fav3)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%222%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%221%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Favorite 3"
;;
radio1)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%223%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%220%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Radio 1"
;;
radio2)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%224%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%220%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Radio 1"
;;
radio3)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3ESetPlayPreset%3C/name%3E%3Cp%20type=%22dec%22%20name=%22presetindex%22%20val=%225%22/%3E%3Cp%20type=%22dec%22%20name=%22presettype%22%20val=%220%22/%3E"
$CURL $MSG -s >/dev/null
echo "Play Radio 1"
;;
song)
count=0
for i in ${!OBJECTID[*]} ; do
ID="${OBJECTID[$i]}"
if [ "$i" -eq 0 ] 2>/dev/null ; then
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3ESetNewPlaylistPlaybackControl%3C%2Fname%3E%3Cp%20type%3D%22dec%22%20name%3D%22selcount%22%20val%3D%221%22%2F%3E%3Cp%20type%3D%22dec%22%20name%3D%22playtime%22%20val%3D%220%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22type%22%20val%3D%22new%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22device_udn%22%20val%3D%22uuid%3A$UUID%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22objectid%22%20val%3D%22$ID%22%2F%3E%3Cp%20type%3D%22cdata%22%20name%3D%22songtitle%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5BSong%201%5D%5D%3E%3C%2Fp%3E%3Cp%20type%3D%22cdata%22%20name%3D%22thumbnail%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5B%5D%5D%3E%3C%2Fp%3E%3Cp%20type%3D%22cdata%22%20name%3D%22artist%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5B%5D%5D%3E%3C%2Fp%3E"
$CURL $MSG -s >/dev/null
else
SONG_N=$(($i+1))
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3EAddSongsToMultiQueue%3C%2Fname%3E%3Cp%20type%3D%22dec%22%20name%3D%22count%22%20val%3D%221%22%2F%3E%3Cp%20type%3D%22dec%22%20name%3D%22totalcount%22%20val%3D%221%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22position%22%20val%3D%22last%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22device_udn%22%20val%3D%22uuid%3A$UUID%22%2F%3E%3Cp%20type%3D%22str%22%20name%3D%22objectid%22%20val%3D%22$ID%22%2F%3E%3Cp%20type%3D%22cdata%22%20name%3D%22songtitle%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5BSong%20$SONG_N%5D%5D%3E%3C%2Fp%3E%3Cp%20type%3D%22cdata%22%20name%3D%22thumbnail%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5B%5D%5D%3E%3C%2Fp%3E%3Cp%20type%3D%22cdata%22%20name%3D%22artist%22%20val%3D%22empty%22%3E%3C!%5BCDATA%5B%5D%5D%3E%3C%2Fp%3E"
$CURL $MSG -s >/dev/null
fi
count=$(( $count + 1 ))
done
if [ "$count" -eq 1 ] ; then
echo "Play Song"
elif [ "$count" -gt 1 ] ; then
echo "Play List with $count songs"
fi
;;
volume)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3ESetVolume%3C/name%3E%3Cp%20type=%22dec%22%20name=%22volume%22%20val=%22$VOLUME%22/%3E"
$CURL $MSG -s >/dev/null
echo "Volume $VOLUME"
;;
show)
IFS_BACK=$IFS
IFS=$'\n'
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3EGetMusicInfo%3C/name%3E"
SONG=$($CURL $MSG -s)
SONG_T=($(echo "$SONG" | grep -oP "(?<=<title>)[^/]+"))
if [ -n "${SONG_T}" ]; then
SONG_T=${SONG_T##*[}
SONG_T=${SONG_T%%]*}
SONG_A=($(echo "$SONG" | grep -oP "(?<=<artist>)[^/]+"))
SONG_A=${SONG_A##*[}
SONG_A=${SONG_A%%]*}
SONG_UUID=($(echo "$SONG" | grep -oP "(?<=<device_udn>)[^<]+"))
SONG_UUID=${SONG_UUID##*:}
SONG_OID=($(echo "$SONG" | grep -oP "(?<=<objectid>)[^/]+"))
SONG_OID=${SONG_OID##*[}
SONG_OID=${SONG_OID%%]*}
if [ $VOLUME == "id" ] ; then
echo "$SONG_UUID $SONG_OID"
exit 1
elif [ $VOLUME == "title" ] ; then
echo "$SONG_T - $SONG_A"
exit 1
else
echo "$SONG_T - $SONG_A (uuid: $SONG_UUID / objectid: $SONG_OID)"
fi
fi
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3EGetRadioInfo%3C/name%3E"
RADIO=$($CURL $MSG -s)
RADIO_T=($(echo "$RADIO" | grep -oP "(?<=<title>)[^<]+"))
if [ -n "${RADIO_T}" ]; then
echo "$RADIO_T"
fi
IFS=$IFS_BACK
;;
presets)
MSG="http://$SPEAKER:$PORT/CPM?cmd=%3Cname%3EGetPresetList%3C/name%3E%3Cp%20type=%22dec%22%20name=%22startindex%22%20val=%220%22/%3E%3Cp%20type=%22dec%22%20name=%22listcount%22%20val=%22100%22/%3E"
PRESETS=$($CURL $MSG -s)
IFS_BACK=$IFS
IFS=$'\n'
TITLES=($(echo "$PRESETS" | grep -oP "(?<=<title>)[^<]+"))
if [ $VOLUME == "fav1" ]; then
echo "${TITLES[0]}"
elif [ $VOLUME == "fav2" ]; then
echo "${TITLES[1]}"
elif [ $VOLUME == "fav3" ]; then
echo "${TITLES[2]}"
elif [ $VOLUME == "radio1" ]; then
echo "${TITLES[3]}"
elif [ $VOLUME == "radio2" ]; then
echo "${TITLES[4]}"
elif [ $VOLUME == "radio3" ]; then
echo "${TITLES[5]}"
elif [ $VOLUME == "radio4" ]; then
echo "${TITLES[6]}"
else
echo "---------Favorites---------"
for i in ${!TITLES[*]}
do
if [ $i \= 3 ]
then
echo "---------Radio-------------"
fi
if [ $i \< 3 ] 2>/dev/null
then
let j=$i+1
echo "Favorite $j: ${TITLES[$i]}"
else
let j=$i-2
echo "Preset $j: ${TITLES[$i]}"
fi
done
fi
IFS=$IFS_BACK
;;
list)
IFS_BACK=$IFS
IFS=$'\n'
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3EGetCurrentMultiQueuelist%3C/name%3E%3Cp%20type=%22dec%22%20name=%22liststartindex%22%20val=%220%22/%3E%3Cp%20type=%22dec%22%20name=%22listcount%22%20val=%22100%22/%3E"
LIST=$($CURL $MSG -s)
UUID=($(echo "$LIST" | grep -oP "(?<=uuid:)[^<]+"))
TITLES=($(echo "$LIST" | grep -oP "(?<=object_id)[^>]+"))
LIST="$UUID"
for i in ${!TITLES[*]} ; do
T=${TITLES[$i]}
T_L=${#T}-3
T=${T:2:T_L}
LIST="$LIST $T"
done
echo "$LIST"
IFS=$IFS_BACK
;;
name)
IFS_BACK=$IFS
IFS=$'\n'
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3EGetSpkName%3C/name%3E"
SPK_NAME=$($CURL $MSG -s)
SPK_NAME=($(echo "$SPK_NAME" | grep -oP "(?<=<spkname>)[^>]+"))
SPK_NAME=${SPK_NAME##*[}
SPK_NAME=${SPK_NAME%%]*}
echo "$SPK_NAME"
IFS=$IFS_BACK
;;
soundshare)
MSG="http://$SPEAKER:$PORT/UIC?cmd=%3Cname%3ESetFunc%3C/name%3E%3Cp%20type=%22str%22%20name=%22function%22%20val=%22soundshare%22/%3E"
$CURL $MSG -s >/dev/null
echo "Input: TV-Connect"
;;
*)
echo "Usage: Error - $COMMAND" >&2
;;
esac
exit 1
@fhatz
Copy link
Copy Markdown
Author

fhatz commented May 6, 2017

No streaming is not possible as (up to now). Samsung speakers only accept a uuid and objectid (from upnp server) as input. A local mp3-file cannot be streamed. Except you install e.g. miniDLNA and lookup the correct uuid and objectid of the file.

Best

Florian

@fhatz
Copy link
Copy Markdown
Author

fhatz commented May 6, 2017

Major update of the script. Playlists are now supported.

@Nicxe
Copy link
Copy Markdown

Nicxe commented May 25, 2017

I have been searching for a way to integrate my Samsung Multiroom in to my Home Assistant setup but I don't have the coding knowledge. But I think that this is the best I have found so far. What is this for code, what dose it do?

Copy link
Copy Markdown

ghost commented Sep 2, 2017

Thanks for this!

@Sloan42
Copy link
Copy Markdown

Sloan42 commented Nov 17, 2017

Hi, thanks for this great work.
Is there a way to send an "off" command to the speakers?
Most of the commands also works with HWH750 Soundbar. But when its off, and i switch "input" (e.g. from soundshare to optical), the soundbar dont turn on. Is there a way to send "on" command? I do this at moment with speakercontrol, but then i here radio for just 2 seconds.

@fhatz
Copy link
Copy Markdown
Author

fhatz commented Nov 17, 2017

Would mute on/off do the trick?

@Sloan42
Copy link
Copy Markdown

Sloan42 commented Nov 17, 2017

No, doesn't work

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