Store remote domain in Cloud preferences (#64532)
parent
9f12612391
commit
3575009330
|
@ -157,10 +157,10 @@ def async_remote_ui_url(hass: HomeAssistant) -> str:
|
|||
if not hass.data[DOMAIN].client.prefs.remote_enabled:
|
||||
raise CloudNotAvailable
|
||||
|
||||
if not hass.data[DOMAIN].remote.instance_domain:
|
||||
if not (remote_domain := hass.data[DOMAIN].client.prefs.remote_domain):
|
||||
raise CloudNotAvailable
|
||||
|
||||
return f"https://{hass.data[DOMAIN].remote.instance_domain}"
|
||||
return f"https://{remote_domain}"
|
||||
|
||||
|
||||
def is_cloudhook_request(request):
|
||||
|
@ -235,7 +235,12 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
Platform.TTS, DOMAIN, {}, config
|
||||
)
|
||||
|
||||
async def _on_initialized():
|
||||
"""Update preferences."""
|
||||
await prefs.async_update(remote_domain=cloud.remote.instance_domain)
|
||||
|
||||
cloud.iot.register_on_connect(_on_connect)
|
||||
cloud.register_on_initialized(_on_initialized)
|
||||
|
||||
await cloud.initialize()
|
||||
await http_api.async_setup(hass)
|
||||
|
|
|
@ -18,6 +18,7 @@ PREF_ALIASES = "aliases"
|
|||
PREF_SHOULD_EXPOSE = "should_expose"
|
||||
PREF_GOOGLE_LOCAL_WEBHOOK_ID = "google_local_webhook_id"
|
||||
PREF_USERNAME = "username"
|
||||
PREF_REMOTE_DOMAIN = "remote_domain"
|
||||
PREF_ALEXA_DEFAULT_EXPOSE = "alexa_default_expose"
|
||||
PREF_GOOGLE_DEFAULT_EXPOSE = "google_default_expose"
|
||||
PREF_TTS_DEFAULT_VOICE = "tts_default_voice"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "cloud",
|
||||
"name": "Home Assistant Cloud",
|
||||
"documentation": "https://www.home-assistant.io/integrations/cloud",
|
||||
"requirements": ["hass-nabucasa==0.51.0"],
|
||||
"requirements": ["hass-nabucasa==0.52.0"],
|
||||
"dependencies": ["http", "webhook"],
|
||||
"after_dependencies": ["google_assistant", "alexa"],
|
||||
"codeowners": ["@home-assistant/cloud"],
|
||||
|
|
|
@ -30,6 +30,7 @@ from .const import (
|
|||
PREF_GOOGLE_REPORT_STATE,
|
||||
PREF_GOOGLE_SECURE_DEVICES_PIN,
|
||||
PREF_OVERRIDE_NAME,
|
||||
PREF_REMOTE_DOMAIN,
|
||||
PREF_SHOULD_EXPOSE,
|
||||
PREF_TTS_DEFAULT_VOICE,
|
||||
PREF_USERNAME,
|
||||
|
@ -85,6 +86,7 @@ class CloudPreferences:
|
|||
alexa_default_expose=UNDEFINED,
|
||||
google_default_expose=UNDEFINED,
|
||||
tts_default_voice=UNDEFINED,
|
||||
remote_domain=UNDEFINED,
|
||||
):
|
||||
"""Update user preferences."""
|
||||
prefs = {**self._prefs}
|
||||
|
@ -103,6 +105,7 @@ class CloudPreferences:
|
|||
(PREF_ALEXA_DEFAULT_EXPOSE, alexa_default_expose),
|
||||
(PREF_GOOGLE_DEFAULT_EXPOSE, google_default_expose),
|
||||
(PREF_TTS_DEFAULT_VOICE, tts_default_voice),
|
||||
(PREF_REMOTE_DOMAIN, remote_domain),
|
||||
):
|
||||
if value is not UNDEFINED:
|
||||
prefs[key] = value
|
||||
|
@ -208,6 +211,11 @@ class CloudPreferences:
|
|||
|
||||
return True
|
||||
|
||||
@property
|
||||
def remote_domain(self):
|
||||
"""Return remote domain."""
|
||||
return self._prefs.get(PREF_REMOTE_DOMAIN)
|
||||
|
||||
@property
|
||||
def alexa_enabled(self):
|
||||
"""Return if Alexa is enabled."""
|
||||
|
@ -321,5 +329,6 @@ class CloudPreferences:
|
|||
PREF_GOOGLE_ENTITY_CONFIGS: {},
|
||||
PREF_GOOGLE_LOCAL_WEBHOOK_ID: webhook.async_generate_id(),
|
||||
PREF_GOOGLE_SECURE_DEVICES_PIN: None,
|
||||
PREF_REMOTE_DOMAIN: None,
|
||||
PREF_USERNAME: username,
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ async def websocket_get_entity(hass, connection, msg):
|
|||
vol.Coerce(RegistryEntryDisabler), RegistryEntryDisabler.USER.value
|
||||
),
|
||||
),
|
||||
vol.Inclusive("options_domain", "entity_option"): str,
|
||||
vol.Inclusive("options", "entity_option"): vol.Any(None, dict),
|
||||
}
|
||||
)
|
||||
async def websocket_update_entity(hass, connection, msg):
|
||||
|
@ -93,7 +95,8 @@ async def websocket_update_entity(hass, connection, msg):
|
|||
"""
|
||||
registry = await async_get_registry(hass)
|
||||
|
||||
if msg["entity_id"] not in registry.entities:
|
||||
entity_id = msg["entity_id"]
|
||||
if entity_id not in registry.entities:
|
||||
connection.send_message(
|
||||
websocket_api.error_message(msg["id"], ERR_NOT_FOUND, "Entity not found")
|
||||
)
|
||||
|
@ -105,7 +108,7 @@ async def websocket_update_entity(hass, connection, msg):
|
|||
if key in msg:
|
||||
changes[key] = msg[key]
|
||||
|
||||
if "new_entity_id" in msg and msg["new_entity_id"] != msg["entity_id"]:
|
||||
if "new_entity_id" in msg and msg["new_entity_id"] != entity_id:
|
||||
changes["new_entity_id"] = msg["new_entity_id"]
|
||||
if hass.states.get(msg["new_entity_id"]) is not None:
|
||||
connection.send_message(
|
||||
|
@ -118,7 +121,7 @@ async def websocket_update_entity(hass, connection, msg):
|
|||
return
|
||||
|
||||
if "disabled_by" in msg and msg["disabled_by"] is None:
|
||||
entity = registry.entities[msg["entity_id"]]
|
||||
entity = registry.entities[entity_id]
|
||||
if entity.device_id:
|
||||
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||
device = device_registry.async_get(entity.device_id)
|
||||
|
@ -132,12 +135,28 @@ async def websocket_update_entity(hass, connection, msg):
|
|||
|
||||
try:
|
||||
if changes:
|
||||
entry = registry.async_update_entity(msg["entity_id"], **changes)
|
||||
registry.async_update_entity(entity_id, **changes)
|
||||
except ValueError as err:
|
||||
connection.send_message(
|
||||
websocket_api.error_message(msg["id"], "invalid_info", str(err))
|
||||
)
|
||||
return
|
||||
|
||||
if "new_entity_id" in msg:
|
||||
entity_id = msg["new_entity_id"]
|
||||
|
||||
try:
|
||||
if "options_domain" in msg:
|
||||
registry.async_update_entity_options(
|
||||
entity_id, msg["options_domain"], msg["options"]
|
||||
)
|
||||
except ValueError as err:
|
||||
connection.send_message(
|
||||
websocket_api.error_message(msg["id"], "invalid_info", str(err))
|
||||
)
|
||||
return
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
result = {"entity_entry": _entry_ext_dict(entry)}
|
||||
if "disabled_by" in changes and changes["disabled_by"] is None:
|
||||
config_entry = hass.config_entries.async_get_entry(entry.config_entry_id)
|
||||
|
@ -195,6 +214,7 @@ def _entry_ext_dict(entry):
|
|||
data = _entry_dict(entry)
|
||||
data["capabilities"] = entry.capabilities
|
||||
data["device_class"] = entry.device_class
|
||||
data["options"] = entry.options
|
||||
data["original_device_class"] = entry.original_device_class
|
||||
data["original_icon"] = entry.original_icon
|
||||
data["original_name"] = entry.original_name
|
||||
|
|
|
@ -15,7 +15,7 @@ certifi>=2021.5.30
|
|||
ciso8601==2.2.0
|
||||
cryptography==35.0.0
|
||||
emoji==1.5.0
|
||||
hass-nabucasa==0.51.0
|
||||
hass-nabucasa==0.52.0
|
||||
home-assistant-frontend==20220118.0
|
||||
httpx==0.21.0
|
||||
ifaddr==0.1.7
|
||||
|
|
|
@ -809,7 +809,7 @@ habitipy==0.2.0
|
|||
hangups==0.4.17
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.51.0
|
||||
hass-nabucasa==0.52.0
|
||||
|
||||
# homeassistant.components.splunk
|
||||
hass_splunk==0.1.1
|
||||
|
|
|
@ -522,7 +522,7 @@ habitipy==0.2.0
|
|||
hangups==0.4.17
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.51.0
|
||||
hass-nabucasa==0.52.0
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.3.1
|
||||
|
|
|
@ -171,6 +171,7 @@ async def test_remote_ui_url(hass, mock_cloud_fixture):
|
|||
with pytest.raises(cloud.CloudNotAvailable):
|
||||
cloud.async_remote_ui_url(hass)
|
||||
|
||||
cl.remote._instance_domain = "example.com"
|
||||
# Remote finished initializing
|
||||
cl.client.prefs._prefs["remote_domain"] = "example.com"
|
||||
|
||||
assert cloud.async_remote_ui_url(hass) == "https://example.com"
|
||||
|
|
|
@ -111,6 +111,7 @@ async def test_get_entity(hass, client):
|
|||
"entity_id": "test_domain.name",
|
||||
"icon": None,
|
||||
"name": "Hello World",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -138,6 +139,7 @@ async def test_get_entity(hass, client):
|
|||
"entity_id": "test_domain.no_name",
|
||||
"icon": None,
|
||||
"name": None,
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -197,6 +199,7 @@ async def test_update_entity(hass, client):
|
|||
"entity_id": "test_domain.world",
|
||||
"icon": "icon:after update",
|
||||
"name": "after update",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -250,6 +253,7 @@ async def test_update_entity(hass, client):
|
|||
"entity_id": "test_domain.world",
|
||||
"icon": "icon:after update",
|
||||
"name": "after update",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -259,6 +263,40 @@ async def test_update_entity(hass, client):
|
|||
"reload_delay": 30,
|
||||
}
|
||||
|
||||
# UPDATE ENTITY OPTION
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 9,
|
||||
"type": "config/entity_registry/update",
|
||||
"entity_id": "test_domain.world",
|
||||
"options_domain": "sensor",
|
||||
"options": {"unit_of_measurement": "beard_second"},
|
||||
}
|
||||
)
|
||||
|
||||
msg = await client.receive_json()
|
||||
|
||||
assert msg["result"] == {
|
||||
"entity_entry": {
|
||||
"area_id": "mock-area-id",
|
||||
"capabilities": None,
|
||||
"config_entry_id": None,
|
||||
"device_class": "custom_device_class",
|
||||
"device_id": None,
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test_domain.world",
|
||||
"icon": "icon:after update",
|
||||
"name": "after update",
|
||||
"options": {"sensor": {"unit_of_measurement": "beard_second"}},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
"platform": "test_platform",
|
||||
"unique_id": "1234",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def test_update_entity_require_restart(hass, client):
|
||||
"""Test updating entity."""
|
||||
|
@ -307,6 +345,7 @@ async def test_update_entity_require_restart(hass, client):
|
|||
"entity_id": "test_domain.world",
|
||||
"icon": None,
|
||||
"name": None,
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -411,6 +450,7 @@ async def test_update_entity_no_changes(hass, client):
|
|||
"entity_id": "test_domain.world",
|
||||
"icon": None,
|
||||
"name": "name of entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
@ -494,6 +534,7 @@ async def test_update_entity_id(hass, client):
|
|||
"entity_id": "test_domain.planet",
|
||||
"icon": None,
|
||||
"name": None,
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": None,
|
||||
|
|
Loading…
Reference in New Issue