• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

net-daemon / netdaemon / 13218430318

08 Feb 2025 06:58PM UTC coverage: 83.697% (-0.04%) from 83.737%
13218430318

push

github

web-flow
Strongly-type EntityState.Attributes (#1251)

For those working with base entities (such as the IHaRegistry API), the virtual property/covariant return override approach isn't helpful. The base property will always return a `Dictionary<string, object>`, which can be useful to iterate through. Instead, we should have strongly-typed derived class _hide_ the base property, so users who are just working with pure entities get a useful key/value pair, and derived users get strongly-typed info.

Co-authored-by: Tomas Hellström <tomas.hellstrom@yahoo.se>

842 of 1139 branches covered (73.92%)

Branch coverage included in aggregate %.

2 of 4 new or added lines in 2 files covered. (50.0%)

1 existing line in 1 file now uncovered.

3337 of 3854 relevant lines covered (86.59%)

919.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.73
/src/HassModel/NetDeamon.HassModel/Entities/EntityState.cs
1
namespace NetDaemon.HassModel.Entities;
2

3
/// <summary>
4
/// Detailed state information
5
/// </summary>
6
public record EntityState
7
{
8
    /// <summary>Unique id of the entity</summary>
9
    [JsonPropertyName("entity_id")] public string EntityId { get; init; } = "";
269✔
10

11
    /// <summary>The state </summary>
12
    [JsonPropertyName("state")] public string? State { get; init; }
479✔
13

14
    /// <summary>The attributes as a JsonElement</summary>
15
    [JsonPropertyName("attributes")] public JsonElement? AttributesJson { get; init; }
159✔
16

17
    /// <summary>
18
    /// The attributes
19
    /// </summary>
NEW
20
    public Dictionary<string, object>? Attributes => AttributesJson?.Deserialize<Dictionary<string, object>>() ?? [];
×
21

22
    /// <summary>Last changed, when state changed from and to different values</summary>
23
    [JsonPropertyName("last_changed")] public DateTime? LastChanged { get; init; }
76✔
24

25
    /// <summary>Last updated, when entity state or attributes changed </summary>
26
    [JsonPropertyName("last_updated")] public DateTime? LastUpdated { get; init; }
76✔
27

28
    /// <summary>Context</summary>
29
    [JsonPropertyName("context")] public Context? Context { get; init; }
83✔
30

31
    internal static TEntityState? Map<TEntityState>(EntityState? state)
32
        where TEntityState : class =>
33
        state == null ? null : (TEntityState)Activator.CreateInstance(typeof(TEntityState), state)!;
133!
34
}
35

36
/// <summary>
37
/// Generic EntityState with specific types of State and Attributes
38
/// </summary>
39
/// <typeparam name="TAttributes">The type of the Attributes Property</typeparam>
40
public record EntityState<TAttributes> : EntityState
41
    where TAttributes : class
42
{
43
    private readonly Lazy<TAttributes?> _attributesLazy;
44

45
    /// <summary>
46
    /// Copy constructor from base class
47
    /// </summary>
48
    /// <param name="source"></param>
49
    public EntityState(EntityState source) : base(source)
128✔
50
    {
51
        _attributesLazy = new (() => AttributesJson?.Deserialize<TAttributes>() ?? default);
153✔
52
    }
128✔
53

54
    /// <inheritdoc/>
55
    public new virtual TAttributes? Attributes => _attributesLazy.Value;
25✔
56
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc