このガイドでは、Butlr Reporting API から Zone(ゾーン)の在室データを取得する方法と、リクエストサイズの上限が原因で空のレスポンスが返るのを防ぐ方法を説明します。
問題点
1 回の API 呼び出しで多すぎる数の Zone について zone_occupancy データをリクエストすると、次のような空のレスポンスが返ることがあります。
{
"data": {},
"page_info": {
"page": 1,
"page_item_count": 0,
"total_item_count": 0,
"total_pages": 1
}
}
これは、API に内部的な処理時間の上限があるためです。Zone 数が多いクエリや時間範囲が広いクエリ(またはその両方)は処理量が多くなり、この上限を超えるとリクエストはデータを返しません。
この場合も API は HTTP 200 を返しますが、data フィールドは空のオブジェクト {} になります。data に結果が含まれているかを必ずご確認ください。
推奨バッチサイズ
1 回のリクエストに含める Zone は 30 個以下にしてください。
このバッチサイズは、一般的なクエリの時間範囲で検証済みです。
| 時間範囲 | 最大 Zone 数(理論値) | 推奨バッチサイズ |
|---|---|---|
| 1 時間以内 | 160 以上 | 30 |
| 2 時間以内 | 約 150 | 30 |
| 4 時間以内 | 約 75 | 20 |
| 8 時間以内 | 約 37 | 20 |
| 24 時間以内 | 約 10 | 10 |
期間が 24 時間以上にわたるクエリでは、バッチサイズを 1 リクエストあたり 10 Zone に減らしてください。
リクエストのバッチ分割方法
30 を超える Zone のデータが必要な場合は、Zone リストをバッチに分割し、API を複数回呼び出します。
ステップ 1:Zone リストを 30 件ずつのバッチに分割
たとえば Zone が 100 個ある場合は、次のように分割します。
- バッチ 1:Zone 1~30
- バッチ 2:Zone 31~60
- バッチ 3:Zone 61~90
- バッチ 4:Zone 91~100
ステップ 2:各バッチを個別のリクエストとして送信
POST /v3/reporting
{
"group_by": {
"order": \\["zone_id"\\],
"raw": true
},
"window": {
"every": "1m",
"function": "max"
},
"filter": {
"start": "2026-04-06T05:00:00.000Z",
"stop": "2026-04-06T09:00:00.000Z",
"measurements": \\["zone_occupancy"\\],
"zones": {
"eq": \\[
"zone_abc123",
"zone_def456"
\\]
},
"value": { "gte": 0 }
}
}
ステップ 3:結果のマージ
各レスポンスの data オブジェクトをクライアント側で結合します。各バッチは Zone ID をキーとする data マップを返すため、簡単にマージできます。
コード例
Python
import requests
ZONES = ["zone_1", "zone_2", ..., "zone_100"]
BATCH_SIZE = 30
API_URL = "<https://api.butlr.io/api/v3/reporting>"
HEADERS = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
all_data = {}
for i in range(0, len(ZONES), BATCH_SIZE):
batch = ZONES[i : i + BATCH_SIZE]
body = {
"group_by": {"order": ["zone_id"], "raw": True},
"window": {"every": "1m", "function": "max"},
"filter": {
"start": "2026-04-06T05:00:00.000Z",
"stop": "2026-04-06T09:00:00.000Z",
"measurements": ["zone_occupancy"],
"zones": {"eq": batch},
"value": {"gte": 0}
}
}
resp = requests.post(API_URL, json=body, headers=HEADERS)
all_data.update(resp.json().get("data", {}))
print(f"Retrieved data for {len(all_data)} zones")
JavaScript
const ZONES = ["zone_1", "zone_2", /* ... */ "zone_100"];
const BATCH_SIZE = 30;
const API_URL = "<https://api.butlr.io/api/v3/reporting>";
async function fetchZoneOccupancy(zones, start, stop) {
const allData = {};
for (let i = 0; i < zones.length; i += BATCH_SIZE) {
const batch = zones.slice(i, i + BATCH_SIZE);
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
group_by: { order: ["zone_id"], raw: true },
window: { every: "1m", function: "max" },
filter: {
start, stop,
measurements: ["zone_occupancy"],
zones: { eq: batch },
value: { gte: 0 }
}
})
});
const result = await response.json();
Object.assign(allData, result.data || {});
}
return allData;
}
クイックリファレンス
| 条件 | 1 リクエストあたりの最大 Zone 数 |
|---|---|
| デフォルト(一般的な用途) | 30 |
| 時間範囲が 24 時間を超える場合 | 10 |
トラブルシューティング
症状:API は 200 OK を返しますが、data が空のオブジェクト {} になっています。
原因:指定した時間範囲に対して Zone 数が多すぎます。
解決策:
- 1 リクエストあたりの Zone 数を 30 以下に減らします。
- それでも空のレスポンスが返る場合は、10 Zone まで減らします。
- 数日にわたるような非常に長い時間範囲では、時間枠を狭め、期間ごとに分けて複数のリクエストを送ることもご検討ください。
コメント
記事コメントは受け付けていません。