Xamarin.iOS 中的 HomeKit
HomeKit 是 Apple 控制家庭自動化裝置的架構。 本文介紹 HomeKit,並涵蓋在 HomeKit 配件模擬器中設定測試配件,以及撰寫簡單的 Xamarin.iOS 應用程式來與這些配件互動。
Apple 在 iOS 8 中引進 HomeKit,以順暢地將來自各種廠商的多個家庭自動化裝置整合到單一連貫的單元中。 藉由推廣通用通訊協定來探索、設定及控制家庭自動化裝置,HomeKit 可讓來自非相關廠商的裝置共同合作,而不需要個別廠商協調工作。
使用 HomeKit,您可以建立 Xamarin.iOS 應用程式,以控制任何已啟用 HomeKit 的裝置,而不需使用廠商提供的 API 或應用程式。 使用 HomeKit,您可以執行下列動作:
- 探索已啟用 HomeKit 的新家用自動化裝置,並將其新增至將保存在所有使用者 iOS 裝置上的資料庫。
- 在 HomeKit 家用設定資料庫中設定、設定、顯示及控制任何裝置。
- 與任何預先設定的 HomeKit 裝置通訊,並命令它們以在音樂會中執行個別動作或工作,例如開啟廚房中的所有燈光。
除了在 Home Configuration Database 中為已啟用 HomeKit 的應用程式提供服務的裝置之外,HomeKit 還提供 Siri 語音命令的存取權。 假設有適當設定的 HomeKit 設定,使用者可以發出語音命令,例如「Siri,開啟客廳中的燈光」。
首頁組態資料庫
HomeKit 會將指定位置中的所有自動化裝置組織成 Home Collection。 此集合可讓使用者使用有意義的人類可讀取標籤,將其家庭自動化裝置分組成以邏輯方式排列的單位。
Home Collection 會儲存在家用設定資料庫中,該資料庫會自動跨所有使用者的 iOS 裝置進行備份和同步處理。 HomeKit 提供下列類別來使用 Home Configuration Database:
HMHome
- 這是最上層容器,可保存單一實體位置中所有家庭自動化裝置的所有資訊和組態(例如單一家庭住宅)。 使用者可能有一個以上的住宅,例如其主要住宅和度假區。 或者,他們可能有不同的「房子」在同一個物業,如主房子和一個賓館在車庫上。 無論哪種方式,至少必須設定並儲存一個HMHome
物件,才能輸入任何其他 HomeKit 資訊。HMRoom
- 雖然是選擇性的,HMRoom
可讓使用者在住宅內定義特定房間,HMHome
例如:廚房、浴室、車庫或客廳。 用戶可以將家裡特定位置的所有家庭自動化裝置分組到 ,HMRoom
並將它們作為單位採取行動。 例如,要求 Siri 關閉車庫燈。HMAccessory
- 這代表已安裝在使用者住所(例如智慧控溫器)的個別實體 HomeKit 自動化裝置。 每個HMAccessory
都會指定給HMRoom
。 如果使用者尚未設定任何會議室,HomeKit 會將配件指派給特殊的預設會議室。HMService
- 表示由指定HMAccessory
所提供的服務,例如淺色或其色彩的開/關狀態(如果支援色彩變更)。 每個HMAccessory
服務可以有多個服務,例如車庫門打開器,也包括燈光。 此外,指定的HMAccessory
可能會有使用者控制外部的服務,例如韌體更新。HMZone
- 允許使用者將物件的集合HMRoom
分組到邏輯區域,例如樓上層、樓下或地下室。 雖然是選擇性的,但允許互動,例如要求 Siri 關閉樓下的所有光線。
布建 HomeKit 應用程式
由於 HomeKit 所強加的安全性需求,使用 HomeKit 架構的 Xamarin.iOS 應用程式必須在 Apple 開發人員入口網站和 Xamarin.iOS 專案檔中正確設定。
執行下列操作:
按兩下 [ 憑證]、[標識符和配置檔]。
如果您尚未這麼做,請按兩下 [標識符] ,然後為您的應用程式建立標識碼(例如
com.company.appname
),否則請編輯現有的標識碼。確定 已檢查 HomeKit 服務是否有指定的識別碼:
儲存您的變更。
點選單擊 [布建設定檔>開發],並為您的應用程式建立新的開發佈建配置檔:
下載並安裝新的布建配置檔,或使用 Xcode 下載並安裝設定檔。
編輯您的 Xamarin.iOS 選項,並確定您使用剛才建立的布建設定檔:
接下來,編輯 Info.plist 檔案,並確定您使用用來建立布建配置檔的應用程式識別碼:
最後,編輯您的 Entitlements.plist 檔案, 並確定已選取 HomeKit 權利:
儲存所有檔案的變更。
有了這些設定,應用程式現在即可存取 HomeKit Framework API。 如需布建的詳細資訊,請參閱我們的 裝置布 建和 布建您的應用程式 指南。
重要
測試已啟用 HomeKit 的應用程式需要已正確布建以進行開發的實際 iOS 裝置。 HomeKit 無法從 iOS 模擬器進行測試。
HomeKit 配件模擬器
為了提供一種方法來測試所有可能的家庭自動化裝置和服務,而不需要擁有實體裝置,Apple 建立了 HomeKit 配件模擬器。 使用此模擬器,您可以設定及設定虛擬 HomeKit 裝置。
安裝模擬器
Apple 提供 HomeKit 配件模擬器做為 Xcode 的個別下載,因此您必須安裝它,才能繼續。
執行下列操作:
在網頁瀏覽器中,流覽 Apple 開發人員的下載
下載適用於 Xcode xxx 的其他工具(其中 xxx 是您安裝的 Xcode 版本):
開啟磁碟映像,並在應用程式目錄中安裝工具。
安裝 HomeKit 配件模擬器后,即可建立虛擬配件進行測試。
建立虛擬配件
若要啟動 HomeKit 配件模擬器並建立一些虛擬配件,請執行下列動作:
從 [應用程式] 資料夾,啟動 HomeKit 配件模擬器:
+按鍵,然後選取 [新增配件...]:
填寫新配件的相關信息,然後按兩下 [ 完成] 按鈕:
按兩下 [ 新增 Service..] 按鈕,然後從下拉式清單中選取服務類型:
提供服務的 [名稱],然後按下 [完成] 按鈕:
您可以按下[ 新增特性 ] 按鈕並設定必要的設定,為服務提供選擇性特性:
重複上述步驟,以建立 HomeKit 支援的每種虛擬家庭自動化裝置類型之一。
建立並設定一些範例虛擬 HomeKit 配件之後,您現在可以從 Xamarin.iOS 應用程式取用及控制這些裝置。
設定 Info.plist 檔案
iOS 10 的新功能(以及更新版本),開發人員必須將密鑰新增 NSHomeKitUsageDescription
至應用程式的 Info.plist
檔案,並提供字串,以宣告應用程式想要存取使用者的 HomeKit 資料庫的原因。 此字串會在使用者第一次執行應用程式時向使用者顯示:
若要設定此機碼,請執行下列動作:
按兩下
Info.plist
方案總管中的檔案以開啟檔案以進行編輯。在畫面底部,切換至 [ 來源 ] 檢視。
將新的 專案 新增至清單。
從下拉式清單中,選取 [隱私權 - HomeKit 使用量描述]:
輸入應用程式想要存取使用者 HomeKit 資料庫的原因描述:
儲存對檔案所做的變更。
重要
在檔案中設定NSHomeKitUsageDescription
金鑰失敗會導致應用程式在運行時間以無訊息方式失敗(在運行時間由系統關閉),在 iOS 10 中執行時不會發生Info.plist
錯誤。
連線 至 HomeKit
若要與 HomeKit 通訊,您的 Xamarin.iOS 應用程式必須先具現化 類別的 HMHomeManager
實例。 Home Manager 是 HomeKit 的中央進入點,負責提供可用房屋清單、更新和維護該清單,以及傳回使用者 的主要首頁。
物件 HMHome
包含提供給家庭的所有相關信息,包括它可能包含的任何會議室、群組或區域,以及已安裝的任何家用自動化配件。 在 HomeKit 中執行任何作業之前,至少必須建立一個 HMHome
作業並指派為主要首頁。
您的應用程式會負責檢查主要首頁是否存在,並在未建立和指派主要首頁時加以指派。
新增 Home Manager
若要將 HomeKit 感知新增至 Xamarin.iOS 應用程式,請編輯 AppDelegate.cs 檔案進行編輯,使其看起來如下所示:
using HomeKit;
...
public HMHomeManager HomeManager { get; set; }
...
public override void FinishedLaunching (UIApplication application)
{
// Attach to the Home Manager
HomeManager = new HMHomeManager ();
Console.WriteLine ("{0} Home(s) defined in the Home Manager", HomeManager.Homes.Count());
// Wire-up Home Manager Events
HomeManager.DidAddHome += (sender, e) => {
Console.WriteLine("Manager Added Home: {0}",e.Home);
};
HomeManager.DidRemoveHome += (sender, e) => {
Console.WriteLine("Manager Removed Home: {0}",e.Home);
};
HomeManager.DidUpdateHomes += (sender, e) => {
Console.WriteLine("Manager Updated Homes");
};
HomeManager.DidUpdatePrimaryHome += (sender, e) => {
Console.WriteLine("Manager Updated Primary Home");
};
}
第一次執行應用程式時,系統會詢問使用者是否要允許它存取其 HomeKit 資訊:
如果使用者回答 [確定],則應用程式將能夠使用其 HomeKit Accessories,否則不會,且對 HomeKit 的任何呼叫都會失敗,併發生錯誤。
有了 Home Manager,下一個應用程式必須查看是否已設定主要首頁,如果尚未設定,請提供一種方式讓使用者建立並指派一個。
存取主要首頁
如上所述,在 HomeKit 可供使用之前,必須先建立並設定主要首頁,且應用程式必須負責提供一種方式,讓使用者在尚未存在時建立和指派主要首頁。
當您的應用程式第一次啟動或從背景傳回時,它必須監視 DidUpdateHomes
類別的事件 HMHomeManager
,以檢查主要首頁是否存在。 如果不存在,它應該會提供介面供使用者建立介面。
下列程式代碼可以新增至檢視控制器,以檢查主要首頁:
using HomeKit;
...
public AppDelegate ThisApp {
get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
}
...
// Wireup events
ThisApp.HomeManager.DidUpdateHomes += (sender, e) => {
// Was a primary home found?
if (ThisApp.HomeManager.PrimaryHome == null) {
// Ask user to add a home
PerformSegue("AddHomeSegue",this);
}
};
當 Home Manager 與 HomeKit 建立連線時,將會引發事件, DidUpdateHomes
如果可用,任何現有的房屋都會載入經理的房屋集合,並載入主要家庭。
新增主要首頁
如果 的 PrimaryHome
HMHomeManager
屬性在 null
事件之後 DidUpdateHomes
,您需要提供一種方式,讓使用者建立並指派主要首頁,然後再繼續。
一般而言,應用程式會呈現窗體供使用者命名新家,然後傳遞至 Home Manager 以設定為主要首頁。 針對 HomeKitIntro 範例應用程式,在 Xcode 介面產生器中建立強制響應檢視,並由應用程式主要介面的 segue 呼叫AddHomeSegue
。
它提供文字欄位,讓使用者輸入新首頁的名稱,以及新增首頁的按鈕。 當使用者點選 [ 新增首頁 ] 按鈕時,下列程式代碼會呼叫 Home Manager 以新增首頁:
// Add new home to HomeKit
ThisApp.HomeManager.AddHome(HomeName.Text,(home,error) =>{
// Did an error occur
if (error!=null) {
// Yes, inform user
AlertView.PresentOKAlert("Add Home Error",string.Format("Error adding {0}: {1}",HomeName.Text,error.LocalizedDescription),this);
return;
}
// Make the primary house
ThisApp.HomeManager.UpdatePrimaryHome(home,(err) => {
// Error?
if (err!=null) {
// Inform user of error
AlertView.PresentOKAlert("Add Home Error",string.Format("Unable to make this the primary home: {0}",err.LocalizedDescription),this);
return ;
}
});
// Close the window when the home is created
DismissViewController(true,null);
});
方法 AddHome
會嘗試建立新的首頁,並將它傳回指定的回呼例程。 error
如果屬性不是 null
,就會發生錯誤,而且應該向用戶顯示錯誤。 最常見的錯誤是由非唯一的家名或 Home Manager 無法與 HomeKit 通訊所造成。
如果已成功建立家庭,您必須呼叫 UpdatePrimaryHome
方法,將新家設定為主要首頁。 同樣地,如果 error
屬性不是 null
,就會發生錯誤,而且應該向用戶顯示錯誤。
您也應該監視 Home Manager 的 DidAddHome
和 DidRemoveHome
事件,並視需要更新應用程式的使用者介面。
重要
AlertView.PresentOKAlert
上述範例程式代碼中使用的方法是 HomeKitIntro 應用程式中的協助程式類別,可讓您更輕鬆地使用 iOS 警示。
尋找新的配件
一旦從 Home Manager 定義或載入主要首頁之後,您的 Xamarin.iOS 應用程式就可以呼叫 HMAccessoryBrowser
來尋找任何新的家庭自動化配件,並將其新增至家庭。
StartSearchingForNewAccessories
呼叫 方法,以在完成時開始尋找新的配件和 StopSearchingForNewAccessories
方法。
重要
StartSearchingForNewAccessories
不應該長時間執行,因為它會對iOS裝置的電池使用時間和效能產生負面影響。 Apple 建議在一分鐘后呼叫 StopSearchingForNewAccessories
,或只在 [尋找配件] UI 向用戶顯示時進行搜尋。
當 DidFindNewAccessory
探索到新的配件時,將會呼叫事件,而且它們將會新增至 DiscoveredAccessories
Accessory Browser 中的清單。
此 DiscoveredAccessories
清單將包含物件的集合 HMAccessory
,這些物件會定義提供已啟用 HomeKit 的家庭自動化裝置及其可用服務,例如燈光或車庫門控。
找到新的配件之後,應該向用戶顯示它,以便他們選取它,並將其新增至家庭。 範例:
AddAccessory
呼叫 方法,將選取的配件新增至首頁的集合。 例如:
// Add the requested accessory to the home
ThisApp.HomeManager.PrimaryHome.AddAccessory (_controller.AccessoryBrowser.DiscoveredAccessories [indexPath.Row], (err) => {
// Did an error occur
if (err !=null) {
// Inform user of error
AlertView.PresentOKAlert("Add Accessory Error",err.LocalizedDescription,_controller);
}
});
err
如果屬性不是 null
,就會發生錯誤,而且應該向用戶顯示錯誤。 否則,系統會要求使用者輸入裝置的安裝碼以新增:
在 HomeKit 配件模擬器中,您可以在 [設定程式代碼] 字段下找到此數位:
針對實際的 HomeKit 配件,安裝程式代碼會列印在裝置本身的標籤、產品方塊或配件的使用者手冊上。
您應該監視 Accessory Browser 的事件 DidRemoveNewAccessory
,並更新使用者介面,以在使用者將其新增至其 Home Collection 之後,從可用的清單中移除配件。
使用配件
一旦建立主要住宅並新增配件,您就可以提供配件清單(以及選擇性會議室),讓用戶能夠使用。
物件 HMRoom
包含指定房間及其所屬之任何配件的所有相關信息。 會議室可以選擇性地組織成一或多個區域。 HMZone
包含指定區域及其所屬所有會議室的所有資訊。
為了這個範例,我們將讓事情保持簡單,並直接使用家庭的配件,而不是將它們組織到房間或區域。
HMHome
物件包含指派的配件清單,可在其 Accessories
屬性中向用戶呈現。 例如:
在此表單中,用戶可以選取指定的配件,並與其提供的服務搭配使用。
使用服務
當使用者與已啟用 HomeKit 的家用自動化裝置互動時,通常是透過所提供的服務。 類別 Services
的 HMAccessory
屬性包含物件的集合 HMService
,這些物件會定義裝置所提供的服務。
服務是燈光、控溫器、車庫門打開器、開關或鎖等專案。 一些設備(如車庫門打開器)將提供一項以上的服務,例如燈光和打開或關閉門的能力。
除了指定配件提供的特定服務之外,每個配件都包含 Information Service
定義其名稱、製造商、型號和序號等屬性的 。
配件服務類型
下列服務類型可透過 HMServiceType
列舉取得:
- AccessoryInformation - 提供指定家庭自動化裝置的相關信息(配件)。
- AirQualitySensor - 定義空氣質量感測器。
- 電池 - 定義配件電池的狀態。
- CarbonDioxideSensor - 定義二氧化碳感測器。
- CarbonMonoxideSensor - 定義一氧化碳感測器。
- ContactSensor - 定義聯繫人感測器(例如開啟或關閉的視窗)。
- Door - 定義門狀態感測器(例如已開啟或關閉)。
- 風扇 - 定義遠端控制風扇。
- GarageDoorOpener - 定義車庫門開啟器。
- HumiditySensor - 定義濕度感測器。
- LeakSensor - 定義洩漏感測器(例如熱水器或洗衣機)。
- LightBulb - 定義獨立光線或屬於另一個配件的光線(如車庫門打開器)。
- LightSensor - 定義光線感測器。
- LockManagement - 定義管理自動化門鎖的服務。
- LockMechanism - 定義遙控器鎖定(如門鎖)。
- MotionSensor - 定義動作感測器。
- OccupancySensor - 定義佔用感測器。
- 輸出 -定義遠端控制牆出口。
- SecuritySystem - 定義家庭安全性系統。
- StatefulProgrammableSwitch - 定義可程式化開關,在觸發後仍處於指定狀態(例如翻轉開關)。
- StatelessProgrammableSwitch - 定義可程式化參數,在觸發後返回其初始狀態(例如按下按鈕)。
- SmokeSensor - 定義煙霧感測器。
- Switch - 定義開啟/關閉開關,例如標準牆開關。
- TemperatureSensor - 定義溫度感測器。
- 控溫器 - 定義用來控制 HVAC 系統的智慧控溫器。
- 視窗 - 定義可遠端開啟或關閉的自動化視窗。
- WindowCovering - 定義遠端控制的視窗範圍,例如可以開啟或關閉的盲人。
顯示服務資訊
載入 HMAccessory
之後,您可以查詢它所提供的個別 HNService
物件,並將該資訊顯示給使用者:
您應該一律先檢查 Reachable
的 HMAccessory
屬性,再嘗試使用。 無法連線到配件,使用者不在裝置範圍內,或已取消連結。
選取服務之後,使用者可以檢視或修改該服務的一或多個特性,以監視或控制指定的家庭自動化裝置。
使用特性
每個 HMService
物件都可以包含物件的集合 HMCharacteristic
,這些物件可以提供有關服務狀態的資訊(例如開啟或關閉的門),或允許使用者調整狀態(例如設定光線的色彩)。
HMCharacteristic
不僅提供特性及其狀態的相關信息,也提供透過特性元數據 (HMCharacteristisMetadata
) 處理狀態的方法。 此元數據可以提供屬性(例如最小和最大值範圍),在向使用者顯示資訊或允許它們修改狀態時很有用。
HMCharacteristicType
列舉提供一組特性元數據值,可定義或修改,如下所示:
- 管理員 OnlyAccess
- AirParticulateDensity
- AirParticulateSize
- AirQuality
- AudioFeedback
- BatteryLevel
- 亮度
- CarbonDioxideDetected
- CarbonDioxideLevel
- CarbonDioxidePeakLevel
- CarbonMonoxideDetected
- CarbonMonoxideLevel
- CarbonMonoxidePeakLevel
- ChargingState
- ContactState
- CoolingThreshold
- CurrentDoorState
- CurrentHeatingCooling
- CurrentHorizontalTilt
- CurrentLightLevel
- CurrentLockMechanismState
- CurrentPosition
- CurrentRelativeHumidity
- CurrentSecuritySystemState
- CurrentTemperature
- CurrentVerticalTilt
- FirmwareVersion
- HardwareVersion
- HeatingCoolingStatus
- HeatingThreshold
- HoldPosition
- Hue
- 確定
- InputEvent
- LeakDetected
- LockManagementAutoSecureTimeout
- LockManagementControlPoint
- LockMechanismLastKnownAction
- 記錄
- 製造商
- 模型
- MotionDetected
- 名稱
- ObstructionDetected
- OccupancyDetected
- OutletInUse
- OutputState
- PositionState
- PowerState
- RotationDirection
- RotationSpeed
- 飽和度
- SerialNumber
- SmokeDetected
- SoftwareVersion
- StatusActive
- StatusFault
- StatusJammed
- StatusLowBattery
- StatusTampered
- TargetDoorState
- TargetHeatingCooling
- TargetHorizontalTilt
- TargetLockMechanismState
- TargetPosition
- TargetRelativeHumidity
- TargetSecuritySystemState
- TargetTemperature
- TargetVerticalTilt
- TemperatureUnits
- 版本
使用特性的值
為了確保您的應用程式具有指定特性的最新狀態,請呼叫 ReadValue
類別的 HMCharacteristic
方法。 err
如果屬性不是 null
,就會發生錯誤,而且可能會或可能不會向用戶顯示錯誤。
Characteristic 的 Value
屬性包含指定特性的目前狀態做為 NSObject
,因此無法在 C# 中直接使用 。
若要讀取值,下列協助程序類別已新增至 HomeKitIntro 範例應用程式:
using System;
using Foundation;
using System.Globalization;
using CoreGraphics;
namespace HomeKitIntro
{
/// <summary>
/// NS object converter is a helper class that helps to convert NSObjects into
/// C# objects
/// </summary>
public static class NSObjectConverter
{
#region Static Methods
/// <summary>
/// Converts to an object.
/// </summary>
/// <returns>The object.</returns>
/// <param name="nsO">Ns o.</param>
/// <param name="targetType">Target type.</param>
public static Object ToObject (NSObject nsO, Type targetType)
{
if (nsO is NSString) {
return nsO.ToString ();
}
if (nsO is NSDate) {
var nsDate = (NSDate)nsO;
return DateTime.SpecifyKind ((DateTime)nsDate, DateTimeKind.Unspecified);
}
if (nsO is NSDecimalNumber) {
return decimal.Parse (nsO.ToString (), CultureInfo.InvariantCulture);
}
if (nsO is NSNumber) {
var x = (NSNumber)nsO;
switch (Type.GetTypeCode (targetType)) {
case TypeCode.Boolean:
return x.BoolValue;
case TypeCode.Char:
return Convert.ToChar (x.ByteValue);
case TypeCode.SByte:
return x.SByteValue;
case TypeCode.Byte:
return x.ByteValue;
case TypeCode.Int16:
return x.Int16Value;
case TypeCode.UInt16:
return x.UInt16Value;
case TypeCode.Int32:
return x.Int32Value;
case TypeCode.UInt32:
return x.UInt32Value;
case TypeCode.Int64:
return x.Int64Value;
case TypeCode.UInt64:
return x.UInt64Value;
case TypeCode.Single:
return x.FloatValue;
case TypeCode.Double:
return x.DoubleValue;
}
}
if (nsO is NSValue) {
var v = (NSValue)nsO;
if (targetType == typeof(IntPtr)) {
return v.PointerValue;
}
if (targetType == typeof(CGSize)) {
return v.SizeFValue;
}
if (targetType == typeof(CGRect)) {
return v.RectangleFValue;
}
if (targetType == typeof(CGPoint)) {
return v.PointFValue;
}
}
return nsO;
}
/// <summary>
/// Convert to string
/// </summary>
/// <returns>The string.</returns>
/// <param name="nsO">Ns o.</param>
public static string ToString(NSObject nsO) {
return (string)ToObject (nsO, typeof(string));
}
/// <summary>
/// Convert to date time
/// </summary>
/// <returns>The date time.</returns>
/// <param name="nsO">Ns o.</param>
public static DateTime ToDateTime(NSObject nsO){
return (DateTime)ToObject (nsO, typeof(DateTime));
}
/// <summary>
/// Convert to decimal number
/// </summary>
/// <returns>The decimal.</returns>
/// <param name="nsO">Ns o.</param>
public static decimal ToDecimal(NSObject nsO){
return (decimal)ToObject (nsO, typeof(decimal));
}
/// <summary>
/// Convert to boolean
/// </summary>
/// <returns><c>true</c>, if bool was toed, <c>false</c> otherwise.</returns>
/// <param name="nsO">Ns o.</param>
public static bool ToBool(NSObject nsO){
return (bool)ToObject (nsO, typeof(bool));
}
/// <summary>
/// Convert to character
/// </summary>
/// <returns>The char.</returns>
/// <param name="nsO">Ns o.</param>
public static char ToChar(NSObject nsO){
return (char)ToObject (nsO, typeof(char));
}
/// <summary>
/// Convert to integer
/// </summary>
/// <returns>The int.</returns>
/// <param name="nsO">Ns o.</param>
public static int ToInt(NSObject nsO){
return (int)ToObject (nsO, typeof(int));
}
/// <summary>
/// Convert to float
/// </summary>
/// <returns>The float.</returns>
/// <param name="nsO">Ns o.</param>
public static float ToFloat(NSObject nsO){
return (float)ToObject (nsO, typeof(float));
}
/// <summary>
/// Converts to double
/// </summary>
/// <returns>The double.</returns>
/// <param name="nsO">Ns o.</param>
public static double ToDouble(NSObject nsO){
return (double)ToObject (nsO, typeof(double));
}
#endregion
}
}
NSObjectConverter
每當應用程式需要讀取特性的目前狀態時,就會使用 。 例如:
var value = NSObjectConverter.ToFloat (characteristic.Value);
上述這一行會將值 float
轉換成 ,然後可用於 Xamarin C# 程式代碼。
若要修改 HMCharacteristic
,請呼叫其 WriteValue
方法,並將新值包裝在呼叫中 NSObject.FromObject
。 例如:
Characteristic.WriteValue(NSObject.FromObject(value),(err) =>{
// Was there an error?
if (err!=null) {
// Yes, inform user
AlertView.PresentOKAlert("Update Error",err.LocalizedDescription,Controller);
}
});
err
如果屬性不是 null
,就會發生錯誤,而且應該向用戶呈現。
測試特性值變更
使用 HMCharacteristics
和 模擬配件時,可以在 HomeKit 配件模擬器內監視對 屬性的修改 Value
。
在 實際 iOS 裝置硬體上執行的 HomeKitIntro 應用程式時,應該幾乎會在 HomeKit 配件模擬器中看到特性值的變更。 例如,變更 iOS 應用程式中光線的狀態:
應該變更 HomeKit 配件模擬器中光線的狀態。 如果值沒有變更,請在撰寫新的特性值時檢查錯誤訊息的狀態,並確定配件仍可連線。
進階 HomeKit 功能
本文涵蓋在 Xamarin.iOS 應用程式中使用 HomeKit 配件所需的基本功能。 不過,此簡介並未涵蓋 HomeKit 的數個進階功能:
- 會議室 - 已啟用 HomeKit 的配件可選擇性地由用戶組織成會議室。 這可讓 HomeKit 以方便使用者瞭解及使用的方式呈現配件。 如需建立和維護會議室的詳細資訊,請參閱Apple的 HMRoom 檔。
- 區域 - 使用者可以選擇性地將會議室組織成區域。 區域是指使用者可能視為單一單位的會議室集合。 例如:樓上、樓下或地下室。 同樣地,這可讓 HomeKit 以對終端使用者有意義的方式呈現及處理配件。 如需建立和維護區域的詳細資訊,請參閱 Apple 的 HMZone 檔。
- 動作和動作集 - 動作會修改配件服務特性,並可分組成集合。 動作集可做為腳本來控制一組配件並協調其動作。 例如,「看電視」腳本可能會關閉盲目、變暗燈光,以及開啟電視及其音效系統。 如需建立和維護動作和動作集的詳細資訊,請參閱Apple的 HMAction 和 HMActionSet 檔。
- 觸發程式 - 當符合一組指定條件時,觸發程式可以啟動一或多個動作集。 例如,開啟埠燈,並在外部變暗時鎖定所有外部門。 如需建立和維護觸發程式的詳細資訊,請參閱Apple的 HMTrigger 檔。
由於這些功能使用相同的技術,因此應該遵循 Apple 的 HomeKitDeveloper 指南、 HomeKit 使用者介面指導方針 和 HomeKit Framework 參考,輕鬆地實作這些功能。
HomeKit 應用程式檢閱指導方針
將已啟用 HomeKit 的 Xamarin.iOS 應用程式提交至 iTunes 連線,以在 iTunes App Store 中發行之前,請確定您遵循已啟用 HomeKit 之應用程式的 Apple 指導方針:
- 如果使用 HomeKit 架構,應用程式的主要用途 必須是 家庭自動化。
- 應用程式的行銷文字必須通知使用者使用 HomeKit,而且必須提供隱私策略。
- 禁止收集使用者資訊或使用 HomeKit 進行廣告。
如需完整的檢閱指導方針,請參閱 Apple 的 App Store 評論指導方針。
iOS 9 的新功能
Apple 已對適用於 iOS 9 的 HomeKit 進行下列變更和新增:
- 維護現有物件 - 如果修改現有的配件,Home Manager (
HMHomeManager
) 會通知您修改的特定專案。 - 持續性標識碼 - 所有相關的 HomeKit 類別現在包含
UniqueIdentifier
屬性,可跨已啟用 HomeKit 的應用程式(或相同應用程式的實例)唯一識別指定的專案。 - 使用者管理 - 已新增內建檢視控制器,以提供使用者管理,讓用戶能夠存取主要使用者家中的 HomeKit 裝置。
- 使用者功能 - HomeKit 使用者現在擁有一組許可權,可控制他們在 HomeKit 和 HomeKit 啟用配件中使用的功能。 您的應用程式應該只會向目前用戶顯示相關功能。 例如,只有系統管理員才能夠維護其他使用者。
- 預先定義的場景 - 已針對平均 HomeKit 用戶發生的四個常見事件建立預先定義的場景 :上車、離開、返回、上床。 無法從家裡刪除這些預先定義的場景。
- 場景和 Siri - Siri 對 iOS 9 中的場景有更深入的支援,並可辨識 HomeKit 中定義的任何場景名稱。 使用者只要向 Siri 說出其名稱即可執行場景。
- 配件類別 - 已將一組預先定義的類別 新增至所有配件,並協助識別要新增至家用或從應用程式內處理之配件的類型。 這些新類別可在配件安裝期間使用。
- Apple Watch 支援 - HomeKit 現已可供 watchOS 使用,Apple Watch 將能夠控制已啟用 HomeKit 的裝置,而沒有 i 電話 靠近手錶。 適用於 watchOS 的 HomeKit 支援下列功能:檢視家庭、控制配件和執行場景。
- 新的事件觸發程式類型 - 除了 iOS 8 中支援的定時器類型觸發程式之外,iOS 9 現在還支援以存取狀態(例如感測器數據)或地理位置為基礎的事件觸發程式。 事件觸發程式會使用
NSPredicates
來設定其執行的條件。 - 遠端存取 - 使用遠端訪問時,當使用者離開位於遠端位置的家時,現在可以控制其 HomeKit 已啟用家用自動化配件。 在 iOS 8 中,只有當使用者在家裡有第三代 Apple TV 時,才支援此功能。 在 iOS 9 中,會隨即解除這項限制,並透過 iCloud 和 HomeKit 存取協定 (HAP) 支援遠端訪問。
- 新的 藍牙 低能(BLE)能力 - HomeKit 現在支援更多的配件類型,可以透過 藍牙 低能(BLE)通訊協議進行通訊。 使用 HAP 安全通道,HomeKit Accessory 可以透過Wi-Fi公開另一個 藍牙 配件(如果超出 藍牙 範圍)。 在 iOS 9 中,BLE 配件已完整支援通知和元數據。
- 新的配件類別 - Apple 在 iOS 9 中新增了下列新的配件類別 :視窗涵蓋範圍、機動式門和 Windows、警示系統、感測器和可程式化開關。
如需 iOS 9 中 HomeKit 新功能的詳細資訊,請參閱 Apple 的 HomeKit 索引 和 HomeKit 的新功能影片。
摘要
本文介紹Apple的HomeKit家用自動化架構。 它示範如何使用 HomeKit 存取模擬器來設定測試裝置,以及如何建立簡單的 Xamarin.iOS 應用程式,以使用 HomeKit 探索、通訊及控制家庭自動化裝置。