From d271bb97aa85a91bd3f28792a40a0db3eab32a13 Mon Sep 17 00:00:00 2001 From: Jasper Date: Sat, 3 Jan 2026 17:26:00 +0100 Subject: [PATCH] Implemented methods to configure logging in the light automation pipeline. --- ...siteLightTransitionPipelineConfigurator.cs | 24 ++++++++++++++++--- .../ILightTransitionPipelineConfigurator.cs | 12 +++++++--- .../Pipeline/LightPipelineFactory.cs | 14 ++++++++--- .../LightTransitionPipelineConfigurator.cs | 23 +++++++++++++++--- ...LightTransitionReactiveNodeConfigurator.cs | 11 +++++++-- ...LightTransitionReactiveNodeConfigurator.cs | 12 +++++++--- ...LightTransitionReactiveNodeConfigurator.cs | 13 +++++++--- .../ReactiveNode/ReactiveNode.cs | 9 +++++++ .../ReactiveNode/ReactiveNodeFactory.cs | 12 ++++++---- .../ReactiveNodeTests.cs | 5 +--- 10 files changed, 107 insertions(+), 28 deletions(-) diff --git a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.cs index e410737..b74d20e 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.cs @@ -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 { @@ -20,9 +22,16 @@ internal partial class CompositeLightTransitionPipelineConfigurator( public Dictionary NodeContainers { get; } = nodeContainers; /// - 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; + } + + /// + public ILightTransitionPipelineConfigurator DisableLogging() + { + NodeContainers.Values.ForEach(b => b.DisableLogging()); return this; } @@ -45,7 +54,16 @@ public ILightTransitionPipelineConfigurator AddReactiveNode( Action 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; } diff --git a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/ILightTransitionPipelineConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/ILightTransitionPipelineConfigurator.cs index e6cc4d3..5950d6e 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/ILightTransitionPipelineConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/ILightTransitionPipelineConfigurator.cs @@ -12,11 +12,17 @@ namespace CodeCasa.AutomationPipelines.Lights.Pipeline; public partial interface ILightTransitionPipelineConfigurator { /// - /// Sets the name for the current pipeline configuration. + /// Enables logging for the pipeline configuration. /// - /// The name to assign to the pipeline. + /// The optional name of the pipeline to include in logs. /// The configurator instance for method chaining. - ILightTransitionPipelineConfigurator SetName(string name); + ILightTransitionPipelineConfigurator EnableLogging(string? pipelineName = null); + + /// + /// Disables logging for the pipeline configuration. + /// + /// The configurator instance for method chaining. + ILightTransitionPipelineConfigurator DisableLogging(); /// /// Adds a pipeline node of type to the pipeline. diff --git a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightPipelineFactory.cs b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightPipelineFactory.cs index 48c5ba2..bd1bfd5 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightPipelineFactory.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightPipelineFactory.cs @@ -68,12 +68,20 @@ internal Dictionary> CreateLightPipelines(IEn return configurators.ToDictionary(kvp => kvp.Key, kvp => { var conf = kvp.Value; + if (conf.Log ?? false) + { + return new Pipeline( + conf.Name ?? conf.Light.Id, + LightTransition.Off(), + conf.Nodes, + conf.Light.ApplyTransition, + logger); + } + return (IPipeline)new Pipeline( - conf.Name ?? conf.Light.Id, LightTransition.Off(), conf.Nodes, - conf.Light.ApplyTransition, - logger); + conf.Light.ApplyTransition); }); } } diff --git a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.cs index eea9e5b..37f3558 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.cs @@ -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> Nodes => _nodes.AsReadOnly(); @@ -31,9 +32,17 @@ public ILightTransitionPipelineConfigurator } /// - public ILightTransitionPipelineConfigurator SetName(string name) + public ILightTransitionPipelineConfigurator EnableLogging(string? pipelineName = null) { - Name = name; + Name = pipelineName; + Log = true; + return this; + } + + /// + public ILightTransitionPipelineConfigurator DisableLogging() + { + Log = false; return this; } @@ -66,7 +75,15 @@ public ILightTransitionPipelineConfigurator AddNode(Func 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); + })); } /// diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs index f72ab7d..8d51871 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs @@ -20,9 +20,16 @@ internal partial class CompositeLightTransitionReactiveNodeConfigurator( : ILightTransitionReactiveNodeConfigurator { /// - 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; + } + + /// + public ILightTransitionReactiveNodeConfigurator DisableLogging() + { + configurators.Values.ForEach(b => b.DisableLogging()); return this; } diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs index 339bf73..1d76089 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs @@ -11,11 +11,17 @@ namespace CodeCasa.AutomationPipelines.Lights.ReactiveNode; public partial interface ILightTransitionReactiveNodeConfigurator { /// - /// Sets the name for the current reactive node configuration. + /// Enables logging for the reactive node configuration. /// - /// The name to assign to the reactive node. + /// The optional name of the reactive node to include in logs. /// The configurator instance for method chaining. - ILightTransitionReactiveNodeConfigurator SetName(string name); + ILightTransitionReactiveNodeConfigurator EnableLogging(string? name = null); + + /// + /// Disables logging for the reactive node configuration. + /// + /// The configurator instance for method chaining. + ILightTransitionReactiveNodeConfigurator DisableLogging(); /// /// Adds a reactive dimmer control that will be reset when the reactive node activates a new node. diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs index 8578c82..68f19f5 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs @@ -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; @@ -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?>> NodeObservables { get; } = new(); internal List Dimmers { get; } = new(); internal DimmerOptions DimmerOptions { get; private set; } = new (); /// - public ILightTransitionReactiveNodeConfigurator SetName(string name) + public ILightTransitionReactiveNodeConfigurator EnableLogging(string? name = null) { Name = name; + Log = true; + return this; + } + + /// + public ILightTransitionReactiveNodeConfigurator DisableLogging() + { + Log = false; return this; } diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNode.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNode.cs index ad3f53a..60ca6e2 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNode.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNode.cs @@ -20,6 +20,15 @@ public class ReactiveNode : PipelineNode private IPipelineNode? _activeNode; private IDisposable? _activeNodeSubscription; + /// + /// Initializes a new instance of the class. + /// + /// An observable that emits the pipeline nodes to activate. Null values deactivate the current node. + public ReactiveNode(IObservable?> nodeObservable) : + this(null, nodeObservable, null!) + { + } + /// /// Initializes a new instance of the class. /// diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNodeFactory.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNodeFactory.cs index 08d5d37..dfb6141 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNodeFactory.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ReactiveNodeFactory.cs @@ -130,10 +130,14 @@ internal Dictionary> CreateReactiveNodes( private ReactiveNode CreateReactiveNode(LightTransitionReactiveNodeConfigurator reactiveNodeConfigurator) { - return new ReactiveNode( - reactiveNodeConfigurator.Name, - reactiveNodeConfigurator.NodeObservables.Merge(), - serviceProvider.GetRequiredService>()); + if (reactiveNodeConfigurator.Log ?? false) + { + return new ReactiveNode( + reactiveNodeConfigurator.Name, + reactiveNodeConfigurator.NodeObservables.Merge(), + serviceProvider.GetRequiredService>()); + } + return new ReactiveNode(reactiveNodeConfigurator.NodeObservables.Merge()); } private void SubscribeToPulses( diff --git a/tests/CodeCasa.AutomationPipelines.Lights.Tests/ReactiveNodeTests.cs b/tests/CodeCasa.AutomationPipelines.Lights.Tests/ReactiveNodeTests.cs index 538b161..1e82fb3 100644 --- a/tests/CodeCasa.AutomationPipelines.Lights.Tests/ReactiveNodeTests.cs +++ b/tests/CodeCasa.AutomationPipelines.Lights.Tests/ReactiveNodeTests.cs @@ -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);