Advertisement
Guest User

SONOS volume control

a guest
Oct 2nd, 2019
6,606
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Param(
  2.     [Parameter(Mandatory=$false)]
  3.     [bool]$auto=$false
  4. )
  5.  
  6. # example file --
  7. # Name,IP,VolumeLimit
  8. # "Sonos1","192.168.0.1",25
  9. # "Sonos2","192.168.0.2",0
  10. $devices = Import-Csv devices.txt
  11.  
  12. # Port that is used for communication (Default = 1400)
  13. $port = 1400
  14.  
  15. #Seconds between checks when running on auto mode
  16. $pollRate = 10
  17.  
  18. #available commands. there are more but these are the only ones I care about
  19. $commands = [ordered]@{
  20.     "1" = "GetVolume"
  21.     "2" = "SetVolume"
  22.     "3" = "Mute"  
  23.     "4" = "Unmute"      
  24. }
  25.  
  26. Function Set-Sonos {
  27.     Param(
  28.         [Parameter(Mandatory=$true,Position=0,valueFromPipeline=$true)]
  29.         [string]
  30.         $action,
  31.  
  32.         [Parameter(Mandatory=$true,Position=1,valueFromPipeline=$true)]
  33.         [string]
  34.         $device,
  35.  
  36.         [Parameter(Mandatory=$false,Position=2,valueFromPipeline=$true)]
  37.         [int]
  38.         $volume,
  39.  
  40.         [Parameter(Mandatory=$false,Position=3,valueFromPipeline=$true)]
  41.         [bool]
  42.         $monitor
  43.     )
  44.  
  45.     $d = $devices[$device-1]
  46.  
  47.     $deviceName = $d.Name
  48.     $sonosIP = $d.IP
  49.     $limit = $d.VolumeLimit
  50.  
  51.     Write-Host "Device: $deviceName, IP: $sonosIP, VolumeLimit: $limit"
  52.  
  53.     $path = "/MediaRenderer/RenderingControl/Control"
  54.     $soapAction = "urn:schemas-upnp-org:service:RenderingControl:1#$action"
  55.     $requiredOptions = @{
  56.                             "SetVolume"= "<DesiredVolume>###DESIRED_VOLUME###</DesiredVolume>";
  57.                             "Mute"="<DesiredMute>1</DesiredMute>";
  58.                             "UnMute"="<DesiredMute>0</DesiredMute>";
  59.                             "GetVolume"="";
  60.                         }
  61.    
  62.     $options = $requiredOptions[$action]
  63.     $envelope = "<s:Envelope xmlns:s=`"http://schemas.xmlsoap.org/soap/envelope/`" s:encodingStyle=`"http://schemas.xmlsoap.org/soap/encoding/`"><s:Body><u:$action xmlns:u=`"urn:schemas-upnp-org:service:RenderingControl:1`"><InstanceID>0</InstanceID><Channel>Master</Channel>$options</u:$action></s:Body></s:Envelope>"    
  64.     $uri = "http://${sonosIP}:$port$path"
  65.    
  66.     # Section for special Actions
  67.     Switch ($action) {
  68.         'setVolume' {
  69.             if($volume -gt $limit) {
  70.                 $volume = $limit
  71.             }
  72.             Write-Host "Set $deviceName Volume $volume"
  73.             $envelope = $envelope.Replace("###DESIRED_VOLUME###", $volume)
  74.         }
  75.     }
  76.  
  77.     # Create SOAP Request
  78.     $soapRequest = [System.Net.WebRequest]::Create($uri)
  79.  
  80.     # Set Headers
  81.     $soapRequest.Accept = 'gzip'
  82.     $soapRequest.Method = 'POST'
  83.     $soapRequest.ContentType = 'text/xml; charset="utf-8"'
  84.     $soapRequest.KeepAlive = $false
  85.     $soapRequest.Headers.Add("SOAPACTION", $soapAction)
  86.  
  87.     # Sending SOAP Request
  88.     $requestStream = $soapRequest.GetRequestStream()
  89.     $envelope = [xml] $envelope
  90.     $envelope.Save($requestStream)
  91.     $requestStream.Close()
  92.  
  93.     # Sending Complete, Get Response
  94.     $response = $soapRequest.GetResponse()
  95.     $responseStream = $response.GetResponseStream()
  96.     $soapReader = [System.IO.StreamReader]($responseStream)
  97.     $returnXml = [Xml] $soapReader.ReadToEnd()
  98.     $responseStream.Close()
  99.     if($action -eq 'GetVolume') {
  100.         $currentVolume = ($returnXml  | select-xml -xpath "//CurrentVolume").toString()
  101.         Write-Host "Current volume of $deviceName is $currentVolume"
  102.         if($monitor -eq $true -and $currentVolume -gt $limit) {
  103.             Write-Host "This is above the volume limit of $limit"
  104.             Set-Sonos "SetVolume" $device $limit
  105.         }
  106.     }
  107. }
  108.  
  109.  
  110. # all this does is continuously poll the devices and sets the volume back to volume limit
  111. # if they go above the limits set above
  112. if($auto) {
  113.  
  114.    while(1) {
  115.        # keep importing the devices so we can change the limits externally
  116.        $devices = Import-Csv devices.txt
  117.        $i = 1;
  118.       foreach($device in $devices) {
  119.         Set-Sonos "GetVolume" $i -monitor $true
  120.         $i++;
  121.        }
  122.        Start-sleep -seconds $pollRate
  123.    }
  124.  
  125. } else {
  126.  
  127.  
  128.     Write-Host "###############################################################"
  129.     Write-Host "#                                                             #"
  130.     Write-Host "#                   SONOS Volume Controller                   #"
  131.     Write-Host "#                                                             #"
  132.     Write-Host "###############################################################"
  133.     Write-Host ""
  134.     Write-Host "Devices:"
  135.     $i = 1;
  136.     foreach($device in $devices) {
  137.         Write-Host "[$i] $($device.Name)"
  138.         $i++
  139.     }
  140.     Write-Host "----------------"
  141.     Write-Host ""
  142.     Write-Host "Options:"
  143.  
  144.     foreach($command in $commands.GetEnumerator()) {
  145.         Write-Host "[$($command.key)] $($command.value)"
  146.     }
  147.  
  148.     Write-Host "----------------"
  149.     Write-Host ""
  150.  
  151.    $device = Read-Host "Please select a device (by number)"
  152.  
  153.    $action = Read-Host "Please select an action (by number)"
  154.  
  155.    $action = $commands["$action"]
  156.  
  157.    if($action -eq "SetVolume") {
  158.      $volume = Read-Host "Enter Volume (1-50)"
  159.    } else {
  160.      $volume = ""
  161.    }
  162.  
  163.    Set-Sonos $action $device $volume
  164.  
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement