mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Merge pull request #42824 from home-assistant/rc
This commit is contained in:
commit
d156e95f8a
@ -3,6 +3,6 @@
|
||||
"name": "AirVisual",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/airvisual",
|
||||
"requirements": ["pyairvisual==5.0.3"],
|
||||
"requirements": ["pyairvisual==5.0.4"],
|
||||
"codeowners": ["@bachya"]
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "bmw_connected_drive",
|
||||
"name": "BMW Connected Drive",
|
||||
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
|
||||
"requirements": ["bimmer_connected==0.7.8"],
|
||||
"requirements": ["bimmer_connected==0.7.11"],
|
||||
"dependencies": [],
|
||||
"codeowners": ["@gerard33", "@rikroe"]
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ class EvoBroker:
|
||||
return
|
||||
|
||||
if refresh:
|
||||
self.hass.helpers.event.async_call_later(1, self.async_update())
|
||||
self.hass.helpers.event.async_call_later(1, self.async_update)
|
||||
|
||||
return result
|
||||
|
||||
|
@ -16,7 +16,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
name = f"{cube.room_by_id(device.room_id).name} {device.name}"
|
||||
|
||||
# Only add Window Shutters
|
||||
if cube.is_windowshutter(device):
|
||||
if device.is_windowshutter():
|
||||
devices.append(MaxCubeShutter(handler, name, device.rf_address))
|
||||
|
||||
if devices:
|
||||
|
@ -70,7 +70,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
for device in cube.devices:
|
||||
name = f"{cube.room_by_id(device.room_id).name} {device.name}"
|
||||
|
||||
if cube.is_thermostat(device) or cube.is_wallthermostat(device):
|
||||
if device.is_thermostat() or device.is_wallthermostat():
|
||||
devices.append(MaxCubeClimate(handler, name, device.rf_address))
|
||||
|
||||
if devices:
|
||||
@ -180,11 +180,11 @@ class MaxCubeClimate(ClimateEntity):
|
||||
device = cube.device_by_rf(self._rf_address)
|
||||
valve = 0
|
||||
|
||||
if cube.is_thermostat(device):
|
||||
if device.is_thermostat():
|
||||
valve = device.valve_position
|
||||
elif cube.is_wallthermostat(device):
|
||||
elif device.is_wallthermostat():
|
||||
for device in cube.devices_by_room(cube.room_by_id(device.room_id)):
|
||||
if cube.is_thermostat(device) and device.valve_position > 0:
|
||||
if device.is_thermostat() and device.valve_position > 0:
|
||||
valve = device.valve_position
|
||||
break
|
||||
else:
|
||||
@ -287,7 +287,7 @@ class MaxCubeClimate(ClimateEntity):
|
||||
cube = self._cubehandle.cube
|
||||
device = cube.device_by_rf(self._rf_address)
|
||||
|
||||
if not cube.is_thermostat(device):
|
||||
if not device.is_thermostat():
|
||||
return {}
|
||||
return {ATTR_VALVE_POSITION: device.valve_position}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Netatmo",
|
||||
"documentation": "https://www.home-assistant.io/integrations/netatmo",
|
||||
"requirements": [
|
||||
"pyatmo==4.1.0"
|
||||
"pyatmo==4.2.0"
|
||||
],
|
||||
"after_dependencies": [
|
||||
"cloud",
|
||||
|
@ -84,7 +84,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
||||
|
||||
if resource_template is not None:
|
||||
resource_template.hass = hass
|
||||
resource = resource_template.render(parse_result=False)
|
||||
resource = resource_template.async_render(parse_result=False)
|
||||
|
||||
if value_template is not None:
|
||||
value_template.hass = hass
|
||||
@ -189,6 +189,6 @@ class RestBinarySensor(BinarySensorEntity):
|
||||
async def async_update(self):
|
||||
"""Get the latest data from REST API and updates the state."""
|
||||
if self._resource_template is not None:
|
||||
self.rest.set_url(self._resource_template.render(parse_result=False))
|
||||
self.rest.set_url(self._resource_template.async_render(parse_result=False))
|
||||
|
||||
await self.rest.async_update()
|
||||
|
@ -103,7 +103,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
||||
|
||||
if resource_template is not None:
|
||||
resource_template.hass = hass
|
||||
resource = resource_template.render(parse_result=False)
|
||||
resource = resource_template.async_render(parse_result=False)
|
||||
|
||||
if username and password:
|
||||
if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
|
||||
@ -202,7 +202,7 @@ class RestSensor(Entity):
|
||||
async def async_update(self):
|
||||
"""Get the latest data from REST API and update the state."""
|
||||
if self._resource_template is not None:
|
||||
self.rest.set_url(self._resource_template.render(parse_result=False))
|
||||
self.rest.set_url(self._resource_template.async_render(parse_result=False))
|
||||
|
||||
await self.rest.async_update()
|
||||
|
||||
|
@ -360,13 +360,17 @@ class OptionsFlow(config_entries.OptionsFlow):
|
||||
"""Check if device can be replaced with selected device."""
|
||||
device_data = self._get_device_data(entry_id)
|
||||
event_code = device_data[CONF_EVENT_CODE]
|
||||
rfx_obj = get_rfx_object(event_code)
|
||||
if (
|
||||
rfx_obj.device.packettype == self._selected_device_object.device.packettype
|
||||
and rfx_obj.device.subtype == self._selected_device_object.device.subtype
|
||||
and self._selected_device_event_code != event_code
|
||||
):
|
||||
return True
|
||||
|
||||
if event_code is not None:
|
||||
rfx_obj = get_rfx_object(event_code)
|
||||
if (
|
||||
rfx_obj.device.packettype
|
||||
== self._selected_device_object.device.packettype
|
||||
and rfx_obj.device.subtype
|
||||
== self._selected_device_object.device.subtype
|
||||
and self._selected_device_event_code != event_code
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
@ -159,7 +159,7 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
|
||||
try:
|
||||
await self._system.set_off()
|
||||
except SimplipyError as err:
|
||||
LOGGER.error('Error while disarming "%s": %s', self._system.name, err)
|
||||
LOGGER.error('Error while disarming "%s": %s', self._system.system_id, err)
|
||||
return
|
||||
|
||||
self._state = STATE_ALARM_DISARMED
|
||||
@ -172,7 +172,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
|
||||
try:
|
||||
await self._system.set_home()
|
||||
except SimplipyError as err:
|
||||
LOGGER.error('Error while arming "%s" (home): %s', self._system.name, err)
|
||||
LOGGER.error(
|
||||
'Error while arming "%s" (home): %s', self._system.system_id, err
|
||||
)
|
||||
return
|
||||
|
||||
self._state = STATE_ALARM_ARMED_HOME
|
||||
@ -185,7 +187,9 @@ class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
|
||||
try:
|
||||
await self._system.set_away()
|
||||
except SimplipyError as err:
|
||||
LOGGER.error('Error while arming "%s" (away): %s', self._system.name, err)
|
||||
LOGGER.error(
|
||||
'Error while arming "%s" (away): %s', self._system.system_id, err
|
||||
)
|
||||
return
|
||||
|
||||
self._state = STATE_ALARM_ARMING
|
||||
|
@ -258,10 +258,9 @@ class SynoApi:
|
||||
self._entry.data[CONF_PASSWORD],
|
||||
self._entry.data[CONF_SSL],
|
||||
timeout=self._entry.options.get(CONF_TIMEOUT),
|
||||
device_token=self._entry.data.get("device_token"),
|
||||
)
|
||||
await self._hass.async_add_executor_job(
|
||||
self.dsm.login, self._entry.data.get("device_token")
|
||||
)
|
||||
await self._hass.async_add_executor_job(self.dsm.login)
|
||||
|
||||
self._with_surveillance_station = bool(
|
||||
self.dsm.apis.get(SynoSurveillanceStation.CAMERA_API_KEY)
|
||||
|
@ -128,6 +128,11 @@ class TasmotaLight(
|
||||
white_value = float(attributes["white_value"])
|
||||
percent_white = white_value / TASMOTA_BRIGHTNESS_MAX
|
||||
self._white_value = percent_white * 255
|
||||
if self._white_value == 0:
|
||||
self._color_temp = None
|
||||
self._white_value = None
|
||||
if self._white_value is not None and self._white_value > 0:
|
||||
self._hs = None
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
|
@ -348,9 +348,11 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle zeroconf discovery."""
|
||||
assert self.hass
|
||||
|
||||
discovery_info[
|
||||
CONF_HOST
|
||||
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
|
||||
# If host already has port, no need to add it again
|
||||
if ":" not in discovery_info[CONF_HOST]:
|
||||
discovery_info[
|
||||
CONF_HOST
|
||||
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
|
||||
|
||||
# Set default name to discovered device name by stripping zeroconf service
|
||||
# (`type`) from `name`
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 117
|
||||
PATCH_VERSION = "2"
|
||||
PATCH_VERSION = "3"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 7, 1)
|
||||
|
@ -8,7 +8,7 @@ attrs==19.3.0
|
||||
bcrypt==3.1.7
|
||||
certifi>=2020.6.20
|
||||
ciso8601==2.1.3
|
||||
cryptography==3.2.0
|
||||
cryptography==3.2
|
||||
defusedxml==0.6.0
|
||||
distro==1.5.0
|
||||
emoji==0.5.4
|
||||
|
@ -12,7 +12,7 @@ httpx==0.16.1
|
||||
importlib-metadata==1.6.0;python_version<'3.8'
|
||||
jinja2>=2.11.2
|
||||
PyJWT==1.7.1
|
||||
cryptography==3.2.0
|
||||
cryptography==3.2
|
||||
pip>=8.0.3
|
||||
python-slugify==4.0.1
|
||||
pytz>=2020.1
|
||||
|
@ -342,7 +342,7 @@ beautifulsoup4==4.9.1
|
||||
bellows==0.20.3
|
||||
|
||||
# homeassistant.components.bmw_connected_drive
|
||||
bimmer_connected==0.7.8
|
||||
bimmer_connected==0.7.11
|
||||
|
||||
# homeassistant.components.bizkaibus
|
||||
bizkaibus==0.1.1
|
||||
@ -1252,7 +1252,7 @@ pyaehw4a1==0.3.9
|
||||
pyaftership==0.1.2
|
||||
|
||||
# homeassistant.components.airvisual
|
||||
pyairvisual==5.0.3
|
||||
pyairvisual==5.0.4
|
||||
|
||||
# homeassistant.components.almond
|
||||
pyalmond==0.0.2
|
||||
@ -1264,7 +1264,7 @@ pyarlo==0.2.3
|
||||
pyatag==0.3.4.4
|
||||
|
||||
# homeassistant.components.netatmo
|
||||
pyatmo==4.1.0
|
||||
pyatmo==4.2.0
|
||||
|
||||
# homeassistant.components.atome
|
||||
pyatome==0.1.1
|
||||
|
@ -615,7 +615,7 @@ py_nextbusnext==0.1.4
|
||||
pyaehw4a1==0.3.9
|
||||
|
||||
# homeassistant.components.airvisual
|
||||
pyairvisual==5.0.3
|
||||
pyairvisual==5.0.4
|
||||
|
||||
# homeassistant.components.almond
|
||||
pyalmond==0.0.2
|
||||
@ -627,7 +627,7 @@ pyarlo==0.2.3
|
||||
pyatag==0.3.4.4
|
||||
|
||||
# homeassistant.components.netatmo
|
||||
pyatmo==4.1.0
|
||||
pyatmo==4.2.0
|
||||
|
||||
# homeassistant.components.blackbird
|
||||
pyblackbird==0.5
|
||||
|
2
setup.py
2
setup.py
@ -44,7 +44,7 @@ REQUIRES = [
|
||||
"jinja2>=2.11.2",
|
||||
"PyJWT==1.7.1",
|
||||
# PyJWT has loose dependency. We want the latest one.
|
||||
"cryptography==3.2.0",
|
||||
"cryptography==3.2",
|
||||
"pip>=8.0.3",
|
||||
"python-slugify==4.0.1",
|
||||
"pytz>=2020.1",
|
||||
|
@ -116,7 +116,7 @@ async def test_setup_minimum_resource_template(hass):
|
||||
{
|
||||
"binary_sensor": {
|
||||
"platform": "rest",
|
||||
"resource_template": "http://localhost",
|
||||
"resource_template": "{% set url = 'http://localhost' %}{{ url }}",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -102,7 +102,7 @@ async def test_setup_minimum_resource_template(hass):
|
||||
{
|
||||
"sensor": {
|
||||
"platform": "rest",
|
||||
"resource_template": "http://localhost",
|
||||
"resource_template": "{% set url = 'http://localhost' %}{{ url }}",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -432,6 +432,8 @@ async def test_controlling_state_via_mqtt_rgbww(hass, mqtt_mock, setup_tasmota):
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get("white_value") == 127.5
|
||||
# Setting white > 0 should clear the color
|
||||
assert not state.attributes.get("rgb_color")
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","CT":300}'
|
||||
@ -440,6 +442,15 @@ async def test_controlling_state_via_mqtt_rgbww(hass, mqtt_mock, setup_tasmota):
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get("color_temp") == 300
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","White":0}'
|
||||
)
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_ON
|
||||
# Setting white to 0 should clear the white_value and color_temp
|
||||
assert not state.attributes.get("white_value")
|
||||
assert not state.attributes.get("color_temp")
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Scheme":3}'
|
||||
)
|
||||
|
@ -27,6 +27,7 @@ from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PIN,
|
||||
CONF_PORT,
|
||||
)
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
@ -777,6 +778,35 @@ async def test_zeroconf_flow_already_configured(
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_zeroconf_flow_with_port_in_host(
|
||||
hass: HomeAssistantType,
|
||||
vizio_connect: pytest.fixture,
|
||||
vizio_bypass_setup: pytest.fixture,
|
||||
vizio_guess_device_type: pytest.fixture,
|
||||
) -> None:
|
||||
"""Test entity is already configured during zeroconf setup when port is in host."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=MOCK_SPEAKER_CONFIG,
|
||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||
unique_id=UNIQUE_ID,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
# Try rediscovering same device, this time with port already in host
|
||||
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
|
||||
discovery_info[
|
||||
CONF_HOST
|
||||
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
|
||||
)
|
||||
|
||||
# Flow should abort because device is already setup
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_zeroconf_dupe_fail(
|
||||
hass: HomeAssistantType,
|
||||
vizio_connect: pytest.fixture,
|
||||
|
Loading…
x
Reference in New Issue
Block a user