Skip to content

Commit

Permalink
Merge pull request #37
Browse files Browse the repository at this point in the history
* Add service for disabling automations in room
  • Loading branch information
x00Pavel authored Mar 9, 2024
1 parent 08324e0 commit f986b34
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 55 deletions.
77 changes: 29 additions & 48 deletions src/Core/Automations/AutomationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,24 @@ internal record ServiceData
public string? value { get; init; }
}

public interface IAutomationBase
public abstract class IAutomationBase
{
}/// <summary>
private bool _enabled = true;
public IObservable<bool> IsEnabledObserver;
public event EventHandler<bool>? IsEnabledChanged;
public bool IsEnabled
{
get => _enabled;
set
{
if (_enabled == value) return;
_enabled = value;
IsEnabledChanged?.Invoke(this, value);
}
}
}

/// <summary>
/// This class represents a base for all automations.
/// The automation works with certain type of entities and uses Finite State Machine to store and represent the state of the entities.
/// </summary>
Expand All @@ -34,21 +49,9 @@ public abstract class AutomationBase<TEntity, TFsm>: IAutomationBase
protected IHaContext Context { get; set; }
protected ILogger Logger { get; set; }
protected AutomationConfig Config { get; set; }
protected IEnumerable<TEntity> EntitiesList { get; set; }
protected List<TEntity> EntitiesList { get; set; }
protected List<TFsm> FsmList;
protected IObservable<bool> IsEnabledObserver;
private bool isEnabled { get; set; } = true;
public event EventHandler<bool>? IsEnabledChanged;
public bool IsEnabled
{
get => isEnabled;
set
{
if (isEnabled == value) return;
isEnabled = value;
IsEnabledChanged?.Invoke(this, value);
}
}

protected AutomationBase(IHaContext context, AutomationConfig config, ILogger logger)
{
Context = context;
Expand All @@ -59,8 +62,7 @@ protected AutomationBase(IHaContext context, AutomationConfig config, ILogger lo
handler => IsEnabledChanged -= handler
).Select(pattern => pattern.EventArgs);
FsmList = new List<TFsm>();
EntitiesList = Config.Entities.OfType<TEntity>().ToArray() ?? [];
InitServices();
EntitiesList = Config.Entities.OfType<TEntity>().ToList();
if (Config is { StartAtTimeFunc: not null, StopAtTimeFunc: not null })
Logger.LogDebug("Working hours from {Start} - {End}", Config.StartAtTimeFunc() , Config.StopAtTimeFunc());
Logger.LogDebug("Night mode from {Start} - {End}", Config.NightMode.StartAtTimeFunc(), Config.NightMode.StopAtTimeFunc());
Expand Down Expand Up @@ -121,7 +123,7 @@ protected void CreateFsm()
/// <returns></returns>
protected IObservable<StateChange> UserEvent(string id) => EntityEvent(id)
.Where(e => !e.IsAutomationInitiated(Config.ServiceAccountId));

/// <summary>
/// Observable for all state changes of a specific entity initiated by the automation.
/// This method uses ServiceAccountId to determine if the state change was initiated by the automation.
Expand All @@ -141,36 +143,15 @@ protected IObservable<StateChange> AutomationEvent(string id) => EntityEvent(id)
protected static void ChooseAction(bool condition, Action action, Action elseAction) => (condition ? action : elseAction)();

/// <summary>
/// This method is used to initialise services for manipulating with the automation from Home Assistant side.
/// It is not yet fully implemented!
/// Helper observable for making actions when automation is disabled.
/// </summary>
private void InitServices()
{
// Context.RegisterServiceCallBack<ServiceData>($"automation_{Config.Name.Replace(' ', '_').ToLower()}_service",
// e =>
// {
// if (Enum.TryParse<ServiceAction>(e.action, ignoreCase: true, out var action))
// {
//
// Logger.LogInformation("Service called action: {Action}", action);
// IsEnabled = action switch
// {
// ServiceAction.Disable => false,
// ServiceAction.Enable => true,
// ServiceAction.Toggle => !isEnabled,
// _ => isEnabled
// };
//
// Logger.LogDebug("Automation {AutomationName} is now {AutomationState}", Config.Name, isEnabled ? "enabled" : "disabled");
// }
// else
// {
// Logger.LogWarning("Service called with unknown action: {Action} value: {value}",
// e.action, e.value);
// }
// });
}

public IObservable<bool> AutomationDisabled => IsEnabledObserver.Where(enabled => !enabled);

/// <summary>
/// Helper observable for making actions when automation is enabled.
/// </summary>
public IObservable<bool> AutomationEnabled => IsEnabledObserver.Where(enabled => enabled);

protected bool IsWorkingHours()
{
if (Config is { StartAtTimeFunc: not null, StopAtTimeFunc: not null })
Expand Down
27 changes: 22 additions & 5 deletions src/Core/Automations/LightAutomationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using NetDaemon.HassModel.Entities;
using NetEntityAutomation.Core.Configs;
using NetEntityAutomation.Core.Fsm;
using NetEntityAutomation.Core.Triggers;
using NetEntityAutomation.Extensions.ExtensionMethods;
using Newtonsoft.Json;

Expand Down Expand Up @@ -38,27 +39,43 @@ private void ConfigureAutomation()

foreach (var sensor in Config.Triggers)
{
sensor.On.Subscribe(TurnOnByAutomation);
sensor.On.Subscribe(e => { if (IsEnabled) TurnOnByAutomation(e.Entity); });
}

AutomationDisabled.Subscribe(e =>
{
Logger.LogDebug("Disabling automation {Automation}", nameof(LightAutomationBase));
foreach (var fsm in LightOnByAutomation)
{
fsm.Timer.Dispose();
}
});

AutomationEnabled.Subscribe(e =>
{
Logger.LogDebug("Enabling automation {Automation}", nameof(LightAutomationBase));
if (Config.Triggers.IsAllOn())
EntitiesList.ForEach(l => TurnOnByAutomation(l));
});
}

private void TurnOnByAutomation(StateChange e)
private void TurnOnByAutomation(IEntityCore entityCore)
{
if (!IsWorkingHours())
{
Logger.LogDebug("Turning on lights by motion sensor {Sensor} is not allowed because it's not working hours",
e.Entity.EntityId);
entityCore.EntityId);
return;
}

if (!Config.Conditions.All(c => c.IsTrue()))
{
Logger.LogDebug("Not all conditions are met to turn on lights by motion sensor {Sensor}",
e.Entity.EntityId);
entityCore.EntityId);
return;
}

Logger.LogDebug("Turning on lights by motion sensor {Sensor}", e.Entity.EntityId);
Logger.LogDebug("Turning on lights by motion sensor {Sensor}", entityCore.EntityId);
switch (Config.NightMode)
{
case { IsEnabled: true, IsWorkingHours: true }:
Expand Down
23 changes: 22 additions & 1 deletion src/Core/RoomManager/Room.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using NetDaemon.HassModel;
using NetDaemon.HassModel.Integration;
using NetEntityAutomation.Core.Automations;
using NetEntityAutomation.Core.Configs;

Expand All @@ -20,6 +21,23 @@ public Room(IRoomConfig roomConfig, IHaContext haContext)
_roomConfig.Logger.LogDebug("Creating room {RoomName}", roomConfig.Name);
_haContext = haContext;
InitAutomations();
InitServices();
}

private void InitServices()
{
var serviceName = _roomConfig.Name.ToLower().Replace(' ', '_') + "_service";
_haContext.RegisterServiceCallBack<RoomData>("toggle_" + serviceName, data =>
{
_automations.ForEach(auto =>
{
auto.IsEnabled = !auto.IsEnabled;
_roomConfig.Logger.LogDebug("Toggling automation {AutomationName} to {IsEnabled}",
auto.GetType().Name,
auto.IsEnabled ? "enabled" : "disabled");
});
});
_roomConfig.Logger.LogDebug("Service {ServiceName} initialised", serviceName);
}

private void InitAutomations()
Expand All @@ -43,7 +61,10 @@ private void InitAutomations()
break;
}
}

_roomConfig.Logger.LogDebug("Number of automations: {AutomationCount}", _automations.Count);
}
}

internal record RoomData
{
}
2 changes: 1 addition & 1 deletion src/Core/RoomManager/RoomManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NetDaemon.HassModel.Integration" Version="24.3.1" />
<PackageReference Include="NetDaemon.HassModel.Integration" Version="24.8.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Scrutor" Version="4.2.2" />
</ItemGroup>
Expand Down

0 comments on commit f986b34

Please sign in to comment.