1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 21:06:19 +00:00

Remove snips integration (#155461)

This commit is contained in:
Robert Resch
2025-10-29 23:22:30 +01:00
committed by GitHub
parent d57dc5d0cd
commit cce6f60b70
9 changed files with 0 additions and 974 deletions

View File

@@ -1,257 +0,0 @@
"""Support for Snips on-device ASR and NLU."""
from datetime import timedelta
import json
import logging
import voluptuous as vol
from homeassistant.components import mqtt
from homeassistant.core import (
DOMAIN as HOMEASSISTANT_DOMAIN,
HomeAssistant,
ServiceCall,
)
from homeassistant.helpers import config_validation as cv, intent
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.typing import ConfigType
DOMAIN = "snips"
CONF_INTENTS = "intents"
CONF_ACTION = "action"
CONF_FEEDBACK = "feedback_sounds"
CONF_PROBABILITY = "probability_threshold"
CONF_SITE_IDS = "site_ids"
SERVICE_SAY = "say"
SERVICE_SAY_ACTION = "say_action"
SERVICE_FEEDBACK_ON = "feedback_on"
SERVICE_FEEDBACK_OFF = "feedback_off"
INTENT_TOPIC = "hermes/intent/#"
FEEDBACK_ON_TOPIC = "hermes/feedback/sound/toggleOn"
FEEDBACK_OFF_TOPIC = "hermes/feedback/sound/toggleOff"
ATTR_TEXT = "text"
ATTR_SITE_ID = "site_id"
ATTR_CUSTOM_DATA = "custom_data"
ATTR_CAN_BE_ENQUEUED = "can_be_enqueued"
ATTR_INTENT_FILTER = "intent_filter"
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Optional(CONF_FEEDBACK): cv.boolean,
vol.Optional(CONF_PROBABILITY, default=0): vol.Coerce(float),
vol.Optional(CONF_SITE_IDS, default=["default"]): vol.All(
cv.ensure_list, [cv.string]
),
}
)
},
extra=vol.ALLOW_EXTRA,
)
INTENT_SCHEMA = vol.Schema(
{
vol.Required("input"): str,
vol.Required("intent"): {vol.Required("intentName"): str},
vol.Optional("slots"): [
{
vol.Required("slotName"): str,
vol.Required("value"): {
vol.Required("kind"): str,
vol.Optional("value"): cv.match_all,
vol.Optional("rawValue"): cv.match_all,
},
}
],
},
extra=vol.ALLOW_EXTRA,
)
SERVICE_SCHEMA_SAY = vol.Schema(
{
vol.Required(ATTR_TEXT): str,
vol.Optional(ATTR_SITE_ID, default="default"): str,
vol.Optional(ATTR_CUSTOM_DATA, default=""): str,
}
)
SERVICE_SCHEMA_SAY_ACTION = vol.Schema(
{
vol.Required(ATTR_TEXT): str,
vol.Optional(ATTR_SITE_ID, default="default"): str,
vol.Optional(ATTR_CUSTOM_DATA, default=""): str,
vol.Optional(ATTR_CAN_BE_ENQUEUED, default=True): cv.boolean,
vol.Optional(ATTR_INTENT_FILTER): vol.All(cv.ensure_list),
}
)
SERVICE_SCHEMA_FEEDBACK = vol.Schema(
{vol.Optional(ATTR_SITE_ID, default="default"): str}
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Activate Snips component."""
async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_system_packages_yaml_integration_{DOMAIN}",
breaks_in_ha_version="2025.12.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="deprecated_system_packages_yaml_integration",
translation_placeholders={
"domain": DOMAIN,
"integration_title": "Snips",
},
)
# Make sure MQTT integration is enabled and the client is available
if not await mqtt.async_wait_for_mqtt_client(hass):
_LOGGER.error("MQTT integration is not available")
return False
async def async_set_feedback(site_ids, state):
"""Set Feedback sound state."""
site_ids = site_ids if site_ids else config[DOMAIN].get(CONF_SITE_IDS)
topic = FEEDBACK_ON_TOPIC if state else FEEDBACK_OFF_TOPIC
for site_id in site_ids:
payload = json.dumps({"siteId": site_id})
await mqtt.async_publish(hass, FEEDBACK_ON_TOPIC, "", qos=0, retain=False)
await mqtt.async_publish(hass, topic, payload, qos=int(state), retain=state)
if CONF_FEEDBACK in config[DOMAIN]:
await async_set_feedback(None, config[DOMAIN][CONF_FEEDBACK])
async def message_received(msg):
"""Handle new messages on MQTT."""
_LOGGER.debug("New intent: %s", msg.payload)
try:
request = json.loads(msg.payload)
except TypeError:
_LOGGER.error("Received invalid JSON: %s", msg.payload)
return
if request["intent"]["confidenceScore"] < config[DOMAIN].get(CONF_PROBABILITY):
_LOGGER.warning(
"Intent below probaility threshold %s < %s",
request["intent"]["confidenceScore"],
config[DOMAIN].get(CONF_PROBABILITY),
)
return
try:
request = INTENT_SCHEMA(request)
except vol.Invalid as err:
_LOGGER.error("Intent has invalid schema: %s. %s", err, request)
return
if request["intent"]["intentName"].startswith("user_"):
intent_type = request["intent"]["intentName"].split("__")[-1]
else:
intent_type = request["intent"]["intentName"].split(":")[-1]
slots = {}
for slot in request.get("slots", []):
slots[slot["slotName"]] = {"value": resolve_slot_values(slot)}
slots[f"{slot['slotName']}_raw"] = {"value": slot["rawValue"]}
slots["site_id"] = {"value": request.get("siteId")}
slots["session_id"] = {"value": request.get("sessionId")}
slots["confidenceScore"] = {"value": request["intent"]["confidenceScore"]}
try:
intent_response = await intent.async_handle(
hass, DOMAIN, intent_type, slots, request["input"]
)
notification = {"sessionId": request.get("sessionId", "default")}
if "plain" in intent_response.speech:
notification["text"] = intent_response.speech["plain"]["speech"]
_LOGGER.debug("send_response %s", json.dumps(notification))
await mqtt.async_publish(
hass, "hermes/dialogueManager/endSession", json.dumps(notification)
)
except intent.UnknownIntent:
_LOGGER.warning(
"Received unknown intent %s", request["intent"]["intentName"]
)
except intent.IntentError:
_LOGGER.exception("Error while handling intent: %s", intent_type)
await mqtt.async_subscribe(hass, INTENT_TOPIC, message_received)
async def snips_say(call: ServiceCall) -> None:
"""Send a Snips notification message."""
notification = {
"siteId": call.data.get(ATTR_SITE_ID, "default"),
"customData": call.data.get(ATTR_CUSTOM_DATA, ""),
"init": {"type": "notification", "text": call.data.get(ATTR_TEXT)},
}
await mqtt.async_publish(
hass, "hermes/dialogueManager/startSession", json.dumps(notification)
)
async def snips_say_action(call: ServiceCall) -> None:
"""Send a Snips action message."""
notification = {
"siteId": call.data.get(ATTR_SITE_ID, "default"),
"customData": call.data.get(ATTR_CUSTOM_DATA, ""),
"init": {
"type": "action",
"text": call.data.get(ATTR_TEXT),
"canBeEnqueued": call.data.get(ATTR_CAN_BE_ENQUEUED, True),
"intentFilter": call.data.get(ATTR_INTENT_FILTER, []),
},
}
await mqtt.async_publish(
hass, "hermes/dialogueManager/startSession", json.dumps(notification)
)
async def feedback_on(call: ServiceCall) -> None:
"""Turn feedback sounds on."""
await async_set_feedback(call.data.get(ATTR_SITE_ID), True)
async def feedback_off(call: ServiceCall) -> None:
"""Turn feedback sounds off."""
await async_set_feedback(call.data.get(ATTR_SITE_ID), False)
hass.services.async_register(
DOMAIN, SERVICE_SAY, snips_say, schema=SERVICE_SCHEMA_SAY
)
hass.services.async_register(
DOMAIN, SERVICE_SAY_ACTION, snips_say_action, schema=SERVICE_SCHEMA_SAY_ACTION
)
hass.services.async_register(
DOMAIN, SERVICE_FEEDBACK_ON, feedback_on, schema=SERVICE_SCHEMA_FEEDBACK
)
hass.services.async_register(
DOMAIN, SERVICE_FEEDBACK_OFF, feedback_off, schema=SERVICE_SCHEMA_FEEDBACK
)
return True
def resolve_slot_values(slot):
"""Convert snips builtin types to usable values."""
if "value" in slot["value"]:
value = slot["value"]["value"]
else:
value = slot["rawValue"]
if slot.get("entity") == "snips/duration":
delta = timedelta(
weeks=slot["value"]["weeks"],
days=slot["value"]["days"],
hours=slot["value"]["hours"],
minutes=slot["value"]["minutes"],
seconds=slot["value"]["seconds"],
)
value = delta.total_seconds()
return value

View File

@@ -1,16 +0,0 @@
{
"services": {
"feedback_off": {
"service": "mdi:message-alert"
},
"feedback_on": {
"service": "mdi:message-alert"
},
"say": {
"service": "mdi:chat"
},
"say_action": {
"service": "mdi:account-voice"
}
}
}

View File

@@ -1,9 +0,0 @@
{
"domain": "snips",
"name": "Snips",
"codeowners": [],
"dependencies": ["mqtt"],
"documentation": "https://www.home-assistant.io/integrations/snips",
"iot_class": "local_push",
"quality_scale": "legacy"
}

View File

@@ -1,56 +0,0 @@
feedback_off:
fields:
site_id:
example: bedroom
default: default
selector:
text:
feedback_on:
fields:
site_id:
example: bedroom
default: default
selector:
text:
say:
fields:
custom_data:
example: user=UserName
default: ""
selector:
text:
site_id:
example: bedroom
default: default
selector:
text:
text:
required: true
example: My name is snips
selector:
text:
say_action:
fields:
can_be_enqueued:
default: true
selector:
boolean:
custom_data:
example: user=UserName
default: ""
selector:
text:
intent_filter:
example: "turnOnLights, turnOffLights"
selector:
object:
site_id:
example: bedroom
default: default
selector:
text:
text:
required: true
example: My name is snips
selector:
text:

View File

@@ -1,68 +0,0 @@
{
"services": {
"feedback_off": {
"description": "Turns feedback sounds off.",
"fields": {
"site_id": {
"description": "Site to turn sounds on, defaults to all sites.",
"name": "Site ID"
}
},
"name": "Feedback off"
},
"feedback_on": {
"description": "Turns feedback sounds on.",
"fields": {
"site_id": {
"description": "[%key:component::snips::services::feedback_off::fields::site_id::description%]",
"name": "Site ID"
}
},
"name": "Feedback on"
},
"say": {
"description": "Sends a TTS message to Snips.",
"fields": {
"custom_data": {
"description": "Custom data that will be included with all messages in this session.",
"name": "Custom data"
},
"site_id": {
"description": "Site to use to start session, defaults to default.",
"name": "Site ID"
},
"text": {
"description": "Text to say.",
"name": "Text"
}
},
"name": "Say"
},
"say_action": {
"description": "Sends a TTS message to Snips to listen for a response.",
"fields": {
"can_be_enqueued": {
"description": "Whether the session should wait for an open session to end. Otherwise it is dropped if another session is already running.",
"name": "Can be enqueued"
},
"custom_data": {
"description": "[%key:component::snips::services::say::fields::custom_data::description%]",
"name": "[%key:component::snips::services::say::fields::custom_data::name%]"
},
"intent_filter": {
"description": "Optional Array of Strings - A list of intents names to restrict the NLU resolution to on the first query.",
"name": "Intent filter"
},
"site_id": {
"description": "[%key:component::snips::services::say::fields::site_id::description%]",
"name": "Site ID"
},
"text": {
"description": "[%key:component::snips::services::say::fields::text::description%]",
"name": "Text"
}
},
"name": "Say action"
}
}
}

View File

@@ -6228,12 +6228,6 @@
"config_flow": true,
"iot_class": "local_push"
},
"snips": {
"name": "Snips",
"integration_type": "hub",
"config_flow": false,
"iot_class": "local_push"
},
"snmp": {
"name": "SNMP",
"integration_type": "hub",

View File

@@ -902,7 +902,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
"sms",
"smtp",
"snapcast",
"snips",
"snmp",
"snooz",
"solaredge",
@@ -1939,7 +1938,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
"sms",
"smtp",
"snapcast",
"snips",
"snmp",
"snooz",
"solaredge",

View File

@@ -1 +0,0 @@
"""Tests for the snips component."""

View File

@@ -1,559 +0,0 @@
"""Test the Snips component."""
import json
import logging
import pytest
import voluptuous as vol
from homeassistant.components import snips
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.intent import ServiceIntentHandler, async_register
from homeassistant.setup import async_setup_component
from tests.common import async_fire_mqtt_message, async_mock_intent, async_mock_service
from tests.typing import MqttMockHAClient
async def test_snips_config(
hass: HomeAssistant,
mqtt_mock: MqttMockHAClient,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test Snips Config."""
assert await async_setup_component(
hass,
"snips",
{
"snips": {
"feedback_sounds": True,
"probability_threshold": 0.5,
"site_ids": ["default", "remote"],
}
},
)
assert (
HOMEASSISTANT_DOMAIN,
f"deprecated_system_packages_yaml_integration_{snips.DOMAIN}",
) in issue_registry.issues
async def test_snips_no_mqtt(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test Snips Config."""
result = await async_setup_component(
hass,
"snips",
{
"snips": {
"feedback_sounds": True,
"probability_threshold": 0.5,
"site_ids": ["default", "remote"],
}
},
)
assert not result
assert "MQTT integration is not available" in caplog.text
async def test_snips_bad_config(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test Snips bad config."""
result = await async_setup_component(
hass,
"snips",
{
"snips": {
"feedback_sounds": "on",
"probability": "none",
"site_ids": "default",
}
},
)
assert not result
async def test_snips_config_feedback_on(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test Snips Config."""
result = await async_setup_component(
hass, "snips", {"snips": {"feedback_sounds": True}}
)
assert result
await hass.async_block_till_done()
assert mqtt_mock.async_publish.call_count == 2
topic = mqtt_mock.async_publish.call_args_list[0][0][0]
assert topic == "hermes/feedback/sound/toggleOn"
topic = mqtt_mock.async_publish.call_args_list[1][0][0]
assert topic == "hermes/feedback/sound/toggleOn"
assert mqtt_mock.async_publish.call_args_list[1][0][2] == 1
assert mqtt_mock.async_publish.call_args_list[1][0][3]
async def test_snips_config_feedback_off(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test Snips Config."""
result = await async_setup_component(
hass, "snips", {"snips": {"feedback_sounds": False}}
)
assert result
await hass.async_block_till_done()
assert mqtt_mock.async_publish.call_count == 2
topic = mqtt_mock.async_publish.call_args_list[0][0][0]
assert topic == "hermes/feedback/sound/toggleOn"
topic = mqtt_mock.async_publish.call_args_list[1][0][0]
assert topic == "hermes/feedback/sound/toggleOff"
assert mqtt_mock.async_publish.call_args_list[1][0][2] == 0
assert not mqtt_mock.async_publish.call_args_list[1][0][3]
async def test_snips_config_no_feedback(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test Snips Config."""
calls = async_mock_service(hass, "snips", "say")
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
await hass.async_block_till_done()
assert len(calls) == 0
async def test_snips_intent(hass: HomeAssistant, mqtt_mock: MqttMockHAClient) -> None:
"""Test intent via Snips."""
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"siteId": "default",
"sessionId": "1234567890ABCDEF",
"input": "turn the lights green",
"intent": {
"intentName": "Lights",
"confidenceScore": 1
},
"slots": [
{
"slotName": "light_color",
"value": {
"kind": "Custom",
"value": "green"
},
"rawValue": "green"
}
]
}
"""
intents = async_mock_intent(hass, "Lights")
async_fire_mqtt_message(hass, "hermes/intent/Lights", payload)
await hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == "snips"
assert intent.intent_type == "Lights"
assert intent
assert intent.slots == {
"light_color": {"value": "green"},
"light_color_raw": {"value": "green"},
"confidenceScore": {"value": 1},
"site_id": {"value": "default"},
"session_id": {"value": "1234567890ABCDEF"},
}
assert intent.text_input == "turn the lights green"
async def test_snips_service_intent(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test ServiceIntentHandler via Snips."""
hass.states.async_set("light.kitchen", "off")
calls = async_mock_service(hass, "light", "turn_on")
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"input": "turn the light on",
"intent": {
"intentName": "Lights",
"confidenceScore": 0.85
},
"siteId": "default",
"slots": [
{
"slotName": "name",
"value": {
"kind": "Custom",
"value": "kitchen"
},
"rawValue": "green"
}
]
}
"""
async_register(
hass, ServiceIntentHandler("Lights", "light", "turn_on", "Turned {} on")
)
async_fire_mqtt_message(hass, "hermes/intent/Lights", payload)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "light"
assert calls[0].service == "turn_on"
assert calls[0].data["entity_id"] == "light.kitchen"
assert "confidenceScore" not in calls[0].data
assert "site_id" not in calls[0].data
async def test_snips_intent_with_duration(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intent with Snips duration."""
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"input": "set a timer of five minutes",
"intent": {
"intentName": "SetTimer",
"confidenceScore": 1
},
"slots": [
{
"rawValue": "five minutes",
"value": {
"kind": "Duration",
"years": 0,
"quarters": 0,
"months": 0,
"weeks": 0,
"days": 0,
"hours": 0,
"minutes": 5,
"seconds": 0,
"precision": "Exact"
},
"range": {
"start": 15,
"end": 27
},
"entity": "snips/duration",
"slotName": "timer_duration"
}
]
}
"""
intents = async_mock_intent(hass, "SetTimer")
async_fire_mqtt_message(hass, "hermes/intent/SetTimer", payload)
await hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == "snips"
assert intent.intent_type == "SetTimer"
assert intent.slots == {
"confidenceScore": {"value": 1},
"site_id": {"value": None},
"session_id": {"value": None},
"timer_duration": {"value": 300},
"timer_duration_raw": {"value": "five minutes"},
}
async def test_intent_speech_response(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intent speech response via Snips."""
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
result = await async_setup_component(
hass,
"intent_script",
{
"intent_script": {
"spokenIntent": {
"speech": {"type": "plain", "text": "I am speaking to you"}
}
}
},
)
assert result
payload = """
{
"input": "speak to me",
"sessionId": "abcdef0123456789",
"intent": {
"intentName": "spokenIntent",
"confidenceScore": 1
},
"slots": []
}
"""
async_fire_mqtt_message(hass, "hermes/intent/spokenIntent", payload)
await hass.async_block_till_done()
assert mqtt_mock.async_publish.call_count == 1
payload = json.loads(mqtt_mock.async_publish.call_args[0][1])
topic = mqtt_mock.async_publish.call_args[0][0]
assert payload["sessionId"] == "abcdef0123456789"
assert payload["text"] == "I am speaking to you"
assert topic == "hermes/dialogueManager/endSession"
async def test_unknown_intent(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mqtt_mock: MqttMockHAClient
) -> None:
"""Test unknown intent."""
caplog.set_level(logging.WARNING)
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"input": "I don't know what I am supposed to do",
"sessionId": "abcdef1234567890",
"intent": {
"intentName": "unknownIntent",
"confidenceScore": 1
},
"slots": []
}
"""
async_fire_mqtt_message(hass, "hermes/intent/unknownIntent", payload)
await hass.async_block_till_done()
assert "Received unknown intent unknownIntent" in caplog.text
async def test_snips_intent_user(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intentName format user_XXX__intentName."""
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"input": "what to do",
"intent": {
"intentName": "user_ABCDEF123__Lights",
"confidenceScore": 1
},
"slots": []
}
"""
intents = async_mock_intent(hass, "Lights")
async_fire_mqtt_message(hass, "hermes/intent/user_ABCDEF123__Lights", payload)
await hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == "snips"
assert intent.intent_type == "Lights"
async def test_snips_intent_username(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intentName format username:intentName."""
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
payload = """
{
"input": "what to do",
"intent": {
"intentName": "username:Lights",
"confidenceScore": 1
},
"slots": []
}
"""
intents = async_mock_intent(hass, "Lights")
async_fire_mqtt_message(hass, "hermes/intent/username:Lights", payload)
await hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == "snips"
assert intent.intent_type == "Lights"
async def test_snips_low_probability(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intent via Snips."""
caplog.set_level(logging.WARNING)
result = await async_setup_component(
hass, "snips", {"snips": {"probability_threshold": 0.5}}
)
assert result
payload = """
{
"input": "I am not sure what to say",
"intent": {
"intentName": "LightsMaybe",
"confidenceScore": 0.49
},
"slots": []
}
"""
async_mock_intent(hass, "LightsMaybe")
async_fire_mqtt_message(hass, "hermes/intent/LightsMaybe", payload)
await hass.async_block_till_done()
assert "Intent below probaility threshold 0.49 < 0.5" in caplog.text
async def test_intent_special_slots(
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
) -> None:
"""Test intent special slot values via Snips."""
calls = async_mock_service(hass, "light", "turn_on")
result = await async_setup_component(hass, "snips", {"snips": {}})
assert result
result = await async_setup_component(
hass,
"intent_script",
{
"intent_script": {
"Lights": {
"action": {
"service": "light.turn_on",
"data_template": {
"confidenceScore": "{{ confidenceScore }}",
"site_id": "{{ site_id }}",
},
}
}
}
},
)
assert result
payload = """
{
"input": "turn the light on",
"intent": {
"intentName": "Lights",
"confidenceScore": 0.85
},
"siteId": "default",
"slots": []
}
"""
async_fire_mqtt_message(hass, "hermes/intent/Lights", payload)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "light"
assert calls[0].service == "turn_on"
assert calls[0].data["confidenceScore"] == 0.85
assert calls[0].data["site_id"] == "default"
async def test_snips_say(hass: HomeAssistant) -> None:
"""Test snips say with invalid config."""
calls = async_mock_service(hass, "snips", "say", snips.SERVICE_SCHEMA_SAY)
data = {"text": "Hello"}
await hass.services.async_call("snips", "say", data)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "snips"
assert calls[0].service == "say"
assert calls[0].data["text"] == "Hello"
async def test_snips_say_action(hass: HomeAssistant) -> None:
"""Test snips say_action with invalid config."""
calls = async_mock_service(
hass, "snips", "say_action", snips.SERVICE_SCHEMA_SAY_ACTION
)
data = {"text": "Hello", "intent_filter": ["myIntent"]}
await hass.services.async_call("snips", "say_action", data)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "snips"
assert calls[0].service == "say_action"
assert calls[0].data["text"] == "Hello"
assert calls[0].data["intent_filter"] == ["myIntent"]
async def test_snips_say_invalid_config(hass: HomeAssistant) -> None:
"""Test snips say with invalid config."""
calls = async_mock_service(hass, "snips", "say", snips.SERVICE_SCHEMA_SAY)
data = {"text": "Hello", "badKey": "boo"}
with pytest.raises(vol.Invalid):
await hass.services.async_call("snips", "say", data)
await hass.async_block_till_done()
assert len(calls) == 0
async def test_snips_say_action_invalid(hass: HomeAssistant) -> None:
"""Test snips say_action with invalid config."""
calls = async_mock_service(
hass, "snips", "say_action", snips.SERVICE_SCHEMA_SAY_ACTION
)
data = {"text": "Hello", "can_be_enqueued": "notabool"}
with pytest.raises(vol.Invalid):
await hass.services.async_call("snips", "say_action", data)
await hass.async_block_till_done()
assert len(calls) == 0
async def test_snips_feedback_on(hass: HomeAssistant) -> None:
"""Test snips say with invalid config."""
calls = async_mock_service(
hass, "snips", "feedback_on", snips.SERVICE_SCHEMA_FEEDBACK
)
data = {"site_id": "remote"}
await hass.services.async_call("snips", "feedback_on", data)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "snips"
assert calls[0].service == "feedback_on"
assert calls[0].data["site_id"] == "remote"
async def test_snips_feedback_off(hass: HomeAssistant) -> None:
"""Test snips say with invalid config."""
calls = async_mock_service(
hass, "snips", "feedback_off", snips.SERVICE_SCHEMA_FEEDBACK
)
data = {"site_id": "remote"}
await hass.services.async_call("snips", "feedback_off", data)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == "snips"
assert calls[0].service == "feedback_off"
assert calls[0].data["site_id"] == "remote"
async def test_snips_feedback_config(hass: HomeAssistant) -> None:
"""Test snips say with invalid config."""
calls = async_mock_service(
hass, "snips", "feedback_on", snips.SERVICE_SCHEMA_FEEDBACK
)
data = {"site_id": "remote", "test": "test"}
with pytest.raises(vol.Invalid):
await hass.services.async_call("snips", "feedback_on", data)
await hass.async_block_till_done()
assert len(calls) == 0