mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 16:17:20 +00:00
Merge branch 'dev' of https://github.com/redgtech-automacao/core into dev
This commit is contained in:
commit
c0db1c8f81
@ -274,6 +274,11 @@ class AssistSatelliteEntity(entity.Entity):
|
||||
|
||||
try:
|
||||
await self.async_start_conversation(announcement)
|
||||
except Exception:
|
||||
# Clear prompt on error
|
||||
self._conversation_id = None
|
||||
self._extra_system_prompt = None
|
||||
raise
|
||||
finally:
|
||||
self._is_announcing = False
|
||||
|
||||
|
@ -354,6 +354,7 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
||||
"""Wait for a backup to complete."""
|
||||
backup_complete = asyncio.Event()
|
||||
backup_id: str | None = None
|
||||
create_errors: list[dict[str, str]] = []
|
||||
|
||||
@callback
|
||||
def on_job_progress(data: Mapping[str, Any]) -> None:
|
||||
@ -361,6 +362,7 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
||||
nonlocal backup_id
|
||||
if data.get("done") is True:
|
||||
backup_id = data.get("reference")
|
||||
create_errors.extend(data.get("errors", []))
|
||||
backup_complete.set()
|
||||
|
||||
unsub = self._async_listen_job_events(backup.job_id, on_job_progress)
|
||||
@ -369,8 +371,11 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
||||
await backup_complete.wait()
|
||||
finally:
|
||||
unsub()
|
||||
if not backup_id:
|
||||
raise BackupReaderWriterError("Backup failed")
|
||||
if not backup_id or create_errors:
|
||||
# We should add more specific error handling here in the future
|
||||
raise BackupReaderWriterError(
|
||||
f"Backup failed: {create_errors or 'no backup_id'}"
|
||||
)
|
||||
|
||||
async def open_backup() -> AsyncIterator[bytes]:
|
||||
try:
|
||||
|
1
homeassistant/components/heicko/__init__.py
Normal file
1
homeassistant/components/heicko/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Virtual integration: Heicko."""
|
6
homeassistant/components/heicko/manifest.json
Normal file
6
homeassistant/components/heicko/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "heicko",
|
||||
"name": "Heicko",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -9,5 +9,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["onedrive_personal_sdk"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["onedrive-personal-sdk==0.0.1"]
|
||||
"requirements": ["onedrive-personal-sdk==0.0.2"]
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["roborock"],
|
||||
"requirements": [
|
||||
"python-roborock==2.9.7",
|
||||
"python-roborock==2.11.1",
|
||||
"vacuum-map-parser-roborock==0.1.2"
|
||||
]
|
||||
}
|
||||
|
1
homeassistant/components/smart_rollos/__init__.py
Normal file
1
homeassistant/components/smart_rollos/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Virtual integration: Smart Rollos."""
|
6
homeassistant/components/smart_rollos/manifest.json
Normal file
6
homeassistant/components/smart_rollos/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "smart_rollos",
|
||||
"name": "Smart Rollos",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -541,9 +541,8 @@ class TodoistProjectData:
|
||||
return None
|
||||
|
||||
# All task Labels (optional parameter).
|
||||
task[LABELS] = [
|
||||
label.name for label in self._labels if label.name in data.labels
|
||||
]
|
||||
labels = data.labels or []
|
||||
task[LABELS] = [label.name for label in self._labels if label.name in labels]
|
||||
if self._label_whitelist and (
|
||||
not any(label in task[LABELS] for label in self._label_whitelist)
|
||||
):
|
||||
|
@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/todoist",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["todoist"],
|
||||
"requirements": ["todoist-api-python==2.1.2"]
|
||||
"requirements": ["todoist-api-python==2.1.7"]
|
||||
}
|
||||
|
1
homeassistant/components/ublockout/__init__.py
Normal file
1
homeassistant/components/ublockout/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Virtual integration: Ublockout."""
|
6
homeassistant/components/ublockout/manifest.json
Normal file
6
homeassistant/components/ublockout/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "ublockout",
|
||||
"name": "Ublockout",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -2521,6 +2521,11 @@
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"heicko": {
|
||||
"name": "Heicko",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
},
|
||||
"heiwa": {
|
||||
"name": "Heiwa",
|
||||
"integration_type": "virtual",
|
||||
@ -5812,6 +5817,11 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
"smart_rollos": {
|
||||
"name": "Smart Rollos",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
},
|
||||
"smarther": {
|
||||
"name": "Smarther",
|
||||
"integration_type": "virtual",
|
||||
@ -6747,6 +6757,11 @@
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
},
|
||||
"ublockout": {
|
||||
"name": "Ublockout",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
},
|
||||
"uk_transport": {
|
||||
"name": "UK Transport",
|
||||
"integration_type": "hub",
|
||||
|
6
requirements_all.txt
generated
6
requirements_all.txt
generated
@ -1559,7 +1559,7 @@ omnilogic==0.4.5
|
||||
ondilo==0.5.0
|
||||
|
||||
# homeassistant.components.onedrive
|
||||
onedrive-personal-sdk==0.0.1
|
||||
onedrive-personal-sdk==0.0.2
|
||||
|
||||
# homeassistant.components.onvif
|
||||
onvif-zeep-async==3.2.5
|
||||
@ -2452,7 +2452,7 @@ python-rabbitair==0.0.8
|
||||
python-ripple-api==0.0.3
|
||||
|
||||
# homeassistant.components.roborock
|
||||
python-roborock==2.9.7
|
||||
python-roborock==2.11.1
|
||||
|
||||
# homeassistant.components.smarttub
|
||||
python-smarttub==0.0.38
|
||||
@ -2899,7 +2899,7 @@ tilt-ble==0.2.3
|
||||
tmb==0.0.4
|
||||
|
||||
# homeassistant.components.todoist
|
||||
todoist-api-python==2.1.2
|
||||
todoist-api-python==2.1.7
|
||||
|
||||
# homeassistant.components.tolo
|
||||
tololib==1.1.0
|
||||
|
6
requirements_test_all.txt
generated
6
requirements_test_all.txt
generated
@ -1304,7 +1304,7 @@ omnilogic==0.4.5
|
||||
ondilo==0.5.0
|
||||
|
||||
# homeassistant.components.onedrive
|
||||
onedrive-personal-sdk==0.0.1
|
||||
onedrive-personal-sdk==0.0.2
|
||||
|
||||
# homeassistant.components.onvif
|
||||
onvif-zeep-async==3.2.5
|
||||
@ -1982,7 +1982,7 @@ python-picnic-api==1.1.0
|
||||
python-rabbitair==0.0.8
|
||||
|
||||
# homeassistant.components.roborock
|
||||
python-roborock==2.9.7
|
||||
python-roborock==2.11.1
|
||||
|
||||
# homeassistant.components.smarttub
|
||||
python-smarttub==0.0.38
|
||||
@ -2321,7 +2321,7 @@ thinqconnect==1.0.2
|
||||
tilt-ble==0.2.3
|
||||
|
||||
# homeassistant.components.todoist
|
||||
todoist-api-python==2.1.2
|
||||
todoist-api-python==2.1.7
|
||||
|
||||
# homeassistant.components.tolo
|
||||
tololib==1.1.0
|
||||
|
@ -34,6 +34,7 @@ def classic_led_ctrl_mock():
|
||||
)
|
||||
classic_led_ctrl_mock.name = "Mock classicLEDcontrol+e"
|
||||
classic_led_ctrl_mock.aquarium_name = "Mock Aquarium"
|
||||
classic_led_ctrl_mock.sw_version = "1.0.0_1.0.0"
|
||||
classic_led_ctrl_mock.light_mode = LightMode.DAYCL_MODE
|
||||
classic_led_ctrl_mock.light_level = (10, 39)
|
||||
return classic_led_ctrl_mock
|
||||
@ -47,6 +48,7 @@ def heater_mock():
|
||||
heater_mock.device_type = EheimDeviceType.VERSION_EHEIM_EXT_HEATER
|
||||
heater_mock.name = "Mock Heater"
|
||||
heater_mock.aquarium_name = "Mock Aquarium"
|
||||
heater_mock.sw_version = "1.0.0_1.0.0"
|
||||
heater_mock.temperature_unit = HeaterUnit.CELSIUS
|
||||
heater_mock.current_temperature = 24.2
|
||||
heater_mock.target_temperature = 25.5
|
||||
|
@ -1360,11 +1360,40 @@ async def test_reader_writer_create_partial_backup_error(
|
||||
assert supervisor_client.backups.partial_backup.call_count == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"supervisor_event",
|
||||
[
|
||||
# Missing backup reference
|
||||
{
|
||||
"event": "job",
|
||||
"data": {
|
||||
"done": True,
|
||||
"uuid": TEST_JOB_ID,
|
||||
},
|
||||
},
|
||||
# Errors
|
||||
{
|
||||
"event": "job",
|
||||
"data": {
|
||||
"done": True,
|
||||
"errors": [
|
||||
{
|
||||
"type": "BackupMountDownError",
|
||||
"message": "test_mount is down, cannot back-up to it",
|
||||
}
|
||||
],
|
||||
"uuid": TEST_JOB_ID,
|
||||
"reference": "test_slug",
|
||||
},
|
||||
},
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("hassio_client", "setup_integration")
|
||||
async def test_reader_writer_create_missing_reference_error(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
supervisor_client: AsyncMock,
|
||||
supervisor_event: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test missing reference error when generating a backup."""
|
||||
client = await hass_ws_client(hass)
|
||||
@ -1395,13 +1424,7 @@ async def test_reader_writer_create_missing_reference_error(
|
||||
assert supervisor_client.backups.partial_backup.call_count == 1
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{
|
||||
"type": "supervisor/event",
|
||||
"data": {
|
||||
"event": "job",
|
||||
"data": {"done": True, "uuid": TEST_JOB_ID},
|
||||
},
|
||||
}
|
||||
{"type": "supervisor/event", "data": supervisor_event}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
|
@ -38,7 +38,7 @@ def temp_dir_prefix() -> str:
|
||||
return "test"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_temp_dir(temp_dir_prefix: str) -> Generator[str]:
|
||||
"""Mock the certificate temp directory."""
|
||||
with patch(
|
||||
|
@ -4,7 +4,6 @@ import asyncio
|
||||
from collections.abc import Callable
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from random import getrandbits
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest.mock import MagicMock, patch
|
||||
@ -199,7 +198,6 @@ async def test_reading_non_exitisting_certificate_file() -> None:
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("temp_dir_prefix", "unknown")
|
||||
async def test_return_default_get_file_path(
|
||||
hass: HomeAssistant, mock_temp_dir: str
|
||||
) -> None:
|
||||
@ -211,12 +209,8 @@ async def test_return_default_get_file_path(
|
||||
and mqtt.util.get_file_path("some_option", "mydefault") == "mydefault"
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.mqtt.util.TEMP_DIR_NAME",
|
||||
f"home-assistant-mqtt-other-{getrandbits(10):03x}",
|
||||
) as temp_dir_name:
|
||||
tempdir = Path(tempfile.gettempdir()) / temp_dir_name
|
||||
assert await hass.async_add_executor_job(_get_file_path, tempdir)
|
||||
temp_dir = Path(tempfile.gettempdir()) / mock_temp_dir
|
||||
assert await hass.async_add_executor_job(_get_file_path, temp_dir)
|
||||
|
||||
|
||||
async def test_waiting_for_client_not_loaded(
|
||||
|
@ -70,6 +70,7 @@ def make_api_task(
|
||||
section_id=None,
|
||||
url="https://todoist.com",
|
||||
sync_id=None,
|
||||
duration=None,
|
||||
)
|
||||
|
||||
|
||||
@ -94,6 +95,7 @@ def mock_api(tasks: list[Task]) -> AsyncMock:
|
||||
url="",
|
||||
is_inbox_project=False,
|
||||
is_team_inbox=False,
|
||||
can_assign_tasks=False,
|
||||
order=1,
|
||||
parent_id=None,
|
||||
view_style="list",
|
||||
|
@ -1084,3 +1084,90 @@ async def test_start_conversation(
|
||||
# Wait for TTS
|
||||
await tts_sent.wait()
|
||||
await conversation_task
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("socket_enabled")
|
||||
async def test_start_conversation_user_doesnt_pick_up(
|
||||
hass: HomeAssistant,
|
||||
voip_devices: VoIPDevices,
|
||||
voip_device: VoIPDevice,
|
||||
) -> None:
|
||||
"""Test start conversation when the user doesn't pick up."""
|
||||
assert await async_setup_component(hass, "voip", {})
|
||||
|
||||
pipeline = assist_pipeline.Pipeline(
|
||||
conversation_engine="test engine",
|
||||
conversation_language="en",
|
||||
language="en",
|
||||
name="test pipeline",
|
||||
stt_engine="test stt",
|
||||
stt_language="en",
|
||||
tts_engine="test tts",
|
||||
tts_language="en",
|
||||
tts_voice=None,
|
||||
wake_word_entity=None,
|
||||
wake_word_id=None,
|
||||
)
|
||||
|
||||
satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id)
|
||||
assert isinstance(satellite, VoipAssistSatellite)
|
||||
assert (
|
||||
satellite.supported_features
|
||||
& assist_satellite.AssistSatelliteEntityFeature.START_CONVERSATION
|
||||
)
|
||||
|
||||
# Protocol has already been mocked, but "outgoing_call" is not async
|
||||
mock_protocol: AsyncMock = hass.data[DOMAIN].protocol
|
||||
mock_protocol.outgoing_call = Mock()
|
||||
|
||||
pipeline_started = asyncio.Event()
|
||||
|
||||
async def async_pipeline_from_audio_stream(
|
||||
hass: HomeAssistant,
|
||||
context: Context,
|
||||
*args,
|
||||
conversation_extra_system_prompt: str | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
# System prompt should be not be set due to timeout (user not picking up)
|
||||
assert conversation_extra_system_prompt is None
|
||||
|
||||
pipeline_started.set()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.assist_satellite.entity.async_get_pipeline",
|
||||
return_value=pipeline,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.voip.assist_satellite.VoipAssistSatellite.async_start_conversation",
|
||||
side_effect=TimeoutError,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.assist_satellite.entity.async_pipeline_from_audio_stream",
|
||||
new=async_pipeline_from_audio_stream,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.assist_satellite.entity.tts_generate_media_source_id",
|
||||
return_value="test media id",
|
||||
),
|
||||
):
|
||||
satellite.transport = Mock()
|
||||
|
||||
# Error should clear system prompt
|
||||
with pytest.raises(TimeoutError):
|
||||
await hass.services.async_call(
|
||||
assist_satellite.DOMAIN,
|
||||
"start_conversation",
|
||||
{
|
||||
"entity_id": satellite.entity_id,
|
||||
"start_message": "test announcement",
|
||||
"extra_system_prompt": "test prompt",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Trigger a pipeline so we can check if the system prompt was cleared
|
||||
satellite.on_chunk(bytes(_ONE_SECOND))
|
||||
async with asyncio.timeout(1):
|
||||
await pipeline_started.wait()
|
||||
|
Loading…
x
Reference in New Issue
Block a user