mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 08:07:45 +00:00
Merge pull request #50417 from home-assistant/rc
This commit is contained in:
commit
5aaead54da
@ -201,11 +201,15 @@ def _monitor_events(hass, name, api, event_codes):
|
||||
while True:
|
||||
api.available_flag.wait()
|
||||
try:
|
||||
for code, start in api.event_actions("All", retries=5):
|
||||
event_data = {"camera": name, "event": code, "payload": start}
|
||||
for code, payload in api.event_actions("All", retries=5):
|
||||
event_data = {"camera": name, "event": code, "payload": payload}
|
||||
hass.bus.fire("amcrest", event_data)
|
||||
if code in event_codes:
|
||||
signal = service_signal(SERVICE_EVENT, name, code)
|
||||
start = any(
|
||||
str(key).lower() == "action" and str(val).lower() == "start"
|
||||
for key, val in payload.items()
|
||||
)
|
||||
_LOGGER.debug("Sending signal: '%s': %s", signal, start)
|
||||
dispatcher_send(hass, signal, start)
|
||||
except AmcrestError as error:
|
||||
|
@ -4,7 +4,7 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/androidtv",
|
||||
"requirements": [
|
||||
"adb-shell[async]==0.3.1",
|
||||
"androidtv[async]==0.0.58",
|
||||
"androidtv[async]==0.0.59",
|
||||
"pure-python-adb[async]==0.3.0.dev0"
|
||||
],
|
||||
"codeowners": ["@JeffLIrion"],
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Denon AVR Network Receivers",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/denonavr",
|
||||
"requirements": ["denonavr==0.10.6"],
|
||||
"requirements": ["denonavr==0.10.7"],
|
||||
"codeowners": ["@scarface-4711", "@starkillerOG"],
|
||||
"ssdp": [
|
||||
{
|
||||
|
@ -6,10 +6,15 @@ import math
|
||||
from aioesphomeapi import SensorInfo, SensorState, TextSensorInfo, TextSensorState
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import DEVICE_CLASSES, SensorEntity
|
||||
from homeassistant.components.sensor import (
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
DEVICE_CLASSES,
|
||||
SensorEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util import dt
|
||||
|
||||
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||
|
||||
@ -74,6 +79,8 @@ class EsphomeSensor(EsphomeEntity, SensorEntity):
|
||||
return None
|
||||
if self._state.missing_state:
|
||||
return None
|
||||
if self.device_class == DEVICE_CLASS_TIMESTAMP:
|
||||
return dt.utc_from_timestamp(self._state.state).isoformat()
|
||||
return f"{self._state.state:.{self._static_info.accuracy_decimals}f}"
|
||||
|
||||
@property
|
||||
|
@ -393,26 +393,29 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
router.subscriptions.clear()
|
||||
|
||||
# Set up device registry
|
||||
device_data = {}
|
||||
sw_version = None
|
||||
if router.data.get(KEY_DEVICE_INFORMATION):
|
||||
device_info = router.data[KEY_DEVICE_INFORMATION]
|
||||
sw_version = device_info.get("SoftwareVersion")
|
||||
if device_info.get("DeviceName"):
|
||||
device_data["model"] = device_info["DeviceName"]
|
||||
if not sw_version and router.data.get(KEY_DEVICE_BASIC_INFORMATION):
|
||||
sw_version = router.data[KEY_DEVICE_BASIC_INFORMATION].get("SoftwareVersion")
|
||||
if sw_version:
|
||||
device_data["sw_version"] = sw_version
|
||||
device_registry = await dr.async_get_registry(hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections=router.device_connections,
|
||||
identifiers=router.device_identifiers,
|
||||
name=router.device_name,
|
||||
manufacturer="Huawei",
|
||||
**device_data,
|
||||
)
|
||||
if router.device_identifiers or router.device_connections:
|
||||
device_data = {}
|
||||
sw_version = None
|
||||
if router.data.get(KEY_DEVICE_INFORMATION):
|
||||
device_info = router.data[KEY_DEVICE_INFORMATION]
|
||||
sw_version = device_info.get("SoftwareVersion")
|
||||
if device_info.get("DeviceName"):
|
||||
device_data["model"] = device_info["DeviceName"]
|
||||
if not sw_version and router.data.get(KEY_DEVICE_BASIC_INFORMATION):
|
||||
sw_version = router.data[KEY_DEVICE_BASIC_INFORMATION].get(
|
||||
"SoftwareVersion"
|
||||
)
|
||||
if sw_version:
|
||||
device_data["sw_version"] = sw_version
|
||||
device_registry = await dr.async_get_registry(hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections=router.device_connections,
|
||||
identifiers=router.device_identifiers,
|
||||
name=router.device_name,
|
||||
manufacturer="Huawei",
|
||||
**device_data,
|
||||
)
|
||||
|
||||
# Forward config entry setup to platforms
|
||||
hass.config_entries.async_setup_platforms(config_entry, CONFIG_ENTRY_PLATFORMS)
|
||||
|
@ -5,7 +5,6 @@ import threading
|
||||
from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient, ModbusUdpClient
|
||||
from pymodbus.constants import Defaults
|
||||
from pymodbus.exceptions import ModbusException
|
||||
from pymodbus.pdu import ExceptionResponse, IllegalFunctionRequest
|
||||
from pymodbus.transaction import ModbusRtuFramer
|
||||
|
||||
from homeassistant.const import (
|
||||
@ -237,8 +236,8 @@ class ModbusHub:
|
||||
result = self._client.read_coils(address, count, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return None
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "bits"):
|
||||
self._log_error(result)
|
||||
return None
|
||||
self._in_error = False
|
||||
@ -251,9 +250,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.read_discrete_inputs(address, count, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return None
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "bits"):
|
||||
self._log_error(result)
|
||||
return None
|
||||
self._in_error = False
|
||||
@ -266,9 +264,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.read_input_registers(address, count, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return None
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "registers"):
|
||||
self._log_error(result)
|
||||
return None
|
||||
self._in_error = False
|
||||
@ -281,9 +278,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.read_holding_registers(address, count, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return None
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "registers"):
|
||||
self._log_error(result)
|
||||
return None
|
||||
self._in_error = False
|
||||
@ -296,9 +292,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.write_coil(address, value, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return False
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "value"):
|
||||
self._log_error(result)
|
||||
return False
|
||||
self._in_error = False
|
||||
@ -311,9 +306,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.write_coils(address, values, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return False
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "count"):
|
||||
self._log_error(result)
|
||||
return False
|
||||
self._in_error = False
|
||||
@ -326,9 +320,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.write_register(address, value, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return False
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "value"):
|
||||
self._log_error(result)
|
||||
return False
|
||||
self._in_error = False
|
||||
@ -341,9 +334,8 @@ class ModbusHub:
|
||||
try:
|
||||
result = self._client.write_registers(address, values, **kwargs)
|
||||
except ModbusException as exception_error:
|
||||
self._log_error(exception_error)
|
||||
return False
|
||||
if isinstance(result, (ExceptionResponse, IllegalFunctionRequest)):
|
||||
result = exception_error
|
||||
if not hasattr(result, "count"):
|
||||
self._log_error(result)
|
||||
return False
|
||||
self._in_error = False
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "OVO Energy",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/ovo_energy",
|
||||
"requirements": ["ovoenergy==1.1.11"],
|
||||
"requirements": ["ovoenergy==1.1.12"],
|
||||
"codeowners": ["@timmo001"],
|
||||
"iot_class": "cloud_polling"
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "philips_js",
|
||||
"name": "Philips TV",
|
||||
"documentation": "https://www.home-assistant.io/integrations/philips_js",
|
||||
"requirements": ["ha-philipsjs==2.7.0"],
|
||||
"requirements": ["ha-philipsjs==2.7.3"],
|
||||
"codeowners": ["@elupus"],
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
|
@ -418,9 +418,8 @@ class RachioZone(RachioSwitch):
|
||||
CONF_MANUAL_RUN_MINS, DEFAULT_MANUAL_RUN_MINS
|
||||
)
|
||||
)
|
||||
self._controller.rachio.zone.start(
|
||||
self.zone_id, manual_run_time.total_seconds()
|
||||
)
|
||||
# The API limit is 3 hours, and requires an int be passed
|
||||
self._controller.rachio.zone.start(self.zone_id, manual_run_time.seconds)
|
||||
_LOGGER.debug(
|
||||
"Watering %s on %s for %s",
|
||||
self.name,
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Sonos",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/sonos",
|
||||
"requirements": ["pysonos==0.0.44"],
|
||||
"requirements": ["pysonos==0.0.45"],
|
||||
"after_dependencies": ["plex"],
|
||||
"ssdp": [
|
||||
{
|
||||
|
@ -498,7 +498,9 @@ class SonosMediaPlayerEntity(SonosEntity, MediaPlayerEntity):
|
||||
if new_status == "TRANSITIONING":
|
||||
return
|
||||
|
||||
self._play_mode = event.current_play_mode if event else self.soco.play_mode
|
||||
self._play_mode = (
|
||||
variables["current_play_mode"] if variables else self.soco.play_mode
|
||||
)
|
||||
self._uri = None
|
||||
self._media_duration = None
|
||||
self._media_image_url = None
|
||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
from asyncio import gather
|
||||
import contextlib
|
||||
import datetime
|
||||
from functools import partial
|
||||
import logging
|
||||
from typing import Any, Callable
|
||||
|
||||
@ -223,7 +224,11 @@ class SonosSpeaker:
|
||||
return
|
||||
|
||||
self._poll_timer = self.hass.helpers.event.async_track_time_interval(
|
||||
async_dispatcher_send(self.hass, f"{SONOS_ENTITY_UPDATE}-{self.soco.uid}"),
|
||||
partial(
|
||||
async_dispatcher_send,
|
||||
self.hass,
|
||||
f"{SONOS_ENTITY_UPDATE}-{self.soco.uid}",
|
||||
),
|
||||
SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
|
@ -203,7 +203,7 @@ async def async_setup_platform(
|
||||
) -> None:
|
||||
"""Set up the system monitor sensors."""
|
||||
entities = []
|
||||
sensor_registry: dict[str, SensorData] = {}
|
||||
sensor_registry: dict[tuple[str, str], SensorData] = {}
|
||||
|
||||
for resource in config[CONF_RESOURCES]:
|
||||
type_ = resource[CONF_TYPE]
|
||||
@ -225,7 +225,9 @@ async def async_setup_platform(
|
||||
_LOGGER.warning("Cannot read CPU / processor temperature information")
|
||||
continue
|
||||
|
||||
sensor_registry[type_] = SensorData(argument, None, None, None, None)
|
||||
sensor_registry[(type_, argument)] = SensorData(
|
||||
argument, None, None, None, None
|
||||
)
|
||||
entities.append(SystemMonitorSensor(sensor_registry, type_, argument))
|
||||
|
||||
scan_interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||
@ -236,7 +238,7 @@ async def async_setup_platform(
|
||||
|
||||
async def async_setup_sensor_registry_updates(
|
||||
hass: HomeAssistant,
|
||||
sensor_registry: dict[str, SensorData],
|
||||
sensor_registry: dict[tuple[str, str], SensorData],
|
||||
scan_interval: datetime.timedelta,
|
||||
) -> None:
|
||||
"""Update the registry and create polling."""
|
||||
@ -245,11 +247,11 @@ async def async_setup_sensor_registry_updates(
|
||||
|
||||
def _update_sensors() -> None:
|
||||
"""Update sensors and store the result in the registry."""
|
||||
for type_, data in sensor_registry.items():
|
||||
for (type_, argument), data in sensor_registry.items():
|
||||
try:
|
||||
state, value, update_time = _update(type_, data)
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Error updating sensor: %s", type_)
|
||||
_LOGGER.exception("Error updating sensor: %s (%s)", type_, argument)
|
||||
data.last_exception = ex
|
||||
else:
|
||||
data.state = state
|
||||
@ -295,7 +297,7 @@ class SystemMonitorSensor(SensorEntity):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
sensor_registry: dict[str, SensorData],
|
||||
sensor_registry: dict[tuple[str, str], SensorData],
|
||||
sensor_type: str,
|
||||
argument: str = "",
|
||||
) -> None:
|
||||
@ -304,6 +306,7 @@ class SystemMonitorSensor(SensorEntity):
|
||||
self._name: str = f"{self.sensor_type[SENSOR_TYPE_NAME]} {argument}".rstrip()
|
||||
self._unique_id: str = slugify(f"{sensor_type}_{argument}")
|
||||
self._sensor_registry = sensor_registry
|
||||
self._argument: str = argument
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
@ -353,7 +356,7 @@ class SystemMonitorSensor(SensorEntity):
|
||||
@property
|
||||
def data(self) -> SensorData:
|
||||
"""Return registry entry for the data."""
|
||||
return self._sensor_registry[self._type]
|
||||
return self._sensor_registry[(self._type, self._argument)]
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Tasmota",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/tasmota",
|
||||
"requirements": ["hatasmota==0.2.11"],
|
||||
"requirements": ["hatasmota==0.2.12"],
|
||||
"dependencies": ["mqtt"],
|
||||
"mqtt": ["tasmota/discovery/#"],
|
||||
"codeowners": ["@emontnemery"],
|
||||
|
@ -140,7 +140,7 @@ async def async_setup_entry(hass, config_entry):
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
config = config_entry.data
|
||||
# Because users can have multiple accounts, we always create a new session so they have separate cookies
|
||||
async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE})
|
||||
async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE}, timeout=60)
|
||||
email = config_entry.title
|
||||
if email in hass.data[DOMAIN] and CONF_SCAN_INTERVAL in hass.data[DOMAIN][email]:
|
||||
scan_interval = hass.data[DOMAIN][email][CONF_SCAN_INTERVAL]
|
||||
|
@ -150,7 +150,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
||||
"""
|
||||
|
||||
config = {}
|
||||
async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE})
|
||||
async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE}, timeout=60)
|
||||
|
||||
try:
|
||||
controller = TeslaAPI(
|
||||
|
@ -111,7 +111,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigType):
|
||||
|
||||
async def async_unload_entry(hass, entry):
|
||||
"""Unload a config entry."""
|
||||
platforms = [platform for platform in PLATFORMS if platform in hass.data[DOMAIN]]
|
||||
platforms = [platform for platform in PLATFORMS if hass.data[DOMAIN].get(platform)]
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, platforms)
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].clear()
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 2021
|
||||
MINOR_VERSION = 5
|
||||
PATCH_VERSION = "1"
|
||||
PATCH_VERSION = "2"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 8, 0)
|
||||
|
@ -254,7 +254,7 @@ ambiclimate==0.2.1
|
||||
amcrest==1.7.2
|
||||
|
||||
# homeassistant.components.androidtv
|
||||
androidtv[async]==0.0.58
|
||||
androidtv[async]==0.0.59
|
||||
|
||||
# homeassistant.components.anel_pwrctrl
|
||||
anel_pwrctrl-homeassistant==0.0.1.dev2
|
||||
@ -479,7 +479,7 @@ defusedxml==0.6.0
|
||||
deluge-client==1.7.1
|
||||
|
||||
# homeassistant.components.denonavr
|
||||
denonavr==0.10.6
|
||||
denonavr==0.10.7
|
||||
|
||||
# homeassistant.components.devolo_home_control
|
||||
devolo-home-control-api==0.17.3
|
||||
@ -720,7 +720,7 @@ guppy3==3.1.0
|
||||
ha-ffmpeg==3.0.2
|
||||
|
||||
# homeassistant.components.philips_js
|
||||
ha-philipsjs==2.7.0
|
||||
ha-philipsjs==2.7.3
|
||||
|
||||
# homeassistant.components.habitica
|
||||
habitipy==0.2.0
|
||||
@ -735,7 +735,7 @@ hass-nabucasa==0.43.0
|
||||
hass_splunk==0.1.1
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.2.11
|
||||
hatasmota==0.2.12
|
||||
|
||||
# homeassistant.components.jewish_calendar
|
||||
hdate==0.10.2
|
||||
@ -1088,7 +1088,7 @@ oru==0.1.11
|
||||
orvibo==1.1.1
|
||||
|
||||
# homeassistant.components.ovo_energy
|
||||
ovoenergy==1.1.11
|
||||
ovoenergy==1.1.12
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
# homeassistant.components.shiftr
|
||||
@ -1741,7 +1741,7 @@ pysnmp==4.4.12
|
||||
pysoma==0.0.10
|
||||
|
||||
# homeassistant.components.sonos
|
||||
pysonos==0.0.44
|
||||
pysonos==0.0.45
|
||||
|
||||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
@ -167,7 +167,7 @@ airly==1.1.0
|
||||
ambiclimate==0.2.1
|
||||
|
||||
# homeassistant.components.androidtv
|
||||
androidtv[async]==0.0.58
|
||||
androidtv[async]==0.0.59
|
||||
|
||||
# homeassistant.components.apns
|
||||
apns2==0.3.0
|
||||
@ -264,7 +264,7 @@ debugpy==1.2.1
|
||||
defusedxml==0.6.0
|
||||
|
||||
# homeassistant.components.denonavr
|
||||
denonavr==0.10.6
|
||||
denonavr==0.10.7
|
||||
|
||||
# homeassistant.components.devolo_home_control
|
||||
devolo-home-control-api==0.17.3
|
||||
@ -393,7 +393,7 @@ guppy3==3.1.0
|
||||
ha-ffmpeg==3.0.2
|
||||
|
||||
# homeassistant.components.philips_js
|
||||
ha-philipsjs==2.7.0
|
||||
ha-philipsjs==2.7.3
|
||||
|
||||
# homeassistant.components.habitica
|
||||
habitipy==0.2.0
|
||||
@ -405,7 +405,7 @@ hangups==0.4.11
|
||||
hass-nabucasa==0.43.0
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.2.11
|
||||
hatasmota==0.2.12
|
||||
|
||||
# homeassistant.components.jewish_calendar
|
||||
hdate==0.10.2
|
||||
@ -576,7 +576,7 @@ onvif-zeep-async==1.0.0
|
||||
openerz-api==0.1.0
|
||||
|
||||
# homeassistant.components.ovo_energy
|
||||
ovoenergy==1.1.11
|
||||
ovoenergy==1.1.12
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
# homeassistant.components.shiftr
|
||||
@ -959,7 +959,7 @@ pysmartthings==0.7.6
|
||||
pysoma==0.0.10
|
||||
|
||||
# homeassistant.components.sonos
|
||||
pysonos==0.0.44
|
||||
pysonos==0.0.45
|
||||
|
||||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
@ -43,6 +43,15 @@ DEFAULT_SENSOR_CONFIG = {
|
||||
}
|
||||
}
|
||||
|
||||
BAD_INDEXED_SENSOR_CONFIG_3 = {
|
||||
"sn": {
|
||||
"Time": "2020-09-25T12:47:15",
|
||||
"ENERGY": {
|
||||
"ApparentPower": [7.84, 1.23, 2.34],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
INDEXED_SENSOR_CONFIG = {
|
||||
"sn": {
|
||||
"Time": "2020-09-25T12:47:15",
|
||||
@ -224,6 +233,117 @@ async def test_indexed_sensor_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
|
||||
assert state.state == "7.8"
|
||||
|
||||
|
||||
async def test_bad_indexed_sensor_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
|
||||
"""Test state update via MQTT where sensor is not matching configuration."""
|
||||
config = copy.deepcopy(DEFAULT_CONFIG)
|
||||
sensor_config = copy.deepcopy(BAD_INDEXED_SENSOR_CONFIG_3)
|
||||
mac = config["mac"]
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
f"{DEFAULT_PREFIX}/{mac}/config",
|
||||
json.dumps(config),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
f"{DEFAULT_PREFIX}/{mac}/sensors",
|
||||
json.dumps(sensor_config),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "unavailable"
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == "unavailable"
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == "unavailable"
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
|
||||
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/LWT", "Online")
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
|
||||
# Test periodic state update
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/SENSOR", '{"ENERGY":{"ApparentPower":[1.2,3.4,5.6]}}'
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "1.2"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == "3.4"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == "5.6"
|
||||
|
||||
# Test periodic state update with too few values
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/SENSOR", '{"ENERGY":{"ApparentPower":[7.8,9.0]}}'
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "7.8"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == "9.0"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "tasmota_49A3BC/tele/SENSOR", '{"ENERGY":{"ApparentPower":2.3}}'
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "2.3"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test polled state update
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"tasmota_49A3BC/stat/STATUS10",
|
||||
'{"StatusSNS":{"ENERGY":{"ApparentPower":[1.2,3.4,5.6]}}}',
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "1.2"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == "3.4"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == "5.6"
|
||||
|
||||
# Test polled state update with too few values
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"tasmota_49A3BC/stat/STATUS10",
|
||||
'{"StatusSNS":{"ENERGY":{"ApparentPower":[7.8,9.0]}}}',
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "7.8"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == "9.0"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass,
|
||||
"tasmota_49A3BC/stat/STATUS10",
|
||||
'{"StatusSNS":{"ENERGY":{"ApparentPower":2.3}}}',
|
||||
)
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_0")
|
||||
assert state.state == "2.3"
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_1")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
state = hass.states.get("sensor.tasmota_energy_apparentpower_2")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
@pytest.mark.parametrize("status_sensor_disabled", [False])
|
||||
async def test_status_sensor_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
|
||||
"""Test state update via MQTT."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user