Role B: バックエンド&Webexモジュール

実装詳細とアーキテクチャ要件

トップページへ戻る

Role Bが担当する「バックエンド&Webexモジュール」は、エッジから送られてくる大量のデータを安全かつ低コストで処理・保存し、外部サービス(Webex)との連携基盤を構築する役割を担います。「スロットリングによるデータ欠損」や「不適切なクエリによるクラウド破産(青天井課金)」、さらには「プライバシー情報の漏洩」を防ぐための堅牢な設計が求められます。
また、他ロールの完成を待つ「ウォーターフォール的な待ち状態」を排除するため、モックAPIを用いた先行構築を積極的に行い、フロントエンドとの結合テストを最速で実施することが重要です。

1. 開発に必要な環境・情報(準備物)

  • インフラ: AWSアカウント(IoT Core, DynamoDB, API Gateway, Lambda, Cognito, S3, CloudFront)、学校配布のIAMユーザー
  • 連携情報 (Role Aから受領): MQTTで送信されるJSONデータのスキーマ(※未定の場合はモックデータで先行開発)

2. 実装手順と技術的課題の根本解決アプローチ

Step 1: IoT CoreルールとDynamoDB連携

目的: エッジから送信されるMQTTメッセージを永続化する。

  1. IoT Coreのメッセージルーティングルールを作成し、特定トピックのデータをDynamoDBにINSERTするアクションを設定する。この際、必ず「DynamoDBv2アクション」を選択し、ペイロードがフラットな構造のまま保存されるようにする。
  2. SQLステートメント内で、TTL(自動削除)用の属性として expiration_time を計算して付与する(例: SELECT *, timestamp() / 1000 + 2592000 AS expiration_time FROM 'topic/#' ※30日間保持の場合)。

【重要】技術的課題と根本解決:
1. ペイロードのネスト問題: レガシーな「DynamoDBアクション」を使用すると、データが payload 属性内にネストされてしまいます。Lambdaを挟んで整形するとコストと障害点が増加するため、必ずJSONを直接マッピングできる「DynamoDBv2アクション」を使用してください。
2. データ欠損対策: プロビジョニングモード(1WCU固定)で運用するため、バーストトラフィック時に書き込みスロットリングが発生しデータが欠損するリスクがあります。必ずIoT Coreルールの「エラーアクション」として、CloudWatch Logsへエラー内容を出力する設定、またはSQS(Dead Letter Queue)へメッセージを退避する設定を実装してください。

Step 2: DynamoDBのテーブル設計(GSIの活用)

目的: 時系列データを効率的に保存し、かつ空間単位で一括検索できるようにする。

  1. テーブル名: HazardEvents
  2. 基本テーブル: パーティションキー(PK)を device_id (String)、ソートキー(SK)を timestamp (Number) に設定。
  3. グローバルセカンダリインデックス(GSI): インデックス名を RoomEventsIndex とし、PKを room_id (String)、SKを timestamp (Number) に設定。射影される属性は ALL とする。
  4. TTL (Time to Live): 古いデータを自動削除するため、属性 expiration_time (Number - Unixタイムスタンプ秒) をTTL属性として有効化する。

【重要】技術的課題と根本解決:
複数カメラがある部屋全体のハザードデータを取得する際、device_id がPKだと複数回のクエリや全件スキャンが必要になります。必ず room_id をPKとするGSIを設計し、1回のQuery操作で特定期間・特定空間のデータを取得できるようにしてRCU消費を抑えてください。また、プロビジョニングモード(1WCU/1RCU固定)で運用するため、不要なデータによるストレージ肥大化とスキャンコスト増大を防ぐべく、TTLによるライフサイクル管理は必須です。

Step 3: フロントエンド用認証基盤(Cognito)の構築

目的: プライバシー情報を保護し、認証済みユーザーのみがシステムにアクセスできるようにする。

  1. API認証用: Amazon Cognitoで「ユーザープール」を作成し、保護者用のアカウントを発行する。サインイン識別子には「メールアドレス」を選択する。
  2. IoT Core接続用: 「IDプール」を作成し、認証プロバイダーとして「Amazon Cognito」を選択する。そこに上記で作成した「ユーザープールID」と「アプリクライアントID」を設定して紐付ける。
  3. IDプールの「認証済みロール」のIAMポリシーに iot:Connect, iot:Subscribe, iot:Receive 権限を付与する。
  4. 【先行タスク】AWSコンソールからCognito User Poolにテストユーザー(メールアドレス)を手動作成し、パスワードを設定してRole Cへ共有する。

【重要】技術的課題と根本解決:
未認証アクセスを許可すると、URLを知る第三者が子供の監視データを覗き見できる重大なインシデントに繋がります。必ずユーザープールによるログインを必須とし、IDプールに紐づくIAMポリシーのResource句は、Role CがSubscribeする特定のMQTTトピックのみに制限して最小権限の原則を徹底してください。

Step 4: API Gateway + Lambdaによる履歴取得APIの構築(モック先行)

目的: Role Cが過去のハザードデータを安全に取得できるようにする。Role AのJSONスキーマ確定を待たずに、インフラと認可の結合テストを先行させる。

  1. API Gateway(HTTP API または REST API)を作成し、Cognito User Pool Authorizerをアタッチしてエンドポイントを保護する。
  2. 【先行タスク】以下の「モックデータを返すLambda関数」をデプロイし、API Gatewayに統合する。これによりRole CはCORSやCognito認可の結合テストを即座に開始できる。
    export const handler = async (event) => {
      return {
        statusCode: 200,
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
          'Access-Control-Allow-Methods': 'OPTIONS,GET'
        },
        body: JSON.stringify([
          { device_id: 'mv_camera_01', room_id: 'living_room', timestamp: Date.now() - 3600000, event_type: 'ai_hazard', details: { hazard_type: 'fall', x: 640, y: 480, confidence: 0.85 } },
          { device_id: 'mt20_door_01', room_id: 'living_room', timestamp: Date.now() - 1800000, event_type: 'sensor_alert', details: { sensor_type: 'door', status: 'open', battery_level: 95 } }
        ])
      };
    };
  3. 結合テスト完了後、DynamoDBのGSIに対して Query を実行する本番ロジックへLambdaを書き換える。

【重要】技術的課題と根本解決:
1. CORSエラーの確実な防止: API Gateway側でのCORS設定だけでなく、Lambda関数からの戻り値(レスポンスヘッダー)にも必ず Access-Control-Allow-Origin などのCORSヘッダーを含めてください。
2. 不正クエリによるDB負荷の防止: フロントエンドから渡されるクエリパラメータをLambda内で厳格に型検証し、不正な値の場合は 400 Bad Request を返すフェイルセーフを実装してください。

Step 5: フロントエンド用ホスティング環境の構築

目的: Role Cが開発した専用サイトをインターネット上に公開する。

  1. Amazon S3バケットを作成し、静的ウェブサイトホスティングを有効化する。
  2. Amazon CloudFrontディストリビューションを作成し、S3をオリジンとして設定する(OACを利用してS3を非公開化)。

【重要】技術的課題と根本解決:
1. セキュリティ: S3バケットを直接パブリック公開せず、必ずCloudFrontを前段に配置し、S3バケットポリシーでCloudFrontからのアクセスのみを許可するセキュアな構成にしてください。
2. SPAルーティング設定(必須): React等のSPAでは、画面遷移後にリロードするとS3のKey NotFoundエラーになります。必ずCloudFrontの「エラーページ」設定で、HTTPステータスコード 404 および 403 に対して、レスポンスページパスを /index.html にし、HTTPレスポンスコードを 200 に設定してください。

Step 6: Webex Botのプロビジョニングと通信テスト

目的: Role Aが画像送信ロジックを実装するために必要なWebexの認証情報と送信先を準備する。

  1. Webex Developer PortalでBotを作成し、Bot Access Token を取得する。
  2. 通知用のWebex Space (Room) を作成し、Botを招待して Room ID を取得する。
  3. Postmanやcurl等を使用し、取得したTokenとRoom IDで実際にWebex Messaging APIへテストメッセージをPOSTし、正常に送信されることを確認する。

【重要】技術的課題と根本解決:
Role AがAI推論と画像エンコードの実装に集中できるよう、インフラ・API連携担当であるRole Bが事前にAPIの疎通確認を済ませておくことが不可欠です。未検証のTokenを渡すと、Role A側でエラーが出た際に「コードのバグ」か「Token/権限の不備」かの切り分けに無駄な時間を費やすことになります。

3. システム共通JSONスキーマと連携ポイント

【重要】AWS IoT CoreおよびDynamoDBで扱うJSONスキーマが以下に確定しました。 これを前提に、DynamoDBのテーブル設計(PK: device_id, SK: timestamp, GSI-PK: room_id, GSI-SK: timestamp, TTL: expiration_time)と、Lambda関数の本番ロジック実装を進めてください。

// パターン1: AI推論アラート
{
  "device_id": "mv_camera_01", "room_id": "living_room", "timestamp": 1723307400000, "event_type": "ai_hazard",
  "details": { "hazard_type": "fall", "x": 640, "y": 480, "confidence": 0.85 }
}
// パターン2: Merakiセンサーアラート
{
  "device_id": "mt20_door_01", "room_id": "living_room", "timestamp": 1723307405000, "event_type": "sensor_alert",
  "details": { "sensor_type": "door", "status": "open", "battery_level": 95 }
}
// パターン3: 複合アラート
{
  "device_id": "system_logic_01", "room_id": "living_room", "timestamp": 1723307410000, "event_type": "complex_alert",
  "details": { "alert_type": "night_wandering", "trigger_device": "mt20_door_01", "lux": 5 }
}
// パターン4: 行動パターン解析結果
{
  "device_id": "system_logic_01", "room_id": "living_room", "timestamp": 1723307420000, "event_type": "risk_suggestion",
  "details": { "risk_level": "high", "suggested_area": { "x": 100, "y": 200, "radius": 50 }, "reason": "unusual_access_time" }
}
  • Role Aへ共有: AWS IoT Coreのエンドポイント、デバイス証明書。およびStep 6で検証済みの Webex Bot Access Token と Room ID。
  • Role Cへ共有(環境変数セット): フロントエンドの結合テストをブロックしないよう、以下の情報を一式提供します。
    • Cognito User Pool ID
    • Cognito Client ID
    • Cognito Identity Pool ID
    • AWS IoT Core エンドポイントURL
    • AWSリージョン名
    • 履歴取得APIのURL(モックから本番へ切り替え)
    • テストユーザーのログインIDとパスワード
    • デプロイ先のS3バケット名