Merge pull request #59951 from home-assistant/rc

This commit is contained in:
Paulus Schoutsen 2021-11-19 12:40:52 -08:00 committed by GitHub
commit dbae448fe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 169 additions and 54 deletions

View File

@ -155,7 +155,6 @@ class DenonDevice(MediaPlayerEntity):
name=config_entry.title, name=config_entry.title,
) )
self._attr_sound_mode_list = receiver.sound_mode_list self._attr_sound_mode_list = receiver.sound_mode_list
self._attr_source_list = receiver.input_func_list
self._receiver = receiver self._receiver = receiver
self._update_audyssey = update_audyssey self._update_audyssey = update_audyssey
@ -246,6 +245,11 @@ class DenonDevice(MediaPlayerEntity):
"""Return the state of the device.""" """Return the state of the device."""
return self._receiver.state return self._receiver.state
@property
def source_list(self):
"""Return a list of available input sources."""
return self._receiver.input_func_list
@property @property
def is_volume_muted(self): def is_volume_muted(self):
"""Return boolean if volume is currently muted.""" """Return boolean if volume is currently muted."""

View File

@ -92,5 +92,5 @@ class FritzBoxBinarySensor(FritzBoxBaseEntity, BinarySensorEntity):
self._attr_is_on = self._fritzbox_tools.update_available self._attr_is_on = self._fritzbox_tools.update_available
self._attr_extra_state_attributes = { self._attr_extra_state_attributes = {
"installed_version": self._fritzbox_tools.current_firmware, "installed_version": self._fritzbox_tools.current_firmware,
"latest_available_version:": self._fritzbox_tools.latest_firmware, "latest_available_version": self._fritzbox_tools.latest_firmware,
} }

View File

@ -330,13 +330,19 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
return self.async_create_entry(title="", data=self.hk_options) return self.async_create_entry(title="", data=self.hk_options)
all_supported_devices = await _async_get_supported_devices(self.hass) all_supported_devices = await _async_get_supported_devices(self.hass)
# Strip out devices that no longer exist to prevent error in the UI
devices = [
device_id
for device_id in self.hk_options.get(CONF_DEVICES, [])
if device_id in all_supported_devices
]
return self.async_show_form( return self.async_show_form(
step_id="advanced", step_id="advanced",
data_schema=vol.Schema( data_schema=vol.Schema(
{ {
vol.Optional( vol.Optional(CONF_DEVICES, default=devices): cv.multi_select(
CONF_DEVICES, default=self.hk_options.get(CONF_DEVICES, []) all_supported_devices
): cv.multi_select(all_supported_devices) )
} }
), ),
) )
@ -445,13 +451,16 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
) )
data_schema = {} data_schema = {}
entities = entity_filter.get(CONF_INCLUDE_ENTITIES, []) entity_schema = vol.In
if self.hk_options[CONF_HOMEKIT_MODE] == HOMEKIT_MODE_ACCESSORY: # Strip out entities that no longer exist to prevent error in the UI
entity_schema = vol.In entities = [
else: entity_id
if entities: for entity_id in entity_filter.get(CONF_INCLUDE_ENTITIES, [])
include_exclude_mode = MODE_INCLUDE if entity_id in all_supported_entities
else: ]
if self.hk_options[CONF_HOMEKIT_MODE] != HOMEKIT_MODE_ACCESSORY:
include_exclude_mode = MODE_INCLUDE
if not entities:
include_exclude_mode = MODE_EXCLUDE include_exclude_mode = MODE_EXCLUDE
entities = entity_filter.get(CONF_EXCLUDE_ENTITIES, []) entities = entity_filter.get(CONF_EXCLUDE_ENTITIES, [])
data_schema[ data_schema[

View File

@ -173,6 +173,8 @@ class NetgearRouter:
"link_rate": None, "link_rate": None,
"signal": None, "signal": None,
"ip": None, "ip": None,
"ssid": None,
"conn_ap_mac": None,
} }
await self.async_update_device_trackers() await self.async_update_device_trackers()

View File

@ -66,7 +66,7 @@ class NetgearSensorEntity(NetgearDeviceEntity, SensorEntity):
self.entity_description = SENSOR_TYPES[self._attribute] self.entity_description = SENSOR_TYPES[self._attribute]
self._name = f"{self.get_device_name()} {self.entity_description.name}" self._name = f"{self.get_device_name()} {self.entity_description.name}"
self._unique_id = f"{self._mac}-{self._attribute}" self._unique_id = f"{self._mac}-{self._attribute}"
self._state = self._device[self._attribute] self._state = self._device.get(self._attribute)
@property @property
def native_value(self): def native_value(self):
@ -78,7 +78,7 @@ class NetgearSensorEntity(NetgearDeviceEntity, SensorEntity):
"""Update the Netgear device.""" """Update the Netgear device."""
self._device = self._router.devices[self._mac] self._device = self._router.devices[self._mac]
self._active = self._device["active"] self._active = self._device["active"]
if self._device[self._attribute] is not None: if self._device.get(self._attribute) is not None:
self._state = self._device[self._attribute] self._state = self._device[self._attribute]
self.async_write_ha_state() self.async_write_ha_state()

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges." "single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
}, },
"create_entry": { "create_entry": {
"default": "\n\nAndroidon, nyissa meg [az OwnTracks appot]({android_url}), majd v\u00e1lassza ki a Preferences -> Connection men\u00fct. V\u00e1ltoztassa meg az al\u00e1bbi be\u00e1ll\u00edt\u00e1sokat:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `<Your name>`\n - Device ID: `<Your device name>`\n\niOS-en, nyissa meg [az OwnTracks appot]({ios_url}), kattintson az (i) ikonra bal oldalon fel\u00fcl -> settings. V\u00e1ltoztassa meg az al\u00e1bbi be\u00e1ll\u00edt\u00e1sokat:\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `<Your name>`\n\n{secret}\n\nN\u00e9zze meg [a dokument\u00e1ci\u00f3t]({docs_url}) tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt." "default": "\n\nAndroidon, nyissa meg [az OwnTracks appot]({android_url}), majd v\u00e1lassza ki a Preferences -> Connection men\u00fct. V\u00e1ltoztassa meg az al\u00e1bbi be\u00e1ll\u00edt\u00e1sokat:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `'<Your name>'`\n - Device ID: `'<Your device name>'`\n\niOS-en, nyissa meg [az OwnTracks appot]({ios_url}), kattintson az (i) ikonra bal oldalon fel\u00fcl -> settings. V\u00e1ltoztassa meg az al\u00e1bbi be\u00e1ll\u00edt\u00e1sokat:\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `'<Your name>'`\n\n{secret}\n\nN\u00e9zze meg [a dokument\u00e1ci\u00f3t]({docs_url}) tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun ass m\u00e9iglech." "single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun ass m\u00e9iglech."
}, },
"create_entry": { "create_entry": {
"default": "\n\nOp Android, an [der OwnTracks App]({android_url}), g\u00e9i an Preferences -> Connection. \u00c4nnert folgend Astellungen:\n- Mode: Private HTTP\n- Host {webhook_url}\n- Identification:\n - Username: `<Your name>`\n - Device ID: `<Your device name>`\n\nOp IOS, an [der OwnTracks App]({ios_url}), klick op (i) Ikon uewen l\u00e9nks -> Settings. \u00c4nnert folgend Astellungen:\n- Mode: HTTP\n- URL: {webhook_url}\n- Turn on authentication:\n- UserID: `<Your name>`\n\n{secret}\n\nKuck w.e.g. [Dokumentatioun]({docs_url}) fir m\u00e9i Informatiounen." "default": "\n\nOp Android, an [der OwnTracks App]({android_url}), g\u00e9i an Preferences -> Connection. \u00c4nnert folgend Astellungen:\n- Mode: Private HTTP\n- Host {webhook_url}\n- Identification:\n - Username: `'<Your name>'`\n - Device ID: `'<Your device name>'`\n\nOp IOS, an [der OwnTracks App]({ios_url}), klick op (i) Ikon uewen l\u00e9nks -> Settings. \u00c4nnert folgend Astellungen:\n- Mode: HTTP\n- URL: {webhook_url}\n- Turn on authentication:\n- UserID: `'<Your name>'`\n\n{secret}\n\nKuck w.e.g. [Dokumentatioun]({docs_url}) fir m\u00e9i Informatiounen."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk." "single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk."
}, },
"create_entry": { "create_entry": {
"default": "\n\nOp Android, open [the OwnTracks app]({android_url}), ga naar 'preferences' -> 'connection'. Verander de volgende instellingen:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `<Your name>`\n - Device ID: `<Your device name>`\n\nOp iOS, open [the OwnTracks app]({ios_url}), tik op het (i) icoon links boven -> 'settings'. Verander de volgende instellingen:\n - Mode: HTTP\n - URL: {webhook_url}\n - zet 'authentication' aan\n - UserID: `<Your name>`\n\n{secret}\n\nZie [the documentation]({docs_url}) voor meer informatie." "default": "\n\nOp Android, open [the OwnTracks app]({android_url}), ga naar 'preferences' -> 'connection'. Verander de volgende instellingen:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `'<Your name>'`\n - Device ID: `'<Your device name>'`\n\nOp iOS, open [the OwnTracks app]({ios_url}), tik op het (i) icoon links boven -> 'settings'. Verander de volgende instellingen:\n - Mode: HTTP\n - URL: {webhook_url}\n - zet 'authentication' aan\n - UserID: `'<Your name>'`\n\n{secret}\n\nZie [the documentation]({docs_url}) voor meer informatie."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja." "single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
}, },
"create_entry": { "create_entry": {
"default": "\n\nNa Androidzie, otw\u00f3rz [aplikacj\u0119 OwnTracks]({android_url}), id\u017a do: ustawienia -> po\u0142\u0105czenia. Zmie\u0144 nast\u0119puj\u0105ce ustawienia:\n - Tryb: Private HTTP\n - Host: {webhook_url}\n - Identyfikacja:\n - Nazwa u\u017cytkownika: `<Your name>`\n - ID urz\u0105dzenia: `<Your device name>`\n\nNa iOS, otw\u00f3rz [aplikacj\u0119 OwnTracks]({ios_url}), naci\u015bnij ikon\u0119 (i) w lewym g\u00f3rnym rogu -> ustawienia. Zmie\u0144 nast\u0119puj\u0105ce ustawienia:\n - Tryb: HTTP\n - URL: {webhook_url}\n - W\u0142\u0105cz uwierzytelnianie\n - ID u\u017cytkownika: `<Your name>`\n\n{secret}\n\nZapoznaj si\u0119 z [dokumentacj\u0105]({docs_url}), by pozna\u0107 szczeg\u00f3\u0142y." "default": "\n\nNa Androidzie, otw\u00f3rz [aplikacj\u0119 OwnTracks]({android_url}), id\u017a do: ustawienia -> po\u0142\u0105czenia. Zmie\u0144 nast\u0119puj\u0105ce ustawienia:\n - Tryb: Private HTTP\n - Host: {webhook_url}\n - Identyfikacja:\n - Nazwa u\u017cytkownika: `'<Your name>'`\n - ID urz\u0105dzenia: `'<Your device name>'`\n\nNa iOS, otw\u00f3rz [aplikacj\u0119 OwnTracks]({ios_url}), naci\u015bnij ikon\u0119 (i) w lewym g\u00f3rnym rogu -> ustawienia. Zmie\u0144 nast\u0119puj\u0105ce ustawienia:\n - Tryb: HTTP\n - URL: {webhook_url}\n - W\u0142\u0105cz uwierzytelnianie\n - ID u\u017cytkownika: `'<Your name>'`\n\n{secret}\n\nZapoznaj si\u0119 z [dokumentacj\u0105]({docs_url}), by pozna\u0107 szczeg\u00f3\u0142y."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e." "single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e."
}, },
"create_entry": { "create_entry": {
"default": "\u0415\u0441\u043b\u0438 \u0412\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 Android, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 [OwnTracks]({android_url}), \u0437\u0430\u0442\u0435\u043c preferences -> connection. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0430\u043a, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `<Your name>`\n - Device ID: `<Your device name>`\n\n\u0415\u0441\u043b\u0438 \u0412\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 iOS, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 [OwnTracks]({ios_url}), \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a (i) \u0432 \u043b\u0435\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 -> settings. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0430\u043a, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `<Your name>`\n\n{secret}\n\n\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 [\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439]({docs_url}) \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438." "default": "\u0415\u0441\u043b\u0438 \u0412\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 Android, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 [OwnTracks]({android_url}), \u0437\u0430\u0442\u0435\u043c preferences -> connection. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0430\u043a, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `'<Your name>'`\n - Device ID: `'<Your device name>'`\n\n\u0415\u0441\u043b\u0438 \u0412\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 iOS, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 [OwnTracks]({ios_url}), \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a (i) \u0432 \u043b\u0435\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 -> settings. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0430\u043a, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435:\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `'<Your name>'`\n\n{secret}\n\n\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 [\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439]({docs_url}) \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -1,7 +1,7 @@
{ {
"config": { "config": {
"create_entry": { "create_entry": {
"default": "\n\n P\u00e5 Android, \u00f6ppna [OwnTracks-appen]({android_url}), g\u00e5 till inst\u00e4llningar -> anslutning. \u00c4ndra f\u00f6ljande inst\u00e4llningar: \n - L\u00e4ge: Privat HTTP \n - V\u00e4rden: {webhook_url}\n - Identifiering: \n - Anv\u00e4ndarnamn: `<Your name>`\n - Enhets-ID: `<Your device name>` \n\n P\u00e5 IOS, \u00f6ppna [OwnTracks-appen]({ios_url}), tryck p\u00e5 (i) ikonen i \u00f6vre v\u00e4nstra h\u00f6rnet -> inst\u00e4llningarna. \u00c4ndra f\u00f6ljande inst\u00e4llningar: \n - L\u00e4ge: HTTP \n - URL: {webhook_url}\n - Sl\u00e5 p\u00e5 autentisering \n - UserID: `<Your name>` \n\n {secret} \n \n Se [dokumentationen]({docs_url}) f\u00f6r mer information." "default": "\n\n P\u00e5 Android, \u00f6ppna [OwnTracks-appen]({android_url}), g\u00e5 till inst\u00e4llningar -> anslutning. \u00c4ndra f\u00f6ljande inst\u00e4llningar: \n - L\u00e4ge: Privat HTTP \n - V\u00e4rden: {webhook_url}\n - Identifiering: \n - Anv\u00e4ndarnamn: `'<Your name>'`\n - Enhets-ID: `'<Your device name>'` \n\n P\u00e5 IOS, \u00f6ppna [OwnTracks-appen]({ios_url}), tryck p\u00e5 (i) ikonen i \u00f6vre v\u00e4nstra h\u00f6rnet -> inst\u00e4llningarna. \u00c4ndra f\u00f6ljande inst\u00e4llningar: \n - L\u00e4ge: HTTP \n - URL: {webhook_url}\n - Sl\u00e5 p\u00e5 autentisering \n - UserID: `'<Your name>'` \n\n {secret} \n \n Se [dokumentationen]({docs_url}) f\u00f6r mer information."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e. \u041c\u043e\u0436\u043d\u0430 \u0434\u043e\u0434\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e." "single_instance_allowed": "\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e. \u041c\u043e\u0436\u043d\u0430 \u0434\u043e\u0434\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e."
}, },
"create_entry": { "create_entry": {
"default": "\u042f\u043a\u0449\u043e \u0412\u0430\u0448 \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043f\u0440\u0430\u0446\u044e\u0454 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u0456\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0456 Android, \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043e\u043a [OwnTracks]({android_url}), \u043f\u043e\u0442\u0456\u043c preferences - > connection. \u0417\u043c\u0456\u043d\u0456\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0442\u0430\u043a, \u044f\u043a \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0438\u0436\u0447\u0435:\n- Mode: Private HTTP\n- Host: {webhook_url}\n- Identification:\n- Username: `<Your name>`\n- Device ID: `<Your device name>` \n\n\u042f\u043a\u0449\u043e \u0412\u0430\u0448 \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043f\u0440\u0430\u0446\u044e\u0454 \u043d\u0430 iOS, \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043e\u043a [OwnTracks]({ios_url}), \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a (i) \u0432 \u043b\u0456\u0432\u043e\u043c\u0443 \u0432\u0435\u0440\u0445\u043d\u044c\u043e\u043c\u0443 \u043a\u0443\u0442\u043a\u0443 - > settings. \u0417\u043c\u0456\u043d\u0456\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0442\u0430\u043a, \u044f\u043a \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0438\u0436\u0447\u0435:\n- Mode: HTTP\n- URL: {webhook_url}\n- Turn on authentication\n- UserID: `<Your name>`\n\n{secret}\n\n\u041e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 [\u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u044f\u043c\u0438]({docs_url}) \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u0431\u0456\u043b\u044c\u0448 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457." "default": "\u042f\u043a\u0449\u043e \u0412\u0430\u0448 \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043f\u0440\u0430\u0446\u044e\u0454 \u043d\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u0456\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0456 Android, \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043e\u043a [OwnTracks]({android_url}), \u043f\u043e\u0442\u0456\u043c preferences - > connection. \u0417\u043c\u0456\u043d\u0456\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0442\u0430\u043a, \u044f\u043a \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0438\u0436\u0447\u0435:\n- Mode: Private HTTP\n- Host: {webhook_url}\n- Identification:\n- Username: `'<Your name>'`\n- Device ID: `'<Your device name>'` \n\n\u042f\u043a\u0449\u043e \u0412\u0430\u0448 \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043f\u0440\u0430\u0446\u044e\u0454 \u043d\u0430 iOS, \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043e\u043a [OwnTracks]({ios_url}), \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043d\u0430 \u0437\u043d\u0430\u0447\u043e\u043a (i) \u0432 \u043b\u0456\u0432\u043e\u043c\u0443 \u0432\u0435\u0440\u0445\u043d\u044c\u043e\u043c\u0443 \u043a\u0443\u0442\u043a\u0443 - > settings. \u0417\u043c\u0456\u043d\u0456\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0442\u0430\u043a, \u044f\u043a \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0438\u0436\u0447\u0435:\n- Mode: HTTP\n- URL: {webhook_url}\n- Turn on authentication\n- UserID: `'<Your name>'`\n\n{secret}\n\n\u041e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 [\u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u044f\u043c\u0438]({docs_url}) \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u0431\u0456\u043b\u044c\u0448 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -1,7 +1,7 @@
{ {
"config": { "config": {
"create_entry": { "create_entry": {
"default": "\n\n\u5728 Android \u8bbe\u5907\u4e0a\uff0c\u6253\u5f00 [OwnTracks APP]({android_url})\uff0c\u524d\u5f80 Preferences -> Connection\u3002\u4fee\u6539\u4ee5\u4e0b\u8bbe\u5b9a\uff1a\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `<Your name>`\n - Device ID: `<Your device name>`\n\n\u5728 iOS \u8bbe\u5907\u4e0a\uff0c\u6253\u5f00 [OwnTracks APP]({ios_url})\uff0c\u70b9\u51fb\u5de6\u4e0a\u89d2\u7684 (i) \u56fe\u6807-> Settings\u3002\u4fee\u6539\u4ee5\u4e0b\u8bbe\u5b9a\uff1a\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `<Your name>`\n\n{secret}\n\n\u8bf7\u53c2\u9605[\u6587\u6863]({docs_url})\u4ee5\u4e86\u89e3\u66f4\u591a\u4fe1\u606f\u3002" "default": "\n\n\u5728 Android \u8bbe\u5907\u4e0a\uff0c\u6253\u5f00 [OwnTracks APP]({android_url})\uff0c\u524d\u5f80 Preferences -> Connection\u3002\u4fee\u6539\u4ee5\u4e0b\u8bbe\u5b9a\uff1a\n - Mode: Private HTTP\n - Host: {webhook_url}\n - Identification:\n - Username: `'<Your name>'`\n - Device ID: `'<Your device name>'`\n\n\u5728 iOS \u8bbe\u5907\u4e0a\uff0c\u6253\u5f00 [OwnTracks APP]({ios_url})\uff0c\u70b9\u51fb\u5de6\u4e0a\u89d2\u7684 (i) \u56fe\u6807-> Settings\u3002\u4fee\u6539\u4ee5\u4e0b\u8bbe\u5b9a\uff1a\n - Mode: HTTP\n - URL: {webhook_url}\n - Turn on authentication\n - UserID: `'<Your name>'`\n\n{secret}\n\n\u8bf7\u53c2\u9605[\u6587\u6863]({docs_url})\u4ee5\u4e86\u89e3\u66f4\u591a\u4fe1\u606f\u3002"
}, },
"step": { "step": {
"user": { "user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002" "single_instance_allowed": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"
}, },
"create_entry": { "create_entry": {
"default": "\n\n\u65bc Android \u8a2d\u5099\uff0c\u6253\u958b [OwnTracks app]({android_url})\u3001\u9ede\u9078\u8a2d\u5b9a\uff08preferences\uff09 -> \u9023\u7dda\uff08connection\uff09\u3002\u8b8a\u66f4\u4ee5\u4e0b\u8a2d\u5b9a\uff1a\n - \u6a21\u5f0f\uff08Mode\uff09\uff1aPrivate HTTP\n - \u4e3b\u6a5f\u7aef\uff08Host\uff09\uff1a{webhook_url}\n - Identification\uff1a\n - Username\uff1a `<Your name>`\n - Device ID\uff1a`<Your device name>`\n\n\u65bc iOS \u8a2d\u5099\uff0c\u6253\u958b [OwnTracks app]({ios_url})\u3001\u9ede\u9078\u5de6\u4e0a\u65b9\u7684 (i) \u5716\u793a -> \u8a2d\u5b9a\uff08settings\uff09\u3002\u8b8a\u66f4\u4ee5\u4e0b\u8a2d\u5b9a\uff1a\n - \u6a21\u5f0f\uff08Mode\uff09\uff1aHTTP\n - URL: {webhook_url}\n - \u958b\u555f authentication\n - UserID: `<Your name>`\n\n{secret}\n\n\u8acb\u53c3\u95b1 [\u6587\u4ef6]({docs_url})\u4ee5\u4e86\u89e3\u66f4\u8a73\u7d30\u8cc7\u6599\u3002" "default": "\n\n\u65bc Android \u8a2d\u5099\uff0c\u6253\u958b [OwnTracks app]({android_url})\u3001\u9ede\u9078\u8a2d\u5b9a\uff08preferences\uff09 -> \u9023\u7dda\uff08connection\uff09\u3002\u8b8a\u66f4\u4ee5\u4e0b\u8a2d\u5b9a\uff1a\n - \u6a21\u5f0f\uff08Mode\uff09\uff1aPrivate HTTP\n - \u4e3b\u6a5f\u7aef\uff08Host\uff09\uff1a{webhook_url}\n - Identification\uff1a\n - Username\uff1a `'<Your name>'`\n - Device ID\uff1a`'<Your device name>'`\n\n\u65bc iOS \u8a2d\u5099\uff0c\u6253\u958b [OwnTracks app]({ios_url})\u3001\u9ede\u9078\u5de6\u4e0a\u65b9\u7684 (i) \u5716\u793a -> \u8a2d\u5b9a\uff08settings\uff09\u3002\u8b8a\u66f4\u4ee5\u4e0b\u8a2d\u5b9a\uff1a\n - \u6a21\u5f0f\uff08Mode\uff09\uff1aHTTP\n - URL: {webhook_url}\n - \u958b\u555f authentication\n - UserID: `'<Your name>'`\n\n{secret}\n\n\u8acb\u53c3\u95b1 [\u6587\u4ef6]({docs_url})\u4ee5\u4e86\u89e3\u66f4\u8a73\u7d30\u8cc7\u6599\u3002"
}, },
"step": { "step": {
"user": { "user": {

View File

@ -267,11 +267,13 @@ class SonosDiscoveryManager:
if change == ssdp.SsdpChange.BYEBYE: if change == ssdp.SsdpChange.BYEBYE:
return return
uid = info.get(ssdp.ATTR_UPNP_UDN)
if not uid.startswith("uuid:RINCON_"):
return
uid = uid[5:]
discovered_ip = urlparse(info[ssdp.ATTR_SSDP_LOCATION]).hostname discovered_ip = urlparse(info[ssdp.ATTR_SSDP_LOCATION]).hostname
boot_seqnum = info.get("X-RINCON-BOOTSEQ") boot_seqnum = info.get("X-RINCON-BOOTSEQ")
uid = info.get(ssdp.ATTR_UPNP_UDN)
if uid.startswith("uuid:"):
uid = uid[5:]
self.async_discovered_player( self.async_discovered_player(
"SSDP", info, discovered_ip, uid, boot_seqnum, info.get("modelName"), None "SSDP", info, discovered_ip, uid, boot_seqnum, info.get("modelName"), None
) )

View File

@ -46,6 +46,10 @@ class IntegerTypeData:
"""Scale a value.""" """Scale a value."""
return value * 1.0 / (10 ** self.scale) return value * 1.0 / (10 ** self.scale)
def scale_value_back(self, value: float | int) -> int:
"""Return raw value for scaled."""
return int(value * (10 ** self.scale))
def remap_value_to( def remap_value_to(
self, self,
value: float, value: float,

View File

@ -322,7 +322,7 @@ class TuyaClimateEntity(TuyaEntity, ClimateEntity):
[ [
{ {
"code": self._set_humidity_dpcode, "code": self._set_humidity_dpcode,
"value": self._set_humidity_type.scale_value(humidity), "value": self._set_humidity_type.scale_value_back(humidity),
} }
] ]
) )
@ -364,7 +364,9 @@ class TuyaClimateEntity(TuyaEntity, ClimateEntity):
{ {
"code": self._set_temperature_dpcode, "code": self._set_temperature_dpcode,
"value": round( "value": round(
self._set_temperature_type.scale_value(kwargs["temperature"]) self._set_temperature_type.scale_value_back(
kwargs["temperature"]
)
), ),
} }
] ]

View File

@ -165,7 +165,7 @@ class TuyaHumidifierEntity(TuyaEntity, HumidifierEntity):
[ [
{ {
"code": self.entity_description.humidity, "code": self.entity_description.humidity,
"value": self._set_humidity_type.scale_value(humidity), "value": self._set_humidity_type.scale_value_back(humidity),
} }
] ]
) )

View File

@ -259,9 +259,9 @@ class TuyaNumberEntity(TuyaEntity, NumberEntity):
# and determine unit of measurement # and determine unit of measurement
if self._status_range.type == "Integer": if self._status_range.type == "Integer":
self._type_data = IntegerTypeData.from_json(self._status_range.values) self._type_data = IntegerTypeData.from_json(self._status_range.values)
self._attr_max_value = self._type_data.max self._attr_max_value = self._type_data.max_scaled
self._attr_min_value = self._type_data.min self._attr_min_value = self._type_data.min_scaled
self._attr_step = self._type_data.step self._attr_step = self._type_data.step_scaled
if description.unit_of_measurement is None: if description.unit_of_measurement is None:
self._attr_unit_of_measurement = self._type_data.unit self._attr_unit_of_measurement = self._type_data.unit
@ -290,7 +290,7 @@ class TuyaNumberEntity(TuyaEntity, NumberEntity):
[ [
{ {
"code": self.entity_description.key, "code": self.entity_description.key,
"value": self._type_data.scale_value(value), "value": self._type_data.scale_value_back(value),
} }
] ]
) )

View File

@ -2,7 +2,7 @@
"domain": "velbus", "domain": "velbus",
"name": "Velbus", "name": "Velbus",
"documentation": "https://www.home-assistant.io/integrations/velbus", "documentation": "https://www.home-assistant.io/integrations/velbus",
"requirements": ["velbus-aio==2021.11.6"], "requirements": ["velbus-aio==2021.11.7"],
"config_flow": true, "config_flow": true,
"codeowners": ["@Cereal2nd", "@brefra"], "codeowners": ["@Cereal2nd", "@brefra"],
"iot_class": "local_push" "iot_class": "local_push"

View File

@ -5,7 +5,7 @@ from typing import Final
MAJOR_VERSION: Final = 2021 MAJOR_VERSION: Final = 2021
MINOR_VERSION: Final = 11 MINOR_VERSION: Final = 11
PATCH_VERSION: Final = "4" PATCH_VERSION: Final = "5"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0) REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import asyncio import asyncio
from collections.abc import Callable from collections.abc import Callable
from contextlib import suppress from contextlib import suppress
from copy import deepcopy
from json import JSONEncoder from json import JSONEncoder
import logging import logging
import os import os
@ -130,6 +131,10 @@ class Store:
# If we didn't generate data yet, do it now. # If we didn't generate data yet, do it now.
if "data_func" in data: if "data_func" in data:
data["data"] = data.pop("data_func")() data["data"] = data.pop("data_func")()
# We make a copy because code might assume it's safe to mutate loaded data
# and we don't want that to mess with what we're trying to store.
data = deepcopy(data)
else: else:
data = await self.hass.async_add_executor_job( data = await self.hass.async_add_executor_job(
json_util.load_json, self.path json_util.load_json, self.path

View File

@ -2360,7 +2360,7 @@ uvcclient==0.11.0
vallox-websocket-api==2.8.1 vallox-websocket-api==2.8.1
# homeassistant.components.velbus # homeassistant.components.velbus
velbus-aio==2021.11.6 velbus-aio==2021.11.7
# homeassistant.components.venstar # homeassistant.components.venstar
venstarcolortouch==0.14 venstarcolortouch==0.14

View File

@ -1364,7 +1364,7 @@ url-normalize==1.4.1
uvcclient==0.11.0 uvcclient==0.11.0
# homeassistant.components.velbus # homeassistant.components.velbus
velbus-aio==2021.11.6 velbus-aio==2021.11.7
# homeassistant.components.venstar # homeassistant.components.venstar
venstarcolortouch==0.14 venstarcolortouch==0.14

View File

@ -365,7 +365,24 @@ async def test_options_flow_devices(
mock_hap, hass, demo_cleanup, device_reg, entity_reg, mock_get_source_ip mock_hap, hass, demo_cleanup, device_reg, entity_reg, mock_get_source_ip
): ):
"""Test devices can be bridged.""" """Test devices can be bridged."""
config_entry = _mock_config_entry_with_options_populated() config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_NAME: "mock_name", CONF_PORT: 12345},
options={
"devices": ["notexist"],
"filter": {
"include_domains": [
"fan",
"humidifier",
"vacuum",
"media_player",
"climate",
"alarm_control_panel",
],
"exclude_entities": ["climate.front_gate"],
},
},
)
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
demo_config_entry = MockConfigEntry(domain="domain") demo_config_entry = MockConfigEntry(domain="domain")
@ -491,6 +508,60 @@ async def test_options_flow_devices_preserved_when_advanced_off(
} }
async def test_options_flow_with_non_existant_entity(hass, mock_get_source_ip):
"""Test config flow options in include mode."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_NAME: "mock_name", CONF_PORT: 12345},
options={
"filter": {
"include_entities": ["climate.not_exist", "climate.front_gate"],
},
},
)
config_entry.add_to_hass(hass)
hass.states.async_set("climate.front_gate", "off")
hass.states.async_set("climate.new", "off")
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(
config_entry.entry_id, context={"show_advanced_options": False}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"domains": ["fan", "vacuum", "climate"]},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "include_exclude"
entities = result["data_schema"]({})["entities"]
assert "climate.not_exist" not in entities
result2 = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
"entities": ["climate.new", "climate.front_gate"],
"include_exclude_mode": "include",
},
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert config_entry.options == {
"mode": "bridge",
"filter": {
"exclude_domains": [],
"exclude_entities": [],
"include_domains": ["fan", "vacuum"],
"include_entities": ["climate.new", "climate.front_gate"],
},
}
async def test_options_flow_include_mode_basic(hass, mock_get_source_ip): async def test_options_flow_include_mode_basic(hass, mock_get_source_ip):
"""Test config flow options in include mode.""" """Test config flow options in include mode."""

View File

@ -93,7 +93,7 @@ def discover_fixture(soco):
async def do_callback(hass, callback, *args, **kwargs): async def do_callback(hass, callback, *args, **kwargs):
await callback( await callback(
{ {
ssdp.ATTR_UPNP_UDN: soco.uid, ssdp.ATTR_UPNP_UDN: f"uuid:{soco.uid}",
ssdp.ATTR_SSDP_LOCATION: f"http://{soco.ip_address}/", ssdp.ATTR_SSDP_LOCATION: f"http://{soco.ip_address}/",
}, },
ssdp.SsdpChange.ALIVE, ssdp.SsdpChange.ALIVE,

View File

@ -49,7 +49,7 @@ import homeassistant.util.dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
DEFAULT_CONFIG_ENTRY_ID = 1 DEFAULT_CONFIG_ENTRY_ID = "1"
DEFAULT_HOST = "1.2.3.4" DEFAULT_HOST = "1.2.3.4"
DEFAULT_SITE = "site_id" DEFAULT_SITE = "site_id"

View File

@ -1089,7 +1089,7 @@ async def test_restoring_client(hass, aioclient_mock):
data=ENTRY_CONFIG, data=ENTRY_CONFIG,
source="test", source="test",
options={}, options={},
entry_id=1, entry_id="1",
) )
registry = er.async_get(hass) registry = er.async_get(hass)

View File

@ -14,7 +14,7 @@ from .test_controller import (
setup_unifi_integration, setup_unifi_integration,
) )
from tests.common import MockConfigEntry from tests.common import MockConfigEntry, flush_store
async def test_setup_with_no_config(hass): async def test_setup_with_no_config(hass):
@ -110,6 +110,7 @@ async def test_wireless_clients(hass, hass_storage, aioclient_mock):
config_entry = await setup_unifi_integration( config_entry = await setup_unifi_integration(
hass, aioclient_mock, clients_response=[client_1, client_2] hass, aioclient_mock, clients_response=[client_1, client_2]
) )
await flush_store(hass.data[unifi.UNIFI_WIRELESS_CLIENTS]._store)
for mac in [ for mac in [
"00:00:00:00:00:00", "00:00:00:00:00:00",

View File

@ -22,6 +22,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
from .test_controller import ( from .test_controller import (
CONTROLLER_HOST, CONTROLLER_HOST,
DEFAULT_CONFIG_ENTRY_ID,
DESCRIPTION, DESCRIPTION,
ENTRY_CONFIG, ENTRY_CONFIG,
setup_unifi_integration, setup_unifi_integration,
@ -857,7 +858,7 @@ async def test_restore_client_succeed(hass, aioclient_mock):
data=ENTRY_CONFIG, data=ENTRY_CONFIG,
source="test", source="test",
options={}, options={},
entry_id=1, entry_id=DEFAULT_CONFIG_ENTRY_ID,
) )
registry = er.async_get(hass) registry = er.async_get(hass)
@ -947,7 +948,7 @@ async def test_restore_client_no_old_state(hass, aioclient_mock):
data=ENTRY_CONFIG, data=ENTRY_CONFIG,
source="test", source="test",
options={}, options={},
entry_id=1, entry_id=DEFAULT_CONFIG_ENTRY_ID,
) )
registry = er.async_get(hass) registry = er.async_get(hass)

View File

@ -25,7 +25,7 @@ MOCK_DATA2 = {"goodbye": "cruel world"}
@pytest.fixture @pytest.fixture
def store(hass): def store(hass):
"""Fixture of a store that prevents writing on Home Assistant stop.""" """Fixture of a store that prevents writing on Home Assistant stop."""
yield storage.Store(hass, MOCK_VERSION, MOCK_KEY) return storage.Store(hass, MOCK_VERSION, MOCK_KEY)
async def test_loading(hass, store): async def test_loading(hass, store):
@ -64,8 +64,8 @@ async def test_loading_parallel(hass, store, hass_storage, caplog):
results = await asyncio.gather(store.async_load(), store.async_load()) results = await asyncio.gather(store.async_load(), store.async_load())
assert results[0] is MOCK_DATA assert results[0] == MOCK_DATA
assert results[1] is MOCK_DATA assert results[0] is results[1]
assert caplog.text.count(f"Loading data for {store.key}") assert caplog.text.count(f"Loading data for {store.key}")
@ -279,3 +279,24 @@ async def test_migrator_transforming_config(hass, store, hass_storage):
"version": MOCK_VERSION, "version": MOCK_VERSION,
"data": data, "data": data,
} }
async def test_changing_delayed_written_data(hass, store, hass_storage):
"""Test changing data that is written with delay."""
data_to_store = {"hello": "world"}
store.async_delay_save(lambda: data_to_store, 1)
assert store.key not in hass_storage
loaded_data = await store.async_load()
assert loaded_data == data_to_store
assert loaded_data is not data_to_store
loaded_data["hello"] = "earth"
async_fire_time_changed(hass, dt.utcnow() + timedelta(seconds=1))
await hass.async_block_till_done()
assert hass_storage[store.key] == {
"version": MOCK_VERSION,
"key": MOCK_KEY,
"data": {"hello": "world"},
}

View File

@ -251,13 +251,6 @@ def test_check_package_global():
assert not package.is_installed(f"{installed_package}<{installed_version}") assert not package.is_installed(f"{installed_package}<{installed_version}")
def test_check_package_version_does_not_match():
"""Test for version mismatch."""
installed_package = list(pkg_resources.working_set)[0].project_name
assert not package.is_installed(f"{installed_package}==999.999.999")
assert not package.is_installed(f"{installed_package}>=999.999.999")
def test_check_package_zip(): def test_check_package_zip():
"""Test for an installed zip package.""" """Test for an installed zip package."""
assert not package.is_installed(TEST_ZIP_REQ) assert not package.is_installed(TEST_ZIP_REQ)