初期化処理

Thing 側のプログラムは main() 関数から始まります。この関数で初期化と初期登録を行います。

プログラム開始時の処理

初めに、プログラム引数の取得と、ステートハンドラーの排他処理に使用するミューテックスの初期化を行っています。

static pthread_mutex_t m_mutex;

int main(int argc, char** argv)
{
  ......

  char *vendorThingID, *thingPassword;

  if (argc != 3) {
    printf("hellothingif {vendor thing id} {thing password}\n");
    exit(1);
  }

  vendorThingID = argv[1];
  thingPassword = argv[2];

  if (pthread_mutex_init(&m_mutex, NULL) != 0) {
    printf("Failed to get mutex.\n");
    exit(1);
  }
  ......
}

サンプルの実行 で示したように、Thing 側のプログラムは、以下のようなコマンドラインパラメーターで起動します。

$ ./hellothingif 1111 DEF456

コマンド名に続いて、vendorThingIDと Thing のパスワードを指定します。

argcargv は、コマンド名を含めて取得されるため、argv[1] を vendorThingID、argv[2] を Thing のパスワードとして扱います。

次に、排他処理用に Pthreads のミューテックスを初期化します。static 変数として宣言されている m_mutex を Pthreads の API である pthread_mutex_init() で初期化します。

Thing-IF SDK の初期化

次に、Thing-IF SDK を初期化します。

Thing-IF SDK は内部で malloc などの動的なメモリ確保を行わずに実装されています。そのため、通信処理で使用するバッファーはユーザープログラム側で用意する必要があります。また、ソースコードの構成 のとおり、アクションハンドラーとステートハンドラーを Thing-IF SDK に渡す必要があります。

これらを実行する処理は、以下のようなコードで実装されています。

int main(int argc, char** argv)
{
  kii_bool_t result;
  kii_thing_if_command_handler_resource_t command_handler_resource;
  kii_thing_if_state_updater_resource_t state_updater_resource;
  char command_handler_buff[EX_COMMAND_HANDLER_BUFF_SIZE];
  char state_updater_buff[EX_STATE_UPDATER_BUFF_SIZE];
  char mqtt_buff[EX_MQTT_BUFF_SIZE];
  kii_thing_if_t kii_thing_if;

  ......

  /* prepare for the command handler */
  memset(&command_handler_resource, 0x00, sizeof(command_handler_resource));
  command_handler_resource.buffer = command_handler_buff;
  command_handler_resource.buffer_size =
      sizeof(command_handler_buff) / sizeof(command_handler_buff[0]);
  command_handler_resource.mqtt_buffer = mqtt_buff;
  command_handler_resource.mqtt_buffer_size =
      sizeof(mqtt_buff) / sizeof(mqtt_buff[0]);
  command_handler_resource.action_handler = action_handler;
  command_handler_resource.state_handler = state_handler;

  /* prepare for the state updater */
  memset(&state_updater_resource, 0x00, sizeof(state_updater_resource));
  state_updater_resource.buffer = state_updater_buff;
  state_updater_resource.buffer_size =
      sizeof(state_updater_buff) / sizeof(state_updater_buff[0]);
  state_updater_resource.period = EX_STATE_UPDATE_PERIOD;
  state_updater_resource.state_handler = state_handler;

  /* initialize */
  result = init_kii_thing_if(&kii_thing_if, EX_APP_ID, EX_APP_KEY, EX_APP_SITE,
          &command_handler_resource, &state_updater_resource, NULL);
  if (result == KII_FALSE) {
    printf("Failed to initialize the SDK.\n");
    exit(1);
  }

  ......
}

ここでは、バッファーとハンドラーを、command_handler_resourcestate_updater_resource に設定して init_kii_thing_if() を呼び出します。処理は複雑に見えますが、以下の図のようにバッファーとハンドラーの設定を行っているだけです。また、state_updater_resource.period としてステートの更新間隔を秒単位で設定します。サンプルプログラムでは、EX_STATE_UPDATE_PERIOD は 60(1 分)に設定されています。

また、init_kii_thing_if() では、AppID、AppKey、サーバー設置場所を指定して、操作の対象となる Kii Cloud のアプリケーションを特定しています。Application クラスの実装 に示したように、モバイルアプリと同じアプリケーションを指定することで、連携を実現します。

初期化の結果、第 1 引数で渡した kii_thing_if_t 構造体が初期化されて制御を戻します。以降、この kii_thing_if_t 構造体を指定して後続の API を実行します。

指定するバッファーサイズは、受信するアクションのサイズや、登録するステートのサイズを処理するのに十分なサイズを確保する必要があります。送受信するデータのサイズに対してバッファーサイズが小さい場合、送信や受信の処理はエラーとなります。

初期登録の実行

次に、Thing 側の初期登録を実行します。Android モバイルアプリの初期登録は、オーナーと Thing の紐付け処理が目的でしたが、ここでは Thing 側だけの登録操作を行います。なお、モバイルアプリの初期登録を先に実行しても、Thing の初期登録を先に実行しても、問題ありません。

int main(int argc, char** argv)
{
  ......
  result = onboard_with_vendor_thing_id(&kii_thing_if, vendorThingID, thingPassword, THING_TYPE, THING_PROPERTIES);
  if (result == KII_FALSE) {
    printf("Failed to onboard the thing.");
    exit(1);
  }
  ......
}

初期登録は、Thing-IF SDK の onboard_with_vendor_thing_id() 関数で実行します。引数には初期化済みの kii_thing_if_t 構造体、vendorThingID、Thing のパスワードを指定します。

残りの引数の THING_TYPETHING_PROPERTY は以下のように宣言されています。いずれも、モバイルアプリの 初期登録 で指定したものと同じものを指定します。

const char THING_TYPE[] = "HelloThingIF-SmartLED";
const char THING_PROPERTIES[] = "{}";

なお、初期登録がエラーを返した場合、その原因の詳細を知ることができます。以下のコードのように修正すると、デバッグ用の情報として Thing Interaction Framework の REST API が返した HTTP レスポンスコードと HTTP レスポンスボディーを取得できます。

printf("Failed to onboard the thing. %d, %s\n",
       kii_thing_if.command_handler.kii_core.response_code,
       kii_thing_if.command_handler.kii_core.response_body);

待機

main() の最後は、while ループによって待ち状態に入ります。

int main(int argc, char** argv)
{
  ......
  printf("Waiting for commands\n");

  while(1){}; /* run forever. */
}

Thing-IF SDK の初期化処理では、内部でアクションとステートの処理用のスレッドを生成しています。これらのスレッドから、アクションハンドラーとステートハンドラーが呼び出されることで Thing 側の処理が行われます。


次は...

コマンドを受信した際の処理を確認します。

コマンドの受信処理 に移動してください。

より詳しく学びたい方へ