Homekit 筆記(一)

簡介

  • 簡介
    1> HomeKit庫是用來溝通和控制家庭自動化配件的,這些家庭自動化配件都支持蘋果的HomeKit Accessory Protocol.
    2> HomeKit應用程序可讓用戶發現兼容配件并配置它們.
    3> 用戶可以創建一些action來控制智能配件(例如恒溫或者光線強弱),對其進行分組,并且可以通過Siri觸發.
    4> HomeKit 對象被存儲在用戶iOS設備的數據庫中,并且通過iCloud還可以同步到其他iOS設備.

啟用Homekit

  • 啟用Homekit
    1> HomeKit應用服務只提供給通過App Store發布的app應用程序.
    2> 在你的Xcode工程中, HomeKit應用程序需要額外的配置,你的app必須有開發證書和代碼簽名才能使用HomeKit。
    3> 啟用HomeKit
    想要使用HomeKit,首先要啟用它。Xcode將會添加HomeKit權限到你的工程授權文件中和會員中心的App ID授權文件中,也會將HomeKit框架添加到你的工程中。HomeKit 需要一個明確的App ID, 這個App ID是為了你完成這些步奏而創建的。
  • 下載Homekit Accessory simulator
    無需為了開發Homekit 應用程序而購買硬件產品。你可以使HomeKit Accessory Simulator來測試HomeKit app和模擬配件設備之間的通信。HomeKit Accessory Simulator不是和Xcode一起發布的

  • 下載HomeKit Accessory Simulator步驟如下:
    1> 在Capabilities面板的HomeKit分區,點擊Download HomeKit Accessory Simulator按鈕。(或者選擇Xcode > Open Developer Tool > More Developer Tools)
    2>在瀏覽器中搜索并且下載"Hardware IO Tools for Xcode ".dmg文件。
    3>在 Finder中雙擊~/Downloads中的.dmg文件。
    4>把HomeKit Accessory Simulator拖拽到/Application文件中。
    之后,你將可以使用HomeKit Accessory Simulator測試你的HomeKit應用程序.

創建Home 布局

  • Home 布局 介紹
    1> HomeKit 允許用戶創建一個或者多個Home布局。每個Home代表一個有網絡設備的住所。
    2> 用戶擁有Home的數據并可通過自己的任何一臺iOS設備進行訪問。
    3> 用戶也可以和客戶共享一個Home,但是客戶的權限會有更多限制。
    4> 被指定為primary home的home默認是Siri指令的對象,并且不能指定home。
    5> 每個Home一般有多個room,并且每個room一般會有多個智能配件。
    6> 在home 中,每個房間是獨立的room,并具有一個有意義的名字,例如“臥室”或者“廚房”,這些名字可以在Siri 命令中使用.
    7> 一個accessory代表實際家庭中的自動化設備,例如車庫開門器。一個sevice 是accessory提供的?種實際服務,例如打開或者關閉車庫,或者車庫上的燈。
    7> 如果你的app 緩存了home布局的信息,那么當其布局發聲改變的時候,app就需要更新這些信息.
    8> 使用HMHomeManager對象可以從HomeKit數據庫獲取HMHome和其他相關的對象。
  • 創建 Home Manager對象
    1> 使用Home Manager對象訪問home、room、配件、服務以及其他HomeKit對象。
    2> 在創建家庭對象管理器(home manager)之后,直接設置它的代理,以便獲取到這些對象(eg:home、room、配件、服務... )之后及時的通知到你。
self.homeManager = [[HMHomeManager alloc] init];
self.homeManager.delegate = self;

當你創建一個home manager對象時,HomeKit就開始從HomeKit數據庫獲取這些homes和相關對象,例如room和accessory對象。當HomeKit正在獲取那些對象時,home manager 的primaryHome屬性是nil,并且homes 屬性是個空數組。

你的app應該處理用戶還沒有完成創建home的情況,但是app應該等待直到HomeKit完成初始化。當獲取對象完成之后,HomeKit 會發送homeManagerDidUpdateHomes:消息給home manager的代理。

注意:當app進入前臺或者在后臺Home manager屬性發生改變時,這個homeManagerDidUpdateHomes:方法就會被調用,詳情請參閱Observing Changes to the Collection of Homes

  • 獲取Primary Home和 Homes集合
通過home manager的primaryHome屬性,可以得到primary home,代碼如下:
HMHome *home = self.homeManager.primaryHome;
  • 使用home manager的homes屬性可以得到用戶的所有home的集合;例如自家主要居所、度假別墅以及辦公室。每個home都對應一個獨立的home對象。
HMHome *home;
 for (home in self.homeManager.homes ){
  ... ...
}
  • 獲取 Home中的所有room
    在一個home中,rooms屬性定義accessories的物理位置。
    用home的rooms屬性可以枚舉home中的所room。
HMHome *home = self.homeManager.primaryHome;
 HMRome *room;
 for (room in home.rooms){
   … ...
 }
  • 獲取Room 中的Accessories
    Accessories 數組屬于home,但是被指定給了home中的room。假如用戶沒有給一個accessory指定room,那么這個accessories被指定一個默認的room ,這個room是方法的返回值。用room的accessories屬性可以枚舉room中所有的accessory。代碼如下:
HMAccessory *accessory;
 for (accessory in room.accessories){
   … ... 
 }

如果你要展示一個個accessory的相關信息或者允許用戶控制它,可設置accessory的代理方法并實現這個代理方法,
一旦你獲取到一個accessory對象,你就可以訪問它的服務和對象

獲取Home中的Accessories屬性使用HMHome類中的accessories的方法,可以直接從Home對象中獲取所有的accessory對象,而不用枚舉home中的所有room對象

創建Homes和添加Accessories

  • HomeKit對象被保存在一個可以共享的HomeKit數據庫里,它可以通過HomeKit框架被多個應英程序訪問。
  • 所有HomeKit調用的方法都是異步寫入的,并且這些方法都包含一個完成處理后的參數。
  • 如果這個方法處理成功了,你的應用將會在完成處理函數里更新本地對象。
  • 應用程序啟動時,HomeKit對象發生改變的并不能收到代理回調?法,只能接受處理完成后的回調函數。

想要觀察其他應用程序啟動時HomeKit對象的變化,請參閱:Observing HomeKit Database Changes。查閱異步消息完成處理后傳過來的錯誤碼的信息,請參閱:HomeKit Constants Reference.

對象命名規則
HomeKit對象的名字,例如home、room和zone對象都可以被Siri識別,這一點已經在文檔中指出。以下幾點是HomeKit對象的命名規則:

  • 對象名字在其命名空間內必須是唯一的。
  • 屬于用戶所有的home名字都在一個命名空間內。
  • 一個home對象及其所包含的對象在另一個命名空間內。
  • 名字只能包含數字、字母、空格以及省略號字符。
  • 名字必須以數字或者字母字符開始。
  • 在名字比較的時候,空格或者省略號是忽略的(例如home1和home 1 同一個名字)。
  • 名字沒有大小寫之分。

(一)創建Homes

  • 在HMHomeManager類中使用addHomeWithName:completionHandler:異步方法可以添加一個home。作為參數傳到那個方法中的home的名字,必須是唯一獨特的,并且是Siri可以識別的home名字。
[self.homeManager addHomeWithName:@"My Home" completionHandler:^(HMHome *home, NSError *error) {
if (error != nil) {
    // Failed to add a home
} else {
    // Successfully added a home
} }];

在else語句中,寫入代碼以更新你應的程序的視圖。

(二)添加房間

  • 在Home中增加一個Room
    使用addRoomWithName:completionHandler:異步方法可以在一個home中添加一個room對象。作為參數傳到那個方法中的room的名字,必須是唯一獨特的,并且是Siri可識別的room名字。
NSString *roomName = @"Living Room";
[home addRoomWithName:roomName completionHandler:^(HMRoom*room, NSError *error) {
if (error != nil) {
    // Failed to add a room to a home
} else {
    // Successfully added a room to a home
} }];

在else語句中,寫入代碼更新應用程序的視圖。

(三)發現配件
Accessories封裝了物理配件的狀態,因此它不能被用戶創建。想要允許用戶給家添加新的配件,我們可以使HMAccessoryBrowser對象找到一個與home沒有關聯的配件。HMAccessoryBrower
對象在后臺搜尋配件,當它找到配件的時候,使用委托來通知你的應用程序。只有在startSearchingForNewAccessories方法調用之后或者stopSearchingForNewAccessories方法調用之前,HMAccessoryBrowserDelegate消息才被發送給代理對象。

  • 發現home中的配件

1> 在你的類接口中添加配件瀏覽器委托協議,并且添加一個配件瀏覽器屬性。代碼如下:

@interface EditHomeViewController ()
@property HMAccessoryBrowser *accessoryBrowser;
@end

2> 創建配件瀏覽器對象,并設置它的代理

self.accessoryBrowser = [[HMAccessoryBrowser alloc] init];
self.accessoryBrowser.delegate = self;

3> 開始搜尋配件

[self.accessoryBrowser startSearchingForNewAccessories];

4> 將找到的配件添加到你的收藏里

- (void)accessoryBrowser:(HMAccessoryBrowser *)browser didFindNewAccessory:(HMAccessory *)accessory {
    // Update the UI per the new accessory; for example,reload a picker view.
    [self.accessoryPicker reloadAllComponents];
}

5> 停止搜尋配件

如果一個視圖控制器正在開始搜尋配件,那么可以通過重寫
-(void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear: animated];
  [self.accessoryBrowser stopSearchingForNewAccessories];
}

注意: 在WiFi網絡環境下,為了安全地獲取新的并且能夠被HomeKit發現的無線配件,請參閱External Accessory Framework Reference.

(四)為Home和room添加配件(Accessory)
配件歸屬于home,并且它可以被隨意添加到home中的任意一個room中。使用addAccessory:completionHandler:這個異步方法可以在home中添加配件。這個配件的名字作為一個參數傳遞到上述異步方法中,并且這個名字在配件所屬的home中必須是唯一的。
使用assignAccessory:toRoom:completionHandler: 這個異步方法可以給home中
的room添加配件。配件默認的room是roomForEntireHome這個方法返回值room。下面的代碼演示了如何給home和room添加配件:

// Add an accesory to a home and a room
// 1. Get the home and room objects for the completion handlers.

__block HMHome *home = self.home;
__block HMRoom *room = roomInHome;

// 2. Add the accessory to the home
[home addAccessory:accessory completionHandler:^(NSError *error) {
    if (error) {
        // Failed to add accessory to home
     } else {
        if (accessory.room != room) {
            // 3. If successfully, add the accessory to the room
            [home assignAccessory:accessory toRoom:room completionHandler:^(NSError *error) {
                if (error) {
                // Failed to add accessory to room
                } 
            }];
        } 
    }
}];

配件可提供一項或者多項服務,這些服務的特性是由制造商定義。想了解配件的服務和特性目的,請參閱 Accessing Services and Characteristics.

  • 更改配件名稱
    使用updateName:completionHandler:異步方法可以改變配件的名稱,代碼如下:
[accessory updateName:@"Kid's Night Light" completionHandler:^(NSError *error) {
    if (error) {
        // Failed to change the name
    } else {
        // Successfully changed the name
    }
}];
  • 為Homes和Room添加Bridge(橋接口)
1> 橋接口是配件中的一個特殊對象,它允許你和其他配件交流,但是不允許你直接和HomeKit交流。例如一個橋接口可以是控制多個燈
的樞紐,它使用的是自己的通信協議,而不是HomeKit配件通信協議。
2> 想要給home添加多個橋接口 ,你可以按照Adding Accessories to Homes and Rooms中所描述的步驟,添加
任何類型的配件到home中。
3> 當你給home添加一個橋接口時,在橋接口底層的配件也會被添加到home中。 
4> 正如Observing HomeKit Database Changes中所描述的那樣,每次更改通知設計模,home的代理不會接收到橋接口的home:didAddAccessory: 
代理消息,而是接收一個有關于配件的home:didAddAccessory:代理消息。

在home中,要把橋接口后的配件和任何類型的配件看成一樣的--例如,把它們加入配件列表的配置表中。相反的是,當你給room增添一個橋接口時,這個橋接口底層的配件并不會自動地添加到room中,原因是橋接口和它的的配件可以位于到不同的room中。

  • 創建分區
    分區 HMZone 是任意可選的房間(rooms)分組;例如樓上、樓下或者臥室。房間可以被添加到一個或者多個區域。
    可使用addZoneWithName:completionHandler: 異步方法創建分區。所創建的作為參數傳遞到這個方法中分區的名稱,在home中必須是唯一的,并且應該能被Siri識別。代碼如下:
__block HMHome *home = self.home;
NSString *zoneName = @"Upstairs";
[home addZoneWithName:zoneName completionHandler:^(HMZone*zone, NSError *error){
    if (error) {
        // Failed to create zone
    } else {
        // Successfully created zone, now add the rooms
    }
}];

可使用addRoom:completionHandler:異步方法給分區添加一個room,代碼如下:

__block HMRoom *room = roomInHome;
[zone addRoom:room completionHandler:^(NSError *error) {
    if (error) {
        // Failed to add room to zone
    } else {
        // Successfully added room to zone
    }
 }];

第五部分:觀察HomeKit數據庫的變化

每個Home都有一個HomeKit數據庫。如下圖所示,HomeKit數據庫會安全地和home授權的用戶的iOS設備以及潛在的客人的iOS設備進行同步。為了給用戶展示當前最新的數據,你的應用需要觀察HomeKit數據庫的變化。


homekit_database.png

(一)Homekit代理方法

  • HomKit使用代理設計模式delegation design pattern來通知應用程序HomeKit對象的改變。
1> 一般來講,如果你的應用程序調用了一個帶有完成處理參數的HomeKit方法,并且這個方法被成功調用了,那么相關聯的代理消息
就會被發送給其他HomeKit應用,無論這些應用是安裝在同一臺iOS設備上還是遠程iOS設備上。
2> 這些應用甚至可以運行在客人的iOS設備上。如果你的應用發起了數據改變,但是代理消息并沒有發送到你的應用,
那么添加代碼到完成處理方法和相關聯的代理方法中來刷新數據和更新視圖就成為必須了。
3> 如果home布局發生了顯著變化,那么就重新加載關于這個home的所有信息。在完成程序處理的情況下,請在更新應用之前檢查那個方法是否成功。
4> Homkit也會調用代理方法來通知你的應用程序home網絡狀態的改變。

例如,下圖演示了使用代理方法的過程:響應用戶的操作,你的應用程序調用了addRoomWithName:completionHandler:方法,并且沒有錯誤發生,完成處理程序應當更新home的所有視圖。如果成功了,homeKit將會發送home:didAddRoom:消息給其他應用中homes的代理。因此,你實現的這個home:didAddRoom:方法也應該更新home的所有視圖。

homedidAddRoom.png

應用程序只有在前臺運行的時候才能接受代理消息。當你的應用在后臺時,HomeKit數據庫的改變并不會成批處理。也就是說,如果你的應用在后臺,當其他的應用成功地添加一個room到home中的時候,你的應用程序并不會接收到home:didAddRoom: 消息。當你的應用程序到前臺運行時,你的應用程序將會接收到homeManagerDidUpdateHomes:消息,這個消息是表示你的應用程序要重新加載所有的數據。

(二)觀察Homes集合的改變

  • 設置home manager的代理并且實現HMHomeManagerDelegate協議,當primary home或者home集合發生改變時,可以接收代理消息。

  • 所有的應用都需要實現homeManagerDidUpdateHomes:方法,這個方法在完成最初獲取homes之后被調用。對新建的home manager來說,在這個方法被調用之前,primaryHome 屬性的值是nil,homes數組是空的數組。

  • 當應用程序開始在前臺運行時也會調用 homeManagerDidUpdateHomes: 方法,當其在后臺運行時數據發生改變。該homeManagerDidUpdateHomes:方法會重新加載與homes相關聯的所有數據。

(三)觀察homes的變化

  • 1>在你的類接口中添加HMHomeManagerDelegate代理和homeManager屬性。代碼如下:
@interface AppDelegate () 
@property (strong, nonatomic) HMHomeManager *homeManager;
@end
  • 2>創建home manager對象并設置其代理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    self.homeManager = [[HMHomeManager alloc] init];
    self.homeManager.delegate = self;
    return YES;
}
  • 3> 實現homes發生改變時調用的代理方法。例如:如果多個視圖控制器展示了homes相關信息,你可以發布一個更改通知去更新所有視圖。
// 代理監聽事件
- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {
    // Send a notification to the other objects
    [[NSNotificationCenter defaultCenter]postNotificationName:@"UpdateHomesNotification" object:self];
}
// 通知分發具體任務
- (void)homeManagerDidUpdatePrimaryHome:(HMHomeManager*)manager {
    // Send a notification to the other objects
    [[NSNotificationCenter defaultCenter] postNotificationName:@"UpdatePrimaryHomeNotification" object:self];
}
  • 4> 視圖控制器注冊更改通知并且執行適當的操作。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateHomes:) name:@"UpdateHomesNotification" object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePrimaryHome:) name:@"UpdatePrimaryHomeNotification" object:nil];

(四)觀察個別home的變化
展示home信息的視圖控制器應該成為home對象的代理,并且當home發生改變時更新視圖控制器的視圖。

  • 觀察特定home對象的改變

1> 在類接口中添加home代理協議。

@interface HomeViewController () @end

2> 設置配件代理

home.delegate = self;

3> 實現HMHomeDelegate]協議
例如:實現home:didAddAccessory:和home:didRemoveAccessory: 方法來更新展示配件的視圖。用HMAccessory類的room屬性可以獲得配件所屬的room。(對配件來說,默認的room是roomForEntireHome這個方法的返回值。

Bridge Note:當你為home添加橋接口時,橋接口底層的配件會自動被添加到home中。你的代理會接收到橋接口后每個配件的 home:didAddAccessory:消息,但是你的代理不會接收到橋接口的home:didAddAccessory:消息。

(五)觀察個別home的變化
配件的狀態可以在任何時間發生變化。配件可能不能被獲得,可以被移除,或者被關閉。請更新用戶界面以反映配件狀態的更改,尤其是如果你的app允許用戶控制配件時。

這以下步驟中,我們假設你已經從HomeKit數據庫中檢索到了配件對象,正如Getting the Accessories in a Room 中描述的那樣。

(五.一)觀察個別home的變化

  • 1> 在類接口中添加配件代理協議。
@interface AccessoryViewController ()  
@end
  • 2> 設置配件的代理
accessory.delegate = self;
  • 3> 實現 HMAccessoryDelegate 協議
    比如,執行accessoryDidUpdateReachability:方法以啟用或者禁用配件控制。
- (void)accessoryDidUpdateReachability:(HMAccessory *)accessory {
    if (accessory.reachable == YES) {
       // Can communicate with the accessory
    } else {
       // The accessory is out of range, turned off, etc
    }
}

如果你展示了配件的服務狀態和特性,那么請執行以下代理方法來相應地更新其視圖:

accessoryDidUpdateServices
accessory:service:didUpdateValueForCharacteristic:

六:訪問服務和特性

服務HMService代表了一個配件(accessory)的某個功能和一些具有可讀寫的特性HMCharacteristic。
一個配件可以擁有多項服務,一個服務也可以有很多特性。比如一個車庫開門器可能擁有一個照明和開關的服務。照明服務可能擁有打開/關閉和調節亮度的特性。

用戶不能制造智能家電配件和它們的服務-配件制造商會制造配件和它們的服務-但是用戶可以改變服務的特性。一些擁有可讀寫屬性的特性代表著某種物理狀態,比如,一個恒溫器中的當前溫度就是一個只可讀的值,但是目標溫度又是可讀寫的。蘋果預先定義了一些服務和特性的名稱,以便讓Siri能夠識別它們。

(一) 獲得配件的服務和屬性
在依照Getting the Accessroties in a Room中描述,你創建了一個配件對象之后,你可以獲得配件的服務和特性。當然你也可以直接從home中按照類型獲得不同的服務。

重要:不要暴露匿名服務-比如固件升級服務-給用戶

  • 通過HMAccessory屬性,我們可以獲得一個配件的服務。
NSArray *services = accessroy.services;
  • 要獲得一個home當中配件提供的特定服務,使用HMHome類對象的servicesWithTypes:方法。
// Get all lights and thermostats in a home
NSArray *lightServices = [home servicesWithTypes:[HMServicesTypeLightbulb]];
NSArray *thermostatServices = [home servicesWithTypes:[HMServicesTypeThermostat]]
  • 使用HMServices類對象的name屬性來獲得服務的名稱
NSString *name = service.name;
  • 要獲得一個服務的特性,請使用characteristics屬性。
NSArray *characteristics = service.characteristics
  • 使用servicesType屬性來獲得服務的類型
NSString *serviceType = service.serviceType;

(二)改變服務名稱

  • 使用updateName:completionHandler:異步方法來改變服務名稱。傳入此方法的服務名稱參數必須在一個home當中是唯一的,并且服務名可被Siri識別。
[service updateName:@"Garage 1 Opener" completionHandler:^(NSError *error) {
    if (error) {
        // Failed to change the name
    } else {
        // Successfully changed the name
    }
}];
  • 訪問特性的值
    特性代表了一個服務的一個參數,它要么是只讀、可讀寫或者只寫。它提供了這個參數可能的值的信息,比如,一個布爾或者一個范圍值。恒溫器中的溫度就是只讀的,而目標溫度又是可讀寫的。一個執行某個任務的命令且不要求任何返回-比如播放一段聲音或者閃爍一下燈光來確認某個配件-可能就是只寫的。

蘋果定義了一些特性的類型,并能被Siri識別:

亮度(Brightness)
最近溫度(Current temperature)
鎖的狀態(Lock state)
電源的狀態(Power state)
目標狀態(Target state)
目標溫度(Target temperature)

  • 在你獲得了一個HMService對象之后,如 Getting Services and Their Properties所描述的,你可以獲得每個服務的特性的值。因為這些值是從配件中獲得的,這些讀寫的方法都是異步的,并可以傳入一個完成回調的block。
使用readValueWithCompletionHandler:異步方法來讀取一個特性的值。

[characteristic readValueWithCompletionHandler:^(NSError *error) {
    if (error == nil) {
        // Successfully read the value
        id value = characteristic.value;
    }
    else {
        // Unable to read the value
    } 
}];

在if語句塊中,加入你的代碼以更新app的視圖。

  • 使用writeValue:completionHandler:異步方法來向一個特性寫入值。
[self.characteristic writeValue:@42 withCompletionHandler:^(NSError *error) {
    if (error == nil) {
       // Successfully wrote the value
    }
    else {
       // Unable to write the value
    }
 }];

不要以為函數調用完成就意味著寫入成功,實際上只有在當完成回調執行并沒有錯誤產生時才表示寫入成功。比如,直到一個開關的特性改變之前都不要改變這個開關的狀態。在if語句塊中,加入你的代碼,以更新app的視圖。
另外,在別的app更新了特性的值時也需要更新視圖,在Observing Changes to Accessories中有描述

(三)創建服務組
一個服務組[HMServiceGroup提供了控制不同配件的任意數量服務的快捷方式-比如,當用戶離開家之后控制家中的某些燈。

serviceGroup.png
  • 在你創建了一個HMHome對象之后,如Getting the Primary Home and Collection of Homes中描述,你也就在這個家中創建一個服務組。
    為了創建一個服務組,我們使用HMHome類對象的addServiceGroupWithName:completionHandler:方法。方法中參數服務組的名稱必須在此家中唯一,并可以被Siri識別。
[self.home addServiceGroupWithName:@"Away Lights" completionHandler:^(HMServiceGroup *serviceGroup, NSError *error) {
    if (error == nil) {
       // Successfully created the service group
    } else {
       // Unable to create the service group
    }
}];
  • 我們使用HMServiceGroup類對象的addService:completionHandler:方法來向服務組中添加一個服務。服務可以在一個或多個服務組中。
[serviceGroup addService:service completionHandler:^(NSError *error) {
    if (error == nil) {
       // Successfully added service to service group
    }else{
       // Unable to add the service to the service group
    }
}];
  • 通過HMHome類對象的serviceGroups屬性,來獲得這個家的所有服務組。
NSArray *serviceGroups = self.home.serviceGroups;
  • 通過HMServiceGroup類對象的accessory屬性,我們獲得服務所對應的智能電器。
HMAccessory *accessory = service.accessory;

和配件類似,代理方法在別的app改變服務組時也會被調用。如果你的app使用了服務組,請閱讀HMHomeDelegate Protocol Reference文檔,獲悉你應該實現哪些方法以觀察這些變化。

七: 測試

八:創建動作集(Action Sets) 和 觸發器(Triggers)

一個動作集合HMActionSet和觸發器HMTimerTrigger允許你同時控制多個智能電器。比如,一個動作集合可能會在用戶上床休息之前執行一組動作HMAction。一個寫動作向一個特性寫入了值。動作集合中的動作是以不確定的順序執行的。一個觸發器會在一個特定的時間出發一個動作集并可以重復執行。每一個動作集合在一個家庭中都有唯一的名稱并可被Siri識別。

(一) 創建寫入動作

寫入動作會向一個服務的特性寫入值并被加入到動作集合中去。HMAction類是HMCharacteristicWriteAction具體類的抽象基類。一個動作有一個相關聯的特性對象,你可以通過Accessing Services and Characteristics中描述的來獲取相關的服務和特性,然后創建這個HMCharacteristicWriteAction。

  • 為了創建一個動作,我們使用HMCharacteristicWriteAction類中的initWithCharacteristic:targetValue:方法。
HMCharacteristicWriteAction *action = [[HMCharacteristicWriteAction alloc] 
initWithCharacteristic:characteristic 
targetValue:value];

在你的代碼中,你使用對應的特性的期望來替換value參數,并使用對應的HMCharacteristic對象來替換characteristic參數。

(二)創建并執行動作集
一個動作集就是一個共同執行的動作的集合。比如一個夜間動作集合可能包含關閉電燈,調低恒溫水平和鎖上房門。

  • 創建一個動作集我們使用addActionSetWithName:completionHandler:異步方法。
[self.home addActionSetWithName:@"NightTime" completionHandler:^(HMActionSet *actionSet, NSError *error) {
    if (error == nil) {
        // 成功添加了一個動作集
    } else {
        // 添加一個動作集失敗
    }
}];
  • 添加一個動作到動作集,我們使用addAction:completionHandler:異步方法。
[actionSet addAction:action completionHandler:^(NSError *error) {
    if (error == nil) {
        // 成功添加了一個動作到動作集
    } else {
    // 添加一個動作到動作集失敗
    }
}];
  • 移除一個動作,可使用removeAction:completionHandler:方法。

  • 想要執行一個動作集,可使用HMHome類的executeActionSet:completionHandler:方法。

比如,用戶希望控制所有的節日彩燈。我們就創建一個動作集來打開所有的節日彩燈,另外一個動作集來關閉所有的節日彩燈。為了打開所有的節日彩燈,發送executeActionSet:completionHandler:消息給home對象,并傳遞"打開節日彩燈"動作集。

九:創建并開啟觸發器

  • 觸發器會執行一個或多個動作集。iOS會在后臺管理和運行你的觸發器。HMTrigger 類是HMTimerTrigger具體類的抽象類。
    當你創建一個定時觸發器時,你需要指定觸發時間和觸發的周期。創建并開啟一個定時觸發器需要多個步驟來完成。

遵循下面幾步來創建并啟動一個定時觸發器

  • 1> 創建一個定時觸發器
self.trigger = [[HMTimerTrigger alloc] initWithName:name fireDate:fireDate timeZone:niL recurrence:nil recurrenceCalendar:nil];

觸發時間必須設置在將來的某個時刻,第二個參數必須為0.如果你設置了一個周期,周期的最小值是5分鐘,最大值是5周。關于如何使用NSDateComponents和NSCalendar來設置周期,請閱讀Date and Time Programming Guide

  • 2> 添加一個動作集到觸發器。
使用HMTrigger基類方法addActionSet:completionHandler:,來添加一個動作集到觸發器。
  • 3> 添加一個觸發器到家庭。
使用HMHome類中的addTrigger:completionHandler:方法來添加一個觸發器到家庭。
  • 4> 啟動觸發器
    新創建的觸發器默認是未啟動的。需要使用enable:complationHandler:方法啟動觸發器。
    一個定時觸發器被啟動后,會周期性的運行它的動作集。

十: 用戶管理

創建home的用戶是該home的管理員,可以執行所有操作,包括添加一個客人用戶到home。任何管理員添加到這個home的用戶(HMUser)都有一個有限的權限。客人不能更改家庭的布局,但是可以執行下面的動作:

  • 識別智能電器
  • 讀寫特性
  • 觀察特性值變化
  • 執行動作集

比如,一個家庭的戶主可以創建一個home布局并向其中添加家庭成員。每個家庭成員必須擁有一個iOS設備和Apple ID以及相關的iCloud賬戶。iCloud需要個人輸入的Apple ID和戶主提供的Apple ID相吻合,以便讓他們訪問這個home。考慮到隱私問題,Apple ID對你的App是不可見的。

管理員需要遵從以下步驟來添加一個客人到home中:

  • 1> 管理員調用一個動作將客人添加到home中。
  • 2> 你的App調用addUserWithCompletionHandler:異步方法。
  • 3> HomeKit展示一個對話框,要求輸入客人的Apple ID。
  • 4> 用戶輸入客人的Apple ID。
  • 5> 在完成回調中返回一個新的用戶。
  • 6> 你的App展示客人的名字。

添加一個客人到home,需要在客人的iOS設備上做以下操作:

  • 1> 用戶在iCloud偏好設置中輸入iCloud憑證(Apple ID和密碼)。
  • 2> 用戶啟動你的App。
  • 3> 你的App通過home manager object獲得一個home集合。
  • 4> 如果iCloud的憑證和管理員輸入的Apple ID相同,那么管理員的home將會出現在homes屬性中。

客人執行的操作可能會失敗。如果一個異步方法中出現HMErrorCodeInsufficientPrivileges錯誤碼的話,這就意味著用戶沒有足夠的權限來執行動作-也許這個用戶只是客人,而不是管理員。

添加和移除用戶

  • 添加一個客人用戶到home,請使用addUserWithCompletionHandler:異步方法。
[self.home addUserWithCompletionHandler:^(HMUser *user, NSError *error) {
    if (error == nil) {
        // Successfully added a user
    }
    else {
       // Unable to add a user
    }
 }];
  • 想要移除home中的用戶,請使用HMHome類的removeUser:completionHandler:方法。

  • 通過實現HMHomeDelegate協議中的home:didAddUser:和home:didRemoveUser:協議方法檢查新添加和移除的用戶并更新視圖。

獲得用戶名
出于隱私的考慮,你的app對用戶名只有讀得權限,并不能讀寫用戶的Apple ID。使用HMHome對象的users屬性來獲取用戶。使用HMUser類的name屬性來獲取用戶名。

Homekit 筆記(二) http://www.lxweimin.com/p/dc3fdbef74a1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容