Skip to content

Commit

Permalink
Cleaner disconnect/reconnect wou multiple instance
Browse files Browse the repository at this point in the history
  • Loading branch information
helto4real committed Dec 25, 2020
1 parent 350feed commit 29b0eb4
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 126 deletions.
20 changes: 11 additions & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@
"coverage-gutters.showGutterCoverage": false,
"coverage-gutters.showLineCoverage": true,
},
"remoteEnv": {
"HOMEASSISTANT__TOKEN": "${localEnv:HOMEASSISTANT__TOKEN}",
"HOMEASSISTANT__HOST": "${localEnv:HOMEASSISTANT__HOST}",
"HOMEASSISTANT__PORT": "${localEnv:HOMEASSISTANT__PORT}",
"LOGGING__MINIMUMLEVEL": "${localEnv:LOGGING__MINIMUMLEVEL}",
"NETDAEMON__GENERATEENTITIES": "${localEnv:NETDAEMON__GENERATEENTITIES}",
"NETDAEMON__ADMIN": "${localEnv:NETDAEMON__ADMIN}",
"ASPNETCORE_URLS": "${localEnv:ASPNETCORE_URLS}"
},
// You can uncomment these if you rather have settings in
// Host environment varialbes.
// "remoteEnv": {
// "HOMEASSISTANT__TOKEN": "${localEnv:HOMEASSISTANT__TOKEN}",
// "HOMEASSISTANT__HOST": "${localEnv:HOMEASSISTANT__HOST}",
// "HOMEASSISTANT__PORT": "${localEnv:HOMEASSISTANT__PORT}",
// "LOGGING__MINIMUMLEVEL": "${localEnv:LOGGING__MINIMUMLEVEL}",
// "NETDAEMON__GENERATEENTITIES": "${localEnv:NETDAEMON__GENERATEENTITIES}",
// "NETDAEMON__ADMIN": "${localEnv:NETDAEMON__ADMIN}",
// "ASPNETCORE_URLS": "${localEnv:ASPNETCORE_URLS}"
// },
// "postCreateCommand": "dotnet restore && .devcontainer/install_prettyprompt.sh",
// Uncomment the next line if you want to publish or forward any ports.
"forwardPorts": [
Expand Down
9 changes: 7 additions & 2 deletions DEV.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Developing NetDaemon
These instructions are for developing NetDaemon. For apps please use [the docs](https://netdaemon.xyz).
For your convenience we provided with a docker setup with Home Assistant you can run on your development machine.
`tests/Docker/HA` you will find the docker-compose file. Run it outside the devcontainer. Remarkts that you should use port 8124 connecting to this instance of Home Assistant.

## Use appsettings.Development.json
Copy the "_appsettings.Development.json under `src/Service`

## Setup the environment vars
Easiest is to setup environment varables for your Home Assistant instance
Alternative to using appsettings for development is to use environment varables for your Home Assistant instance

| Environment variable | Description |
| ------ | ------ |
Expand All @@ -12,6 +17,6 @@ Easiest is to setup environment varables for your Home Assistant instance
| NETDAEMON__GENERATEENTITIES | Generate entities, recommed set false unless debugging |
| NETDAEMON__APPSOURCE | The folder/project/dll where it will find daemon. Set this to empty `""` to debug apps local. If needed to debug the dynamic source compilation, set to `/workspaces/netdaemon/Service/apps` |

Use `src/Service/apps` as starting point to debug your stuff!
Use `src/Development/apps` as starting point to debug your stuff!

Good luck
10 changes: 5 additions & 5 deletions src/App/NetDaemon.App/Common/NetDaemonAppBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,27 +163,27 @@ public async Task RestoreAppStateAsync()
if (isDisabled)
{
IsEnabled = false;
if (appState != "off")
if (appState == "on")
{
dynamic serviceData = new FluentExpandoObject();
serviceData.entity_id = EntityId;
await _daemon.SetStateAsync(EntityId, "off").ConfigureAwait(false);
await _daemon.CallServiceAsync("switch", "turn_off", serviceData);
}
return;
}
else if (appState == null || (appState != "on" && appState != "off"))
else
{
IsEnabled = true;
if (appState != "on")
if (appState == "off")
{
dynamic serviceData = new FluentExpandoObject();
serviceData.entity_id = EntityId;
await _daemon.SetStateAsync(EntityId, "on").ConfigureAwait(false);
await _daemon.CallServiceAsync("switch", "turn_on", serviceData);
}

return;
}
IsEnabled = appState == "on";
}

/// <inheritdoc/>
Expand Down
7 changes: 5 additions & 2 deletions src/App/NetDaemon.App/Common/Reactive/AppDaemonRxApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,13 @@ internal virtual IDisposable CreateObservableIntervall(TimeSpan timespan, Action
}
catch (Exception e)
{
LogError(e, "Error, RunEvery APP: {app}", Id ?? "unknown");
LogError(e, "Error, ObservableIntervall APP: {app}", Id ?? "unknown");
}
},
() => LogTrace("Exiting RunEvery for app {app}, {trigger}:{span}", Id!, timespan)
ex =>
{
LogTrace("Exiting ObservableIntervall for app {app}, {trigger}:{span}", Id!, timespan);
}
, result.Token);

return result;
Expand Down
1 change: 1 addition & 0 deletions src/App/NetDaemon.App/Common/Reactive/ObservableBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public void Dispose()
if (_observer is not null)
{
_observers.TryRemove(_observer, out _);
_observer.OnCompleted();
}
// System.Console.WriteLine($"Subscribers:{_observers.Count}");
}
Expand Down
2 changes: 1 addition & 1 deletion src/App/NetDaemon.App/NetDaemon.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JoySoftware.HassClient" Version="20.49.1-beta" />
<PackageReference Include="JoySoftware.HassClient" Version="20.52.1-beta" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
</ItemGroup>
Expand Down
42 changes: 27 additions & 15 deletions src/Daemon/NetDaemon.Daemon/Daemon/NetDaemonHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,17 @@ public async Task Run(string host, short port, bool ssl, string token, Cancellat
HassEvent changedEvent = await _hassClient.ReadEventAsync(cancellationToken).ConfigureAwait(false);
if (changedEvent != null)
{
if (changedEvent.Data is HassServiceEventData hseData)
{
if (hseData.Domain == "homeassistant" &&
(hseData.Service == "stop" || hseData.Service == "restart"))
{
// The user stopped HA so just stop processing messages
Logger.LogInformation("User {action} Home Assistant, will try to reconnect...",
hseData.Service == "stop" ? "stopping" : "restarting");
return;
}
}
// Remove all completed Tasks
_eventHandlerTasks.RemoveAll(x => x.IsCompleted);
_eventHandlerTasks.Add(HandleNewEvent(changedEvent, cancellationToken));
Expand All @@ -474,13 +485,20 @@ public async Task Run(string host, short port, bool ssl, string token, Cancellat
}
catch (OperationCanceledException)
{
// Normal
// Normal operation, ignore and return
}
catch (Exception e)
{
Connected = false;
Logger.LogError(e, "Error, during operation");
}
finally
{
// Set cancel token to avoid background processes
// to access disconnected Home Assistant
Connected = false;
_cancelTokenSource.Cancel();
}
}

public IScript RunScript(INetDaemonApp app, params string[] entityId)
Expand Down Expand Up @@ -584,44 +602,37 @@ public async Task Stop()
{
try
{
if (_stopped)
{
return;
}
Logger.LogDebug("Try stopping Instance NetDaemonHost");
Logger.LogTrace("Try stopping Instance NetDaemonHost");

await UnloadAllApps().ConfigureAwait(false);

await _scheduler.Stop().ConfigureAwait(false);

await _hassClient.CloseAsync().ConfigureAwait(false);

InternalState.Clear();

_stopped = true;

Connected = false;

Logger.LogInformation("Stopped Instance NetDaemonHost");
await _hassClient.CloseAsync().ConfigureAwait(false);
Logger.LogTrace("Stopped Instance NetDaemonHost");
}
catch (Exception e)
{
Logger.LogError(e, "Error stopping NetDaemon");
Logger.LogError("Error stopping NetDaemon, use trace level for details");
Logger.LogTrace(e, "Error stopping NetDaemon");
}
}

/// <inheritdoc/>
public async Task UnloadAllApps()
{
if (_runningAppInstances is null || _runningAppInstances.Count() == 0)
return;

foreach (var app in _allAppInstances)
{
await app.Value.DisposeAsync().ConfigureAwait(false);
}
_runningAppInstances.Clear();
_allAppInstances.Clear();
_runningAppInstances.Clear();
}

/// <summary>
Expand Down Expand Up @@ -1228,11 +1239,12 @@ private async Task LoadAllApps()

foreach (INetDaemonAppBase appInstance in instancedApps!)
{
_allAppInstances[appInstance.Id!] = appInstance;
if (await RestoreAppState(appInstance).ConfigureAwait(false))
{
_runningAppInstances[appInstance.Id!] = appInstance;
}
_allAppInstances[appInstance.Id!] = appInstance;

}

// Now run initialize on all sorted by dependencies
Expand Down
2 changes: 1 addition & 1 deletion src/Daemon/NetDaemon.Daemon/NetDaemon.Daemon.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<tags>Home Assistant</tags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JoySoftware.HassClient" Version="20.49.1-beta" />
<PackageReference Include="JoySoftware.HassClient" Version="20.52.1-beta" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="YamlDotNet" Version="9.1.0" />
Expand Down
2 changes: 1 addition & 1 deletion src/DaemonRunner/DaemonRunner/DaemonRunner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JoySoftware.HassClient" Version="20.49.1-beta" />
<PackageReference Include="JoySoftware.HassClient" Version="20.52.1-beta" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public LocalDaemonAppCompiler(ILogger<DaemonAppCompiler> logger)
public IEnumerable<Type> GetApps()
{
_logger.LogDebug("Loading local assembly apps...");

var assemblies = LoadAll();
var apps = assemblies.SelectMany(x => x.GetTypesWhereSubclassOf<NetDaemonAppBase>()).ToList();

Expand All @@ -48,6 +48,7 @@ private IEnumerable<Assembly> LoadAll()

foreach (var netDaemonDllToLoadDynamically in netDaemonDllsToLoadDynamically)
{
_logger.LogTrace("Loading {dll} into AssemblyLoadContext", netDaemonDllToLoadDynamically);
AssemblyLoadContext.Default.LoadFromAssemblyPath(netDaemonDllToLoadDynamically);
}

Expand Down

0 comments on commit 29b0eb4

Please sign in to comment.