亚马逊 Alexa 自定义技能
我想构建用于 Echo 的自定义命令
内置的 Alexa 集成功能允许您将 Home Assistant 集成到 Alexa/Amazon Echo 中。此集成功能将允许您通过使用语音查询信息并在 Home Assistant 中执行操作。Home Assistant 没有内置的句子,但提供了一个框架让您定义自己的句子。
要求
- 亚马逊开发者账号。您可以在 这里
注册。 - 如果您想使用 Alexa 自定义技能 API,则需要一个 AWS 账户
。您部分的 Alexa 自定义技能将托管在 AWS Lambda 上。不过,您无需担心费用,因为 AWS Lambda 每月允许最多使用 100 万次请求和 1GB 的外部数据传输免费。 - Alexa 自定义技能 API 还需要您的 Home Assistant 实例能够通过 HTTPS 在 443 端口从互联网访问,使用 亚马逊认可的证书机构
签名的证书。这是为了能够进行账户链接。更多信息请阅读我们关于 如何为 Home Assistant 设置加密的博客。当运行 Home Assistant OS 或 Supervised 时,使用 Duck DNS 插件是最简单的方法。
创建您的亚马逊 Alexa 自定义技能
- 登录 亚马逊开发者控制台
- 点击控制台顶部的 Alexa 按钮
- 点击右上角的蓝色“创建技能”按钮
- 模型添加:自定义
- 名称:HomeAssistantIntentsSkill(或您想命名的该技能)
- 托管方法:自行提供
您可以使用这个 特别大小的 Home Assistant 图标 作为大图标,使用 这个 作为小图标。
创建您的 Lambda 函数
Alexa 自定义技能会触发一个 AWS Lambda 函数来处理请求,我们将编写一小段代码作为 Lambda 函数来基本上将请求重定向到您的 Home Assistant 实例,然后 Home Assistant 中的 Alexa 集成功能将处理请求并发送响应。您的 Lambda 函数将把响应传递回 Alexa。
好的,我们开始吧。您需要先登录您的 AWS 控制台
为 Lambda 创建 IAM 角色
在您登录 AWS 控制台
- 点击顶部导航栏中的
Service
,展开菜单以显示所有 AWS 服务,点击Security, Identity, & Compliance
下的IAM
以导航到 IAM 控制台。或者您也可以使用这个 链接 - 在左侧面板中点击
Roles
,然后点击Create role
,在向导的第一页选择AWS Service
->Lambda
,然后点击Next: Permissions
- 选择
AWSLambdaBasicExecutionRole
策略,然后点击Next: Tags
。(提示:您可以使用搜索框过滤策略)
- 您可以跳过
Add tags
页面,点击Next: Review
。 - 给您的新角色命名,例如
AWSLambdaBasicExecutionRole-Intents
,然后点击Create role
按钮。您现在应该可以在角色列表中找到您的新角色。
创建 Lambda 函数并添加代码
接下来您需要创建一个 Lambda 函数。
- 点击顶部导航栏中的
Service
,展开菜单以显示所有 AWS 服务,在Compute
部分点击Lambda
以导航到 Lambda 控制台。或者您也可以使用这个 链接 -
重要 您当前的区域将在右上角显示。确保根据您亚马逊账户所在的国家选择正确的区域:
- 美国东部 (N. Virginia) 区域适用于英语(美国)或英语(加拿大)技能
- 欧洲 (爱尔兰) 区域适用于英语(英国)、英语(印度)、德语(德国)、西班牙语(西班牙)或法语(法国)技能
- 美国西部 (爱达荷) 区域适用于日语和英语(澳大利亚)技能。
- 在左侧导航栏中点击
Functions
,显示您的 Lambda 函数列表。 - 点击
Create function
,选择Author from scratch
,然后输入一个Function name
。 - 选择 Python 3. 作为
Runtime
(在此时可用 Python 3.9)。 - 选择 Use an existing role 作为
Execution role
,然后从Existing role
列表中选择您刚创建的角色。 - 点击
Create function
,然后您可以配置 Lambda 函数的详细信息。 - 在
Configuration
标签下,展开Designer
,然后在面板的左侧点击+ Add trigger
并从下拉列表中选择Alexa Skills Kit
为您的 Lambda 函数添加 Alexa Skills Kit 触发器。 - 向下滚动一点,您需要输入在上一步创建的技能中的
Skill ID
。(您可能需要切换回 Alexa 开发者控制台以复制Skill ID
。) - 在图表中点击您的 Lambda Function 图标并向下滚动,您将看到一个
Function code
窗口。 - 清除示例代码并复制这个 GitHub Gist
中的 Python 脚本。 - 点击
Function code
窗口的Deploy
按钮。 - 再次向下滚动并选择
Configuration
标签,点击它并在左侧您现在会找到Environment variables
,点击Edit
按钮并根据需要添加以下环境变量:- BASE_URL (必填):您的 Home Assistant 实例的互联网可访问 URL(如果需要,带端口)。不要包括尾部的
/
。 - NOT_VERIFY_SSL (可选):设置为 True 以忽略 SSL 问题,如果您没有有效的 SSL 证书或您正在使用自签名证书。
- DEBUG (可选):设置为 True 以记录调试信息。
- LONG_LIVED_ACCESS_TOKEN (可选,不推荐):您将连接您的 Alexa 自定义技能与 Home Assistant 用户账户,因此您不需要在此使用长期访问令牌。 然而,您从登录流程获得的访问令牌仅在 30 分钟内有效。 在测试数据中使用访问令牌进行 Lambda 函数测试会很困难。因此,为了方便起见,您可以从测试数据中删除访问令牌, 生成一个长期访问令牌 放在这里,这样函数将退回到从环境变量中读取令牌。(提示:您没有为环境变量启用安全存储,因此您在这里保存的令牌并不安全。您仅应将其用于调试和测试目的。调试完成后,应删除长期访问令牌。)
- BASE_URL (必填):您的 Home Assistant 实例的互联网可访问 URL(如果需要,带端口)。不要包括尾部的
- 点击
Save
按钮保存您的环境变量。 - 接下来,复制页面顶部显示的 ARN,这是该 Lambda 函数的身份。
- 返回到您的 Alexa 技能中,转到左侧的 Custom->Endpoint 菜单选项。
- 在“默认区域”中粘贴 ARN 值。注意:在您完成上一步向 AWS Lambda 函数添加 Alexa Skills Kit 触发器(在上一步中完成)之前,您将无法执行此操作。
账户链接
Alexa 可以将您的亚马逊账户链接到您的 Home Assistant 账户。因此 Home Assistant 可以确保只有经过身份验证的 Alexa 请求被执行。为了链接帐户,您必须确保您的 Home Assistant 实例可以从 Internet 访问。
- 登录 亚马逊开发者控制台
- 转到
Alexa Skills
页面。 - 找到您刚创建的技能,并在
Actions
列中点击Edit
。 - 在构建页面的左侧导航栏中点击
ACCOUNT LINKING
- 输入所有必需的信息。假设您的 Home Assistant 可以通过
https://[YOUR HOME ASSISTANT URL:PORT]
访问-
Authorization URI
:https://[YOUR HOME ASSISTANT URL]/auth/authorize
-
Access Token URI
:https://[YOUR HOME ASSISTANT URL]/auth/token
- 注意:您必须使用有效/受信任的 SSL 证书和 443 端口才能使账号链接正常工作。
-
Client ID
:-
https://pitangui.amazon.com/
如果您在美国 -
https://layla.amazon.com/
如果您在欧洲 -
https://alexa.amazon.co.jp/
如果您在日本或澳大利亚
尾部的斜杠在这里非常重要。
-
-
Client Secret
:输入您喜欢的任何内容,Home Assistant 不会检查此字段。 -
Client Authentication Scheme
:确保选择了 Credentials in request body。 Home Assistant 不支持 HTTP Basic。 -
Scope
:输入intent
。 Home Assistant 目前还不使用此项,但我们可能在未来使用它,当时会允许更细粒度的访问控制。
-
- 您可以将
Domain List
和Default Access Token Expiration Time
保持为空。
- 点击右上角的
Save
按钮。 - 接下来,您将使用 Alexa 手机应用程序或 Alexa 基于网络的应用程序
链接您的账户。 - 打开 Alexa 应用,导航到
Skills
->Your Skills
->Dev Skills
- 点击您刚创建的自定义技能。
- 点击
Enable
。 - 将打开一个新窗口,指引您进入您的 Home Assistant 登录屏幕。
- 在您成功登录后,您将被重定向回 Alexa 应用。
- 打开 Alexa 应用,导航到
配置您的亚马逊 Alexa 技能
Alexa 基于意图工作。每个意图都有一个名称和变量槽。例如,LocateIntent
有一个包含 User
的槽。示例意图架构:
{
"intents": [
{
"intent": "LocateIntent",
"slots": [
{
"name": "User",
"type": "AMAZON.US_FIRST_NAME"
}]
},
{
"intent": "WhereAreWeIntent",
"slots": []
}
]
}
要将这些意图绑定到用户说出的句子上,您需要定义话语。例如,这些示例话语可能如下所示:
LocateIntent Where is {User}
LocateIntent Where's {User}
LocateIntent Where {User} is
LocateIntent Where did {User} go
WhereAreWeIntent where we are
这意味着我们现在可以问 Alexa 诸如:
- Alexa,问 Home Assistant Paul 在哪里
- Alexa,问 Home Assistant 我们在哪里
配置 Home Assistant
当激活时,Alexa 集成将使 Home Assistant 的本机意图支持处理传入的意图。如果您想根据意图运行操作,请使用 intent_script
集成。
要启用 Alexa,请在您的 configuration.yaml
configuration.yaml 文件是 Home Assistant 的主要配置文件。它列出了要加载的集成及其特定配置。在某些情况下,需要直接在 configuration.yaml 文件中手动编辑配置。大多数集成可以在 UI 中配置。 [Learn more] 文件中添加以下条目。
在更改了configuration.yaml
configuration.yaml 文件是 Home Assistant 的主要配置文件。它列出了要加载的集成及其特定配置。在某些情况下,需要直接在 configuration.yaml 文件中手动编辑配置。大多数集成可以在 UI 中配置。 [Learn more] 文件后,重启 Home Assistant 以应用更改。
alexa:
使用场景
Alexa 集成最有用的应用之一是直接调用场景。通过在 Home Assistant 一侧进行一些简单设置并让 Alexa 知道您想要运行哪个场景,这很容易实现。
首先,我们将配置 Alexa。在亚马逊互动模块中添加以下内容到意图架构:
{
"intent": "ActivateSceneIntent",
"slots":
[
{
"name" : "Scene",
"type" : "Scenes"
}
]
}
然后创建一个名为 Scenes
的自定义槽类型,列出您想要控制的每个场景:
支持场景的自定义槽类型。
名称必须与场景名称完全匹配(去掉下划线 - 亚马逊会将其丢弃,我们稍后会通过模板将其映射回来)。
在新的 Alexa Skills Kit 中,您还可以为槽类型值创建同义词,可以在话语中用作基本值的替代。 同义词将替换在发送给 Alexa API 端点的意图请求中的其相关槽值,但仅当没有多个同义词匹配时。否则,将使用所说的同义词的值。
如果您想使用“可选 ID”字段替代同义词值,您只需在模板变量的末尾添加 “_Id”,例如 Scene_Id
。
带有同义词的自定义槽值。
添加一个示例话语:
ActivateSceneIntent activate {Scene}
然后将意图添加到 HA 配置文件中的 intent_script
部分:
intent_script:
ActivateSceneIntent:
action:
action: scene.turn_on
target:
entity_id: scene.{{ Scene | replace(" ", "_") }}
data:
id: {{ Scene_Id }}
speech:
type: plain
text: OK
在这里,我们使用 [模板] 来获取我们给 Alexa 的名称,例如,downstairs on
并将空格替换为下划线,使其变成 downstairs_on
,因为 Home Assistant 是这样期望的。
现在说 Alexa ask Home Assistant to activate <some scene>
,Alexa 将为您激活该场景。
添加脚本
我们可以轻松地将上述想法扩展到脚本上。同样,为脚本添加一个意图:
{
"intent": "RunScriptIntent",
"slots":
[
{
"name" : "Script",
"type" : "Scripts"
}
]
}
创建一个名为 Scripts
的自定义槽类型,列出您想要运行的每个脚本:
支持脚本的自定义槽类型。
添加一个示例话语:
RunScriptIntent run {Script}
然后将意图添加到 HA 配置文件的 intent_script 部分:
intent_script:
RunScriptIntent:
action:
action: script.turn_on
target:
entity_id: script.{{ Script | replace(" ", "_") }}
speech:
type: plain
text: OK
现在说 Alexa ask Home Assistant to run <some script>
,Alexa 将为您运行该脚本。
支持启动请求
有时您可能希望响应由“Alexa,红色警报!”之类的命令发起的启动请求。
首先,您需要获取技能 ID:
- 登录到 亚马逊开发者控制台
- 点击控制台顶部的 Alexa 按钮
- 点击 Alexa Skills Kit 开始按钮
- 查找您希望支持启动请求的技能
- 点击“查看技能 ID”链接并复制 ID
配置与意图相同,唯一不同的是您将使用技能 ID 而不是意图名称。
intent_script:
amzn1.ask.skill.08888888-7777-6666-5555-444444444444:
action:
action: script.turn_on
target:
entity_id: script.red_alert
speech:
type: plain
text: OK
支持会话结束请求
有时,您可能希望对由缺乏语音响应引发的会话结束请求进行处理。
首先,您需要获取技能 ID:
- 登录到 亚马逊开发者控制台
- 点击控制台顶部的 Alexa 按钮
- 点击 Alexa Skills Kit 开始按钮
- 查找您希望支持会话结束请求的技能
- 点击“查看技能 ID”链接并复制 ID
配置与意图相同,唯一不同的是您将使用技能 ID 而不是意图名称。
intent_script:
amzn1.ask.skill.08888888-7777-6666-5555-444444444444:
speech:
text: 已经很晚了。我关灯吗?
reprompt:
text: 我关灯吗?
AMAZON.YesIntent:
speech:
text: 完成了。晚安!
action:
action: switch.turn_off
target:
entity_id:
- switch.room1
- switch.room2
AMAZON.NoIntent:
speech:
text: 好的
amzn1.ask.skill.08888888-7777-6666-5555-444444444444.SessionEndedRequest:
action:
action: switch.turn_off
target:
entity_id:
- switch.room1
- switch.room2
赋予 Alexa 一些个性
在上述示例中,当 Alexa 成功完成任务时,我们告诉她说 OK
。这样有效但有点乏味!我们可以再次使用 [模板] 来给事情增添一些趣味。
首先创建一个名为 alexa_confirm.yaml
的文件,内容可以如下(继续,发挥创意!):
>
{{ [
"好的",
"当然",
"如果你坚持的话",
"完成了",
"没问题",
"我可以做到",
"交给我吧",
"一切照办",
"遵命",
"听从你的命令",
"确认",
"是的,尊敬的阁下",
"我会",
"依照你的命令行事",
"没问题"
] | random }}
然后,在您想像 OK
这样的简单文本响应的地方,将其替换为对该文件的引用,以便:
text: OK
变成:
text: !include alexa_confirm.yaml
现在,Alexa 每次都将用随机短语作出响应。您可以对尽可能多的不同意图使用这个 include,这样您只需创建列表一次。
规避必须说技能名称的问题
有时,您希望在不使用技能名称的情况下运行脚本或场景意图。例如,使用 ‘Alexa <some script>
’ 而不是 ‘Alexa ask Home Assistant to run <some script>
’,因为前者更简短。
您可以通过使用 Alexa 例程来实现此目的。
- 在 Alexa 应用中配置一个例程,以响应您想要使用的命令:
- 例如,‘Alexa,打开干衣机’。
- 确保此例程包括一个自定义操作,包含您在技能中配置的完整短语:
- 例如,‘Alexa,问 Home Assistant 运行干衣机上的脚本’。