使用Olami SDK 語音控制一個支持HomeKit的智能家居的iOS程序

一直在尋找類似的中文解析API,這篇文章不錯


前言

HomeKit是蘋果發佈的智能家居平臺。通過HomeKit組件,用戶可以通過iphone、iPad和ipod Touch來控制智能燈泡,風扇、空調等支持HomeKit的智能家居,尤其是可以通過Siri進行語音控制。 
但是通過Siri進行語音控制有個很大的問題,就是Siri支持的語料無法進行自由的擴展,沒辦法添加更多的說法。而Olami SDK則可以通過OSL(OLAMI 語法描述語言 OLAMI Syntax Language,簡稱:OSL)自由的進行擴展,對智能對話的能力擴展變得非常容易通過。Olami的服務器對輸入的語料進行語義的解析,獲得想要的控制結果。這樣就可以自己對語料和說法進行擴展,豐富了操作的功能。

準備工作

  • HomeKit關於智能設備的一些基本概念和模擬器的安裝

    由於市面上支持HomeKit的設備不多也比較昂貴,蘋果貼心的提供了一個HomeKit模擬器來幫助程序員進行HomeKit設備的開發。這個Demo是模擬一個智能空調,功能是通過語音控制空調的開關和調節溫度。

    HomeKit模擬器默認不是安裝的,要去下載安裝 
    在Taget->Capabilities->HomeKit一項中可以下載,見下圖

這裏寫圖片描述

安裝好以後,就可以打開使用了。見下圖 
這裏寫圖片描述

在Homekit中有幾個概念,在這裏簡單的介紹一下APP裏用到的,網上有比較詳細的介紹,也可以參考我轉載的這篇博文: 
http://blog.csdn.net/dfman1978/article/details/72179458 
HomeKit允許用戶添加多個home,但是使用的時候只能有一個home,稱爲primaryHome。每個Home可以有多個room.智能設備稱爲Accessory屬於home,但是每個Accessory可以配個一個room。如果沒有指定room,則默認分配給roomForEntireHome返回的默認room.每個Accessory可以有多個Service,每個Service可以有多個特性(HMCharacteristic)。有的特性是隻讀的,例如空調當前的溫度;有的特性是可讀可寫的,例如空調的開關。APP就是通過控制這些特性的值來控制智能設備的。

在程序中添加了一個Accessory,名稱起爲空調。然後給它添加了兩個Service:一個是Switch 開關,一個是Temperature 控制空調的溫度。通過APP,可是實現空調的開關和溫度的調節。

  • Olami 智能設備的語法規則的編寫和配置 
    用戶的說的話, APP怎麼知道說的是什麼意思,怎麼去理解呢?這就涉及到了OSL語法描述語言。想要使用Olami平臺提供的語音和語義理解API,首先要根據OLAMI 語法描述語言(OLAMI Syntax Language,簡稱:OSL)的規則編寫一套語法。OSL的簡介如下網址有詳細的介紹https://cn.olami.ai/wiki/?mp=osl&content=osl1.html 
    通過Olami平臺提供的NLI 自然語言語義互動系統,可以學習到如何爲自己應用的業務編寫一套語法規則。

自然語言語義互動(Natural Language Interaction, 簡稱:NLI)管理系統是一套在線語義解析管理工具,NLI 系統採用 OLAMI 語法描述語言(OLAMI Syntax Language,簡稱:OSL)取代複雜的編碼編程,讓即便沒有軟件研發背景的使用者也能輕鬆快速的維護包含語義擴展及答案的智能對話流。

在如下網址可以瞭解到更加詳細的內容 
https://cn.olami.ai/wiki/?mp=nli&content=nli1.html 
方便的是Olami平臺已經對很多領域方面的提供了一些寫好的語法規則,這些在Olami中稱爲模塊。其中關於智能設備已經寫好,下面就一步一步配置一下。 
首先要去Olami的平臺註冊一下,註冊後進入到這個界面

這裏寫圖片描述

點擊“創建應用”轉到下面這個頁面

這裏寫圖片描述

填寫 應用名稱,應用描述,應用介紹以後,就可以創建了。回到上一個頁面,就可以看到創建的應用了。

點擊”進入NLI系統”就可以進入模塊頁面 
這裏寫圖片描述

在官網已經內置了很多領域的grammar.在模塊頁面大家點擊“導入”按鈕,查看已有領域的模塊 
這裏寫圖片描述

選擇一個要使用的,例如我要導入”smarthome”這個模塊,先選擇它,點擊“導入” 按鈕 
這裏寫圖片描述

然後進入 smarthome模塊,就可以看到例句了 
這裏寫圖片描述

但是這個時候還是不能使用,需要先進行發佈。點擊頁面上方的”發佈”按鈕,進入發佈頁面 
這裏寫圖片描述

點擊“發佈”按鈕,發佈成功 
這裏寫圖片描述

最後還要回到“我的應用”界面,點擊”配置NLI模塊”按鈕,讓自己創建的應用和模塊關聯起來 
這裏寫圖片描述

這樣smarthome的語法文件就配置好了,就可以使用了。

代碼的實現

1.獲取home和Accessory的對象

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.accessories = [NSMutableArray array];

    if (self.homeManager && self.homeManager.primaryHome) {
        for (HMAccessory *accessory in self.homeManager.primaryHome.accessories) {
            [self.accessories insertObject:accessory atIndex:0];
            accessory.delegate = self;
            [self.tableView reloadData];
        }
    }

    if (_currentHome) {
        _currentHomeLabel.text = [NSString stringWithFormat:@"當前Home:%@", _currentHome.name];
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在ViewWillAppear的時候來獲取當前Home的對象和名字,還有Accessory的對象,並保存起來,用一個tableView來顯示下圖是程序剛啓動的時候的界面,這個時候因爲沒有添加Home,所以什麼都沒有 
這裏寫圖片描述

點擊“添加Home”按鈕彈出一個對話框,可以填入一個Home的名稱。對應的代碼

- (IBAction)addHomeBtnClicked:(id)sender
  • 1
  • 1

下一步就是添加Accessory,在代碼裏沒有做這一步。是通過iOS提供的“家庭”APP來添加智能空調的。 
點擊“家庭”App,彈出頁面 
這裏寫圖片描述

點擊“開始使用”,彈出 
這裏寫圖片描述

點擊“添加配件”,App會自動搜索剛纔在模擬器添加的那個空調,按照提示一步一步添加,最後顯示空調的兩個Service:Switch和Temperature 
這裏寫圖片描述

在回到APP,這個時候APP,就會顯示出搜索到的Accessory:空調 
這裏寫圖片描述

點擊“空調”,進入語音控制頁面 
這裏寫圖片描述 
在這個頁面中,上面的TableView顯示了空調的一些屬性。 
下面的TextView用來顯示ASR的一些結果 
圓形按鈕用來錄音

2..去網址https://cn.olami.ai/wiki/?mp=sdk&content=sdk_and_sample.html下載Olami SDK.包括兩個文件,其中的一個是Olami的靜態函數庫,一個是其頭文件 
第一步是初始化Olami的語音識別對象,並設置代理

olamiRecognizer= [[OlamiRecognizer alloc] init];
olamiRecognizer.delegate = self;
  • 1
  • 2
  • 1
  • 2

3.調用setAuthorization函數進行授權

[olamiRecognizer setAuthorization:@"d13bbcbef2a4460dbf19ced850eb5d83"
    api:@"asr" appSecret:@"3b08b349c0924a79869153bea334dd86" cusid:OLACUSID];
  • 1
  • 2
  • 1
  • 2

這個函數的參數的說明在OlamiRecognizer中有說明,也可以去在線API說明去查看 
https://cn.olami.ai/wiki/?mp=sdk&content=sdk/ios/reference.html

參數就是剛纔創建應用的時候獲得的。

4.設置語系

[olamiRecognizer setLocalization:LANGUAGE_SIMPLIFIED_CHINESE];
  • 1
  • 2
  • 1
  • 2

在進行錄音之前必須要先進行設置,否則會得不到結果。目前只支持簡體中文(LANGUAGE_SIMPLIFIED_CHINESE)

4.開始錄音 
調用 start()接口開始進行錄音

[olamiRecognizer start];
  • 1
  • 1

5.得到錄音的文字和語義,並對其進行處理 
通過調用stop()函數或者自動停止,都會獲得錄音的文字和對其進行的語義分析的結果 
實現OlamiRecognizerDelegate onResult函數可以獲得結果,其結果以一個json字符串的形式回調過來,對這個字符串進行解析,就可以獲得想要的數字。例如對着話筒說”打開空調”,得到的結果如下

{
    "data": {
        "asr": {
            "result": "打開空調",
            "speech_status": 0,
            "final": true,
            "status": 0
        },
        "nli": [
            {
                "desc_obj": {
                    "status": 0
                },
                "semantic": [
                    {
                        "app": "smarthome",
                        "input": "打開空調",
                        "slots": [
                            {
                                "name": "device",
                                "value": "空調"
                            }
                        ],
                        "modifier": [
                            "open"
                        ],
                        "customer": "58df685e84ae11f0bb7b4893"
                    }
                ],
                "type": "smarthome"
            }
        ]
    },
    "status": "ok"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

這個是根據OSL語法描述語言定義的一套規則,返回的結果。這個結果的說明在 https://cn.olami.ai/wiki/?mp=api_nlu&content=api_nlu3.html 這個網址上有說明。 
6.獲得所有Accessory的對象

for(HMService *service in _accessory.services) {
        [_serviceDic setObject:service forKey:service.name];
        NSLog(@"service.name is %@",service.name);
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

保存在一個Dictionary中,服務的名稱是key,對象的指針是Value

7.onResult 函數的說明 
在整個程序中,最主要的一個函數就是onResult函數,這個函數就是對傳過來的結果進行處理。在這個函數中,調用了三個函數,分別來處理josn格式中的三個比較重要的節點

- (void)processASR:(NSDictionary*)asrDic 
  • 1
  • 1

這個用來處理ASR節點,獲得語音識別的結果,如果沒有結果,則彈出一個對話框進行提示

- (void)processSemantic:(NSDictionary*)semanticDic
  • 1
  • 1

這個用來處理Semantic節點,這個節點中包含了slot的值和modifier的值。OSL 語法描述語言中的 slot 可理解爲語義中的變量,用於傳遞、提取信息,是代碼處理的數據的來源。對於本程序來說,就是進行控制空調的各種動作,例如開,關。還有就是調節的溫度值。關於slot的值可以參考 https://cn.olami.ai/wiki/?mp=osl&content=osl_slot.html,這裏有詳細說明

- (void)processModify:(NSString*) str 
  • 1
  • 1

這個用來處理語音和語義的結果。這個函數主要是處理json字符串中的modifier節點。modifier 語法描述規則是 OSL 語法描述語言中,除了 slot 以外的另一種內置的信息傳遞機制,一般用來表示語義目的,也可以理解爲對於語義的一種註釋方式,以便讓應用程序的開發者得知 grammar 所代表的相應意圖。詳細說明參考 
https://cn.olami.ai/wiki/?mp=osl&content=osl_regex.html#11,通過modifier,我們才能知道程序的意圖是什麼?例如是想打開、關閉空調。還是調節溫度

在代碼中我們處理了三個modifier:”open”、”close” 和”control_temperature”.然後根據slot的值進行進行進一步處理。 
拿其中處理“關閉”空調的動作來做說明

if ([str isEqualToString:@"close"]){//關閉空調
        HMService *tmpService = _serviceDic[@"Switch"];
        HMCharacteristic *characteristic = tmpService.characteristics[1];

        if ([characteristic.characteristicType isEqualToString:HMCharacteristicTypeTargetLockMechanismState] ||
            [characteristic.characteristicType isEqualToString:HMCharacteristicTypePowerState] ||
            [characteristic.characteristicType isEqualToString:HMCharacteristicTypeObstructionDetected]) {

            [characteristic writeValue:@NO completionHandler:^(NSError *error){

                if(error == nil) {
                    dispatch_async(dispatch_get_main_queue(), ^ {
                        _asrTextView.text = @"空調已關閉";
                    });
                } else {
                    NSLog(@"error in writing characterstic: %@", error);
                    _asrTextView.text = @"空調關閉失敗,請重試!";
                }
            }];

        }


    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

如果modifier等於”close”,那麼說明這是一個Switch服務的屬性。通過“Switch”獲得Service的指針,然後獲得Switch的屬性。然後通過

- (void)writeValue:(nullable id)value completionHandler:(void (^)(NSError * __nullable error))completion;
  • 1
  • 2
  • 1
  • 2

函數來修改這個屬性的值。因爲是關閉空調,所以直接寫入@NO就可以了 
因爲這個函數是異步返回的,返回的時候不一定操作成功,所以要對返回結果進行一下處理。

代碼下載

代碼可以到GitHub上下載 
https://github.com/lym-ay/SmartHome

Olami SDK 相關開發資源

另外這裏還有兩篇anroid上使用Olami SDK開發程序的文章

這個是一個聽書的程序 
http://blog.csdn.net/ls0609/article/details/71519203

這個是一個關於天氣的程序 
http://blog.csdn.net/zhangxy0605/article/details/71601604

3












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章