### Async Initialization Example Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/application_lifecycle.md Implement IAsyncInitializable to perform asynchronous setup after instantiation and before the app runs. Pass the cancellation token to async methods. ```csharp [NetDaemonApp] public class AsyncUsingApp : IAsyncInitializable { private Task? _longRunningTask; public async Task InitializeAsync(CancellationToken cancellationToken) { // Always pass the cancellationToken to async methods since it will be cancelled // when NetDaemon is stopping and disposing the app var result = await SomeInitAsync(cancellationToken); _longRunningTask = Task.Run(() => DoSomeLongRunningTask(cancellationToken)); } } ``` -------------------------------- ### Basic NetDaemon Host Setup Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/app_model.md This snippet shows the fundamental setup for a NetDaemon application using `HostApplicationBuilder`. It registers the runtime, state manager, and loads apps from the executing assembly or defines a lightweight app. ```csharp using Microsoft.Extensions.Hosting; using NetDaemon.AppModel; using NetDaemon.Runtime; using NetDaemon.HassModel; var hostBuilder = Host.CreateApplicationBuilder(args); hostBuilder.Services .AddNetDaemonRuntime() .AddNetDaemonStateManager() .AddAppsFromAssembly(Assembly.GetExecutingAssembly()) // and / or .AddNetDaemonApp("LightWeightApp", (IHaContext ha) => ha.Entity("input_button.test_button") .StateAllChanges() .Subscribe(_ => ha.Entity("input_boolean.dummy_switch").CallService("toggle"))); await hostBuilder.Build().RunAsync(); ``` -------------------------------- ### Install NetDaemon.HassModel.Integration NuGet Package Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_integration_servicecallback.md Install this package to enable callback service registration. This is a prerequisite for using the `RegisterServiceCallBack` method. ```shell PM> Install-Package NetDaemon.HassModel.Integration ``` -------------------------------- ### Start NetDaemon Docs Development Server Source: https://github.com/net-daemon/docs/blob/main/README.md Run this command within the development container to start the Docusaurus development server. Ensure you are in the correct directory. Yarn may take a long time to start. ```bash root ➜ /workspaces/netdaemon-docs (readme-containers ✗) $ yarn start yarn run v1.22.17 $ docusaurus start --host 0.0.0.0 [INFO] Starting the development server... Warn: `blogDir` doesn't exist: "/workspaces/netdaemon-docs/blog". [SUCCESS] Docusaurus website is running at: http://localhost:3000/ ✔ Client Compiled successfully in 23.06s client (webpack 5.96.1) compiled successfully ``` -------------------------------- ### Setup Routing and Endpoints Source: https://github.com/net-daemon/docs/blob/main/docs/user/tutorials/webhost.md Configure application routing, including controllers, Blazor, and fallback pages. ```csharp // use controller routes app.MapControllers(); // configure Blazor app.UseStaticFiles(); app.UseRouting(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); await app.RunAsync(); ``` -------------------------------- ### Install New NetDaemon CLI Templates Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/moving_from_v3.md Install the new NetDaemon CLI templates for .NET 10. Ensure the old templates are uninstalled first. ```bash dotnet new --install NetDaemon.Templates.Project ``` -------------------------------- ### Configure appsettings.json for Home Assistant Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/get_started.md Example configuration file for connecting NetDaemon to Home Assistant. Ensure 'Host', 'Port', and 'Token' are correctly set. ```json { "Logging": { "LogLevel": { "Default": "Debug", "Microsoft": "Warning" }, "ConsoleThemeType": "Ansi" }, "HomeAssistant": { "Host": "home_assistant_host", "Port": 8123, "Ssl": false, "Token": "my_very_secret_token_from_homeassistant" }, "NetDaemon": { "ApplicationConfigurationFolder": "./apps" }, "CodeGeneration": { "Namespace": "HomeAssistantGenerated", "OutputFile": "HomeAssistantGenerated.cs", "UseAttributeBaseClasses": "false" } } ``` -------------------------------- ### Create a NetDaemon Source Project Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/development_source_deploy.md Use this command to install the NetDaemon source project template and create a new project for source file deployment. ```bash dotnet new --install NetDaemon.Templates.Project mkdir NetDaemonApps cd NetDaemonApps dotnet new nd-src-project ``` -------------------------------- ### Configure NetDaemon TTS Service in Host Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/tts.md Example of how to configure the text-to-speech service in the host builder within program.cs. ```csharp await Host.CreateDefaultBuilder(args) .UseNetDaemonTextToSpeech() ``` -------------------------------- ### Install NetDaemon Scheduling NuGet Package Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/scheduling.md Include the NetDaemon.Extensions.Scheduling nuget package to enable scheduling features. ```powershell Install-Package NetDaemon.Extensions.Scheduling ``` -------------------------------- ### Minimal App with Async Initialization and Cleanup Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/app_model.md Shows how to define a minimal NetDaemon app using a delegate. This example includes asynchronous initialization (`SomeInitAsync`) and returns an `IDisposable` for cleanup logic, logging when the app stops. ```csharp Services .AddNetDaemonApp("LightWeightApp", async (IHaContext ha, ILogger logger) => { ha.Entity("input_button.test_button") .StateAllChanges() .Subscribe(_ => ha.Entity("input_boolean.dummy_switch").CallService("toggle")); await SomeInitAsync(); return Disposable.Create(() => logger.LogInformation("Stopping minimal App")); }); ``` -------------------------------- ### Example INI Configuration File Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_config.md A simple INI file structure for custom configuration values. This file should be placed next to program.cs and copied to the build output. ```ini MyConfigValue=My Super Awesome value ``` -------------------------------- ### JSON Structure Example Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_generated_service.md This is an example of the JSON structure returned by the weather.get_forecasts service. ```json { "weather.smhi_hemma": { "forecast": [ { "datetime": "2024-06-09T16:00:00", "condition": "rainy", "wind_bearing": 54, "cloud_coverage": 100, "temperature": 11.0, "templow": 11.0, "pressure": 989.0, "wind_gust_speed": 12.96, "wind_speed": 6.12, "precipitation": 0.4, "humidity": 87 } ] } } ``` -------------------------------- ### Accessing and Toggling Entities via Registry Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_registry.md Inject `IHaRegistry` to access floors, areas, and entities. This example retrieves the 'upstairs' floor, filters for entities starting with 'input_boolean.', and toggles them. ```csharp using NetDaemon.App; using NetDaemon.Common.Reactive; using System.Linq; [NetDaemonApp] public sealed class RegistryApp { public RegistryApp(IHaRegistry haRegistry) { var floor = haRegistry.GetFloor("upstairs"); var upstairsAreas = floor.Areas; var upstairsBooleans = upstairsAreas .SelectMany(n => n.Entities .Where(x => x.EntityId.StartsWith("input_boolean."))); upstairsBooleans.ToList().ForEach(x => x.CallService("toggle")); } } ``` -------------------------------- ### Implement Async Initialization and Disposal in NetDaemon Apps Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/async_features.md Implement IAsyncInitializable for asynchronous setup and IAsyncDisposable for asynchronous cleanup. Choose between IDisposable and IAsyncDisposable based on your needs. ```csharp using NetDaemon.App; using NetDaemon.Extensions.Logging; using Microsoft.Extensions.Logging; using System.Reactive.Linq; [NetDaemonApp] public class AsyncUsingApp : IAsyncInitializable, IAsyncDisposable { private readonly IHomeAssistantApiManager _apiManager; public AsyncUsingApp(IHomeAssistantApiManager apiManager) { _apiManager = apiManager; } public async Task InitializeAsync(CancellationToken cancellationToken) { // Use your extension method defined below var result = await SomeFunctionAsync("a string", cancellationToken); } // Get called when app is being disposed public async ValueTask DisposeAsync() { // Do some async dispose here. Do not implement both IDisposable and IAsyncDisposable, choose one of the two depend on your needs } } ``` -------------------------------- ### Zone Entity Attributes Example Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_working_with_entities.md Example of attributes for a zone entity in Home Assistant. ```yaml latitude: 40.657722371758105 longitude: -74.10552978515626 radius: 12280.977677710147 passive: false editable: true friendly_name: New York icon: mdi:map-marker ``` -------------------------------- ### Studio Code Server Addon Initialization Commands Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/development_tools.md These commands are used to install the .NET SDK and the NetDaemon code generation tool within the Studio Code Server Addon container. Ensure these are placed in the `init_commands` section of the add-on configuration. ```yaml init_commands: - >- wget https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb - dpkg -i packages-microsoft-prod.deb - rm packages-microsoft-prod.deb - apt-get update - apt-get install -y apt-transport-https - apt-get update - apt-get install -y dotnet-sdk-10.0 - dotnet tool install -g NetDaemon.HassModel.CodeGen packages: [] log_level: info config_path: / ``` -------------------------------- ### Check Installed Global Tool Version Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_codegen.md Displays the installed version of the NetDaemon code generator global tool. ```cmd dotnet tool list -g ``` -------------------------------- ### Install NetDaemon Code Generator Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/moving_from_v3.md Install the NetDaemon code generator for .NET 10. You may need to uninstall the old version first due to namespace changes. ```bash dotnet tool install -g NetDaemon.HassModel.CodeGen ``` -------------------------------- ### Run NetDaemon Code Generator (Global Tool) Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_codegen.md Runs the NetDaemon code generator after it has been installed as a global tool. ```cmd nd-codegen ``` -------------------------------- ### IHomeAssistantRunner Implementation Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/client.md Example of implementing a background service using IHomeAssistantRunner to connect, subscribe to events, and manage the connection lifecycle with Home Assistant. ```APIDOC ## 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. ```csharp 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; } } } ``` ``` -------------------------------- ### Usage Example for MQTT Button Action Trigger Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_subscribe_to_triggers.md Demonstrates how to use the RegisterMqttButtonActionTrigger extension method within a NetDaemonApp to subscribe to button events and log received actions. ```csharp [NetDaemonApp] public class TestDeviceTriggerApp { public TestDeviceTriggerApp(ITriggerManager triggerManager, ILogger logger) { var trigger = triggerManager.RegisterMqttButtonActionTrigger("my_button_mqtt_device_name"); trigger.Subscribe(e => { logger.LogInformation("Received event {event}", e); }); } } ``` -------------------------------- ### Configure Host Builder with Default NetDaemon Settings Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_config.md This is the default configuration setup for the NetDaemon Host Builder, which includes default logging and app settings. ```csharp try { await Host.CreateDefaultBuilder(args) .UseDefaultNetDaemonLogging() .UseNetDaemonAppSettings()// <----- .UseNetDaemon() .Build() .RunAsync(); /// ... } ``` -------------------------------- ### Constructor Injection Example Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/application_lifecycle.md Inject dependencies like IHaContext and ILogger into your NetDaemon app's constructor. Avoid blocking operations here. ```csharp [NetDaemonApp] public class MyFirstApp : NetDaemonApp { private readonly IHaContext _haContext; private readonly ILogger _logger; public MyFirstApp(IHaContext haContext, ILogger logger) { _haContext = haContext; _logger = logger; // Do some initialization of subscriptions to events etc. here } } ``` -------------------------------- ### Example Service Call Data in Home Assistant Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_integration_servicecallback.md This YAML demonstrates the data structure expected by the `callback_demo` service registered in NetDaemon. Ensure the `data` fields match the `ServiceData` record defined in your C# code. ```yaml service: netdaemon.callback_demo data: action: heat value: 22 ``` -------------------------------- ### Example App Logic with HassModel Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/example.md This C# code snippet demonstrates a basic NetDaemon application. It uses the HassModel API to subscribe to state changes of a binary sensor and control a light entity. Ensure you have the necessary NetDaemon and Home Assistant generated code set up. ```csharp using System; using System.Reactive.Linq; using NetDaemon.AppModel; using NetDaemon.HassModel; using HomeAssistantGenerated; [NetDaemonApp] public class ExampleAppHaContext { public ExampleAppHaContext(IHaContext ha) { var entities = new Entities(ha); entities.BinarySensor.OfficeMotion .StateChanges() .Where(e => e.New.IsOn()) .Subscribe(_ =>entities.Light.Office.TurnOn()); } } ``` -------------------------------- ### Serilog Configuration in appsettings.json Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_logging.md Configure Serilog by replacing the 'Logging' section with 'Serilog'. This example sets minimum log levels and defines file and console sinks. ```json { "Serilog": { "MinimumLevel": { "Default": "Warning", "Override": { "System": "Information", "Microsoft": "Information", "System.Net.Http.HttpClient": "Warning", "daemonapp.apps.ScottHome": "Verbose" } }, "WriteTo": [ { "Name": "File", "Args": { "path": "logs/log-.txt", "rollingInterval": "Day" } }, { "Name": "Console", "Args": { "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {NewLine}{Exception}" } } ] }, "HomeAssistant": { // Rest of your config starts here... ``` -------------------------------- ### C# Example: Using Generated Services with Return Values Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_generated_service.md This C# code demonstrates how to call a Home Assistant service that returns data, log the raw JSON, deserialize it into a C# record, and handle results from multiple entities. It includes defining a record to match the JSON structure and using snake_case JSON naming policy. ```csharp using System.Threading; using System.Threading.Tasks; using System.Text.Json; public record WeaterForecastItem { public DateTime Datetime { get; init; } public string Condition { get; init; } public int WindBearing { get; init; } public int CloudCoverage { get; init; } public float Temperature { get; init; } public float Templow { get; init; } public float Pressure { get; init; } public float WindGustSpeed { get; init; } public float WindSpeed { get; init; } public float Precipitation { get; init; } public int Humidity { get; init; } } [NetDaemonApp] public class UseServiceWithReturnValueApp( Entities entities, Services services, ILogger logger) : IAsyncInitializable { // Snake-case json options private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }; public async Task InitializeAsync(CancellationToken cancellationToken) { // Get the forecasts from SmhiHemma entity using the code generated entities var forecastResult = await entities.Weather.SmhiHemma.GetForecastsAsync(type: "hourly"); // Log the forecast to look for the structure of the result // Remove when you created the correct class/record for deserialization logger.LogInformation("Forecast: {forecast}", forecastResult); // Find the forecast property and deserialize it to a list of WeaterForecastItem var forecasts = forecastResult?.GetProperty(entities.Weather.SmhiHemma.EntityId) .GetProperty("forecast"); if (forecasts is not null) { var forecastItems = forecasts.Value.Deserialize>(_jsonOptions); logger.LogInformation("Forecast items: {forecastItems}", forecastItems); } // You can return multiple values from a service call var multipleEntitiesForecastResult = await services.Weather .GetForecastsAsync(ServiceTarget.FromEntities("weather.smhi_hemma", "weather.test"), "hourly"); logger.LogInformation("Muliple returns {multiple}", multipleEntitiesForecastResult); // Do something useful with the result of multiple forecasts from multiple entities } } ``` -------------------------------- ### Accessing Zone Entity Attributes in C# Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_working_with_entities.md Example of how to instantiate an Entity and access its typed attributes. ```csharp var zone = new Entity(haContext, "zone.new_york"); double latitude = zone.Attributes.latitude; double longitude = zone.Attributes.longitude; ``` -------------------------------- ### Run NetDaemon Code Generator (Local Tool) Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_codegen.md Installs and runs the NetDaemon code generator as a local tool. This ensures the tool version stays in sync with NetDaemon versions. ```cmd dotnet tool run nd-codegen ``` -------------------------------- ### Force NetDaemon Docs Cleanup and Reinstall Source: https://github.com/net-daemon/docs/blob/main/README.md Use this command to clear cached files and force a fresh installation of dependencies within the development container. This can help resolve build issues. ```bash rm -rf node_modules && yarn install ``` -------------------------------- ### Responding to State Changes Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_generated_entities.md Subscribe to state change events for an entity using RxNetDaemon. This example triggers an action when the kitchen light's brightness increases past a threshold. ```csharp kitchenLight.StateAllChanges() .Where(s => s.Old?.Attributes?.Brightness < 128 && s.New?.Attributes?.Brightness >= 128) .Subscribe(e => HandleBrightnessUp()); ``` -------------------------------- ### C# Application Configuration Injection Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/instancing_apps.md Define a configuration class and inject it into your application's constructor using `IAppConfig<>`. The `LightManager` example demonstrates turning on a light upon initialization using the injected configuration. ```csharp public class LightConfig { // This property will be automapped with ´the_light´ config // Using autogenerated entity classes in HassModel public LightEntity? TheLight { get; set; } } public class LightManager { /// /// Initialize, is automatically run by the daemon /// public LightManager(IAppConfig config) { // Turn on the light when loading config.Value.TheLight?.TurnOn(); } } ``` -------------------------------- ### Create NetDaemon Project Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/get_started.md Scaffolds a new NetDaemon application. Navigate to your desired directory and execute these commands. ```bash mkdir NetDaemonApps cd NetDaemonApps dotnet new nd-project ``` -------------------------------- ### Configure WebApplicationBuilder in program.cs Source: https://github.com/net-daemon/docs/blob/main/docs/user/tutorials/webhost.md Replace IHostBuilder with WebApplicationBuilder and configure NetDaemon services. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Host .UseNetDaemonAppSettings() .UseNetDaemonDefaultLogging() .UseNetDaemonRuntime() .UseNetDaemonTextToSpeech() .UseNetDaemonMqttEntityManagement() .ConfigureServices((_, services) => { services .AddAppsFromAssembly(Assembly.GetExecutingAssembly()) .AddNetDaemonStateManager() .AddNetDaemonScheduler() .AddHomeAssistantGenerated(); }); ``` -------------------------------- ### Enable MQTT Entity Management in Host Builder Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Call `.UseNetDaemonMqttEntityManagement()` on the `HostBuilder` in your `program.cs` to activate the entity manager. ```csharp await Host.CreateDefaultBuilder(args) // More Host Extensions .UseNetDaemonMqttEntityManagement() // <--- .ConfigureServices((_, services) => // More Service Extensions ) .Build() .RunAsync() .ConfigureAwait(false); ``` -------------------------------- ### Define Minimal API Endpoint Source: https://github.com/net-daemon/docs/blob/main/docs/user/tutorials/webhost.md Map a simple GET endpoint for a minimal API. ```csharp // minimal API app.MapGet("/mini", () => "Hello from Minimal API!"); ``` -------------------------------- ### Get Entity State Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/calling_ha_api.md This method retrieves the current state of a specified entity from Home Assistant. ```APIDOC ## MyGetEntityStateAsync ### Description Get the current state for a entity. ### Method GET ### Endpoint /states/{entityId} ### Parameters #### Path Parameters - **entityId** (string) - Required - The ID of the entity to retrieve the state for. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **HassState** (object) - The current state of the entity. #### Response Example ```json { "entity_id": "light.my_light", "state": "on", "last_changed": "2023-10-27T10:00:00Z", "last_updated": "2023-10-27T10:05:00Z", "attributes": { "friendly_name": "My Light" } } ``` ``` -------------------------------- ### Run NetDaemon Project Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/get_started.md Executes the NetDaemon project from the command line. Ensure you are in the project directory. ```bash dotnet run ``` -------------------------------- ### Uninstall Old NetDaemon CLI Templates Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/moving_from_v3.md Uninstall the old NetDaemon CLI templates to prevent conflicts with the new installation. ```bash dotnet new uninstall JoySoftware.NetDaemon.Templates.Project ``` -------------------------------- ### Update NetDaemon Code Generator (Global Tool) Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_codegen.md Updates the NetDaemon code generator to the latest version when installed as a global tool. ```cmd dotnet tool update -g NetDaemon.HassModel.CodeGen ``` -------------------------------- ### Publish .NET Project for NetDaemon Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/installation.md Publish your .NET project in Release configuration, outputting to a specified directory. Copy the contents of this directory to your Home Assistant host. ```bash dotnet publish -c Release -o [outputdir] ``` -------------------------------- ### Update NetDaemon Code Generator (Local Tool) Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_codegen.md Updates the NetDaemon code generator to the latest version when installed as a local tool. ```cmd dotnet tool update NetDaemon.HassModel.CodeGen ``` -------------------------------- ### Create a Simple Binary Sensor Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Creates a binary sensor with a specified device class. Refer to Home Assistant documentation for available device classes. ```csharp await _entityManager.CreateAsync("binary_sensor.basic_sensor", new EntityCreationOptions(DeviceClass: "connectivity")) .ConfigureAwait(false); ``` -------------------------------- ### Accessing Entity State and Attributes Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_generated_entities.md Access the state and attributes of a strongly typed entity. This example checks if a light is 'on' and its brightness level. ```csharp if (livingRoomLight.State == "on" && livingRoomLight.Attributes.Brightness > 100) // ... ``` -------------------------------- ### Create a Minimal App with Delegates Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/app_model.md Create a lightweight app using a delegate that is directly registered with the ServiceCollection. It can accept resolved dependencies. ```csharp Services .AddNetDaemonApp("LightWeightApp", (IHaContext ha) => { ha.CallService("notify", "persistent_notification", data: new { message = "Started", title = "My App" }); }); ``` -------------------------------- ### Create NetDaemon App Folder Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/installation.md Create this folder structure on your Home Assistant host to store NetDaemon applications. ```text /config/netdaemon6 ``` -------------------------------- ### Use Default NetDaemon Logging Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_logging.md This snippet shows how to apply the default NetDaemon logging configuration. It's typically used in the application's startup. ```csharp await Host.CreateDefaultBuilder(args) .UseDefaultNetDaemonLogging() // <----- .UseNetDaemon() .Build() .RunAsync(); ``` -------------------------------- ### Add MQTT Entity Management Package Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Include the NetDaemon.Extensions.Mqtt NuGet package to enable MQTT entity management. ```powershell dotnet add package NetDaemon.Extensions.Mqtt ``` -------------------------------- ### Targeting Service Calls with ServiceTarget Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_registry.md Use the `ServiceTarget` class to specify floors, areas, or devices for service calls. This example toggles entities only on the 'upstairs' floor. ```csharp using NetDaemon.App; using NetDaemon.Common.Reactive; [NetDaemonApp] public sealed class TestServiceTargetApp { public TestServiceTargetApp(IHaContext ha) { ha.CallService("input_boolean", "toggle", new ServiceTarget{ FloorIds = ["upstairs"] }); } } ``` -------------------------------- ### Publish NetDaemon App for Deployment Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/get_started.md Publishes a release build of the NetDaemon application. Replace '[your output directory]' with your desired path. ```bash dotnet publish -c Release -o [your output directory] ``` -------------------------------- ### Class-Based App Lifecycle Implementation Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/app_model.md Demonstrates a class-based NetDaemon application implementing `IAsyncInitializable` and `IAsyncDisposable` for asynchronous initialization and cleanup. The constructor and methods show logging at different lifecycle stages. ```csharp [NetDaemonApp] public sealed class LifeTimeApp : IAsyncInitializable, IAsyncDisposable { private readonly ILogger _logger; public LifeTimeApp(IHaContext ha, ILogger logger) { ha.Events.Where(n => n.EventType == "test_event").Subscribe( _ => { logger.LogInformation("LifeTimeApp Hello testevent"); }); _logger.LogInformation("LifeTimeApp created"); } public async Task InitializeAsync(CancellationToken cancellationToken) { // async initialisation logic here _logger.LogInformation("LifeTimeApp initialized"); } public async ValueTask DisposeAsync() { // cleanup logic here _logger.LogInformation("LifeTimeApp disposed"); } } ``` -------------------------------- ### Overriding Logging Minimum Level in appsettings.json Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/instancing_apps.md Configure the minimum logging level for NetDaemon by modifying the `appsettings.json` file. This example sets the minimum level to `Debug`. ```json { "Logging": { "MinimumLevel": "Debug" }, ... } ``` -------------------------------- ### Create an MQTT Entity Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Use `CreateAsync` to register a new entity in Home Assistant. The `entityId` is mandatory and follows the 'domain.identifier' format. Optional parameters allow customization of device class, unique ID, name, persistence, and availability payloads. ```csharp Task CreateAsync(string entityId, EntityCreationOptions? options = null, object? additionalConfig = null); ``` -------------------------------- ### Extension Method to Get Entity State Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/calling_ha_api.md Create extension methods for IHomeAssistantApiManager to encapsulate common API calls. This method retrieves the current state of a specified entity. ```csharp using System.Threading; using System.Threading.Tasks; using System.Web; /// /// Get the current state for a entity /// /// ApiManager to extend /// Id of the event /// Token to cancel async operation public static async Task MyGetEntityStateAsync(this IHomeAssistantApiManager apiManager, string entityId, CancellationToken cancellationToken) { var apiUrl = $"states/{HttpUtility.UrlEncode(entityId)}"; return await apiManager.GetApiCallAsync(apiUrl, cancellationToken); } ``` -------------------------------- ### Add NetDaemon Add-on Repository Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/installation.md Add the NetDaemon repository URL to your Home Assistant add-on store. ```text https://github.com/net-daemon/homeassistant-addon ``` -------------------------------- ### Injecting IHomeAssistantApiManager in an App Source: https://github.com/net-daemon/docs/blob/main/docs/user/advanced/calling_ha_api.md Inject the IHomeAssistantApiManager interface into your NetDaemon apps to gain access to Home Assistant API functionalities. This example demonstrates how to use it within an IAsyncInitializable app. ```csharp using Microsoft.Extensions.Hosting; using NetDaemon.App; using System.Threading; using System.Threading.Tasks; [NetDaemonApp] public class UsingApiCallsApp : IAsyncInitializable { private readonly IHomeAssistantApiManager _apiManager; public UsingApiCallsApp(IHomeAssistantApiManager apiManager) { _apiManager = apiManager; } public async Task InitializeAsync(CancellationToken cancellationToken) { // Use your extension method defined below var entityState = await _apiManager.MyGetEntityStateAsync("light.my_light", cancellationToken); } } ``` -------------------------------- ### Register a state trigger Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_subscribe_to_triggers.md Inject ITriggerManager to register a state trigger. The RegisterTrigger method returns an IObservable that can be deserialized. This example subscribes to a state change trigger for a media player. ```csharp public TheApp(ITriggerManager triggerManager) { var triggerObservable = triggerManager.RegisterTrigger( new { platform = "state", entity_id = new string[] { "media_player.vardagsrum" }, from = new string[] { "idle", "playing" }, to = "off" }); triggerObservable.Subscribe(n => // Do some magic here ); } ``` -------------------------------- ### Create a Switch with Device Class Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Switches require a device class to be specified during creation. Ensure the device class is appropriate for a switch. ```csharp await _entityManager.CreateAsync("switch.kitchen_lights", new EntityCreationOptions(Name: "Kitchen lights switch", DeviceClass: "switch")) .ConfigureAwait(false); ``` -------------------------------- ### Filter State Changes with Old and New States Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_working_with_entities.md Filter state changes based on both the previous and current state of an entity. This example turns on a light only if the motion sensor changes from 'off' to 'on'. ```csharp myEntities.BinarySensor.MyMotionSensor .StateChanges() .Where(e => e.New?.State == "on" && e.Old?.State == "off") .Subscribe(s => myEntities.Light.Attic.TurnOn()); ``` -------------------------------- ### Copy INI File to Build Output Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_config.md XML configuration for the project file (.csproj) to ensure the appsettings.ini file is always copied to the build output directory. ```xml Always ``` -------------------------------- ### Getting an entity's state Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_working_with_entities.md Retrieve the current state value of an entity as a string using the `State` property. This value is cached internally by NetDaemon and does not require a direct call to Home Assistant. ```csharp var state = atticLight.State; ``` -------------------------------- ### Constructor Signature Source: https://github.com/net-daemon/docs/blob/main/docs/user/started/example.md The constructor receives an IHaContext for interacting with Home Assistant. Do not block the constructor; use IAsyncInitializable for asynchronous operations. ```cs public ExampleAppHaContext(IHaContext ha) ``` -------------------------------- ### Inject IScheduler into App Constructor Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/scheduling.md Get an instance of the IScheduler interface by injecting it into your NetDaemon app's constructor. The provided scheduler ensures tasks are cancelled when the app stops and logs exceptions. ```csharp using System.Reactive.Concurrency.Scheduler; [NetDaemonApp] class MyApp(IScheduler scheduler) { } ``` -------------------------------- ### Wait for Entity State for a Duration Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_working_with_entities.md Use the `WhenStateIsFor` extension method to react only after an entity has remained in a specific state for a defined duration. This example turns off a light after a motion sensor has been 'off' for 5 minutes. ```csharp myEntities.BinarySensor.MyMotionSensor .StateChanges() .WhenStateIsFor(s => s?.State == "off", TimeSpan.FromMinutes(5), scheduler) .Subscribe(s => myEntities.Light.Attic.TurnOff()); ``` -------------------------------- ### Prepare Command Subscription for Entity Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Prepare an observable to receive command updates for a specific entity. This is typically used for devices like switches. ```csharp Task> PrepareCommandSubscriptionAsync(string entityId); ``` -------------------------------- ### PrepareCommandSubscriptionAsync Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Returns an observable string that you can subscribe to for command updates. ```APIDOC ## PrepareCommandSubscriptionAsync ### Description Prepares a subscription for command updates. ### Method ```csharp IObservable PrepareCommandSubscriptionAsync(string entityId) ``` ### Parameters #### Path Parameters - **entityId** (string) - Required - The "domain.identifier" format entity ID for which to subscribe to command updates. ``` -------------------------------- ### Configure MQTT Broker Connection Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Update your `appsettings.json` with the MQTT broker's IP address. Optional parameters like Port, UserName, and Password can also be configured. ```json { "Logging": { // more config }, "NetDaemon": { // more config }, "Mqtt": { "Host": "ENTER YOUR IP TO your MQTT Broker" } } ``` -------------------------------- ### Create a Simple Sensor Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Use this to create a basic sensor entity. Ensure the entity ID is unique. ```csharp await _entityManager.CreateAsync("sensor.basic_sensor").ConfigureAwait(false); ``` -------------------------------- ### Basic TTS Usage in a NetDaemon App Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/tts.md Demonstrates how to inject and use the ITextToSpeechService to send queued TTS messages. Ensure the TTS service is configured in program.cs. ```csharp [NetDaemonApp] public class MyTtsApp { public MyTtsApp(ITextToSpeechService tts) { // This uses the google service you may use some other like google cloud version, google_cloud_say tts.Speak("media_player.kitchen", "Hello this is first queued message", "google_say"); tts.Speak("media_player.kitchen", "Hello this is second queued message", "google_say"); } } ``` -------------------------------- ### Create Entity with Availability Payloads Source: https://github.com/net-daemon/docs/blob/main/docs/user/extensions/mqttEntityManager.md Demonstrates how to create an entity and configure its availability payloads. ```APIDOC ## Create Entity with Availability Payloads ### Description Creates an entity with specified payloads for available and unavailable states. ### Method `CreateAsync` ### Parameters #### Path Parameters - **domain** (string) - Required - The domain of the entity. - **creationOptions** (EntityCreationOptions) - Required - Options for entity creation, including availability payloads. #### Request Body (Implicit in EntityCreationOptions) - **PayloadAvailable** (string) - Required - The payload that marks the entity as available. - **PayloadNotAvailable** (string) - Required - The payload that marks the entity as unavailable. ### Request Example ```csharp await entityManager.CreateAsync("domain.sensor", new EntityCreationOptions(PayloadAvailable: "up", PayloadNotAvailable: "down")) .ConfigureAwait(false); ``` ``` -------------------------------- ### Register a time pattern trigger with a record class Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_subscribe_to_triggers.md Use RegisterTrigger to automatically deserialize the trigger response to a specified record class. This example registers a time pattern trigger and logs the received message. A record class representing the expected response structure is also defined. ```csharp // Record representing result from subscription record TimePatternResult(string id, string alias, string platform, DateTimeOffset now, string description); // ... ctr of your app public TimeApp(ITriggerManager triggerManager) { var timePatternTriggerObservable = triggerManager.RegisterTrigger(new { platform = "time_pattern", id = "some id", seconds = "/1" }); var disposedSubscription = timePatternTriggerObservable.Subscribe(n => _logger.LogCritical("Got trigger message: {Message}", n) ); } ``` -------------------------------- ### Call Home Assistant Service with Response Source: https://github.com/net-daemon/docs/blob/main/docs/user/hass_model/hass_model_service_with_returnvalue.md Use `CallServiceWithResponseAsync` to invoke a Home Assistant service and retrieve its return value. This is useful for getting data like calendar events. Ensure the service you are calling supports returning values. The result is deserialized into a specified record type. ```csharp using System.Text.Json; using Microsoft.Extensions.Logging; using NetDaemon.AppModel; using NetDaemon.HassModel; using NetDaemon.HassModel.Entities; namespace Apps; [NetDaemonApp] public sealed class ServiceApp : IAsyncInitializable { private readonly IHaContext _ha; private readonly ILogger _logger; private readonly JsonSerializerOptions _jsonOptions = new() { PropertyNameCaseInsensitive = true }; public ServiceApp(IHaContext ha, ILogger logger) { _ha = ha; _logger = logger; } public async Task InitializeAsync(CancellationToken cancellationToken) { var result = await _ha.CallServiceWithResponseAsync("calendar", "list_events", ServiceTarget.FromEntity("calendar.cal"), data: new { start_date_time = "2023-07-21 00:00:00", end_date_time = "2023-07-22 03:00:00"}); if (result is not null) { var events = result.Value.Deserialize(_jsonOptions); if (events is null) _logger.LogWarning("No results!"); else _logger.LogInformation("Events: {Events}", events); } } } public record CalendarEvents(IEnumerable Events); public record CalendarEvent(DateTime Start, DateTime End, string Summary, string Description); ``` -------------------------------- ### Create Custom Logging Configuration Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/custom_logging.md This C# code defines a custom logging provider using Serilog. It reads logging configuration from `appsettings.json` and integrates it with the host builder. Ensure this class is placed in your app folder. ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Serilog; namespace HomeAssistantGenerated.Logging; public static class CustomLoggingProvider { /// /// Adds standard Serilog logging configuration, from appsettings, as per: /// https://github.com/datalust/dotnet6-serilog-example /// /// public static IHostBuilder UseCustomLogging(this IHostBuilder builder) { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); var logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .CreateLogger(); return builder.UseSerilog(logger); } } ``` -------------------------------- ### Create a Class-Based NetDaemon App Source: https://github.com/net-daemon/docs/blob/main/docs/user/app_model/app_model.md Define a class-based app by decorating it with the [NetDaemonApp] attribute. The constructor can receive dependencies like IHaContext. ```csharp [NetDaemonApp] public class MyApp { public MyApp(IHaContext ha) { ha.CallService("notify", "persistent_notification", data: new { message = "Started", title = "My App" }); } } ```