實例分享--告訴你如何使用語音和自然語言控制智能家居

来源:http://www.cnblogs.com/huangmeimao/archive/2017/09/07/7490622.html
-Advertisement-
Play Games

“智能家居”很早就出現在大家的視野中,但目前大部分還是停留在概念階段,如何讓智能家居真正的落地開花呢?我想人工智慧的出現必然會打破這種現狀。 作為一個開發者,你是不是還在糾結如何能夠用語音控制你的家居產品呢? 比如,用戶說:我回家了。 你可以幫他打開燈、打開空調。 ... ...


   ZigBee作為一種短距離、低功耗的無線通信區域網協議,其優點是超低功耗、安全性高和自組網,並且可容納多個設備,因此在智能家居控制中占有很大的優勢。

   但是,僅僅使用ZigBee技術來控制家居設備顯得比較單薄,或者不夠“智能”。

 比如,用戶說:我回家了。

 你可以幫他打開燈、打開空調。

 用戶說:來點浪漫的氣氛

 你可以給他打開音箱,情景燈調整柔和的狀態。

   要實現這些功能,需要經過錄音->語音識別->語義識別->根據語義輸出命令給硬體->硬體執行命令的過程。每個過程的實現都不是那麼容易。

   而隨著人工智慧、語音識別、自然語義理解的發展,語音控制智能家居將成為可能,但目前為止,大部分還處在概念階段或者開源的不是很多,如何讓智能家居真正的落地開花呢?本實例將做一些探索。

   這裡會以window java應用程式為例,講解如何通過語音識別控制智能家居,並輸出ZigBee3.0協議,也很方便和ZigBee協調器進行對接,實現語音直接控制硬體。

   下麵詳細介紹程式的功能和代碼實現,希望語音、語義理解今後能廣泛的應用在家居等控制領域。

1. 代碼下載

語音和自然語言控制智能家居輸出Zibee3.0協議實例源碼

註:下載代碼後請仔細閱讀說明文檔。
APP 測試請查看第3節。

2.功能分析

2.1 APP 工作流程

   APP的工作流程如下圖所示,圖中虛線框部分均由OLAMI開發平臺提供,後面會具體介紹OLAMI開發平臺的使用方法。
   其餘部分由APP來完成

enter image description here

  • 語音輸入

   OLAMI的語音識別支持兩種格式:

WAV 格式的 PCM 錄音數據,單聲道(mono)、16K 採樣率(16 KHz Sample Rate)、16 bits 位深(Bit
Resolution)。

Speex 音頻壓縮,節省數據傳輸量,壓縮參數:Wideband 模式、Quality(壓縮比)= 10、單聲道(mono)、16K
採樣率(16 KHz Sample Rate)。

   首先要確保硬體設備沒有問題,可以進行正常的語音錄入。在電腦上安裝好麥克風之後,在“開始菜單”中輸入“錄音機”。

enter image description here

   然後在彈出的錄音機中點擊“開始錄音”,使用話筒錄音後點擊“停止錄音”後會彈出保存錄音結果的對話框,保存,聽聽聲音正常即可。當然,也可以使用QQ等第三方測試麥克風的軟體。

enter image description here

   確定硬體設備無誤之後,只要通過javax.sound.sampled.TargetDataLine調用windows錄音功能,錄下符合OLAMI語音識別介面的聲音數據即可,我的錄音方式是一邊錄音,同時將原始數據通過speex壓縮的方式post給 OLAMI 語音識別的API介面。不是保存為wav文件之後再上傳,這樣能夠提高語音識別的效率。

  • 文字輸入:

    文字輸入即直接文本輸入,比如“打開空調”,“把彩燈調成紅色”。

  • 處理NLI輸出:

   即根據OLAMI NLI的語義輸出結果決定如何操作設備,比如當輸入為“打開燈”時,我們可以收到如下JSON數據:

    {
        "data": {
            "asr": {
                "result": "打開燈",
                "speech_status": 0,
                "final": true,
                "status": 0
            },
            "seg": "打開 燈 ",
            "nli": [
                {
                    "desc_obj": {
                        "status": 0
                    },
                    "semantic": [
                        {
                            "app": "smarthome",
                            "input": "打開燈",
                            "slots": [
                                {
                                    "modifier": [
                                        "open"
                                    ],
                                    "name": "control_obj",
                                    "value": "燈"
                                }
                            ],
                            "modifier": [],
                            "customer": "593664ad84ae0a0a3feec056"
                        }
                    ],
                    "type": "smarthome"
                }
            ]
        },
        "status": "ok"
    }

   slots中的“control_obj”即要操作的設備,上面的結果可以看到需要操作的設備是"燈",動作為"打開"。應用程式根據這兩個信息就可以在自己的設備中尋找“燈”這個設備,併發出“打開”命令。

  • 輸出ZigBee 3.0 協議:

   根據NLI的輸出我們可以判定要控制的設備是燈,而燈的cluster我們選擇了ZCL_CLUSTER_ID_GEN_ON_OFF, 根據這個cluster以及等的device ID等輸出命令即可。

  • 連接硬體:

    這裡沒有提供驅動硬體的代碼,但基本流程就是,將ZigBee協調器的開發版通過串口和電腦相連,軟體發出的命令經串口發送給協調器,再由協調器控制ZigBee協議即可。

2.2 APP功能

enter image description here

  • 文字輸入:

   通過設備選擇可以切換不同的例句。同時,可以在例句的框里輸入其他控制語句,按回車可以重覆輸入。比如:“請幫我打開燈”,“燈給我打開”,“開一下空調”,“空調的溫度提高一點”

enter image description here

  • 語音輸入:

點擊”開始錄音”,如果沒有點擊“停止錄音”,3秒之後會自動停止錄音。如果在這之前點擊了“停止錄音”,那麼會及時停止錄音,併進行語音識別。
識別後的文字會顯示在按鈕的上方,如下圖所示:

enter image description here

  • 設備模擬:

如上圖所示,應用程式中會模擬彩燈的顏色和空調的溫度、模式、風力,其原理就是根據輸出的Zigbee3.0協議進行顯示。

  • 命令輸出:

即輸出ZigBee3.0的協議。下麵列出例子中的幾種設備的協議信息

功能:僅支持打開和關閉
Device Dype: 0x100
命令:
Cluster ID: 0x0300
Cluster ID 的TI定義:ZCL_CLUSTER_ID_GEN_ON_OFF

actionID Action_frame(1 bit ) 參數組 說明
0x00 0x01 Off,關閉
0x01 0x01 On,打開

彩燈

功能:打開,關閉,顏色調節(例子僅支持紅、橙、黃、綠、青、藍、紫),氛圍調節,色調調節。比如運動氛圍、浪漫氛圍、冷色調、暖色調等。

Device Dype:0x0102
 命令:
Cluster ID: 0x0006
Cluster ID 的TI定義:ZCL_CLUSTER_ID_GEN_ON_OFF

actionID Action_frame(1 bit ) 參數組 說明
0x00 0x01 Off,關閉
0x01 0x01 On,打開

Cluster ID: 0x0300
Cluster ID 的TI定義:ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL

actionID Action_frame(1 bit ) 參數組 說明
0x08 0x01 Attr1,Attr2 (均為int16,即兩個位元組,數據格式編號為0x29 ) 設置彩燈的顏色,即R,G,B值。

第一個參數的高八位表示R值。
第一個參數的低八位表示G值。
第二個參數的高八位表示B值。
第二個參數的低八位無意義。|

電視

 功能:打開,關閉,提高降低音量,換台,
Device Dype:0x0006
命令:
Cluster ID: 0x0006
Cluster ID 的TI定義:ZCL_CLUSTER_ID_GEN_ON_OFF

actionID Action_frame(1 bit ) 參數組 說明
0x00 0x01 Off,關閉
0x01 0x01 On,打開
0x05 0x01 提高音量
0x06 0x01 降低音量

Cluster ID: 0x0008
Cluster ID 的TI定義:ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL

actionID Action_frame(1bit ) 參數組 說明
0x00 0x01 1個位元組,uint8 切換頻道
0x01 0x01 切換下個頻道
0x02 0x01 切換上個頻道

空調

功能:
開關功能,即打開和關閉空調。
切換模式,順序為“自動-製冷-除濕-送風-加熱”模式按順序迴圈切換,但不支持某個模式的設置。
風力切換,切換順序為“自動-低速-中低速-中速-中高速-高速-超強”。
其中,製冷和制熱模式支持上述7種風力切換。
送風和自動模式沒有“超強”風力
除濕無風力調節。
註意,僅支持切換,無風力設置。
升高溫度,切換一次,溫度上升一度,基礎範圍是16-30.
降低溫度,每切換一次,溫度下降一度,基礎範圍是16-30
狀態查詢,開關、溫度、風力、模式查詢。

Device Dype:0x0102

命令:

Cluster ID: 0x0300
Cluster ID 的TI定義:ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL

actionID Action_frame(1bit ) 參數組 說明
0x00 0x01 切換開關
0x01 0x01 切換模式
0x02 0x01 切換風速
0x03 0x01 Setup Button
0x04 0x01 Setdown Button

窗帘

功能:
打開,關閉,停止運行,指定窗帘運行的位置。
Device Dype: 0x202
命令:
Cluster ID: 0x102
Cluster ID 的TI定義:ZCL_CLUSTER_ID_CLOSURES_WINDOW_COVERING

actionID Action_frame(1bit ) 參數組 說明
0x00 0x01 打開
0x01 0x01 關閉
0x02 0x01 窗帘電機停止移動,並返回當前位置的百分比
0x04 0x01 窗帘號房間號,2bytes 設置窗帘號,房間號.其中高8位是房間號,低8位是窗帘號
0x05 0x01 百分比 單位百分比

其餘設備和感測器的ZigBee 輸出協議不再一 一列出,可以直接在APP中測試。

3 APP測試

   代碼下載解壓之後,可以在根目錄找到 smarthome.jar,在windows7 環境下雙擊即可以運行。
應用程式支持的語料除了選項里的,其他的相似說法也支持。

4 APP源碼解析

4.1 OLAMI語法載入

   因為APP調用了OLAMI的自然語言理解介面,所以首先是必須先寫語法,來匹配智能家居控制語句。比如:“打開燈”,“幫我打開空調”,必須在完成語法之後,才能從OLAMI的介面中獲取NLI結果。語法相關定義和寫法等請參考博客:告訴你如何使用OLAMI自然語言理解開放平臺API製作自己的智能對話助手

   如果你希望修改語法,添加更多的句子支持,必須將語法文件導入到歐拉蜜NLI系統。

   下載包解壓之後,根目錄找到smarthome.osl,這個就是智能家居支持的語法。然後註冊並登錄歐拉蜜官網,在自己的賬號下找到“應用管理”,併進入NLI系統。如下圖所示。

enter image description here

   接著新增模塊,並將智能家居語法smarthome.osl導入,如下圖所示,點擊“新建”並輸入APP的名字“smarthome”,這個名字必須與smarthome.osl的名字相同,否則導入時會報錯。當然也可以修改,但同時要修改smarthome.ols中APP name相關欄位。

enter image description here

   模塊創建之後,選擇“上傳OSL文件”,然後選擇smarthome.osl並確認即可。上傳成功之後會進入該模塊內部,然後在例句庫中可以看到很多智能家居控制的句子,同時也可以查看Grammar,Rule等。至此OLAMI語法載入完畢。

enter image description here

4.2 獲取應用程式的APP KEY和APP Secreat

    如果希望獲取句子解析後的結果,必須在歐拉蜜平臺中創建自己的應用程式,名字任意,我的叫smarthome
回到“應用管理”界面-----創建應用程式。
   應用程式創建成功之後,還需要把剛纔創建的smarthome 語法模塊添加到應用程式中,一個應用程式可以支持多個語法模塊。

enter image description here

   點擊圖中的“測試”,輸入“打開燈”,就可以看到JSON格式的語義輸出結果了:

enter image description here

   語法模塊配置好之後,點擊應用程式的”查看Key”的按鈕,可以看到平臺分配的APP Key和APP Secret.

4.3 源碼分析
   源碼工程是smarthome_source_code.jar,解壓之後,添加入Eclispe工程,我的開發環境是JDK1.8.
Eclipse Version: Mars.2 Release (4.5.2).
註意:導入工程後,如果出現文字報錯,請將預設編碼修改為UTF-8,方法 Project->Properties->Resource
代碼結構:

enter image description here

替換KEY
   在smarthome packge中的NLIProcess.java中,替換之前創建語法應用時的APP Key和APP Secreat:

   // * Replace your APP KEY with this variable.
    private static String appKey = "*****your APP Key******";       
    // * Replace your APP SECRET with this variable.
    private static String appSecret = "****your APP Secret*****";

程式入口
   程式入口為smarthome packge下的window.java,可以安裝windows Builder插件,直接操作界面。

smarthome packge:

   smarthome包里的源碼包括了APP應用的基本框架,其中:

   window.java為APP入口,即界面。
   NLIProces.java表示處理來自OLAMI NLI介面的語義結果.
   錄音處理為:getSemanticBySpeech()
   文字處理為:getSemanticByText(String inputText)
   windowVariable.java是window.java和NLIProces.java的數據傳遞媒介, window.java中會將NLIProcess.java 需要的控制項傳過去:

 private void initialize() {
            nliwindowdata.setCmdTable(cmd_table);
            nliwindowdata.setcolortext(color_text);
            nliwindowdata.setAnswerText(answer_Text);
            nliwindowdata.setModetext(mode_text);
            nliwindowdata.setTempetext(tempe_text);
            nliwindowdata.setVoicetext(voice_text);
            nliwindowdata.setWindtext(wind_text);
            nliwindowdata.setisRed(isred);
            nliprocess.SetAnswerConfigCom(nliwindowdata);
            ........

   smartHomeApp.java用來處理智能家居APP的語法解析和命令輸出。是NLIProces.java中其中一個小模塊。 你還可以在NLI處理中添加其他處理模塊,比如天氣查詢、詩歌背誦等等。目前NLIprocess.java中僅處理了smarthome相關的NLI輸出:


    private void ProcessNLIResults(NLIResult[] nliResults) {
        // TODO Auto-generated method stub
        String  answer="對不起,你說的話我還不能理解";
        boolean isnormal=false;
        for(int i=0;i<nliResults.length;i++){
            NLIResult tempNlI=nliResults[i];
            //tempNlI.
            //voice_text
            if(tempNlI.getType()!=null&&tempNlI.getType().equals(nliDefinitions.smarthome_app)){
            .......

   APPSlotEntry.java----處理NLI返回的JSON數據中slots相關信息
   OutputMap.java------存放smartHomeApp.java返回給NLIProcess.java的輸出語句和命令。

Smarthome.definition packge

   該包是智能家居處理中用到的定義和設備狀態解析。
Demo中模擬了燈,彩燈,電視,空調,感測器等設備,初始化數據見smartHomeApp.java的InitDeviceData()。

   所有設備信息通過ClientHomeAutomation.java解析並存儲。

    //key is deviceID
   Map<String,HomeAutodeviceObjectNew> addedDeviceMapNew=new       ConcurrentHashMap<String,HomeAutodeviceObjectNew>();

****Smarthome.util****

   DataBuffer.java 和Microphone.java用來進行麥克風錄音;錄音格式按照歐拉蜜平臺的要求,參數為16位深採樣率,16KHZ頻率,單聲道。

源碼為


    public Microphone() {
    
            this.sampleRate = 16000;
            this.bigEndian = false;
            this.signed = true;
    
            this.desiredFormat = new AudioFormat
                    (sampleRate, 16, 1, signed, bigEndian);
    
            //this.closeBetweenUtterances = closeBetweenUtterances;
            this.msecPerRead = 100;
            //this.keepDataReference = keepLastAudio;
            //this.stereoToMono = stereoToMono;
            //this.selectedChannel = selectedChannel;
            //this.selectedMixerIndex = selectedMixerIndex;
            this.audioBufferSize = 9600;
            
            recorderData = new DataBuffer();
        }

   麥克風的錄音開始和停止通過線程監控完成。直到沒有聲音錄入時,錄音線程才會觸發錄音停止機制,因此希望停止錄音時必須通Microphone.stopRecording()關閉錄音,程式才能停止錄音。
   因此錄音時最好設置預設的錄音時長或者通過標誌來停止錄音,並調用Microphone.stopRecording(),我這裡的預設錄音時長為3s.
代碼見NLIProcess.java的

        //最多錄3秒數據,因為採樣頻率是16000點每秒,每個點占兩個位元組。
        // readcount<=0表示錄音結束
        int num=0;
        int srcint=0;
        while(readcount > 0 ) 
        {           
            if(total_count >= 48000*2||needstop)
                break;
    
            num++;
            System.out.println("數據"+(num+1));
            total_count += readcount;
            System.out.println("單數"+readcount);
                 
            speechrecoginzer.appendAudioFramesData(databytes);
       
            readcount = mic.getData(databytes, 0, temsize);
        }
    
        mic.stopRecording();

WaveFileWriter.java可以為錄音數據添加wav頭。

5 和硬體設備對接

 和硬體設備對接,需要串口或者USB等將輸出的ZigBee協議發給協調器,由協調器控制各智能設備做出反應。
 

6 技術交流

QQ群:656580961


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...