Compare commits

..

5 Commits

5 changed files with 164 additions and 83 deletions

View File

@@ -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
}
}

View File

@@ -1,4 +1,11 @@
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Core;

View File

@@ -1,16 +0,0 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Interface for rooms with a list of destinations
/// </summary>
public interface IHasDestinations
{
/// <summary>
/// Gets the dictionary of destinations.
/// </summary>
Dictionary<string, IRoutingSink> Destinations { get; }
}
}

View File

@@ -1,15 +0,0 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Interface for rooms with a list of destinations
/// </summary>
public interface IHasSourceList
{
/// <summary>
/// Gets the list of sources.
/// </summary>
Dictionary<string, SourceListItem> SourceList { get; }
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Routing
@@ -123,16 +121,20 @@ namespace PepperDash.Essentials.Core.Routing
RoutingInputPort inputPort
)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"Updating destination {destination} with inputPort {inputPort}",
this,
destination?.Key,
inputPort?.Key
);
if (inputPort == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"Destination {destination} has not reported an input port yet",
this,
destination.Key
);
return;
@@ -150,8 +152,10 @@ namespace PepperDash.Essentials.Core.Routing
if (firstTieLine == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"No tieline found for inputPort {inputPort}. Clearing current source",
this,
inputPort
);
@@ -162,14 +166,14 @@ namespace PepperDash.Essentials.Core.Routing
};
destination.CurrentSourceInfo = tempSourceListItem;
;
destination.CurrentSourceInfoKey = "$transient";
return;
}
}
catch (Exception ex)
{
this.LogException(ex, "Error getting first tieline: {Exception}", ex.Message);
Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex);
return;
}
@@ -182,7 +186,8 @@ namespace PepperDash.Essentials.Core.Routing
if (sourceTieLine == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"No route found to source for inputPort {inputPort}. Clearing current source",
this,
inputPort
@@ -201,7 +206,7 @@ namespace PepperDash.Essentials.Core.Routing
}
catch (Exception ex)
{
this.LogException(ex, "Error getting sourceTieLine: {Exception}", ex.Message);
Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex);
return;
}
@@ -225,71 +230,47 @@ namespace PepperDash.Essentials.Core.Routing
return roomDefaultDisplay.DefaultDisplay.Key == destination.Key;
}
if (r is IHasDestinations roomDestinationList)
{
return roomDestinationList.Destinations.Any(d =>
d.Value.Key == destination.Key
);
}
var destList = ConfigReader.ConfigObject.GetDestinationListForKey(r.DestinationListKey);
return false;
}
);
if (room == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"No room found for display {destination}",
this,
destination.Key
);
return;
}
this.LogVerbose("Found room {room} for destination {destination}", room.Key, destination.Key);
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key);
Dictionary<string, SourceListItem> sourceList = null;
if (room is IHasSourceList roomWithSourceList)
{
sourceList = roomWithSourceList.SourceList;
}
else
{
sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
}
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
if (sourceList == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}",
this,
room.SourceListKey,
sourceTieLine
);
return;
}
this.LogVerbose("Found sourceList for room {room}", room.Key);
if (sourceTieLine.SourcePort?.ParentDevice == null)
{
this.LogDebug(
"********SourcePort or ParentDevice is null for tieLine. Unable to find source for destination {destination}.",
destination.Key
);
return;
}
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key);
var sourceListItem = sourceList.FirstOrDefault(sli =>
{
if (sli.Value == null) return false;
this.LogVerbose(
"********SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
sli.Key,
sli.Value.SourceKey,
sourceTieLine.SourcePort.ParentDevice.Key);
//// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose,
// "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
// this,
// sli.Key,
// sli.Value.SourceKey,
// sourceTieLine.SourcePort.ParentDevice.Key);
return sli.Value.SourceKey.Equals(
sourceTieLine.SourcePort.ParentDevice.Key,
@@ -302,10 +283,12 @@ namespace PepperDash.Essentials.Core.Routing
if (source == null)
{
this.LogDebug(
Debug.LogMessage(
Serilog.Events.LogEventLevel.Debug,
"No source found for device {key}. Creating transient source for {destination}",
this,
sourceTieLine.SourcePort.ParentDevice.Key,
destination.Key
destination
);
var tempSourceListItem = new SourceListItem
@@ -319,7 +302,7 @@ namespace PepperDash.Essentials.Core.Routing
return;
}
this.LogVerbose("Got Source {@source} with key {sourceKey}", source, sourceKey);
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {@source} with key {sourceKey}", this, source, sourceKey);
destination.CurrentSourceInfoKey = sourceKey;
destination.CurrentSourceInfo = source;