mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 08:07:45 +00:00
Merge pull request #35001 from home-assistant/rc
This commit is contained in:
commit
02cca1a4da
@ -195,6 +195,7 @@ homeassistant/components/ipp/* @ctalkington
|
||||
homeassistant/components/iqvia/* @bachya
|
||||
homeassistant/components/irish_rail_transport/* @ttroy50
|
||||
homeassistant/components/islamic_prayer_times/* @engrbm87
|
||||
homeassistant/components/isy994/* @bdraco
|
||||
homeassistant/components/izone/* @Swamp-Ig
|
||||
homeassistant/components/jewish_calendar/* @tsvi
|
||||
homeassistant/components/juicenet/* @jesserockz
|
||||
|
@ -190,6 +190,9 @@ stages:
|
||||
pip install -U pip setuptools wheel
|
||||
pip install -r requirements_all.txt -c homeassistant/package_constraints.txt
|
||||
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
|
||||
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
|
||||
# Find offending deps with `pipdeptree -r -p typing`
|
||||
pip uninstall -y typing
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
pip install -e .
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Brother Printer",
|
||||
"documentation": "https://www.home-assistant.io/integrations/brother",
|
||||
"codeowners": ["@bieniu"],
|
||||
"requirements": ["brother==0.1.13"],
|
||||
"requirements": ["brother==0.1.14"],
|
||||
"zeroconf": ["_printer._tcp.local."],
|
||||
"config_flow": true,
|
||||
"quality_scale": "platinum"
|
||||
|
@ -5,7 +5,7 @@ from typing import Any, Callable, Iterable, List
|
||||
|
||||
from directv import DIRECTV, DIRECTVError
|
||||
|
||||
from homeassistant.components.remote import RemoteDevice
|
||||
from homeassistant.components.remote import ATTR_NUM_REPEATS, RemoteDevice
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
@ -95,12 +95,15 @@ class DIRECTVRemote(DIRECTVEntity, RemoteDevice):
|
||||
blue, chanup, chandown, prev, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, dash, enter
|
||||
"""
|
||||
for single_command in command:
|
||||
try:
|
||||
await self.dtv.remote(single_command, self._address)
|
||||
except DIRECTVError:
|
||||
_LOGGER.exception(
|
||||
"Sending command %s to device %s failed",
|
||||
single_command,
|
||||
self._device_id,
|
||||
)
|
||||
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
||||
|
||||
for _ in range(num_repeats):
|
||||
for single_command in command:
|
||||
try:
|
||||
await self.dtv.remote(single_command, self._address)
|
||||
except DIRECTVError:
|
||||
_LOGGER.exception(
|
||||
"Sending command %s to device %s failed",
|
||||
single_command,
|
||||
self._device_id,
|
||||
)
|
||||
|
@ -165,7 +165,9 @@ class Fan(HomeAccessory):
|
||||
self.char_direction.set_value(hk_direction)
|
||||
|
||||
# Handle Speed
|
||||
if self.char_speed is not None:
|
||||
if self.char_speed is not None and state != STATE_OFF:
|
||||
# We do not change the homekit speed when turning off
|
||||
# as it will clear the restore state
|
||||
speed = new_state.attributes.get(ATTR_SPEED)
|
||||
hk_speed_value = self.speed_mapping.speed_to_homekit(speed)
|
||||
if hk_speed_value is not None and self.char_speed.value != hk_speed_value:
|
||||
|
@ -200,7 +200,7 @@ class HomeKitSpeedMapping:
|
||||
if speed is None:
|
||||
return None
|
||||
speed_range = self.speed_ranges[speed]
|
||||
return speed_range.target
|
||||
return round(speed_range.target)
|
||||
|
||||
def speed_to_states(self, speed):
|
||||
"""Map HomeKit speed to Home Assistant speed state."""
|
||||
|
@ -3,12 +3,15 @@ import logging
|
||||
from typing import Callable
|
||||
|
||||
from homeassistant.components.light import DOMAIN, SUPPORT_BRIGHTNESS, Light
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from . import ISY994_NODES, ISYDevice
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_LAST_BRIGHTNESS = "last_brightness"
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass, config: ConfigType, add_entities: Callable[[list], None], discovery_info=None
|
||||
@ -21,13 +24,13 @@ def setup_platform(
|
||||
add_entities(devices)
|
||||
|
||||
|
||||
class ISYLightDevice(ISYDevice, Light):
|
||||
class ISYLightDevice(ISYDevice, Light, RestoreEntity):
|
||||
"""Representation of an ISY994 light device."""
|
||||
|
||||
def __init__(self, node) -> None:
|
||||
"""Initialize the ISY994 light device."""
|
||||
super().__init__(node)
|
||||
self._last_brightness = self.brightness
|
||||
self._last_brightness = None
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
@ -56,7 +59,7 @@ class ISYLightDevice(ISYDevice, Light):
|
||||
# pylint: disable=arguments-differ
|
||||
def turn_on(self, brightness=None, **kwargs) -> None:
|
||||
"""Send the turn on command to the ISY994 light device."""
|
||||
if brightness is None and self._last_brightness is not None:
|
||||
if brightness is None and self._last_brightness:
|
||||
brightness = self._last_brightness
|
||||
if not self._node.on(val=brightness):
|
||||
_LOGGER.debug("Unable to turn on light")
|
||||
@ -65,3 +68,23 @@ class ISYLightDevice(ISYDevice, Light):
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_BRIGHTNESS
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the light attributes."""
|
||||
return {ATTR_LAST_BRIGHTNESS: self._last_brightness}
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Restore last_brightness on restart."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
self._last_brightness = self.brightness or 255
|
||||
last_state = await self.async_get_last_state()
|
||||
if not last_state:
|
||||
return
|
||||
|
||||
if (
|
||||
ATTR_LAST_BRIGHTNESS in last_state.attributes
|
||||
and last_state.attributes[ATTR_LAST_BRIGHTNESS]
|
||||
):
|
||||
self._last_brightness = last_state.attributes[ATTR_LAST_BRIGHTNESS]
|
||||
|
@ -3,5 +3,5 @@
|
||||
"name": "Universal Devices ISY994",
|
||||
"documentation": "https://www.home-assistant.io/integrations/isy994",
|
||||
"requirements": ["PyISY==1.1.2"],
|
||||
"codeowners": []
|
||||
"codeowners": ["@bdraco"]
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ def log_messages(hass: HomeAssistantType, entity_id: str) -> MessageCallbackType
|
||||
debug_info = hass.data[DATA_MQTT_DEBUG_INFO]
|
||||
messages = debug_info["entities"][entity_id]["subscriptions"][
|
||||
msg.subscribed_topic
|
||||
]
|
||||
]["messages"]
|
||||
if msg not in messages:
|
||||
messages.append(msg)
|
||||
|
||||
@ -50,16 +50,27 @@ def add_subscription(hass, message_callback, subscription):
|
||||
entity_info = debug_info["entities"].setdefault(
|
||||
entity_id, {"subscriptions": {}, "discovery_data": {}}
|
||||
)
|
||||
entity_info["subscriptions"][subscription] = deque([], STORED_MESSAGES)
|
||||
if subscription not in entity_info["subscriptions"]:
|
||||
entity_info["subscriptions"][subscription] = {
|
||||
"count": 0,
|
||||
"messages": deque([], STORED_MESSAGES),
|
||||
}
|
||||
entity_info["subscriptions"][subscription]["count"] += 1
|
||||
|
||||
|
||||
def remove_subscription(hass, message_callback, subscription):
|
||||
"""Remove debug data for subscription."""
|
||||
"""Remove debug data for subscription if it exists."""
|
||||
entity_id = getattr(message_callback, "__entity_id", None)
|
||||
if entity_id and entity_id in hass.data[DATA_MQTT_DEBUG_INFO]["entities"]:
|
||||
hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]["subscriptions"].pop(
|
||||
hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]["subscriptions"][
|
||||
subscription
|
||||
)
|
||||
]["count"] -= 1
|
||||
if not hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]["subscriptions"][
|
||||
subscription
|
||||
]["count"]:
|
||||
hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]["subscriptions"].pop(
|
||||
subscription
|
||||
)
|
||||
|
||||
|
||||
def add_entity_discovery_data(hass, discovery_data, entity_id):
|
||||
@ -127,10 +138,10 @@ async def info_for_device(hass, device_id):
|
||||
"topic": topic,
|
||||
"messages": [
|
||||
{"payload": msg.payload, "time": msg.timestamp, "topic": msg.topic}
|
||||
for msg in list(messages)
|
||||
for msg in list(subscription["messages"])
|
||||
],
|
||||
}
|
||||
for topic, messages in entity_info["subscriptions"].items()
|
||||
for topic, subscription in entity_info["subscriptions"].items()
|
||||
]
|
||||
discovery_data = {
|
||||
"topic": entity_info["discovery_data"].get(ATTR_DISCOVERY_TOPIC, ""),
|
||||
|
@ -123,7 +123,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
if not person.controllers:
|
||||
_LOGGER.error("No Rachio devices found in account %s", person.username)
|
||||
return False
|
||||
_LOGGER.info("%d Rachio device(s) found", len(person.controllers))
|
||||
_LOGGER.info(
|
||||
"%d Rachio device(s) found; The url %s must be accessible from the internet in order to receive updates",
|
||||
len(person.controllers),
|
||||
webhook_url,
|
||||
)
|
||||
|
||||
# Enable component
|
||||
hass.data[DOMAIN][entry.entry_id] = person
|
||||
|
@ -7,7 +7,7 @@ from requests.exceptions import (
|
||||
)
|
||||
from roku import RokuException
|
||||
|
||||
from homeassistant.components.remote import RemoteDevice
|
||||
from homeassistant.components.remote import ATTR_NUM_REPEATS, RemoteDevice
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
@ -84,8 +84,11 @@ class RokuRemote(RemoteDevice):
|
||||
|
||||
def send_command(self, command, **kwargs):
|
||||
"""Send a command to one device."""
|
||||
for single_command in command:
|
||||
if not hasattr(self.roku, single_command):
|
||||
continue
|
||||
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
||||
|
||||
getattr(self.roku, single_command)()
|
||||
for _ in range(num_repeats):
|
||||
for single_command in command:
|
||||
if not hasattr(self.roku, single_command):
|
||||
continue
|
||||
|
||||
getattr(self.roku, single_command)()
|
||||
|
@ -3,6 +3,7 @@ import asyncio
|
||||
import logging
|
||||
|
||||
from homeassistant.components.vacuum import (
|
||||
ATTR_STATUS,
|
||||
STATE_CLEANING,
|
||||
STATE_DOCKED,
|
||||
STATE_ERROR,
|
||||
@ -16,6 +17,7 @@ from homeassistant.components.vacuum import (
|
||||
SUPPORT_SEND_COMMAND,
|
||||
SUPPORT_START,
|
||||
SUPPORT_STATE,
|
||||
SUPPORT_STATUS,
|
||||
SUPPORT_STOP,
|
||||
StateVacuumDevice,
|
||||
)
|
||||
@ -40,6 +42,7 @@ SUPPORT_IROBOT = (
|
||||
| SUPPORT_SEND_COMMAND
|
||||
| SUPPORT_START
|
||||
| SUPPORT_STATE
|
||||
| SUPPORT_STATUS
|
||||
| SUPPORT_STOP
|
||||
| SUPPORT_LOCATE
|
||||
)
|
||||
@ -143,7 +146,7 @@ class IRobotVacuum(IRobotEntity, StateVacuumDevice):
|
||||
state = STATE_MAP[phase]
|
||||
except KeyError:
|
||||
return STATE_ERROR
|
||||
if cycle != "none" and state != STATE_CLEANING and state != STATE_RETURNING:
|
||||
if cycle != "none" and state in (STATE_IDLE, STATE_DOCKED):
|
||||
state = STATE_PAUSED
|
||||
return state
|
||||
|
||||
@ -173,6 +176,9 @@ class IRobotVacuum(IRobotEntity, StateVacuumDevice):
|
||||
# Set properties that are to appear in the GUI
|
||||
state_attrs = {ATTR_SOFTWARE_VERSION: software_version}
|
||||
|
||||
# Set legacy status to avoid break changes
|
||||
state_attrs[ATTR_STATUS] = self.vacuum.current_state
|
||||
|
||||
# Only add cleaning time and cleaned area attrs when the vacuum is
|
||||
# currently on
|
||||
if self.state == STATE_CLEANING:
|
||||
|
@ -24,7 +24,8 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
|
@ -101,7 +101,7 @@ def add_entities(controller, async_add_entities):
|
||||
|
||||
if tracker_class is UniFiClientTracker:
|
||||
|
||||
if item.is_wired:
|
||||
if mac not in controller.wireless_clients:
|
||||
if not controller.option_track_wired_clients:
|
||||
continue
|
||||
else:
|
||||
|
@ -132,7 +132,7 @@ class VizioDevice(MediaPlayerDevice):
|
||||
self._state = None
|
||||
self._volume_level = None
|
||||
self._volume_step = config_entry.options[CONF_VOLUME_STEP]
|
||||
self._is_muted = None
|
||||
self._is_volume_muted = None
|
||||
self._current_input = None
|
||||
self._current_app = None
|
||||
self._current_app_config = None
|
||||
@ -190,7 +190,7 @@ class VizioDevice(MediaPlayerDevice):
|
||||
if not is_on:
|
||||
self._state = STATE_OFF
|
||||
self._volume_level = None
|
||||
self._is_muted = None
|
||||
self._is_volume_muted = None
|
||||
self._current_input = None
|
||||
self._available_inputs = None
|
||||
self._current_app = None
|
||||
@ -207,7 +207,10 @@ class VizioDevice(MediaPlayerDevice):
|
||||
)
|
||||
if audio_settings is not None:
|
||||
self._volume_level = float(audio_settings["volume"]) / self._max_volume
|
||||
self._is_muted = audio_settings["mute"].lower() == "on"
|
||||
if "mute" in audio_settings:
|
||||
self._is_volume_muted = audio_settings["mute"].lower() == "on"
|
||||
else:
|
||||
self._is_volume_muted = None
|
||||
|
||||
if VIZIO_SOUND_MODE in audio_settings:
|
||||
self._supported_commands |= SUPPORT_SELECT_SOUND_MODE
|
||||
@ -324,7 +327,7 @@ class VizioDevice(MediaPlayerDevice):
|
||||
@property
|
||||
def is_volume_muted(self):
|
||||
"""Boolean if volume is currently muted."""
|
||||
return self._is_muted
|
||||
return self._is_volume_muted
|
||||
|
||||
@property
|
||||
def source(self) -> str:
|
||||
@ -428,10 +431,10 @@ class VizioDevice(MediaPlayerDevice):
|
||||
"""Mute the volume."""
|
||||
if mute:
|
||||
await self._device.mute_on()
|
||||
self._is_muted = True
|
||||
self._is_volume_muted = True
|
||||
else:
|
||||
await self._device.mute_off()
|
||||
self._is_muted = False
|
||||
self._is_volume_muted = False
|
||||
|
||||
async def async_media_previous_track(self) -> None:
|
||||
"""Send previous channel command."""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 109
|
||||
PATCH_VERSION = "1"
|
||||
PATCH_VERSION = "2"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 7, 0)
|
||||
|
@ -365,7 +365,7 @@ bravia-tv==1.0.2
|
||||
broadlink==0.13.2
|
||||
|
||||
# homeassistant.components.brother
|
||||
brother==0.1.13
|
||||
brother==0.1.14
|
||||
|
||||
# homeassistant.components.brottsplatskartan
|
||||
brottsplatskartan==0.0.1
|
||||
|
@ -147,7 +147,7 @@ bravia-tv==1.0.2
|
||||
broadlink==0.13.2
|
||||
|
||||
# homeassistant.components.brother
|
||||
brother==0.1.13
|
||||
brother==0.1.14
|
||||
|
||||
# homeassistant.components.buienradar
|
||||
buienradar==1.0.4
|
||||
|
@ -304,6 +304,7 @@ async def test_fan_speed(hass, hk_driver, cls, events):
|
||||
call_set_speed = async_mock_service(hass, DOMAIN, "set_speed")
|
||||
|
||||
char_speed_iid = acc.char_speed.to_HAP()[HAP_REPR_IID]
|
||||
char_active_iid = acc.char_active.to_HAP()[HAP_REPR_IID]
|
||||
|
||||
hk_driver.set_characteristics(
|
||||
{
|
||||
@ -320,12 +321,37 @@ async def test_fan_speed(hass, hk_driver, cls, events):
|
||||
await hass.async_add_executor_job(acc.char_speed.client_update_value, 42)
|
||||
await hass.async_block_till_done()
|
||||
acc.speed_mapping.speed_to_states.assert_called_with(42)
|
||||
assert acc.char_speed.value == 42
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
assert call_set_speed[0]
|
||||
assert call_set_speed[0].data[ATTR_ENTITY_ID] == entity_id
|
||||
assert call_set_speed[0].data[ATTR_SPEED] == "ludicrous"
|
||||
assert len(events) == 1
|
||||
assert events[-1].data[ATTR_VALUE] == "ludicrous"
|
||||
|
||||
# Verify speed is preserved from off to on
|
||||
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SPEED: SPEED_OFF})
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_speed.value == 42
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hk_driver.set_characteristics(
|
||||
{
|
||||
HAP_REPR_CHARS: [
|
||||
{
|
||||
HAP_REPR_AID: acc.aid,
|
||||
HAP_REPR_IID: char_active_iid,
|
||||
HAP_REPR_VALUE: 1,
|
||||
},
|
||||
]
|
||||
},
|
||||
"mock_addr",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_speed.value == 42
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
|
||||
async def test_fan_set_all_one_shot(hass, hk_driver, cls, events):
|
||||
"""Test fan with speed."""
|
||||
|
@ -960,6 +960,42 @@ async def test_mqtt_ws_remove_discovered_device_twice(
|
||||
assert response["error"]["code"] == websocket_api.const.ERR_NOT_FOUND
|
||||
|
||||
|
||||
async def test_mqtt_ws_remove_discovered_device_same_topic(
|
||||
hass, device_reg, hass_ws_client, mqtt_mock
|
||||
):
|
||||
"""Test MQTT websocket device removal."""
|
||||
config_entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
config_entry.add_to_hass(hass)
|
||||
await async_start(hass, "homeassistant", {}, config_entry)
|
||||
|
||||
data = (
|
||||
'{ "device":{"identifiers":["0AFFD2"]},'
|
||||
' "state_topic": "foobar/sensor",'
|
||||
' "availability_topic": "foobar/sensor",'
|
||||
' "unique_id": "unique" }'
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")}, set())
|
||||
assert device_entry is not None
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json(
|
||||
{"id": 5, "type": "mqtt/device/remove", "device_id": device_entry.id}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
|
||||
await client.send_json(
|
||||
{"id": 6, "type": "mqtt/device/remove", "device_id": device_entry.id}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert not response["success"]
|
||||
assert response["error"]["code"] == websocket_api.const.ERR_NOT_FOUND
|
||||
|
||||
|
||||
async def test_mqtt_ws_remove_non_mqtt_device(
|
||||
hass, device_reg, hass_ws_client, mqtt_mock
|
||||
):
|
||||
@ -1306,7 +1342,60 @@ async def test_debug_info_filter_same(hass, mqtt_mock):
|
||||
assert {
|
||||
"topic": "sensor/#",
|
||||
"messages": [
|
||||
{"topic": "sensor/abc", "payload": "123", "time": dt1},
|
||||
{"topic": "sensor/abc", "payload": "123", "time": dt2},
|
||||
{"payload": "123", "time": dt1, "topic": "sensor/abc"},
|
||||
{"payload": "123", "time": dt2, "topic": "sensor/abc"},
|
||||
],
|
||||
} == debug_info_data["entities"][0]["subscriptions"][0]
|
||||
|
||||
|
||||
async def test_debug_info_same_topic(hass, mqtt_mock):
|
||||
"""Test debug info."""
|
||||
config = {
|
||||
"device": {"identifiers": ["helloworld"]},
|
||||
"platform": "mqtt",
|
||||
"name": "test",
|
||||
"state_topic": "sensor/status",
|
||||
"availability_topic": "sensor/status",
|
||||
"unique_id": "veryunique",
|
||||
}
|
||||
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
await async_start(hass, "homeassistant", {}, entry)
|
||||
registry = await hass.helpers.device_registry.async_get_registry()
|
||||
|
||||
data = json.dumps(config)
|
||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||
assert device is not None
|
||||
|
||||
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
|
||||
assert {"topic": "sensor/status", "messages": []} in debug_info_data["entities"][0][
|
||||
"subscriptions"
|
||||
]
|
||||
|
||||
start_dt = datetime(2019, 1, 1, 0, 0, 0)
|
||||
with mock.patch("homeassistant.util.dt.utcnow") as dt_utcnow:
|
||||
dt_utcnow.return_value = start_dt
|
||||
async_fire_mqtt_message(hass, "sensor/status", "123", qos=0, retain=False)
|
||||
|
||||
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
|
||||
assert {
|
||||
"payload": "123",
|
||||
"time": start_dt,
|
||||
"topic": "sensor/status",
|
||||
} in debug_info_data["entities"][0]["subscriptions"][0]["messages"]
|
||||
|
||||
config["availability_topic"] = "sensor/availability"
|
||||
data = json.dumps(config)
|
||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
start_dt = datetime(2019, 1, 1, 0, 0, 0)
|
||||
with mock.patch("homeassistant.util.dt.utcnow") as dt_utcnow:
|
||||
dt_utcnow.return_value = start_dt
|
||||
async_fire_mqtt_message(hass, "sensor/status", "123", qos=0, retain=False)
|
||||
|
@ -621,3 +621,26 @@ async def test_setup_with_no_running_app(
|
||||
assert attr["source"] == "CAST"
|
||||
assert "app_id" not in attr
|
||||
assert "app_name" not in attr
|
||||
|
||||
|
||||
async def test_setup_tv_without_mute(
|
||||
hass: HomeAssistantType,
|
||||
vizio_connect: pytest.fixture,
|
||||
vizio_update: pytest.fixture,
|
||||
) -> None:
|
||||
"""Test Vizio TV entity setup when mute property isn't returned by Vizio API."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_USER_VALID_TV_CONFIG),
|
||||
unique_id=UNIQUE_ID,
|
||||
)
|
||||
|
||||
async with _cm_for_test_setup_without_apps(
|
||||
{"volume": int(MAX_VOLUME[VIZIO_DEVICE_CLASS_TV] / 2)}, STATE_ON,
|
||||
):
|
||||
await _add_config_entry_to_hass(hass, config_entry)
|
||||
|
||||
attr = _get_attr_and_assert_base_attr(hass, DEVICE_CLASS_TV, STATE_ON)
|
||||
_assert_sources_and_volume(attr, VIZIO_DEVICE_CLASS_TV)
|
||||
assert "sound_mode" not in attr
|
||||
assert "is_volume_muted" not in attr
|
||||
|
Loading…
x
Reference in New Issue
Block a user