For Sonos this is almost done. I created two functions (for now) to control the player and volume of the device.
I created some functions to get to status of the device too, but this is not completely finished at the moment.
The status of the device and volume levels can be fetched without a problem, but I'm not happy yet of the output of what is playing.
This does work, but the way it is shown on the virtual device is not yet perfect. I will share this part when it is finished.
The function to control the player:
Code: Select all
function SonosControl(Device_Sonos_IP,command) -- Play, Stop, Pause, Next, Previous
if (command == "Play") or (command == "Stop") or (command == "Pause") or (command == "Next") or (command == "Previous")
then
Device_Sonos_Port = "1400"
Device_Sonos_url = "/MediaRenderer/AVTransport/Control"
Device_Sonos_Method = "urn:schemas-upnp-org:service:AVTransport:1#" .. command
url = ('curl --header \'SOAPACTION: ' .. Device_Sonos_Method .. '\' --data \'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:' .. command .. ' xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><Speed>1</Speed></u:' .. command .. '></s:Body></s:Envelope>\' http://' .. Device_Sonos_IP .. ':' .. Device_Sonos_Port .. '' .. Device_Sonos_url .. '')
io.popen(url .. ' &')
end
end
Code: Select all
SonosControl("192.168.0.2","Play") -- Starts playing on Sonos device with IP address 192.168.0.2
SonosControl("192.168.0.2","Pause") -- Pauses on Sonos device with IP address 192.168.0.2
SonosControl("192.168.0.2","Stop") -- Sops playing on Sonos device with IP address 192.168.0.2
SonosControl("192.168.0.2","Next") -- Next song on Sonos device with IP address 192.168.0.2
SonosControl("192.168.0.2","Previous") -- Previous on Sonos device with IP address 192.168.0.2
Code: Select all
function SonosVolume(Device_Sonos_IP,command,value) -- Volume -> 0-100, Mute -> On/Off
if ((command == "Volume") or (command == "Mute")) and
((value == "Off") or (value == "On") or ((tonumber(value) >= 0) and (tonumber(value) <= 100)))
then
if (value == "Off") then value = 0
elseif (value == "On") then value = 1
end
Device_Sonos_Port = "1400"
Device_Sonos_url = "/MediaRenderer/RenderingControl/Control"
Device_Sonos_Method = "urn:schemas-upnp-org:service:RenderingControl:1#Set".. command
url = ('curl --header \'SOAPACTION: ' .. Device_Sonos_Method .. '\' --data \'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Set' .. command ..' xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"><InstanceID>0</InstanceID><Channel>Master</Channel><Desired' .. command ..'>' .. value .. '</Desired' .. command ..'></u:Set' .. command ..'></s:Body></s:Envelope>\' http://' .. Device_Sonos_IP .. ':' .. Device_Sonos_Port .. '' .. Device_Sonos_url .. '')
io.popen(url .. ' &')
end
end
Code: Select all
SonosVolume("192.168.0.2","Volume", 15) -- Sets volume to 15% for Sonos device with IP address 192.168.0.2
SonosVolume("192.168.0.2","Mute", "On") -- Mutes Sonos device with IP address 192.168.0.2
SonosVolume("192.168.0.2","Mute", "Off") -- Unmutes Sonos device with IP address 192.168.0.2
Code: Select all
function SonosGetStatus(Device_Sonos_IP)
Device_Sonos_Port = "1400"
Device_Sonos_url = "/MediaRenderer/AVTransport/Control"
Device_Sonos_Method = "urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo"
-- config ---------------------------------------------------------
url = ('curl --header \'SOAPACTION: ' .. Device_Sonos_Method .. '\' --data \'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetTransportInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:GetTransportInfo></s:Body></s:Envelope>\' http://' .. Device_Sonos_IP .. ':' .. Device_Sonos_Port .. '' .. Device_Sonos_url .. '')
local f = io.popen(url)
line = f:read()
i, j = string.find(line, '<CurrentTransportState>')
ValueStart = j+1
i, j = string.find(line, '</CurrentTransportState>')
ValueStop = i-1
SonosResult = string.sub(line, ValueStart, ValueStop)
return SonosResult
end
Code: Select all
print(SonosGetStatus("192.168.0.2") -- Gets player status from Sonos device with IP address 192.168.0.2
Code: Select all
function SonosGetVolume(Device_Sonos_IP,command) -- Volume, Mute
Device_Sonos_Port = "1400"
Device_Sonos_url = "/MediaRenderer/RenderingControl/Control"
Device_Sonos_Method = "urn:schemas-upnp-org:service:RenderingControl:1#Get" .. command
-- config ---------------------------------------------------------
url = ('curl --header \'SOAPACTION: ' .. Device_Sonos_Method .. '\' --data \'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Get'.. command .. ' xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"><InstanceID>0</InstanceID><Channel>Master</Channel></u:Get'.. command .. '></s:Body></s:Envelope>\' http://' .. Device_Sonos_IP .. ':' .. Device_Sonos_Port .. '' .. Device_Sonos_url .. '')
local f = io.popen(url)
line = f:read()
i, j = string.find(line, '<Current' .. command .. '>')
ValueStart = j+1
i, j = string.find(line, '</Current' .. command .. '>')
ValueStop = i-1
SonosResult = string.sub(line, ValueStart, ValueStop)
if (command == "Mute") and (SonosResult == "0") then SonosResult = "Off"
elseif (command == "Mute") and (SonosResult == "1") then SonosResult = "On"
end
return SonosResult
end
Code: Select all
print(SonosGetVolume("192.168.0.2","Volume") -- Gets volume status from Sonos device with IP address 192.168.0.2
print(SonosGetVolume("192.168.0.2","Mute") -- Gets mutestatus from Sonos device with IP address 192.168.0.2
The function to get information are stored in a timed LUA script, which works fine.
Updates are done every minute and for me that is fast enough.
Update with title information:
Code: Select all
function SonosGetTitle(Device_Sonos_IP)
Device_Sonos_Port = "1400"
Device_Sonos_url = "/MediaRenderer/AVTransport/Control"
Device_Sonos_Method = "uurn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"
-- config ---------------------------------------------------------
url = ('curl --header \'SOAPACTION: ' .. Device_Sonos_Method .. '\' --data \'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetPositionInfo></s:Body></s:Envelope>\' http://' .. Device_Sonos_IP .. ':' .. Device_Sonos_Port .. '' .. Device_Sonos_url .. '')
local f = io.popen(url)
line = f:read()
if string.find(line, "spdif") and not string.find(line, "streamContent")
then
-- Result
SonosResult = "Playing from external source"
elseif string.find(line, "dc:creator")
then
-- Title
i, j = string.find(line, 'dc:title>')
ValueStart = j+1
i, j = string.find(line, '</dc:title')
ValueStop = i-1
SonosTitle = string.sub(line, ValueStart, ValueStop)
-- Artist
i, j = string.find(line, 'dc:creator>')
ValueStart = j+1
i, j = string.find(line, '</dc:creator')
ValueStop = i-1
SonosArtist = string.sub(line, ValueStart, ValueStop)
-- Result
SonosResult = SonosTitle .. ' - ' .. SonosArtist
else
--Radio/streaming title
i, j = string.find(line, 'streamContent>')
ValueStart = j+1
i, j = string.find(line, '</r:streamContent')
ValueStop = i-1
SonosTitle = string.sub(line, ValueStart, ValueStop)
-- Radio Station
i, j = string.find(line, 'dc:title>')
ValueStart = j+1
i, j = string.find(line, '</dc:title')
ValueStop = i-1
SonosRadio = string.sub(line, ValueStart, ValueStop)
SonosRadioFirst, SonosRadioLast = SonosRadio:match("([^.]+).([^.]+)")
SonosResult = SonosTitle .. ' @ ' .. SonosRadioFirst
end
--Adding music source
if string.find(line, "mp3radio")
then
SonosResult = SonosResult .. " (Radio)"
elseif string.find(line, "spotify")
then
SonosResult = SonosResult .. " (Spotify)"
end
--Formating string
SonosResult = string.lower(SonosResult)
SonosResult = string.gsub(" "..SonosResult, "%W%l", string.upper):sub(2)
SonosResult = string.gsub(SonosResult, "&Amp;Amp;", "&")
SonosResult = string.gsub(SonosResult, "&Amp;", "&")
SonosResult = string.gsub(SonosResult, "≪", "<")
SonosResult = string.gsub(SonosResult, "≫", ">")
return SonosResult
end