1111
This commit is contained in:
+15
-4
@@ -30,8 +30,13 @@ public sealed class HomeAssistantLightTransitionService : IHostedService, ILight
|
||||
}
|
||||
|
||||
public ILightTransitionRuntime ForEntity(string entityId)
|
||||
=> _lights.TryGetValue(entityId, out var light) ? light
|
||||
: entityId == _primary.GetStatus().EntityId ? _primary
|
||||
=> ResolveLight(entityId);
|
||||
|
||||
public Task<HomeAssistantLightTransitionOutput?> StartSleepIfIdleAsync(string entityId, int kelvin, CancellationToken token)
|
||||
=> ResolveLight(entityId).StartSleepIfIdleAsync(kelvin, token);
|
||||
|
||||
private LightTransitionWorker ResolveLight(string entityId)
|
||||
=> !string.IsNullOrWhiteSpace(entityId) && _lights.TryGetValue(entityId, out var light) ? light
|
||||
: throw new InvalidOperationException("该灯未配置为场景灯");
|
||||
|
||||
public HomeAssistantLightTransitionOutput GetStatus()
|
||||
@@ -44,31 +49,37 @@ public sealed class HomeAssistantLightTransitionService : IHostedService, ILight
|
||||
// 旧助眠/晨起接口只作用于原卧室灯;额外灯由各自场景模块调用。
|
||||
public async Task<HomeAssistantLightTransitionOutput> StartSleepAsync(int kelvin, CancellationToken token)
|
||||
{
|
||||
EnsurePrimaryConfigured();
|
||||
await _primary.StartSleepAsync(kelvin, token);
|
||||
return GetStatus();
|
||||
}
|
||||
public async Task<HomeAssistantLightTransitionOutput> StartWakeAsync(CancellationToken token)
|
||||
{
|
||||
EnsurePrimaryConfigured();
|
||||
await _primary.StartWakeAsync(token);
|
||||
return GetStatus();
|
||||
}
|
||||
public async Task<HomeAssistantLightTransitionOutput> CancelPrimaryAsync(CancellationToken token)
|
||||
{
|
||||
EnsurePrimaryConfigured();
|
||||
await _primary.CancelAsync(token);
|
||||
return GetStatus();
|
||||
}
|
||||
|
||||
private void EnsurePrimaryConfigured()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_primary.GetStatus().EntityId)) throw new InvalidOperationException("卧室灯光未配置");
|
||||
}
|
||||
|
||||
// 一键关闭/场景替换必须取消全部灯的计时任务,防止后续 tick 重新点亮灯。
|
||||
public async Task<HomeAssistantLightTransitionOutput> CancelAsync(CancellationToken token)
|
||||
{
|
||||
foreach (var light in _lights.Values) await light.CancelAsync(token);
|
||||
if (_lights.Count == 0) await _primary.CancelAsync(token);
|
||||
return GetStatus();
|
||||
}
|
||||
public Task StartAsync(CancellationToken token) => Task.CompletedTask;
|
||||
public async Task StopAsync(CancellationToken token)
|
||||
{
|
||||
foreach (var light in _lights.Values) await light.StopAsync(token);
|
||||
if (_lights.Count == 0) await _primary.StopAsync(token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,20 @@ public sealed class HomeAssistantOptions : IConfigurableOptions
|
||||
public int TimeoutSeconds { get; set; } = 15;
|
||||
// 匹配已退役设备的明确实体绑定,不按名称或品牌隐藏设备。
|
||||
public List<string> ExcludedDeviceEntityIds { get; set; } = [];
|
||||
public bool OnlyConfiguredDevices { get; set; }
|
||||
public List<DisplayOnlyDeviceOptions> DisplayOnlyDevices { get; set; } = [];
|
||||
public HomeAssistantEntityOptions Entities { get; set; } = new();
|
||||
public HomeAssistantSleepSceneOptions SleepScene { get; set; } = new();
|
||||
public List<SceneLightOptions> AdditionalSleepLights { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class DisplayOnlyDeviceOptions
|
||||
{
|
||||
public string EntityId { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Category { get; set; } = "Other";
|
||||
}
|
||||
|
||||
/// <summary>明确加入舒睡/全关的额外灯具;未配置的灯仍仅提供单独控制。</summary>
|
||||
public sealed class SceneLightOptions
|
||||
{
|
||||
|
||||
+8
@@ -71,10 +71,18 @@ internal sealed class LightTransitionWorker : ILightTransitionRuntime
|
||||
}
|
||||
|
||||
public async Task<HomeAssistantLightTransitionOutput> StartSleepAsync(int colorTemperatureKelvin, CancellationToken cancellationToken)
|
||||
=> (await StartSleepCoreAsync(colorTemperatureKelvin, onlyIfIdle: false, cancellationToken))!;
|
||||
|
||||
internal Task<HomeAssistantLightTransitionOutput?> StartSleepIfIdleAsync(int colorTemperatureKelvin, CancellationToken cancellationToken)
|
||||
=> StartSleepCoreAsync(colorTemperatureKelvin, onlyIfIdle: true, cancellationToken);
|
||||
|
||||
private async Task<HomeAssistantLightTransitionOutput?> StartSleepCoreAsync(int colorTemperatureKelvin, bool onlyIfIdle,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await _operationLock.WaitAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
if (onlyIfIdle && GetStatus().Running) return null;
|
||||
await StopCurrentAsync();
|
||||
var light = await ReadAvailableLightAsync(cancellationToken);
|
||||
var data = BuildSleepStartData(light, colorTemperatureKelvin);
|
||||
|
||||
Reference in New Issue
Block a user