Ameba Arduino: [RTL8195] Amazon Alexa

使用Amazon Alexa控制Ameba

Alexa是Amazon底下的语音服务, 它可以连结至Amazon其它服务, 完成许多功能。著名的应用像是Amazon Echo, 功能定为在语音管家, 使用者可以对Amazon Echo说话, Echo解析这段语音, 做出适合的回应。
这个范例里会介绍如何使用Alexa控制Ameba上的LED, 涵盖的服务包括Amazon Alexa, AWS Lambda, AWS IoT, AWS IAM。

材料准备

  • Ameba x 1
  • LED灯泡 x 1

范例说明

底下是范例里的使用情境
(1) 使用者对支援Amazon Alexa服务的装置说 “Turn on the light”, Alexa根据使用者提供的schema与sample utterances file,解析之后产生intent json
(2) Alexa提交intent json至AWS Lambda, Lambda根据intent以及内容, 更新AWS IoT Shadow service
(3) AWS IoT Shadow service收到Lambda的讯息, 更新shadow state
(3.1) 此时如果Ameba在线上并且subscribe对应的shadow service, 就点亮LED
(3.2) Lambda产生回应至Alexa的文字与语音讯息, 并递交给Alexa
(4) 使用者听到成功点亮LED的语音讯息
1
其中Lambda取用其他服务时, 牵涉到权限的问题, 这部份会使用到AWS IAM的服务
底下各个章节分别介绍各个服务与范例的设定

Amazon Alexa – short introduction

Alexa Skills Kit (ASK) 是voice-driven的服务, 它可以连结至云端服务, 让使用者可以使用语音完成云端服务, 并且得到语音的回应, 其中语音的解析让使用者省去不少语音辨识的麻烦, 让使用者可以专心于设计互动模型与云端服务上。

Amazon Alexa - Custom Skills ag. Smart Home Skills

Alexa的服务可以分成两类
(1) Custom Skills: 使用者可以根据自己的需求设计互动模型, 包括对话流程, 解析关键字, 并发出intent
(2) Smart Home Skills: 使用者使用Alexa已经建制好的smart home的模型, 并且发出intent
这两类其实概念上很类似,Smart Home Skills省去一些麻烦,但考量到设计上的弹性, 这个范例里我们使用Custom Skills。
Amazon官方文件里有对这两类的比较有更详细的说明:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/understanding-the-different-types-of-skills

Amazon Alexa - Create Skill

首先我们先登入Alexa的开发网页, 点选Sign In, 填入的帐号可以与Amazon AWS的帐号不同
https://developer.amazon.com/alexa
2
接着点选ALEXA页签
3

出现Get started with Alexa的选项, 这里我们选择Alexa Skill Kit
4

进到管理skill的页面之后, 我们点选右边的 “Add a New Skill”
5

Amazon Alexa - Create Flow

点选 “Add a New Skill” 之后, 会出现一些设定的选项, 左边有整个流程的项目, 简介如下
6
1. Skill Information: 这里要​​填入一些基本资讯
2. Interaction Model: 这里要​​填入互动模型
3. Configuration: 这里要​​设定Alexa收到语音命令之后, 该往哪里提交request
4. Test: 这里可以对已经建制好的模型做测试, 这个阶段里, 使用者已经可以使用自己创建的服务
5. Publishing: Alexa的服务流程里, 最后会将使用者设计的服务上架, 所以需要填写相关的资讯
6. Privacy & Compliance: 设定一些隐私相关的设定

Amazon Alexa - Skill Information

我们首先填Skill Information
1. Skill type: 选择 “Custom Interaction Model”
2. Name: 这个地方填的是要显示给一般使用者的名称, 我们填入 “Control Light of Ameba”
3. Invocation Name: 这里填的是让Alexa识别要启动session的名称。一般来说, Alexa启动session的方式有两种, 第一种是讲出完整的内容, 让Alexa分析互动模型来决定要启动哪个session, 第二种是使用者只讲Invocation Name, 让Alexa启动特定的session。这里我们填入 “Ameba Controller”
Invocation Name的取名有一些限制, 要避开Alexa设定的关键字, 以及会造成误判语意的名称, 详细的限制说明可以参考这里:
https://developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kit/docs/choosing-the-invocation-name-for-an-alexa-skill
设定好之后, 我们点选Next
7

Amazon Alexa - Interaction Model

Intent Schema设定了这个Skill会用到的intent, 它使用JSON格式如下
8

一个skill里面可以填多个intent, 每个intent触发的的情况不同。 Intent里面可以填slot(也可以不填),slot就像是程式里的列举变数, 它分成两种

  • Custom slot type: 使用者需要为slot列举可能的值
  • Built-in slot type: Amazon定义了一些常用的slot, 像是日期, 数字, 城市名……, 这类的slot会以AMAZON为前缀字
  • 详细的schema写法可以参考Amazon官网文章:
    https://developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface
    这里我们将schema填入底下的值:
    9
    其中intent的名称是 “ControlLight”, 它有一个slot名称是 “LightState”, 型态是custom slot type “LIGHT_STATE”

    其中LIGHT_STATE是custom slot type, 所以我们点选 “Add Slot Type”来设定
    10
    接着会跳出一个视窗让我们填slot的名字, 以及列举的值,
    这里 “Enter Type” 的地方我们填 “LIGHT_STATE”, 接着 “Enter Values​​”的地方填入 “on”, “off”, 填完之后按 “Save”
    11
    于是在Custom Slot Types的地方可以看到多了一个 “LIGHT_STATE”的栏位
    12
    接着我们填写 Sample Utterances, 这里要填的是当使用者说了什么句子时, 可以触发哪些intent, 我们填入以下的值

    ControlLight Turn {LightState} the light
    ControlLight Turn the light {LightState}
    

    它的格式里, 前面带的是intent名称, 接着是空白或tab, 后面跟着是使用者说的句子, 以第一行来说, 代表当使用者说了 “Turn on the light”会触发ControlLight intent
    填完之后我们按 “Next”
    13

    Amazon Alexa - Configuration

    这个页面里需要填写与Alexa衔接的Endpoint。当使用者触发Alexa的intent之后, Alexa会将这个intent传递给其它service处理, 使用者可以自己架构这样的server, 或是使用Amazon AWS Lambda, 这里我们将暂停设定Alexa, 并且设定AWS Lambda, 稍后再将这部份完成
    14

    AWS Lambda – short introduction

    AWS Lambda是Amazon提供的计算服务, 它目前提供的程式语言有Node.js, Python, 以及java, 使用者可以撰写程式码, 并且使用AWS其它服务 (Ex. AWS IoT, logger)。 Lambda让使用者设定计算所需要的资源, 像是记忆体, 运算时间等等,Lambda会处理运算的部份。

    AWS Lambda – Create and select blueprint

    我们在浏览器开新的分页, 并且进入AWS Lambda的首页 https://aws.amazon.com/lambda/
    点选右边 “Sign in to the Console”
    15
    如果是第一次使用Amazon AWS的服务, 在写这篇文章的当下(2016/08/24), Amazon AWS提供第一年免费的试用方案。
    登入之后, 会进到AWS的服务列表, 因为写这篇文章的时候, Alexa与Lambda衔接的服务只支援us-east-1的区域, 所以我们先切换region, 点选右上角设定region, 选择 “US East (N. Virginia)
    16
    然后在左边Compute相关的服务里, 点选Lambda
    17
    点选 “Get Started Now”
    18
    Lambda预先设计了一些使用情境, 这些情境提供了一些sample code与default setting。要使用Alexa与Lambda衔接, 我们在Filter的地方填入Alexa
    19
    填完之后会筛选出与Alexa相关的blueprint, 其中“alexa-skills-kit-color-expert”与“alexa-skills-kit-color-export-python”是相似的blueprint, 差别只在于“alexa-skills -kit-color-expert”使用的程式语言是JavaScript, 而“alexa-skills-kit-color-export-python”使用python, 这里我们选择“alexa-skills-kit-color-expert”

    AWS Lambda – Configure triggers

    这个页面里可以设定触发Lambda开始运算的event从哪里来, 我们点中间的虚线方框, 底下会出现预先设定好的服务列表, 这里我们选择 “Alexa Skills Kit”
    20
    然后点选 “Next”
    21

    AWS Lambda – Configure function

    这个页面里, 我们要填入与程式相关的内容
    在Configure function里面, 有三个栏位:
    “Name”的栏位用来识别这个Lambda function, 这里我们填 “ControlLight”
    “Description”的栏位用来说明这个Lambda function的用途, 我们目前先使用预设值
    “Runtime”的栏位设定要使用的程式语言, 根据之前设定的blueprint, 这边出现的值是 “Node.js 4.3”, 使用者也可以在这里或之后切换使用的程式语言
    22
    在Lambda function code里面, 可以设定 Code entry type, 使用者可以选择直接线上写code, 或是上传程式码, 这里我们选择线上写code
    中间有一块是Lambda根据Alexa Skill Kit的blueprint提供的sample code, 有兴趣的读者可以花时间读一下了解它的架构
    这里我们先保留sample code, 之后再回来改code
    23
    接下来设定Lambda function handler and role
    “Handler”的部份, 我们保留预设值
    “Role”的设定关系到Lambda的权限, 为了避免Lambda function使用了不该使用的服务, 我们可以设定Lambda function的权限, 这部份的服务来自于AWS IAM, 不过我们可以在这里直接设定, 在“Role”的下拉选单里, 点选“Create a custom role”
    24
    此时将弹出新的浏览器页面, 并将你带至AWS IAM的服务

    AWS IAM – Create role from AWS Lambda

    在Lambda带出的AWS IAM的设定页面里, 我们设定 “Role Name”为 “control_light”
    25
    然后点选 “View Policy Document”
    26
    会出现这个role的权限, 我们点选 “Edit”
    27
    会跳出视窗, 要你读过Execution Role的说明, 这里点选 “OK”
    然后我们可以编辑这个role的权限, 可以看到预设值里, 这个Role的权限只有log的权限, 因为我们需要使用AWS IoT的权限, 所以我们修改它如下
    28
    接着点选 “Allow”
    29
    接着页面会关闭, 我们会跳回前一个Lambda设定的页面

    AWS Lambda – Configure function (cont.)

    设定新的Role并且从AWS IAM返回之后, 可以看到 “Role”以及 “Existing Role”的栏位已经有值
    30
    接着我们设定 Advanced settings
    这里可以设定 Lambda需要使用的memory与执行的时间,
    这里我们保留预设值, 接着点选 “Next”
    31

    AWS Lambda – Review

    最后会让你review相关的设定, 不过这些设定都可以之后再改变, 这里我们点选 “Create function”
    32
    会出现恭喜你已完成设定的讯息, 请注意, 右上角的字串“ARN - arn:aws:lambda:us-east-1:553661462376:function:ControlLight”, 就是这个Lambda function的end point, 这个会用来填入Alexa的设定页面
    33
    这里我们暂停AWS Lambda的设定, 并且设定好AWS IoT相关的设定

    AWS IoT – Create thing

    请参考之前的文章将Ameba与AWS IoT Shadow的设定完成:
    https://www.amebaiot.com/ameba-arduino-amazon-aws-iot/
    example的部份, 我们使用 "File" -> "Examples" -> "AmebaMQTTClient" -> "amazon_awsiot_with_ack"
    因为Alexa的限制需要将region改成us-east-1, 这部份需要特别注意:
    34
    完成之后, 我们点选ameba的thing, 让右边的资讯栏出现, 其中REST API endpoint里, 这个字串“a2zweh2b7yb784.iot.us-east-1.amazonaws.com”是AWS IoT提供给其它服务使用的endpoint, 这个endpoint我们会拿来填入Lambda所需的资讯里
    35

    AWS Lambda – Coding

    我们回到Lambda的设定页面, 点选 “code”页签
    36
    然后我们根据原本的程式码修改如下:code
    一些需要注意的修改如下:
    在这边, region要填入正确的region, 在endpoint的地方需要填入AWS IoT的endpoint, 也就是在thing 的资讯栏里, REST API endpoint的资讯, 请根据你创建的thing填入对应的endpoint
    37
    在onIntent函式里, 会比对intent的名字, 这边我们会比对我们设定的intent名字 “ControlLight”, 并且呼叫 setLightInSession的处理函式
    38
    在setLightInSession里面, 我们可以取得intent的slots资讯, 这边我们要取得的slot是 “LightState”
    39
    接着我们判断这个slot的内容, 并准备要上传至AWS IoT thing shadow的内容, 其中 “thingName”是AWS IoT我们设定好的thing name, 而payload是thing shadow的格式
    40
    设定好内容之后, 我们呼叫 updateThingShadow并上传至AWS IoT thing shadow
    41
    成功之后, 会呼叫console.log纪录内容在log里, 接着设定让Alexa回应的语音与文字内容
    42
    确认程式码之后, 点选上方的 “Save”
    43
    接着点选 “Action”, 会跳出一些选项, 我们点选 “Configure test event”
    44
    这部份在于设定测试用的event, 这个代表我们可以模拟从Alexa来的event, 以及该event携带的资讯, 我们将内容填入如下, 其中跟这个范例有关的修改有intent name, slot name & value
    45
    接着点选 “Save and test”
    46
    下方会出现执行的结果与log, 在Execution result里, 会看到response的outputSpeech里讯息为 “I now know you want to turn on the light”, 这段文字将预期会让Alexa以语音方式回应。右下角则是log, 如果写程式遇到麻烦需要加log, 可以在这边看到执行期间的log
    47
    切到AWS IoT的页面, 点选thing ameba, 在右边的资讯栏也会看到 “Last update” 会有一笔最新的更新, 代表AWS Lambda到AWS IoT这段功能已经成功
    49

    Amazon Alexa – Configuration (cont.)

    我们将浏览器的页签切回Alexa, 并且在Endpoint的栏位里选择“Lambda ARN”, 并且填入Lambda的endpoint “arn:aws:lambda:us-east-1:553661462376:function:ControlLight”,请根据你创建的Lambda function的endpoint填入对应的值, (请注意, 这个endpoint并不是AWS IoT里thing的REST API endpoint, 而是Lumbda function右上角的ARN的内容)
    接着点选 “Next”
    50

    Amazon Alexa – Test

    在Test页面, 我们可以做一些基本测试
    在Voice Simulator里, 我们可以测试Alexa收到的语音资料里, 它会如何发音
    它使用SSML tags让Alexa发出特定的语音像是拼出hello, 点选Listen就可以听看看语音的结果
    51
    这边的文字也就是Lambda回传的outputSpeech内容, 所以我们可以在Lambda的回传语音讯息里有更多弹性

    在 “Service Simulator”, 我们可以填入使用者发出的语音讯息, 并且让Alexa假装听到这个讯息做对应的处理, 这里我们填入 “Turn on the light”, 然后点选 “Ask Control Light of Ameba”
    52
    这段语音讯息会被Alexa处理, 送至Lambda function, Lambda function处理完之后再回传结果, 我们点选右下角的 “Listen” 可以聆听这段结果
    53
    同时我们可以切换浏览器页签至AWS IoT确定thing ameba有收到这份更新
    到这个阶段, 我们已经将整个功能都做完了。由于这个skill只是测试用途, 我们并不会接着做上架的设定, 使用者如果有兴趣可以接着做 “Publishing Information” 与 “Privacy & Compliance”
    但是在 “Test”阶段, 使用者已经可以使用自己创建的Skill, 我们接着看该如何实际测试

    测试 - 支援Alexa的装置

    首先我们需要支援Alexa的装置, Amazon有推出支援Alexa的装置, 你可以在这边找到相关的讯息:
    https://www.amazon.com/Amazon-Echo-Bluetooth-Speaker-with-WiFi-Alexa/dp/B00X4WHP5E
    或者你可以使用支援Alexa的手机应用程式, 这里我们使用IOS的应用程式:
    https://itunes.apple.com/us/app/lexi-for-alexa-voice-services/id1092933088
    一般来说这类app需要你登入amazon的帐户

    测试 - 管理Amazon Alexa

    在实际使用支援Alexa的装置时, 我们可以管理我们可以使用哪些Skill, 比如说我们可以订阅披萨公司推出的skill, 并用该skill订购披萨
    你可以登入网页版的管理页面:
    http://alexa.amazon.com/spa/index.html#cards
    或是使用手机应用程式, 但要注意目前app只开放美国地区下载
    https://www.amazon.com/gp/help/customer/display.html?nodeId=201602060
    在首页里, 会出现上一次Alexa听到的讯息, 这可以帮助你厘清是程式写错或者是Alexa听错
    54

    测试 - Demo

    实际在测试时, 因为turn on与turn off的语句与Amazon Smart home kit的关联性太高, 开关灯的其它的字眼也容易触发Smart home kit, 造成我们开发的skill无法被触发, 所以我们分两段呼叫我们的skill: 底下是影片事件流程
    1. Us​​er: “Alexa, ask Ameba Controller”
    这里的“Alexa, ask…”会让Alexa尝试找寻Invocation Name, 我们在“Amazon Alexa – Skill Information” 这小节里将Invocation Name设定成“Ameba Controller”, 所以当我们这样说, Alexa会开启Ameba Controller的session
    2. Alexa: "Welcome to the Ameba Controller example. Please tell me next action by saying, turn on the light"
    这段话出自于Lambda function里的 getWelcomeResponse(), 代表Lambda function 有收到IntentRequest的命令
    3. User: “Turn on the light”
    此时会等一阵子, Lambda会尝试将开灯的命令传至AWS IoT thing shadow
    4. Alexa: “I now know you want to turn on the light”
    此时灯亮, Lambda function在上传命令至AWS IoT thing shadow之后会关闭session, 整个流程就完成了
    关灯的流程是差不多的, 就不赘述了