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.

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 = None

Used to signal that the server should stop.

Type:threading.Event
server = None

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 = None

Indicates whether the server is currently running

Type:bool
requested_port_number = None

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 = None

A unique ID for this subscription

Type:str
timeout = None

The amount of time in seconds until the subscription expires.

Type:int
is_subscribed = None

An indication of whether the subscription is subscribed.

Type:bool
events = None

The queue on which events are placed.

Type:Queue
requested_timeout = None

The period (seconds) for which the subscription is requested

Type:int
auto_renew_fail = None

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.
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 = None

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

Type:weakref.WeakValueDictionary
subscriptions_lock = None

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.

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 = None

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 = None

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.

count

The number of active or pending subscriptions.

Type:int

soco.events_asyncio module