-
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Proposed change The change implements the System.Reactive (Rx) style of using streams of changes for automations. ## Refactorings of where logic is put In order to make application lifecycle easier, all eventlisteners and state handlers are tied to each app-instance. This makes it way more easy to disable individual apps in runtime plus manage lifecykle in the Rx stuff too. ## Implement the Rx API Implement the Rx interface. This is an alternative implementation to @jvert suggestions (thanks alot for this great idéa). This proposal was so different it was easier to implement it in own PR rather than change yours.. Hope that is ok :). New BaseClass `NetDaemonRxApp` that will implement the Rx style. We do not want to mix with old style. This is event based and not Async/await. All calls post a message on a Channel and async code takes care of the async stuff. Tests will be added. after feedback. More API features will be added before merge. Example of usage: ```c# // Observable that get state changes StateChanges.Subscribe(t=> Log(t.New.State)); // Observable that get all state changes inkluding attributes StateAllChanges.Subscribe(t=> Log(t.New.State)); // IEnumerable<EntityState> var allLights = States.Select(n => n.EntityId.StartsWith("light.")); // Gets single state var state = State("light.my_light")?.State; // No async, handled in background CallService("light", "turn_on", new {entity_id = "light.my_light"}); // Entity now not fluent // Action on single entity Entity("light.my_light").TurnOn(); Entity("light.my_light").Toggle(); // Action on multiple entities Entities("light.my_light", "light.my_light").Toggle(); // Or lambda Entities(n => n.EntityId.StartsWith("light.").Toggle(); // Merging observables <3 Entities( "binary_sensor.tomas_rum_pir", "binary_sensor.vardagsrum_pir") .StateChanges .Subscribe(e => { Log("{entity}: {state}({oldstate}, {lastchanged})", e.New.EntityId, e.New.State, e.Old.State, e.New.LastChanged); }); // Merging observables all changes including attributes <3 Entities( "binary_sensor.tomas_rum_pir", "binary_sensor.vardagsrum_pir") .StateAllChanges .Subscribe(e => { Log("{entity}: {state}({oldstate}, {lastchanged})", e.New.EntityId, e.New.State, e.Old.State, e.New.LastChanged); }); // Set state SetState("sensor.thesensor", "on", new {attributex="cool"}); // Set state selecting with Entity Selector Entity("sensor.x", "sensor.y").SetState("on"); // Merging of entity results // Schedulers RunEvery(TimeSpan.FromMinutes(1)).Subscribe(....); RunDaily("12:00:00").Subscribe(...); // Events EventChanges .Subscribe(f => { Log("event: {domain}.{event} - {data}", f?.Domain??"none", f.Event, f?.Data); }); ```
- Loading branch information
1 parent
ad40a2d
commit 6aab278
Showing
58 changed files
with
4,614 additions
and
2,184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,6 @@ TestResults | |
lcov.info | ||
codecover | ||
**.DS_Store | ||
.generated | ||
.generated | ||
scripts/version.txt | ||
packages/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using JoySoftware.HomeAssistant.NetDaemon.Common.Reactive; | ||
using Helto4real.Powertools; | ||
public static class DaemonAppExtensions | ||
{ | ||
|
||
/// <summary> | ||
/// Takes a snapshot of given entity id of camera and sends to private discord server | ||
/// </summary> | ||
/// <param name="app">NetDaemonApp to extend</param> | ||
/// <param name="camera">Unique id of the camera</param> | ||
public static void CameraTakeSnapshotAndNotify(this NetDaemonRxApp app, string camera) | ||
{ | ||
var imagePath = app.CameraSnapshot(camera); | ||
|
||
app.NotifyImage(camera, imagePath); | ||
} | ||
|
||
public static void Notify(this NetDaemonRxApp app, string message) | ||
{ | ||
app.CallService("notify", "hass_discord", new | ||
{ | ||
message = message, | ||
target = "511278310584746008" | ||
}); | ||
} | ||
|
||
public static void NotifyImage(this NetDaemonRxApp app, string message, string imagePath) | ||
{ | ||
var dict = new Dictionary<string, IEnumerable<string>> | ||
{ | ||
["images"] = new List<string> { imagePath } | ||
}; | ||
|
||
app.CallService("notify", "hass_discord", new | ||
{ | ||
data = dict, | ||
message = message, | ||
target = "511278310584746008" | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
|
||
using System; | ||
using System.Threading.Tasks; | ||
using JoySoftware.HomeAssistant.NetDaemon.Common; | ||
|
||
// public static class ServiceCallExtensions | ||
// { | ||
// public static Task ToggleAsync(this NetDaemonApp app, string entityId, params (string name, object val)[] attributeNameValuePair) | ||
// { | ||
// // Get the domain if supported, else domain is homeassistant | ||
// string domain = GetDomainFromEntity(entityId); | ||
// // Use it if it is supported else use default "homeassistant" domain | ||
|
||
// // Use expando object as all other methods | ||
// dynamic attributes = attributeNameValuePair.ToDynamic(); | ||
// // and add the entity id dynamically | ||
// attributes.entity_id = entityId; | ||
|
||
// return app.CallService(domain, "toggle", attributes, false); | ||
// } | ||
|
||
// public static Task TurnOffAsync(this NetDaemonApp app, string entityId, params (string name, object val)[] attributeNameValuePair) | ||
// { | ||
// // Get the domain if supported, else domain is homeassistant | ||
// string domain = GetDomainFromEntity(entityId); | ||
// // Use it if it is supported else use default "homeassistant" domain | ||
|
||
// // Use expando object as all other methods | ||
// dynamic attributes = attributeNameValuePair.ToDynamic(); | ||
// // and add the entity id dynamically | ||
// attributes.entity_id = entityId; | ||
|
||
// return app.CallService(domain, "turn_off", attributes, false); | ||
// } | ||
|
||
// public static Task TurnOnAsync(this NetDaemonApp app, string entityId, params (string name, object val)[] attributeNameValuePair) | ||
// { | ||
// // Use default domain "homeassistant" if supported is missing | ||
// string domain = GetDomainFromEntity(entityId); | ||
// // Use it if it is supported else use default "homeassistant" domain | ||
|
||
// // Convert the value pairs to dynamic type | ||
// dynamic attributes = attributeNameValuePair.ToDynamic(); | ||
// // and add the entity id dynamically | ||
// attributes.entity_id = entityId; | ||
|
||
// return app.CallService(domain, "turn_on", attributes, false); | ||
// } | ||
|
||
// private static string GetDomainFromEntity(string entity) | ||
// { | ||
// var entityParts = entity.Split('.'); | ||
// if (entityParts.Length != 2) | ||
// throw new ApplicationException($"entity_id is mal formatted {entity}"); | ||
|
||
// return entityParts[0]; | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using JoySoftware.HomeAssistant.NetDaemon.Common.Reactive; | ||
|
||
// Use unique namespaces for your apps if you going to share with others to avoid | ||
// conflicting names | ||
namespace Helto4real.Powertools | ||
{ | ||
public static class Powertools | ||
{ | ||
/// <summary> | ||
/// Takes a snapshot of given entity id of camera and sends to private discord server | ||
/// </summary> | ||
/// <param name="app">NetDaemonApp to extend</param> | ||
/// <param name="camera">Unique id of the camera</param> | ||
/// <returns>The path to the snapshot</returns> | ||
public static string CameraSnapshot(this NetDaemonRxApp app, string camera) | ||
{ | ||
var resultingFilename = $"/config/www/motion/{camera}_latest.jpg"; | ||
app.CallService("camera", "snapshot", new | ||
{ | ||
entity_id = camera, | ||
filename = resultingFilename | ||
}); | ||
|
||
return resultingFilename; | ||
} | ||
|
||
/// <summary> | ||
/// Takes a snapshot of given entity id of camera and sends to private discord server | ||
/// </summary> | ||
/// <param name="app">NetDaemonApp to extend</param> | ||
/// <param name="camera">Unique id of the camera</param> | ||
public static void CameraSnapshot(this NetDaemonRxApp app, string camera, string snapshotPath) | ||
{ | ||
app.CallService("camera", "snapshot", new | ||
{ | ||
entity_id = camera, | ||
filename = snapshotPath | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Prints the contents from a IDictionary to a string | ||
/// </summary> | ||
/// <param name="app">NetDaemonApp to extend</param> | ||
/// <param name="dict">The dict to print from, typically from dynamic result</param> | ||
/// <returns></returns> | ||
public static string PrettyPrintDictData(this NetDaemonRxApp app, IDictionary<string, object>? dict) | ||
{ | ||
|
||
if (dict == null) | ||
return string.Empty; | ||
|
||
var builder = new StringBuilder(100); | ||
foreach (var key in dict.Keys) | ||
{ | ||
builder.AppendLine($"{key}:{dict[key]}"); | ||
} | ||
return builder.ToString(); | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
my_app: | ||
class: BatteryManager | ||
# HelloWorldSecret: !secret test_secret | ||
dependencies: | ||
- global_app | ||
class: BatteryManager | ||
# HelloWorldSecret: !secret test_secret | ||
# dependencies: | ||
# - global_app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,33 @@ | ||
Invoke-Expression "del D:\GIT\netdaemon\src\App\NetDaemon.App\bin\Debug\*.nupkg" | ||
Invoke-Expression "del D:\GIT\netdaemon\src\Daemon\NetDaemon.Daemon\bin\Debug\*.nupkg" | ||
Invoke-Expression "del D:\GIT\netdaemon\src\DaemonRunner\DaemonRunner\bin\Debug\*.nupkg" | ||
# | ||
# This script is building the nuget packages for you to import and test in a dev environment | ||
# for building apps. Run once to create the version file. Then set the version you want to use | ||
# run script and the packages is copied to ./packages folder. | ||
# In your app dev environment, | ||
# - change version in csproj file | ||
# - Do a "dotnet restore -s [path_to_package_folder]" | ||
# | ||
# RUN THIS FILE FROM PROJECT ROOT! | ||
# | ||
|
||
Invoke-Expression "dotnet pack ..\src\" | ||
# Create the version file if not exists | ||
if ((Test-Path ./scripts/version.txt) -eq $False) { | ||
New-Item -Path ./scripts -Name "version.txt" -ItemType "file" -Value "0.0.1-beta" | ||
} | ||
|
||
Invoke-Expression "del D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.App\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\App\NetDaemon.App\bin\Debug\*.nupkg D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.App\" | ||
Invoke-Expression "del D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.App\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\App\NetDaemon.App\bin\Debug\*.nupkg D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.App\" | ||
if ((Test-Path ./packages) -eq $False) { | ||
New-Item . -Name "packages" -ItemType "directory" | ||
} | ||
# Remove all current nuget packages | ||
Get-ChildItem ./src -file -recurse "*.nupkg" | Remove-Item | ||
|
||
Invoke-Expression "del D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.Daemon\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\Daemon\NetDaemon.Daemon\bin\Debug\*.nupkg D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.Daemon\" | ||
Invoke-Expression "del D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.Daemon\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\Daemon\NetDaemon.Daemon\bin\Debug\*.nupkg D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.Daemon\" | ||
# Get version to be used | ||
$version = Get-Content ./scripts/version.txt | ||
|
||
# Pack | ||
dotnet pack -p:PackageVersion=$version | ||
|
||
# Copy the two app packages | ||
Get-ChildItem ./src/App -file -recurse "*.nupkg" | Copy-Item -Destination "./packages" | ||
Get-ChildItem ./src/DaemonRunner -file -recurse "*.nupkg" | Copy-Item -Destination "./packages" | ||
Get-ChildItem ./src/Daemon -file -recurse "*.nupkg" | Copy-Item -Destination "./packages" | ||
|
||
Invoke-Expression "del D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.DaemonRunner\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\DaemonRunner\DaemonRunner\bin\Debug\*.nupkg D:\GIT\daemonapp\packs\JoySoftware.NetDaemon.DaemonRunner\" | ||
Invoke-Expression "del D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.DaemonRunner\*.nupkg" | ||
Invoke-Expression "cp D:\GIT\netdaemon\src\DaemonRunner\DaemonRunner\bin\Debug\*.nupkg D:\GIT\daemontest\cs\package\JoySoftware.NetDaemon.DaemonRunner\" |
Oops, something went wrong.