Skip to content
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8817d70
feat: add interfaces for VLAN and PoE management in network switches
ndorin Mar 20, 2026
76311b8
feat: add event and arguments for port state changes in network switc…
ndorin Mar 20, 2026
6db7581
feat: add Unknown event type to NetworkSwitchPortEventType enum for i…
ndorin Mar 20, 2026
84c730b
feat: enhance NetworkSwitchPortEventType enum with additional states …
ndorin Mar 20, 2026
1b10910
fix: update GetFeedbacksForDeviceRequestHandler to return JSON respon…
ndorin Apr 1, 2026
d0ab42c
Merge branch 'feature/add-network-switch-poe-interfaces' into feature…
ndorin Apr 1, 2026
2121734
Merge branch 'main' into feature/web-api-updates
erikdred May 19, 2026
94c9e75
Merge branch 'main' into feature/web-api-updates
ngenovese11 May 21, 2026
6587444
fix: update routing logic and enhance logging in Extensions and MockV…
ndorin May 21, 2026
92d13f2
fix: refine routing logic by filtering IRoutingInputs and IRoutingOut…
ndorin May 21, 2026
74a12c9
fix: add null or empty checks for midpoint keys in RoutingFeedbackMan…
ndorin May 22, 2026
b32bab0
fix: remove impossibleRoutes cache
andrew-welker Jun 9, 2026
162a06f
feat: adds interface for wireless sharing
aknous Jun 11, 2026
d18fca8
fix: handle null properties in DeviceMessageBase and DeviceStateMessa…
ndorin Jun 10, 2026
6a4e3d5
feat: add port forwarding functionality for debug websocket in DebugS…
jkdevito Jun 12, 2026
6f2231a
Potential fix for pull request finding
ndorin Jun 12, 2026
e4cd361
fix: add csIp handling and update debug session URL in DebugSessionRe…
ndorin Jun 12, 2026
7ff4f29
fix: improve CS LAN IP handling and update fallback debug session URL…
ndorin Jun 12, 2026
ee971c4
fix: add port forward timeout handling in DebugSessionRequestHandler
ndorin Jun 12, 2026
0896327
Initial plan
Claude Jun 26, 2026
8a9c8b5
Mark IMobileControlMessengerWithSubscriptions and EnableMessengerSubs…
Claude Jun 26, 2026
493cd91
Potential fix for pull request finding
ndorin Jun 26, 2026
13a4f81
Update XML summary for EnableMessengerSubscriptions to reflect obsole…
Copilot Jun 26, 2026
9eacc50
Clarify summary for EnableMessengerSubscriptions property
ndorin Jun 26, 2026
fb424ed
refactor: marked mobile control subscription items as obsolete
Claude Jun 26, 2026
f85343d
fix: string formatting for console responses was incorrect in some ca…
andrew-welker Jul 2, 2026
e623865
feat: add optional room combiner operation status lifecycle
equinoy Jul 7, 2026
8e9dbb6
feat: add optional room combiner operation timeout setting
equinoy Jul 7, 2026
b499097
feat: gate combiner completion on provider reconciliation
equinoy Jul 7, 2026
707195b
fix: guard PartitionPresent getter against null sensor feedback
equinoy Jul 15, 2026
ae01c59
docs(readme): document room combiner operation lifecycle and combinat…
equinoy Jul 15, 2026
a638ffa
Potential fix for pull request finding
equinoy Jul 15, 2026
1ffa010
Potential fix for pull request finding
equinoy Jul 15, 2026
40693f8
Potential fix for pull request finding
equinoy Jul 15, 2026
2d453ba
Potential fix for pull request finding
equinoy Jul 15, 2026
c771817
Potential fix for pull request finding
equinoy Jul 15, 2026
a4f6c10
fix: potential fix for pull request finding
equinoy Jul 15, 2026
58c7f9b
Merge branch 'feature/room-combination-change-in-progress-lockout' of…
equinoy Jul 15, 2026
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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,38 @@ Utilization of Essentials Framework falls into the following categories:

For detailed documentation, see the [Wiki](https://github.com/PepperDash/EssentialsFramework/wiki).

## Room Combiner Operation Lifecycle

Essentials room combiner now exposes an operation lifecycle that clients can use to show progress and terminal status during scenario changes.

Lifecycle states:
- Idle
- InProgress
- Completed
- Failed
- TimedOut

The lifecycle is exposed on room combiners that implement the operation-status extension and is included in app server combiner messages under the combinationOperation payload.

Configuration:
- combinationOperationTimeoutSeconds (optional): timeout in seconds for an in-progress operation.
- Default when omitted: 300 seconds.
- Values less than or equal to 0 are treated as invalid and fall back to the default.

Example room combiner properties:

```json
{
"defaultToManualMode": false,
"defaultScenarioKey": "divided",
"combinationOperationTimeoutSeconds": 30,
"roomKeys": ["roomA", "roomB"]
}
```

Operational note:
- When an operation reaches a terminal state (Completed, Failed, TimedOut), the operation timeout timer is stopped.

## Support

* Check out our [Discord Server](https://discord.gg/rWyeRH3K)
Expand Down
16 changes: 16 additions & 0 deletions src/PepperDash.Core/Logging/DebugWebsocketSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ public string Url
/// </summary>
public bool IsRunning { get => _httpsServer?.IsListening ?? false; }

/// <summary>
/// Gets a value indicating whether there are active WebSocket connections.
/// </summary>
public bool HasActiveConnections
{
get
{
if (_httpsServer == null || !_httpsServer.IsListening) return false;
var service = _httpsServer.WebSocketServices[_path];
if (service == null) return false;
return service.Sessions.Count > 0;
}
}


private readonly ITextFormatter _textFormatter;

Expand Down Expand Up @@ -217,6 +231,8 @@ public void StartServerAndSetPort(int port)
{
Debug.LogInformation("Starting Websocket Server on port: {0}", port);




Start(port, CertPath, _certificatePassword);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;

Comment thread
Copilot marked this conversation as resolved.
Outdated
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
/// <summary>
/// Defines the contract for a wireless presentation endpoint that reports whether a wireless
/// sharing session is currently active. Implemented by platforms such as Crestron AirMedia,
/// Mersive Solstice, Barco ClickShare, Miracast/Teams receivers, etc. Allows consumers (e.g.
/// room plugins) to react to wireless sharing activity without taking a dependency on any
/// concrete device implementation.
/// </summary>
/// <remarks>
/// This refers specifically to wireless screen/device mirroring, as distinct from in-call
/// content sharing on a video conference.
/// </remarks>
public interface IHasWirelessSharing
{
/// <summary>
/// Reports whether a wireless sharing session is currently active (content is being presented).
/// </summary>
BoolFeedback IsSharingFeedback { get; }

/// <summary>
/// Raised when wireless sharing starts or stops. The event args carry the new sharing state.
/// </summary>
event EventHandler<WirelessSharingEventArgs> SharingChanged;
}

/// <summary>
/// Event arguments describing a change in wireless sharing state.
/// </summary>
public class WirelessSharingEventArgs : EventArgs
{
/// <summary>
/// True if a wireless sharing session is active (content is being presented), false otherwise.
/// </summary>
public bool IsSharing { get; private set; }

/// <summary>
/// Creates a new <see cref="WirelessSharingEventArgs"/>.
/// </summary>
/// <param name="isSharing">True if a wireless sharing session is active, false otherwise.</param>
public WirelessSharingEventArgs(bool isSharing)
{
IsSharing = isSharing;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using PepperDash.Core;

namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
/// <summary>
/// Defines the contract for IMobileControlMessenger
/// Obsolete: messengers are subscription based by default; use IMobileControlMessenger instead.
/// </summary>
[Obsolete("This interface is obsolete and will be removed in a future version. All messengers are now subscription based.")]
public interface IMobileControlMessengerWithSubscriptions : IMobileControlMessenger
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System;

namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
/// <summary>
/// Interface for network switches that support VLAN assignment on individual ports.
/// </summary>
public interface INetworkSwitchVlanManager
{
/// <summary>
/// Returns the current access VLAN ID configured on the port.
/// Return -1 when the value is unavailable (e.g. the switch has not been polled yet
/// or the implementation does not support VLAN queries).
/// </summary>
/// <param name="port">Switch port identifier</param>
/// <returns>VLAN ID or -1 when unavailable</returns>
int GetPortCurrentVlan(string port);

/// <summary>
/// Changes the access VLAN of a single switch port.
/// The implementation is responsible for entering/exiting privileged/config mode.
/// </summary>
/// <param name="port">Switch port identifier (e.g. "1/0/3" for Netgear, "gi1/0/3" for Cisco)</param>
/// <param name="vlanId">Target VLAN ID (1-4093)</param>
void SetPortVlan(string port, uint vlanId);
}

/// <summary>
/// Interface for network switches that support Power over Ethernet (PoE) control on individual ports.
/// </summary>
public interface INetworkSwitchPoeManager
{
/// <summary>
/// Enables or disables PoE power delivery on a single switch port.
/// The implementation is responsible for entering/exiting privileged/config mode.
/// </summary>
/// <param name="port">Switch port identifier</param>
/// <param name="enabled">True to enable PoE; false to disable PoE</param>
void SetPortPoeState(string port, bool enabled);
}

/// <summary>
/// Standardized interface for network switch devices that support per-port PoE control
/// and VLAN assignment.
/// </summary>
public interface INetworkSwitchPoeVlanManager : INetworkSwitchVlanManager, INetworkSwitchPoeManager
{
/// <summary>
/// Event that is raised when the state of a switch port changes, such as a VLAN change or PoE state change.
/// </summary>
event EventHandler<NetworkSwitchPortEventArgs> PortStateChanged;

}

/// <summary>
/// Event arguments for port state changes on a network switch, such as VLAN changes or PoE state changes.
/// </summary>
public class NetworkSwitchPortEventArgs : EventArgs
{
/// <summary>
/// The identifier of the port that changed state (e.g. "1/0/3" for Netgear, "gi1/0/3" for Cisco).
/// </summary>
public string Port { get; private set; }

/// <summary>
/// The type of event that occurred on the port (e.g. VLAN change, PoE enabled/disabled).
/// </summary>
public NetworkSwitchPortEventType EventType { get; private set; }

/// <summary>
/// Constructor for NetworkSwitchPortEventArgs
/// </summary>
/// <param name="port">The identifier of the port that changed state</param>
/// <param name="eventType">The type of event that occurred on the port</param>
public NetworkSwitchPortEventArgs(string port, NetworkSwitchPortEventType eventType)
{
Port = port;
EventType = eventType;
}
}

/// <summary>
/// Event arguments for port state changes on a network switch, such as VLAN changes or PoE state changes.
/// </summary>
public enum NetworkSwitchPortEventType
{
/// <summary>
/// Indicates that the type of event is unknown or cannot be determined.
/// </summary>
Unknown,

/// <summary>
/// Indicates that a VLAN change is in progress on the port, either through a call to SetPortVlan or an external change detected by polling.
/// </summary>
VlanChangeInProgress,

/// <summary>
/// Indicates that the access VLAN on a port has changed, either through a successful call to SetPortVlan
/// </summary>
VlanChanged,

/// <summary>
/// Indicates that PoE is being disabled on the port, either through a call to SetPortPoeState or an external change detected by polling.
/// </summary>
PoeDisableInProgress,

/// <summary>
/// Indicates that the PoE state on a port has changed, either through a successful call to SetPortPoeState
/// </summary>
PoEDisabled,

/// <summary>
/// Indicates that PoE is being enabled on the port, either through a call to SetPortPoeState or an external change detected by polling.
/// </summary>
PoeEnableInProgress,

/// <summary>
/// Indicates that the PoE state on a port has changed, either through a successful call to SetPortPoeState
/// </summary>
PoEEnabled
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public bool PartitionPresent
{
if (IsInAutoMode)
{
return _partitionSensor.PartitionPresentFeedback.BoolValue;
return _partitionSensor?.PartitionPresentFeedback?.BoolValue ?? _partitionPresent;
}

return _partitionPresent;
Expand Down
Loading