import type { VoiceTool } from './_types' import { tabletJson } from './_http' /** * Управление светом (лампами) через Home Assistant. * * Голосовой агент (tablet-agent) распознаёт интенты light_on/light_off и слот * device («свет у кровати», «лампу для чтения»). Здесь имя лампы сопоставляется * с entity_id Home Assistant. * * Реальные entity_id задаются переменной окружения LIGHT_ENTITIES_JSON (в * tablet.env), например: * LIGHT_ENTITIES_JSON={"bedside":"light.yeelight_bedside","reading":"light.reading_lamp","default":"light.bedside"} * Ключи — короткие имена (см. DEVICE_ALIASES ниже). Пока переменная не задана, * используются заглушки light.* — команды проходят как mock (HA вернёт success). */ // Короткое имя лампы → entity_id. Переопределяется LIGHT_ENTITIES_JSON. const DEFAULT_ENTITIES: Record = { bedside: 'light.bedside', // «Свет у кровати» reading: 'light.reading', // «Лампа для чтения» default: 'light.bedside', // если лампа не названа — эта } function lightEntities(): Record { const raw = process.env.LIGHT_ENTITIES_JSON if (raw) { try { return { ...DEFAULT_ENTITIES, ...JSON.parse(raw) } } catch { // некорректный JSON — падаем на дефолты } } return DEFAULT_ENTITIES } // Разговорные имена ламп → короткий ключ. Слот device приходит куском текста. const DEVICE_ALIASES: Array<[RegExp, string]> = [ [/крова|спальн|ночник|прикроват/i, 'bedside'], [/чтени|настольн|рабоч/i, 'reading'], ] function resolveEntity(device?: string): string { const map = lightEntities() if (device) { for (const [re, key] of DEVICE_ALIASES) { if (re.test(device) && map[key]) return map[key] } } return map.default || 'light.bedside' } const controlLight: VoiceTool = { schema: { type: 'function', function: { name: 'control_light', description: 'Управление светом (лампами): включить или выключить. ' + 'Лампы: «свет у кровати», «лампа для чтения». Если лампа не названа — ' + 'используется лампа по умолчанию. Используй для команд вроде «включи свет», ' + '«выключи лампу для чтения», «зажги свет у кровати».', parameters: { type: 'object', properties: { action: { type: 'string', enum: ['turn_on', 'turn_off'], description: 'Включить или выключить', }, device: { type: 'string', description: 'Какая лампа: «свет у кровати», «лампа для чтения». ' + 'Опционально — без неё берётся лампа по умолчанию.', }, brightness_pct: { type: 'number', description: 'Яркость 0-100 (опционально, только при turn_on)', }, }, required: ['action'], }, }, }, async execute(args) { const action = String(args?.action || '') if (action !== 'turn_on' && action !== 'turn_off') { return { error: `unknown action: ${action}` } } const entity_id = resolveEntity(args?.device as string | undefined) const payload: Record = { domain: 'light', service: action, entity_id } if (action === 'turn_on' && typeof args?.brightness_pct === 'number') { payload.brightness_pct = Math.max(0, Math.min(100, Math.round(args.brightness_pct))) } await tabletJson('POST', '/api/voice/tools/smart-home', payload) return { success: true, action, entity_id, ...(args?.device ? { device: args.device } : {}) } }, } export const tools: VoiceTool[] = [controlLight]