Skip to main content

Client API

While the recommended way to interact with Home Assistant is through the AppModel and HassModel API, there are scenarios where direct interaction with Home Assistant is required. The Client APIs offer a convenient method for lower-level interactions with Home Assistant.

IHomeAssistantConnection

You can access the client API through the IHomeAssistantConnection interface on the existing connection. This can be injected into a NetDaemon app's constructor. Most methods in this interface are asynchronous, so you need to implement the IAsyncInitializable interface to use them in the InitializeAsync method. Refer to how to use async features for more details on using async in the subscribe method. Don't forget to include the NetDaemon.Client.HomeAssistant.Extensions namespace to access extended features.

using NetDaemon.AppModel;
using NetDaemon.Client;
using NetDaemon.Client.HomeAssistant.Extensions;

namespace Apps;

[NetDaemonApp]
public sealed class HelperApp(IHomeAssistantConnection conn) : IAsyncInitializable
{
private readonly IHomeAssistantConnection _conn = conn;

public async Task InitializeAsync(CancellationToken cancellationToken)
{
// Use the connection to call Home Assistant features here...
}
}

IHomeAssistantRunner

If you need to implement a solution that only requires connecting to Home Assistant and utilizing basic NetDaemon features without the full app model, you can use the IHomeAssistantRunner interface. This interface handles connection and reconnection to Home Assistant.

Add the client NuGet package to your application and use the HomeAssistantRunner class to connect to Home Assistant. The AddHomeAssistantClient extension method on the IServiceCollection must be used to add the client to dependency injection.

Example: Implementation of a background service that uses the IHomeAssistantRunner to connect to Home Assistant and subscribe to all events.

internal sealed class MyOwnService : BackgroundService
{
private const int TimeoutInSeconds = 5;

private readonly IHomeAssistantRunner _homeAssistantRunner;

private readonly IHostApplicationLifetime _hostLifetime;

private CancellationToken? _cancelToken;
private IHomeAssistantConnection? _connection;

public MyOwnService(
IHostApplicationLifetime hostLifetime,
IHomeAssistantRunner homeAssistantRunner,
{
_hostLifetime = hostLifetime;
_homeAssistantRunner = homeAssistantRunner;

// When ever the client is connected it will trigger the OnConnect
homeAssistantRunner.OnConnect
.Select(async s => await OnHomeAssistantClientConnected(s).ConfigureAwait(false))
.Subscribe();

// When ever the client is disconnected it will trigger the OnDisconnect
homeAssistantRunner.OnDisconnect.Subscribe(OnHomeAssistantClientDisconnected);
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_cancelToken = stoppingToken;
await _homeAssistantRunner.RunAsync(
"localhost",
8123,
false,
"YOUR_LONG_LIVED_ACCESS_TOKEN",
TimeSpan.FromSeconds(TimeoutInSeconds),
stoppingToken).ConfigureAwait(false);

// Stop application if this is exited and use _cancelToken as token
_hostLifetime.StopApplication();
}

private async Task OnHomeAssistantClientConnected(IHomeAssistantConnection connection)
{
// First you need to tell Home Assistant to subscribe to events
var hassEvents = await connection.SubscribeToHomeAssistantEventsAsync(null, _cancelToken ?? CancellationToken.None).ConfigureAwait(false);

// We subscribe to the events that Home Assistant sends and handle them in the HandleEvent method
hassEvents.Subscribe(HandleEvent);

}

private void OnHomeAssistantClientDisconnected(DisconnectReason reason)
{
// Here you would typically cancel and dispose any functions
// using the connection
if (_connection is not null) _connection = null;
}

private void HandleEvent(HassEvent hassEvent)
{
switch (hassEvent.EventType)
{
case "state_changed":
var state = hassEvent.ToStateChangedEvent();
// Do something with the state
break;
}
}
}