diff --git a/src/CodeCasa.AutomationPipelines.Lights/Nodes/TurnOffThenPassThroughNode.cs b/src/CodeCasa.AutomationPipelines.Lights/Nodes/TurnOffThenPassThroughNode.cs index 3ad407e..00d0a98 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Nodes/TurnOffThenPassThroughNode.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Nodes/TurnOffThenPassThroughNode.cs @@ -2,8 +2,25 @@ namespace CodeCasa.AutomationPipelines.Lights.Nodes; -internal class TurnOffThenPassThroughNode : PipelineNode +/// +/// A pipeline node that initially outputs , +/// then switches to pass-through mode after receiving its first input. +/// +/// +/// This node is useful for scenarios where a light should be turned off, +/// but then forward subsequent inputs from upstream nodes without modification. +/// The pass-through behavior is activated upon receiving the first input. +/// +public sealed class TurnOffThenPassThroughNode : PipelineNode { + /// + /// Initializes a new instance of the class. + /// + /// + /// The initial output is set to . + /// Pass-through mode is not enabled in the constructor because the input + /// is immediately set when this node is added to the timeline. + /// public TurnOffThenPassThroughNode() { // Note: we cannot simply call ChangeOutputAndTurnOnPassThroughOnNextInput here, as the input will immediately be set when this node is added to the timeline. diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs index fad90d6..1c24a4e 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/CompositeLightTransitionReactiveNodeConfigurator.cs @@ -76,6 +76,23 @@ public ILightTransitionReactiveNodeConfigurator AddUncoupledDimmer(IDimm } return this; + + } + + /// + public ILightTransitionReactiveNodeConfigurator AddNodeSource() + where TNodeSource : IObservable?>> + { + configurators.Values.ForEach(c => c.AddNodeSource()); + return this; + } + + /// + public ILightTransitionReactiveNodeConfigurator AddNodeSource( + Func?>>> nodeFactorySourceFactory) + { + configurators.Values.ForEach(c => c.AddNodeSource(nodeFactorySourceFactory)); + return this; } /// diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs index b71c38e..6e09150 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/ILightTransitionReactiveNodeConfigurator.cs @@ -57,6 +57,25 @@ public partial interface ILightTransitionReactiveNodeConfigurator where /// The configurator instance for method chaining. ILightTransitionReactiveNodeConfigurator AddUncoupledDimmer(IDimmer dimmer, Action dimOptions); + /// + /// Adds a dynamic node source resolved from the service provider. + /// The node source type must implement where T is a factory function for creating pipeline nodes. + /// Useful for reusable, class-based node sources registered in dependency injection. + /// + /// The type of the node source, which must be an observable that emits node factory functions. + /// The configurator instance for method chaining. + ILightTransitionReactiveNodeConfigurator AddNodeSource() + where TNodeSource : IObservable?>>; + + /// + /// Adds a dynamic node source created by a factory function that receives the service provider. + /// Useful for extension methods that need to compose existing DI services to build the observable. + /// + /// A factory function that receives the service provider and returns an observable that emits node factory functions. + /// The configurator instance for method chaining. + ILightTransitionReactiveNodeConfigurator AddNodeSource( + Func?>>> nodeFactorySourceFactory); + /// /// Adds a dynamic node source that activates a new node in the reactive node each time the observable emits a factory. /// The emitted factory is invoked to create and activate the new pipeline node. diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs index 0ce7f0d..05e97c3 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.cs @@ -113,6 +113,20 @@ public ILightTransitionReactiveNodeConfigurator AddNodeSource(IObservabl return this; } + /// + public ILightTransitionReactiveNodeConfigurator AddNodeSource() + where TNodeSource : IObservable?>> + { + return AddNodeSource(ActivatorUtilities.CreateInstance(ServiceProvider)); + } + + /// + public ILightTransitionReactiveNodeConfigurator AddNodeSource( + Func?>>> nodeFactorySourceFactory) + { + return AddNodeSource(nodeFactorySourceFactory(ServiceProvider)); + } + /// public ILightTransitionReactiveNodeConfigurator AddNodeSource(IObservable?>> nodeFactorySource) {