Files
2026-11-11 16:11:41 +08:00

49 lines
2.0 KiB
C#

using Evergreen.Health.Application.Health.Integrations.HomeAssistant;
using Evergreen.Health.Application.Health.Scenes;
using Evergreen.Health.Application.Health.Sleep;
using Microsoft.Extensions.Options;
namespace Evergreen.Health.Application.Health.Devices.Curtain;
public sealed class BedPresenceCurtainCloseAction(CurtainModule curtain, DeviceActionRunner runner,
IOptions<HomeAssistantOptions> options) : IBedPresenceAction
{
public string Key => "curtain-close";
public string Description => "关闭窗帘";
public TimeSpan ExecutionTimeout => TimeSpan.FromSeconds(55);
public bool SupportsTarget(string entityId) => options.Value.Enabled &&
entityId?.StartsWith("cover.", StringComparison.Ordinal) == true && entityId == curtain.PrimaryEntityId;
public async Task<string> ExecuteAsync(string entityId, CancellationToken token)
{
if (!SupportsTarget(entityId)) return "target-not-configured";
var state = await runner.ReadAvailableStateAsync(entityId, token);
if (state.State == "closed") return "already-closed";
if (state.State == "closing") return "already-closing";
if (state.State != "open") return "state-not-open";
var close = curtain.BuildParameterCommand("curtain_action", "close");
var command = close with
{
ExpectedState = "closed",
ValidateCurrentState = current =>
{
close.ValidateCurrentState?.Invoke(current);
if (current.State != "open") throw new InvalidOperationException("窗帘状态已改变,跳过关帘");
}
};
await runner.SendAsync(command, token);
try
{
// 机械行程需要较长回读时间。沿用窗帘命令的只读回读配置,失败不重发关帘。
await runner.VerifyParameterAsync(command, token, verificationAttempts: 20);
return "readback-confirmed";
}
catch (InvalidOperationException)
{
return "sent-readback-unconfirmed";
}
}
}