Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ omit =
homeassistant/components/smarthab/*
homeassistant/components/sms/*
homeassistant/components/smtp/notify.py
homeassistant/components/snapcast/media_player.py
homeassistant/components/snapcast/*
homeassistant/components/snmp/*
homeassistant/components/sochain/sensor.py
homeassistant/components/socialblade/sensor.py
Expand Down
33 changes: 3 additions & 30 deletions homeassistant/components/snapcast/__init__.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,23 @@
"""The snapcast component."""

import asyncio

import voluptuous as vol

from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send

DOMAIN = "snapcast"

SERVICE_SNAPSHOT = "snapshot"
SERVICE_RESTORE = "restore"
SERVICE_JOIN = "join"
SERVICE_UNJOIN = "unjoin"
SERVICE_SET_LATENCY = "set_latency"

ATTR_MASTER = "master"
ATTR_LATENCY = "latency"

SERVICE_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.entity_ids})

JOIN_SERVICE_SCHEMA = SERVICE_SCHEMA.extend({vol.Required(ATTR_MASTER): cv.entity_id})


async def async_setup(hass, config):
"""Handle service configuration."""
service_event = asyncio.Event()

async def service_handle(service):
"""Dispatch a service call."""
service_event.clear()
async_dispatcher_send(
hass, DOMAIN, service_event, service.service, service.data
)
await service_event.wait()

hass.services.async_register(
DOMAIN, SERVICE_SNAPSHOT, service_handle, schema=SERVICE_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_RESTORE, service_handle, schema=SERVICE_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_JOIN, service_handle, schema=JOIN_SERVICE_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_UNJOIN, service_handle, schema=SERVICE_SCHEMA
)

return True
LATENCY_SCHEMA = SERVICE_SCHEMA.extend({vol.Required(ATTR_LATENCY): cv.positive_int})
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
67 changes: 34 additions & 33 deletions homeassistant/components/snapcast/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
SUPPORT_VOLUME_SET,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_HOST,
CONF_PORT,
STATE_IDLE,
Expand All @@ -22,14 +21,14 @@
STATE_PLAYING,
STATE_UNKNOWN,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers import config_validation as cv, entity_platform

from . import (
ATTR_LATENCY,
ATTR_MASTER,
DOMAIN,
SERVICE_JOIN,
SERVICE_RESTORE,
SERVICE_SET_LATENCY,
SERVICE_SNAPSHOT,
SERVICE_UNJOIN,
)
Expand Down Expand Up @@ -58,36 +57,23 @@
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the Snapcast platform."""

_LOGGER.debug("Reached async_setup_platform")
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated

host = config.get(CONF_HOST)
port = config.get(CONF_PORT, CONTROL_PORT)

async def async_service_handle(service_event, service, data):
"""Handle dispatched services."""
entity_ids = data.get(ATTR_ENTITY_ID)
devices = [
device for device in hass.data[DATA_KEY] if device.entity_id in entity_ids
]
for device in devices:
if service == SERVICE_SNAPSHOT:
device.snapshot()
elif service == SERVICE_RESTORE:
await device.async_restore()
elif service == SERVICE_JOIN:
if isinstance(device, SnapcastClientDevice):
master = [
e
for e in hass.data[DATA_KEY]
if e.entity_id == data[ATTR_MASTER]
]
if isinstance(master[0], SnapcastClientDevice):
await device.async_join(master[0])
elif service == SERVICE_UNJOIN:
if isinstance(device, SnapcastClientDevice):
await device.async_unjoin()

service_event.set()

async_dispatcher_connect(hass, DOMAIN, async_service_handle)
platform = entity_platform.current_platform.get()
platform.async_register_entity_service(SERVICE_SNAPSHOT, {}, "snapshot")
platform.async_register_entity_service(SERVICE_RESTORE, {}, "async_restore")
platform.async_register_entity_service(
SERVICE_JOIN, {vol.Required(ATTR_MASTER): cv.entity_id}, "async_join"
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
)
platform.async_register_entity_service(SERVICE_UNJOIN, {}, "async_unjoin")
Comment thread
BarrettLowe marked this conversation as resolved.
Outdated
platform.async_register_entity_service(
SERVICE_SET_LATENCY,
{vol.Required(ATTR_LATENCY): cv.positive_int},
"async_set_latency",
)

try:
server = await snapcast.control.create_server(
Expand Down Expand Up @@ -260,14 +246,23 @@ def state(self):
@property
def device_state_attributes(self):
"""Return the state attributes."""
state_attrs = {}
if self.latency is not None:
state_attrs["latency"] = self.latency
Comment thread
MartinHjelmare marked this conversation as resolved.
name = f"{self._client.friendly_name} {CLIENT_SUFFIX}"
return {"friendly_name": name}
state_attrs["friendly_name"] = name
return state_attrs

@property
def should_poll(self):
"""Do not poll for state."""
return False

@property
def latency(self):
"""Latency for Client."""
return self._client.latency

async def async_select_source(self, source):
"""Set input source."""
streams = self._client.group.streams_by_name()
Expand All @@ -287,10 +282,11 @@ async def async_set_volume_level(self, volume):

async def async_join(self, master):
"""Join the group of the master player."""
masters = [e for e in self.hass.data[DATA_KEY] if e.entity_id == master]
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
master_group = [
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
group
for group in self._client.groups_available()
if master.identifier in group.clients
if masters[0].identifier in group.clients
]
await master_group[0].add_client(self._client.identifier)
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
self.async_write_ha_state()
Expand All @@ -307,3 +303,8 @@ def snapshot(self):
async def async_restore(self):
"""Restore the client state."""
await self._client.restore()

async def async_set_latency(self, latency):
"""Set the latency of the client."""
await self._client.set_latency(latency)
self.async_write_ha_state()
9 changes: 9 additions & 0 deletions homeassistant/components/snapcast/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@ restore:
entity_id:
description: Name(s) of entities that will be restored. Platform dependent.
example: "media_player.living_room"

set_latency:
description: Set client set_latency
fields:
entity_id:
description: Name of entities that will have adjusted latency
latency:
description: Latency in master
example: 14