diff --git a/src/services/health.ts b/src/services/health.ts index ab3aecb..3403a29 100644 --- a/src/services/health.ts +++ b/src/services/health.ts @@ -294,9 +294,9 @@ export const healthApi = { executeSleepScene: () => http.post('/api/health/home-assistant/scenes/sleep', undefined, { timeout: 90000 }), executeAllOffScene: () => - http.post('/api/health/home-assistant/scenes/all-off'), + http.post('/api/health/home-assistant/scenes/all-off', undefined, { timeout: 90000 }), switchDevice: (payload: { deviceId: string; turnOn: boolean; entityId?: string }) => - http.post('/api/health/home-assistant/devices/switch', payload), + http.post('/api/health/home-assistant/devices/switch', payload, { timeout: 45000 }), setParameter: (payload: HomeAssistantSetParameterInput) => - http.post('/api/health/home-assistant/devices/set-parameter', payload) + http.post('/api/health/home-assistant/devices/set-parameter', payload, { timeout: 45000 }) } diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue index decac7f..95b93b8 100644 --- a/src/views/DashboardView.vue +++ b/src/views/DashboardView.vue @@ -134,7 +134,7 @@ onMounted(load)
助眠音箱 - {{ dashboard?.sceneConfig?.enableSpeakerSleepMode ? '开启睡眠模式' : '关闭睡眠模式' }} · {{ dashboard?.sceneConfig?.speakerVolumePercent || 15 }}% + 体质音乐循环播放 · 60% 起每 5 秒降 1% 至停止 · {{ dashboard?.sceneConfig?.enableSpeakerSleepMode ? '开启睡眠模式' : '关闭睡眠模式' }}
8H 床垫 diff --git a/src/views/DeviceControlView.vue b/src/views/DeviceControlView.vue index 35fa0e2..b677bc2 100644 --- a/src/views/DeviceControlView.vue +++ b/src/views/DeviceControlView.vue @@ -287,11 +287,6 @@ function isDeviceTurnedOn(device?: HomeAssistantDiscoveredDevice): boolean { if (!device || !device.primaryControlEntityId) return false const target = device.entities.find(e => e.entityId === device.primaryControlEntityId) if (!target) return false - if (target.domain === 'media_player') { - const muted = target.attributes?.is_volume_muted - if (typeof muted === 'boolean') return !muted - if (typeof muted === 'string') return muted.toLowerCase() !== 'true' - } return target.state === 'on' || target.state === 'playing' } @@ -314,12 +309,9 @@ async function toggleDevice(device?: HomeAssistantDiscoveredDevice) { return } const nextOn = !isDeviceTurnedOn(device) - const isMediaDevice = device.category === 'Media' switchingDeviceId.value = device.deviceId const loadingToast = showLoadingToast({ - message: isMediaDevice - ? (nextOn ? '正在取消静音…' : '正在静音…') - : (nextOn ? '正在开启设备…' : '正在关闭设备…'), + message: nextOn ? '正在开启设备…' : '正在关闭设备…', forbidClick: true, duration: 0 }) @@ -329,9 +321,7 @@ async function toggleDevice(device?: HomeAssistantDiscoveredDevice) { turnOn: nextOn, entityId: device.primaryControlEntityId }) - const message = res.message || (isMediaDevice - ? (nextOn ? '音箱声音已开启' : '音箱已静音') - : (nextOn ? '设备已开启' : '设备已关闭')) + const message = res.message || (nextOn ? '设备已开启' : '设备已关闭') if (!res.success) throw new Error(message) await loadStatus() // 命令接口已经回读并确认真实状态;覆盖可能仍处于短暂缓存中的状态列表。 @@ -349,6 +339,38 @@ async function toggleDevice(device?: HomeAssistantDiscoveredDevice) { } } +async function controlSpeaker(device: HomeAssistantDiscoveredDevice, play: boolean) { + if (!device.primaryControlEntityId) { + const message = '音箱缺少已确认的控制实体' + setFeedback('fail', message) + showFailToast(message) + return + } + switchingDeviceId.value = device.deviceId + const loadingToast = showLoadingToast({ + message: play ? '正在发送播放指令…' : '正在发送停止指令…', + forbidClick: true, + duration: 0 + }) + try { + const res = await healthApi.switchDevice({ + deviceId: device.deviceId, + entityId: device.primaryControlEntityId, + turnOn: play + }) + if (!res.success) throw new Error(res.message || '音箱控制失败') + setFeedback('success', res.message) + showSuccessToast(res.message) + } catch (err) { + const message = err instanceof Error ? err.message : '音箱控制失败' + setFeedback('fail', message) + showFailToast(message) + } finally { + loadingToast.close() + switchingDeviceId.value = null + } +} + // 调节参数 API async function applyParam(deviceId: string, paramType: string, val: unknown, entityId?: string) { const key = `${deviceId}_${paramType}` @@ -369,7 +391,7 @@ async function applyParam(deviceId: string, paramType: string, val: unknown, ent }) const message = res.message || `${label}设置成功` if (!res.success) throw new Error(message) - await loadStatus() + if (paramType !== 'volume') await loadStatus() setFeedback('success', message) showSuccessToast(message) } catch (err) { @@ -728,27 +750,35 @@ onUnmounted(() => { 睡眠音频

{{ speakerDevice.name }}

- {{ speakerDevice.online ? '设备在线' : '设备离线' }} + {{ speakerDevice.online ? 'HA 实体在线' : 'HA 实体离线' }}
+ + +
- {{ isDeviceTurnedOn(speakerDevice) ? '声音开启' : '已静音' }} - + @click="controlSpeaker(speakerDevice, true)" + >播放测试音乐 + 停止播放
+ 手动按钮播放测试音频;一键开启按体质选曲循环播放,音量自动渐弱至停止
- 助眠播放音量 + 手动播放音量 {{ localParams.speakerVolume }}%
{ 50% 适中聆听 100% 满格音量
+ 手动调整音量会停止本次自动渐弱
音箱睡眠模式
- 使用设备当前音源,仅切换睡眠模式并调整音量 + 睡眠模式由 Home Assistant 单独控制
-

香型需人工更换,音乐风格暂不能自动选择,室温仅供参考;一键启动只下发当前已支持的设备参数。

+

香型需人工更换,体质音乐可由音箱自动播放,室温仅供参考;一键启动只下发当前已支持的设备参数。

一键启动预设

湿度 {{ result.sceneConfig.targetHumidity }}% · 灯光 {{ result.sceneConfig.lightColorTemperatureKelvin }}K

-

香氛{{ result.sceneConfig.enableFragrance ? '开启' : '关闭' }} · 音箱睡眠模式 {{ result.sceneConfig.speakerVolumePercent }}% 音量

+

香氛{{ result.sceneConfig.enableFragrance ? '开启' : '关闭' }} · 体质音乐循环播放,从 60% 每 5 秒降 1% 至停止

床垫加热按重庆冬季天气决定;软硬度按健康档案 BMI 给出可手动修改的演示起点。