From d5bb7f24ddf8a8a4a8291966e5bc1176790702db Mon Sep 17 00:00:00 2001 From: Akira Date: Tue, 3 Mar 2026 13:25:25 +0900 Subject: [PATCH] =?UTF-8?q?Claude=20Code=E3=81=AB=E3=82=88=E3=82=8B?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...30_マスタードキュメント_Alexa_TTS_API編.md | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/docs/30_マスタードキュメント_Alexa_TTS_API編.md b/docs/30_マスタードキュメント_Alexa_TTS_API編.md index 36472ee..bcd5ad0 100644 --- a/docs/30_マスタードキュメント_Alexa_TTS_API編.md +++ b/docs/30_マスタードキュメント_Alexa_TTS_API編.md @@ -97,7 +97,7 @@ Windmill ワークフロー | `.env` | `alexa-api/`(.gitignore 対象) | 実際の Cookie 保管 | Git にコミットしない | | `auth4.js` | `alexa-api/` | Amazon 認証・Cookie 取得スクリプト | **ローカルのみで実行**(Windowsブラウザ認証が必要) | | `auth.js` / `auth2.js` / `auth3.js` | `alexa-api/` | auth4.js の旧バージョン | 参考用。実際は auth4.js を使う | -| `test_tts.js` | `alexa-api/` | ローカルテスト用スクリプト | 直接 alexa.amazon.co.jp を叩いて動作確認 | +| `test_tts.js` | `alexa-api/` | ローカルテスト用スクリプト | `.env` を読んで直接 alexa.amazon.co.jp を叩く。テスト対象デバイスはシリアル `G0922H08525302K5`(オフィスの右エコー)にハードコード。TABLET は一覧表示から除外。 | --- @@ -186,6 +186,8 @@ await main("G0922H08525302K5", "来客がありました"); } ``` +- Amazon は **200 または 202** を返す(どちらも成功として扱う。202 は非同期処理を示す) + **レスポンス(失敗)**: ```json { @@ -209,6 +211,29 @@ await main("G0922H08525302K5", "来客がありました"); ] ``` +- `force=true` で**常にキャッシュを無効化**して最新一覧を取得する(`/speak` の5分キャッシュとは独立) +- TABLET や Alexa アプリなど、Echo 以外のデバイスも含む全デバイスを返す + +### デバイス検索ロジック(findDevice) + +`/speak` の `device` パラメータは以下の優先順位で検索する: + +1. **シリアル番号完全一致**(`serialNumber === device`) +2. **アカウント名完全一致**(大文字小文字を無視) +3. **アカウント名部分一致**(`includes()` 、大文字小文字を無視) + +```javascript +// 例: "右エコー" でも "オフィスの右エコー" を見つけられる +``` + +### キャッシュ仕様 + +| 対象 | TTL | 備考 | +|------|-----|------| +| `customerId` | サーバー再起動まで永続 | Bootstrap API から取得 | +| デバイス一覧(`/speak` 経由) | 5分 | 期限切れ後は自動更新 | +| デバイス一覧(`/devices` 経由) | なし(毎回強制取得) | 診断・確認用途 | + --- ## 6. Alexa API の仕組み(重要な知識) @@ -234,6 +259,16 @@ await main("G0922H08525302K5", "来客がありました"); → シーケンス JSON を送信して読み上げ実行 ``` +### サーバー起動時の自動初期化 + +`app.listen()` の直後に非同期で初期化処理を実行する: + +1. `getCustomerId()` を呼び出して `customerId` をキャッシュ(成功すると `[INFO] Customer ID: xxx` をログ出力) +2. `getDevices()` を呼び出してデバイス一覧をキャッシュ(5分 TTL) +3. `deviceType` が `A4ZXE` または `ASQZWP` で始まるデバイス(Echo 系)のみをログ出力 + +**失敗してもサーバーは起動し続ける**(`[WARN] Startup init failed:` と出力して続行)。ただし Cookie が無効な場合、その後の `/speak` リクエストも全て失敗する。 + ### POST /api/behaviors/preview のリクエスト構造 ```json @@ -318,11 +353,19 @@ AMAZON_EMAIL="メールアドレス" AMAZON_PASSWORD="パスワード" node auth ### auth4.js のログインフロー 1. `GET https://www.amazon.co.jp/ap/signin?openid.assoc_handle=amzn_dp_project_dee_jp` -2. hidden フィールド(anti-csrftoken-a2z, appActionToken, workflowState 等)を抽出 -3. POST でメール/パスワードを送信 -4. `alexa.amazon.co.jp/api/apps/v1/token` へのリダイレクトをたどる + - `openid.assoc_handle: 'amzn_dp_project_dee_jp'` が **Alexa Japan 専用のハンドル**(他のAmazonサービスとは異なる) + - `openid.return_to: 'https://alexa.amazon.co.jp/api/apps/v1/token'` にリダイレクト先を指定 +2. hidden フィールド(anti-csrftoken-a2z, appActionToken, workflowState 等)を HTML から抽出 +3. POST でメール/パスワードを `rememberMe: 'true'` と一緒に送信(長期Cookie取得のため重要) +4. 3xx リダイレクトを最大10回たどる(`alexa.amazon.co.jp/api/apps/v1/token` 等) 5. 取得した Cookie(at-acbjp, sess-at-acbjp, sst-acbjp, session-token 等)を `.env` に保存 +**成功判定**: Cookie に `at-acbjp` または `session-token` が含まれているかで判定。 + +**失敗時のエラー検出**: +- CAPTCHA が要求されている場合: `※ CAPTCHA が要求されています。しばらく待ってから再試行してください。` +- パスワードが間違っている場合: `※ パスワードが間違っている可能性があります。` + ### Cookie の有効期限 数日〜数週間で期限切れになる。期限切れの症状: `/health` を叩くと Cookie 長は正常だが、`/speak` が 400 や 403 を返す。 @@ -479,6 +522,10 @@ curl -X POST \ | `AlexaAnnouncement` は別用途 | コンテンツでなくノード名が読まれる | | レート制限 | 短時間連続リクエストで HTTP 429 または無音。通知用途では問題なし | | Gitea push がブロックされる | pre-receive フックでエラー。ファイル転送は scp を使う | +| 起動ログに Echo デバイスが出ない | deviceType が `A4ZXE` or `ASQZWP` で始まるもののみ表示。新デバイス追加時は確認を | +| test_tts.js のテスト対象が固定 | シリアル `G0922H08525302K5`(オフィスの右エコー)にハードコード。他デバイスでテストする場合は一時的に書き換える | +| auth4.js で CAPTCHA が出る | Amazon のレート制限。しばらく時間を置いてから再実行 | +| `/devices` と `/speak` のキャッシュが異なる | `/devices` は毎回最新取得、`/speak` は5分キャッシュ。新しいデバイス追加直後に `/speak` が失敗する場合、コンテナ再起動でキャッシュクリア | --- @@ -489,7 +536,7 @@ curl -X POST \ | ファイル | 説明 | |---------|------| | `alexa-api/server.js` | Express API サーバー。Alexa への直接 HTTPS 実装 | -| `alexa-api/Dockerfile` | node:20-alpine ベース | +| `alexa-api/Dockerfile` | node:20-alpine ベース。**`npm install --omit=dev`** で devDependencies(alexa-remote2, alexa-cookie2)を除外してビルド。コピーするのは `server.js` のみ(auth4.js 等はコンテナに含まれない) | | `alexa-api/docker-compose.yml` | windmill_windmill-internal ネットワーク接続設定 | | `alexa-api/auth4.js` | Amazon 認証・Cookie 取得(ローカルのみ) | | `alexa-api/test_tts.js` | ローカルテスト用スクリプト | @@ -554,3 +601,4 @@ var rawSequenceJson = JSON.stringify(sequenceObj).replace( | 2026-03-02〜03 | 日本語TTS問題の調査・試行錯誤 | | 2026-03-03 | `\uXXXX` エスケープで日本語TTS完全解決。server.js・test_tts.js に反映 | | 2026-03-03 | 本マスタードキュメント作成 | +| 2026-03-03 | findDevice 検索ロジック、キャッシュ仕様、起動初期化、auth4.js 詳細、Dockerfile 仕様を追記 |