IBM Bob と一緒にオフィス在席確認アプリ「ここいる」を作った話【仕様編】
はじめに
みなさんはオフィスで「あの人いまどこにいるんだろう?」と思ったことはありませんか?
私はIBM Bobというコーディングアシスタントを使って、スマートフォンのGPSと気圧センサーを活用したオフィス在席確認アプリ「ここいる」を作りました。今回はオフィス想定ですが、災害時などの存在確認にも応用可能です。
作成した経緯ですが、普段はAnalytics関連の業務に携わっており、分析支援やトレーニング、システム導入などを行っていますが、プログラムを作成することはほぼなく、ましてスマホで動作するアプリなどを作成したことはありません。今回は、IBM Bobの勉強も兼ねて、初めて使用してみました。
この記事では、Bobと会話しながら仕様やシステム構成を決めていったプロセスを紹介します。
実装の詳細は続編の【実装編】で紹介します。
IBM Bobとは、IBM社が提供するAIコーディングアシスタントです。コードの生成・修正・デプロイまで会話形式でサポートしてくれます。
アプリの概要
アプリ名:ここいる
スマートフォンのGPSと気圧センサーから位置と高度(階数)を取得し、オフィスのレイアウトマップ上に誰がどこにいるかをリアルタイムで表示するWebアプリです。
Step 1:Bobに要件を伝える
まず、やりたいことをそのままBobに投げてみました。
私のプロンプト:
アプリ名:ここいる
<仕様>
・ログイン時に名前を入れる
・スマホのGPSと気圧センサーから位置と高度(階数)を取得する
・オフィスのレイアウトをマッピングする(レイアウト情報はPDFで持っている)
・名前でどこにいるか検索できるようにする。
・可能ならWebsocketなどを利用して動きをとらえるようする(30秒毎)
<制約条件>
・IBMCloudのサービスを利用してください。
・まずはプロトタイプなので、簡単な構成でよいです。
・非機能要件は考慮しなくてよいです。
するとBobはすぐにアーキテクチャ設計を提案してくれました。
Step 2:Bobが提案したアーキテクチャ
Bobが提案した構成はこちらです。
[スマホブラウザ]
├─ GPS + DeviceMotion API(気圧→高度推定)
├─ WebSocket (30秒ごとに位置送信)
└─ PDF.js でオフィスレイアウト表示
↕ WebSocket / REST
[IBM Cloud (Code Engine)]
└─ Node.js + Express + ws (WebSocket)
└─ IBM Cloudant (位置データ保存) ← IBM Cloud サービス
技術スタックの提案
| レイヤー | 技術 |
|---|---|
| フロントエンド | HTML/CSS/Vanilla JS, PDF.js |
| バックエンド | Node.js + Express + ws
|
| リアルタイム | WebSocket (30秒インターバル) |
| DB | IBM Cloudant (NoSQL) |
| ホスティング | IBM Cloud Foundry / Code Engine |
| 高度推定 | Web Sensor API(気圧→高度計算) |
シンプルでわかりやすい構成です。プロトタイプとしては十分です。
Step 3:デプロイ方法の確認
私のプロンプト:
PCで作成したものをIBMCloud上にDeployするという認識であっていますか?
Bobの回答のポイント:
- ローカル(PC)ではページ表示・WebSocket動作確認ができる
- GPS取得はPC次第(精度低い)、気圧センサーはPCにないため未取得
- IBM CloudにデプロイするとHTTPSが自動で付与され、スマホで気圧センサーが使えるようになる
- 気圧センサー(
AbsolutePressureSensor)はHTTPS環境でないと動作しない
この点は盲点でした。ローカルではHTTPなので気圧センサーが動かないのです。IBM CloudのCode EngineはデフォルトでHTTPSになるため、デプロイ後にスマホで動作確認する流れが最適だということがわかりました。
Step 4:オフィスレイアウトの扱い方を決める
当初はPDF.jsでPDFを表示する予定でしたが、オフィスのレイアウト画像(PNG)を用意したためPNG画像表示に変更しました。
また、フロアごとに緯度経度が必要という点もBobが指摘してくれました。
私がBobに提供した情報:
- オフィスの4隅の緯度経度(右上・右下・左上・左下)
- 対象フロア:1F / 2F / 5F / 6F(4Fはレイアウト図なし)
Bobの提案:バイリニア逆変換(Newton法)
単純な線形補間ではなく、建物が歪んでいても正確にマップできるバイリニア逆変換を採用しました。
4隅の緯度経度 → 正規化パラメータ (s,t) を Newton法で反復計算
→ キャンバス座標 (x,y) に変換
フロアによって緯度経度が異なる場合にも対応できるよう、フロアごとに corners を持つ構造にしました。
Step 5:フロア判定ロジックの設計
最初は高度(メートル)から階数を計算する方式を提案してもらいました。
// 初期案(階高4mで計算)
const floor = Math.max(1, Math.round(altitudeM / 4.0) + 1);
しかし実際にスマホで計測したところ、オフィスの各フロアの実測高度がわかりました。
私のプロンプト:
高度とフロア情報ですが、以下のように判定するようにしましょう。
49.0m以上は6F、39.1m以下は1F、39.1mから43mは2F、43mから49.0m未満は5F
初期表示は高度を取得して、取得したエリアを表示するようにしましょう。
Bobが実装した判定ロジック:
function altitudeToFloor(altitudeM) {
if (altitudeM >= 49.0) return 6;
if (altitudeM >= 43.0) return 5;
if (altitudeM >= 39.1) return 2;
return 1;
}
シンプルで明快です。実測値ベースなので精度も高くなります。
Step 6:フロア自動切り替えの仕様決め
実装してみると、高度取得のたびにマップのフロアが自動切り替わる仕様になっていました。
私のフィードバック:
画面の自動切換えはログインした後の1回だけにしましょう。
自動で次々切り替わると他の階に誰がいるのかが分からなくなります。
後、他の階にいると判定した人は、違う階を表示しているときは、表示しないようにしましょう。
Bobが対応した内容:
-
autoFloorDoneフラグを追加し、初回のみ自動切り替え - ピン表示は現在表示中のフロアにいる人のみ表示(他フロアは非表示)
- メンバーリストは全フロアの全員を表示(誰がどこにいるか確認できる)
これはBobに任せっきりではなく、実際に使ってみてから改善点を伝えたことで生まれた仕様です。
Step 7:セッションタイムアウトの設計
私のプロンプト:
途中で切れたセッションが残っています。
切れたセッションで一定時間たったものはクリアする処理を入れてください。
Bobが提案・実装したタイムアウト仕様:
| 設定 | 値 |
|---|---|
| タイムアウト判定 | 最後の位置送信から 2分 経過したユーザーを削除 |
| チェック間隔 | 30秒ごと にサーバーが自動確認 |
| 削除後の挙動 | 全クライアントに即ブロードキャスト → マップからピンが消える |
送信間隔が5秒なので、回線が切れた場合は最大 2分30秒 でマップから消える計算です。
Step 8:WiFiによるフロア判定の検討
気圧センサーだけではフロア判定に誤差が出る問題を相談しました。
私のプロンプト:
フロア毎のWifiが設置されているので、接続されているWifiの機器IDで初期フロアを決定し、
そこからの気圧の変化でフロアを変更するようなロジックにしたいです。
Bobからの回答は現実的なものでした。
残念ながらスマホのブラウザ(Safari / Chrome)からはWiFiのBSSIDを直接取得できません。
セキュリティ上の理由でWebAPIとして公開されていません。
代替案として以下が提示されました:
| 方法 | 難易度 | 内容 |
|---|---|---|
| ネイティブアプリ化 | 高 | Swift/KotlinでBSSIDを取得しWebViewに渡す |
| ユーザーが手動でWiFiを選択 | 低 | フロア選択UIで対応 |
| IPアドレスでフロア推定 | 中 | フロアごとにサブネットが分かれていれば実装可能 |
| QRコードをフロアに設置 | 低 | フロアごとのQRをスキャンして基準点をセット |
ネットワーク構成の確認が必要なため、この機能は保留としました。現状は気圧センサー+手動設定で対応しています。
最終的な仕様まとめ
機能一覧
| 機能 | 仕様 |
|---|---|
| ログイン | 名前入力のみ(認証なし・プロトタイプ) |
| 位置取得 | GPS(緯度・経度)+ 気圧センサー(高度・階数) |
| フロア判定 | 実測高度ベースの閾値判定(1F/2F/5F/6F) |
| 位置送信 | WebSocket、5秒ごと |
| セッションタイムアウト | 2分間更新なしで自動削除 |
| マップ表示 | PNG画像 + バイリニア逆変換でピン配置 |
| フロア自動切替 | ログイン後初回のみ |
| 名前検索 | リアルタイムフィルタリング |
| スマホUI | マップ/メンバーのタブ切り替え |
システム構成(最終版)
[スマホブラウザ]
├─ GPS (Geolocation API)
├─ 気圧センサー (AbsolutePressureSensor)
├─ WebSocket(5秒ごとに位置送信)
└─ オフィスレイアウト画像表示(バイリニア逆変換)
↕ WebSocket / REST API
[IBM Cloud Code Engine (jp-tok)]
└─ Node.js 20 + Express + ws
└─ インメモリストア
(IBM Cloudant接続時は永続化)
今後の課題
| 課題 | 内容 |
|---|---|
| データ永続化 | Cloudant接続(現状はインメモリ) |
| 認証 | 名前入力のみ、なりすまし対策なし |
| フロア判定の精度向上 | WiFi BSSID・IPアドレスによる補正(保留中) |
Bobと仕様を決めてみて感じたこと
よかった点
1. 技術的な制約を即座に教えてくれる
「ブラウザからBSSIDは取れません」「HTTPSでないと気圧センサーが動きません」など、自分では気づかなかった制約をすぐに指摘してくれました。
2. 複数の選択肢を提示してくれる
WiFiフロア判定の代替案のように、「こういうやり方もあります」と選択肢を並べて提示してくれるので、意思決定がしやすいです。
3. プロトタイプに適した提案をしてくれる
「プロトタイプなので簡単な構成でよい」という制約を守りながら、後から拡張できる設計にしてくれました。
気をつけた点
実際に動かしてからフィードバックする
フロア自動切り替えの問題のように、動かしてみて初めてわかる問題があります。Bobは言われたことを実装するので、ユーザー視点でのフィードバックは人間がしっかり行うことが重要です。
まとめ
IBM Bobと会話しながら仕様を決めていくプロセスは、まるで優秀なエンジニアと設計ミーティングをしているようでした。
- 要件をそのまま伝えるだけでアーキテクチャを提案してくれる
- 技術的な制約や代替案をすぐに教えてくれる
- 「プロトタイプ」「非機能要件は不要」などの制約もきちんと守ってくれる
次の【実装編】では、Bobと実際にコードを書いていく過程を紹介します。
IBM Bobに興味がある方は、是非以下の弊社サイトからお問い合わせください。
https://www.ait-solution.jp/ai365/ibm_bob/