FlagMaker
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ###### tags: `FM611A` `MQTT` # MQTT 版 Lab 06 語音聲控電源插座實作教學 在 《[AI × LINE 聲控/人臉辨識生活大應用](https://www.flag.com.tw/maker/FM611A)》的〈Lab 06 語音聲控電源插座〉中, 由於 D1 mini 是**在區域網路**中, 如果你不在該區域網路下就無法使用, 減損了這個實驗的應用廣度。在這篇教學中, 我們就把原本的實驗改成使用在物聯網應用**相當普遍的 MQTT 傳輸協定**, 讓網頁改放至公開的網路上, 並透過 MQTT 當中介傳輸資料, 讓 D1 mini 可以接收到網頁語音辨識的結果。 ## MQTT 協定簡介 傳統網頁使用的 http 因為是泛用的協定, 必須考量到各種情況, 因此在傳輸資料時, 光是表頭的資料就要耗掉一定的傳輸量, 甚至常常有表頭的大小是實際傳輸資料量的數十甚至數百倍的狀況。如果採用 https, 又再加上電子憑證處理與加解密, 更是加重運算的負擔。 由於物聯網應用中, 個別裝置傳輸的資料量通常不大, 像是溫濕度數值、開關訊號等, 都是幾個位元組而以, 使用 http 不但浪費傳輸頻寬, 也會加重單晶片或是控制板的負擔。因此便有了**專門為物聯網應用而生的傳輸協定--MQTT**。 MQTT 傳輸協定主要區分為三種角色:**發佈端 (publisher)、中介伺服器 (broker)、訂閱端 (subscriber)**: ```graphviz digraph hierarchy { nodesep=1.0 // increases the separation between nodes node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour edge [color=Blue, style=dashed] //All the lines look like this 發佈端->中介伺服器 [label="發佈"] 中介伺服器->訂閱端 [label="轉送"] 訂閱端->中介伺服器 [label="訂閱"] {rank=same;發佈端 中介伺服器 訂閱端} // Put them on the same level } ``` - **中介伺服器**:建立傳輸資料的通道, 稱為**主題 (topic)**, 負責轉送發佈端送出的資料給訂閱端。 - **發送端**:可將資料送至中介伺服器上的特定主題。 - **訂閱端**:可向中介伺服器訂閱主題, 並在發送端傳送資料到該主題時自動收到由中介伺服器轉送過來的資料。 由於發送端與訂閱端都是與中介伺服器溝通, 因此統稱為 **MQTT 用戶端 (client)**, 兩者並不直接傳輸資料。每一個裝置都可以連上中介伺服器成為發佈端或是訂閱端, 甚至同時是發佈端與訂閱端。 這樣的作法連帶的好處就是發佈端與訂閱端都只要能夠連上外部網路接到 MQTT 中介伺服器即可相互通訊, 不會因為**防火牆**或是**路由器**阻擋外部裝置連入而無法傳遞資料。 ## 實驗架構 本實驗就以語音辨識網頁為發佈端, Adafruit IO(簡稱 AIO) 為中介伺服器, D1 mini 控制板為訂閱端, 利用 MQTT 傳輸語音辨識結果: ```graphviz digraph hierarchy { nodesep=1.0 // increases the separation between nodes node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour edge [color=Blue, style=dashed] //All the lines look like this p[label="語音辨識網頁"] m[label="AIO 中介伺服器"] s[label="D1 mini 控制板"] p->m [label="發佈"] m->s [label="轉送"] s->m [label="訂閱"] {rank=same;p m s} // Put them on the same level } ``` 每當語音辨識網頁辨識出開燈的口令, 就要傳送 "100" 到中介伺服器的 voice 主題上;若是關燈的口令, 則要傳送 "0" 到 voice 主題上。D1 mini 則是要向中介伺服器訂閱 voice 主題, 就會自動在辨識出開關燈口令時收到 "100" 或是 "0", 即可依據收到的資料做出對應控制的動作了。 我們已經將語音辨識網頁準備好放在 https://flagtech.github.io/FM611A/voice_recog_mqtt.html, 只要使用瀏覽器連上就可以使用: ![](https://i.imgur.com/ObnZW25.png) 後續教學我們將著重在 AIO 以及 D1 mini 的程式上。 ## 申請 AIO 帳號 要完成 MQTT 傳輸, 最重要的就是中介伺服器, 請依照以下步驟到 AIO 註冊帳號, 並且建立 MQTT 傳輸主題: 1. 請連線至 [Adafruit IO](https://io.adafruit.com/): ![](https://i.imgur.com/4HEyirs.png) 點選**Get Started fir Free** 1. 填寫必要欄位後按 **CREATE ACCOUNT** 建立帳號: ![](https://i.imgur.com/Y8wGMwg.png) 1. 建立後點選上方的 **IO** 頁次: ![](https://i.imgur.com/kCkVtjs.png) 1. 點選 **Feeds** 頁次後按 **view all**: ![](https://i.imgur.com/vCTxk3Q.png) 按 **New Feed** ![](https://i.imgur.com/K8AbEW1.png) 填入名稱為 "voice" 後按 **Create** 建立: ![](https://i.imgur.com/Ekmj4MJ.png) 這裡建立的 feed 就是稍後 MQTT 傳輸時的主題。 1. 按一下網頁右上方的 **My Key**: ![](https://i.imgur.com/v9TkK7U.png) 這裡顯示的 **Username** 與 **Active Key** 就是稍後用戶端連上 AIO 時要填入的使用者名稱與金鑰: ![](https://i.imgur.com/pEODTwC.png) 請把網頁停留在這個畫面, 方便稍後複製使用。 ## 使用語音辨識網頁測試 AIO 建立好 AIO 帳號與傳輸主題後, 就可以使用語音辨識網頁測試: 1. 請使用 Chrome 瀏覽器連至 [https://flagtech.github.io/FM611A/voice_recog_mqtt.html](https://flagtech.github.io/FM611A/voice_recog_mqtt.html), 請在網頁下方欄位分別填入剛剛看到的 AIO 使用者名稱與金鑰, 然後按一下**開始辨識聲音**: ![](https://i.imgur.com/nn017i1.png) 按**允許**以便能夠使用麥克風蒐集聲音: ![](https://i.imgur.com/WvLfom7.png) 上方會出現訊息告知以成功連至 MQTT 伺服器: ![](https://i.imgur.com/Rz5tdWW.png) 1. 此時即可說出『打開』口令, 若成功辨識, 便會出現訊息表示已將辨識結果傳送至 AIO: ![](https://i.imgur.com/wvTZlue.png) 1. 切換到 AIO 網頁, 關閉剛剛的金鑰顯示畫面後按剛剛建立的 voice: ![](https://i.imgur.com/eIJdRCh.png) 往下捲就會看到剛剛打開口令傳送的 100: ![](https://i.imgur.com/St6WBsD.png) 1. 你可以試看看講『關閉』或是『打開』多次, 就可以看到每次辨識結果送來的資料: ![](https://i.imgur.com/0PhlxZZ.png) :::info 有關語音辨識網頁的內容, 有興趣的人可以自行檢視原始碼, 我們並不會詳細說明。 ::: ## FlagsBlock 程式 現在已經可以讓語音辨識網頁將辨識結果發佈至 AIO 上, 最後一步就是要讓 D1 mini 程式可以跟 AIO 訂閱資料, 並依據資料執行對應的開關動作了: :::info 你可以在這裡[下載程式檔](https://github.com/FlagTech/FM611A_Extra/archive/8be273da9fc6abe8b30ccc43bc2a7d57ecba2d94.zip) ::: 1. 請進入 FlagsBlock, 完成以下積木, 這部分與其他實驗相同, 不再贅述: ![](https://i.imgur.com/iilFyKe.png) 請務必記得修改成你自己的無線網路名稱與密碼。 2. 定義處理收到 MQTT 訊息時的處理, 請先加入**函式/定義函式**積木後更改名稱為 "取得遠端指令": ![](https://i.imgur.com/4falSFC.png) 加入**流程控制/如果**積木, 並展開**否則如果**分支: ![](https://i.imgur.com/cJ7Q3Fv.png) 加入 2 個**邏輯/=** 積木: ![](https://i.imgur.com/vgdjszD.png) 在 **=** 積木內部左側的欄位都放入 **ESP8266 物聯網/新訊息內容**積木, 右側分別放入**文字/❝❞**積木後填入 100 與 0: ![](https://i.imgur.com/Ld02dkh.png) 最後填入收到個別訊息時要執行的開關繼電器動作: ![](https://i.imgur.com/kO7RNSa.png) 1. 指定 MQTT 中介伺服器的位址與通訊埠邊號, 請加入**ESP8266 物聯網/啟用網址...埠號...的 MQTT 服務**, 填入 AIO 中介伺服器的網址 io.adafruit.com 與埠號 1883: ![](https://i.imgur.com/Nx2xvhc.png) 再加入**ESP8266 物聯網/使用...函式接收 MQTT 訊息**積木, 並選取剛剛設計的**取得遠端指令**函式, 這表示當收到新的訊息時, 會自動執行這個函式: ![](https://i.imgur.com/sPDQjr7.png) 1. 最後就是實際連接 AIO 中介伺服器並接收資料的程式了, 請加入**流程控制/重複當**積木、**邏輯/非**積木、**ESP8266 物聯網/已連上 MQTT 伺服器?**積木後如下組合: ![](https://i.imgur.com/fD7oYqy.png) 再加入**流程控制/如果**積木後展開**否則如果**分支, 如下組合: ![](https://i.imgur.com/EeoFiwE.png) 加入**ESP8266 物聯網/以...名稱...帳號...密碼連上 MQTT 伺服器**積木, 名稱欄位請留空, 然後在**帳號**與**密碼**欄位填入剛剛看到的 AIO 名稱與金鑰: ![](https://i.imgur.com/Y9leR3w.png) 加入**ESP8266 物聯網/訂閱 MQTT 主題**積木在連線成功時訂閱主題, 注意到雖然我們建立的 Feed 名稱是 "voice", 但是 AIO 規定主題要再加上使用者名稱與 "feeds" 字樣, 並以 "/" 分隔, 所以完整的主題是 "你的使用者名稱/feed/voice": ![](https://i.imgur.com/4RoWFAS.png) 上例就是因為我的使用者名稱是 "meeboxflag", 所以訂閱的主題是 "meeboxflag/feeds/voice"。接著再加上**時間/暫停 1000 毫秒**積木在無法連上 MQTT 伺服器時等待 1 秒後再重試: ![](https://i.imgur.com/HFjyhrw.png) 最後最重要的是加上**ESP8266 物聯網/處理 MQTT 請求**積木, 以便能夠接收 MQTT 伺服器送來的資料: ![](https://i.imgur.com/ULdjy7i.png) 1. 這樣就完成了 D1 mini 的程式, 請記得修改你的無線網路名稱與密碼、AIO 使用者名稱與金鑰、訂閱主題中的 AIO 使用者名稱後上傳程式, 利用語音辨識網頁辨識口令, 即可控制接在 D1 mini 上的繼電器了。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully