Xamarin.iOS の HomeKit
HomeKit は、ホーム オートメーション デバイスを制御するための Apple のフレームワークです。 この記事では、HomeKit について説明し、HomeKit アクセサリ シミュレーターでテスト アクセサリを構成し、これらのアクセサリと対話するための単純な Xamarin.iOS アプリを記述する方法について説明します。
Apple は、さまざまなベンダーの複数のホーム オートメーション デバイスを 1 つのコヒーレント ユニットにシームレスに統合する方法として、iOS 8 で HomeKit を導入しました。 HomeKit は、ホーム オートメーション デバイスを検出、構成、制御するための共通プロトコルを推進することで、関連のないベンダーのデバイスが連携して作業できるようにします。個々のベンダーが作業を調整する必要はありません。
HomeKit を使用すると、ベンダーが提供する API やアプリを使用せずに、HomeKit 対応デバイスを制御する Xamarin.iOS アプリを作成できます。 HomeKit を使用すると、次の操作を行うことができます:
- 新しい HomeKit 対応ホーム オートメーション デバイスを検出し、ユーザーのすべての iOS デバイスにわたって保持されるデータベースに追加します。
- HomeKit Home Configuration Database 内の任意のデバイスをセットアップ、構成、表示、および制御します。
- 事前に構成された HomeKit デバイスと通信し、個々のアクションを実行したり、キッチン内のすべての照明をオンにするなど、連携して作業するように命令します。
HomeKit 対応アプリにホーム構成データベースのデバイスを提供するだけでなく、HomeKit は Siri 音声コマンドへのアクセスを提供します。 適切に構成された HomeKit セットアップを使用すると、ユーザーは "Siri、リビングルームの照明をオンにして" などの音声コマンドを発行できます。
ホーム構成データベース
HomeKit は、特定の場所にあるすべてのオートメーション デバイスをホーム コレクションに整理します。 このコレクションは、ユーザーが、意味のある人間が判読できるラベルを持つ論理的に配置されたユニットにホーム オートメーション デバイスをグループ化する方法を提供します。
ホーム コレクションはホーム構成データベースに格納され、ユーザーのすべての iOS デバイス間で自動的にバックアップおよび同期されます。 HomeKit には、ホーム構成データベースを操作するための次のクラスが用意されています:
HMHome
- これは、すべてのホーム オートメーション デバイスのすべての情報と構成を 1 つの物理的な場所 (単一の家族の住居など) に保持する最上位のコンテナーです。 ユーザーには、メインの家や別荘など、複数の住居がある可能性があります。 または、メインの家やガレージの上のゲストハウスなど、同じ物件に異なる「家」を持っているかもしれません。 いずれの場合も、他の HomeKit 情報を入力前に、少なくとも 1 つのHMHome
オブジェクトをセットアップして格納する必要があります。HMRoom
- オプションですが、HMRoom
を使用すると、キッチン、バスルーム、ガレージ、リビングルームなど、家庭内の特定の部屋 (HMHome
) を定義できます。 ユーザーは、自宅の特定の場所にあるすべてのホーム オートメーション デバイスをHMRoom
にグループ化し、それらを 1 つのユニットとして操作できます。 たとえば、Siri にガレージ照明の電源を切るように依頼できます。HMAccessory
- これは、ユーザーの家にインストールされている、個々の物理 HomeKit 対応オートメーション デバイス (スマート サーモスタットなど) を表します。 各HMAccessory
は、HMRoom
に割り当てられます。 ユーザーが部屋を構成していない場合、HomeKit は特別な既定の部屋にアクセサリを割り当てます。HMService
- 照明のオン/オフ状態やその色 (色の変更がサポートされている場合) など、特定のHMAccessory
によって提供されるサービスを表します。 各HMAccessory
は、照明を含むガレージ ドアの開閉器など、複数のサービスを持つことができます。 さらに、特定のHMAccessory
には、ファームウェアの更新などのユーザーの制御下にないサービスが含まれる場合があります。HMZone
- ユーザーがHMRoom
オブジェクトのコレクションを論理ゾーン (上階、階下、地下など) にグループ化できるようにします。 オプションですが、これにより、Siri にすべての照明の階下をオフにするように求めるなどの操作が可能になります。
HomeKit アプリのプロビジョニング
HomeKit によって課されるセキュリティ要件のため、HomeKit フレームワークを使用する Xamarin.iOS アプリは、Apple Developer ポータルと Xamarin.iOS プロジェクト ファイルの両方で適切に構成する必要があります。
次の操作を行います。
Apple Developer ポータルにログインします。
[証明書、識別子、プロファイル] をクリックします。
まだ行っていない場合は、[識別子] をクリックし、アプリの ID (
com.company.appname
など) を作成します。それ以外の場合は、既存の ID を編集します。HomeKit サービスで、指定された ID がチェックされていることを確認します:
変更を保存。
[プロビジョニング プロファイル]>[開発] をクリックし、アプリ用の新しい開発プロビジョニング プロファイルを作成します:
新しいプロビジョニング プロファイルをダウンロードしてインストールするか、Xcode を使用してプロファイルをダウンロードしてインストールします。
Xamarin.iOS プロジェクト オプションを編集し、先ほど作成したプロビジョニング プロファイルを使用していることを確認します:
次に、Info.plist ファイルを編集し、プロビジョニング プロファイルの作成に使用したアプリ ID を使用していることを確認します:
最後に、Entitlements.plist ファイルを編集し、HomeKit エンタイトルメントが選択されていることを確認します:
変更をすべてのファイルに保存します。
これらの設定を設定すると、アプリケーションは HomeKit Framework API にアクセスする準備が整いました。 プロビジョニングの詳細については、「デバイス プロビジョニング」ガイド と「アプリのプロビジョニング」ガイドを参照してください。
重要
HomeKit 対応アプリをテストするには、開発用に適切にプロビジョニングされた実際の iOS デバイスが必要です。 iOS シミュレーターから HomeKit をテストすることはできません。
HomeKit アクセサリ シミュレーター
物理デバイスを持たずに、可能なすべてのホームオートメーションデバイスとサービスをテストする方法を提供するために、Appleは HomeKit アクセサリ シミュレーターを作成しました。 このシミュレーターを使用すると、仮想 HomeKit デバイスをセットアップおよび構成できます。
シミュレーターのインストール
Apple は Xcode とは別のダウンロードとして HomeKit アクセサリ シミュレーターを提供しているため、続行する前にこれをインストールする必要があります。
次の操作を行います。
Web ブラウザーで、Apple Developer 向けダウンロード
Xcode 用 追加ツール xxx をダウンロードします (xxx は、インストールした Xcode のバージョンです):
ディスク イメージを開き、Applications ディレクトリにツールをインストールします。
HomeKit アクセサリ シミュレーターをインストールすると、テスト用に仮想アクセサリを作成できます。
仮想アクセサリの作成
HomeKit アクセサリ シミュレーターを起動し、いくつかの仮想アクセサリを作成するには、次の操作を行います:
Applications フォルダーから、HomeKit アクセサリ シミュレーターを起動します:
[+] ボタンをクリックし、[新しいアクセサリ...] を選択します:
新しいアクセサリに関する情報を入力し、[完了] ボタンをクリックします:
[サービスの追加...] ボタンをクリックし、し、ドロップダウンからサービスの種類を選択します:
サービスの名前を指定し、[完了] ボタンをクリックします:
[特性の追加] ボタンをクリックし、必要な設定を構成することで、サービスにオプションの特性を指定できます:
上記の手順を繰り返して、HomeKit がサポートする仮想ホーム オートメーション デバイスの種類ごとに 1 つを作成します。
いくつかのサンプルの仮想 HomeKit アクセサリを作成して構成すると、Xamarin.iOS アプリからこれらのデバイスを使用して制御できるようになりました。
Info.plist ファイルの構成
iOS 10 以降の新機能である開発者は、アプリの Info.plist
ファイルに NSHomeKitUsageDescription
キーを追加し、アプリがユーザーの HomeKit データベースにアクセスする理由を宣言する文字列を提供する必要があります。 この文字列は、アプリを初めて実行するとユーザーに表示されます:
このキーを設定するには、以下の操作を行います:
ソリューション エクスプローラーで
Info.plist
ファイルをダブルクリックして、編集用に開きます。画面の下部にあるソース ビューに切り替えます。
新しいエントリを一覧に追加します。
ドロップダウン リストから、[プライバシー - HomeKit の使用状況の説明] を選択します:
アプリがユーザーの HomeKit データベースにアクセスする理由の説明を入力します:
変更をファイルに保存します。
重要
Info.plist
ファイルで NSHomeKitUsageDescription
キーを設定しないと、iOS 10 (またはそれ以降) で実行すると、アプリは、エラーなしで (実行時にシステムによって閉じられている) がサイレントに失敗します。
HomeKit への接続
HomeKit と通信するには、Xamarin.iOS アプリで最初に HMHomeManager
クラスのインスタンスをインスタンス化する必要があります。 ホーム マネージャーは、HomeKit の中心的なエントリ ポイントであり、利用可能な家の一覧を提供し、そのリストを更新して維持し、ユーザーのプライマリ ホームを返す役割を担います。
HMHome
オブジェクトには、すべての部屋、グループ、またはゾーンを含む、家に関するすべての情報と、インストールされているホーム オートメーション アクセサリが含まれます。 HomeKit で操作を実行するには、少なくとも 1 つの HMHome
を作成し、プライマリ ホームとして割り当てる必要があります。
アプリは、プライマリ ホームが存在するかどうかを確認し、存在しない場合は作成して割り当てる役割を担います。
ホーム マネージャーの追加
Xamarin.iOS アプリに HomeKit 認識を追加するには、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 情報へのアクセスを許可するかどうかを確認するメッセージが表示されます:
ユーザーが "OK" と答えた場合、アプリケーションは HomeKit アクセサリを操作できるようになります。そうしないと、HomeKit への呼び出しはエラーで失敗します。
ホーム マネージャーを配置したら、次にアプリケーションでプライマリ ホームが構成されているかどうかを確認する必要があります。構成されていない場合は、ユーザーがホームを作成して割り当てる方法を提供します。
プライマリ ホームへのアクセス
前述のように、HomeKit を使用する前にプライマリ ホームを作成して構成する必要があります。また、プライマリ ホームがまだ存在しない場合は、ユーザーがプライマリ ホームを作成して割り当てる方法を提供するのはアプリ側の責任です。
アプリが最初に起動またはバックグラウンドから戻るときに、プライマリ ホームの存在を確認するには、HMHomeManager
クラスの DidUpdateHomes
イベントを監視する必要があります。 存在しない場合は、ユーザーがインターフェイスを作成するためのインターフェイスを提供する必要があります。
次のコードをビュー コントローラーに追加して、プライマリ ホームを確認できます:
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);
}
};
ホーム マネージャーが HomeKit に接続すると、DidUpdateHomes
イベントが発生し、既存の家がマネージャーの家のコレクションに読み込まれ、プライマリ ホームが読み込まれます (使用可能な場合)。
プライマリ ホームの追加
HMHomeManager
の PrimaryHome
プロパティが DidUpdateHomes
イベントの後に null
である場合は、続行する前にプライマリ ホームを作成して割り当てる方法をユーザーに提供する必要があります。
通常、アプリはユーザーが新しいホームに名前を付けるフォームを表示し、ホーム マネージャーに渡してプライマリ ホームとしてセットアップします。 HomeKitIntro サンプル アプリの場合、Xcode Interface Builder でモーダル ビューが作成され、アプリのメイン インターフェイスから AddHomeSegue
セグエによって呼び出されました。
ユーザーが新しいホームの名前を入力するためのテキスト フィールドと、ホームを追加するボタンが提供されます。 ユーザーが [ホームの追加] ボタンをタップすると、次のコードによってホーム マネージャーが呼び出され、ホームが追加されます:
// 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
でない場合は、すsラーが発生しており、ユーザーに表示する必要があります。 最も一般的なエラーは、一意でないホーム名またはホーム マネージャーが HomeKit と通信できないことが原因で発生します。
ホームが正常に作成された場合は、UpdatePrimaryHome
メソッドを呼び出して、新しいホームをプライマリ ホームとして設定する必要があります。 ここでも、error
プロパティが null
でない場合は、エラーが発生しており、ユーザーに表示する必要があります。
また、ホーム マネージャーの DidAddHome
と DidRemoveHome
イベントを監視し、必要に応じてアプリのユーザー インターフェイスを更新する必要があります。
重要
上記のサンプル コードで使用されている AlertView.PresentOKAlert
メソッドは、iOS アラートの操作を容易にする HomeKitIntro アプリケーションのヘルパー クラスです。
新しいアクセサリの検索
プライマリ ホームがホーム マネージャーで定義または読み込まれたら、Xamarin.iOS アプリで HMAccessoryBrowser
を呼び出して、新しいホーム オートメーション アクセサリを検索し、ホームに追加できます。
StartSearchingForNewAccessories
メソッドを呼び出して、新しいアクセサリの検索を開始し、完了したら StopSearchingForNewAccessories
メソッドを呼び出します。
重要
StartSearchingForNewAccessories
は、iOS デバイスのバッテリ寿命とパフォーマンスの両方に悪影響を及ぼすため、長時間実行したままにしないでください。 Apple は、1 分後に StopSearchingForNewAccessories
を呼び出すか、アクセサリの検索 UI がユーザーに表示された場合にのみ検索することを提案しています。
DidFindNewAccessory
イベントは、新しいアクセサリが検出されると呼び出され、アクセサリ ブラウザーの DiscoveredAccessories
リストに追加されます。
DiscoveredAccessories
リストには、特定の HomeKit 対応ホーム オートメーション デバイスとその使用可能なサービス (照明やガレージ ドア コントロールなど) を定義する HMAccessory
オブジェクトのコレクションが含まれます。
新しいアクセサリが見つかったら、それをユーザーに提示し、それを選択してホームに追加できるようにします。 例:
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 アクセサリの場合、セットアップ コードは、デバイス自体のラベル、製品ボックス、またはアクセサリのユーザー マニュアルに印刷されます。
アクセサリ ブラウザーの DidRemoveNewAccessory
イベントを監視し、ユーザーがホーム コレクションに追加したアクセサリを使用可能なリストから削除するようにユーザー インターフェイスを更新する必要があります。
アクセサリの操作
プライマリ ホームが確立され、アクセサリが追加されたら、ユーザーが操作できるアクセサリ (および必要に応じて部屋) の一覧を表示できます。
HMRoom
オブジェクトには、特定の部屋とその部屋に属するすべてのアクセサリに関するすべての情報が含まれます。 必要に応じて、部屋を 1 つ以上のゾーンに編成できます。 HMZone
には、特定のゾーンとそのゾーンに属するすべての部屋に関するすべての情報が含まれます。
この例では、部屋やゾーンに整理するのではなく、シンプルに保ち、ホームのアクセサリーを直接操作します。
HMHome
オブジェクトには、Accessories
プロパティでユーザーに表示できる割り当てられたアクセサリの一覧が含まれています。 次に例を示します。
ここからユーザーは特定のアクセサリを選択し、提供するサービスを操作できます。
サービスの操作
ユーザーが特定の HomeKit 対応ホーム オートメーション デバイスと対話する場合、通常は、提供されるサービスを通じて行われます。 HMAccessory
クラスの Services
プロパティには、デバイスが提供するサービスを定義する HMService
オブジェクトのコレクションが含まれています。
サービスは、照明、サーモスタット、ガレージ ドア開閉器、スイッチ、ロックのようなものです。 一部のデバイス (ガレージ ドア開閉器など) は、照明やドアを開閉する機能など、複数のサービスを提供します。
特定のアクセサリが提供する特定のサービスに加えて、各アクセサリには、その名前、製造元、モデル、シリアル番号などのプロパティを定義する Information Service
が含まれています。
アクセサリ サービスの種類
HMServiceType
列挙型では、次のサービスの種類を使用できます:
- AccessoryInformation - 特定のホーム オートメーション デバイス (アクセサリ) に関する情報を提供します。
- AirQualitySensor - 空気品質センサーを定義します。
- Battery - アクセサリのバッテリの状態を定義します。
- CarbonDioxideSensor - 二酸化炭素センサーを定義します。
- CarbonMonoxideSensor - 一酸化炭素センサーを定義します。
- ContactSensor - 連絡先センサー (窓の開閉など) を定義します。
- Door - ドア状態センサー (開閉など) を定義します。
- Fan - リモート制御ファンを定義します。
- GarageDoorOpener - ガレージ ドア開閉器を定義します。
- HumiditySensor - 湿度センサーを定義します。
- LeakSensor - リーク センサー (温水ヒーターや洗濯機など) を定義します。
- LightBulb - スタンド アロンの照明または別のアクセサリの一部である照明 (ガレージ ドア開閉器など) を定義します。
- LightSensor - 照明センサーを定義します。
- LockManagement - 自動ドア ロックを管理するサービスを定義します。
- LockMechanism - リモート制御ロック (ドア ロックなど) を定義します。
- MotionSensor - モーション センサーを定義します。
- OccupancySensor - 占有率センサーを定義します。
- Outlet - リモコン制御された壁コンセントを定義します。
- SecuritySystem - ホーム セキュリティ システムを定義します。
- StatefulProgrammableSwitch - (フリップ スイッチなど) トリガーされると、特定の状態のままであるプログラマブル スイッチを定義します。
- StatelessProgrammableSwitch - (プッシュ ボタンなど) トリガーされた後に初期状態に戻るプログラム可能なスイッチを定義します。
- SmokeSensor - 煙センサーを定義します。
- Switch - 標準の壁スイッチのようなオン/オフ スイッチを定義します。
- TemperatureSensor - 温度センサーを定義します。
- Thermostat - HVAC システムを制御するために使用されるスマート サーモスタットを定義します。
- Window - リモートで開けたり閉じたりできる自動窓を定義します。
- WindowCovering - 開いたり閉じたりできるブラインドなど、リモートで制御されるウィンドウ カバーを定義します。
サービス情報の表示
HMAccessory
を読み込んだ後、提供される個々の HNService
オブジェクトに対してクエリを実行し、その情報をユーザーに表示できます:
操作を試みる前に、常に HMAccessory
の Reachable
プロパティを確認する必要があります。 アクセサリは、ユーザーがデバイスの範囲内にいないか、取り外された場合に到達できない可能性があります。
サービスを選択すると、ユーザーはそのサービスの 1 つ以上の特性を表示または変更して、特定のホーム オートメーション デバイスを監視または制御できます。
特性の操作
各 HMService
オブジェクトには、サービスの状態に関する情報 (ドアが開いているか閉じているかなど) に関する情報を提供したり、ユーザーが状態を調整したり (光の色の設定など)、HMCharacteristic
オブジェクトのコレクションを含めることができます。
HMCharacteristic
は、特性とその状態に関する情報を提供するだけでなく、特性メタデータ (HMCharacteristisMetadata
) を使用して状態を操作する方法も提供します。 このメタデータは、ユーザーに情報を表示したり、状態を変更したりするときに役立つプロパティ (最小値や最大値の範囲など) を提供できます。
HMCharacteristicType
列挙型は、次のように定義または変更できる一連の特性メタデータ値を提供します:
- AdminOnlyAccess
- 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
- ソフトウェア バージョン
- StatusActive
- StatusFault
- StatusJammed
- StatusLowBattery
- StatusTampered
- TargetDoorState
- TargetHeatingCooling
- TargetHorizontalTilt
- TargetLockMechanismState
- TargetPosition
- TargetRelativeHumidity
- TargetSecuritySystemState
- TargetTemperature
- TargetVerticalTilt
- TemperatureUnits
- バージョン
特性の値の操作
アプリが特定の特性の最新の状態であることを確認するには、HMCharacteristic
クラスの ReadValue
メソッドを呼び出します。 err
プロパティが null
でない場合は、エラーが発生しており、ユーザーに表示される場合と表示されない場合があります。
特性の 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);
上記の行は、値を Xamarin C# コードで使用できる float
に変換します。
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
およびシミュレートされたアクセサリを使用する場合、Value
プロパティの変更を HomeKit アクセサリ シミュレーター内で監視できます。
HomeKitIntro アプリが実際の iOS デバイス ハードウェアで実行されている場合、HomeKit アクセサリ シミュレーターで特性の値の変更がほぼ瞬時に表示されます。 たとえば、iOS アプリで照明の状態を変更するとします:
HomeKit アクセサリ シミュレーターの照明の状態を変更する必要があります。 値が変更されない場合は、新しい特性値を書き込むときにエラー メッセージの状態を確認し、アクセサリに到達できることを確認します。
HomeKit の高度な機能
この記事では、Xamarin.iOS アプリで HomeKit アクセサリを操作するために必要な基本的な機能について説明しました。 ただし、HomeKit には、この概要では説明されていない高度な機能がいくつかあります:
- Rooms - HomeKit 対応アクセサリは、必要に応じてエンド ユーザーがルームに編成できます。 これにより、HomeKit では、ユーザーが簡単に理解して操作できる方法でアクセサリが提示できます。 ルームの作成と保守の詳細については、Apple の HMRoom ドキュメントを参照してください。
- Zone - エンドユーザーは、必要に応じてルームをゾーンに編成できます。 ゾーンとは、ユーザーが 1 つのユニットとして扱う可能性がある部屋のコレクションを指します。 たとえば、上階、階下、地下などです。 ここでも、HomeKit はエンド ユーザーに理にかなった方法でアクセサリを提示して操作できます。 ゾーンの作成と保守の詳細については、Apple の HMZone に関するドキュメントを参照してください。
- アクションとアクション セット - アクションはアクセサリ サービスの特性を変更し、セットにグループ化できます。 アクション セットは、アクセサリのグループを制御し、アクションを調整するためのスクリプトとして機能します。 たとえば、"テレビの視聴" スクリプトは、ブラインドを閉じてライトを暗くし、テレビとそのサウンド システムをオンにするでしょう。 アクションとアクション セットの作成と保守の詳細については、Apple の HMAction および HMActionSet に関するドキュメントを参照してください。
- Trigger - トリガーは、特定の条件セットが満たされたときに、1 つ以上のアクション セットをアクティブ化できます。 たとえば、外が暗くなったら、玄関灯を点灯して、すべての外部ドアをロックします。 トリガーの作成と保守の詳細については、Apple の HMTrigger に関するドキュメントを参照してください。
これらの機能は上記と同じ手法を使用するため、Apple の「HomeKitDeveloper ガイド」、「HomeKit ユーザー インターフェイス ガイドライン」、「HomeKit フレームワーク リファレンス」に従って簡単に実装できるようにする必要があります。
HomeKit アプリ レビュー ガイドライン
iTunes App Store でリリースするために HomeKit 対応 Xamarin.iOS アプリを iTunes Connect に提出する前に、HomeKit 対応アプリに関する Apple のガイドラインに従っていることを確認してください:
- HomeKit フレームワークを使用する場合、アプリの主な目的はホーム オートメーションである必要があります。
- アプリのマーケティング テキストは、HomeKit が使用されていることをユーザーに通知し、プライバシー ポリシーを提供する必要があります。
- ユーザー情報を収集したり、広告のために HomeKit を使用したりすることは固く禁じられています。
完全なレビュー ガイドラインについては、Apple の「App Store レビュー ガイドライン」を参照してください。
iOS 9 の新機能
Apple は、iOS 9 用 HomeKit に次の変更と追加を行いました:
- 既存のオブジェクトの保守 - 既存のアクセサリが変更された場合、ホーム マネージャー (
HMHomeManager
) によって、変更された特定の項目が通知されます。 - 永続的な識別子 - 関連するすべての HomeKit クラスに、HomeKit が有効なアプリ (または同じアプリのインスタンス) 全体で特定の項目を一意に識別する
UniqueIdentifier
プロパティが含まれるようになりました。 - ユーザー管理 - プライマリ ユーザーのホーム内の HomeKit デバイスにアクセスできるユーザーに対するユーザー管理を提供する組み込みのビュー コントローラーを追加しました。
- ユーザー機能 - HomeKit ユーザーは、HomeKit および HomeKit 対応アクセサリで使用できる機能を制御する権限のセットを持つようになりました。 アプリでは、現在のユーザーにのみ関連する機能を表示する必要があります。 たとえば、管理者のみが他のユーザーを維持できる必要があります。
- 定義済みのシーン - 定義済みのシーンは、平均的な HomeKit ユーザーに対して発生する 4 つの一般的なイベント (起床、出発、帰宅、就寝) に対して作成されています。 これらの定義済みのシーンは、ホームから削除することはできません。
- シーンと Siri - Siri は iOS 9 のシーンをより深くサポートしており、HomeKit で定義されている任意のシーンの名前を認識できます。 ユーザーは、その名前を Siri に話すだけでシーンを実行できます。
- アクセサリ カテゴリ - 定義済みのカテゴリのセットがすべてのアクセサリに追加され、ホームに追加されるアクセサリの種類やアプリ内から操作されているアクセサリの種類を識別するのに役立ちます。 これらの新しいカテゴリは、アクセサリのセットアップ中に使用できます。
- Apple Watch のサポート - watchOS で HomeKit を利用できるようになりました。Apple Watch では、iPhone がウォッチの近くになくても HomeKit 対応デバイスを制御できるようになります。 watchOS 用 HomeKit では、ホームの表示、アクセサリの制御、シーンの実行などの機能がサポートされています。
- 新しいイベント トリガーの種類 - iOS 8 でサポートされているタイマーの種類のトリガーに加えて、iOS 9 ではアクセサリの状態 (センサー データなど) や位置情報に基づくイベント トリガーがサポートされるようになりました。 イベント トリガーは、実行の条件を設定するために
NSPredicates
を使用します。 - リモート アクセス - リモート アクセスを使用すると、ユーザーは遠隔地にある家から離れているときに、HomeKit 対応のホーム オートメーション アクセサリを制御できるようになりました。 iOS 8では、これはユーザーが家庭に第 3 世代の Apple TV を持っていた場合にのみサポートされていました。 iOS 9 では、この制限は解除され、リモート アクセスは iCloud と HomeKit アクセサリ プロトコル (HAP) を介してサポートされます。
- 新しい Bluetooth Low Energy (BLE) 機能 - HomeKit では、Bluetooth Low Energy (BLE) プロトコルを介して通信できるアクセサリの種類が追加されました。 HomeKit アクセサリは、HAP セキュア トンネリングを使用して、Wi-Fi 経由で別の Bluetooth アクセサリを公開できます (Bluetooth 範囲外の場合)。 iOS 9 では、BLE アクセサリは通知とメタデータを完全にサポートしています。
- 新しいアクセサリ カテゴリ - Appleは、iOS 9の新しいアクセサリ カテゴリを追加しました: ウィンドウ カバー、電動ドアと窓、アラーム システム、センサー、プログラマブル スイッチ。
iOS 9 の HomeKit の新機能の詳細については、Apple の HomeKit インデックス と HomeKit の新機能に関するビデオを参照してください。
まとめ
この記事では、Apple の HomeKit ホーム オートメーション フレームワークについて説明しました。 HomeKit アクセサリ シミュレーターを使用してテスト デバイスをセットアップおよび構成する方法と、HomeKit を使用してホーム オートメーション デバイスを検出、通信、制御する簡単な Xamarin.iOS アプリを作成する方法について説明しました。