Harmony auto discovery via netdisco (#7741)

* Use netdisco to automatically discover harmony hubs.

* Allow some settings in configuration.yml to override even on discovered hubs.

* Global is not required as no assignment on variable

* Use `set` instead of list for perf

* Store cache of discovered devices against `hass.data` rather than in global

* Handle case if the device cache is empty

* Fix indentation issue
This commit is contained in:
Anthony Hughes 2017-06-22 07:43:35 +02:00 committed by Paulus Schoutsen
parent a95fe588ca
commit 6bfeac7f80
2 changed files with 53 additions and 15 deletions

View File

@ -55,6 +55,7 @@ SERVICE_HANDLERS = {
'apple_tv': ('media_player', 'apple_tv'), 'apple_tv': ('media_player', 'apple_tv'),
'frontier_silicon': ('media_player', 'frontier_silicon'), 'frontier_silicon': ('media_player', 'frontier_silicon'),
'openhome': ('media_player', 'openhome'), 'openhome': ('media_player', 'openhome'),
'harmony': ('remote', 'harmony'),
'bose_soundtouch': ('media_player', 'soundtouch'), 'bose_soundtouch': ('media_player', 'soundtouch'),
} }

View File

@ -26,12 +26,13 @@ _LOGGER = logging.getLogger(__name__)
DEFAULT_PORT = 5222 DEFAULT_PORT = 5222
DEVICES = [] DEVICES = []
CONF_DEVICE_CACHE = 'device_cache'
SERVICE_SYNC = 'harmony_sync' SERVICE_SYNC = 'harmony_sync'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_NAME): cv.string, vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Required(ATTR_ACTIVITY, default=None): cv.string, vol.Required(ATTR_ACTIVITY, default=None): cv.string,
}) })
@ -44,29 +45,65 @@ HARMONY_SYNC_SCHEMA = vol.Schema({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Harmony platform.""" """Set up the Harmony platform."""
import pyharmony import pyharmony
global DEVICES
name = config.get(CONF_NAME) host = None
host = config.get(CONF_HOST) activity = None
port = config.get(CONF_PORT)
_LOGGER.debug("Loading Harmony platform: %s", name)
harmony_conf_file = hass.config.path( if CONF_DEVICE_CACHE not in hass.data:
'{}{}{}'.format('harmony_', slugify(name), '.conf')) hass.data[CONF_DEVICE_CACHE] = []
if discovery_info:
# Find the discovered device in the list of user configurations
override = next((c for c in hass.data[CONF_DEVICE_CACHE]
if c.get(CONF_NAME) == discovery_info.get(CONF_NAME)),
False)
port = DEFAULT_PORT
if override:
activity = override.get(ATTR_ACTIVITY)
port = override.get(CONF_PORT, DEFAULT_PORT)
host = (
discovery_info.get(CONF_NAME),
discovery_info.get(CONF_HOST),
port)
# Ignore hub name when checking if this hub is known - ip and port only
if host and host[1:] in set([h[1:] for h in DEVICES]):
_LOGGER.debug("Discovered host already known: %s", host)
return
elif CONF_HOST in config:
host = (
config.get(CONF_NAME),
config.get(CONF_HOST),
config.get(CONF_PORT),
)
activity = config.get(ATTR_ACTIVITY)
else:
hass.data[CONF_DEVICE_CACHE].append(config)
return
name, address, port = host
_LOGGER.info("Loading Harmony Platform: %s at %s:%s, startup activity: %s",
name, address, port, activity)
try: try:
_LOGGER.debug("Calling pyharmony.ha_get_token for remote at: %s:%s", _LOGGER.debug("Calling pyharmony.ha_get_token for remote at: %s:%s",
host, port) address, port)
token = urllib.parse.quote_plus(pyharmony.ha_get_token(host, port)) token = urllib.parse.quote_plus(pyharmony.ha_get_token(address, port))
_LOGGER.debug("Received token: %s", token)
except ValueError as err: except ValueError as err:
_LOGGER.warning("%s for remote: %s", err.args[0], name) _LOGGER.warning("%s for remote: %s", err.args[0], name)
return False return False
_LOGGER.debug("Received token: %s", token) harmony_conf_file = hass.config.path(
DEVICES = [HarmonyRemote( '{}{}{}'.format('harmony_', slugify(name), '.conf'))
config.get(CONF_NAME), config.get(CONF_HOST), config.get(CONF_PORT), device = HarmonyRemote(
config.get(ATTR_ACTIVITY), harmony_conf_file, token)] name, address, port,
add_devices(DEVICES, True) activity, harmony_conf_file, token)
DEVICES.append(device)
add_devices([device])
register_services(hass) register_services(hass)
return True return True