Merge pull request #49424 from home-assistant/rc

pull/50148/head 2021.4.6
Franck Nijhof 2021-04-19 18:09:01 +02:00 committed by GitHub
commit 5ee373869a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 138 additions and 19 deletions

View File

@ -791,7 +791,7 @@ class TemperatureSettingTrait(_Trait):
if preset in self.preset_to_google:
response["thermostatMode"] = self.preset_to_google[preset]
else:
response["thermostatMode"] = self.hvac_to_google.get(operation)
response["thermostatMode"] = self.hvac_to_google.get(operation, "none")
current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE)
if current_temp is not None:

View File

@ -3,6 +3,6 @@
"name": "Meteorologisk institutt (Met.no)",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/met",
"requirements": ["pyMetno==0.8.1"],
"requirements": ["pyMetno==0.8.2"],
"codeowners": ["@danielhiversen", "@thimic"]
}

View File

@ -319,7 +319,19 @@ class ModbusRegisterSensor(RestoreEntity, SensorEntity):
# If unpack() returns a tuple greater than 1, don't try to process the value.
# Instead, return the values of unpack(...) separated by commas.
if len(val) > 1:
self._value = ",".join(map(str, val))
# Apply scale and precision to floats and ints
v_result = []
for entry in val:
v_temp = self._scale * entry + self._offset
# We could convert int to float, and the code would still work; however
# we lose some precision, and unit tests will fail. Therefore, we do
# the conversion only when it's absolutely necessary.
if isinstance(v_temp, int) and self._precision == 0:
v_result.append(str(v_temp))
else:
v_result.append(f"{float(v_temp):.{self._precision}f}")
self._value = ",".join(map(str, v_result))
else:
val = val[0]

View File

@ -67,7 +67,7 @@ def round_state(func):
class AirSensor(AirQualityEntity):
"""Representation of an Yr.no sensor."""
"""Representation of an air quality sensor."""
def __init__(self, name, coordinates, forecast, session):
"""Initialize the sensor."""

View File

@ -2,6 +2,6 @@
"domain": "norway_air",
"name": "Om Luftkvalitet i Norge (Norway Air)",
"documentation": "https://www.home-assistant.io/integrations/norway_air",
"requirements": ["pyMetno==0.8.1"],
"requirements": ["pyMetno==0.8.2"],
"codeowners": []
}

View File

@ -328,9 +328,8 @@ async def _async_discover_roombas(hass, host):
discovery = _async_get_roomba_discovery()
try:
if host:
discovered = [
await hass.async_add_executor_job(discovery.get, host)
]
device = await hass.async_add_executor_job(discovery.get, host)
discovered = [device] if device else []
else:
discovered = await hass.async_add_executor_job(discovery.get_all)
except OSError:

View File

@ -1,7 +1,7 @@
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 2021
MINOR_VERSION = 4
PATCH_VERSION = "5"
PATCH_VERSION = "6"
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 8, 0)

View File

@ -1203,12 +1203,9 @@ class Script:
self._changed()
raise
async def _async_stop(self, update_state, spare=None):
aws = [
asyncio.create_task(run.async_stop()) for run in self._runs if run != spare
]
if not aws:
return
async def _async_stop(
self, aws: list[asyncio.Task], update_state: bool, spare: _ScriptRun | None
) -> None:
await asyncio.wait(aws)
if update_state:
self._changed()
@ -1217,7 +1214,15 @@ class Script:
self, update_state: bool = True, spare: _ScriptRun | None = None
) -> None:
"""Stop running script."""
await asyncio.shield(self._async_stop(update_state, spare))
# Collect a a list of script runs to stop. This must be done before calling
# asyncio.shield as asyncio.shield yields to the event loop, which would cause
# us to wait for script runs added after the call to async_stop.
aws = [
asyncio.create_task(run.async_stop()) for run in self._runs if run != spare
]
if not aws:
return
await asyncio.shield(self._async_stop(aws, update_state, spare))
async def _async_get_condition(self, config):
if isinstance(config, template.Template):

View File

@ -1229,7 +1229,7 @@ pyHS100==0.3.5.2
# homeassistant.components.met
# homeassistant.components.norway_air
pyMetno==0.8.1
pyMetno==0.8.2
# homeassistant.components.rfxtrx
pyRFXtrx==0.26.1

View File

@ -648,7 +648,7 @@ pyHS100==0.3.5.2
# homeassistant.components.met
# homeassistant.components.norway_air
pyMetno==0.8.1
pyMetno==0.8.2
# homeassistant.components.rfxtrx
pyRFXtrx==0.26.1

View File

@ -14,6 +14,7 @@ from homeassistant.components.modbus.const import (
CONF_REVERSE_ORDER,
CONF_SCALE,
CONF_SENSORS,
DATA_TYPE_CUSTOM,
DATA_TYPE_FLOAT,
DATA_TYPE_INT,
DATA_TYPE_STRING,
@ -26,6 +27,7 @@ from homeassistant.const import (
CONF_NAME,
CONF_OFFSET,
CONF_SLAVE,
CONF_STRUCTURE,
)
from .conftest import base_config_test, base_test
@ -338,6 +340,7 @@ async def test_config_sensor(hass, do_discovery, do_config):
)
async def test_all_sensor(hass, cfg, regs, expected):
"""Run test for sensor."""
sensor_name = "modbus_test_sensor"
state = await base_test(
hass,
@ -352,3 +355,41 @@ async def test_all_sensor(hass, cfg, regs, expected):
scan_interval=5,
)
assert state == expected
async def test_struct_sensor(hass):
"""Run test for sensor struct."""
sensor_name = "modbus_test_sensor"
# floats: 7.931250095367432, 10.600000381469727,
# 1.000879611487865e-28, 10.566553115844727
expected = "7.93,10.60,0.00,10.57"
state = await base_test(
hass,
{
CONF_NAME: sensor_name,
CONF_REGISTER: 1234,
CONF_COUNT: 8,
CONF_PRECISION: 2,
CONF_DATA_TYPE: DATA_TYPE_CUSTOM,
CONF_STRUCTURE: ">4f",
},
sensor_name,
SENSOR_DOMAIN,
CONF_SENSORS,
CONF_REGISTERS,
[
0x40FD,
0xCCCD,
0x4129,
0x999A,
0x10FD,
0xC0CD,
0x4129,
0x109A,
],
expected,
method_discovery=False,
scan_interval=5,
)
assert state == expected

View File

@ -711,7 +711,7 @@ async def test_dhcp_discovery_and_roomba_discovery_finds(hass, discovery_data):
@pytest.mark.parametrize("discovery_data", DHCP_DISCOVERY_DEVICES_WITHOUT_MATCHING_IP)
async def test_dhcp_discovery_falls_back_to_manual(hass, discovery_data):
"""Test we can process the discovery from dhcp but roomba discovery cannot find the device."""
"""Test we can process the discovery from dhcp but roomba discovery cannot find the specific device."""
await setup.async_setup_component(hass, "persistent_notification", {})
mocked_roomba = _create_mocked_roomba(
@ -782,6 +782,68 @@ async def test_dhcp_discovery_falls_back_to_manual(hass, discovery_data):
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize("discovery_data", DHCP_DISCOVERY_DEVICES_WITHOUT_MATCHING_IP)
async def test_dhcp_discovery_no_devices_falls_back_to_manual(hass, discovery_data):
"""Test we can process the discovery from dhcp but roomba discovery cannot find any devices."""
await setup.async_setup_component(hass, "persistent_notification", {})
mocked_roomba = _create_mocked_roomba(
roomba_connected=True,
master_state={"state": {"reported": {"name": "myroomba"}}},
)
with patch(
"homeassistant.components.roomba.config_flow.RoombaDiscovery",
_mocked_no_devices_found_discovery,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_DHCP},
data=discovery_data,
)
await hass.async_block_till_done()
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] is None
assert result["step_id"] == "manual"
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: MOCK_IP, CONF_BLID: "blid"},
)
await hass.async_block_till_done()
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result2["errors"] is None
with patch(
"homeassistant.components.roomba.config_flow.Roomba",
return_value=mocked_roomba,
), patch(
"homeassistant.components.roomba.config_flow.RoombaPassword",
_mocked_getpassword,
), patch(
"homeassistant.components.roomba.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"],
{},
)
await hass.async_block_till_done()
assert result3["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result3["title"] == "myroomba"
assert result3["result"].unique_id == "BLID"
assert result3["data"] == {
CONF_BLID: "BLID",
CONF_CONTINUOUS: True,
CONF_DELAY: 1,
CONF_HOST: MOCK_IP,
CONF_PASSWORD: "password",
}
assert len(mock_setup_entry.mock_calls) == 1
async def test_dhcp_discovery_with_ignored(hass):
"""Test ignored entries do not break checking for existing entries."""
await setup.async_setup_component(hass, "persistent_notification", {})