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

net-daemon / netdaemon / 6714879316

29 Oct 2023 10:48AM UTC coverage: 79.419% (-0.09%) from 79.505%
6714879316

push

github

web-flow
On release created now activates a pre-release push to docker and nuget (#980)

* On release created now activates a pre-release push to docker and nuget

* removed bad comment

802 of 1143 branches covered (0.0%)

Branch coverage included in aggregate %.

2891 of 3507 relevant lines covered (82.44%)

50.24 hits per line

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

83.53
/src/Client/NetDaemon.HassClient/Internal/HomeAssistantRunner.cs
1
namespace NetDaemon.Client.Internal;
2

3
internal class HomeAssistantRunner(IHomeAssistantClient client,
8✔
4
    ILogger<IHomeAssistantRunner> logger) : IHomeAssistantRunner
8✔
5
{
6
    // The internal token source will make sure we
7
    // always cancel operations on dispose
8
    private readonly CancellationTokenSource _internalTokenSource = new();
8✔
9
    private readonly Subject<IHomeAssistantConnection> _onConnectSubject = new();
8✔
10

11
    private readonly Subject<DisconnectReason> _onDisconnectSubject = new();
8✔
12

13

14
    private Task? _runTask;
15

16
    public IObservable<IHomeAssistantConnection> OnConnect => _onConnectSubject;
1✔
17
    public IObservable<DisconnectReason> OnDisconnect => _onDisconnectSubject;
5✔
18
    public IHomeAssistantConnection? CurrentConnection { get; internal set; }
34✔
19

20
    public Task RunAsync(string host, int port, bool ssl, string token, TimeSpan timeout,
21
        CancellationToken cancelToken)
22
    {
23
        return RunAsync(host, port, ssl, token, HomeAssistantSettings.DefaultWebSocketPath, timeout, cancelToken);
×
24
    }
25
    public Task RunAsync(string host, int port, bool ssl, string token, string websocketPath, TimeSpan timeout, CancellationToken cancelToken)
26
    {
27
        _runTask = InternalRunAsync(host, port, ssl, token, websocketPath, timeout, cancelToken);
7✔
28
        return _runTask;
7✔
29
    }
30

31
    private bool _isDisposed;
32
    public async ValueTask DisposeAsync()
33
    {
34
        if (_isDisposed)
7!
35
            return;
×
36
        await _internalTokenSource.CancelAsync();
7✔
37

38
        if (_runTask?.IsCompleted == false)
7!
39
            try
40
            {
41
                await Task.WhenAny(
×
42
                    _runTask,
×
43
                    Task.Delay(5000)
×
44
                ).ConfigureAwait(false);
×
45
            }
×
46
            catch
×
47
            {
48
                // Ignore errors
49
            }
×
50

51
        _onConnectSubject.Dispose();
7✔
52
        _onDisconnectSubject.Dispose();
7✔
53
        _internalTokenSource.Dispose();
7✔
54
        _isDisposed = true;
7✔
55
    }
7✔
56

57
    private async Task InternalRunAsync(string host, int port, bool ssl, string token, string websocketPath, TimeSpan timeout,
58
        CancellationToken cancelToken)
59
    {
60
        var combinedToken = CancellationTokenSource.CreateLinkedTokenSource(_internalTokenSource.Token, cancelToken);
7✔
61
        while (!combinedToken.IsCancellationRequested)
7!
62
        {
63
            try
64
            {
65
                CurrentConnection = await client.ConnectAsync(host, port, ssl, token, websocketPath, combinedToken.Token)
7✔
66
                    .ConfigureAwait(false);
7✔
67
                // Start the event processing before publish the connection
68
                var eventsTask = CurrentConnection.WaitForConnectionToCloseAsync(combinedToken.Token);
3✔
69
                _onConnectSubject.OnNext(CurrentConnection);
3✔
70
                await eventsTask.ConfigureAwait(false);
3✔
71
            }
×
72
            catch (HomeAssistantConnectionException de) when (de.Reason == DisconnectReason.Unauthorized)
2✔
73
            {
74
                logger.LogError("User token unauthorized! Will not retry connecting...");
1✔
75
                await DisposeConnectionAsync();
1✔
76
                _onDisconnectSubject.OnNext(DisconnectReason.Unauthorized);
1✔
77
                return;
1✔
78
            }
79
            catch (HomeAssistantConnectionException de) when (de.Reason == DisconnectReason.NotReady)
1✔
80
            {
81
                logger.LogInformation("Home Assistant is not ready yet!");
1✔
82
                await DisposeConnectionAsync();
1✔
83
                _onDisconnectSubject.OnNext(DisconnectReason.NotReady);
1✔
84
            }
1✔
85
            catch (OperationCanceledException)
4✔
86
            {
87
                await DisposeConnectionAsync();
4✔
88
                if (_internalTokenSource.IsCancellationRequested)
4✔
89
                {
90
                    // We have internal cancellation due to dispose
91
                    // just return without any further due
92
                    return;
1✔
93
                }
94

95
                _onDisconnectSubject.OnNext(cancelToken.IsCancellationRequested
3✔
96
                    ? DisconnectReason.Client
3✔
97
                    : DisconnectReason.Remote);
3✔
98
            }
3✔
99
            catch (Exception e)
1✔
100
            {
101
                logger.LogError(e, "Error running HassClient");
1✔
102
                await DisposeConnectionAsync();
1✔
103
                _onDisconnectSubject.OnNext(DisconnectReason.Error);
1✔
104
            }
105

106
            await DisposeConnectionAsync();
5✔
107
            logger.LogInformation("Client disconnected, retrying in {Seconds} seconds...", timeout.TotalSeconds);
5✔
108
            await Task.Delay(timeout, combinedToken.Token).ConfigureAwait(false);
5✔
109
        }
110
    }
2✔
111

112
    private async Task DisposeConnectionAsync()
113
    {
114
        if (CurrentConnection is not null)
12✔
115
        {
116
            // Just try to dispose the connection silently
117
            try
118
            {
119
                await CurrentConnection.DisposeAsync().ConfigureAwait(false);
3✔
120
            }
3✔
121
            finally
122
            {
123
                CurrentConnection = null;
3✔
124
            }
125
        }
126
    }
12✔
127
}
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