Skip to content

Commit

Permalink
Handel changed service metadata json with multiple targets entities (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankBakkerNl authored Apr 6, 2023
1 parent 7fbcc0f commit 4b5b3c4
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static IEnumerable<MemberDeclarationSyntax> Generate(IEnumerable<HassServ
private static IEnumerable<MemberDeclarationSyntax> GenerateExtensionMethodsForService(string domain, HassService service, ILookup<string, string> entityClassNameByDomain)
{
// There can be multiple Target Domains, so generate methods for each
var targetEntityDomains = service.Target?.Entity?.Domain ?? Array.Empty<string>();
var targetEntityDomains = service.Target?.Entity.SelectMany(e => e.Domain) ?? Array.Empty<string>();

return targetEntityDomains.SelectMany(targetEntityDomain => GenerateExtensionMethodsForService(domain, service, targetEntityDomain, entityClassNameByDomain));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ internal record NumberSelector : Selector

internal record TargetSelector : Selector
{
public AreaSelector? Area { get; init; }

public DeviceSelector? Device { get; init; }

public EntitySelector? Entity { get; init; }
[JsonConverter(typeof(SingleObjectAsArrayConverter<EntitySelector>))]
public EntitySelector[] Entity { get; init; } = Array.Empty<EntitySelector>();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Text.Json.Serialization;

namespace NetDaemon.HassModel.CodeGenerator.Model;

/// <summary>
/// Converts either a single object or an array to an array
/// </summary>
class SingleObjectAsArrayConverter<T> : JsonConverter<T[]>
{
public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.StartObject)
{
return new [] { JsonSerializer.Deserialize<T>(ref reader, options)! };
}

return JsonSerializer.Deserialize<T[]>(ref reader, options);
}

public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options)
=> throw new NotSupportedException();
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public void TestNumberExtensionMethodGeneration()
new() {
Service = "set_value",
Target = new TargetSelector {
Entity = new() { Domain = new [] {"number"} }
Entity = new[] { new EntitySelector { Domain = new[] { "number" } } }
},
Fields = new HassServiceField[] {
new() { Field = "value", Selector = new NumberSelector(), },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void TestSomeBasicServicesCanBeParsed()
var res = ServiceMetaDataParser.Parse(element);
res.Should().HaveCount(1);
res.First().Domain.Should().Be("homeassistant");
res.First().Services.ElementAt(1).Target!.Entity!.Domain.Should().BeEmpty();
res.First().Services.ElementAt(1).Target!.Entity.SelectMany(e=>e.Domain).Should().BeEmpty();
}

[Fact]
Expand Down Expand Up @@ -112,6 +112,38 @@ public void TestMultiDomainTargetWithRequiredFieldAsString()
result.First().Services.First().Fields!.First().Required.Should().BeTrue();
}

[Fact]
public void DeserializeTargetEntityArray()
{
var sample = """
{
"testdomain": {
"purge_entities":{
"name":"Purge Entities",
"fields":{
},
"target":{
"entity":[
{
"domain":"targetdomain1"
},
{
"domain":["targetdomain2", "targetdomain3"]
}

]
}
}
}
}
""";
var result = Parse(sample);
result.First().Services.First().Target!.Entity.Should().HaveCount(2);
result.First().Services.First().Target!.Entity[0].Domain.Should().Equal("targetdomain1");
result.First().Services.First().Target!.Entity[1].Domain.Should().Equal("targetdomain2", "targetdomain3");

}

private static IReadOnlyCollection<HassServiceDomain> Parse(string sample)
{
var element = JsonDocument.Parse(sample).RootElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,22 @@ public void TestServicesGeneration()
Services = new HassService[] {
new() {
Service = "turn_off",
Target = new TargetSelector { Entity = new() { Domain = new [] {"light"} } }
Target = new TargetSelector
{
Entity = new[] { new EntitySelector { Domain = new[] { "light" } } }
}

},
new() {
Service = "turn_on",
Fields = new HassServiceField[] {
new() { Field = "transition", Selector = new NumberSelector(), },
new() { Field = "brightness", Selector = new NumberSelector { Step = 0.2f }, }
},
Target = new TargetSelector { Entity = new() { Domain = new [] {"light" } } }
Target = new TargetSelector
{
Entity = new[] { new EntitySelector { Domain = new[] { "light" } } }
}
}
}
}
Expand Down Expand Up @@ -82,12 +89,18 @@ public void TestServiceWithoutAnyTargetEntity_ExtensionMethodSkipped()
Domain = "smart_things",
Services = new HassService[] {
new() {
Service = "dig",
Target = new TargetSelector { Entity = new() { Domain = new [] {"humidifiers"} } },
Service = "dig",
Target = new TargetSelector
{
Entity = new[] { new EntitySelector { Domain = new[] { "humidifiers" } } }
},
},
new() {
Service = "orbit",
Target = new TargetSelector { Entity = new() { Domain = new [] {"orbiter" }} },
Target = new TargetSelector
{
Entity = new[] { new EntitySelector { Domain = new[] { "orbiter" } } }
},
}
},
}
Expand Down Expand Up @@ -134,7 +147,10 @@ public void TestServiceWithoutAnyMethods_ClassSkipped()
Services = new HassService[] {
new() {
Service = "push_button",
Target = new TargetSelector { Entity = new() { Domain = new [] {"uselessbox" }} },
Target = new TargetSelector
{
Entity = new[] { new EntitySelector { Domain = new[] { "uselessbox" } } }
},
},
},
}
Expand Down Expand Up @@ -178,7 +194,7 @@ public void TestServiceWithKeyWordFieldName_ParamEscaped()
new() {
Service = "set_value",
Target = new TargetSelector {
Entity = new() { Domain = new [] {"light"} }
Entity = new[] { new EntitySelector { Domain = new[] { "light" } } }
},
Fields = new HassServiceField[] {
new() { Field = "class", Selector = new NumberSelector(), },
Expand Down

0 comments on commit 4b5b3c4

Please sign in to comment.