mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Merge pull request #45156 from home-assistant/rc
This commit is contained in:
commit
2600fdfa67
@ -181,8 +181,8 @@ class AfterShipSensor(Entity):
|
||||
track["tracking_number"] if track["title"] is None else track["title"]
|
||||
)
|
||||
last_checkpoint = (
|
||||
"Shipment pending"
|
||||
if track["tag"] == "Pending"
|
||||
f"Shipment {track['tag'].lower()}"
|
||||
if not track["checkpoints"]
|
||||
else track["checkpoints"][-1]
|
||||
)
|
||||
status_counts[status] = status_counts.get(status, 0) + 1
|
||||
|
@ -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.13"],
|
||||
"requirements": ["bimmer_connected==0.7.14"],
|
||||
"codeowners": ["@gerard33", "@rikroe"],
|
||||
"config_flow": true
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "myq",
|
||||
"name": "MyQ",
|
||||
"documentation": "https://www.home-assistant.io/integrations/myq",
|
||||
"requirements": ["pymyq==2.0.13"],
|
||||
"requirements": ["pymyq==2.0.14"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"config_flow": true,
|
||||
"homekit": {
|
||||
|
@ -37,7 +37,7 @@ class NeatoSensor(Entity):
|
||||
def __init__(self, neato, robot):
|
||||
"""Initialize Neato sensor."""
|
||||
self.robot = robot
|
||||
self._available = neato is not None
|
||||
self._available = False
|
||||
self._robot_name = f"{self.robot.name} {BATTERY}"
|
||||
self._robot_serial = self.robot.serial
|
||||
self._state = None
|
||||
|
@ -40,7 +40,7 @@ class NeatoConnectedSwitch(ToggleEntity):
|
||||
"""Initialize the Neato Connected switches."""
|
||||
self.type = switch_type
|
||||
self.robot = robot
|
||||
self._available = neato is not None
|
||||
self._available = False
|
||||
self._robot_name = f"{self.robot.name} {SWITCH_TYPES[self.type][0]}"
|
||||
self._state = None
|
||||
self._schedule_state = None
|
||||
|
@ -1,7 +1,10 @@
|
||||
"""Support for the OpenWeatherMap (OWM) service."""
|
||||
import datetime
|
||||
|
||||
from .abstract_owm_sensor import AbstractOpenWeatherMapSensor
|
||||
from .const import (
|
||||
ATTR_API_FORECAST,
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
DOMAIN,
|
||||
ENTRY_NAME,
|
||||
ENTRY_WEATHER_COORDINATOR,
|
||||
@ -95,5 +98,10 @@ class OpenWeatherMapForecastSensor(AbstractOpenWeatherMapSensor):
|
||||
"""Return the state of the device."""
|
||||
forecasts = self._weather_coordinator.data.get(ATTR_API_FORECAST)
|
||||
if forecasts is not None and len(forecasts) > 0:
|
||||
return forecasts[0].get(self._sensor_type, None)
|
||||
value = forecasts[0].get(self._sensor_type, None)
|
||||
if self._device_class is DEVICE_CLASS_TIMESTAMP:
|
||||
value = datetime.datetime.fromtimestamp(
|
||||
value, datetime.timezone.utc
|
||||
).isoformat()
|
||||
return value
|
||||
return None
|
||||
|
@ -138,7 +138,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
||||
|
||||
def _convert_forecast(self, entry):
|
||||
forecast = {
|
||||
ATTR_FORECAST_TIME: entry.reference_time("unix") * 1000,
|
||||
ATTR_FORECAST_TIME: entry.reference_time("unix"),
|
||||
ATTR_FORECAST_PRECIPITATION: self._calc_precipitation(
|
||||
entry.rain, entry.snow
|
||||
),
|
||||
|
@ -169,7 +169,11 @@ class UtilityMeterSensor(RestoreEntity):
|
||||
new_state = event.data.get("new_state")
|
||||
if new_state is None:
|
||||
return
|
||||
if self._tariff == new_state.state:
|
||||
|
||||
self._change_status(new_state.state)
|
||||
|
||||
def _change_status(self, tariff):
|
||||
if self._tariff == tariff:
|
||||
self._collecting = async_track_state_change_event(
|
||||
self.hass, [self._sensor_source_id], self.async_reading
|
||||
)
|
||||
@ -271,25 +275,26 @@ class UtilityMeterSensor(RestoreEntity):
|
||||
self._last_reset = dt_util.parse_datetime(
|
||||
state.attributes.get(ATTR_LAST_RESET)
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
if state.attributes.get(ATTR_STATUS) == PAUSED:
|
||||
# Fake cancellation function to init the meter paused
|
||||
if state.attributes.get(ATTR_STATUS) == COLLECTING:
|
||||
# Fake cancellation function to init the meter in similar state
|
||||
self._collecting = lambda: None
|
||||
|
||||
@callback
|
||||
def async_source_tracking(event):
|
||||
"""Wait for source to be ready, then start meter."""
|
||||
if self._tariff_entity is not None:
|
||||
_LOGGER.debug("Track %s", self._tariff_entity)
|
||||
_LOGGER.debug(
|
||||
"<%s> tracks utility meter %s", self.name, self._tariff_entity
|
||||
)
|
||||
async_track_state_change_event(
|
||||
self.hass, [self._tariff_entity], self.async_tariff_change
|
||||
)
|
||||
|
||||
tariff_entity_state = self.hass.states.get(self._tariff_entity)
|
||||
if self._tariff != tariff_entity_state.state:
|
||||
self._change_status(tariff_entity_state.state)
|
||||
return
|
||||
|
||||
_LOGGER.debug("tracking source: %s", self._sensor_source_id)
|
||||
_LOGGER.debug("<%s> collecting from %s", self.name, self._sensor_source_id)
|
||||
self._collecting = async_track_state_change_event(
|
||||
self.hass, [self._sensor_source_id], self.async_reading
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 2021
|
||||
MINOR_VERSION = 1
|
||||
PATCH_VERSION = "1"
|
||||
PATCH_VERSION = "2"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 7, 1)
|
||||
|
@ -339,7 +339,7 @@ beautifulsoup4==4.9.1
|
||||
bellows==0.21.0
|
||||
|
||||
# homeassistant.components.bmw_connected_drive
|
||||
bimmer_connected==0.7.13
|
||||
bimmer_connected==0.7.14
|
||||
|
||||
# homeassistant.components.bizkaibus
|
||||
bizkaibus==0.1.1
|
||||
@ -1536,7 +1536,7 @@ pymsteams==0.1.12
|
||||
pymusiccast==0.1.6
|
||||
|
||||
# homeassistant.components.myq
|
||||
pymyq==2.0.13
|
||||
pymyq==2.0.14
|
||||
|
||||
# homeassistant.components.mysensors
|
||||
pymysensors==0.18.0
|
||||
|
@ -189,7 +189,7 @@ base36==0.1.1
|
||||
bellows==0.21.0
|
||||
|
||||
# homeassistant.components.bmw_connected_drive
|
||||
bimmer_connected==0.7.13
|
||||
bimmer_connected==0.7.14
|
||||
|
||||
# homeassistant.components.blebox
|
||||
blebox_uniapi==1.3.2
|
||||
@ -779,7 +779,7 @@ pymodbus==2.3.0
|
||||
pymonoprice==0.3
|
||||
|
||||
# homeassistant.components.myq
|
||||
pymyq==2.0.13
|
||||
pymyq==2.0.14
|
||||
|
||||
# homeassistant.components.nut
|
||||
pynut2==2.1.2
|
||||
|
@ -10,17 +10,24 @@ from homeassistant.components.utility_meter.const import (
|
||||
SERVICE_CALIBRATE_METER,
|
||||
SERVICE_SELECT_TARIFF,
|
||||
)
|
||||
from homeassistant.components.utility_meter.sensor import (
|
||||
ATTR_LAST_RESET,
|
||||
ATTR_STATUS,
|
||||
COLLECTING,
|
||||
PAUSED,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
)
|
||||
from homeassistant.core import State
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.common import async_fire_time_changed, mock_restore_cache
|
||||
|
||||
|
||||
@contextmanager
|
||||
@ -55,6 +62,21 @@ async def test_state(hass):
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_onpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_midpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
now = dt_util.utcnow() + timedelta(seconds=10)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=now):
|
||||
hass.states.async_set(
|
||||
@ -68,14 +90,17 @@ async def test_state(hass):
|
||||
state = hass.states.get("sensor.energy_bill_onpeak")
|
||||
assert state is not None
|
||||
assert state.state == "1"
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_midpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@ -99,14 +124,17 @@ async def test_state(hass):
|
||||
state = hass.states.get("sensor.energy_bill_onpeak")
|
||||
assert state is not None
|
||||
assert state.state == "1"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_midpeak")
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state is not None
|
||||
assert state.state == "3"
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@ -131,6 +159,65 @@ async def test_state(hass):
|
||||
assert state.state == "0.123"
|
||||
|
||||
|
||||
async def test_restore_state(hass):
|
||||
"""Test utility sensor restore state."""
|
||||
config = {
|
||||
"utility_meter": {
|
||||
"energy_bill": {
|
||||
"source": "sensor.energy",
|
||||
"tariffs": ["onpeak", "midpeak", "offpeak"],
|
||||
}
|
||||
}
|
||||
}
|
||||
mock_restore_cache(
|
||||
hass,
|
||||
[
|
||||
State(
|
||||
"sensor.energy_bill_onpeak",
|
||||
"3",
|
||||
attributes={
|
||||
ATTR_STATUS: PAUSED,
|
||||
ATTR_LAST_RESET: "2020-12-21T00:00:00.013073+00:00",
|
||||
},
|
||||
),
|
||||
State(
|
||||
"sensor.energy_bill_offpeak",
|
||||
"6",
|
||||
attributes={
|
||||
ATTR_STATUS: COLLECTING,
|
||||
ATTR_LAST_RESET: "2020-12-21T00:00:00.013073+00:00",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, DOMAIN, config)
|
||||
assert await async_setup_component(hass, SENSOR_DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# restore from cache
|
||||
state = hass.states.get("sensor.energy_bill_onpeak")
|
||||
assert state.state == "3"
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state.state == "6"
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
|
||||
# utility_meter is loaded, now set sensors according to utility_meter:
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("utility_meter.energy_bill")
|
||||
assert state.state == "onpeak"
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_onpeak")
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state.attributes.get("status") == PAUSED
|
||||
|
||||
|
||||
async def test_net_consumption(hass):
|
||||
"""Test utility sensor state."""
|
||||
config = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user