mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-08-31 19:08:29 +00:00
feat: add optional room combiner operation status lifecycle
This commit is contained in:
parent
f85343d8fd
commit
e623865c2a
3 changed files with 176 additions and 7 deletions
|
|
@ -17,7 +17,7 @@ namespace PepperDash.Essentials.Core
|
||||||
/// combinations based on partition states and predefined scenarios. It supports both automatic and manual modes
|
/// 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
|
/// 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.</remarks>
|
/// based on partition sensor states. In manual mode, scenarios can be set explicitly by the user.</remarks>
|
||||||
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
|
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombinerWithOperationStatus
|
||||||
{
|
{
|
||||||
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
|
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
|
||||||
|
|
||||||
|
|
@ -79,6 +79,13 @@ namespace PepperDash.Essentials.Core
|
||||||
|
|
||||||
private Mutex _scenarioChange = new Mutex();
|
private Mutex _scenarioChange = new Mutex();
|
||||||
|
|
||||||
|
private readonly object _combinationOperationLock = new object();
|
||||||
|
|
||||||
|
private CombinationOperationStatus _combinationOperation = new CombinationOperationStatus
|
||||||
|
{
|
||||||
|
State = CombinationOperationState.Idle
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="EssentialsRoomCombiner"/> class, which manages room combination
|
/// Initializes a new instance of the <see cref="EssentialsRoomCombiner"/> class, which manages room combination
|
||||||
/// scenarios and partition states.
|
/// scenarios and partition states.
|
||||||
|
|
@ -256,13 +263,19 @@ namespace PepperDash.Essentials.Core
|
||||||
|
|
||||||
private async Task ChangeScenario(IRoomCombinationScenario newScenario)
|
private async Task ChangeScenario(IRoomCombinationScenario newScenario)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (newScenario == _currentScenario)
|
if (newScenario == _currentScenario)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetCombinationOperationStatus(
|
||||||
|
CombinationOperationState.InProgress,
|
||||||
|
newScenario != null ? newScenario.Key : null,
|
||||||
|
null,
|
||||||
|
true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
// Deactivate the old scenario first
|
// Deactivate the old scenario first
|
||||||
if (_currentScenario != null)
|
if (_currentScenario != null)
|
||||||
{
|
{
|
||||||
|
|
@ -281,7 +294,22 @@ namespace PepperDash.Essentials.Core
|
||||||
|
|
||||||
RoomCombinationScenarioChanged?.Invoke(this, new EventArgs());
|
RoomCombinationScenarioChanged?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
|
SetCombinationOperationStatus(
|
||||||
|
CombinationOperationState.Completed,
|
||||||
|
_currentScenario != null ? _currentScenario.Key : null,
|
||||||
|
null,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.LogException(ex, "Error changing room combination scenario");
|
||||||
|
|
||||||
|
SetCombinationOperationStatus(
|
||||||
|
CombinationOperationState.Failed,
|
||||||
|
newScenario != null ? newScenario.Key : null,
|
||||||
|
"Combination operation failed",
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IEssentialsRoomCombiner Members
|
#region IEssentialsRoomCombiner Members
|
||||||
|
|
@ -293,6 +321,11 @@ namespace PepperDash.Essentials.Core
|
||||||
/// changes. Subscribers can use this event to update their logic or UI based on the new scenario.</remarks>
|
/// changes. Subscribers can use this event to update their logic or UI based on the new scenario.</remarks>
|
||||||
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the room combination operation status changes.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<EventArgs> CombinationOperationStatusChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current room combination scenario.
|
/// Gets the current room combination scenario.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -304,6 +337,20 @@ namespace PepperDash.Essentials.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current room combination operation status.
|
||||||
|
/// </summary>
|
||||||
|
public CombinationOperationStatus CombinationOperation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_combinationOperationLock)
|
||||||
|
{
|
||||||
|
return CloneCombinationOperationStatus(_combinationOperation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the IsInAutoModeFeedback
|
/// Gets or sets the IsInAutoModeFeedback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -455,6 +502,53 @@ namespace PepperDash.Essentials.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void SetCombinationOperationStatus(
|
||||||
|
CombinationOperationState state,
|
||||||
|
string scenarioKey,
|
||||||
|
string message,
|
||||||
|
bool resetStartedUtc)
|
||||||
|
{
|
||||||
|
lock (_combinationOperationLock)
|
||||||
|
{
|
||||||
|
if (resetStartedUtc)
|
||||||
|
{
|
||||||
|
_combinationOperation = new CombinationOperationStatus
|
||||||
|
{
|
||||||
|
OperationId = Guid.NewGuid().ToString(),
|
||||||
|
ScenarioKey = scenarioKey,
|
||||||
|
StartedUtc = DateTime.UtcNow.ToString("o"),
|
||||||
|
State = state,
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_combinationOperation.ScenarioKey = scenarioKey ?? _combinationOperation.ScenarioKey;
|
||||||
|
_combinationOperation.State = state;
|
||||||
|
_combinationOperation.Message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CombinationOperationStatusChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CombinationOperationStatus CloneCombinationOperationStatus(CombinationOperationStatus status)
|
||||||
|
{
|
||||||
|
if (status == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CombinationOperationStatus
|
||||||
|
{
|
||||||
|
OperationId = status.OperationId,
|
||||||
|
ScenarioKey = status.ScenarioKey,
|
||||||
|
StartedUtc = status.StartedUtc,
|
||||||
|
State = status.State,
|
||||||
|
Message = status.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,14 @@ namespace PepperDash.Essentials.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current room combination scenario
|
/// The current room combination scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("currentScenario")]
|
[JsonProperty("currentScenario")]
|
||||||
IRoomCombinationScenario CurrentScenario { get; }
|
IRoomCombinationScenario CurrentScenario { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When true, indicates the current mode is auto mode
|
/// When true, indicates the current mode is auto mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -85,6 +87,56 @@ namespace PepperDash.Essentials.Core
|
||||||
void SetRoomCombinationScenario(string scenarioKey);
|
void SetRoomCombinationScenario(string scenarioKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional extension for room combiners that provide operation lifecycle status.
|
||||||
|
/// </summary>
|
||||||
|
public interface IEssentialsRoomCombinerWithOperationStatus : IEssentialsRoomCombiner
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the room combination operation status has changed.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler<EventArgs> CombinationOperationStatusChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current room combination operation status.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("combinationOperation")]
|
||||||
|
CombinationOperationStatus CombinationOperation { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines lifecycle states for a room combination operation.
|
||||||
|
/// </summary>
|
||||||
|
public enum CombinationOperationState
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
InProgress,
|
||||||
|
Completed,
|
||||||
|
Failed,
|
||||||
|
TimedOut
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents room combination operation status details.
|
||||||
|
/// </summary>
|
||||||
|
public class CombinationOperationStatus
|
||||||
|
{
|
||||||
|
[JsonProperty("operationId", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string OperationId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scenarioKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string ScenarioKey { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("startedUtc", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string StartedUtc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("state")]
|
||||||
|
public CombinationOperationState State { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a scenario for combining rooms, including activation, deactivation, and associated state.
|
/// Represents a scenario for combining rooms, including activation, deactivation, and associated state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
private readonly IEssentialsRoomCombiner _roomCombiner;
|
private readonly IEssentialsRoomCombiner _roomCombiner;
|
||||||
|
|
||||||
|
private readonly IEssentialsRoomCombinerWithOperationStatus _roomCombinerWithOperationStatus;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="IEssentialsRoomCombinerMessenger"/> class, which facilitates
|
/// Initializes a new instance of the <see cref="IEssentialsRoomCombinerMessenger"/> class, which facilitates
|
||||||
/// messaging for an <see cref="IEssentialsRoomCombiner"/> instance.
|
/// messaging for an <see cref="IEssentialsRoomCombiner"/> instance.
|
||||||
|
|
@ -35,6 +37,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
: base(key, messagePath, roomCombiner as IKeyName)
|
: base(key, messagePath, roomCombiner as IKeyName)
|
||||||
{
|
{
|
||||||
_roomCombiner = roomCombiner;
|
_roomCombiner = roomCombiner;
|
||||||
|
_roomCombinerWithOperationStatus = roomCombiner as IEssentialsRoomCombinerWithOperationStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -98,6 +101,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
SendFullStatus();
|
SendFullStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (_roomCombinerWithOperationStatus != null)
|
||||||
|
{
|
||||||
|
_roomCombinerWithOperationStatus.CombinationOperationStatusChanged += (sender, args) =>
|
||||||
|
{
|
||||||
|
var message = new
|
||||||
|
{
|
||||||
|
combinationOperation = _roomCombinerWithOperationStatus.CombinationOperation
|
||||||
|
};
|
||||||
|
|
||||||
|
PostStatusMessage(JToken.FromObject(message));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
_roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) =>
|
_roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) =>
|
||||||
{
|
{
|
||||||
var message = new
|
var message = new
|
||||||
|
|
@ -138,6 +154,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
DisableAutoMode = _roomCombiner.DisableAutoMode,
|
DisableAutoMode = _roomCombiner.DisableAutoMode,
|
||||||
IsInAutoMode = _roomCombiner.IsInAutoMode,
|
IsInAutoMode = _roomCombiner.IsInAutoMode,
|
||||||
CurrentScenario = _roomCombiner.CurrentScenario,
|
CurrentScenario = _roomCombiner.CurrentScenario,
|
||||||
|
CombinationOperation = _roomCombinerWithOperationStatus != null ? _roomCombinerWithOperationStatus.CombinationOperation : null,
|
||||||
Rooms = rooms,
|
Rooms = rooms,
|
||||||
RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios,
|
RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios,
|
||||||
Partitions = _roomCombiner.Partitions
|
Partitions = _roomCombiner.Partitions
|
||||||
|
|
@ -194,6 +211,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public IRoomCombinationScenario CurrentScenario { get; set; }
|
public IRoomCombinationScenario CurrentScenario { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the room combination operation status.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("combinationOperation", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public CombinationOperationStatus CombinationOperation { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the collection of rooms associated with the entity.
|
/// Gets or sets the collection of rooms associated with the entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue