Files
Evergreen-Health/Evergreen.Health.Application/Health/Devices/Lighting/LightingModule.cs
T
2026-11-09 16:10:05 +08:00

81 lines
4.7 KiB
C#

using Evergreen.Health.Application.Health.Devices.Contracts;
using Evergreen.Health.Application.Health.Integrations.HomeAssistant;
using Evergreen.Health.Application.Health.Models;
using Evergreen.Health.Application.Health.Scenes;
using Microsoft.Extensions.Options;
namespace Evergreen.Health.Application.Health.Devices.Lighting;
public sealed class LightingModule : HealthDeviceModule
{
private readonly HomeAssistantEntityOptions _entities;
private readonly ILightTransitionRuntime _transition;
private readonly LightOffDispatcher _lightOff;
public LightingModule(DeviceActionRunner runner, IOptions<HomeAssistantOptions> options,
ILightTransitionRuntime transition, LightOffDispatcher lightOff) : base(runner)
{
_entities = options.Value.Entities; _transition = transition; _lightOff = lightOff;
Parameters =
[
new("brightness", PrimaryEntityId, value =>
{
var brightness = DeviceValues.Integer(value, 0, 100, "灯光亮度");
return new("设置灯光亮度", PrimaryEntityId, "light", brightness == 0 ? "turn_off" : "turn_on",
brightness == 0 ? null : new Dictionary<string, object?> { ["brightness_pct"] = brightness })
{ Intent = brightness == 0 ? DeviceCommandIntent.TurnRelaxationLightOff : DeviceCommandIntent.TurnRelaxationLightOn };
}, "灯光亮度", 0, 100),
new("color_temp", PrimaryEntityId, value => new("设置灯光色温", PrimaryEntityId, "light", "turn_on",
new Dictionary<string, object?> { ["color_temp_kelvin"] = DeviceValues.Integer(value, 2200, 5000, "灯光色温") })
{ Intent = DeviceCommandIntent.TurnRelaxationLightOn },
"灯光色温", 2200, 5000)
];
}
public override string Key => "lighting";
public override string Category => nameof(HealthDeviceCategory.Lighting);
public override string DisplayName => "卧室灯光";
public override string PrimaryEntityId => _entities.AmbientLight;
public override IReadOnlyList<DeviceParameterDefinition> Parameters { get; }
public override async Task ExecuteParameterAsync(DeviceCommand command, CancellationToken cancellationToken)
{
// 标准手动面板复用本灯的专属安全钩子;其他灯不会触发主灯关灯事件。
command = command with { Intent = command.Service == "turn_off"
? DeviceCommandIntent.TurnRelaxationLightOff : DeviceCommandIntent.TurnRelaxationLightOn };
await _transition.CancelAsync(cancellationToken);
await Runner.SendAsync(command, cancellationToken);
if (command.Service == "turn_off") await _lightOff.NotifyAsync(cancellationToken);
if (command.ExpectedState is not null) await Runner.VerifyParameterAsync(command, cancellationToken);
}
public override async Task SetPowerAsync(bool turnOn, CancellationToken cancellationToken)
{
if (turnOn) { await _transition.StartSleepAsync(2700, cancellationToken); return; }
await _transition.CancelAsync(cancellationToken);
await Runner.SendAsync(new("关闭助眠灯光", PrimaryEntityId, "light", "turn_off")
{ Intent = DeviceCommandIntent.TurnRelaxationLightOff }, cancellationToken);
await _lightOff.NotifyAsync(cancellationToken);
}
public override async Task ExecuteSleepAsync(DeviceSceneContext context, PersonalizedSceneConfig config,
string constitutionCode, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(PrimaryEntityId) || !context.States.TryGetValue(PrimaryEntityId, out var state) ||
!DeviceActionRunner.IsAvailable(state))
{
context.Results.Add(new() { Name = "开启助眠渐暗灯光", EntityId = PrimaryEntityId,
Status = "Skipped", Message = "灯光未配置或离线" }); return;
}
await context.ExternalAsync("开启助眠渐暗灯光", PrimaryEntityId,
async token => { await _transition.StartSleepAsync(config.LightColorTemperatureKelvin, token); }, cancellationToken);
}
public override IEnumerable<DeviceCommand> GetShutdownCommands()
=> [new("关闭助眠灯光", PrimaryEntityId, "light", "turn_off", ExpectedState: "off")
{ Intent = DeviceCommandIntent.TurnRelaxationLightOff }];
public override HomeAssistantScenePresetItem? BuildPreview(PersonalizedSceneConfig config, string constitutionCode)
=> string.IsNullOrWhiteSpace(PrimaryEntityId) ? null : Preview("开启助眠渐暗灯光",
$"从50%开始,每5秒降低1%,最终关灯 · 色温 {config.LightColorTemperatureKelvin}K",
new() { ["brightness"] = "50%→关闭", ["color_temp"] = $"{config.LightColorTemperatureKelvin}K" });
}