SONOS control from Logic Machine
Example: SONOS HiFi system control from Logic Machine
In LogicMachine with Application Store supported you can use SONOS control app installed from store.
Another way is to control SONOS via scripting. Below are both examples shown.
Sonos control app
Sonos control function
Add the following function into Common functions
- function upnpavcmd(host, port, cmd, param)
- local client, soap, reqs, service, res, err
-
- require('socket')
- client = socket.tcp()
- client:settimeout(3)
-
- -- try connecting to upnp endpoint
- res, err = client:connect(host, port)
- if not res then
- return nil, err
- end
-
- -- guess service name based on command
- if cmd == 'SetVolume' or cmd == 'GetVolume' or cmd == 'SetMute' or cmd == 'GetMute' then
- service = 'RenderingControl'
- else
- service = 'AVTransport'
- end
-
- -- soap envelope
- soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' ..
- '<s:Body>' ..
- '<u:' .. cmd .. ' xmlns:u="urn:schemas-upnp-org:service:' .. service .. ':1">' ..
- '<InstanceID>0</InstanceID>' ..
- (param or '') ..
- '</u:' .. cmd .. '>' ..
- '</s:Body>' ..
- '</s:Envelope>'
-
- -- http request
- reqs = 'POST /MediaRenderer/' .. service .. '/Control HTTP/1.1\r\n' ..
- 'CONNECTION: close\r\n' ..
- 'HOST: ' .. host .. ':' .. port .. '\r\n' ..
- 'CONTENT-LENGTH: ' .. soap:len() .. '\r\n' ..
- 'CONTENT-TYPE: text/xml; charset="utf-8"\r\n' ..
- 'SOAPACTION: "urn:schemas-upnp-org:service:' .. service .. ':1#' .. cmd .. '"\r\n' ..
- '\r\n' .. soap
-
- -- send http request
- res, err = client:send(reqs)
- if not res then
- return nil, err
- end
-
- -- get reply and close connection
- res, err = client:receive('*a')
- client:close()
-
- return res, err
- end
Event-based script which sends volume and other commands to Sonos on specific KNX group address change
- -- ip, port, command, optional param
- upnpavcmd('192.168.1.52', 1400, 'SetVolume', '<Channel>Master</Channel><DesiredVolume>20</DesiredVolume>')
- upnpavcmd('192.168.1.52', 1400, 'Pause')
- upnpavcmd('192.168.1.52', 1400, 'Play', '<Speed>1</Speed>')
- upnpavcmd('192.168.1.52', 1400, 'Next')
- upnpavcmd('192.168.1.52', 1400, 'Previous')
- upnpavcmd('192.168.1.52', 1400, 'SetMute', '<Channel>Master</Channel><DesiredMute>0</DesiredMute>')
- upnpavcmd('192.168.1.52', 1400, 'SetMute', '<Channel>Master</Channel><DesiredMute>1</DesiredMute>')
Scheduled script for searching Sonos players
Created by Joep van den Aker from KNX groep B.V
- require("socket")
- require('socket.http')
-
- local udp = socket.udp()
-
- udp:settimeout(5)
-
- if udp == nil then
- return
- else
- local result, message
- local datagram = "M-SEARCH * HTTP/1.1\r\n"
- .. "HOST: 239.255.255.250:1900\r\n"
- .. "ST: urn:schemas-upnp-org:device:ZonePlayer:1\r\n"
- .. "\r\n"
- result, message = udp:sendto(datagram, "239.255.255.250", 1900)
-
- for i = 1, 254 do
- datagram, message = udp:receivefrom()
- if datagram == nil then
- break
- else
- ip = datagram:match("LOCATION: http://(.-):1400/xml/device_description.xml")
- if ip then -- Fix for other UPNP devices like Philips Hue.
- data = socket.http.request("http://" .. ip .. ":1400/status/zp")
- zonename = data:match([[(.+).+%((%a+)%)]]) -- Fix for Sonos stereo pair
- if zonename == nil then
- zonename = data:match([[(.+)]])
- end
- pair = data:match([[.+%((%a+)%)]])
- if pair == "R" then
- log("Zoneplayer is part of a stereo pair and can't be used as a seperate zone " .. ip)
- elseif pair == "L" then
- log(zonename:gsub("%s", "-") .. " " .. ip)
- storage.set(zonename:gsub("%s", "-"), ip) -- Create storage with zonename and ip address. This can be used for the Sonos scripts (stereo pair)
- elseif pair == nil then
- log(zonename:gsub("%s", "-") .. " " .. ip)
- storage.set(zonename:gsub("%s", "-"), ip) -- Create storage with zonename and ip address. This can be used for the Sonos scripts (seperate player)
- end
- else
- log("No Sonos device: " .. datagram)
- break
- end
- end
- end
- end
-
- udp:close()
Questions/Answers
Q: I am looking for a way to “dim” volume up and down.
A: It’s not possible to set relative volume directly. You have to get the current volume, parse the response and send set volume command afterwards:
- res = upnpavcmd('192.168.1.52', 1400, 'GetVolume', '<Channel>Master</Channel>')
Q: Is it possible to change to a specified Spotify playlist or to change radio channel.
A: Try this for playing radio:
- upnpavcmd('192.168.1.52', 1400, 'SetAVTransportURI', '<CurrentURI>x-rincon-mp3radio://www.abc-lounge.com/listen.m3u</CurrentURI><CurrentURIMetaData/>')