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的設定完成:
    http://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. User: “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, 整個流程就完成了
    關燈的流程是差不多的, 就不贅述了