簡介
- 簡介
1> HomeKit庫是用來溝通和控制家庭自動(dòng)化配件的疯攒,這些家庭自動(dòng)化配件都支持蘋果的HomeKit Accessory Protocol.
2> HomeKit應(yīng)用程序可讓用戶發(fā)現(xiàn)兼容配件并配置它們.
3> 用戶可以創(chuàng)建一些action來控制智能配件(例如恒溫或者光線強(qiáng)弱)嗦随,對(duì)其進(jìn)行分組,并且可以通過Siri觸發(fā).
4> HomeKit 對(duì)象被存儲(chǔ)在用戶iOS設(shè)備的數(shù)據(jù)庫中敬尺,并且通過iCloud還可以同步到其他iOS設(shè)備.
啟用Homekit
- 啟用Homekit
1> HomeKit應(yīng)用服務(wù)只提供給通過App Store發(fā)布的app應(yīng)用程序.
2> 在你的Xcode工程中枚尼, HomeKit應(yīng)用程序需要額外的配置,你的app必須有開發(fā)證書和代碼簽名才能使用HomeKit砂吞。
3> 啟用HomeKit
想要使用HomeKit署恍,首先要啟用它。Xcode將會(huì)添加HomeKit權(quán)限到你的工程授權(quán)文件中和會(huì)員中心的App ID授權(quán)文件中蜻直,也會(huì)將HomeKit框架添加到你的工程中盯质。HomeKit 需要一個(gè)明確的App ID, 這個(gè)App ID是為了你完成這些步奏而創(chuàng)建的。
下載Homekit Accessory simulator
無需為了開發(fā)Homekit 應(yīng)用程序而購買硬件產(chǎn)品概而。你可以使HomeKit Accessory Simulator來測試HomeKit app和模擬配件設(shè)備之間的通信呼巷。HomeKit Accessory Simulator不是和Xcode一起發(fā)布的下載HomeKit Accessory Simulator步驟如下:
1> 在Capabilities面板的HomeKit分區(qū),點(diǎn)擊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應(yīng)用程序.
創(chuàng)建Home 布局
- Home 布局 介紹
1> HomeKit 允許用戶創(chuàng)建一個(gè)或者多個(gè)Home布局鲜漩。每個(gè)Home代表一個(gè)有網(wǎng)絡(luò)設(shè)備的住所。
2> 用戶擁有Home的數(shù)據(jù)并可通過自己的任何一臺(tái)iOS設(shè)備進(jìn)行訪問集惋。
3> 用戶也可以和客戶共享一個(gè)Home宇整,但是客戶的權(quán)限會(huì)有更多限制。
4> 被指定為primary home的home默認(rèn)是Siri指令的對(duì)象芋膘,并且不能指定home鳞青。
5> 每個(gè)Home一般有多個(gè)room,并且每個(gè)room一般會(huì)有多個(gè)智能配件为朋。
6> 在home 中臂拓,每個(gè)房間是獨(dú)立的room,并具有一個(gè)有意義的名字习寸,例如“臥室”或者“廚房”胶惰,這些名字可以在Siri 命令中使用.
7> 一個(gè)accessory代表實(shí)際家庭中的自動(dòng)化設(shè)備,例如車庫開門器霞溪。一個(gè)sevice 是accessory提供的?種實(shí)際服務(wù)孵滞,例如打開或者關(guān)閉車庫,或者車庫上的燈鸯匹。
7> 如果你的app 緩存了home布局的信息坊饶,那么當(dāng)其布局發(fā)聲改變的時(shí)候,app就需要更新這些信息.
8> 使用HMHomeManager對(duì)象可以從HomeKit數(shù)據(jù)庫獲取HMHome和其他相關(guān)的對(duì)象殴蓬。
- 創(chuàng)建 Home Manager對(duì)象
1> 使用Home Manager對(duì)象訪問home匿级、room、配件染厅、服務(wù)以及其他HomeKit對(duì)象痘绎。
2> 在創(chuàng)建家庭對(duì)象管理器(home manager)之后,直接設(shè)置它的代理肖粮,以便獲取到這些對(duì)象(eg:home孤页、room、配件涩馆、服務(wù)... )之后及時(shí)的通知到你行施。
self.homeManager = [[HMHomeManager alloc] init];
self.homeManager.delegate = self;
當(dāng)你創(chuàng)建一個(gè)home manager對(duì)象時(shí),HomeKit就開始從HomeKit數(shù)據(jù)庫獲取這些homes和相關(guān)對(duì)象凌净,例如room和accessory對(duì)象悲龟。當(dāng)HomeKit正在獲取那些對(duì)象時(shí),home manager 的primaryHome屬性是nil冰寻,并且homes 屬性是個(gè)空數(shù)組须教。
你的app應(yīng)該處理用戶還沒有完成創(chuàng)建home的情況,但是app應(yīng)該等待直到HomeKit完成初始化。當(dāng)獲取對(duì)象完成之后轻腺,HomeKit 會(huì)發(fā)送homeManagerDidUpdateHomes:消息給home manager的代理乐疆。
注意:當(dāng)app進(jìn)入前臺(tái)或者在后臺(tái)Home manager屬性發(fā)生改變時(shí),這個(gè)homeManagerDidUpdateHomes:方法就會(huì)被調(diào)用贬养,詳情請(qǐng)參閱Observing Changes to the Collection of Homes
- 獲取Primary Home和 Homes集合
通過home manager的primaryHome屬性挤土,可以得到primary home,代碼如下:
HMHome *home = self.homeManager.primaryHome;
- 使用home manager的homes屬性可以得到用戶的所有home的集合误算;例如自家主要居所仰美、度假別墅以及辦公室。每個(gè)home都對(duì)應(yīng)一個(gè)獨(dú)立的home對(duì)象儿礼。
HMHome *home;
for (home in self.homeManager.homes ){
... ...
}
- 獲取 Home中的所有room
在一個(gè)home中咖杂,rooms屬性定義accessories的物理位置。
用home的rooms屬性可以枚舉home中的所room蚊夫。
HMHome *home = self.homeManager.primaryHome;
HMRome *room;
for (room in home.rooms){
… ...
}
- 獲取Room 中的Accessories
Accessories 數(shù)組屬于home诉字,但是被指定給了home中的room。假如用戶沒有給一個(gè)accessory指定room知纷,那么這個(gè)accessories被指定一個(gè)默認(rèn)的room ,這個(gè)room是方法的返回值壤圃。用room的accessories屬性可以枚舉room中所有的accessory。代碼如下:
HMAccessory *accessory;
for (accessory in room.accessories){
… ...
}
如果你要展示一個(gè)個(gè)accessory的相關(guān)信息或者允許用戶控制它琅轧,可設(shè)置accessory的代理方法并實(shí)現(xiàn)這個(gè)代理方法瞳步,
一旦你獲取到一個(gè)accessory對(duì)象胡桃,你就可以訪問它的服務(wù)和對(duì)象
獲取Home中的Accessories屬性使用HMHome類中的accessories的方法蜂嗽,可以直接從Home對(duì)象中獲取所有的accessory對(duì)象闷畸,而不用枚舉home中的所有room對(duì)象
創(chuàng)建Homes和添加Accessories
- HomeKit對(duì)象被保存在一個(gè)可以共享的HomeKit數(shù)據(jù)庫里,它可以通過HomeKit框架被多個(gè)應(yīng)英程序訪問模蜡。
- 所有HomeKit調(diào)用的方法都是異步寫入的,并且這些方法都包含一個(gè)完成處理后的參數(shù)扁凛。
- 如果這個(gè)方法處理成功了忍疾,你的應(yīng)用將會(huì)在完成處理函數(shù)里更新本地對(duì)象。
- 應(yīng)用程序啟動(dòng)時(shí)谨朝,HomeKit對(duì)象發(fā)生改變的并不能收到代理回調(diào)?法卤妒,只能接受處理完成后的回調(diào)函數(shù)。
想要觀察其他應(yīng)用程序啟動(dòng)時(shí)HomeKit對(duì)象的變化字币,請(qǐng)參閱:Observing HomeKit Database Changes则披。查閱異步消息完成處理后傳過來的錯(cuò)誤碼的信息,請(qǐng)參閱:HomeKit Constants Reference.
對(duì)象命名規(guī)則
HomeKit對(duì)象的名字洗出,例如home士复、room和zone對(duì)象都可以被Siri識(shí)別,這一點(diǎn)已經(jīng)在文檔中指出。以下幾點(diǎn)是HomeKit對(duì)象的命名規(guī)則:
- 對(duì)象名字在其命名空間內(nèi)必須是唯一的阱洪。
- 屬于用戶所有的home名字都在一個(gè)命名空間內(nèi)便贵。
- 一個(gè)home對(duì)象及其所包含的對(duì)象在另一個(gè)命名空間內(nèi)。
- 名字只能包含數(shù)字冗荸、字母承璃、空格以及省略號(hào)字符。
- 名字必須以數(shù)字或者字母字符開始蚌本。
- 在名字比較的時(shí)候,空格或者省略號(hào)是忽略的(例如home1和home 1 同一個(gè)名字)盔粹。
- 名字沒有大小寫之分。
(一)創(chuàng)建Homes
- 在HMHomeManager類中使用addHomeWithName:completionHandler:異步方法可以添加一個(gè)home程癌。作為參數(shù)傳到那個(gè)方法中的home的名字玻佩,必須是唯一獨(dú)特的,并且是Siri可以識(shí)別的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語句中咬崔,寫入代碼以更新你應(yīng)的程序的視圖。
(二)添加房間
- 在Home中增加一個(gè)Room
使用addRoomWithName:completionHandler:異步方法可以在一個(gè)home中添加一個(gè)room對(duì)象烦秩。作為參數(shù)傳到那個(gè)方法中的room的名字垮斯,必須是唯一獨(dú)特的,并且是Siri可識(shí)別的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語句中兜蠕,寫入代碼更新應(yīng)用程序的視圖。
(三)發(fā)現(xiàn)配件
Accessories封裝了物理配件的狀態(tài)抛寝,因此它不能被用戶創(chuàng)建熊杨。想要允許用戶給家添加新的配件,我們可以使HMAccessoryBrowser對(duì)象找到一個(gè)與home沒有關(guān)聯(lián)的配件盗舰。HMAccessoryBrower
對(duì)象在后臺(tái)搜尋配件晶府,當(dāng)它找到配件的時(shí)候,使用委托來通知你的應(yīng)用程序钻趋。只有在startSearchingForNewAccessories方法調(diào)用之后或者stopSearchingForNewAccessories方法調(diào)用之前,HMAccessoryBrowserDelegate消息才被發(fā)送給代理對(duì)象川陆。
- 發(fā)現(xiàn)home中的配件
1> 在你的類接口中添加配件瀏覽器委托協(xié)議,并且添加一個(gè)配件瀏覽器屬性蛮位。代碼如下:
@interface EditHomeViewController ()
@property HMAccessoryBrowser *accessoryBrowser;
@end
2> 創(chuàng)建配件瀏覽器對(duì)象较沪,并設(shè)置它的代理
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> 停止搜尋配件
如果一個(gè)視圖控制器正在開始搜尋配件,那么可以通過重寫
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear: animated];
[self.accessoryBrowser stopSearchingForNewAccessories];
}
注意: 在WiFi網(wǎng)絡(luò)環(huán)境下失仁,為了安全地獲取新的并且能夠被HomeKit發(fā)現(xiàn)的無線配件尸曼,請(qǐng)參閱External Accessory Framework Reference.
(四)為Home和room添加配件(Accessory)
配件歸屬于home,并且它可以被隨意添加到home中的任意一個(gè)room中萄焦。使用addAccessory:completionHandler:這個(gè)異步方法可以在home中添加配件控轿。這個(gè)配件的名字作為一個(gè)參數(shù)傳遞到上述異步方法中,并且這個(gè)名字在配件所屬的home中必須是唯一的。
使用assignAccessory:toRoom:completionHandler: 這個(gè)異步方法可以給home中
的room添加配件解幽。配件默認(rèn)的room是roomForEntireHome這個(gè)方法返回值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
}
}];
}
}
}];
配件可提供一項(xiàng)或者多項(xiàng)服務(wù),這些服務(wù)的特性是由制造商定義躲株。想了解配件的服務(wù)和特性目的片部,請(qǐng)參閱 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> 橋接口是配件中的一個(gè)特殊對(duì)象霜定,它允許你和其他配件交流档悠,但是不允許你直接和HomeKit交流。例如一個(gè)橋接口可以是控制多個(gè)燈
的樞紐望浩,它使用的是自己的通信協(xié)議辖所,而不是HomeKit配件通信協(xié)議。
2> 想要給home添加多個(gè)橋接口 磨德,你可以按照Adding Accessories to Homes and Rooms中所描述的步驟缘回,添加
任何類型的配件到home中。
3> 當(dāng)你給home添加一個(gè)橋接口時(shí)典挑,在橋接口底層的配件也會(huì)被添加到home中酥宴。
4> 正如Observing HomeKit Database Changes中所描述的那樣,每次更改通知設(shè)計(jì)模您觉,home的代理不會(huì)接收到橋接口的home:didAddAccessory:
代理消息拙寡,而是接收一個(gè)有關(guān)于配件的home:didAddAccessory:代理消息。
在home中琳水,要把橋接口后的配件和任何類型的配件看成一樣的--例如肆糕,把它們加入配件列表的配置表中。相反的是在孝,當(dāng)你給room增添一個(gè)橋接口時(shí)诚啃,這個(gè)橋接口底層的配件并不會(huì)自動(dòng)地添加到room中,原因是橋接口和它的的配件可以位于到不同的room中浑玛。
- 創(chuàng)建分區(qū)
分區(qū) HMZone 是任意可選的房間(rooms)分組绍申;例如樓上、樓下或者臥室顾彰。房間可以被添加到一個(gè)或者多個(gè)區(qū)域。
可使用addZoneWithName:completionHandler: 異步方法創(chuàng)建分區(qū)胃碾。所創(chuàng)建的作為參數(shù)傳遞到這個(gè)方法中分區(qū)的名稱涨享,在home中必須是唯一的,并且應(yīng)該能被Siri識(shí)別仆百。代碼如下:
__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:異步方法給分區(qū)添加一個(gè)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數(shù)據(jù)庫的變化
每個(gè)Home都有一個(gè)HomeKit數(shù)據(jù)庫。如下圖所示,HomeKit數(shù)據(jù)庫會(huì)安全地和home授權(quán)的用戶的iOS設(shè)備以及潛在的客人的iOS設(shè)備進(jìn)行同步吁讨。為了給用戶展示當(dāng)前最新的數(shù)據(jù)髓迎,你的應(yīng)用需要觀察HomeKit數(shù)據(jù)庫的變化。
(一)Homekit代理方法
- HomKit使用代理設(shè)計(jì)模式delegation design pattern來通知應(yīng)用程序HomeKit對(duì)象的改變建丧。
1> 一般來講排龄,如果你的應(yīng)用程序調(diào)用了一個(gè)帶有完成處理參數(shù)的HomeKit方法,并且這個(gè)方法被成功調(diào)用了翎朱,那么相關(guān)聯(lián)的代理消息
就會(huì)被發(fā)送給其他HomeKit應(yīng)用橄维,無論這些應(yīng)用是安裝在同一臺(tái)iOS設(shè)備上還是遠(yuǎn)程iOS設(shè)備上。
2> 這些應(yīng)用甚至可以運(yùn)行在客人的iOS設(shè)備上拴曲。如果你的應(yīng)用發(fā)起了數(shù)據(jù)改變争舞,但是代理消息并沒有發(fā)送到你的應(yīng)用,
那么添加代碼到完成處理方法和相關(guān)聯(lián)的代理方法中來刷新數(shù)據(jù)和更新視圖就成為必須了澈灼。
3> 如果home布局發(fā)生了顯著變化竞川,那么就重新加載關(guān)于這個(gè)home的所有信息。在完成程序處理的情況下叁熔,請(qǐng)?jiān)诟聭?yīng)用之前檢查那個(gè)方法是否成功委乌。
4> Homkit也會(huì)調(diào)用代理方法來通知你的應(yīng)用程序home網(wǎng)絡(luò)狀態(tài)的改變。
例如者疤,下圖演示了使用代理方法的過程:響應(yīng)用戶的操作福澡,你的應(yīng)用程序調(diào)用了addRoomWithName:completionHandler:方法,并且沒有錯(cuò)誤發(fā)生驹马,完成處理程序應(yīng)當(dāng)更新home的所有視圖革砸。如果成功了,homeKit將會(huì)發(fā)送home:didAddRoom:消息給其他應(yīng)用中homes的代理糯累。因此算利,你實(shí)現(xiàn)的這個(gè)home:didAddRoom:方法也應(yīng)該更新home的所有視圖。
應(yīng)用程序只有在前臺(tái)運(yùn)行的時(shí)候才能接受代理消息泳姐。當(dāng)你的應(yīng)用在后臺(tái)時(shí)效拭,HomeKit數(shù)據(jù)庫的改變并不會(huì)成批處理。也就是說胖秒,如果你的應(yīng)用在后臺(tái)缎患,當(dāng)其他的應(yīng)用成功地添加一個(gè)room到home中的時(shí)候,你的應(yīng)用程序并不會(huì)接收到home:didAddRoom: 消息阎肝。當(dāng)你的應(yīng)用程序到前臺(tái)運(yùn)行時(shí)挤渔,你的應(yīng)用程序?qū)?huì)接收到homeManagerDidUpdateHomes:消息,這個(gè)消息是表示你的應(yīng)用程序要重新加載所有的數(shù)據(jù)风题。
(二)觀察Homes集合的改變
設(shè)置home manager的代理并且實(shí)現(xiàn)HMHomeManagerDelegate協(xié)議判导,當(dāng)primary home或者h(yuǎn)ome集合發(fā)生改變時(shí)嫉父,可以接收代理消息。
所有的應(yīng)用都需要實(shí)現(xiàn)homeManagerDidUpdateHomes:方法眼刃,這個(gè)方法在完成最初獲取homes之后被調(diào)用绕辖。對(duì)新建的home manager來說,在這個(gè)方法被調(diào)用之前擂红,primaryHome 屬性的值是nil仪际,homes數(shù)組是空的數(shù)組。
當(dāng)應(yīng)用程序開始在前臺(tái)運(yùn)行時(shí)也會(huì)調(diào)用 homeManagerDidUpdateHomes: 方法篮条,當(dāng)其在后臺(tái)運(yùn)行時(shí)數(shù)據(jù)發(fā)生改變弟头。該homeManagerDidUpdateHomes:方法會(huì)重新加載與homes相關(guān)聯(lián)的所有數(shù)據(jù)。
(三)觀察homes的變化
- 1>在你的類接口中添加HMHomeManagerDelegate代理和homeManager屬性涉茧。代碼如下:
@interface AppDelegate ()
@property (strong, nonatomic) HMHomeManager *homeManager;
@end
- 2>創(chuàng)建home manager對(duì)象并設(shè)置其代理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.homeManager = [[HMHomeManager alloc] init];
self.homeManager.delegate = self;
return YES;
}
- 3> 實(shí)現(xiàn)homes發(fā)生改變時(shí)調(diào)用的代理方法赴恨。例如:如果多個(gè)視圖控制器展示了homes相關(guān)信息,你可以發(fā)布一個(gè)更改通知去更新所有視圖伴栓。
// 代理監(jiān)聽事件
- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {
// Send a notification to the other objects
[[NSNotificationCenter defaultCenter]postNotificationName:@"UpdateHomesNotification" object:self];
}
// 通知分發(fā)具體任務(wù)
- (void)homeManagerDidUpdatePrimaryHome:(HMHomeManager*)manager {
// Send a notification to the other objects
[[NSNotificationCenter defaultCenter] postNotificationName:@"UpdatePrimaryHomeNotification" object:self];
}
- 4> 視圖控制器注冊(cè)更改通知并且執(zhí)行適當(dāng)?shù)牟僮鳌?/li>
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateHomes:) name:@"UpdateHomesNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePrimaryHome:) name:@"UpdatePrimaryHomeNotification" object:nil];
(四)觀察個(gè)別home的變化
展示home信息的視圖控制器應(yīng)該成為home對(duì)象的代理伦连,并且當(dāng)home發(fā)生改變時(shí)更新視圖控制器的視圖。
- 觀察特定home對(duì)象的改變
1> 在類接口中添加home代理協(xié)議钳垮。
@interface HomeViewController () @end
2> 設(shè)置配件代理
home.delegate = self;
3> 實(shí)現(xiàn)HMHomeDelegate]協(xié)議
例如:實(shí)現(xiàn)home:didAddAccessory:和home:didRemoveAccessory: 方法來更新展示配件的視圖惑淳。用HMAccessory類的room屬性可以獲得配件所屬的room。(對(duì)配件來說饺窿,默認(rèn)的room是roomForEntireHome這個(gè)方法的返回值歧焦。
Bridge Note:當(dāng)你為home添加橋接口時(shí),橋接口底層的配件會(huì)自動(dòng)被添加到home中肚医。你的代理會(huì)接收到橋接口后每個(gè)配件的 home:didAddAccessory:消息绢馍,但是你的代理不會(huì)接收到橋接口的home:didAddAccessory:消息。
(五)觀察個(gè)別home的變化
配件的狀態(tài)可以在任何時(shí)間發(fā)生變化肠套。配件可能不能被獲得舰涌,可以被移除,或者被關(guān)閉你稚。請(qǐng)更新用戶界面以反映配件狀態(tài)的更改瓷耙,尤其是如果你的app允許用戶控制配件時(shí)。
這以下步驟中刁赖,我們假設(shè)你已經(jīng)從HomeKit數(shù)據(jù)庫中檢索到了配件對(duì)象搁痛,正如Getting the Accessories in a Room 中描述的那樣。
(五.一)觀察個(gè)別home的變化
- 1> 在類接口中添加配件代理協(xié)議宇弛。
@interface AccessoryViewController ()
@end
- 2> 設(shè)置配件的代理
accessory.delegate = self;
- 3> 實(shí)現(xiàn) HMAccessoryDelegate 協(xié)議
比如落追,執(zhí)行accessoryDidUpdateReachability:方法以啟用或者禁用配件控制。
- (void)accessoryDidUpdateReachability:(HMAccessory *)accessory {
if (accessory.reachable == YES) {
// Can communicate with the accessory
} else {
// The accessory is out of range, turned off, etc
}
}
如果你展示了配件的服務(wù)狀態(tài)和特性涯肩,那么請(qǐng)執(zhí)行以下代理方法來相應(yīng)地更新其視圖:
accessoryDidUpdateServices
accessory:service:didUpdateValueForCharacteristic:
六:訪問服務(wù)和特性
服務(wù)HMService代表了一個(gè)配件(accessory)的某個(gè)功能和一些具有可讀寫的特性HMCharacteristic轿钠。
一個(gè)配件可以擁有多項(xiàng)服務(wù),一個(gè)服務(wù)也可以有很多特性。比如一個(gè)車庫開門器可能擁有一個(gè)照明和開關(guān)的服務(wù)病苗。照明服務(wù)可能擁有打開/關(guān)閉和調(diào)節(jié)亮度的特性疗垛。
用戶不能制造智能家電配件和它們的服務(wù)-配件制造商會(huì)制造配件和它們的服務(wù)-但是用戶可以改變服務(wù)的特性。一些擁有可讀寫屬性的特性代表著某種物理狀態(tài)硫朦,比如贷腕,一個(gè)恒溫器中的當(dāng)前溫度就是一個(gè)只可讀的值,但是目標(biāo)溫度又是可讀寫的咬展。蘋果預(yù)先定義了一些服務(wù)和特性的名稱泽裳,以便讓Siri能夠識(shí)別它們。
(一) 獲得配件的服務(wù)和屬性
在依照Getting the Accessroties in a Room中描述破婆,你創(chuàng)建了一個(gè)配件對(duì)象之后,你可以獲得配件的服務(wù)和特性涮总。當(dāng)然你也可以直接從home中按照類型獲得不同的服務(wù)。
重要:不要暴露匿名服務(wù)-比如固件升級(jí)服務(wù)-給用戶
- 通過HMAccessory屬性祷舀,我們可以獲得一個(gè)配件的服務(wù)瀑梗。
NSArray *services = accessroy.services;
- 要獲得一個(gè)home當(dāng)中配件提供的特定服務(wù),使用HMHome類對(duì)象的servicesWithTypes:方法裳扯。
// Get all lights and thermostats in a home
NSArray *lightServices = [home servicesWithTypes:[HMServicesTypeLightbulb]];
NSArray *thermostatServices = [home servicesWithTypes:[HMServicesTypeThermostat]]
- 使用HMServices類對(duì)象的name屬性來獲得服務(wù)的名稱
NSString *name = service.name;
- 要獲得一個(gè)服務(wù)的特性抛丽,請(qǐng)使用characteristics屬性。
NSArray *characteristics = service.characteristics
- 使用servicesType屬性來獲得服務(wù)的類型
NSString *serviceType = service.serviceType;
(二)改變服務(wù)名稱
- 使用updateName:completionHandler:異步方法來改變服務(wù)名稱饰豺。傳入此方法的服務(wù)名稱參數(shù)必須在一個(gè)home當(dāng)中是唯一的亿鲜,并且服務(wù)名可被Siri識(shí)別。
[service updateName:@"Garage 1 Opener" completionHandler:^(NSError *error) {
if (error) {
// Failed to change the name
} else {
// Successfully changed the name
}
}];
- 訪問特性的值
特性代表了一個(gè)服務(wù)的一個(gè)參數(shù)冤吨,它要么是只讀蒿柳、可讀寫或者只寫。它提供了這個(gè)參數(shù)可能的值的信息锅很,比如其馏,一個(gè)布爾或者一個(gè)范圍值。恒溫器中的溫度就是只讀的爆安,而目標(biāo)溫度又是可讀寫的叛复。一個(gè)執(zhí)行某個(gè)任務(wù)的命令且不要求任何返回-比如播放一段聲音或者閃爍一下燈光來確認(rèn)某個(gè)配件-可能就是只寫的。
蘋果定義了一些特性的類型扔仓,并能被Siri識(shí)別:
亮度(Brightness)
最近溫度(Current temperature)
鎖的狀態(tài)(Lock state)
電源的狀態(tài)(Power state)
目標(biāo)狀態(tài)(Target state)
目標(biāo)溫度(Target temperature)
- 在你獲得了一個(gè)HMService對(duì)象之后,如 Getting Services and Their Properties所描述的,你可以獲得每個(gè)服務(wù)的特性的值褐奥。因?yàn)檫@些值是從配件中獲得的,這些讀寫的方法都是異步的翘簇,并可以傳入一個(gè)完成回調(diào)的block撬码。
使用readValueWithCompletionHandler:異步方法來讀取一個(gè)特性的值。
[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:異步方法來向一個(gè)特性寫入值夫否。
[self.characteristic writeValue:@42 withCompletionHandler:^(NSError *error) {
if (error == nil) {
// Successfully wrote the value
}
else {
// Unable to write the value
}
}];
不要以為函數(shù)調(diào)用完成就意味著寫入成功,實(shí)際上只有在當(dāng)完成回調(diào)執(zhí)行并沒有錯(cuò)誤產(chǎn)生時(shí)才表示寫入成功叫胁。比如凰慈,直到一個(gè)開關(guān)的特性改變之前都不要改變這個(gè)開關(guān)的狀態(tài)。在if語句塊中驼鹅,加入你的代碼微谓,以更新app的視圖。
另外输钩,在別的app更新了特性的值時(shí)也需要更新視圖豺型,在Observing Changes to Accessories中有描述
(三)創(chuàng)建服務(wù)組
一個(gè)服務(wù)組[HMServiceGroup提供了控制不同配件的任意數(shù)量服務(wù)的快捷方式-比如,當(dāng)用戶離開家之后控制家中的某些燈买乃。
- 在你創(chuàng)建了一個(gè)HMHome對(duì)象之后,如Getting the Primary Home and Collection of Homes中描述,你也就在這個(gè)家中創(chuàng)建一個(gè)服務(wù)組姻氨。
為了創(chuàng)建一個(gè)服務(wù)組,我們使用HMHome類對(duì)象的addServiceGroupWithName:completionHandler:方法。方法中參數(shù)服務(wù)組的名稱必須在此家中唯一为牍,并可以被Siri識(shí)別哼绑。
[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類對(duì)象的addService:completionHandler:方法來向服務(wù)組中添加一個(gè)服務(wù)。服務(wù)可以在一個(gè)或多個(gè)服務(wù)組中碉咆。
[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類對(duì)象的serviceGroups屬性抖韩,來獲得這個(gè)家的所有服務(wù)組。
NSArray *serviceGroups = self.home.serviceGroups;
- 通過HMServiceGroup類對(duì)象的accessory屬性疫铜,我們獲得服務(wù)所對(duì)應(yīng)的智能電器茂浮。
HMAccessory *accessory = service.accessory;
和配件類似,代理方法在別的app改變服務(wù)組時(shí)也會(huì)被調(diào)用壳咕。如果你的app使用了服務(wù)組席揽,請(qǐng)閱讀HMHomeDelegate Protocol Reference文檔,獲悉你應(yīng)該實(shí)現(xiàn)哪些方法以觀察這些變化谓厘。
七: 測試
八:創(chuàng)建動(dòng)作集(Action Sets) 和 觸發(fā)器(Triggers)
一個(gè)動(dòng)作集合HMActionSet和觸發(fā)器HMTimerTrigger允許你同時(shí)控制多個(gè)智能電器幌羞。比如,一個(gè)動(dòng)作集合可能會(huì)在用戶上床休息之前執(zhí)行一組動(dòng)作HMAction竟稳。一個(gè)寫動(dòng)作向一個(gè)特性寫入了值属桦。動(dòng)作集合中的動(dòng)作是以不確定的順序執(zhí)行的。一個(gè)觸發(fā)器會(huì)在一個(gè)特定的時(shí)間出發(fā)一個(gè)動(dòng)作集并可以重復(fù)執(zhí)行他爸。每一個(gè)動(dòng)作集合在一個(gè)家庭中都有唯一的名稱并可被Siri識(shí)別聂宾。
(一) 創(chuàng)建寫入動(dòng)作
寫入動(dòng)作會(huì)向一個(gè)服務(wù)的特性寫入值并被加入到動(dòng)作集合中去。HMAction類是HMCharacteristicWriteAction具體類的抽象基類诊笤。一個(gè)動(dòng)作有一個(gè)相關(guān)聯(lián)的特性對(duì)象系谐,你可以通過Accessing Services and Characteristics中描述的來獲取相關(guān)的服務(wù)和特性,然后創(chuàng)建這個(gè)HMCharacteristicWriteAction讨跟。
- 為了創(chuàng)建一個(gè)動(dòng)作纪他,我們使用HMCharacteristicWriteAction類中的initWithCharacteristic:targetValue:方法鄙煤。
HMCharacteristicWriteAction *action = [[HMCharacteristicWriteAction alloc]
initWithCharacteristic:characteristic
targetValue:value];
在你的代碼中,你使用對(duì)應(yīng)的特性的期望來替換value參數(shù)止喷,并使用對(duì)應(yīng)的HMCharacteristic對(duì)象來替換characteristic參數(shù)馆类。
(二)創(chuàng)建并執(zhí)行動(dòng)作集
一個(gè)動(dòng)作集就是一個(gè)共同執(zhí)行的動(dòng)作的集合。比如一個(gè)夜間動(dòng)作集合可能包含關(guān)閉電燈弹谁,調(diào)低恒溫水平和鎖上房門。
- 創(chuàng)建一個(gè)動(dòng)作集我們使用addActionSetWithName:completionHandler:異步方法句喜。
[self.home addActionSetWithName:@"NightTime" completionHandler:^(HMActionSet *actionSet, NSError *error) {
if (error == nil) {
// 成功添加了一個(gè)動(dòng)作集
} else {
// 添加一個(gè)動(dòng)作集失敗
}
}];
- 添加一個(gè)動(dòng)作到動(dòng)作集预愤,我們使用addAction:completionHandler:異步方法。
[actionSet addAction:action completionHandler:^(NSError *error) {
if (error == nil) {
// 成功添加了一個(gè)動(dòng)作到動(dòng)作集
} else {
// 添加一個(gè)動(dòng)作到動(dòng)作集失敗
}
}];
移除一個(gè)動(dòng)作咳胃,可使用removeAction:completionHandler:方法植康。
想要執(zhí)行一個(gè)動(dòng)作集,可使用HMHome類的executeActionSet:completionHandler:方法展懈。
比如销睁,用戶希望控制所有的節(jié)日彩燈。我們就創(chuàng)建一個(gè)動(dòng)作集來打開所有的節(jié)日彩燈存崖,另外一個(gè)動(dòng)作集來關(guān)閉所有的節(jié)日彩燈冻记。為了打開所有的節(jié)日彩燈,發(fā)送executeActionSet:completionHandler:消息給home對(duì)象来惧,并傳遞"打開節(jié)日彩燈"動(dòng)作集冗栗。
九:創(chuàng)建并開啟觸發(fā)器
- 觸發(fā)器會(huì)執(zhí)行一個(gè)或多個(gè)動(dòng)作集。iOS會(huì)在后臺(tái)管理和運(yùn)行你的觸發(fā)器供搀。HMTrigger 類是HMTimerTrigger具體類的抽象類隅居。
當(dāng)你創(chuàng)建一個(gè)定時(shí)觸發(fā)器時(shí),你需要指定觸發(fā)時(shí)間和觸發(fā)的周期葛虐。創(chuàng)建并開啟一個(gè)定時(shí)觸發(fā)器需要多個(gè)步驟來完成胎源。
遵循下面幾步來創(chuàng)建并啟動(dòng)一個(gè)定時(shí)觸發(fā)器
- 1> 創(chuàng)建一個(gè)定時(shí)觸發(fā)器
self.trigger = [[HMTimerTrigger alloc] initWithName:name fireDate:fireDate timeZone:niL recurrence:nil recurrenceCalendar:nil];
觸發(fā)時(shí)間必須設(shè)置在將來的某個(gè)時(shí)刻,第二個(gè)參數(shù)必須為0.如果你設(shè)置了一個(gè)周期屿脐,周期的最小值是5分鐘涕蚤,最大值是5周。關(guān)于如何使用NSDateComponents和NSCalendar來設(shè)置周期摄悯,請(qǐng)閱讀Date and Time Programming Guide
- 2> 添加一個(gè)動(dòng)作集到觸發(fā)器赞季。
使用HMTrigger基類方法addActionSet:completionHandler:,來添加一個(gè)動(dòng)作集到觸發(fā)器奢驯。
- 3> 添加一個(gè)觸發(fā)器到家庭申钩。
使用HMHome類中的addTrigger:completionHandler:方法來添加一個(gè)觸發(fā)器到家庭。
- 4> 啟動(dòng)觸發(fā)器
新創(chuàng)建的觸發(fā)器默認(rèn)是未啟動(dòng)的瘪阁。需要使用enable:complationHandler:方法啟動(dòng)觸發(fā)器撒遣。
一個(gè)定時(shí)觸發(fā)器被啟動(dòng)后邮偎,會(huì)周期性的運(yùn)行它的動(dòng)作集。
十: 用戶管理
創(chuàng)建home的用戶是該home的管理員义黎,可以執(zhí)行所有操作禾进,包括添加一個(gè)客人用戶到home。任何管理員添加到這個(gè)home的用戶(HMUser)都有一個(gè)有限的權(quán)限廉涕⌒涸疲客人不能更改家庭的布局,但是可以執(zhí)行下面的動(dòng)作:
- 識(shí)別智能電器
- 讀寫特性
- 觀察特性值變化
- 執(zhí)行動(dòng)作集
比如狐蜕,一個(gè)家庭的戶主可以創(chuàng)建一個(gè)home布局并向其中添加家庭成員宠纯。每個(gè)家庭成員必須擁有一個(gè)iOS設(shè)備和Apple ID以及相關(guān)的iCloud賬戶。iCloud需要個(gè)人輸入的Apple ID和戶主提供的Apple ID相吻合层释,以便讓他們?cè)L問這個(gè)home婆瓜。考慮到隱私問題贡羔,Apple ID對(duì)你的App是不可見的廉白。
管理員需要遵從以下步驟來添加一個(gè)客人到home中:
- 1> 管理員調(diào)用一個(gè)動(dòng)作將客人添加到home中。
- 2> 你的App調(diào)用addUserWithCompletionHandler:異步方法乖寒。
- 3> HomeKit展示一個(gè)對(duì)話框猴蹂,要求輸入客人的Apple ID。
- 4> 用戶輸入客人的Apple ID宵统。
- 5> 在完成回調(diào)中返回一個(gè)新的用戶晕讲。
- 6> 你的App展示客人的名字。
添加一個(gè)客人到home马澈,需要在客人的iOS設(shè)備上做以下操作:
- 1> 用戶在iCloud偏好設(shè)置中輸入iCloud憑證(Apple ID和密碼)瓢省。
- 2> 用戶啟動(dòng)你的App。
- 3> 你的App通過home manager object獲得一個(gè)home集合痊班。
- 4> 如果iCloud的憑證和管理員輸入的Apple ID相同勤婚,那么管理員的home將會(huì)出現(xiàn)在homes屬性中。
客人執(zhí)行的操作可能會(huì)失敗涤伐。如果一個(gè)異步方法中出現(xiàn)HMErrorCodeInsufficientPrivileges錯(cuò)誤碼的話馒胆,這就意味著用戶沒有足夠的權(quán)限來執(zhí)行動(dòng)作-也許這個(gè)用戶只是客人,而不是管理員凝果。
添加和移除用戶
- 添加一個(gè)客人用戶到home祝迂,請(qǐng)使用addUserWithCompletionHandler:異步方法。
[self.home addUserWithCompletionHandler:^(HMUser *user, NSError *error) {
if (error == nil) {
// Successfully added a user
}
else {
// Unable to add a user
}
}];
想要移除home中的用戶器净,請(qǐng)使用HMHome類的removeUser:completionHandler:方法型雳。
通過實(shí)現(xiàn)HMHomeDelegate協(xié)議中的home:didAddUser:和home:didRemoveUser:協(xié)議方法檢查新添加和移除的用戶并更新視圖。
獲得用戶名
出于隱私的考慮,你的app對(duì)用戶名只有讀得權(quán)限纠俭,并不能讀寫用戶的Apple ID沿量。使用HMHome對(duì)象的users屬性來獲取用戶。使用HMUser類的name屬性來獲取用戶名冤荆。
Homekit 筆記(二) http://www.reibang.com/p/dc3fdbef74a1