mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Persist emulated hue IDs (#5435)
This commit is contained in:
parent
dbcad34b47
commit
887a33c7d1
@ -5,6 +5,7 @@ For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/emulated_hue/
|
||||
"""
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
@ -24,6 +25,8 @@ DOMAIN = 'emulated_hue'
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
NUMBERS_FILE = 'emulated_hue_ids.json'
|
||||
|
||||
CONF_HOST_IP = 'host_ip'
|
||||
CONF_LISTEN_PORT = 'listen_port'
|
||||
CONF_UPNP_BIND_MULTICAST = 'upnp_bind_multicast'
|
||||
@ -63,7 +66,7 @@ ATTR_EMULATED_HUE = 'emulated_hue'
|
||||
|
||||
def setup(hass, yaml_config):
|
||||
"""Activate the emulated_hue component."""
|
||||
config = Config(yaml_config.get(DOMAIN, {}))
|
||||
config = Config(hass, yaml_config.get(DOMAIN, {}))
|
||||
|
||||
server = HomeAssistantWSGI(
|
||||
hass,
|
||||
@ -112,10 +115,11 @@ def setup(hass, yaml_config):
|
||||
class Config(object):
|
||||
"""Holds configuration variables for the emulated hue bridge."""
|
||||
|
||||
def __init__(self, conf):
|
||||
def __init__(self, hass, conf):
|
||||
"""Initialize the instance."""
|
||||
self.hass = hass
|
||||
self.type = conf.get(CONF_TYPE)
|
||||
self.numbers = {}
|
||||
self.numbers = None
|
||||
self.cached_states = {}
|
||||
|
||||
# Get the IP address that will be passed to the Echo during discovery
|
||||
@ -165,6 +169,9 @@ class Config(object):
|
||||
if self.type == TYPE_ALEXA:
|
||||
return entity_id
|
||||
|
||||
if self.numbers is None:
|
||||
self.numbers = self._load_numbers_json()
|
||||
|
||||
# Google Home
|
||||
for number, ent_id in self.numbers.items():
|
||||
if entity_id == ent_id:
|
||||
@ -172,6 +179,7 @@ class Config(object):
|
||||
|
||||
number = str(len(self.numbers) + 1)
|
||||
self.numbers[number] = entity_id
|
||||
self._save_numbers_json()
|
||||
return number
|
||||
|
||||
def number_to_entity_id(self, number):
|
||||
@ -179,6 +187,9 @@ class Config(object):
|
||||
if self.type == TYPE_ALEXA:
|
||||
return number
|
||||
|
||||
if self.numbers is None:
|
||||
self.numbers = self._load_numbers_json()
|
||||
|
||||
# Google Home
|
||||
assert isinstance(number, str)
|
||||
return self.numbers.get(number)
|
||||
@ -205,3 +216,26 @@ class Config(object):
|
||||
domain_exposed_by_default and explicit_expose is not False
|
||||
|
||||
return is_default_exposed or explicit_expose
|
||||
|
||||
def _load_numbers_json(self):
|
||||
"""Helper method to load numbers json."""
|
||||
try:
|
||||
with open(self.hass.config.path(NUMBERS_FILE),
|
||||
encoding='utf-8') as fil:
|
||||
return json.loads(fil.read())
|
||||
except (OSError, ValueError) as err:
|
||||
# OSError if file not found or unaccessible/no permissions
|
||||
# ValueError if could not parse JSON
|
||||
if not isinstance(err, FileNotFoundError):
|
||||
_LOGGER.warning('Failed to open %s: %s', NUMBERS_FILE, err)
|
||||
return {}
|
||||
|
||||
def _save_numbers_json(self):
|
||||
"""Helper method to save numbers json."""
|
||||
try:
|
||||
with open(self.hass.config.path(NUMBERS_FILE), 'w',
|
||||
encoding='utf-8') as fil:
|
||||
fil.write(json.dumps(self.numbers))
|
||||
except OSError as err:
|
||||
# OSError if file write permissions
|
||||
_LOGGER.warning('Failed to write %s: %s', NUMBERS_FILE, err)
|
||||
|
@ -106,7 +106,7 @@ def hass_hue(loop, hass):
|
||||
def hue_client(loop, hass_hue, test_client):
|
||||
"""Create web client for emulated hue api."""
|
||||
web_app = mock_http_component_app(hass_hue)
|
||||
config = Config({'type': 'alexa'})
|
||||
config = Config(None, {'type': 'alexa'})
|
||||
|
||||
HueUsernameView().register(web_app.router)
|
||||
HueAllLightsStateView(config).register(web_app.router)
|
||||
|
@ -1,31 +1,44 @@
|
||||
"""Test the Emulated Hue component."""
|
||||
from unittest.mock import patch
|
||||
import json
|
||||
|
||||
from unittest.mock import patch, Mock, mock_open
|
||||
|
||||
from homeassistant.components.emulated_hue import Config, _LOGGER
|
||||
|
||||
|
||||
def test_config_google_home_entity_id_to_number():
|
||||
"""Test config adheres to the type."""
|
||||
conf = Config({
|
||||
conf = Config(Mock(), {
|
||||
'type': 'google_home'
|
||||
})
|
||||
|
||||
number = conf.entity_id_to_number('light.test')
|
||||
assert number == '1'
|
||||
mop = mock_open(read_data=json.dumps({'1': 'light.test2'}))
|
||||
handle = mop()
|
||||
|
||||
number = conf.entity_id_to_number('light.test')
|
||||
assert number == '1'
|
||||
with patch('homeassistant.components.emulated_hue.open', mop, create=True):
|
||||
number = conf.entity_id_to_number('light.test')
|
||||
assert number == '2'
|
||||
assert handle.write.call_count == 1
|
||||
assert json.loads(handle.write.mock_calls[0][1][0]) == {
|
||||
'1': 'light.test2',
|
||||
'2': 'light.test',
|
||||
}
|
||||
|
||||
number = conf.entity_id_to_number('light.test2')
|
||||
assert number == '2'
|
||||
number = conf.entity_id_to_number('light.test')
|
||||
assert number == '2'
|
||||
assert handle.write.call_count == 1
|
||||
|
||||
entity_id = conf.number_to_entity_id('1')
|
||||
assert entity_id == 'light.test'
|
||||
number = conf.entity_id_to_number('light.test2')
|
||||
assert number == '1'
|
||||
assert handle.write.call_count == 1
|
||||
|
||||
entity_id = conf.number_to_entity_id('1')
|
||||
assert entity_id == 'light.test2'
|
||||
|
||||
|
||||
def test_config_alexa_entity_id_to_number():
|
||||
"""Test config adheres to the type."""
|
||||
conf = Config({
|
||||
conf = Config(None, {
|
||||
'type': 'alexa'
|
||||
})
|
||||
|
||||
@ -45,7 +58,7 @@ def test_config_alexa_entity_id_to_number():
|
||||
def test_warning_config_google_home_listen_port():
|
||||
"""Test we warn when non-default port is used for Google Home."""
|
||||
with patch.object(_LOGGER, 'warning') as mock_warn:
|
||||
Config({
|
||||
Config(None, {
|
||||
'type': 'google_home',
|
||||
'host_ip': '123.123.123.123',
|
||||
'listen_port': 8300
|
||||
|
Loading…
x
Reference in New Issue
Block a user