mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
parent
7fcf07c964
commit
f18056f0a4
@ -8,6 +8,7 @@ import logging
|
|||||||
|
|
||||||
from voip_utils import SIP_PORT
|
from voip_utils import SIP_PORT
|
||||||
|
|
||||||
|
from homeassistant.auth.const import GROUP_ID_USER
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -43,6 +44,18 @@ class DomainData:
|
|||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up VoIP integration from a config entry."""
|
"""Set up VoIP integration from a config entry."""
|
||||||
|
# Make sure there is a valid user ID for VoIP in the config entry
|
||||||
|
if (
|
||||||
|
"user" not in entry.data
|
||||||
|
or (await hass.auth.async_get_user(entry.data["user"])) is None
|
||||||
|
):
|
||||||
|
voip_user = await hass.auth.async_create_system_user(
|
||||||
|
"Voice over IP", group_ids=[GROUP_ID_USER]
|
||||||
|
)
|
||||||
|
hass.config_entries.async_update_entry(
|
||||||
|
entry, data={**entry.data, "user": voip_user.id}
|
||||||
|
)
|
||||||
|
|
||||||
devices = VoIPDevices(hass, entry)
|
devices = VoIPDevices(hass, entry)
|
||||||
devices.async_setup()
|
devices.async_setup()
|
||||||
transport = await _create_sip_server(
|
transport = await _create_sip_server(
|
||||||
@ -87,3 +100,11 @@ async def async_remove_config_entry_device(
|
|||||||
) -> bool:
|
) -> bool:
|
||||||
"""Remove device from a config entry."""
|
"""Remove device from a config entry."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||||
|
"""Remove VoIP entry."""
|
||||||
|
if "user" in entry.data and (
|
||||||
|
user := await hass.auth.async_get_user(entry.data["user"])
|
||||||
|
):
|
||||||
|
await hass.auth.async_remove_user(user)
|
||||||
|
@ -2,16 +2,11 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"description": "Receive Voice over IP calls to interact with Assist."
|
||||||
"ip_address": "IP Address"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"invalid_ip_address": "Invalid IPv4 address."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entity": {
|
"entity": {
|
||||||
|
@ -55,6 +55,7 @@ class HassVoipDatagramProtocol(VoipDatagramProtocol):
|
|||||||
hass,
|
hass,
|
||||||
hass.config.language,
|
hass.config.language,
|
||||||
devices.async_get_or_create(call_info),
|
devices.async_get_or_create(call_info),
|
||||||
|
Context(user_id=devices.config_entry.data["user"]),
|
||||||
),
|
),
|
||||||
invalid_protocol_factory=lambda call_info: NotConfiguredRtpDatagramProtocol(
|
invalid_protocol_factory=lambda call_info: NotConfiguredRtpDatagramProtocol(
|
||||||
hass,
|
hass,
|
||||||
@ -77,6 +78,7 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol):
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
language: str,
|
language: str,
|
||||||
voip_device: VoIPDevice,
|
voip_device: VoIPDevice,
|
||||||
|
context: Context,
|
||||||
pipeline_timeout: float = 30.0,
|
pipeline_timeout: float = 30.0,
|
||||||
audio_timeout: float = 2.0,
|
audio_timeout: float = 2.0,
|
||||||
listening_tone_enabled: bool = True,
|
listening_tone_enabled: bool = True,
|
||||||
@ -94,7 +96,7 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol):
|
|||||||
self.listening_tone_enabled = listening_tone_enabled
|
self.listening_tone_enabled = listening_tone_enabled
|
||||||
|
|
||||||
self._audio_queue: asyncio.Queue[bytes] = asyncio.Queue()
|
self._audio_queue: asyncio.Queue[bytes] = asyncio.Queue()
|
||||||
self._context = Context()
|
self._context = context
|
||||||
self._conversation_id: str | None = None
|
self._conversation_id: str | None = None
|
||||||
self._pipeline_task: asyncio.Task | None = None
|
self._pipeline_task: asyncio.Task | None = None
|
||||||
self._session_id: str | None = None
|
self._session_id: str | None = None
|
||||||
|
13
tests/components/voip/snapshots/test_init.ambr
Normal file
13
tests/components/voip/snapshots/test_init.ambr
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_user_management
|
||||||
|
list([
|
||||||
|
dict({
|
||||||
|
'id': 'system-users',
|
||||||
|
'name': 'Users',
|
||||||
|
'policy': dict({
|
||||||
|
'entities': True,
|
||||||
|
}),
|
||||||
|
'system_generated': True,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
# ---
|
@ -1,4 +1,6 @@
|
|||||||
"""Test VoIP init."""
|
"""Test VoIP init."""
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
|
||||||
@ -9,3 +11,22 @@ async def test_unload_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test adding/removing VoIP."""
|
"""Test adding/removing VoIP."""
|
||||||
assert await hass.config_entries.async_unload(config_entry.entry_id)
|
assert await hass.config_entries.async_unload(config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_management(
|
||||||
|
hass: HomeAssistant, config_entry, setup_voip, snapshot: SnapshotAssertion
|
||||||
|
) -> None:
|
||||||
|
"""Test creating and removing voip user."""
|
||||||
|
user = await hass.auth.async_get_user(config_entry.data["user"])
|
||||||
|
assert user is not None
|
||||||
|
assert user.is_active
|
||||||
|
assert user.system_generated
|
||||||
|
assert not user.is_admin
|
||||||
|
assert user.name == "Voice over IP"
|
||||||
|
assert user.groups == snapshot
|
||||||
|
assert len(user.credentials) == 0
|
||||||
|
assert len(user.refresh_tokens) == 0
|
||||||
|
|
||||||
|
await hass.config_entries.async_remove(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert await hass.auth.async_get_user(user.id) is None
|
||||||
|
@ -6,7 +6,7 @@ import async_timeout
|
|||||||
|
|
||||||
from homeassistant.components import assist_pipeline, voip
|
from homeassistant.components import assist_pipeline, voip
|
||||||
from homeassistant.components.voip.devices import VoIPDevice
|
from homeassistant.components.voip.devices import VoIPDevice
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import Context, HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
_ONE_SECOND = 16000 * 2 # 16Khz 16-bit
|
_ONE_SECOND = 16000 * 2 # 16Khz 16-bit
|
||||||
@ -86,6 +86,7 @@ async def test_pipeline(
|
|||||||
hass,
|
hass,
|
||||||
hass.config.language,
|
hass.config.language,
|
||||||
voip_device,
|
voip_device,
|
||||||
|
Context(),
|
||||||
listening_tone_enabled=False,
|
listening_tone_enabled=False,
|
||||||
)
|
)
|
||||||
rtp_protocol.transport = Mock()
|
rtp_protocol.transport = Mock()
|
||||||
@ -133,6 +134,7 @@ async def test_pipeline_timeout(hass: HomeAssistant, voip_device: VoIPDevice) ->
|
|||||||
hass,
|
hass,
|
||||||
hass.config.language,
|
hass.config.language,
|
||||||
voip_device,
|
voip_device,
|
||||||
|
Context(),
|
||||||
pipeline_timeout=0.001,
|
pipeline_timeout=0.001,
|
||||||
listening_tone_enabled=False,
|
listening_tone_enabled=False,
|
||||||
)
|
)
|
||||||
@ -170,6 +172,7 @@ async def test_stt_stream_timeout(hass: HomeAssistant, voip_device: VoIPDevice)
|
|||||||
hass,
|
hass,
|
||||||
hass.config.language,
|
hass.config.language,
|
||||||
voip_device,
|
voip_device,
|
||||||
|
Context(),
|
||||||
audio_timeout=0.001,
|
audio_timeout=0.001,
|
||||||
listening_tone_enabled=False,
|
listening_tone_enabled=False,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user