電話連結服務

設定電話互動選單內容

1.簡單的電話選單

使用RESTful Client透過phoneConfig API輸入下列JSON資料:
最簡單的JSON資料,必須要包含MAIN節點以及服務電話號碼,同時在送出資料到phoneConfig API的HTTP request header也要包含X-API-KEY header,才可以通過系統認證,成功設定播報的內容。
設定完成後,請使用電話撥打您租用的服務電話號碼(此範例中為028192000),電話接通後,就可以聽到語音播報出剛剛所輸入在text屬性的文字內容。

2.設定男聲或女聲

可以在各個JSON資料節點中promptMode屬性,設定播放的語音使用男性(M)或是女性(F),請再次使用RESTful Client送出下列資料到phoneConfig API:
再次撥打租用的服務電話028192000就可以聽到改用女性的聲音播報文字內容。

3.接收用戶輸入的數字按鍵

若是有多個語音選項要用戶輸入時,除了用JSON格式把資料輸入到phoneConfig API外,還需要搭配MQTT Client程式取得用戶輸入的按鍵。例如,要製作一個播報台北、台中、高雄天氣的電話服務,可以先透過phoneConfig API輸入下列的JSON資料:
與前一份JSON文件比較,在MAIN節點中加上了"collectDTMF":true的設定,代表在播放text的時,可以接收用戶按下的話機數字鍵。若用戶在播完語音後超過一段時間都沒有任何輸入(timeout),或是用戶按下數字鍵0-9,都會透過MQTT callEvent topic發送給創客的MQTT Client。
再來,需要撰寫一個簡單的MQTT Client程式,帳號及密碼請填寫IoT平台上金鑰管理中建立的API-KEY,連上伺服器(iot.cht.com.tw:2883)後,訂閱phone-conn/callEvent/${SNKey} topic,其中SNKey為當初在reg API租用電話服務號碼時,回傳訊息中的SNKey數值。本範例中回應的SNKey是38JUGOPLQ7deRpLm14IItQ,此處要訂閱的MQTT topic就是"phone-conn/callEvent/38JUGOPLQ7deRpLm14IItQ"。
測試時,撥打服務電話號碼,輸入按鍵1後,MQTT Client會從callEvent topic中收到如下的訊息:
在訊息中id屬性值由系統產生的一個識別字串,透過MQTT發送訊息回系統時,要回傳與接收到的訊息完全相同的id值,系統才可以正常運作。type屬性目前有"request"及"event"兩種,系統送回用戶按鍵事件其type為"request",若是系統送回的是用戶撥入服務號碼或是掛斷電話事件,type值會設定為"event"。phone屬性是撥入所租用電話服務號碼的用戶來電號碼,node屬性則是用戶所按下的數字鍵。在node屬性中,回報的數值是MAIN,1,代表的是用戶聽到MAIN節點的撥音後,按下的數字鍵1,此時,MQTT Client程式在接收到這個 MAIN,1 的事件後,應該從資料庫或是其他來源取得台北的天氣資料,轉換為如下JSON資料,並透過MQTT publish發送到phone-conn/callAction/${SNKey},以此例是發送到"phone-conn/callAction/38JUGOPLQ7deRpLm14IItQ" topic:
系統在收到回應的訊息後,用戶就可以從電話中聽到語音播報目前台北的氣溫及天氣狀況。
要注意的是,送到callAction中的訊息id屬性必須要與從callEvent接收到的id屬性完全相同,訊息才可以正確的被系統解讀, 並且必須要有node屬性以指定此訊息的節點名稱。node屬性的命名只允許英文A-Z、a-z、數字0-9及_符號,且首字必須為英文 字母(以正規表示式可以寫為node屬性只接受 ^[A-Za-z][A-Za-z0-9_]*$ )。另外也不可將節點命名為MAIN、CUSTOM、END等保 留字,節點名稱最長只允許16個字元,若沒有設定node屬性或是node屬性值不合法,則系統會將此MQTT訊息忽略。
MQTT訊息中的time屬性,是使用ISO 8601的時間表示法,所以以Z結尾時,代表表示的時間是世界協調時間(UTC+0),若是要轉換為台北時間(UTC+8)則是要自行加上8個小時。

4.用戶輸入錯誤及輸入逾時

修改一下phoneConfig的JSON資料,加入提示用戶輸入錯誤及輸入逾時(timeout)的處理訊息:
與之前的JSON文件比較,增加了一個命名為error的節點,也要修改一下MQTT Client程式,在收到不是預先規劃的"MAIN,1"、"MAIN,2"、"MAIN,3"輸入事件時,回應下列訊息給系統:
node屬性必須存在以設定節點的名稱,可以自行決定有意義的節點名稱。沒有text屬性,代表不播報任何語音,增加了nextNode屬性,代表跳轉到JSON文件中的error節點。
系統在跳轉到error節點,播放error節點中的錯誤訊息後,依error節點的設定,再跳轉到MAIN節點,重新播放選單內容。
另外,如果用戶太久沒有輸入任何的數字,系統會回應輸入逾時的事件給創客的MQTT Client,範例訊息如下:
此訊息代表在節點MAIN中等待太久都沒有取得用戶的輸入,所以callEvent topic回應MAIN,timeout的事件給創客,創客可以送出下列的回應訊息到MQTT topic
這個訊息指示系統跳轉到JSON中定義的timeout_handler節點播放語音,播完後再依timeout_handler節點的nextNode屬性值,跳回content節點重新播放選單及接收用戶輸入。
如果系統接收到用戶輸入太多次的錯誤時,也可以透過MQTT回應"nextNode":"END"訊息主動掛斷電話,END是系統保留的關鍵字,收到後會在播完訊息後掛斷電話,範例如下:

5.歡迎詞、結束詞

如果想設計一個有「歡迎詞」、「結束詞」提示用戶輸入按鍵的選單,要怎麼做?可以修改一下前面的範例,重新在phoneConfig API輸入JSON資料:
原本是選單進入點的MAIN節點,現在加上了系統歡迎詞,選單內文放在了content節點,text中的文字重複了2次,避免用第一次沒有聽清楚時,可以再重複聽一次,重複的句字間增加了多餘的空白,讓2段文字間可以有一些停頓的時間,而JSON中也增加了exit節點,放置系統結束詞,nextNode設定為系統保留字"END",會在播放在text的文字後,自動掛斷電話。
在這個範例中,用戶輸入1或2,創客從接收到的callEvent訊息中得知該執行查詢台北或是查詢高雄天氣的程式,而在用戶輸入數字鍵3時,則可以透過MQTT Client回應"nextNode":"exit"給系統,接收到的事件及回應訊息如下:
依照創客MQTT Client回應的訊息,系統會跳到exit節點,該節點有設定"nextNode":"END",系統會在播放完語音後自動掛斷電話。

6.多層選單

透過phoneConfig API的設定,可以建立多層的選單。考慮在phoneConfig API輸入下面的JSON選單內容:
在MAIN節點中,增加了DTMF屬性,這個屬性搭配collectDTMF屬性使用時,用來設定用戶可以按的數字鍵,以上面的設定為例,JSON中DTMF屬性指定了用戶只可以輸入數字鍵1或2,若用戶輸入數字1或2以外的按鍵,則會自動重覆播放text屬性,直到用戶輸入數字鍵1或2為止。
DTMF屬性使用"${key}":"${value}"的格式指定用戶輸入特定數字鍵後,要跳轉的節點名稱。如範例所示,用戶輸入1時,則會跳到weather_menu執行,播放text屬性設定的天氣選單。用戶輸入2時,所指定的節點是CUSTOM,這個是特別的保留字,執行CUSTOM時,系統會透過MQTT的callEvent topic發送"node":"MAIN,2"的訊息到創客的AP,等待創客的MQTT Client端程式發送MQTT訊息到callAction topic以指定接下來處理行為。
例如,若用戶撥入服務號碼後按下數字鍵2,創客的MQTT Client需要執行查詢台北空氣品質數值的程式取得查詢結果,再將結果轉換為合適的MQTT訊息送到callAction topic給系統,讓系統用語音方式播報給用戶聽。

7.通話事件

在創客的MQTT Client端,訂閱callEvent topic後,除了在用戶按下DTMF按鍵後會回報按鍵外,在每次用戶撥入租用的電話服務號碼時,也會收到「電話接通(CallEstablished)」及「電話掛斷(CallHangup)」事件通知。如下面的例子:系統接通電話後,會接到CallEstablished通知。
如下面的例子:系統接通電話後,會接到CallEstablished通知。
當用戶掛斷電話後,會收到CallHangUp通知。
從收到的事件通知訊息中,可以從phone屬性取得用戶的來電號碼是034240010,也可以由接收「電話接通(CallEstablished)」的事件通知來取得用戶使用服務的時間,或是在「電話掛斷(CallHangUp)」事件後進行一些用戶使用系統資源的釋放動作。

8.撥入電話先查詢再播音

試想一個使用情境是在用戶撥入服務電話後,需要先通知創客AP進行資料查詢或處理後,再決定要播放的語音檔內容。可以先在phoneConfig API中輸入下列的JSON資料:
這樣在用戶撥入電話後,會執行到nextNode屬性,跳到特別的保留字CUSTOM,系統會透過MQTT callEvent topic發送出"node":"MAIN"的訊息,創客收到的系統訊息範例如下:
創客可以在收到訊息後先進行自行架設的資料庫中進行用戶資料查詢或是其他操作,之後再透過callAction topic回應訊息,決定要播放給用戶的訊息內容,回應訊息的範例如下:
回應訊息的id值,要設定成與之前收到的MQTT "type": "request" 訊息相同的數值,系統才可以接收此回應訊息。範例中回應訊息的node屬性設定為playNode01,其中有指定播放的語音及設定"collectDTMF": true代表將等待用戶按鍵。用戶按下數字鍵後,將會再收到MQTT訊息告知用戶輸入的按鈕,訊息如下:
此訊息收到用戶在"node":"playNode01"執行時按下數字鍵1的事件,創客應執行「查詢剩餘停車位」的動作,執行完後再依查詢結果回應 callAction訊息,播放對應的語音訊息給用戶:

9.STT(音轉字)功能

系統中支援STT(音轉字)功能,首先,在phoneConfig API中輸入下列的JSON資料:
用戶撥入電話後,系統在發音完text屬性的文字後,會透過MQTT callEvent topic發送需求,等待創客回應下一個要執行的動作:
再來,請透過MQTT發送訊息到callAction topic中,回應的訊息要包含"collectText":"true"屬性,並且訊息中要包含node屬性,指明該節點的名稱。不可同時設定collectDTMF及collectText都為true,這樣該訊息會被系統忽略。
訊息包含"collectText":"true"屬性,所以在系統接收完用戶的語音後,會將語音辨識後的文字及信心值,透過MQTT callEvent topic回傳給創客:
回傳訊息中的node屬性值會列出進行collectText的節點名稱、語音辨識的結果文字以及辨識結果的「信心值」,通常是數值越高,代表用戶輸入的聲音較清晰,文字辨識效果較好。
再來,可以透過MQTT送出包含text屬性的訊息,回應適當的訊息給用戶:

10.MQTT與電話連結系統關係圖

上圖綠色的線條及圖示為創客在「電話互動選單功能」操作過程中要訂閱(subscribe)及發佈(publish)的topic。
創客端應用程式(Application, AP)要使用MQTT通訊協定訂閱callEvent topic及發佈callAction topic,在從callEvent topic接收到DTMF按鍵及電話事件後,發送訊息到callAction topic,控制電話系統回應給客戶的動作。