From f3c00dffc9c52ef40cb3ac708036d83827cc05e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Hellstr=C3=B6m?= Date: Sun, 28 Apr 2024 20:55:51 +0200 Subject: [PATCH] Added support for floors and labels to the ServiceTarget class (#1084) * Added support for floors and labels to the ServiceTarget class * Added tests * Removed all Focus attributes from debug project * Removed the focus attribute for registry app as well --- .../Common/HomeAssistant/Model/Targets.cs | 14 ++++- .../AppScopedHaContextProviderTest.cs | 54 +++++++++++++++++-- .../Internal/HassObjectMapper.cs | 4 +- .../NetDeamon.HassModel/ServiceTarget.cs | 12 ++++- .../DebugHost/apps/Client/ClientDebug.cs | 1 - src/debug/DebugHost/apps/Client/LabelDebug.cs | 1 - src/debug/DebugHost/apps/Config/ConfigApp.cs | 1 - .../DebugHost/apps/HaRegistry/RegistryApp.cs | 22 ++++++++ src/debug/DebugHost/apps/HelloApp/HelloApp.cs | 1 - src/debug/DebugHost/apps_src/hellow.cs | 1 - .../MyInterfaceAutomation/InterfaceUsage.cs | 2 +- 11 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 src/debug/DebugHost/apps/HaRegistry/RegistryApp.cs diff --git a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/Targets.cs b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/Targets.cs index 46937dbf5..91541bd36 100644 --- a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/Targets.cs +++ b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/Targets.cs @@ -22,4 +22,16 @@ public record HassTarget /// [JsonPropertyName("area_id")] public IReadOnlyCollection? AreaIds { get; init; } -} \ No newline at end of file + + /// + /// Zero or more floor ids to target with the service call + /// + [JsonPropertyName("floor_id")] + public IReadOnlyCollection? FloorIds { get; init; } + + /// + /// Zero or more floor ids to target with the service call + /// + [JsonPropertyName("label_id")] + public IReadOnlyCollection? LabelIds { get; init; } +} diff --git a/src/HassModel/NetDaemon.HassModel.Tests/Internal/AppScopedHaContextProviderTest.cs b/src/HassModel/NetDaemon.HassModel.Tests/Internal/AppScopedHaContextProviderTest.cs index 0164d5433..c1cc1aa00 100644 --- a/src/HassModel/NetDaemon.HassModel.Tests/Internal/AppScopedHaContextProviderTest.cs +++ b/src/HassModel/NetDaemon.HassModel.Tests/Internal/AppScopedHaContextProviderTest.cs @@ -47,6 +47,54 @@ public async void TestCallService() It.IsAny()), Times.Once); } + [Fact] + public async void TestCallServiceWithFloor() + { + var haContext = await CreateTargetAsync(); + + var target = new ServiceTarget { FloorIds = ["floor1", "floor2"] }; + var data = new { Name = "value" }; + haContext.CallService("domain", "service", target, data); + + var expectedCommand = new CallServiceCommand + { + Domain = "domain", + Service = "service", + ServiceData = data, + Target = new HassTarget + { + FloorIds = target.FloorIds + } + }; + _hassConnectionMock.Verify( + c => c.SendCommandAsync(expectedCommand, + It.IsAny()), Times.Once); + } + + [Fact] + public async void TestCallServiceWithLabel() + { + var haContext = await CreateTargetAsync(); + + var target = new ServiceTarget { LabelIds = ["label1", "label2"] }; + var data = new { Name = "value" }; + haContext.CallService("domain", "service", target, data); + + var expectedCommand = new CallServiceCommand + { + Domain = "domain", + Service = "service", + ServiceData = data, + Target = new HassTarget + { + LabelIds = target.LabelIds + } + }; + _hassConnectionMock.Verify( + c => c.SendCommandAsync(expectedCommand, + It.IsAny()), Times.Once); + } + [Fact] public async Task TestCallServiceWithResponseAsync() { @@ -266,7 +314,7 @@ private async Task CreateServiceProvider() serviceCollection.AddScopedHaContext(); var backgroundTaskTrackerMock = new Mock(); - serviceCollection.AddScoped>(_=> backgroundTaskTrackerMock); + serviceCollection.AddScoped>(_ => backgroundTaskTrackerMock); serviceCollection.AddScoped(_ => backgroundTaskTrackerMock.Object); var provider = serviceCollection.BuildServiceProvider(); @@ -280,7 +328,7 @@ public record TestEventData(string command, int endpoint_id, string otherField); public void Dispose() { - _hassEventSubjectMock.Dispose(); - GC.SuppressFinalize(this); + _hassEventSubjectMock.Dispose(); + GC.SuppressFinalize(this); } } diff --git a/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs b/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs index 7ab893975..f38ebdb0c 100644 --- a/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs +++ b/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs @@ -40,7 +40,9 @@ public static StateChange Map(this HassStateChangedEventData source, IHaContext { AreaIds = target.AreaIds, DeviceIds = target.DeviceIds, - EntityIds = target.EntityIds + EntityIds = target.EntityIds, + FloorIds = target.FloorIds, + LabelIds = target.LabelIds }; } diff --git a/src/HassModel/NetDeamon.HassModel/ServiceTarget.cs b/src/HassModel/NetDeamon.HassModel/ServiceTarget.cs index 03fae8a37..c9f288cf7 100644 --- a/src/HassModel/NetDeamon.HassModel/ServiceTarget.cs +++ b/src/HassModel/NetDeamon.HassModel/ServiceTarget.cs @@ -49,4 +49,14 @@ public ServiceTarget() /// Ids of Areas to invoke a service on /// public IReadOnlyCollection? AreaIds { get; init; } -} \ No newline at end of file + + /// + /// Ids of floors to invoke a service on + /// + public IReadOnlyCollection? FloorIds { get; init; } + + /// + /// Ids of labels to invoke a service on + /// + public IReadOnlyCollection? LabelIds { get; init; } +} diff --git a/src/debug/DebugHost/apps/Client/ClientDebug.cs b/src/debug/DebugHost/apps/Client/ClientDebug.cs index c1f361eb2..69089dec0 100644 --- a/src/debug/DebugHost/apps/Client/ClientDebug.cs +++ b/src/debug/DebugHost/apps/Client/ClientDebug.cs @@ -5,7 +5,6 @@ namespace Apps; [NetDaemonApp] -// [Focus] public sealed class ClientApp : IAsyncDisposable { private readonly ILogger _logger; diff --git a/src/debug/DebugHost/apps/Client/LabelDebug.cs b/src/debug/DebugHost/apps/Client/LabelDebug.cs index f62c5b81c..c90b3848b 100644 --- a/src/debug/DebugHost/apps/Client/LabelDebug.cs +++ b/src/debug/DebugHost/apps/Client/LabelDebug.cs @@ -8,7 +8,6 @@ namespace Apps; [NetDaemonApp] -[Focus] public sealed class LabelApp : IAsyncInitializable { private readonly ILogger _logger; diff --git a/src/debug/DebugHost/apps/Config/ConfigApp.cs b/src/debug/DebugHost/apps/Config/ConfigApp.cs index b2b9cd333..b789b9eda 100644 --- a/src/debug/DebugHost/apps/Config/ConfigApp.cs +++ b/src/debug/DebugHost/apps/Config/ConfigApp.cs @@ -3,7 +3,6 @@ namespace Apps; [NetDaemonApp] -// [Focus] public class ConfigApp { public ConfigApp(IAppConfig config) diff --git a/src/debug/DebugHost/apps/HaRegistry/RegistryApp.cs b/src/debug/DebugHost/apps/HaRegistry/RegistryApp.cs new file mode 100644 index 000000000..7c21216ac --- /dev/null +++ b/src/debug/DebugHost/apps/HaRegistry/RegistryApp.cs @@ -0,0 +1,22 @@ +using System.Reactive.Linq; +using Microsoft.Extensions.Logging; +using NetDaemon.AppModel; +using NetDaemon.HassModel; +using NetDaemon.HassModel.Entities; +namespace Apps; + +[NetDaemonApp] +public sealed class RegistryApp +{ + public RegistryApp(IHaRegistry haRegistry, IHaContext ha) + { + // var floor = haRegistry.GetFloor("upstairs"); + // var upstairsAreas = floor.Areas; + // var upstairsBooleans = upstairsAreas + // .SelectMany(n => n.Entities + // .Where(x => x.EntityId.StartsWith("input_boolean."))); + // + // upstairsBooleans.ToList().ForEach(x => x.CallService("toggle")); + ha.CallService("input_boolean", "toggle", new ServiceTarget{ FloorIds = ["upstairs"] }); + } +} diff --git a/src/debug/DebugHost/apps/HelloApp/HelloApp.cs b/src/debug/DebugHost/apps/HelloApp/HelloApp.cs index c61bb667a..97e52b3aa 100644 --- a/src/debug/DebugHost/apps/HelloApp/HelloApp.cs +++ b/src/debug/DebugHost/apps/HelloApp/HelloApp.cs @@ -6,7 +6,6 @@ namespace Apps; [NetDaemonApp] -[Focus] public sealed class HelloApp : IAsyncDisposable { private readonly ILogger _logger; diff --git a/src/debug/DebugHost/apps_src/hellow.cs b/src/debug/DebugHost/apps_src/hellow.cs index 0e3d5d569..0e2a8156c 100644 --- a/src/debug/DebugHost/apps_src/hellow.cs +++ b/src/debug/DebugHost/apps_src/hellow.cs @@ -6,7 +6,6 @@ namespace Apps; [NetDaemonApp] -[Focus] public sealed class HelloAppSrc : IAsyncDisposable { private readonly ILogger _logger; diff --git a/src/debug/MyNDApp/apps/HassModel/MyInterfaceAutomation/InterfaceUsage.cs b/src/debug/MyNDApp/apps/HassModel/MyInterfaceAutomation/InterfaceUsage.cs index 2d4a24a81..87a87cd22 100644 --- a/src/debug/MyNDApp/apps/HassModel/MyInterfaceAutomation/InterfaceUsage.cs +++ b/src/debug/MyNDApp/apps/HassModel/MyInterfaceAutomation/InterfaceUsage.cs @@ -11,7 +11,7 @@ namespace Debug.apps.HassModel.MyInterfaceAutomation; [NetDaemonApp] -[Focus] +//[Focus] public class InterfaceUsage { public InterfaceUsage(IHaContext haContext, ILogger logger, IScheduler scheduler)