This commit is contained in:
fuenmao
2026-11-11 16:11:41 +08:00
parent 3ca90c4cf3
commit 61e25175db
39 changed files with 2176 additions and 31 deletions
@@ -147,6 +147,52 @@ public sealed class DeviceArchitectureTests
Assert.Equal("light.bedroom", device.PrimaryControlEntityId);
}
[Fact]
public async Task Configured_inventory_filters_retired_devices_even_if_ha_cache_still_reports_them()
{
var services = new ServiceCollection();
services.AddLogging(); services.AddOptions(); services.AddHttpClient(); services.AddHealthDevices();
var gateway = new FakeHaGateway { ReadsToFail = 1 };
services.AddSingleton<IHomeAssistantGateway>(gateway);
services.AddSingleton(Options.Create(new HomeAssistantOptions
{
OnlyConfiguredDevices = true,
Entities = new()
{
Climate = "climate.keep", Temperature = "sensor.keep_temperature", Curtain = "cover.keep",
Dehumidifier = "humidifier.keep", FragranceSwitch = "switch.keep_fragrance", Speaker = "media_player.keep"
},
DisplayOnlyDevices = [new() { EntityId = "switch.wake_fragrance", Name = "香氛机 唤醒", Category = "Fragrance" }]
}));
using var provider = services.BuildServiceProvider();
var entities = new[] { "climate.keep", "sensor.keep_temperature", "cover.keep", "humidifier.keep",
"switch.keep_fragrance", "media_player.keep", "switch.wake_fragrance", "light.removed", "switch.removed_outlet", "sensor.removed_weight" };
var registry = new HomeAssistantRegistries
{
Devices = entities.Select(id => new HomeAssistantDeviceRegistryItem { Id = id, Name = id }).ToList(),
Entities = entities.Select(id => new HomeAssistantEntityRegistryItem { DeviceId = id, EntityId = id }).ToList()
};
var state = entities.ToDictionary(id => id, id => new HomeAssistantState { EntityId = id, State = "on" });
var catalog = provider.GetRequiredService<HomeAssistantDeviceCatalog>();
foreach (var inventory in new[] { catalog.BuildDiscoveredDevices(registry, state), catalog.BuildDiscoveredDevices(null, state) })
{
Assert.Equal(7, inventory.Count);
Assert.DoesNotContain(inventory.SelectMany(device => device.Entities), entity => entity.EntityId.Contains("removed"));
var wake = Assert.Single(inventory, device => device.Entities.Any(entity => entity.EntityId == "switch.wake_fragrance"));
Assert.Null(wake.PrimaryControlEntityId);
Assert.True(wake.Online);
var sleep = Assert.Single(inventory, device => device.Entities.Any(entity => entity.EntityId == "switch.keep_fragrance"));
Assert.Equal("switch.keep_fragrance", sleep.PrimaryControlEntityId);
}
var modules = provider.GetRequiredService<DeviceModuleRegistry>();
Assert.DoesNotContain(modules.Modules, module => module.Key is "lighting" or "outlet");
Assert.Throws<InvalidOperationException>(() => modules.ForParameter("brightness"));
var lights = provider.GetRequiredService<HomeAssistantLightTransitionService>();
await Assert.ThrowsAsync<InvalidOperationException>(() => lights.StartSleepAsync(2700, default));
Assert.Equal(1, gateway.ReadsToFail);
Assert.Empty(gateway.Calls);
}
[Fact]
public async Task ShutdownContinuesAfterAnIndividualDeviceFailure()
{
@@ -218,7 +264,7 @@ public sealed class DeviceArchitectureTests
services.AddHealthDevices();
using var provider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true, ValidateScopes = true });
Assert.NotNull(provider.GetRequiredService<HealthSceneCoordinator>());
Assert.Equal(2, provider.GetServices<IHostedService>().Count());
Assert.Equal(4, provider.GetServices<IHostedService>().Count());
Assert.DoesNotContain(provider.GetRequiredService<DeviceModuleRegistry>().Modules, module => module.Key == "mattress");
Assert.Empty(provider.GetServices<ILightOffHandler>());
Assert.Throws<InvalidOperationException>(() => provider.GetRequiredService<DeviceModuleRegistry>().ForParameter("mattress_left_heating"));