初期化コードの実装(ゲートウェイ)

SDK を導入するアプリケーションから初期化処理を実行する必要があります。

このページは、Thing Interaction Framework の ゲートウェイ 機能を使用して、ゲートウェイやエンドノードを初期化する方法を示しています。スタンドアローンの Thing として初期化する場合は、初期化コードの実装 の手順を使用してください。

まずは、ゲートウェイを初期化し、エンドノードが追加されるごとにエンドノードを初期化します。初期化処理が完了すると、アプリケーション上の Thing に示すように、ゲートウェイと複数のエンドノードが Kii Cloud 上に作成され、それらがモバイルアプリの操作ユーザーと紐付いた状態になります。

初期化を行うには、ゲートウェイやエンドノードと、モバイルアプリとの間で、ゲートウェイのユーザー名とパスワードを共有しておく必要があります。これらはゲートウェイの製品本体に貼り付けたシールやラベルを見てモバイルアプリに手入力したり、Bluetooth などの近距離無線通信によって共有したりすることで、モバイルアプリ側の情報として用意しておきます。

ゲートウェイの初期化

ゲートウェイアプリ、エンドノードアプリとも、ゲートウェイの Thing の初期化処理を次の手順で実行します。

  1. Kii Cloud SDK の初期化

  2. ThingIFAPI の取得

  3. GatewayAPI の取得と接続

  4. 初期登録の実行

ここでは、SDK での API の構成 に示す API インスタンスのうち、ゲートウェイの ThingIFAPI インスタンスと、GatewayAPI インスタンスを取得します。これらはゲートウェイ本体そのものの操作を行うための API クラスです。エンドノード用の API クラスは後のエンドノードアプリ用の手順によって取得します。

初期化手順のコードを読み解く際は、機能ガイドの ゲートウェイの初期登録 の図と見比べながらコードを確認すると、全体の流れが理解しやすくなります。

Kii Cloud SDK の初期化

下記のコードを、AppDelegate の application:didFinishLaunchingWithOptions メソッドに追加します。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    // Initialize the Kii Cloud SDK. Call this method before any other Kii SDK API calls.
    Kii.beginWithID("___APPID___", andKey: "___APPKEY___", andSite: KiiSite.JP)

    // Override point for customization after application launch.
    return true
}

___APPID______APPKEY___ の項目は、開発者ポータルにて取得した AppID と任意の値を設定してください(アプリケーションの作成 を参照してください)。

AppID をクライアントアプリに埋め込んでも、アクセス制御を正しく行えば安全性は確保できます。詳細は、セキュリティ をご覧ください。

ThingIFAPI の取得

次に、ゲートウェイを操作するために Thing Interaction Framework にリクエストを行うための ThingIFAPI インスタンスを取得します。この処理は、上記 Kii Cloud SDK の初期化後であれば、アプリ中のどの位置で実行しても問題ありません。

// Instantiate your application on Kii Cloud.
let app = App(appID: "___APPID___", appKey: "___APPKEY___", site: Site.JP)

// Instantiate a Thing-IF API from a ThingIFAPIBuilder instance.
let apiGateway = ThingIFAPIBuilder(app: app, owner: owner, tag:"gateway").build()

ソースコード中、以下の情報を指定します。

  • ___APPID______APPKEY___ の項目は、開発者ポータルにて取得した AppID と任意の値を設定してください(アプリケーションの作成 を参照してください)。

    Site の代わりに api-jp.kii.com のようなサーバーのホスト名を指定して初期化することもできます。詳細は 詳細ドキュメント をご覧ください。

  • owner はゲートウェイのオーナーとなるユーザーを表します。取得方法は オーナーの定義(ゲートウェイ) をご覧ください。

    ユーザーの指定方法は、モバイルアプリのデザインによって様々な形式が考えられます。本ガイドでは、仮ユーザー(Pseudo User)を使って明示的なユーザー作成やログインを行わずにユーザーを利用する方法を案内しています。明示的にログイン操作を行うデザインを採用した場合は、ログイン画面を用意し、ログイン処理の完了時に Thing-IF SDK を初期化することになります。

初期化が完了すると、API を実装しているインスタンスを取得できます。ThingIFAPIBuilderbuild メソッドを呼び出すと、Thing-IF SDK が初期化されて ThingIFAPI インスタンスが返されます。ThingIFAPI インスタンスは、クラスのフィールドに保持するなどして、後続の処理で呼び出せる状態にしておきます。また、初期化済みの情報の保存と復元(ゲートウェイ) に示す方法によって、保存や読み込みを行ったりできます。

ThingIFAPIBuilder メソッドの tag パラメーターでは、各 ThingIFAPI を識別するための一意の名前をタグとして与えます。タグは saveInstanceloadFromStoredInstance によって保存や読み込みを行う際にインスタンスを識別するために使用します。エンドノードでは、後述の初期化処理で "gateway" とは異なるタグを付けて識別します。

GatewayAPI の取得と接続

次に、GatewayAPI インスタンスを取得します。このインスタンスは、Wi-Fi 等のローカルネットワークを使ってモバイルアプリからゲートウェイにアクセスする際に必要な API をまとめたオブジェクトです。

// Instantiate a gateway API object.
let gatewayAddress = NSURL(string: "___GATEWAY_URL___")
let gatewayLocal = GatewayAPIBuilder(app, address:gatewayAddress).build()

// Authenticate a user to the gateway.
gatewayLocal.login("___GATEWAY_USERNAME___", password:"___GATEWAY_PASSWORD___", completionHandler: { (error: ThingIFError?) -> Void in
    // Check for an error.
})
  • ゲートウェイの URL、ユーザー名、パスワードを ___GATEWAY_URL______GATEWAY_USERNAME______GATEWAY_PASSWORD___ に指定します。ゲートウェイの URL は、http://192.168.0.10/ のような、モバイルアプリからローカルネットワーク上で Wi-Fi アクセスできるアドレスです。また、ゲートウェイのユーザー名とパスワードは、ゲートウェイエージェントが持つ認証用の情報で、何らかの形でモバイルアプリと共有しておきます。

  • GatewayAPIBuilderapp パラメーターは、ThingIFAPI を初期化した際の App インスタンスと同じものを指定します。AppID、AppKey などが設定されています。

  • login メソッドを呼び出すと、ゲートウェイにアクセスして認証処理を行います。

初期登録の実行

モバイルアプリからゲートウェイやエンドノードなどの Thing を制御するには、モバイルアプリと Thing を紐付ける操作が必要です。この紐付け操作を初期登録(Onboarding)と呼びます。

ゲートウェイでは、以下の方法で初期登録を行います。

// Instantiate the gateway.
gatewayLocal.onboardGateway( { (gateway: Gateway?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }

  // Get the thing ID of the gateway.
  let thingID = gateway!.thingID

  // Set the gateway password.
  let thingPassword = "___GATEWAY_PASSWORD___"

  // Onboard the gateway to Thing Interaction Framework.
  apiGateway.onboard(thingID, thingPassword: thingPassword, completionHandler: { (target: Target?, error: ThingIFError?) -> Void in
    if error != nil {
      // Handle the error.
      return
    }
  })
})

ここでは以下の処理を行っています。

  1. onboardGateway によって、Wi-Fi 経由でゲートウェイに初期登録の要求を出します。成功すると、Gateway インスタンスが返ります。Gateway インスタンスからは、ゲートウェイの thingID を取得できます。

  2. onboard によって、Thing Interaction Framework に初期登録の要求を出します。これによって、apiGateway の初期化の際に指定したオーナーと、thingID で指定されたゲートウェイが紐づくことになります。

ゲートウェイの初期登録は、ここに示す 1 通りの方法だけをサポートしています。スタンドアローンの Thing では、初期登録をモバイルアプリから行うか、Thing とモバイルアプリの両方から行うかを選択できます。

ここまでの処理が完了すると、ゲートウェイとモバイルアプリの紐付けが完了したことになります。取得できた apiGatewaygatewayLocal を使って後続の処理を行います。

ゲートウェイアプリでは、必要な初期化処理は以上で完了です。エンドノードアプリではこれに加え、次に示すエンドノードの初期化が必要です。

エンドノードの初期化

エンドノードアプリでは、ゲートウェイの初期化後、エンドノードが追加されるごとにその初期化処理を行います。

エンドノードの Thing は次の手順で初期化します。

  1. 未処理リストの取得

  2. 初期登録の実行

  3. ThingIFAPI の取得

  4. デバイスのインストール

  5. ゲートウェイへの完了通知

初期化手順のコードを読み解く際は、機能ガイドの エンドノードの初期登録 の図と見比べながらコードを確認すると、全体の流れが理解しやすくなります。

未処理リストの取得

はじめに、ゲートウェイにアクセスして、初期化処理が未完了となっているエンドノードのリストを取得します。ゲートウェイでは、ゲートウェイには接続済みだが、Thing Interaction Framework への初期登録が行われていないエンドノードの一覧を管理しています。ゲートウェイの API を通して、この一覧を取得できます。

ゲートウェイへのアクセスには、すでに取得している GatewayAPI のインスタンス gatewayLocal を使用します。未処理のエンドノードの一覧を取得し、このうちの 1 件を選択して、後続の初期化処理を行います。

// Get a list of pending end nodes.
gatewayLocal.listPendingEndNodes( { (nodes: [PendingEndNode]?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }

  for index in 0..<nodes!.count {
    let endnodeVendorThingID = nodes![index].vendorThingID
    let endnodeThingType = nodes![index].thingType
    let endnodeProperties = nodes![index].thingProperties
    // Select a pending end node to onboard.
  }
})

listPendingEndNodes を呼び出すと、Thing Interaction Framework に未登録のエンドノードの一覧を [PendingEndNode] として取得できます。このサンプルコードでは、その一覧を 1 件ずつ処理してそのエンドノードの詳細情報を取得しています。

モバイルアプリでは、処理対象となる PendingEndNode インスタンスを 1 つ決定します。処理対象を決めるため、モバイルアプリのユーザーインターフェイスによって対象のエンドノードをユーザーに選択させたり、すべての未処理エンドノードを順番に 1 件ずつ処理したりする方法が考えられます。

対象のエンドノードをユーザーに選択させる場合、対象のエンドノードを識別する情報として、エンドノードの Thing タイプと Thing 情報を使用できます。これらは、エンドノードをゲートウェイに接続する際、モバイルアプリの仕様に合わせて自由に使用できる値です。たとえば、endnodeProperties のフィールドとして、製品のシリアル番号や、E26 型 Kii スマート LED [ABC-123] のような製品名を持たせることができます。これらを画面に表示するなどして、初期化対象の PendingEndNode インスタンスを 1 つ決めます。

初期化対象の PendingEndNode インスタンスが決定したら、次の処理に進みます。

初期登録の実行

次に、エンドノードの Thing、モバイルアプリ(操作しているユーザー)、ゲートウェイの 3 つを紐付ける初期登録の操作を行います。

初期登録を行う前に、エンドノードのパスワードをモバイルアプリに用意します。これは、エンドノードを扱う際に Thing Interaction Framework 上のセキュリティを向上するためのもので、ユーザーインターフェイス等で入力しても、モバイルアプリ内部で決めても構いません。ただし、エンドノードのパスワードが漏洩すると不正な操作が行われるおそれがあり、紛失するとアクセスできなくなる問題が発生するため、安全な方法で管理する必要があります。

エンドノードでは、以下のエンドノード専用の API を使って初期登録を行います。

// Set the end node password.
let endNodePassword = "___END_NODE_PASSWORD___"

// Set the data grouping interval option.
let options = OnboardEndnodeWithGatewayOptions(interval: DataGroupingInterval.INTERVAL_15_MINUTES)

// Onboard the end node.
apiGateway.onboardEndnodeWithGateway(pendingEndNode, endnodePassword: endNodePassword, options: options, completionHandler: { (endNode: EndNode?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

ここでは以下の値を設定しています。

  • interval:ステート履歴を保存する場合、履歴をグループ化する間隔を指定します。指定のない場合はステート履歴は保存されません。指定可能な値は INTERVAL_1_MINUTE、INTERVAL_15_MINUTES、INTERVAL_30_MINUTES、INTERVAL_1_HOUR、INTERVAL_12_HOURS のいずれかです。詳しくは こちら をご参照ください。
  • pendingEndNode未処理リストの取得 で決定した初期化対象のエンドノードです。
  • endNodePassword: 初期化対象のエンドノードのパスワードです。何らかの形でモバイルアプリに用意しておきます。

初期登録が完了すると、初期登録済みのエンドノードを表す EndNode インスタンスを取得できます。これは次のステップで利用します。

モバイルアプリからの初期登録が行われるまで、ステート履歴は利用できない点にご注意ください。初めのモバイルアプリが紐付くまでの間に Thing はステートをアップロードできますが、そのステートは履歴に保存されません。

ThingIFAPI の取得

各エンドノードに対して Thing Interaction Framework 経由でリクエストを行うための ThingIFAPI インスタンスを取得します。

ここでは、取得済みのインスタンスを apiEndNode1 としていますが、実際のプログラムではゲートウェイに接続されているエンドノード数分だけ ThingIFAPI インスタンスを生成します。Map や 配列など、複数のエンドノードを扱えるデータ構造で管理する方法をおすすめします。

// Instantiate a Thing-IF API from a ThingIFAPIBuilder instance.
let apiEndNode1 = ThingIFAPIBuilder(app: app, owner: owner, target: endNode, tag: "endnode1").build()

ThingIFAPIBuilder で下記のパラメーターを指定して新しい ThingIFAPI インスタンスを作成します。また、既存の apiGateway と同じ内容でターゲットとタグだけが異なるインスタンスを作成する場合は copyWithTarget メソッドで取得できます。

  • app パラメーターは、ThingIFAPI を初期化した際の App インスタンスと同じものを指定します。AppID、AppKey などが設定されています。

  • owner はエンドノードのオーナーとなるユーザーを表します。取得方法は オーナーの定義(ゲートウェイ) をご覧ください。

  • target パラメーターによって、作成される ThingIFAPI を初期登録済みの EndNode と紐付けます。

  • tag パラメーターには、タグ "endnode1" を指定しています。ここで指定しているタグは、saveInstanceloadFromStoredInstance によって保存や読み込みを行う際にインスタンスを識別するために使用するものです。ゲートウェイや他のエンドノードとは異なる一意の文字列を指定してください。初期化済みの情報の保存と復元(ゲートウェイ) のコード例もご覧ください。

デバイスのインストール

エンドノードでは、コマンドを送信した際にエンドノードからの応答を受け取れるよう、デバイスのインストールを行います。この操作により、オーナーと APNs のデバイストークンが Kii Cloud 上で紐付きます。

デバイスのインストール

エンドノードのそれぞれに対して、上記で取得した ThingIFAPI のインスタンスを使って以下のように実行します。

// Register the device token for the thing owner to Kii Cloud.
apiEndNode1.installPush(token, development: false, completionHandler: { (installID: String? error: ThingIFError?) -> void in
  if error != nil {
    // Handle the error.
    return
  }
})
  • token には、プッシュ通知の初期化処理(プッシュ通知の導入手順)で取得したデバイストークンを指定します。
  • development パラメーターで開発環境か(true)、配布環境か(false)を選択します。 デバイスのインストールが完了すると、ThingIFAPI 作成時に指定したオーナーは、指定されたデバイストークンと紐付けて Thing Interaction Framework に登録されます。既存のデバイストークンはインストールによって上書きされるため、以前紐付いていたオーナーへのプッシュ通知はこのデバイスに届かなくなります。

デバイスのアンインストール

インストールしたデバイスをアンインストールしたい場合は、以下のコードを実行します。

この処理をエンドノードのどれか 1 つで実行すると、全てのエンドノードについて、プッシュ通知が届かなくなります。アンインストール処理は、最後のエンドノードを取り除くような場合に実行してください。

// Unregister the device token for the thing owner from Kii Cloud.
apiEndNode1.uninstallPush(apiEndNode1.installationID, completionHandler: { (error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

このコードはデバイスのインストールが完了していることを前提としています。installationID プロパティは、installPush でインストールが成功していない場合 nil を返します。

成功すると、Thing Interaction Framework からのプッシュ通知がこの端末に届かなくなります。

ゲートウェイへの完了通知

最後に、初期登録が完了したことをゲートウェイに通知します。

// Notify the gateway of the completion of onboarding.
gatewayLocal.notifyOnboardingCompletion(endNode, completionHandler: { (error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

endNode には、初期登録の実行結果として得られた EndNode インスタンスを指定します。

機能の実行

以上の操作により、ゲートウェイと各エンドノードの初期化が完了します。初期化の完了時、以下のインスタンスを取得できています。

  • ゲートウェイの ThingIFAPI インスタンス

    ここでは apiGateway として表現しています。Thing Interaction Framework 経由でゲートウェイにアクセスする際に使用します。エンドノードやゲートウェイ自身の管理のために使用します。現在のバージョンでは、新しいエンドノードを初期化するために必要です。

  • ゲートウェイの GatewayAPI インスタンス

    ここでは gatewayLocal として表現しています。Wi-Fi によってゲートウェイに直接アクセスする際に使用します。エンドノードやゲートウェイ自身の管理のために使用します。現在のバージョンでは、新しいエンドノードを初期化するために必要です。

  • エンドノードの ThingIFAPI インスタンス

    ここでは apiEndNode1 として表現しています。複数個のエンドノードを接続した場合は複数個のインスタンスが得られます。

    このインスタンスを使って、エンドノードにコマンドを送信したり、エンドノードのステートを調べたりできます。たとえば、apiEndNode1 にコマンドを送信すると、Thing Interaction Framework は接続しているゲートウェイにコマンドを送信し、そのエンドノードはゲートウェイ経由でコマンドを受け取ることができます。

    実際にコマンドを送信したりステートを受信したりする方法は、コマンドの実行ステートの参照トリガー を参照してください。この際、各サンプルコードの api は、操作対象となるエンドノードの apiEndNode1 に読み替えてください。