From 1a9e1087de4a58a3ac59cd833c534faa9ad45e13 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 27 Jun 2025 10:32:21 -0400 Subject: [PATCH 1/3] fix: add property to disable auto mode --- .../Room/Combining/EssentialsRoomCombiner.cs | 105 ++++++++++++++++++ .../EssentialsRoomCombinerPropertiesConfig.cs | 45 ++++++-- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index f0fb5e98..681f8810 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -10,6 +10,13 @@ using System.Threading.Tasks; namespace PepperDash.Essentials.Core { + /// + /// Represents a device that manages room combinations by controlling partitions and scenarios. + /// + /// The allows for dynamic configuration of room + /// combinations based on partition states and predefined scenarios. It supports both automatic and manual modes + /// for managing room combinations. In automatic mode, the device determines the current room combination scenario + /// based on partition sensor states. In manual mode, scenarios can be set explicitly by the user. public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner { private EssentialsRoomCombinerPropertiesConfig _propertiesConfig; @@ -18,6 +25,9 @@ namespace PepperDash.Essentials.Core private List _rooms; + /// + /// Gets a list of rooms represented as key-name pairs. + /// public List Rooms { get @@ -28,6 +38,12 @@ namespace PepperDash.Essentials.Core private bool _isInAutoMode; + /// + /// Gets or sets a value indicating whether the system is operating in automatic mode. + /// + /// Changing this property triggers an update event via + /// IsInAutoModeFeedback.FireUpdate(). Ensure that any event listeners are properly configured to handle + /// this update. public bool IsInAutoMode { get @@ -52,6 +68,19 @@ namespace PepperDash.Essentials.Core private Mutex _scenarioChange = new Mutex(); + /// + /// Initializes a new instance of the class, which manages room combination + /// scenarios and partition states. + /// + /// The class is designed to handle dynamic room + /// combination scenarios based on partition states. It supports both automatic and manual modes for managing + /// room combinations. By default, the instance starts in automatic mode unless the + /// specifies otherwise. After activation, the room combiner initializes partition state providers and sets up + /// the initial room configuration. Additionally, it subscribes to the event to ensure proper initialization of dependent devices + /// before determining or setting the room combination scenario. + /// The unique identifier for the room combiner instance. + /// The configuration properties for the room combiner, including default settings and debounce times. public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props) : base(key) { @@ -246,8 +275,16 @@ namespace PepperDash.Essentials.Core #region IEssentialsRoomCombiner Members + /// + /// Occurs when the room combination scenario changes. + /// + /// This event is triggered whenever the configuration or state of the room combination + /// changes. Subscribers can use this event to update their logic or UI based on the new scenario. public event EventHandler RoomCombinationScenarioChanged; + /// + /// Gets the current room combination scenario. + /// public IRoomCombinationScenario CurrentScenario { get @@ -256,10 +293,25 @@ namespace PepperDash.Essentials.Core } } + /// + /// Gets the feedback indicating whether the system is currently in auto mode. + /// public BoolFeedback IsInAutoModeFeedback { get; private set; } + /// + /// Enables auto mode for the room combiner and its partitions, allowing automatic room combination scenarios to + /// be determined. + /// + /// Auto mode allows the room combiner to automatically adjust its configuration based on + /// the state of its partitions. If auto mode is disabled in the configuration, this method logs a warning and + /// does not enable auto mode. public void SetAutoMode() { + if(_propertiesConfig.DisableAutoMode) + { + this.LogWarning("Auto mode is disabled for this room combiner. Cannot set to auto mode."); + return; + } IsInAutoMode = true; foreach (var partition in Partitions) @@ -270,6 +322,12 @@ namespace PepperDash.Essentials.Core DetermineRoomCombinationScenario(); } + /// + /// Switches the system to manual mode, disabling automatic operations. + /// + /// This method sets the system to manual mode by updating the mode state and propagates + /// the change to all partitions. Once in manual mode, automatic operations are disabled for the system and its + /// partitions. public void SetManualMode() { IsInAutoMode = false; @@ -280,6 +338,11 @@ namespace PepperDash.Essentials.Core } } + /// + /// Toggles the current mode between automatic and manual. + /// + /// If the current mode is automatic, this method switches to manual mode. If the + /// current mode is manual, it switches to automatic mode. public void ToggleMode() { if (IsInAutoMode) @@ -292,10 +355,22 @@ namespace PepperDash.Essentials.Core } } + /// + /// Gets the collection of room combination scenarios. + /// public List RoomCombinationScenarios { get; private set; } + /// + /// Gets the collection of partition controllers managed by this instance. + /// public List Partitions { get; private set; } + /// + /// Toggles the state of the partition identified by the specified partition key. + /// + /// If no partition with the specified key exists, the method performs no + /// action. + /// The key of the partition whose state is to be toggled. This value cannot be null or empty. public void TogglePartitionState(string partitionKey) { var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)); @@ -306,6 +381,17 @@ namespace PepperDash.Essentials.Core } } + /// + /// Sets the room combination scenario based on the specified scenario key. + /// + /// This method manually adjusts the partition states according to the specified + /// scenario. If the application is in auto mode, the operation will not proceed, and a log message will be + /// generated indicating that the mode must be set to manual first. If the specified scenario key does not + /// match any existing scenario, a debug log message will be generated. For each partition state in the + /// scenario, the corresponding partition will be updated to either "Present" or "Not Present" based on the + /// scenario's configuration. If a partition key in the scenario cannot be found, a debug log message will be + /// generated. + /// The key identifying the room combination scenario to apply. This must match the key of an existing scenario. public void SetRoomCombinationScenario(string scenarioKey) { if (IsInAutoMode) @@ -354,13 +440,32 @@ namespace PepperDash.Essentials.Core #endregion } + /// + /// Provides a factory for creating instances of devices. + /// + /// This factory is responsible for constructing devices + /// based on the provided configuration. It supports the type name "essentialsroomcombiner" for device + /// creation. public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the class. + /// + /// This factory is used to create instances of room combiners with the specified type + /// names. By default, the factory includes the type name "essentialsroomcombiner". public EssentialsRoomCombinerFactory() { TypeNames = new List { "essentialsroomcombiner" }; } + /// + /// Creates and initializes a new instance of the device. + /// + /// This method uses the provided device configuration to extract the properties and + /// create an device. Ensure that the configuration contains valid + /// properties for the device to be created successfully. + /// The device configuration containing the key and properties required to build the device. + /// A new instance of initialized with the specified configuration. public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) { Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EssentialsRoomCombiner Device"); diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs index 745f303f..cd6f3f17 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs @@ -1,10 +1,4 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; using PepperDash.Core; @@ -17,6 +11,13 @@ namespace PepperDash.Essentials.Core /// public class EssentialsRoomCombinerPropertiesConfig { + /// + /// Gets or sets a value indicating whether the system operates in automatic mode. + /// Some systems don't have partitions sensors, and show shouldn't allow auto mode to be turned on. When this is true in the configuration, + /// auto mode won't be allowed to be turned on. + /// + public bool DisableAutoMode { get; set; } + /// /// The list of partitions that device the rooms /// @@ -47,6 +48,9 @@ namespace PepperDash.Essentials.Core [JsonProperty("defaultScenarioKey")] public string defaultScenarioKey { get; set; } + /// + /// Gets or sets the debounce time, in seconds, for scenario changes. + /// [JsonProperty("scenarioChangeDebounceTimeSeconds")] public int ScenarioChangeDebounceTimeSeconds { get; set; } } @@ -56,9 +60,15 @@ namespace PepperDash.Essentials.Core /// public class PartitionConfig : IKeyName { + /// + /// Gets or sets the unique key associated with the object. + /// [JsonProperty("key")] public string Key { get; set; } + /// + /// Gets or sets the name associated with the object. + /// [JsonProperty("name")] public string Name { get; set; } @@ -80,12 +90,21 @@ namespace PepperDash.Essentials.Core /// public class RoomCombinationScenarioConfig : IKeyName { + /// + /// Gets or sets the key associated with the object. + /// [JsonProperty("key")] public string Key { get; set; } + /// + /// Gets or sets the name associated with the object. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the collection of partition states. + /// [JsonProperty("partitionStates")] public List PartitionStates { get; set; } @@ -95,9 +114,15 @@ namespace PepperDash.Essentials.Core [JsonProperty("uiMap")] public Dictionary UiMap { get; set; } + /// + /// Gets or sets the list of actions to be performed during device activation. + /// [JsonProperty("activationActions")] public List ActivationActions { get; set; } + /// + /// Gets or sets the list of actions to be performed when a device is deactivated. + /// [JsonProperty("deactivationActions")] public List DeactivationActions { get; set; } } @@ -107,9 +132,15 @@ namespace PepperDash.Essentials.Core /// public class PartitionState { + /// + /// Gets or sets the partition key used to group and organize data within a storage system. + /// [JsonProperty("partitionKey")] public string PartitionKey { get; set; } + /// + /// Gets or sets a value indicating whether a partition is currently present. + /// [JsonProperty("partitionSensedState")] public bool PartitionPresent { get; set; } } From c1809459a62f2ef6a8457d0969ffe89ae5896665 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 27 Jun 2025 10:37:49 -0400 Subject: [PATCH 2/3] chore: format property name correctly for JSON --- .../Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs index cd6f3f17..fec7e380 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs @@ -16,6 +16,7 @@ namespace PepperDash.Essentials.Core /// Some systems don't have partitions sensors, and show shouldn't allow auto mode to be turned on. When this is true in the configuration, /// auto mode won't be allowed to be turned on. /// + [JsonProperty("disableAutoMode")] public bool DisableAutoMode { get; set; } /// From 96ac266d24e9dd1102408bc2206d4b3f69280b87 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 27 Jun 2025 10:45:42 -0400 Subject: [PATCH 3/3] fix: room combiner messenger sends disableAutoMode property --- .../Room/Combining/EssentialsRoomCombiner.cs | 11 ++++ .../Room/Combining/IEssentialsRoomCombiner.cs | 21 +++++++ .../IEssentialsRoomCombinerMessenger.cs | 55 +++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index 681f8810..d2a16739 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -62,6 +62,17 @@ namespace PepperDash.Essentials.Core } } + /// + /// Gets a value indicating whether automatic mode is disabled. + /// + public bool DisableAutoMode + { + get + { + return _propertiesConfig.DisableAutoMode; + } + } + private CTimer _scenarioChangeDebounceTimer; private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s diff --git a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs index fefdc2da..04dfd16f 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs @@ -28,9 +28,20 @@ namespace PepperDash.Essentials.Core [JsonIgnore] BoolFeedback IsInAutoModeFeedback {get;} + /// + /// Gets a value indicating whether the automatic mode is disabled. + /// + [JsonProperty("disableAutoMode")] + bool DisableAutoMode { get; } + /// + /// Gets a value indicating whether the system is operating in automatic mode. + /// [JsonProperty("isInAutoMode")] bool IsInAutoMode { get; } + /// + /// Gets the collection of rooms associated with the current object. + /// [JsonProperty("rooms")] List Rooms { get; } @@ -74,6 +85,13 @@ namespace PepperDash.Essentials.Core void SetRoomCombinationScenario(string scenarioKey); } + /// + /// Represents a scenario for combining rooms, including activation, deactivation, and associated state. + /// + /// This interface defines the behavior for managing room combination scenarios, including + /// activation and deactivation, tracking the active state, and managing related partition states and UI mappings. + /// Implementations of this interface are expected to handle the logic for room combinations based on the provided + /// partition states and UI mappings. public interface IRoomCombinationScenario : IKeyName { /// @@ -82,6 +100,9 @@ namespace PepperDash.Essentials.Core [JsonIgnore] BoolFeedback IsActiveFeedback { get; } + /// + /// Gets a value indicating whether the entity is active. + /// [JsonProperty("isActive")] bool IsActive { get; } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs index a29d7b9e..1752b567 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs @@ -8,16 +8,42 @@ using System.Collections.Generic; namespace PepperDash.Essentials.AppServer.Messengers { + /// + /// Provides messaging functionality for managing room combination scenarios and partition states in an instance. Enables external systems to interact with the room combiner via + /// predefined actions and status updates. + /// + /// This class facilitates communication with an by + /// exposing actions for toggling modes, managing partitions, and setting room combination scenarios. It also + /// listens for feedback changes and broadcasts status updates to connected systems. Typical usage involves + /// registering actions for external commands and handling feedback events to synchronize state changes. public class IEssentialsRoomCombinerMessenger : MessengerBase { private readonly IEssentialsRoomCombiner _roomCombiner; + /// + /// Initializes a new instance of the class, which facilitates + /// messaging for an instance. + /// + /// This class is designed to enable communication and interaction with an through the specified messaging path. Ensure that the parameter is not null when creating an instance. + /// The unique key identifying this messenger instance. + /// The path used for messaging operations. + /// The instance associated with this messenger. public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner) : base(key, messagePath, roomCombiner as IKeyName) { _roomCombiner = roomCombiner; } + /// + /// Registers actions and event handlers for managing room combination scenarios and partition states. + /// + /// This method sets up various actions that can be triggered via specific endpoints, + /// such as toggling modes, setting room combination scenarios, and managing partition states. It also + /// subscribes to feedback events to update the status when changes occur in room combination scenarios or + /// partition states. protected override void RegisterActions() { AddAction("/fullStatus", (id, content) => SendFullStatus()); @@ -107,6 +133,7 @@ namespace PepperDash.Essentials.AppServer.Messengers var message = new IEssentialsRoomCombinerStateMessage { + DisableAutoMode = _roomCombiner.DisableAutoMode, IsInAutoMode = _roomCombiner.IsInAutoMode, CurrentScenario = _roomCombiner.CurrentScenario, Rooms = rooms, @@ -132,20 +159,48 @@ namespace PepperDash.Essentials.AppServer.Messengers } } + /// + /// Represents the state message for a room combiner system, providing information about the current configuration, + /// operational mode, and associated rooms, partitions, and scenarios. + /// + /// This class is used to encapsulate the state of a room combiner system, including its current + /// mode of operation, active room combination scenario, and the list of rooms and partitions involved. It is + /// typically serialized and transmitted to communicate the state of the system. public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase { + /// + /// Gets or sets a value indicating whether automatic mode is disabled. + /// + [JsonProperty("disableAutoMode", NullValueHandling = NullValueHandling.Ignore)] + public bool DisableAutoMode { get; set; } + + /// + /// Gets or sets a value indicating whether the system is operating in automatic mode. + /// [JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)] public bool IsInAutoMode { get; set; } + /// + /// Gets or sets the current room combination scenario. + /// [JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)] public IRoomCombinationScenario CurrentScenario { get; set; } + /// + /// Gets or sets the collection of rooms associated with the entity. + /// [JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)] public List Rooms { get; set; } + /// + /// Gets or sets the collection of room combination scenarios. + /// [JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)] public List RoomCombinationScenarios { get; set; } + /// + /// Gets or sets the collection of partition controllers. + /// [JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)] public List Partitions { get; set; } }