soco.events module

Classes to handle Sonos UPnP Events and Subscriptions.

The Subscription class from this module will be used in soco.services unless config.EVENTS_MODULE is set to point to soco.events_twisted, in which case soco.events_twisted.Subscription will be used. See the Example in soco.events_twisted.

Example

Run this code, and change your volume, tracks etc:

from queue import Empty

import logging
logging.basicConfig()
import soco
from pprint import pprint
from soco.events import event_listener
# pick a device at random and use it to get
# the group coordinator
device = soco.discover().pop().group.coordinator
print (device.player_name)
sub = device.renderingControl.subscribe()
sub2 = device.avTransport.subscribe()

while True:
    try:
        event = sub.events.get(timeout=0.5)
        pprint (event.variables)
    except Empty:
        pass
    try:
        event = sub2.events.get(timeout=0.5)
        pprint (event.variables)
    except Empty:
        pass

    except KeyboardInterrupt:
        sub.unsubscribe()
        sub2.unsubscribe()
        event_listener.stop()
        break
class soco.events.EventServer(server_address, RequestHandlerClass, bind_and_activate=True)[source]

A TCP server which handles each new request in a new thread.

Constructor. May be extended, do not override.

class soco.events.EventNotifyHandler(*args, **kwargs)[source]

Handles HTTP NOTIFY Verbs sent to the listener server. Inherits from soco.events_base.EventNotifyHandlerBase.

do_NOTIFY()[source]

Serve a NOTIFY request by calling handle_notification with the headers and content.

log_message(fmt, *args)[source]

Log an arbitrary message.

This is used by all other logging functions. Override it if you have specific logging wishes.

The first argument, FORMAT, is a format string for the message to be logged. If the format string contains any % escapes requiring parameters, they should be specified as subsequent arguments (it’s just like printf!).

The client ip and current date/time are prefixed to every message.

Unicode control characters are replaced with escaped hex before writing the output to stderr.

class soco.events.EventServerThread(server)[source]

The thread in which the event listener server will run.

Parameters

address (tuple) – The (ip, port) address on which the server should listen.

stop_flag

Used to signal that the server should stop.

Type

threading.Event

server

The (ip, port) address on which the server is configured to listen.

Type

tuple

run()[source]

Start the server

Handling of requests is delegated to an instance of the EventNotifyHandler class.

stop()[source]

Stop the server.

class soco.events.EventListener[source]

The Event Listener.

Runs an http server in a thread which is an endpoint for NOTIFY requests from Sonos devices. Inherits from soco.events_base.EventListenerBase.

listen(ip_address)[source]

Start the event listener listening on the local machine at port 1400 (default). If this port is unavailable, the listener will attempt to listen on the next available port, within a range of 100.

Make sure that your firewall allows connections to this port.

This method is called by soco.events_base.EventListenerBase.start

Parameters

ip_address (str) – The local network interface on which the server should start listening.

Returns

requested_port_number. Included for compatibility with soco.events_twisted.EventListener.listen

Return type

int

Note

The port on which the event listener listens is configurable. See config.EVENT_LISTENER_PORT

stop_listening(address)[source]

Stop the listener.

class soco.events.Subscription(service, event_queue=None)[source]

A class representing the subscription to a UPnP event. Inherits from soco.events_base.SubscriptionBase.

Parameters
  • service (Service) – The SoCo Service to which the subscription should be made.

  • event_queue (Queue) – A queue on which received events will be put. If not specified, a queue will be created and used.

subscribe(requested_timeout=None, auto_renew=False, strict=True)[source]

Subscribe to the service.

If requested_timeout is provided, a subscription valid for that number of seconds will be requested, but not guaranteed. Check timeout on return to find out what period of validity is actually allocated.

This method calls events_base.SubscriptionBase.subscribe.

Note

SoCo will try to unsubscribe any subscriptions which are still subscribed on program termination, but it is good practice for you to clean up by making sure that you call unsubscribe() yourself.

Parameters
  • requested_timeout (int, optional) – The timeout to be requested.

  • auto_renew (bool, optional) – If True, renew the subscription automatically shortly before timeout. Default False.

  • strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

renew(requested_timeout=None)[source]

Renew the event subscription. You should not try to renew a subscription which has been unsubscribed, or once it has expired.

This method calls events_base.SubscriptionBase.renew.

Parameters
  • requested_timeout (int, optional) – The period for which a renewal request should be made. If None (the default), use the timeout requested on subscription.

  • is_autorenew (bool, optional) – Whether this is an autorenewal. Default ‘False’.

  • strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

unsubscribe()[source]

Unsubscribe from the service’s events. Once unsubscribed, a Subscription instance should not be reused

This method calls events_base.SubscriptionBase.unsubscribe.

Parameters

strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

soco.events_base module

Base classes used by soco.events and soco.events_twisted.

soco.events_base.parse_event_xml(xml_event)[source]

Parse the body of a UPnP event.

Parameters

xml_event (bytes) – bytes containing the body of the event encoded with utf-8.

Returns

A dict with keys representing the evented variables. The relevant value will usually be a string representation of the variable’s value, but may on occasion be:

  • a dict (eg when the volume changes, the value will itself be a dict containing the volume for each channel: {'Volume': {'LF': '100', 'RF': '100', 'Master': '36'}})

  • an instance of a DidlObject subclass (eg if it represents track metadata).

  • a SoCoFault (if a variable contains illegal metadata)

Return type

dict

class soco.events_base.Event(sid, seq, service, timestamp, variables=None)[source]

A read-only object representing a received event.

The values of the evented variables can be accessed via the variables dict, or as attributes on the instance itself. You should treat all attributes as read-only.

Parameters
  • sid (str) – the subscription id.

  • seq (str) – the event sequence number for that subscription.

  • timestamp (str) – the time that the event was received (from Python’s time.time function).

  • service (str) – the service which is subscribed to the event.

  • variables (dict, optional) – contains the {names: values} of the evented variables. Defaults to None. The values may be SoCoFault objects if the metadata could not be parsed.

Raises

AttributeError – Not all attributes are returned with each event. An AttributeError will be raised if you attempt to access as an attribute a variable which was not returned in the event.

Example

>>> print event.variables['transport_state']
'STOPPED'
>>> print event.transport_state
'STOPPED'
class soco.events_base.EventNotifyHandlerBase[source]

Base class for soco.events.EventNotifyHandler and soco.events_twisted.EventNotifyHandler.

handle_notification(headers, content)[source]

Handle a NOTIFY request by building an Event object and sending it to the relevant Subscription object.

A NOTIFY request will be sent by a Sonos device when a state variable changes. See the UPnP Spec §4.3 [pdf] for details.

Parameters
  • headers (dict) – A dict of received headers.

  • content (str) – A string of received content.

Note

Each of the soco.events and the soco.events_twisted modules has a subscriptions_map object which keeps a record of Subscription objects. The get_subscription method of the subscriptions_map object is used to look up the subscription to which the event relates. When the Event Listener runs in a thread (the default), a lock is used by this method for thread safety. The send_event method of the relevant Subscription will first check to see whether the callback variable of the Subscription has been set. If it has been and is callable, then the callback will be called with the Event object. Otherwise, the Event object will be sent to the event queue of the Subscription object. The callback variable of the Subscription object is intended for use only if soco.events_twisted is being used, as calls to it are not threadsafe.

This method calls the log_event method, which must be overridden in the class that inherits from this class.

class soco.events_base.EventListenerBase[source]

Base class for soco.events.EventListener and soco.events_twisted.EventListener.

is_running

Indicates whether the server is currently running

Type

bool

requested_port_number

Port on which to listen.

Type

int

start(any_zone)[source]

Start the event listener listening on the local machine.

Parameters

any_zone (SoCo) – Any Sonos device on the network. It does not matter which device. It is used only to find a local IP address reachable by the Sonos net.

stop()[source]

Stop the Event Listener.

listen(ip_address)[source]

Start the event listener listening on the local machine. This method is called by start.

Parameters

ip_address (str) – The local network interface on which the server should start listening.

Returns

The port on which the server is listening.

Return type

int

Note

This method must be overridden in the class that inherits from this class.

stop_listening(address)[source]

Stop the listener.

Note

This method must be overridden in the class that inherits from this class.

class soco.events_base.SubscriptionBase(service, event_queue=None)[source]

Base class for soco.events.Subscription and soco.events_twisted.Subscription

Parameters
  • service (Service) – The SoCo Service to which the subscription should be made.

  • event_queue (Queue) – A queue on which received events will be put. If not specified, a queue will be created and used.

sid

A unique ID for this subscription

Type

str

timeout

The amount of time in seconds until the subscription expires.

Type

int

is_subscribed

An indication of whether the subscription is subscribed.

Type

bool

events

The queue on which events are placed.

Type

Queue

requested_timeout

The period (seconds) for which the subscription is requested

Type

int

auto_renew_fail

an optional function to be called if an exception occurs upon autorenewal. This will be called with the exception (or failure, when using soco.events_twisted) as its only parameter. This function must be threadsafe (unless soco.events_twisted is being used).

Type

function

subscribe(requested_timeout=None, auto_renew=False)[source]

Subscribe to the service.

If requested_timeout is provided, a subscription valid for that number of seconds will be requested, but not guaranteed. Check timeout on return to find out what period of validity is actually allocated.

Note

SoCo will try to unsubscribe any subscriptions which are still subscribed on program termination, but it is good practice for you to clean up by making sure that you call unsubscribe() yourself.

Parameters
  • requested_timeout (int, optional) – The timeout to be requested.

  • auto_renew (bool, optional) – If True, renew the subscription automatically shortly before timeout. Default False.

renew(requested_timeout=None)[source]

Renew the event subscription. You should not try to renew a subscription which has been unsubscribed, or once it has expired.

Parameters
  • requested_timeout (int, optional) – The period for which a renewal request should be made. If None (the default), use the timeout requested on subscription.

  • is_autorenew (bool, optional) – Whether this is an autorenewal.

unsubscribe()[source]

Unsubscribe from the service’s events. Once unsubscribed, a Subscription instance should not be reused

send_event(event)[source]

Send an Event to self.callback or self.events. If self.callback is set and is callable, it will be called with the Event as the only parameter. Otherwise the Event will be sent to self.events. As self.callback is not threadsafe, it should be set only if soco.events_twisted.Subscription is being used.

Parameters

event (Event) – The Event to send to self.callback or self.events.

property time_left

The amount of time left until the subscription expires (seconds) If the subscription is unsubscribed (or not yet subscribed), time_left is 0.

Type

int

class soco.events_base.SubscriptionsMap[source]

Maintains a mapping of sids to soco.events.Subscription instances and the thread safe lock to go with it. Registers each subscription to be unsubscribed at exit.

SubscriptionsMapTwisted inherits from this class.

subscriptions

Thread safe mapping. Used to store a mapping of sid to subscription

Type

weakref.WeakValueDictionary

subscriptions_lock

for use with subscriptions

Type

threading.Lock

register(subscription)[source]

Register a subscription by updating local mapping of sid to subscription and registering it to be unsubscribed at exit.

Parameters

subscription (soco.events.Subscription) – the subscription to be registered.

unregister(subscription)[source]

Unregister a subscription by updating local mapping of sid to subscription instances.

Parameters

subscription (soco.events.Subscription) – the subscription to be unregistered.

When using soco.events_twisted, an instance of soco.events_twisted.Subscription will be unregistered.

get_subscription(sid)[source]

Look up a subscription from a sid.

Args:

sid(str): The sid from which to look up the subscription.

Returns:

soco.events.Subscription: The subscription relating to that sid.

When using soco.events_twisted, an instance of soco.events_twisted.Subscription will be returned.

property count

The number of active subscriptions.

Type

int

soco.events_base.get_listen_ip(ip_address)[source]

Find the listen ip address.

soco.events_twisted module

Classes to handle Sonos UPnP Events and Subscriptions.

The Subscription class from this module will be used in soco.services if config.EVENTS_MODULE is set to point to this module.

Example

Run this code, and change your volume, tracks etc:

from __future__ import print_function
import logging
logging.basicConfig()
import soco
from pprint import pprint

from soco import events_twisted
soco.config.EVENTS_MODULE = events_twisted
from twisted.internet import reactor

def print_event(event):
    try:
        pprint (event.variables)
    except Exception as e:
        pprint ('There was an error in print_event:', e)

def main():
    # pick a device at random and use it to get
    # the group coordinator
    device = soco.discover().pop().group.coordinator
    print (device.player_name)
    sub = device.renderingControl.subscribe().subscription
    sub2 = device.avTransport.subscribe().subscription
    sub.callback = print_event
    sub2.callback = print_event

    def before_shutdown():
        sub.unsubscribe()
        sub2.unsubscribe()
        events_twisted.event_listener.stop()

    reactor.addSystemEventTrigger(
        'before', 'shutdown', before_shutdown)

if __name__=='__main__':
    reactor.callWhenRunning(main)
    reactor.run()
class soco.events_twisted.Resource[source]

Fake Resource class to use when building docs

class soco.events_twisted.EventNotifyHandler[source]

Handles HTTP NOTIFY Verbs sent to the listener server. Inherits from soco.events_base.EventNotifyHandlerBase.

render_NOTIFY(request)[source]

Serve a NOTIFY request by calling handle_notification with the headers and content.

class soco.events_twisted.EventListener[source]

The Event Listener.

Runs an http server which is an endpoint for NOTIFY requests from Sonos devices. Inherits from soco.events_base.EventListenerBase.

port

set at listen

Type

twisted.internet.tcp.Port

listen(ip_address)[source]

Start the event listener listening on the local machine at port 1400 (default). If this port is unavailable, the listener will attempt to listen on the next available port, within a range of 100.

Make sure that your firewall allows connections to this port.

This method is called by soco.events_base.EventListenerBase.start

Handling of requests is delegated to an instance of the EventNotifyHandler class.

Parameters

ip_address (str) – The local network interface on which the server should start listening.

Returns

The port on which the server is listening.

Return type

int

Note

The port on which the event listener listens is configurable. See config.EVENT_LISTENER_PORT

stop_listening(address)[source]

Stop the listener.

class soco.events_twisted.Subscription(service, event_queue=None)[source]

A class representing the subscription to a UPnP event. Inherits from soco.events_base.SubscriptionBase.

Parameters
  • service (Service) – The SoCo Service to which the subscription should be made.

  • event_queue (Queue) – A queue on which received events will be put. If not specified, a queue will be created and used.

callback

callback function to be called whenever an Event is received. If it is set and is callable, the callback function will be called with the Event as the only parameter and the Subscription’s event queue won’t be used.

Type

function

subscribe(requested_timeout=None, auto_renew=False, strict=True)[source]

Subscribe to the service.

If requested_timeout is provided, a subscription valid for that number of seconds will be requested, but not guaranteed. Check timeout on return to find out what period of validity is actually allocated.

This method calls events_base.SubscriptionBase.subscribe.

Note

SoCo will try to unsubscribe any subscriptions which are still subscribed on program termination, but it is good practice for you to clean up by making sure that you call unsubscribe() yourself.

Parameters
  • requested_timeout (int, optional) – The timeout to be requested.

  • auto_renew (bool, optional) – If True, renew the subscription automatically shortly before timeout. Default False.

  • strict (bool, optional) – If True and an Exception occurs during execution, the returned Deferred will fail with a Failure which will be passed to the applicable errback (if any has been set by the calling code) or, if False, the Failure will be logged and the Subscription instance will be passed to the applicable callback (if any has been set by the calling code). Default True.

Returns

A Deferred the result of which will be the Subscription instance and the subscription property of which will point to the Subscription instance.

Return type

Deferred

renew(requested_timeout=None)[source]

Renew the event subscription. You should not try to renew a subscription which has been unsubscribed, or once it has expired.

This method calls events_base.SubscriptionBase.renew.

Parameters
  • requested_timeout (int, optional) – The period for which a renewal request should be made. If None (the default), use the timeout requested on subscription.

  • is_autorenew (bool, optional) – Whether this is an autorenewal. Default False.

  • strict (bool, optional) – If True and an Exception occurs during execution, the returned Deferred will fail with a Failure which will be passed to the applicable errback (if any has been set by the calling code) or, if False, the Failure will be logged and the Subscription instance will be passed to the applicable callback (if any has been set by the calling code). Default True.

Returns

A Deferred the result of which will be the Subscription instance and the subscription property of which will point to the Subscription instance.

Return type

Deferred

unsubscribe()[source]

Unsubscribe from the service’s events. Once unsubscribed, a Subscription instance should not be reused

This method calls events_base.SubscriptionBase.unsubscribe.

Parameters

strict (bool, optional) – If True and an Exception occurs during execution, the returned Deferred will fail with a Failure which will be passed to the applicable errback (if any has been set by the calling code) or, if False, the Failure will be logged and the Subscription instance will be passed to the applicable callback (if any has been set by the calling code). Default True.

Returns

A Deferred the result of which will be the Subscription instance and the subscription property of which will point to the Subscription instance.

Return type

Deferred

class soco.events_twisted.SubscriptionsMapTwisted[source]

Maintains a mapping of sids to soco.events_twisted.Subscription instances. Registers each subscription to be unsubscribed at exit.

Inherits from soco.events_base.SubscriptionsMap.

register(subscription)[source]

Register a subscription by updating local mapping of sid to subscription and registering it to be unsubscribed at exit.

Parameters

subscription (soco.events_twisted.Subscription) – the subscription to be registered.

subscribing()[source]

Called when the Subscription.subscribe method commences execution.

finished_subscribing()[source]

Called when the Subscription.subscribe method completes execution.

property count

The number of active or pending subscriptions.

Type

int

soco.events_asyncio module

Classes to handle Sonos UPnP Events and Subscriptions using asyncio.

The Subscription class from this module will be used in soco.services if config.EVENTS_MODULE is set to point to this module.

Example

Run this code, and change your volume, tracks etc:

import logging

logging.basicConfig()
import soco
import asyncio
from pprint import pprint

from soco import events_asyncio

soco.config.EVENTS_MODULE = events_asyncio


def print_event(event):
    try:
        pprint(event.variables)
    except Exception as e:
        print("There was an error in print_event:", e)


def _get_device():
    device = soco.discover().pop().group.coordinator
    print(device.player_name)
    return device


async def main():
    # pick a device at random and use it to get
    # the group coordinator
    loop = asyncio.get_event_loop()
    device = await loop.run_in_executor(None, _get_device)
    sub = await device.renderingControl.subscribe()
    sub2 = await device.avTransport.subscribe()
    sub.callback = print_event
    sub2.callback = print_event

    async def before_shutdown():
        await sub.unsubscribe()
        await sub2.unsubscribe()
        await events_asyncio.event_listener.async_stop()

    await asyncio.sleep(1)
    print("Renewing subscription..")
    await sub.renew()

    await asyncio.sleep(100)
    await before_shutdown()


if __name__ == "__main__":
    asyncio.run(main())
class soco.events_asyncio.EventNotifyHandler[source]

Handles HTTP NOTIFY Verbs sent to the listener server. Inherits from soco.events_base.EventNotifyHandlerBase.

async notify(request)[source]

Serve a NOTIFY request by calling handle_notification with the headers and content.

class soco.events_asyncio.EventListener[source]

The Event Listener.

Runs an http server which is an endpoint for NOTIFY requests from Sonos devices. Inherits from soco.events_base.EventListenerBase.

start(any_zone)[source]

A stub since the first subscribe calls async_start.

listen(ip_address)[source]

A stub since since async_listen is used.

async async_start(any_zone)[source]

Start the event listener listening on the local machine under the lock.

Parameters

any_zone (SoCo) – Any Sonos device on the network. It does not matter which device. It is used only to find a local IP address reachable by the Sonos net.

async async_listen(ip_address)[source]

Start the event listener listening on the local machine at port 1400 (default). If this port is unavailable, the listener will attempt to listen on the next available port, within a range of 100.

Make sure that your firewall allows connections to this port.

This method is called by soco.events_base.EventListenerBase.start

Handling of requests is delegated to an instance of the EventNotifyHandler class.

Parameters

ip_address (str) – The local network interface on which the server should start listening.

Returns

The port on which the server is listening.

Return type

int

Note

The port on which the event listener listens is configurable. See config.EVENT_LISTENER_PORT

async async_stop()[source]

Stop the listener.

stop_listening(address)[source]

Stop the listener.

class soco.events_asyncio.Subscription(service, callback=None)[source]

A class representing the subscription to a UPnP event. Inherits from soco.events_base.SubscriptionBase.

Parameters
  • service (Service) – The SoCo Service to which the subscription should be made.

  • event_queue (Queue) – A queue on which received events will be put. If not specified, a queue will be created and used.

callback

callback function to be called whenever an Event is received. If it is set and is callable, the callback function will be called with the Event as the only parameter and the Subscription’s event queue won’t be used.

Type

function

subscribe(requested_timeout=None, auto_renew=False, strict=True)[source]

Subscribe to the service.

If requested_timeout is provided, a subscription valid for that number of seconds will be requested, but not guaranteed. Check timeout on return to find out what period of validity is actually allocated.

This method calls events_base.SubscriptionBase.subscribe.

Note

SoCo will try to unsubscribe any subscriptions which are still subscribed on program termination, but it is good practice for you to clean up by making sure that you call unsubscribe() yourself.

Parameters
  • requested_timeout (int, optional) – The timeout to be requested.

  • auto_renew (bool, optional) – If True, renew the subscription automatically shortly before timeout. Default False.

  • strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

async renew(requested_timeout=None)[source]

Renew the event subscription. You should not try to renew a subscription which has been unsubscribed, or once it has expired.

This method calls events_base.SubscriptionBase.renew.

Parameters
  • requested_timeout (int, optional) – The period for which a renewal request should be made. If None (the default), use the timeout requested on subscription.

  • is_autorenew (bool, optional) – Whether this is an autorenewal. Default False.

  • strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

async unsubscribe()[source]

Unsubscribe from the service’s events. Once unsubscribed, a Subscription instance should not be reused

This method calls events_base.SubscriptionBase.unsubscribe.

Parameters

strict (bool, optional) – If True and an Exception occurs during execution, the Exception will be raised or, if False, the Exception will be logged and the Subscription instance will be returned. Default True.

Returns

The Subscription instance.

Return type

Subscription

class soco.events_asyncio.nullcontext(enter_result=None)[source]

Context manager that does no additional processing.

Backport from python 3.7+ for older pythons.

class soco.events_asyncio.SubscriptionsMapAio[source]

Maintains a mapping of sids to soco.events_asyncio.Subscription instances. Registers each subscription to be unsubscribed at exit.

Inherits from soco.events_base.SubscriptionsMap.

register(subscription)[source]

Register a subscription by updating local mapping of sid to subscription and registering it to be unsubscribed at exit.

Parameters

subscription (soco.events_asyncio.Subscription) – the subscription to be registered.

subscribing()[source]

Called when the Subscription.subscribe method commences execution.

finished_subscribing()[source]

Called when the Subscription.subscribe method completes execution.

property count

The number of active or pending subscriptions.

Type

int