Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using CodeCasa.AutomationPipelines.Lights.Extensions;
using CodeCasa.AutomationPipelines.Lights.ReactiveNode;
using CodeCasa.Lights;
using System.Collections.Generic;
using System.Xml.Linq;

namespace CodeCasa.AutomationPipelines.Lights.Pipeline
{
Expand All @@ -20,9 +22,16 @@ internal partial class CompositeLightTransitionPipelineConfigurator(
public Dictionary<string, LightTransitionPipelineConfigurator> NodeContainers { get; } = nodeContainers;

/// <inheritdoc/>
public ILightTransitionPipelineConfigurator SetName(string name)
public ILightTransitionPipelineConfigurator EnableLogging(string? pipelineName = null)
{
NodeContainers.Values.ForEach(b => b.SetName(name));
NodeContainers.Values.ForEach(b => b.EnableLogging(pipelineName));
return this;
}

/// <inheritdoc/>
public ILightTransitionPipelineConfigurator DisableLogging()
{
NodeContainers.Values.ForEach(b => b.DisableLogging());
return this;
}

Expand All @@ -45,7 +54,16 @@ public ILightTransitionPipelineConfigurator AddReactiveNode(
Action<ILightTransitionReactiveNodeConfigurator> configure)
{
var nodes = reactiveNodeFactory.CreateReactiveNodes(NodeContainers.Select(nc => nc.Value.Light),
configure);
c =>
{
var firstContainer = NodeContainers.Values.First();
if (firstContainer.Log ?? false)
{
// If logging is enabled, enable it on the reactive node configurator by default.
c.EnableLogging($"Reactive Node in {firstContainer.Name ?? "light group"}");
}
configure(c);
});
NodeContainers.ForEach(kvp => kvp.Value.AddNode(nodes[kvp.Key]));
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ namespace CodeCasa.AutomationPipelines.Lights.Pipeline;
public partial interface ILightTransitionPipelineConfigurator
{
/// <summary>
/// Sets the name for the current pipeline configuration.
/// Enables logging for the pipeline configuration.
/// </summary>
/// <param name="name">The name to assign to the pipeline.</param>
/// <param name="pipelineName">The optional name of the pipeline to include in logs.</param>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionPipelineConfigurator SetName(string name);
ILightTransitionPipelineConfigurator EnableLogging(string? pipelineName = null);

/// <summary>
/// Disables logging for the pipeline configuration.
/// </summary>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionPipelineConfigurator DisableLogging();

/// <summary>
/// Adds a pipeline node of type <typeparamref name="TNode"/> to the pipeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ internal Dictionary<string, IPipeline<LightTransition>> CreateLightPipelines(IEn
return configurators.ToDictionary(kvp => kvp.Key, kvp =>
{
var conf = kvp.Value;
if (conf.Log ?? false)
{
return new Pipeline<LightTransition>(
conf.Name ?? conf.Light.Id,
LightTransition.Off(),
conf.Nodes,
conf.Light.ApplyTransition,
logger);
}

return (IPipeline<LightTransition>)new Pipeline<LightTransition>(
conf.Name ?? conf.Light.Id,
LightTransition.Off(),
conf.Nodes,
conf.Light.ApplyTransition,
logger);
conf.Light.ApplyTransition);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal partial class LightTransitionPipelineConfigurator(

internal ILight Light { get; } = light;
internal string? Name { get; private set; }
internal bool? Log { get; private set; }

public IReadOnlyCollection<IPipelineNode<LightTransition>> Nodes => _nodes.AsReadOnly();

Expand All @@ -31,9 +32,17 @@ public ILightTransitionPipelineConfigurator
}

/// <inheritdoc/>
public ILightTransitionPipelineConfigurator SetName(string name)
public ILightTransitionPipelineConfigurator EnableLogging(string? pipelineName = null)
{
Name = name;
Name = pipelineName;
Log = true;
return this;
}

/// <inheritdoc/>
public ILightTransitionPipelineConfigurator DisableLogging()
{
Log = false;
return this;
}

Expand Down Expand Up @@ -66,7 +75,15 @@ public ILightTransitionPipelineConfigurator AddNode(Func<ILightPipelineContext,
public ILightTransitionPipelineConfigurator AddReactiveNode(
Action<ILightTransitionReactiveNodeConfigurator> configure)
{
return AddNode(reactiveNodeFactory.CreateReactiveNode(Light, configure));
return AddNode(reactiveNodeFactory.CreateReactiveNode(Light, c =>
{
if (Log ?? false)
{
// If logging is enabled, enable it on the reactive node configurator by default.
c.EnableLogging($"Reactive Node in {Name ?? Light.Id}");
}
configure(c);
}));
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@ internal partial class CompositeLightTransitionReactiveNodeConfigurator(
: ILightTransitionReactiveNodeConfigurator
{
/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator SetName(string name)
public ILightTransitionReactiveNodeConfigurator EnableLogging(string? name = null)
{
configurators.Values.ForEach(c => c.SetName(name));
configurators.Values.ForEach(b => b.EnableLogging(name));
return this;
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator DisableLogging()
{
configurators.Values.ForEach(b => b.DisableLogging());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ namespace CodeCasa.AutomationPipelines.Lights.ReactiveNode;
public partial interface ILightTransitionReactiveNodeConfigurator
{
/// <summary>
/// Sets the name for the current reactive node configuration.
/// Enables logging for the reactive node configuration.
/// </summary>
/// <param name="name">The name to assign to the reactive node.</param>
/// <param name="name">The optional name of the reactive node to include in logs.</param>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionReactiveNodeConfigurator SetName(string name);
ILightTransitionReactiveNodeConfigurator EnableLogging(string? name = null);

/// <summary>
/// Disables logging for the reactive node configuration.
/// </summary>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionReactiveNodeConfigurator DisableLogging();

/// <summary>
/// Adds a reactive dimmer control that will be reset when the reactive node activates a new node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Xml.Linq;
using CodeCasa.AutomationPipelines.Lights.Utils;
using Microsoft.Extensions.DependencyInjection;

namespace CodeCasa.AutomationPipelines.Lights.ReactiveNode;
Expand All @@ -30,14 +28,23 @@ internal partial class LightTransitionReactiveNodeConfigurator(
public ILight Light { get; } = light;

internal string? Name { get; private set; }
internal bool? Log { get; private set; }
internal List<IObservable<IPipelineNode<LightTransition>?>> NodeObservables { get; } = new();
internal List<IDimmer> Dimmers { get; } = new();
internal DimmerOptions DimmerOptions { get; private set; } = new ();

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator SetName(string name)
public ILightTransitionReactiveNodeConfigurator EnableLogging(string? name = null)
{
Name = name;
Log = true;
return this;
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator DisableLogging()
{
Log = false;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ public class ReactiveNode : PipelineNode<LightTransition>
private IPipelineNode<LightTransition>? _activeNode;
private IDisposable? _activeNodeSubscription;

/// <summary>
/// Initializes a new instance of the <see cref="ReactiveNode"/> class.
/// </summary>
/// <param name="nodeObservable">An observable that emits the pipeline nodes to activate. Null values deactivate the current node.</param>
public ReactiveNode(IObservable<IPipelineNode<LightTransition>?> nodeObservable) :
this(null, nodeObservable, null!)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ReactiveNode"/> class.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,14 @@ internal Dictionary<string, IPipelineNode<LightTransition>> CreateReactiveNodes(

private ReactiveNode CreateReactiveNode(LightTransitionReactiveNodeConfigurator reactiveNodeConfigurator)
{
return new ReactiveNode(
reactiveNodeConfigurator.Name,
reactiveNodeConfigurator.NodeObservables.Merge(),
serviceProvider.GetRequiredService<ILogger<ReactiveNode>>());
if (reactiveNodeConfigurator.Log ?? false)
{
return new ReactiveNode(
reactiveNodeConfigurator.Name,
reactiveNodeConfigurator.NodeObservables.Merge(),
serviceProvider.GetRequiredService<ILogger<ReactiveNode>>());
}
return new ReactiveNode(reactiveNodeConfigurator.NodeObservables.Merge());
}

private void SubscribeToPulses(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ public void Initialize()
public void CreateNode()
{
// Act
var node = _reactiveNodeFactory.CreateReactiveNode(_lightMock.Object, config =>
{
config.SetName("TestNode");
});
var node = _reactiveNodeFactory.CreateReactiveNode(_lightMock.Object, _ => { });

// Assert
Assert.IsNotNull(node);
Expand Down