From 4a090e94bd9c508f1616a70a0403918905c79fd8 Mon Sep 17 00:00:00 2001 From: Steven Pelech Date: Wed, 11 Sep 2024 15:45:42 -0500 Subject: [PATCH] Expose Entity Registration Conversation Options (#1167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add deserialization off entity conversation options * add conversation options to HassModel * add HassClient and HassModel test updates for conversation options * add Options handling to HassObjectMapper * remove unused constructor --------- Co-authored-by: Tomas Hellström --- .../Testdata/result_get_entities.json | 61 +++++++++++-------- .../Integration/WebsocketIntegrationTests.cs | 13 ++++ .../Model/HassConversationOptions.cs | 7 +++ .../Common/HomeAssistant/Model/HassEntity.cs | 3 + .../HomeAssistant/Model/HassEntityOptions.cs | 7 +++ .../Registry/RegistryNavigationTest.cs | 37 ++++++++++- .../Internal/HassObjectMapper.cs | 1 + .../Registry/ConversationOptions.cs | 28 +++++++++ .../Registry/EntityOptions.cs | 26 ++++++++ .../Registry/EntityRegistration.cs | 5 ++ 10 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassConversationOptions.cs create mode 100644 src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntityOptions.cs create mode 100644 src/HassModel/NetDeamon.HassModel/Registry/ConversationOptions.cs create mode 100644 src/HassModel/NetDeamon.HassModel/Registry/EntityOptions.cs diff --git a/src/Client/NetDaemon.HassClient.Tests/Integration/Testdata/result_get_entities.json b/src/Client/NetDaemon.HassClient.Tests/Integration/Testdata/result_get_entities.json index 6c3c1b588..35d317131 100644 --- a/src/Client/NetDaemon.HassClient.Tests/Integration/Testdata/result_get_entities.json +++ b/src/Client/NetDaemon.HassClient.Tests/Integration/Testdata/result_get_entities.json @@ -1,26 +1,37 @@ { - "id": 3, - "type": "result", - "success": true, - "result": [ - { - "config_entry_id": null, - "device_id": "42cdda32a2a3428e86c2e27699d79ead", - "disabled_by": null, - "entity_id": "media_player.tv_uppe2", - "area_id": "42cdda1212a3428e86c2e27699d79ead", - "name": null, - "icon": null, - "platform": "cast" - }, - { - "config_entry_id": "4b85129c61c74b27bd90e593f6b7482e", - "device_id": "6e17380a6d2744d18045fe4f627db706", - "disabled_by": null, - "entity_id": "sensor.plex_plex", - "name": null, - "icon": null, - "platform": "plex" - } - ] -} \ No newline at end of file + "id": 3, + "type": "result", + "success": true, + "result": [ + { + "config_entry_id": null, + "device_id": "42cdda32a2a3428e86c2e27699d79ead", + "disabled_by": null, + "entity_id": "media_player.tv_uppe2", + "area_id": "42cdda1212a3428e86c2e27699d79ead", + "name": null, + "icon": null, + "platform": "cast", + "options": { + "conversation": { + "should_expose": true + } + } + + }, + { + "config_entry_id": "4b85129c61c74b27bd90e593f6b7482e", + "device_id": "6e17380a6d2744d18045fe4f627db706", + "disabled_by": null, + "entity_id": "sensor.plex_plex", + "name": null, + "icon": null, + "platform": "plex", + "options": { + "conversation": { + "should_expose": false + } + } + } + ] +} diff --git a/src/Client/NetDaemon.HassClient.Tests/Integration/WebsocketIntegrationTests.cs b/src/Client/NetDaemon.HassClient.Tests/Integration/WebsocketIntegrationTests.cs index c69dd8db7..2681c8d8d 100644 --- a/src/Client/NetDaemon.HassClient.Tests/Integration/WebsocketIntegrationTests.cs +++ b/src/Client/NetDaemon.HassClient.Tests/Integration/WebsocketIntegrationTests.cs @@ -126,6 +126,19 @@ public async Task TestGetEntitiesShouldHaveCorrectCounts() entities.Should().HaveCount(2); } + + [Fact] + public async Task TestGetEntitiesShouldHaveConversationOptions() + { + await using var ctx = await GetConnectedClientContext().ConfigureAwait(false); + var entities = await ctx.HomeAssistantConnection + .GetEntitiesAsync(TokenSource.Token) + .ConfigureAwait(false); + + bool? should_expose = entities?.ElementAt(0).Options?.Conversation?.ShouldExpose; + should_expose.Should().BeTrue(); + } + [Fact] public async Task TestGetConfigShouldReturnCorrectInformation() { diff --git a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassConversationOptions.cs b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassConversationOptions.cs new file mode 100644 index 000000000..58eae5048 --- /dev/null +++ b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassConversationOptions.cs @@ -0,0 +1,7 @@ +namespace NetDaemon.Client.HomeAssistant.Model +{ + public record HassEntityConversationOptions + { + [JsonPropertyName("should_expose")] public bool ShouldExpose { get; init; } + } +} diff --git a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntity.cs b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntity.cs index d3658d7be..4e923d379 100644 --- a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntity.cs +++ b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntity.cs @@ -15,4 +15,7 @@ public record HassEntity [JsonPropertyName("platform")] public string? Platform { get; init; } [JsonPropertyName("labels")] public IReadOnlyList Labels { get; init; } = []; + + [JsonPropertyName("options")]public HassEntityOptions? Options { get; init; } } + diff --git a/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntityOptions.cs b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntityOptions.cs new file mode 100644 index 000000000..44cfd78aa --- /dev/null +++ b/src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassEntityOptions.cs @@ -0,0 +1,7 @@ +namespace NetDaemon.Client.HomeAssistant.Model +{ + public record HassEntityOptions + { + [JsonPropertyName("conversation")] public HassEntityConversationOptions? Conversation { get; init; } + } +} diff --git a/src/HassModel/NetDaemon.HassModel.Tests/Registry/RegistryNavigationTest.cs b/src/HassModel/NetDaemon.HassModel.Tests/Registry/RegistryNavigationTest.cs index 07d82a666..e28b11233 100644 --- a/src/HassModel/NetDaemon.HassModel.Tests/Registry/RegistryNavigationTest.cs +++ b/src/HassModel/NetDaemon.HassModel.Tests/Registry/RegistryNavigationTest.cs @@ -29,14 +29,21 @@ private async Task InitializeCacheAndBuildRegistry() return new HaRegistry(haContextMock.Object, cache); } - [Fact] - public async Task TestNavigateModel() + private void InitializeDataModel() { SetupCommandResult("config/entity_registry/list", [ new HassEntity { EntityId = "light.mb_nightlight", AreaId = "master_bedroom"}, new HassEntity { EntityId = "light.babyroom_nightlight", AreaId = "baby_room", Labels = ["stay_on"] }, new HassEntity { EntityId = "sensor.babyroom_humidity", DeviceId = "24:AB:1B:9A"}, + new HassEntity { EntityId = "light.desk_lamp", AreaId = "study", Options = new HassEntityOptions() + { + Conversation = new HassEntityConversationOptions() + { + ShouldExpose = true + } + } + }, ]); SetupCommandResult("config/device_registry/list", @@ -65,7 +72,13 @@ public async Task TestNavigateModel() new HassLabel { Id = "bedroom", Name = "Bedroom", Description = "Areas that serve as bedrooms" }, new HassLabel { Id = "stay_on", Name = "Stay On", Description = "Lights that should stay on at night" }, ]); + } + [Fact] + public async Task TestNavigateModel() + { + // Setup: + InitializeDataModel(); // Act: var registry = await InitializeCacheAndBuildRegistry(); @@ -77,6 +90,7 @@ public async Task TestNavigateModel() new { Id = "light.mb_nightlight" }, new { Id = "light.babyroom_nightlight" }, new { Id = "sensor.babyroom_humidity" }, + new { Id = "light.desk_lamp"} ]); registry.Devices.Should().BeEquivalentTo( @@ -137,7 +151,24 @@ public async Task TestNavigateModel() } - private void SetupCommandResult(string command, IReadOnlyCollection result) + [Fact] + public async Task TestConversationOptions() + { + // Setup: + InitializeDataModel(); + + // Act: + var registry = await InitializeCacheAndBuildRegistry(); + + registry.GetEntityRegistration("light.desk_lamp")! + .Options! + .ConversationOptions! + .ShouldExpose + .Should() + .BeTrue(); + } + + private void SetupCommandResult(string command, IReadOnlyCollection result) { _connectionMock.Setup(m => m.SendCommandAndReturnResponseAsync>( new SimpleCommand(command), It.IsAny())).ReturnsAsync(result); diff --git a/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs b/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs index e85b04de5..ddceca4e1 100644 --- a/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs +++ b/src/HassModel/NetDeamon.HassModel/Internal/HassObjectMapper.cs @@ -120,6 +120,7 @@ public static EntityRegistration Map(this HassEntity hassEntity, IHaRegistryNavi Device = device, Labels = hassEntity.Labels.Select(registry.GetLabel).OfType