Auto-sync: 2026-03-03 17:00:01
This commit is contained in:
@@ -6,10 +6,11 @@ schema:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
device:
|
device:
|
||||||
type: string
|
type: object
|
||||||
description: ''
|
description: ''
|
||||||
default: null
|
default: null
|
||||||
originalType: string
|
format: dynselect-device
|
||||||
|
originalType: DynSelect_device
|
||||||
text:
|
text:
|
||||||
type: string
|
type: string
|
||||||
description: ''
|
description: ''
|
||||||
|
|||||||
@@ -1,20 +1,69 @@
|
|||||||
export async function main(
|
/**
|
||||||
device: string,
|
* alexa_speak.ts
|
||||||
text: string,
|
* 指定した Echo デバイスにテキストを読み上げさせる Windmill スクリプト
|
||||||
): Promise<{ ok: boolean; device: string; text: string }> {
|
*
|
||||||
|
* パラメータ:
|
||||||
|
* device - ドロップダウンから選択するデバイス(内部的にはシリアル番号)
|
||||||
|
* text - 読み上げるテキスト
|
||||||
|
*/
|
||||||
|
|
||||||
const ALEXA_API_URL = "http://alexa_api:3500";
|
const ALEXA_API_URL = "http://alexa_api:3500";
|
||||||
|
|
||||||
|
type DeviceOption = { value: string; label: string };
|
||||||
|
|
||||||
|
const FALLBACK_DEVICE_OPTIONS: DeviceOption[] = [
|
||||||
|
{ value: "G0922H085165007R", label: "プレハブ (G0922H085165007R)" },
|
||||||
|
{ value: "G8M2DB08522600RL", label: "リビングエコー1 (G8M2DB08522600RL)" },
|
||||||
|
{ value: "G8M2DB08522503WF", label: "リビングエコー2 (G8M2DB08522503WF)" },
|
||||||
|
{ value: "G0922H08525302K5", label: "オフィスの右エコー (G0922H08525302K5)" },
|
||||||
|
{ value: "G0922H08525302J9", label: "オフィスの左エコー (G0922H08525302J9)" },
|
||||||
|
{ value: "G8M2HN08534302XH", label: "寝室のエコー (G8M2HN08534302XH)" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Windmill Dynamic Select: 引数名 `device` に対応する `DynSelect_device` と `device()` を定義
|
||||||
|
export type DynSelect_device = string;
|
||||||
|
|
||||||
|
export async function device(): Promise<DeviceOption[]> {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${ALEXA_API_URL}/devices`);
|
||||||
|
if (!res.ok) return FALLBACK_DEVICE_OPTIONS;
|
||||||
|
|
||||||
|
const devices = (await res.json()) as Array<{
|
||||||
|
name?: string;
|
||||||
|
serial?: string;
|
||||||
|
family?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
const options = devices
|
||||||
|
.filter((d) => d.family === "ECHO" && d.serial)
|
||||||
|
.map((d) => ({
|
||||||
|
value: d.serial as string,
|
||||||
|
label: `${d.name ?? d.serial} (${d.serial})`,
|
||||||
|
}))
|
||||||
|
.sort((a, b) => a.label.localeCompare(b.label, "ja"));
|
||||||
|
|
||||||
|
return options.length > 0 ? options : FALLBACK_DEVICE_OPTIONS;
|
||||||
|
} catch {
|
||||||
|
return FALLBACK_DEVICE_OPTIONS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function main(
|
||||||
|
device: DynSelect_device,
|
||||||
|
text: string,
|
||||||
|
): Promise<{ ok: boolean; device: string; text: string }> {
|
||||||
const res = await fetch(`${ALEXA_API_URL}/speak`, {
|
const res = await fetch(`${ALEXA_API_URL}/speak`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ device, text }), // ← SSMLなし、素のテキスト
|
body: JSON.stringify({ device, text }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const body = await res.json().catch(() => ({}));
|
const body = await res.json().catch(() => ({}));
|
||||||
throw new Error(`alexa-api error ${res.status}: ${JSON.stringify(body)}`);
|
throw new Error(
|
||||||
|
`alexa-api error ${res.status}: ${JSON.stringify(body)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await res.json();
|
return await res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ locks:
|
|||||||
f/weather/weather_sync__flow+気象データ取得・同期.py: 86c9953ec7346601eaa13c681e2db5c01c9a5b4b45a3c47e8667ad3c47557029
|
f/weather/weather_sync__flow+気象データ取得・同期.py: 86c9953ec7346601eaa13c681e2db5c01c9a5b4b45a3c47e8667ad3c47557029
|
||||||
g/all/setup_app__app+__app_hash: d71add32e14e552d1a4c861c972a50d9598b07c0af201bbadec5b59bbd99d7e3
|
g/all/setup_app__app+__app_hash: d71add32e14e552d1a4c861c972a50d9598b07c0af201bbadec5b59bbd99d7e3
|
||||||
g/all/setup_app__app+change_account.deno.ts: 3c592cac27e9cdab0de6ae19270bcb08c7fa54355ad05253a12de2351894346b
|
g/all/setup_app__app+change_account.deno.ts: 3c592cac27e9cdab0de6ae19270bcb08c7fa54355ad05253a12de2351894346b
|
||||||
u/admin/alexa_speak: 38de2eb567f82488e6f819c82dc7d83f41d83f015fac0c944d98dcc6b33a29a1
|
u/admin/alexa_speak: e5bef63ab682e903715056cf24b4a94e87a14d4db60d8d29cd7c579359b56c72
|
||||||
u/admin/hub_sync: aaf9fd803fa229f3029d1bb02bbe3cc422fce680cad39c4eec8dd1da115de102
|
u/admin/hub_sync: aaf9fd803fa229f3029d1bb02bbe3cc422fce680cad39c4eec8dd1da115de102
|
||||||
u/akiracraftwork/hourly_chime__flow+__flow_hash: 79974bee69ff196e45a08b74e9539d8a3b50885ef0abba6907a00530809984fa
|
u/akiracraftwork/hourly_chime__flow+__flow_hash: 79974bee69ff196e45a08b74e9539d8a3b50885ef0abba6907a00530809984fa
|
||||||
u/akiracraftwork/hourly_chime__flow+a.ts: b27320279be1d14184a210632e15d0e89d701243545d2d73cdd20e11dd413c53
|
u/akiracraftwork/hourly_chime__flow+a.ts: b27320279be1d14184a210632e15d0e89d701243545d2d73cdd20e11dd413c53
|
||||||
|
|||||||
Reference in New Issue
Block a user