This commit is contained in:
fuenmao
2026-11-12 15:45:52 +08:00
parent 61e25175db
commit 718b138033
30 changed files with 1511 additions and 99 deletions
@@ -193,6 +193,53 @@ public sealed class DeviceArchitectureTests
Assert.Empty(gateway.Calls);
}
[Fact]
public async Task FragranceManualControlsUseTheirOwnDeviceAndKeepWakeOutOfSleepScenes()
{
var services = new ServiceCollection();
services.AddLogging(); services.AddOptions(); services.AddHttpClient(); services.AddHealthDevices();
var gateway = new FakeHaGateway();
services.AddSingleton<IHomeAssistantGateway>(gateway);
services.AddSingleton(Options.Create(new HomeAssistantOptions
{
OnlyConfiguredDevices = true,
Entities = new()
{
FragranceSwitch = "switch.sleep_fragrance", FragranceDuration = "number.sleep_duration",
FragranceQuickRelease = "button.sleep_release",
WakeFragranceSwitch = "switch.wake_fragrance", WakeFragranceDuration = "number.wake_duration",
WakeFragranceQuickRelease = "button.wake_release"
}
}));
using var provider = services.BuildServiceProvider();
var registry = provider.GetRequiredService<DeviceModuleRegistry>();
var catalog = provider.GetRequiredService<HomeAssistantDeviceCatalog>();
var parameters = provider.GetRequiredService<DeviceParameterController>();
var sleep = Assert.Single(registry.Modules, module => module.Key == "fragrance");
var wake = Assert.Single(registry.Modules, module => module.Key == "wake-fragrance");
foreach (var id in sleep.EntityIds.Concat(wake.EntityIds))
gateway.States[id] = new() { EntityId = id, State = "off" };
var inventory = catalog.BuildDiscoveredDevices(null, gateway.States);
var sleepDevice = Assert.Single(inventory, device => device.ModuleKey == sleep.Key);
var wakeDevice = Assert.Single(inventory, device => device.ModuleKey == wake.Key);
Assert.Equal("switch.wake_fragrance", wakeDevice.PrimaryControlEntityId);
await wake.SetPowerAsync(true, default);
await parameters.ExecuteAsync(wakeDevice, gateway.States, "wake_fragrance_duration", 5, null, default);
await parameters.ExecuteAsync(wakeDevice, gateway.States, "wake_fragrance_quick_release", true, null, default);
await parameters.ExecuteAsync(sleepDevice, gateway.States, "fragrance_duration", 3, null, default);
await Assert.ThrowsAsync<InvalidOperationException>(() => parameters.ExecuteAsync(
wakeDevice, gateway.States, "fragrance_quick_release", true, null, default));
await Assert.ThrowsAsync<InvalidOperationException>(() => parameters.ExecuteAsync(
sleepDevice, gateway.States, "wake_fragrance_quick_release", true, null, default));
Assert.Equal(new[] { "switch.wake_fragrance", "number.wake_duration", "button.wake_release", "number.sleep_duration" },
gateway.Calls.Select(command => command.EntityId));
Assert.Null(wake.BuildPreview(new(), "balanced"));
Assert.Empty(wake.GetShutdownCommands());
var context = new DeviceSceneContext(Runner(gateway), gateway.States, []);
await wake.ExecuteSleepAsync(context, new() { EnableFragrance = true }, "balanced", default);
Assert.Equal(4, gateway.Calls.Count);
}
[Fact]
public async Task ShutdownContinuesAfterAnIndividualDeviceFailure()
{