ステートの登録と取得

Thing の状態を表す値をステートとして Thing Interaction Framework に登録し、アプリから参照することができます。これにより、Thing の持つセンサー値や設定値をアプリから様々な形で利用できます。

ステートの概要については ステートの登録と取得 をご参照ください。

REST API では以下の操作が行えます。

ステートの登録

Thing のステートをアップロードする例を以下に挙げます。

curl -v -X PUT \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states" \
  -d '{
    "power":true,
    "presetTemperature":25,
    "fanspeed":5,
    "currentTemperature":28,
    "currentHumidity":65
  }'

Thing または Thing オーナーのアクセストークンを指定してください。また {THING_ID} を対象となる Thing の thingID に差し替えてください。上記の例のように、ステートは JSON 形式で表現します。

ステートとして登録可能なデータの最大サイズは、キーと値のペアを JSON 形式で表現した状態で 10 KB までです。

ステートとして入れ子(ネスト)構造になっている JSON データを使うこともできます。この場合、以下の制限が適用されます。

  • ステート履歴集計時に フィールド条件 として指定できるのは、ステートのトップレベルのフィールドのみです。
  • トリガー実行条件の ステート条件 として指定できるのは、ステートのトップレベルのフィールドのみです。

ステートの登録が成功すると 201 または 204 応答が返されます(初回アップロードの場合は 201、それ以降は 204 が返されます)。

Thing 側でタイムスタンプを付与

登録されたステートにはタイムスタンプが付与されます。タイムスタンプは、基本的には Thing Interaction Framework 側で自動的に付与されますが、Thing 側で明示的にタイムスタンプを付与することもできます。

Thing 側でタイムスタンプを付与する例を以下にあげます。この例のように、"_created" フィールドにタイムスタンプ(UNIX 時間、ミリ秒、UTC)を設定してから、ステートを登録してください。

curl -v -X PUT \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states" \
  -d '{
    "power":true,
    "presetTemperature":25,
    "fanspeed":5,
    "currentTemperature":28,
    "currentHumidity":65,
    "_created": 1469158821211
  }'

なお、Thing 側で設定するタイムスタンプと実際にステート登録が行われた実時間との差には制限があります。詳しくは ステート履歴の管理 をご覧ください。

最新ステートの取得

Thing の最新ステートを参照する例を以下に挙げます。

curl -v -X GET \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states"

Thing または Thing オーナーのアクセストークンを指定してください。また {THING_ID} を対象となる Thing の thingID に差し替えてください。

最新ステートは以下のように 200 応答として返されます。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "power":true,
  "presetTemperature":25,
  "fanspeed":5,
  "currentTemperature":28,
  "currentHumidity":65
}

「最新」ステートとは最後に登録されたステートのことを指します。特に Thing 側でタイムスタンプを設定する場合、設定したタイムスタンプを元に最新ステートが決定されるわけではない点に注意してください。

ステート履歴の検索および取得

Thing のステート履歴は、Object の取得 と同様に、取得したいステート履歴を検索条件で絞り込んで取得します。

指定可能な検索条件は以下のとおりです。

検索結果を取得する際には、結果をグループ別にするかしないかが選択できます。グループ別にする場合は、さらにステート履歴自体を取得するか集計値を取得するかが選択可能です。詳しくは 検索結果の取得方法 をご覧ください。

これらの条件を組み合わせて実際にステート履歴を検索・閲覧する具体例は ステート履歴検索例 をご覧ください。

ステート履歴の検索や取得を行うためには、Thing を 初期登録 する際にステート履歴のグループ化の間隔を設定する必要があります。

取得するステートの時間範囲

取得対象とするステート履歴の時間範囲を withinTimeRange 条件で指定します。時間範囲の指定は必須です。

{
  "type": "withinTimeRange",
  "lowerLimit": 1467000000000,
  "upperLimit": 1467003000000
}

lowerLimit と upperLimit に、取得対象とするステート履歴の下限と上限をそれぞれ指定します。指定はタイムスタンプ(UNIX 時間、ミリ秒、UTC)で行います。

なお、実際のステート履歴取得はグループ単位で実行されます。例えば以下の図において時間範囲を A に指定した場合、グループ #1 内のすべてのステート履歴が取得対象となります。同様に時間範囲を B に指定した場合、グループ #1 と #2 内の全てのステート履歴が取得対象となります。

なお上限・下限として指定したタイムスタンプがグループ境界ちょうどの値の場合は、このグループも取得対象となります。

取得対象が 60 グループ以上になる時間範囲は指定できません。指定するとエラーになります。

ステート履歴のタイムスタンプやグループ化の概要は こちら をご参照ください。

取得するステート履歴のフィールド条件

取得するステート履歴を絞り込むフィールド条件が指定できます。フィールド条件の指定は任意です。

絞り込みには Object 検索 と同じ検索条件が利用可能です。ただし GeoBoxClause と GeoDistance 条件は利用できません。

なお、ステートが入れ子(ネスト)構造の JSON データの場合は、トップレベルのフィールドのみが条件として指定可能です。

フィールド条件は、次のように時間範囲と andClause で結合してください。

{
  "type": "and",
  "clauses": [
    {
      "type": "range",
      "field": "currentTemperature",
      "lowerLimit": 32
    },
    {
      "type": "withinTimeRange",
      "lowerLimit": 1467000000000,
      "upperLimit": 1467003000000
    }
  ]
}

検索結果の取得方法

ステートの履歴は検索結果として返されます。

検索結果の取得形式は、以下より選択できます。

グループごとに取得 集計 ステート履歴の取得方法
しない しない 検索条件に合致するステート履歴を取得します。履歴はデフォルトではタイムスタンプで昇順ソートされた形となります。
する しない 検索条件に合致するステート履歴を、グループごとにまとめた形で取得します。履歴はタイムスタンプで昇順ソートされます。
する する 検索条件に合致するステート履歴について、グループごとに集計した結果を取得します。

グループごとに履歴を取得しない場合

ステート履歴をグループごとに取得しない場合は、Object 検索 と同様に orderBy や descending による履歴の取得順番指定ができます。orderBy の指定がない場合は、タイムスタンプ昇順でステート履歴は返されます。

また、bestEffortLimit や paginationKey を使った ページネーション も利用できます。

グループごとに履歴を取得する場合

ステート履歴をグループごとに取得する場合は、検索時に以下を指定します。

{"grouped": true}

グループごとに取得する場合、ステート履歴の取得順番は常にタイムスタンプ昇順となります。orderBy や descending による取得順番の指定はできません。またページネーションも利用できません。

グループごとに履歴を集計した結果を取得する場合

グループごとにステート履歴を集計した結果を取得する場合は、前記の "grouped": true の指定に加えて集計ルールを指定します。

集計ルールは、次の例のように aggregations 内に指定します。

{
  "aggregations": [
    {
      "field": "temperature",
      "fieldType": "DECIMAL",
      "type": "MAX",
      "putAggregationInto": "max"
    }
  ]
}

集計ルールは検索ごとに 1 つのみ指定可能です(今後複数指定できるようになる予定です)。

以下の情報を指定します。

  • field: 集計対象とするステートのフィールド。
  • fieldType: 集計対象フィールドのデータ型。STRING, INTEGER, DECIMAL, BOOLEAN のいずれかが利用可能です。
  • type: 使用する集計関数。以下のいずれか利用可能です。

    • COUNT: 集計対象フィールドの値が null ではないステート履歴の件数。
    • SUM: 集計対象フィールドの合計値。
    • MAX: 集計対象フィールドの最大値。
    • MIN: 集計対象フィールドの最小値。
    • MEAN: 集計対象フィールドの平均値。
  • putAggregationInto: 集計結果につける名前。一例として先ほどの集計ルールの場合、集計値である "temperature" フィールドの最大値は次のように返されます。

    {
      "aggregations" : [ {
        "value": 35,
        "name": "max"
      } ]
    }
    

ステート履歴検索例

ここでは実際にステート履歴を取得する例をいくつかあげます。

時間範囲指定のみ

最初に、取得するステートの時間範囲のみを指定したシンプルな例をあげます。これは機能ガイドの 例 1 の実行例です。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states/query" \
  -d '{
    "query": {
      "clause": {
        "type": "withinTimeRange",
        "lowerLimit": 1467000000000,
        "upperLimit": 1467003000000
      },
      "grouped": true
    }
  }'

上記のリクエストでは "grouped": true により検索結果のグループ化を指定しているため、ステート履歴は次のように返されます。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "queryDescription" : "WHERE withinTimeRange(1467000000000, 1467003000000)",
  "groupedResults" : [ {
    "range" : {
      "from" : 1467000000000,
      "to" : 1467000900000
    },
    "objects" : [ {
      "currentTemperature" : 32,
      "fanspeed" : 5,
      "_created" : 1467000010000,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    }, {
      "currentTemperature" : 31,
      "fanspeed" : 5,
      "_created" : 1467000374001,
      "currentHumidity" : 70,
      "presetTemperature" : 25,
      "power" : true
    }, {
      "currentTemperature" : 29,
      "fanspeed" : 5,
      "_created" : 1467000384970,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    }, {
      "currentTemperature" : 32,
      "fanspeed" : 5,
      "_created" : 1467000460422,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    } ]
  }, {
    "range" : {
      "from" : 1467000900000,
      "to" : 1467001800000
    },
    "objects" : [ {
      "currentTemperature" : 31,
      "fanspeed" : 5,
      "_created" : 1467001000000,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    }, {
      "currentTemperature" : 31,
      "fanspeed" : 5,
      "_created" : 1467001221211,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    } ]
  }, {
    "range" : {
      "from" : 1467001800000,
      "to" : 1467002700000
    },
    "objects" : [ ]
  }, {
    "range" : {
      "from" : 1467002700000,
      "to" : 1467003600000
    },
    "objects" : [ {
      "currentTemperature" : 31,
      "fanspeed" : 5,
      "_created" : 1467003321211,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    } ]
  } ]
}

リクエスト時に "grouped": true で検索結果のグループ化を指定しなかった場合は、次のようにタイムスタンプ順に昇順ソートされた形でステート履歴が返されます。これは機能ガイドの 例 2 の実行例です。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "queryDescription" : "WHERE withinTimeRange(1467000000000, 1467003000000)",
  "results" : [ {
    "currentTemperature" : 32,
    "fanspeed" : 5,
    "_created" : 1467000010000,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 31,
    "fanspeed" : 5,
    "_created" : 1467000374001,
    "currentHumidity" : 70,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 29,
    "fanspeed" : 5,
    "_created" : 1467000384970,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 32,
    "fanspeed" : 5,
    "_created" : 1467000460422,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 31,
    "fanspeed" : 5,
    "_created" : 1467001000000,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 31,
    "fanspeed" : 5,
    "_created" : 1467001221211,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  }, {
    "currentTemperature" : 31,
    "fanspeed" : 5,
    "_created" : 1467003321211,
    "currentHumidity" : 72,
    "presetTemperature" : 25,
    "power" : true
  } ]
}

時間範囲指定+フィールド条件(集計なし)

次に、時間範囲指定に加えてフィールド条件を指定する例をあげます。これは機能ガイドの 例 3 の実行例です。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states/query" \
  -d '{
    "query": {
      "clause": {
        "type": "and",
        "clauses": [
          {
            "type": "range",
            "field": "currentTemperature",
            "lowerLimit": 32
          },
          {
            "type": "withinTimeRange",
            "lowerLimit": 1467000000000,
            "upperLimit": 1467003000000
          }
        ]
      },
      "grouped": true
    }
  }'

最初の例と同じ時間範囲条件に加え、今回は「"currentTemperature" フィールドの値が 32 以上」というフィールド条件を追加しています。検索結果のグループ化も指定しているため、次のようにステート履歴が返されます。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "queryDescription" : "WHERE ( ( 32 <= currentTemperature ) AND withinTimeRange(1467000000000, 1467003000000) )",
  "groupedResults" : [ {
    "range" : {
      "from" : 1467000000000,
      "to" : 1467000900000
    },
    "objects" : [ {
      "currentTemperature" : 32,
      "fanspeed" : 5,
      "_created" : 1467000010000,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    }, {
      "currentTemperature" : 32,
      "fanspeed" : 5,
      "_created" : 1467000460422,
      "currentHumidity" : 72,
      "presetTemperature" : 25,
      "power" : true
    } ]
  }, {
    "range" : {
      "from" : 1467000900000,
      "to" : 1467001800000
    },
    "objects" : [ ]
  }, {
    "range" : {
      "from" : 1467001800000,
      "to" : 1467002700000
    },
    "objects" : [ ]
  }, {
    "range" : {
      "from" : 1467002700000,
      "to" : 1467003600000
    },
    "objects" : [ ]
  } ]
}

時間範囲指定+フィールド条件(集計あり)

最後に、グループごとの集計を行う例を紹介します。

次の例では、先ほどと同じ検索を、今度は集計関数として COUNT を指定して実施しています。これにより "currentTemperature" フィールドの値が 32 以上のステート履歴の件数がカウントされます。これは機能ガイドの 例 4 の実行例です。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states/query" \
  -d '{
    "query": {
      "clause": {
        "type": "and",
        "clauses": [
          {
            "type": "range",
            "field": "currentTemperature",
            "lowerLimit": 32
          },
          {
            "type": "withinTimeRange",
            "lowerLimit": 1467000000000,
            "upperLimit": 1467003000000
          }
        ]
      },
      "grouped": true,
      "aggregations": [
        {
          "field": "currentTemperature",
          "fieldType": "INTEGER",
          "type": "COUNT",
          "putAggregationInto": "state_count"
        }
      ]
    }
  }'

次のように、指定条件に合致するステート履歴の件数がグループごとに集計され返されます。ステート履歴自体は返されない点に注意してください。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "queryDescription" : "SELECT count(currentTemperature) as state_count WHERE ( ( 32 <= currentTemperature ) AND withinTimeRange(1467000000000, 1467003000000) )",
  "groupedResults" : [ {
    "range" : {
      "from" : 1467000000000,
      "to" : 1467000900000
    },
    "aggregations" : [ {
      "value" : 2,
      "name" : "state_count"
    } ]
  }, {
    "range" : {
      "from" : 1467000900000,
      "to" : 1467001800000
    },
    "aggregations" : [ { } ]
  }, {
    "range" : {
      "from" : 1467001800000,
      "to" : 1467002700000
    },
    "aggregations" : [ { } ]
  }, {
    "range" : {
      "from" : 1467002700000,
      "to" : 1467003600000
    },
    "aggregations" : [ { } ]
  } ]
}

次に、集計関数として MIN を利用した例をあげます。この例ではフィールド条件を指定せず、各グループ内の全ステート履歴の中から最も低い "currentHumidity" の値を集計します。

curl -v -X POST \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "X-Kii-AppID: {APP_ID}" \
  -H "X-Kii-AppKey: {APP_KEY}" \
  -H "Content-Type: application/json" \
  "https://api-jp.kii.com/thing-if/apps/{APP_ID}/targets/thing:{THING_ID}/states/query" \
  -d '{
    "query": {
      "clause": {
        "type": "withinTimeRange",
        "lowerLimit": 1467000000000,
        "upperLimit": 1467003000000
      },
      "grouped": true,
      "aggregations": [
        {
          "field": "currentHumidity",
          "fieldType": "INTEGER",
          "type": "MIN",
          "putAggregationInto": "minimum_humidity"
        }
      ]
    }
  }'

結果は次のように返されます。今回の場合、グループ内で最小の "currentHumidity" 値を持つステート履歴が一意に特定されるため、このステート履歴が "object" フィールドの値として返されています。これは機能ガイドの 例 5 の実行例です。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "queryDescription" : "SELECT min(currentHumidity) as minimum_humidity WHERE withinTimeRange(1467000000000, 1467003000000)",
  "groupedResults" : [ {
    "range" : {
      "from" : 1467000000000,
      "to" : 1467000900000
    },
    "aggregations" : [ {
      "value" : 70,
      "name" : "minimum_humidity",
      "object" : {
        "currentTemperature" : 31,
        "fanspeed" : 5,
        "_created" : 1467000374001,
        "currentHumidity" : 70,
        "presetTemperature" : 25,
        "power" : true
      }
    } ]
  }, {
    "range" : {
      "from" : 1467000900000,
      "to" : 1467001800000
    },
    "aggregations" : [ {
      "value" : 72,
      "name" : "minimum_humidity",
      "object" : {
        "currentTemperature" : 31,
        "fanspeed" : 5,
        "_created" : 1467001000000,
        "currentHumidity" : 72,
        "presetTemperature" : 25,
        "power" : true
      }
    } ]
  }, {
    "range" : {
      "from" : 1467001800000,
      "to" : 1467002700000
    },
    "aggregations" : [ { } ]
  }, {
    "range" : {
      "from" : 1467002700000,
      "to" : 1467003600000
    },
    "aggregations" : [ {
      "value" : 72,
      "name" : "minimum_humidity",
      "object" : {
        "currentTemperature" : 31,
        "fanspeed" : 5,
        "_created" : 1467003321211,
        "currentHumidity" : 72,
        "presetTemperature" : 25,
        "power" : true
      }
    } ]
  } ]
}