設定計時器 - Wio Terminal
在本課程的這部分,你將調用你的無伺服器代碼來理解語音,並根據結果在你的 Wio Terminal 上設置計時器。
設定計時器
從語音轉文字調用返回的文本需要發送到你的無伺服器代碼中,由 LUIS 處理,並返回計時器的秒數。這個秒數可以用來設置計時器。
微控制器在 Arduino 中本身不支持多線程,所以沒有像在 Python 或其他高級語言中那樣的標準計時器類。相反,你可以使用計時器庫,這些庫通過在 loop
函數中測量經過的時間,並在時間到時調用函數來工作。
任務 - 將文本發送到無伺服器函數
-
如果尚未打開,請 在 VS Code 中打開
smart-timer
項目。 -
打開
config.h
頭文件,並添加你的函數應用的 URL:const char *TEXT_TO_TIMER_FUNCTION_URL = "<URL>";
將
<URL>
替換為你在上一課的最後一步中獲得的函數應用的 URL,指向運行函數應用的本地機器的 IP 地址。 -
在
src
文件夾中創建一個名為language_understanding.h
的新文件。這將用於定義一個類,將識 別的語音發送到你的函數應用,並使用 LUIS 轉換為秒數。 -
在此文件的頂部添加以下內容:
#pragma once
#include <Arduino.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <WiFiClient.h>
#include "config.h"這包括了一些需要的頭文件。
-
定義一個名為
LanguageUnderstanding
的類,並聲明這個類的一個實例:class LanguageUnderstanding
{
public:
private:
};
LanguageUnderstanding languageUnderstanding; -
要調用你的函數應用,你需要聲明一個 WiFi 客戶端。將以下內容添加到類的
private
部分:WiFiClient _client;
-
在
public
部分,聲明一個名為GetTimerDuration
的方法來調用函數應用:int GetTimerDuration(String text)
{
} -
在
GetTimerDuration
方法中,添加以下代碼來構建要發送到函數應用的 JSON:DynamicJsonDocument doc(1024);
doc["text"] = text;
String body;
serializeJson(doc, body);這將傳遞給
GetTimerDuration
方法的文本轉換為以下 JSON:{
"text" : "<text>"
}其中
<text>
是傳遞給函數的文本。 -
在此下面,添加以下代碼來調用函數應用:
HTTPClient httpClient;
httpClient.begin(_client, TEXT_TO_TIMER_FUNCTION_URL);
int httpResponseCode = httpClient.POST(body);這會向函數應用發出一個 POST 請求,傳遞 JSON 主體並獲取響應代碼。
-
在此下面添加以下代碼:
int seconds = 0;
if (httpResponseCode == 200)
{
String result = httpClient.getString();
Serial.println(result);
DynamicJsonDocument doc(1024);
deserializeJson(doc, result.c_str());
JsonObject obj = doc.as<JsonObject>();
seconds = obj["seconds"].as<int>();
}
else
{
Serial.print("Failed to understand text - error ");
Serial.println(httpResponseCode);
}這段代碼檢查響應代碼。如果是 200(成功),則從響應主體中檢索計時器的秒數。否則,將錯誤發送到串行監視器,並將秒數設置為 0。
-
在此方法的末尾添加以下代碼來關閉 HTTP 連接並返回秒數:
httpClient.end();
return seconds; -
在
main.cpp
文件中,包含這個新的頭文件:#include "speech_to_text.h"
-
在
processAudio
函數的末尾,調用GetTimerDuration
方法來獲取計時器的持續時間:int total_seconds = languageUnderstanding.GetTimerDuration(text);
這將從調用
SpeechToText
類的文本轉換為計時器的秒數。
任務 - 設置計時器
這個秒數可以用來設置計時器。
-
在
platformio.ini
文件中添加以下庫依賴項來添加一個設置計時器的庫:contrem/arduino-timer @ 2.3.0
-
在
main.cpp
文件中添加這個庫的包含指令:#include <arduino-timer.h>
-
在
processAudio
函數上方,添加以下代碼:auto timer = timer_create_default();
這段代碼聲明了一個名為
timer
的計時器。 -
在此下面添加以下代碼:
void say(String text)
{
Serial.print("Saying ");
Serial.println(text);
}這個
say
函數最終會將文本轉換為語音,但現在它只會將傳遞的文本寫入串行監視器。 -
在
say
函數下面,添加以下代碼:bool timerExpired(void *announcement)
{
say((char *)announcement);
return false;
}這是一個回調函數,當計時器到期時會被調用。它會在計時器到期時傳遞一個消息。計時器可以重複,這可以通過這個回調的返回值來控制 - 這裡返回
false
,告訴計時器不要再次運行。 -
在
processAudio
函數的末尾添加以下代碼:if (total_seconds == 0)
{
return;
}
int minutes = total_seconds / 60;
int seconds = total_seconds % 60;這段代碼檢查總秒數,如果是 0,則從函數調用中返回,這樣就不會設置計時器。然後將總秒數轉換為分鐘和秒。
-
在此代碼下面,添加以下代碼來創建一個在計時器開始時要說的消息:
String begin_message;
if (minutes > 0)
{
begin_message += minutes;
begin_message += " minute ";
}
if (seconds > 0)
{
begin_message += seconds;
begin_message += " second ";
}
begin_message += "timer started."; -
在此下面,添加類似的代碼來創建一個在計時器到期時要說的消息:
String end_message("Times up on your ");
if (minutes > 0)
{
end_message += minutes;
end_message += " minute ";
}
if (seconds > 0)
{
end_message += seconds;
end_message += " second ";
}
end_message += "timer."; -
在此之後,說出計時器開始的消息:
say(begin_message);
-
在此函數的末尾,啟動計時器:
timer.in(total_seconds * 1000, timerExpired, (void *)(end_message.c_str()));
這會觸發計時器。計時器是以毫秒為單位設置的,所以總秒數乘以 1,000 轉換為毫秒。
timerExpired
函數作為回調傳遞,並將end_message
作為參數傳遞給回調。這個回調只接受void *
參數,所以字符串被適當地轉換。 -
最後,計時器需要 tick,這是在
loop
函數中完成的。在loop
函數的末尾添加以下代碼:timer.tick();
-
構建這個代碼,將其上傳到你的 Wio Terminal,並通過串行監視器進行測試。當你在串行監視器中看到
Ready
時,按下 C 按鈕(左側最靠近電源開關的那個),然後說話。將捕獲 4 秒的音頻,轉換為文本,然後發送到你的函數應用,並設置計時器。確保你的函數應用在本地運行。你將看到計時器開始和結束的時間。
--- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at http://bit.ly/pio-monitor-filters
--- Miniterm on /dev/cu.usbmodem1101 9600,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Connecting to WiFi..
Connected!
Got access token.
Ready.
Starting recording...
Finished recording
Sending speech...
Speech sent!
{"RecognitionStatus":"Success","DisplayText":"Set a 2 minute and 27 second timer.","Offset":4700000,"Duration":35300000}
Set a 2 minute and 27 second timer.
{"seconds": 147}
2 minute 27 second timer started.
Times up on your 2 minute 27 second timer.
💁 你可以在 code-timer/wio-terminal 文件夾中找到這段代碼。
😀 你的計時器程序成功了!