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,
)
self._attr_sound_mode_list = receiver.sound_mode_list
self._attr_source_list = receiver.input_func_list
self._receiver = receiver
self._update_audyssey = update_audyssey
@ -246,6 +245,11 @@ class DenonDevice(MediaPlayerEntity):
"""Return the state of the device."""
return self._receiver.state
@property
def source_list(self):
"""Return a list of available input sources."""
return self._receiver.input_func_list
@property
def is_volume_muted(self):
"""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_extra_state_attributes = {
"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)
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(
step_id="advanced",
data_schema=vol.Schema(
{
vol.Optional(
CONF_DEVICES, default=self.hk_options.get(CONF_DEVICES, [])
): cv.multi_select(all_supported_devices)
vol.Optional(CONF_DEVICES, default=devices): cv.multi_select(
all_supported_devices
)
}
),
)
@ -445,13 +451,16 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
)
data_schema = {}
entities = entity_filter.get(CONF_INCLUDE_ENTITIES, [])
if self.hk_options[CONF_HOMEKIT_MODE] == HOMEKIT_MODE_ACCESSORY:
entity_schema = vol.In
else:
if entities:
include_exclude_mode = MODE_INCLUDE
else:
entity_schema = vol.In
# Strip out entities that no longer exist to prevent error in the UI
entities = [
entity_id
for entity_id in entity_filter.get(CONF_INCLUDE_ENTITIES, [])
if entity_id in all_supported_entities
]
if self.hk_options[CONF_HOMEKIT_MODE] != HOMEKIT_MODE_ACCESSORY:
include_exclude_mode = MODE_INCLUDE
if not entities:
include_exclude_mode = MODE_EXCLUDE
entities = entity_filter.get(CONF_EXCLUDE_ENTITIES, [])
data_schema[

View File

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

View File

@ -66,7 +66,7 @@ class NetgearSensorEntity(NetgearDeviceEntity, SensorEntity):
self.entity_description = SENSOR_TYPES[self._attribute]
self._name = f"{self.get_device_name()} {self.entity_description.name}"
self._unique_id = f"{self._mac}-{self._attribute}"
self._state = self._device[self._attribute]
self._state = self._device.get(self._attribute)
@property
def native_value(self):
@ -78,7 +78,7 @@ class NetgearSensorEntity(NetgearDeviceEntity, SensorEntity):
"""Update the Netgear device."""
self._device = self._router.devices[self._mac]
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.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."
},
"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": {
"user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun ass m\u00e9iglech."
},
"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": {
"user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk."
},
"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": {
"user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
},
"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": {
"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."
},
"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": {
"user": {

View File

@ -1,7 +1,7 @@
{
"config": {
"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": {
"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."
},
"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": {
"user": {

View File

@ -1,7 +1,7 @@
{
"config": {
"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": {
"user": {

View File

@ -4,7 +4,7 @@
"single_instance_allowed": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"
},
"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": {
"user": {

View File

@ -267,11 +267,13 @@ class SonosDiscoveryManager:
if change == ssdp.SsdpChange.BYEBYE:
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
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(
"SSDP", info, discovered_ip, uid, boot_seqnum, info.get("modelName"), None
)

View File

@ -46,6 +46,10 @@ class IntegerTypeData:
"""Scale a value."""
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(
self,
value: float,

View File

@ -322,7 +322,7 @@ class TuyaClimateEntity(TuyaEntity, ClimateEntity):
[
{
"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,
"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,
"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
if self._status_range.type == "Integer":
self._type_data = IntegerTypeData.from_json(self._status_range.values)
self._attr_max_value = self._type_data.max
self._attr_min_value = self._type_data.min
self._attr_step = self._type_data.step
self._attr_max_value = self._type_data.max_scaled
self._attr_min_value = self._type_data.min_scaled
self._attr_step = self._type_data.step_scaled
if description.unit_of_measurement is None:
self._attr_unit_of_measurement = self._type_data.unit
@ -290,7 +290,7 @@ class TuyaNumberEntity(TuyaEntity, NumberEntity):
[
{
"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",
"name": "Velbus",
"documentation": "https://www.home-assistant.io/integrations/velbus",
"requirements": ["velbus-aio==2021.11.6"],
"requirements": ["velbus-aio==2021.11.7"],
"config_flow": true,
"codeowners": ["@Cereal2nd", "@brefra"],
"iot_class": "local_push"

View File

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

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import asyncio
from collections.abc import Callable
from contextlib import suppress
from copy import deepcopy
from json import JSONEncoder
import logging
import os
@ -130,6 +131,10 @@ class Store:
# If we didn't generate data yet, do it now.
if "data_func" in data:
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:
data = await self.hass.async_add_executor_job(
json_util.load_json, self.path

View File

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

View File

@ -1364,7 +1364,7 @@ url-normalize==1.4.1
uvcclient==0.11.0
# homeassistant.components.velbus
velbus-aio==2021.11.6
velbus-aio==2021.11.7
# homeassistant.components.venstar
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
):
"""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)
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):
"""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):
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.SsdpChange.ALIVE,

View File

@ -49,7 +49,7 @@ import homeassistant.util.dt as dt_util
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_SITE = "site_id"

View File

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

View File

@ -14,7 +14,7 @@ from .test_controller import (
setup_unifi_integration,
)
from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, flush_store
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(
hass, aioclient_mock, clients_response=[client_1, client_2]
)
await flush_store(hass.data[unifi.UNIFI_WIRELESS_CLIENTS]._store)
for mac in [
"00:00:00:00:00:00",

View File

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

View File

@ -25,7 +25,7 @@ MOCK_DATA2 = {"goodbye": "cruel world"}
@pytest.fixture
def store(hass):
"""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):
@ -64,8 +64,8 @@ async def test_loading_parallel(hass, store, hass_storage, caplog):
results = await asyncio.gather(store.async_load(), store.async_load())
assert results[0] is MOCK_DATA
assert results[1] is MOCK_DATA
assert results[0] == MOCK_DATA
assert results[0] is results[1]
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,
"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}")
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():
"""Test for an installed zip package."""
assert not package.is_installed(TEST_ZIP_REQ)