4. musiccast2mqtt Package

4.1. Warning

Work in Progress.

4.2. Modules

4.2.1. __init__

Package header for musiccast2mqtt.

This header declares the version, the exceptions, the constants, the classes defining the tokens to use in the threading queues, and the lists of official keywords for the MusicCast API.

exception musiccast2mqtt.AnyError[source]

Bases: exceptions.Exception

All the errors from this package.

exception musiccast2mqtt.CommsError[source]

Bases: musiccast2mqtt.AnyError

Communication errors.

exception musiccast2mqtt.LogicError[source]

Bases: musiccast2mqtt.AnyError

Logic errors.

exception musiccast2mqtt.ConfigError[source]

Bases: musiccast2mqtt.AnyError

Configuration errors.

musiccast2mqtt.APP_NAME = 'musiccast'

Name of this app to appear as sender and gateway in messages.

class musiccast2mqtt.DeviceHandle(task, device_id=None, host=None, api_port=None)[source]

Bases: object

The token to be used in the Device Factory queue.

CREATE = 1
DELETE = 2
class musiccast2mqtt.DeviceTask(task, zone=None, event=None, msg=None)[source]

Bases: object

The token to be used in the Device Task queues.

REFRESH_STATUS = 0
PROCESS_EVENT = 1
PROCESS_MESSAGE = 2
DISABLE_DEVICE = 3

4.2.2. musiccast_start

Entry point for the MusicCast gateway.

musiccast2mqtt.musiccast_start.main()[source]

launch the gateway

4.2.3. musiccast_interface

Interface for MusicCast gateway

=== OLD System Docstring Representation of the Audio-Video system, including non-MusicCast devices.

The Audio-Video system is represented by a tree structure made of the System as root, having a list of musiccastDevice objects as branches. Devices have then lists of Input objects and lists of Zone objects.

The initialisation process is separated in 3 steps:

  1. Instantiate objects, load the static data from a JSON file into local attributes and propagate this initialisation steps to the next level, i.e. devices and then inputs and zones.
  2. Post initialisation step, where some attributes are created based on the whole tree structure being already initialised in step 1. For example, finding and assigning the actual object represented by a string id in the JSON file, is done here.
  3. Attempt to retrieve live data from all the MusicCast devices and initialise various parameters based on this data. In case of failure, the retrieval of the information is delayed and the functionality of the device is not available until it goes back online. Beware that in this case some helper dictionaries might still point to objects that are not valid, so always test if a device is ready before proceeding using MusicCast related attributes.

The execution of a command is triggered by a lambda function retrieved from the ACTIONS dictionary. These lambda functions are methods called from a Zone objects that perform all the steps to execute these actions, including sending the actual requests to the devices over HTTP (through the musiccast_comm module).

Note on replies: The policy to send back status messages depends on the addressing used by the incoming MQTT message: if it is addressed specifically to this interface or to a specific MusicCast device, then a reply will always be sent back (case called explicit); if it is not, a reply is sent only if a command is executed, otherwise it stays silent as the message is probably intended for somebody else.

class musiccast2mqtt.musiccast_interface.musiccastInterface(params, msglist_in, msglist_out)[source]

Bases: object

The Interface.

Resolves the system definition file path and calls the System class in musiccast_system. Creates the locations and devices dictionaries.

Parameters:
  • params (dictionary) – includes all options from the dedicated section of the configuration file. This class only requires the sysdefpath option to be defined. It is the location of the JSON file describing the system. If that option is not found then the local directory is used instead.
  • msglist_in (list of internalMsg) – the list of incoming messages.
  • msglist_out (list of internalMsg) – the list of outgoing messages.
_get_device_from_id(device_id, raises=False)[source]

Returns the device object if found, None otherwise.

_device_factory()[source]

Waits on the queue for tasks relating to the devices list.

This is a loop in a thread listening to a queue of devices represented by their device_id and the IP address where they can be reached. If the device_id is definitely new then the musiccastDevice class is called to create a new device. The item in the queue has to be a dictionary containing the following keys:

  • ‘device_id’: a 12 digit ASCII string,
  • ‘ip_address’: a valid address string e.g. ‘127.0.0.1’,
  • ‘task’: one of CREATE or DELETE objects (defined in the package’s __init__)
_event_processor()[source]

Wait for a MusicCast event and dispatches it to the right device.

OLD DOCSTRING: Checks if a MusicCast event has arrived and parses it.

This method uses the dictionary EVENTS based on all possible fields that a MusicCast can have (see Yamaha doc for more details). This dictionary has only 2 levels and every node is either a dict or a callable. Any event object received from a MusicCast device should have a structure which is a subset of the EVENTS one. The algorithm goes through the received event structure in parallel of going through the EVENTS one. If there is a key mismatch, the specific key in event that cannot find a match in EVENTS is ignored. If there is a key match, the lambda function found as value of that key in EVENTS is called with the value of that same key found in event (the argument).

TODO: check if more than one event could be received in a single call.

static _filter_topics(msg)[source]

Returns True is topics are valid, False otherwise.

_resolve_zone(msg)[source]

Finds the zone to operate by resolving the “address” from the topic items.

The resolution uses both location and device fields from the topic. The current algorithm is a strict one, meaning that if a field is provided, it needs to exist otherwise an exception is thrown. One could imagine a more tolerant algorithm if necessary (e.g. if both location and device are provided and the location produces a valid result while the device does not, then the location resolution wins). The location defines a zone directly. The device defines only the device (…) so the zone has to be in the arguments otherwise a default is taken (the first zone in the list). This implies that there should always be at least 1 zone in a device and that the first one should be the main one if possible. This method should be thread-safe. It uses a re-entrant lock for the devices disctionary.

Parameters:( (msg) – class:internalMsg): the incoming message to parse.
Returns:class:Zone: a valid Zone object
Raises:LogicError, ConfigError.
_message_processor()[source]

Waits for a message, parses and executes it.

loop_start()[source]

Starts all the threads and loops needed.

loop_stop()[source]

Stops all loops and threads started in loop_start.

4.2.4. musiccast_discovery

Discovery module for MusicCast devices.

Based on the UPnP protocol v2.0:
http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf

This module searches for MusicCast devices in the network by using the UPnP protocol. A complete search process is made of 2 steps, each launched in a separate thread:

  1. a discovery step where a broadcast is sent over the network and simple responses are expected from discovered devices; those responses are put in a queue to be picked up by the description thread;
  2. a description step where each discovered device retrieved from the queue is polled to get more information about it; each discovered new MusicCast device is written to a dictionary to be retrieved by any other thread that might be interested.

The methods loop_start and loop_stop are used to start or stop the search process. The method retrieve_new_devices can be called at any time to retrieve a dictionary with all the devices that have been discovered since the last call. Use the method get_new_device_event to get an event which will be set each time a new device is discovered. Use it or not. The method update_online_devices allows to tell this module what are the devices already online and avoids going through the description process for these devices. It is a nice to have but it does not need to be used. If unused, the new devices retrieved with the retrieve_new_devices call might not be new, but then the calling thread must know that it needs to check that before doing anything else with those not really new devices.

New devices do not go in any queue but in a dictionary, so even if the retrieve_new_devices method is not called for a while, it does not matter.

musiccast2mqtt.musiccast_discovery._XML_TAGS = {'UDN': ('upnp:device', 'upnp:UDN'), 'friendlyName': ('upnp:device', 'upnp:friendlyName'), 'modelDescription': ('upnp:device', 'upnp:modelDescription'), 'modelName': ('upnp:device', 'upnp:modelName'), 'modelURL': ('upnp:device', 'upnp:modelURL'), 'serialNumber': ('upnp:device', 'upnp:serialNumber'), 'yamaha_URLBase': ('yamaha:X_device', 'yamaha:X_URLBase')}

Dictionary of relevant tags inside the XML dataframe. The keys of the dictionary are arbitrary names for the field being referred to; usually it is the same as the tag name of the XML element being sought, but it does not have to be. The values are lists of tag names that represent the path down the XML tree to reach the element requested.

musiccast2mqtt.musiccast_discovery._XML_NAMESPACES = {'dlna': 'urn:schemas-dlna-org:device-1-0', 'upnp': 'urn:schemas-upnp-org:device-1-0', 'yamaha': 'urn:schemas-yamaha-com:device-1-0'}

This dictionary provides the full name-spaces needed to properly parse the tree with the _XML_TAGS dictionary. It simply avoids to write down the long name-spaces for every tag in the _XML_TAGS dictionary.

musiccast2mqtt.musiccast_discovery._xml_tag(root, key)[source]

Retrieves the content of the tag based on the key in the dictionary _XML_TAGS.

musiccast2mqtt.musiccast_discovery._RESPONSE_HEADERS = {'cache': 'CACHE-CONTROL', 'location': 'LOCATION', 'target': 'ST', 'usn': 'USN'}

Dictionary that maps the headers of the search response with the attributes of the class.

class musiccast2mqtt.musiccast_discovery.searchResponse(response)[source]

Bases: object

Represents a response to the SSDP search. The attributes of this class are listed as values in the _RESPONSE_HEADERS dictionary, except for sender which is retrieved from the second field in the response parameter.

Parameters:response – the data as returned by the call to socket.recvfrom
class musiccast2mqtt.musiccast_discovery.musiccastDiscovery(device_factory_queue, refresh_event=None, cycle=30)[source]

Bases: object

Manages the periodic discovery process for new devices online.

The discovery process for MusicCast devices (based on Yamaha documentation): - launches a SSDP search for Media Renderers; - Read the responses as they arrive; - Put all valid devices on the outgoing queue.

Parameters:
  • ( (device_queue) – class:Queue): to put the new devices
  • cycle (int) – maximum time between 2 searches, in seconds. Loops only once if it is <= 0.
  • refresh_event (Event) – triggers a new search before waiting for the end of cycle.
loop_start()[source]

Starts the loop in a separate thread.

loop_stop()[source]

Stops the loop via the appropriate events.

_loop()[source]

The actual loop. It does a full search then waits either for a ‘refresh’ event or for the full cycle, then tests the ‘loop_stop’ event if to exit or loop again.

Full search process to discover online devices.

Launches two threads and blocks until they are both finished.

_discovery(target, mx=3)[source]

Launches the discovery process.

Sends a search request (SSDP search) then listens to the socket for responses. Terminates after the socket timeout.

_description()[source]

Retrieves the description of any device found from the search.

Reads the queue for new found devices, retrieves the address to call for the description, makes the ‘GET’ request accordingly, filters to keep only the right devices, parses the XML data and puts a new device object on the new device queue.

4.2.5. musiccast_listener

Listener for MusicCast events over the network.

class musiccast2mqtt.musiccast_listener.musiccastListener(port=41100)[source]

Bases: object

docstring

get_musiccast_events_queue()[source]

Returns the event queue.

loop_start()[source]

Starts the loop in a separate thread.

loop_stop()[source]

Stops the loop via the appropriate events.

_loop()[source]

The actual loop. It does a full search then waits either for a ‘refresh’ event or for the full cycle, then tests the ‘loop_stop’ event if to exit or loop again.

_create_socket()[source]

Creates the socket.

_release_socket()[source]

Releases the socket in case of error.

_listen()[source]

Listens for new events.

The ‘body’ of the event (see below) is in the form:
‘{“main”:{“power”:”on”},”device_id”:”00A0DED57E83”}’
or:
‘{“main”:{“volume”:88},”zone2”:{“volume”:0}, “device_id”:”00A0DED3FD57”}’

The ‘address’ is a pair (host, port) as in (‘192.168.1.44’, 38507).

4.2.6. musiccast_device

Declaration of musiccastDevice objects.

musiccastDevice objects are created when a new device is discovered by the discovery process or when it is present in the cache file at start-up. As soon as they are created, a new thread is started with the its own queue to process incoming events or incoming messages.

Notes on refreshing the device:

There are 3 reasons why one needs to refresh the status of a device:

1- because the MusicCast devices need to receive at least one request every 10 minutes
(with the right headers) so that they keep sending events;
2- when this gateway has sent a set command and one wants to check if the command
has been successful. It seems though that one needs to wait a bit before requesting a fresh status as experience shows that firing a getStatus request straight after a command does not reflect the change even if the command is supposed to be successful.
3- when the device is ‘down’ or ‘offline’, e.g. it has had a few errors of communication
and this application has decided to categorise it as not available but still existing, and therefore at some point it needs to be initialised again (or at least this application should ‘try’ to initialise it again).
class musiccast2mqtt.musiccast_device.musiccastDevice(device_id, host, api_port, listenport, msgl_out, device_factory_queue)[source]

Bases: object

Represents a device in the audio-video system.

Parameters:
  • device_id (string) – 12 digit ASCII uniquely representing the device
  • ip_address (string) – where to reach the device
  • listenport (int) – the port where to listen for incoming events
  • msgl_out – the queue for the outgoing messages
  • device_factory_queue – the device factory queue (…)
get_id()[source]

Getter for _device_mcid.

name()[source]

Returns a friendly name for the device.

get_argument(arg)[source]

Retrieves argument from arguments dictionary.

This method is used by the lambdas to get access to the argument of the message. It is essential that the lambdas are running in the same thread as the one that updated the _msg attribute in the same musiccastDevice instance.

Parameters:arg (string) – the name of the argument sought
get_zone(zone_mcid, raises=False)[source]

Returns the Zone object from its identification.

Parameters:
  • zone_mcid (string) – the MusicCast id of the zone searched
  • raises (boolean) – if True, raises an exception instead of returning False
get_input(input_mcid, raises=False)[source]

Returns the Input object from its mcid. :param input_mcid: the MusicCast id of the input searched :type input_mcid: string :param raises: if True, raises an exception instead of returning False :type raises: boolean

Returns:Input object if found, or None
Raises:ConfigError or LogicError.
init_infotype(play_info_type)[source]

Returns a new or an existing instance of PlayInfoType.

For each type there is only one instance of the corresponding class.

Parameters:play_info_type (string) – one of tuner, cd, or netusb.
Raises:ConfigError – if the play_info_type is not recognised.
get_infotype(play_info_type)[source]

Retrieves the info_type instance.

Only used (for now) by the event lambdas.

get_feature(flist)[source]

Returns a branch from the getFeatures tree.

This method retrieves a branch or leaf from a JSON type object. The argument is a list made of strings and/or pairs of string. For each string, the method expect to find a dictionary as the next branch, and selects the value (which is another branch or leaf) returned by that string as key. For each single key dictionary {key: value}, it expects to find an array or similar objects, and in that case it searches for the array that contains the right ‘value’ for that ‘key’.

This method helps in reading the responses from Yamaha MusicCast API.

Parameters:flist – list representing a leaf or a branch from a JSON type of string
Raises:CommsError, ConfigError.

Example

Use get_feature((‘zone’, {‘id’: ‘main’}, ‘range_step’, {‘id’: ‘volume’}, ‘max’)) to retrieve

is_ready(raises=False)[source]

Returns True if the device is ready to be operated.

Parameters:raises (boolean) – if True, raises an exception when device is not ready, otherwise it just returns False.
Returns:True if device is ready, False if not and raises is False.
Return type:boolean
Raises:LogicError – if the device is not ready and the raises argument is True.
disable()[source]

Disables the device to make requests. Can be called more than once.

insert_delayed_request(delay, zone)[source]

Inserts a delayed request in the appropriate list.

_device_loop()[source]

Main thread for a new device.

_init_device()[source]

Initialise the device within its own thread.

Raises:CommsError, ConfigError.
process_event(event)[source]

Processes the event received and executes whatever lambdas found.

This method parses the event through a function and dictionary in musiccast_data that walks through the event ad matches every step with the template event dictionary. When it reaches the leaf, a set of lambdas are found to be executed.

process_message(msg, zone)[source]

Processes the incoming message, passing it to the relevant zone.

This method simply handles the incoming message to the right zone.

static parse_event(event)[source]

Reads event dictionary and returns lambdas for each key match found.

EVENTS = {'cd': {'device_status': None, 'play_info_updated': <function <lambda>>, 'play_time': <function <lambda>>}, 'clock': {'settings_updated': None}, 'device_id': None, 'dist': {'dist_info_updated': None}, 'main': {'input': <function <lambda>>, 'mute': <function <lambda>>, 'power': <function <lambda>>, 'signal_info_updated': None, 'status_updated': <function <lambda>>, 'volume': <function <lambda>>}, 'netusb': {'account_updated': None, 'list_info_updated': None, 'multiple_play_errors': None, 'play_error': None, 'play_info_updated': <function <lambda>>, 'play_message': <function <lambda>>, 'play_time': <function <lambda>>, 'preset_control': None, 'preset_info_updated': <function <lambda>>, 'recent_info_updated': None, 'trial_status': None, 'trial_time_left': None}, 'system': {'bluetooth_info_updated': None, 'func_status_updated': None, 'location_info_updated': None, 'name_text_updated': None, 'speaker_settings_updated': None, 'stereo_pair_info_updated': None, 'tag_updated': None}, 'tuner': {'play_info_updated': <function <lambda>>, 'preset_info_updated': <function <lambda>>}, 'zone2': {'input': <function <lambda>>, 'mute': <function <lambda>>, 'power': <function <lambda>>, 'signal_info_updated': None, 'status_updated': <function <lambda>>, 'volume': <function <lambda>>}, 'zone3': {}, 'zone4': {}}

Dictionary to decode incoming events.

The lambdas should be called by a Device object.

4.2.7. musiccast_zone

Representation of a zone.

Assumptions on Zones:

  • all MusicCast zones have always a valid input assigned (even when off).
class musiccast2mqtt.musiccast_zone.Zone(zone_data, device)[source]

Bases: object

Represents a zone on the device.

Parameters:
  • zone_data (dictionary) – the zone data returned from the getFeatures call to the API
  • device (Device) – the parent device.
name()[source]

Returns a friendly name for the zone.

_get_dict_item(dico, key)[source]

Retrieves the item in the dictionary.

This is a safety method in case a structure sent back by MusicCast does not have the item expected. It catches the KeyError exception and changes it into a CommsError one.

Parameters:
  • dico (dict) – the dictionary to look into
  • item (string) – the key to look for
_transform_arg(key, invalue=None, mcvalue=None)[source]

Transforms a message argument from/to internal to/from MusicCast.

This method goes hand in hand with the TRANSFORM_ARG dictionary.

Parameters:
  • key (string) – internal name of argument.
  • invalue (string) – the internal value to be transformed; if provided the transformation is done from this value to the MusicCast value, which is returned.
  • mcvalue (string) – the MusicCast value to be transformed; relevant only if invalue is None, in which case the transformation is done from this value to the internal value, which is returned.
Returns:

the transformed representation of the value.

Return type:

string

execute_action(msg)[source]

Executes the action requested in the message

This method relies on the ACTIONS dictionary to produce the lambda to execute.

Parameters:( (msg) – py:class:internalMsg): internal message
Raises:LogicError, ConfigError, CommsError – in case of error in executing the lambdas
refresh_status()[source]

Retrieve the state of the zone and store it locally.

update_power(mcvalue)[source]

Updates internal state of zone after change in power state.

Parameters:
  • invalue (boolean) – the new value of the power state
  • mcvalue (string) – “on” or “standby”
Returns:

True if there is a change.

Return type:

Boolean

set_power(power)[source]

Sets the power of the zone.

Parameters:power (boolean) – converted into ‘on’ or ‘standby’.
is_power_on(raises=False)[source]

Helper function to test if power of zone is ON.

Always returns True if the zone is ON.

Parameters:raises (boolean) – if True, raises an exception when zone is OFF, otherwise it just returns False.
Returns:True if zone is ON, False if not and raises is False.
Return type:boolean
Raises:LogicError – if the zone is OFF and the raises argument is True.
update_volume(mcvalue=None)[source]

Updates internal state of zone after change in volume.

Parameters:
  • invalue (int) – the new value of the volume in internal metric
  • mcvalue (int) – the new value of the volume in MusicCast metric
Returns:

True if there is a change.

Return type:

Boolean

set_volume(vol_up=None)[source]

Sets the volume of the zone.

Parameters:vol_up (boolean) – if given defines if volume is stepped up or down, if not then the volume to set has to be in the arguments.
update_mute(mcvalue=None)[source]

Updates internal state of zone after change in mute state.

Parameters:mcvalue (string) – “true” or “false”
Returns:True if there is a change.
Return type:Boolean
set_mute(mute)[source]

Sets the mute property of the zone.

Parameters:mute (boolean) – converted into ‘true’ or ‘false’
update_input(mcvalue)[source]

Updates internal value of input object after change in input.

Parameters:mcvalue (string) – a valid Input MusicCast id
Returns:True if there is a change.
Return type:Boolean
set_input(input_mcid=None)[source]

Sets the input of the zone.

This method simply switches the input of the current zone. It does not matter if the input is a source or not. No other action is performed, so if for example the input is a source on the same device and it needs to be started or tuned, this is not done here.

Parameters:input_mcid (string) – input internal identifier
get_inputs()[source]

docstring

get_sources()[source]

docstring

set_playback(mc_action, src_mcid=None)[source]

Triggers the specified play-back action.

To be able to play a source, it has to be selected first.

Parameters:
  • action (string) – the action to send to the MusicCast device.
  • src_mcid (string) – the MusicCast keyword of the source to be played, if supplied, otherwise it is expected to be in the arguments.
set_preset(src_mcid=None)[source]

Set the preset specified in the arguments for the source.

Parameters:source_id (string) – the MusicCast keyword of the source to be preset, if supplied, otherwise it is expected to be in the arguments. It can only be tuner or netusb.
str_status()[source]

Returns the full status dictionary.

str_zone()[source]

Returns the identification of a zone.

dump_zone()[source]

Returns most characteristics of a zone.

musiccast2mqtt.musiccast_zone.TRANSFORM_ARG = {'action': (<function <lambda>>, <function <lambda>>), 'input': (<function <lambda>>, <function <lambda>>), 'mute': (<function <lambda>>, <function <lambda>>), 'power': (<function <lambda>>, <function <lambda>>), 'preset': (<function <lambda>>, <function <lambda>>), 'source': (<function <lambda>>, <function <lambda>>), 'volume': (<function <lambda>>, <function <lambda>>)}

Transforms arguments from internal keyword to MusicCast keyword and back.

The value for each key is a pair of lambdas; the first one transforms its arguments from internal representation to Musiccast, and the second one does the reverse. The lambdas have to be called by a Zone object.

musiccast2mqtt.musiccast_zone.ACTIONS = {'CD_BACK': <function <lambda>>, 'CD_FORWARD': <function <lambda>>, 'CD_PAUSE': <function <lambda>>, 'CD_PLAY': <function <lambda>>, 'CD_STOP': <function <lambda>>, 'GET_INPUTS': <function <lambda>>, 'GET_SOURCES': <function <lambda>>, 'INPUT_CD': <function <lambda>>, 'INPUT_NETRADIO': <function <lambda>>, 'INPUT_SPOTIFY': <function <lambda>>, 'INPUT_TUNER': <function <lambda>>, 'MUTE_OFF': <function <lambda>>, 'MUTE_ON': <function <lambda>>, 'MUTE_TOGGLE': <function <lambda>>, 'NETRADIO_PRESET': <function <lambda>>, 'POWER_OFF': <function <lambda>>, 'POWER_ON': <function <lambda>>, 'SET_INPUT': <function <lambda>>, 'SET_SOURCE': <function <lambda>>, 'SET_VOLUME': <function <lambda>>, 'SOURCE_CD': <function <lambda>>, 'SOURCE_NETRADIO': <function <lambda>>, 'SOURCE_SPOTIFY': <function <lambda>>, 'SOURCE_TUNER': <function <lambda>>, 'SPOTIFY_BACK': <function <lambda>>, 'SPOTIFY_FORWARD': <function <lambda>>, 'SPOTIFY_PLAYPAUSE': <function <lambda>>, 'TUNER_PRESET': <function <lambda>>, 'VOLUME_DOWN': <function <lambda>>, 'VOLUME_UP': <function <lambda>>}

The dictionary with all the data to process the various commands.

It has to be called from a Zone object.

4.2.8. musiccast_input

Representation of Inputs

class musiccast2mqtt.musiccast_input.Input(input_data, device)[source]

Bases: object

Represents an input on the device.

Parameters:
  • input_data (dict) – input data from getFeatures
  • device (Device) – the parent device
class musiccast2mqtt.musiccast_input.Feed(feed_data, device)[source]

Bases: musiccast2mqtt.musiccast_input.Input

Represents an input on the device that is not a source.

A feed within a MusicCast system is an input for which the play_info_type field within the getFeatures structure is set to none.

Parameters:
  • feed_data (data) – the feed data
  • device (Device) – the parent device.
class musiccast2mqtt.musiccast_input.Source(source_data, device)[source]

Bases: musiccast2mqtt.musiccast_input.Input

Represents a source on the device.

A source within a MusicCast system is an input for which the play_info_type field within the getFeatures structure is set to a different value than none, normally either cd, tuner or netusb.

Parameters:
  • source_data (dict) – the source data
  • device (Device) – the parent device.

4.2.9. musiccast_playinfotype

Declaration of PlayInfoType structures.

class musiccast2mqtt.musiccast_playinfotype.PlayInfoType(play_info_type, device)[source]

Bases: object

Represents information that is not source specific in Yamaha API.

Some of the information about sources in MusicCast devices are only available for groups of sources, and not source by source. This is true for the netusb type, which covers a wide range of sources (server, net_radio, and all streaming services). This information can not be stored on a source by source basis but in an ad-hoc structure that sources will link to. For any device, there can be only one instance of each type (cd, tuner and netusb) so the instantiation of these classes is triggered by the Source object initialisation, that finds out of what type it is and then calls a sort of factory method within the parent Device object that then decides to instantiate a new object if it does not exist yet or returns the existing object (a sort of singleton pattern).

Parameters:
  • play_info_type (string) – one of tuner, cd, or netusb.
  • ( (device) – class:Device object): parent device of the source.
update_play_info()[source]

Retrieves the play_info structure.

The sources involved in this command are tuner, cd, and all sources part of the netusb group.

update_preset_info()[source]

Retrieves the preset_info structure.

The getPresetInfo request involves only types tuner and netusb. Treatment in either case is different, see the Yamaha doc for details. This method is supposed to be overridden in both cases.

update_play_time(value)[source]

Updates the play_time attribute with the new value.

Only concerns MusicCast types cd and netusb. The play_time event get sent every second by MusicCast devices once a cd or a streaming service starts playing.

Parameters:value (integer in string form) – the new value of play_time.
update_play_message(value)[source]

Updates the play_message attribute with the new value.

This event only applies to the netusb group.
Parameters:value (string) – the new value of play_message.
get_preset_arguments(source, preset_num)[source]

Returns a dictionary with the preset information.

Parameters:
  • source (Source) – the source with the preset information
  • preset_num (int) – the preset number to retrieve
class musiccast2mqtt.musiccast_playinfotype.Tuner(device)[source]

Bases: musiccast2mqtt.musiccast_playinfotype.PlayInfoType

Tuner specific information.

Parameters:device (Device object) – parent device.
update_preset_info()[source]

Retrieves the preset_info structure.

Info type == tuner: the request requires a band argument that depends on the features of the device. As the structure returned by the request is a list of objects that always include the band that the preset relates to, we can concatenate all the preset lists.

get_preset_arguments(source, preset_num)[source]

Returns a dictionary with the preset information.

Parameters:
  • source (Source) – the source with the preset information
  • preset_num (int) – the preset number to retrieve
class musiccast2mqtt.musiccast_playinfotype.CD(device)[source]

Bases: musiccast2mqtt.musiccast_playinfotype.PlayInfoType

CD specifc information.

Parameters:device (Device object) – parent device.
update_play_time(value)[source]

Updates the play_time attribute with the new value.

Parameters:value (integer in string form) – the new value of play_time.
class musiccast2mqtt.musiccast_playinfotype.NetUSB(device)[source]

Bases: musiccast2mqtt.musiccast_playinfotype.PlayInfoType

NetUSB specific information.

Parameters:device (Device object) – parent device.
update_preset_info()[source]

Retrieves the preset_info structure.

Info type == netusb: the request is sent as is and the structure returned includes a list of objects where one of fields indicates the input that the preset relate to (I am not sure what the input can be anything else that net_radio though).

update_play_time(value)[source]

Updates the play_time attribute with the new value.

Note: There is an uncertainty on which source is playing when the type is netusb. The event does not give any extra information. It probably means that there can only be one source that can play at any given time in the netusb group, even if there are multiple zones in the device.

Parameters:value (integer in string form) – the new value of play_time.
update_play_message(value)[source]

Updates the play_message attribute with the new value.

Parameters:value (string) – the new value of play_message.
get_preset_arguments(source, preset_num)[source]

Returns a dictionary with the preset information.

Parameters:
  • source (Source) – the source with the preset information
  • preset_num (int) – the preset number to retrieve

4.2.10. musiccast_comm

Low-level communication with the MusicCast system.

class musiccast2mqtt.musiccast_comm.musiccastComm(host, api_port, listen_port)[source]

Bases: object

Manages the low-level calls to the MusicCast devices.

Every instance represents a single live connection to a given MusicCast device, represented simply by a host address.

Parameters:
  • host (string) – the HTTP address for the host, as recognisable by the httplib library.
  • api_port (int) – the port of the API where to send the HTTP requests.
  • listen_port (int) – the port where to listen for events; has to go in the headers.
disable()[source]

Disables the requests for this connection.

_dummy(qualifier, mc_command)[source]

Does nothing.

_mcrequest(qualifier, mc_command)[source]

Sends a single HTTP request and returns the response.

This method sends the request and read the response step by step in order to catch properly any error in the process. Currently the requests are always with method = ‘GET’ and version = ‘v1’.

Parameters:
  • qualifier (string) – the token in the MusicCast syntax representing either a zone or a source, depending on the type of command sent;
  • mc_command (string) – the command to send at the end of the request; it has to include any extra argument if there are any.
Raises:

commsError – in case of any form of Communication Error with the device.

Returns:

the dictionary equivalent of the JSON structure sent back as a reply

from the device.

Return type:

dictionary