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

net-daemon / netdaemon / 6682362857

29 Oct 2023 08:56AM UTC coverage: 79.505% (-1.2%) from 80.706%
6682362857

push

github

web-flow
Bump Roslynator.Analyzers from 4.5.0 to 4.6.1 (#960)

Bumps [Roslynator.Analyzers](https://github.com/dotnet/roslynator) from 4.5.0 to 4.6.1.
- [Release notes](https://github.com/dotnet/roslynator/releases)
- [Changelog](https://github.com/dotnet/roslynator/blob/main/ChangeLog.md)
- [Commits](https://github.com/dotnet/roslynator/compare/v4.5.0...v4.6.1)

---
updated-dependencies:
- dependency-name: Roslynator.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

802 of 1143 branches covered (0.0%)

Branch coverage included in aggregate %.

2895 of 3507 relevant lines covered (82.55%)

50.4 hits per line

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

86.08
/src/Client/NetDaemon.HassClient/Internal/HomeAssistantClient.cs
1
namespace NetDaemon.Client.Internal;
2

3
internal class HomeAssistantClient(ILogger<IHomeAssistantClient> logger,
25✔
4
        IWebSocketClientFactory webSocketClientFactory,
25✔
5
        IWebSocketClientTransportPipelineFactory transportPipelineFactory,
25✔
6
        IHomeAssistantConnectionFactory connectionFactory)
25✔
7
    : IHomeAssistantClient
8
{
9
    public Task<IHomeAssistantConnection> ConnectAsync(string host, int port, bool ssl, string token,
10
        CancellationToken cancelToken)
11
    {
12
        return ConnectAsync(host, port, ssl, token, HomeAssistantSettings.DefaultWebSocketPath, cancelToken);
×
13
    }
14

15
    public async Task<IHomeAssistantConnection> ConnectAsync(string host, int port, bool ssl, string token,
16
        string websocketPath,
17
        CancellationToken cancelToken)
18
    {
19
        var websocketUri = GetHomeAssistantWebSocketUri(host, port, ssl, websocketPath);
24✔
20
        logger.LogDebug("Connecting to Home Assistant websocket on {Path}", websocketUri);
24✔
21
        var ws = webSocketClientFactory.New();
24✔
22

23
        try
24
        {
25
            await ws.ConnectAsync(websocketUri, cancelToken).ConfigureAwait(false);
24✔
26

27
            var transportPipeline = transportPipelineFactory.New(ws);
23✔
28

29
            var hassVersionInfo = await HandleAuthorizationSequenceAndReturnHassVersionInfo(token, transportPipeline, cancelToken).ConfigureAwait(false);
23✔
30

31
            if (VersionHelper.ReplaceBeta(hassVersionInfo) >= new Version(2022, 9))
22✔
32
            {
33
                await AddCoalesceSupport(transportPipeline, cancelToken).ConfigureAwait(false);
2✔
34
            }
35

36
            var connection = connectionFactory.New(transportPipeline);
22✔
37

38
            if (await CheckIfRunning(connection, cancelToken).ConfigureAwait(false)) return connection;
43✔
39
            await connection.DisposeAsync().ConfigureAwait(false);
1✔
40
            throw new HomeAssistantConnectionException(DisconnectReason.NotReady);
1✔
41
        }
42
        catch (OperationCanceledException)
×
43
        {
44
            logger.LogDebug("Connect to Home Assistant was cancelled");
×
45
            throw;
×
46
        }
47
        catch (Exception e)
3✔
48
        {
49
            logger.LogDebug(e, "Error connecting to Home Assistant");
3✔
50
            throw;
3✔
51
        }
52
    }
21✔
53

54
    private static async Task AddCoalesceSupport(IWebSocketClientTransportPipeline transportPipeline, CancellationToken cancelToken)
55
    {
56
        var supportedFeaturesCommandMsg = new SupportedFeaturesCommand
2✔
57
            {Id = 1, Features = new Features() { CoalesceMessages = 1 }};
2✔
58

59
        // Send the supported features command
60
        await transportPipeline.SendMessageAsync(
2✔
61
            supportedFeaturesCommandMsg,
2✔
62
            cancelToken
2✔
63
        ).ConfigureAwait(false);
2✔
64

65
        // Get the result from command
66
        var resultMsg = await transportPipeline
2✔
67
            .GetNextMessagesAsync<HassMessage>(cancelToken).ConfigureAwait(false);
2✔
68

69
        if (resultMsg.Single().Success == true)
2!
70
        {
71
            return;
2✔
72
        }
73
        throw new InvalidOperationException($"Failed to get result from supported feature command : {resultMsg.Single()}");
×
74
    }
2✔
75

76
    private static Uri GetHomeAssistantWebSocketUri(string host, int port, bool ssl, string websocketPath)
77
    {
78
        return new Uri($"{(ssl ? "wss" : "ws")}://{host}:{port}/{websocketPath}");
24✔
79
    }
80

81
    private static async Task<bool> CheckIfRunning(IHomeAssistantConnection connection, CancellationToken cancelToken)
82
    {
83
        var connectTimeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
22✔
84
        connectTimeoutTokenSource.CancelAfter(5000);
22✔
85
        // Now send the auth message to Home Assistant
86
        var config = await connection
22!
87
                         .SendCommandAndReturnResponseAsync<SimpleCommand, HassConfig>
22✔
88
                             (new SimpleCommand("get_config"), cancelToken).ConfigureAwait(false) ??
22✔
89
                     throw new NullReferenceException("Unexpected null return from command");
22✔
90

91
        return config.State == "RUNNING";
22✔
92
    }
22✔
93

94
    private static async Task<string> HandleAuthorizationSequenceAndReturnHassVersionInfo(string token,
95
        IWebSocketClientTransportPipeline transportPipeline, CancellationToken cancelToken)
96
    {
97
        var connectTimeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
23✔
98
        connectTimeoutTokenSource.CancelAfter(5000);
23✔
99
        // Begin the authorization sequence
100
        // Expect 'auth_required'
101
        var msg = await transportPipeline.GetNextMessagesAsync<HassMessage>(connectTimeoutTokenSource.Token)
23✔
102
            .ConfigureAwait(false);
23✔
103
        if (msg[0].Type != "auth_required")
23!
104
            throw new ApplicationException($"Unexpected type: '{msg[0].Type}' expected 'auth_required'");
×
105

106
        // Now send the auth message to Home Assistant
107
        await transportPipeline.SendMessageAsync(
23✔
108
            new HassAuthMessage {AccessToken = token},
23✔
109
            connectTimeoutTokenSource.Token
23✔
110
        ).ConfigureAwait(false);
23✔
111
        // Now get the result
112
        var authResultMessage = await transportPipeline
23✔
113
            .GetNextMessagesAsync<HassAuthResponse>(connectTimeoutTokenSource.Token).ConfigureAwait(false);
23✔
114

115
        switch (authResultMessage.Single().Type)
23!
116
        {
117
            case "auth_ok":
118

119
                return authResultMessage[0].HaVersion;
22✔
120

121
            case "auth_invalid":
122
                await transportPipeline.CloseAsync().ConfigureAwait(false);
1✔
123
                throw new HomeAssistantConnectionException(DisconnectReason.Unauthorized);
1✔
124

125
            default:
126
                throw new ApplicationException($"Unexpected response ({authResultMessage.Single().Type})");
×
127
        }
128
    }
22✔
129
}
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