Python API?

Posted on
Thu Jun 25, 2015 12:41 pm
DrLove offline
Posts: 260
Joined: Dec 12, 2014
Location: Sweden

Python API?

Hi!

Is it possible to control the Sonos Plugin from Python?
I.e. set a player volume based on some other parameter.

Best regards, L

Love Kull (yes it's my name)
Blog (in Swedish)
Sweden

Posted on
Thu Jul 02, 2015 7:58 am
Colorado4Wheeler offline
User avatar
Posts: 2794
Joined: Jul 20, 2009
Location: Colorado

Re: Python API?

I don't see why not. A quick search on Google found a few folks who are doing it on their Linux box. As long as there is a way to get to the data it can be parsed with Python. Here's one that someone posted that looks like it might be a good starting place for you (I don't personally have a Sonos so I don't know what the API looks like for it):

Code: Select all
#!/usr/bin/env python
#
# Remote control for the Sonos sound system.
#
# Copyright (c) 2014, Matthias Friedrich <matt@mafr.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
from __future__ import print_function
import argparse
import soco

# Hostname or IP address of your speaker.
DEVICE_ADDRESS = '192.168.178.36'

# Speaker volume cutoff for safety :)
MAX_VOLUME = 20


QUEUE_FMT = '{pos:3}. {item.creator} - {item.title}'
STATUS_FMT = '''\
{artist} - {title}
{album}
{position} - {duration}, pos {playlist_position}, vol {vol}\
'''

def mk_parser(subparsers, name, fun):
    parser = subparsers.add_parser(name)
    parser.set_defaults(fun=fun)
    return parser

def play(args):
    if args.track_no is None:
        args.dev.play()
    else:
        args.dev.play_from_queue(args.track_no)

def volume(args):
    if args.volume is not None:
        vol = args.dev.volume + (1 if args.volume == '+' else -1)
        args.dev.volume = min(vol, MAX_VOLUME)
    print(args.dev.volume)

def status(args):
    print(STATUS_FMT.format(
        vol=args.dev.volume,
        **args.dev.get_current_track_info()
    ))

def queue(args):
    for pos, track in enumerate(args.dev.get_queue()):
        print(QUEUE_FMT.format(pos=pos, item=track))


parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
mk_parser(subparsers, 'queue', queue)
mk_parser(subparsers, 'status', status)
mk_parser(subparsers, 'next', lambda a: a.dev.next())
mk_parser(subparsers, 'previous', lambda a: a.dev.previous())
mk_parser(subparsers, 'pause', lambda a: a.dev.pause())

parser_play = subparsers.add_parser('play')
parser_play.add_argument('track_no', metavar='N', type=int, nargs='?',
                        help='Queue track number to play (0-based)')
parser_play.set_defaults(fun=play)

parser_volume = subparsers.add_parser('volume')
parser_volume.add_argument('volume', metavar='X', choices=('+', '-'), nargs='?',
                        help='Increase ("+") or decrese ("-") volume level')
parser_volume.set_defaults(fun=volume)


if __name__ == '__main__':
    device = soco.SoCo(DEVICE_ADDRESS)

    parser.set_defaults(dev=device)
    args = parser.parse_args()
    if hasattr(args, 'fun'):
        args.fun(args)
    else:
        parser.parse_args(['-h'])

# EOF

My Modest Contributions to Indigo:

HomeKit Bridge | Device Extensions | Security Manager | LCD Creator | Room-O-Matic | Smart Dimmer | Scene Toggle | Powermiser | Homebridge Buddy

Check Them Out Here

Posted on
Thu Jul 02, 2015 8:09 am
FlyingDiver online
User avatar
Posts: 7213
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Python API?

Colorado4Wheeler wrote:
I don't see why not. A quick search on Google found a few folks who are doing it on their Linux box. As long as there is a way to get to the data it can be parsed with Python. Here's one that someone posted that looks like it might be a good starting place for you (I don't personally have a Sonos so I don't know what the API looks like for it):


I think he meant controlling Nick's Sonos plugin from a python script running in Indigo.

Nick has a couple examples of doing this on his website: https://vulture.lagaros.com/wiki/pages/ ... tions.html

Code for changing volume would be something like:

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction(deviceId=[deviceId],  "Volume", props={'setting':str(volumeVariable)})

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Thu Jul 02, 2015 8:18 am
Colorado4Wheeler offline
User avatar
Posts: 2794
Joined: Jul 20, 2009
Location: Colorado

Re: Python API?

LOL, oops, my bad, I wasn't paying attention to which forum that question was posted in :lol:

My Modest Contributions to Indigo:

HomeKit Bridge | Device Extensions | Security Manager | LCD Creator | Room-O-Matic | Smart Dimmer | Scene Toggle | Powermiser | Homebridge Buddy

Check Them Out Here

Posted on
Thu Jul 02, 2015 10:21 am
DrLove offline
Posts: 260
Joined: Dec 12, 2014
Location: Sweden

Re: Python API?

FlyingDiver wrote:
Colorado4Wheeler wrote:
I don't see why not. A quick search on Google found a few folks who are doing it on their Linux box. As long as there is a way to get to the data it can be parsed with Python. Here's one that someone posted that looks like it might be a good starting place for you (I don't personally have a Sonos so I don't know what the API looks like for it):


I think he meant controlling Nick's Sonos plugin from a python script running in Indigo.

Nick has a couple examples of doing this on his website: https://vulture.lagaros.com/wiki/pages/ ... tions.html

Code for changing volume would be something like:

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction(deviceId=[deviceId],  "Volume", props={'setting':str(volumeVariable)})


Thanks, exactly what I was looking for!

Love Kull (yes it's my name)
Blog (in Swedish)
Sweden

Posted on
Sun Jul 12, 2015 2:26 pm
DrLove offline
Posts: 260
Joined: Dec 12, 2014
Location: Sweden

Re: Python API?

It does not work for me :/ Not even the example on Nicks homepage:

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction(deviceId=[769403082], "actionPlay")


I get "non-keyword arg after keyword arg" :(
What an I doing wrong here?

Love Kull (yes it's my name)
Blog (in Swedish)
Sweden

Posted on
Sun Jul 12, 2015 2:30 pm
FlyingDiver online
User avatar
Posts: 7213
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Python API?

You're going to have to post the entire script. And the error message should have a line number in it as well.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Jul 12, 2015 2:56 pm
DrLove offline
Posts: 260
Joined: Dec 12, 2014
Location: Sweden

Re: Python API?

That is the whole script actually.
I get the error when trying to compile the script in the script window in an action.
The line that is marked is the last one.

Love Kull (yes it's my name)
Blog (in Swedish)
Sweden

Posted on
Sun Jul 12, 2015 3:10 pm
FlyingDiver online
User avatar
Posts: 7213
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Python API?

Try:

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction(deviceId=769403082, "actionPlay")


That is, remove the square brackets.

joe

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Jul 12, 2015 4:44 pm
matt (support) offline
Site Admin
User avatar
Posts: 21416
Joined: Jan 27, 2003
Location: Texas

Re: Python API?

You need to change the order of the arguments:
Code: Select all
    SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
    if SonosPlugin.isEnabled():
        SonosPlugin.executeAction("actionPlay",  deviceId=769403082)

Image

Posted on
Mon Jul 13, 2015 2:17 am
DrLove offline
Posts: 260
Joined: Dec 12, 2014
Location: Sweden

Re: Python API?

It works!

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction("actionVolume",  props={'setting':str(volVar)}, deviceId=769403082)


Thanks!

Love Kull (yes it's my name)
Blog (in Swedish)
Sweden

Posted on
Fri Oct 09, 2015 6:34 am
Londonmark offline
Posts: 509
Joined: Feb 29, 2012

Re: Python API?

Hi,

I'm also trying some python scripting with this plugin - to replace the queue with a playlist that I would store in a variable. Let's ignore the variable bit for a moment - I'm simply trying to get the playlist to work. Playlist name is Movies, but this script doesn't work.

Code: Select all
SonosPlugin = indigo.server.getPlugin("com.ssi.indigoplugin.Sonos")
if SonosPlugin.isEnabled():
    SonosPlugin.executeAction("actionZP_LIST", deviceId=388657864, props={'setting':"Movies",'mode':"Replace Queue"})


The error I get back is:
    Traceback (most recent call last):
    File "plugin.py", line 136, in actionZP_LIST
    File "/Library/Application Support/Perceptive Automation/Indigo 6/Plugins/Sonos.indigoPlugin/Contents/Server Plugin/Sonos.py", line 955, in actionDirect
    <type 'exceptions.UnboundLocalError'>: local variable 'plist_name' referenced before assignment

Any ideas?

LM

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 5 guests