Files
DP44/DataPRO/ICommand/Classes/DiscoveredDevice.cs

239 lines
8.9 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00

using DTS.Common.Interface.DASFactory;
using System;
using System.Collections.Generic;
using System.Linq;
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
namespace DTS.DASLib.Command.Classes
{
/// <summary>
/// DiscoveredDevice class is used by the multicast autodiscovery mechanism to describe response payload from devices
/// </summary>
public class DiscoveredDevice : IDiscoveredDevice, IComparable<DiscoveredDevice>
{
//Addresses are strings so SortableBindingList can be used unmodified
#region UDP payload properties
/// <summary>
/// Device Serial Number
/// </summary>
public string Serial { get; set; }
/// <summary>
/// Device type
/// </summary>
public MultiCastDeviceClasses DevClass { get; set; }
/// <summary>
/// Device Mac
/// </summary>
public string Mac { get; set; }
public IDiscoveredDevice Parent { get; set; }
public bool IsParent(IDiscoveredDevice possibleChild)
{
if (null == Connections)
{
return false;
}
var matches = from connection in Connections where connection.MACAddress == possibleChild.Mac select connection;
var connectedEthernetDevices = matches as ConnectedEthernetDevice[] ?? matches.ToArray();
if (!connectedEthernetDevices.Any()) { return false; }
//if it matches it's our DIRECT uplink/parent if it contains all of our children and no other children ON THIS PORT.
var port = connectedEthernetDevices[0].Port;
var childrenOnPort = from connection in Connections where connection.Port == port select connection;
return childrenOnPort.Count() == 1 + possibleChild.Connections.Length;
}
public int GetPort(IDiscoveredDevice device)
{
var matches = from connection in Connections where connection.MACAddress == device.Mac select connection;
var connectedEthernetDevices = matches as ConnectedEthernetDevice[] ?? matches.ToArray();
if (!connectedEthernetDevices.Any()) { return -1; }
return connectedEthernetDevices[0].Port;
}
private List<IDiscoveredDevice> _orderedList = null;
public int GetSlot(IDiscoveredDevice child, Dictionary<string, IDiscoveredDevice> lookup)
{
if (null == _orderedList)
{
_orderedList = new List<IDiscoveredDevice>();
foreach (var macAddress in Connections.Select(x => x.MACAddress))
{
if (!lookup.ContainsKey(macAddress)) continue;
var device = lookup[macAddress];
if (null == device) continue;
_orderedList.Add(device);
_orderedList.Sort(new DiscoveredChildrenSorter());
}
}
var slot = _orderedList.IndexOf(child);
return slot <= 0 ? 1 : 1 + slot;
}
public int GetSlotOnPort(IDiscoveredDevice child, Dictionary<string, IDiscoveredDevice> lookup)
{
var matches = from device in _orderedList where device.Port == child.Port select device;
var slotOnPort = matches.ToList().IndexOf(child);
return slotOnPort <= 0 ? 1 : 1 + slotOnPort;
}
/// <summary>
/// so what we want here is first alphabetic by ultimate parent, then
/// by slot within each parent
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo(DiscoveredDevice other)
{
var myUltimateParent = GetParent(this);
var otherUltimateParent = GetParent(other);
if (null == myUltimateParent && null == otherUltimateParent)
{
//both SLICE6dbs or both without a chain...
return String.Compare(Serial, other.Serial, StringComparison.Ordinal);
}
if (null == myUltimateParent)
{
if (otherUltimateParent == this)
{
return -1;
}
return string.Compare(Serial, otherUltimateParent.Serial, StringComparison.Ordinal);
}
if (null == otherUltimateParent)
{
if (myUltimateParent == other)
{
return 1;
}
return string.Compare(myUltimateParent.Serial, other.Serial, StringComparison.Ordinal);
}
//we both have parents, if they aren't the same, then use their serial numbers
if (myUltimateParent != otherUltimateParent)
{
return string.Compare(myUltimateParent.Serial, otherUltimateParent.Serial, StringComparison.Ordinal);
}
//same parent, first compare port
if (Port != other.Port) { return Port.CompareTo(other.Port); }
//on same port, then use slot
return PositionOnDistributor.CompareTo(other.PositionOnDistributor);
}
public static IDiscoveredDevice GetParent(IDiscoveredDevice device)
{
var target = device;
while (null != target.Parent) { target = target.Parent; }
return target != device ? target : null;
}
public class DiscoveredChildrenSorter : IComparer<IDiscoveredDevice>
{
int IComparer<IDiscoveredDevice>.Compare(IDiscoveredDevice x, IDiscoveredDevice y)
{
if (x == y) { return 0; }
if (null == x) { return -1; }
if (null == y) { return 1; }
return x.Port != y.Port ? x.Port.CompareTo(y.Port) : y.Connections.Length.CompareTo(x.Connections.Length);
}
}
public bool IsModule { get; set; }
/// <summary>
/// if I'm on a SLICE6DB, what port am I on
/// </summary>
public int Port { get; set; }
/// <summary>
/// starting at the first device in the chain on the first point, up until the last device on the last chain/port, where is this device
/// this is used to as we don't show SLICE6 devices when on a SLICE6Db, but we still need to know which devices is where for showing
/// the channels in the UI
/// </summary>
public int PositionOnDistributor { get; set; }
/// <summary>
/// where is this device in a chain of devices, only used for SLICE6 on a SLICE6Db right now
/// </summary>
public int PositionOnChain { get; set; }
/// <summary>
/// Is DHCP enabled
/// </summary>
public bool Dhcp { get; set; }
/// <summary>
/// Device IP
/// </summary>
public string Ip { get; set; }
/// <summary>
/// Device Subnet
/// </summary>
public string Subnet { get; set; }
/// <summary>
/// Device Gateway
/// </summary>
public string Gateway { get; set; }
/// <summary>
/// Device DNS Sever
/// </summary>
public string Dns { get; set; }
/// <summary>
/// Is Device connected to another host
/// </summary>
public bool Connected { get; set; }
/// <summary>
/// Host IP that device is connected to
/// </summary>
public string ConnectedIp { get; set; }
/// <summary>
/// Host Name Resolution that device is connected to
/// </summary>
public string ConnectedHost { get; set; }
/// <summary>
/// User entry for Distributor ID that device is connected to
/// </summary>
public ushort SystemId { get; set; }
/// <summary>
/// User entry for location of device
/// </summary>
public string Location { get; set; }
/// <summary>
/// Firmware version string
/// [Product Name]-[FW/BL]-[REL/DBG]-[Board #]-[FW Ver Name]
/// </summary>
public string FirmwareVersion { get; set; }
/// <summary>
/// Build Server number for the firmware
/// </summary>
public string BuildId { get; set; }
#endregion
public IConnectedEthernetDevice[] Connections { get; set; }
public DiscoveredDevice()
{
Connections = new IConnectedEthernetDevice[0];
}
}
public class ConnectedEthernetDevice : IConnectedEthernetDevice
{
public string MACAddress { get; }
public int Port { get; }
public ConnectedEthernetDevice(string macAddress, int port) { MACAddress = macAddress; Port = port; }
public string SerialNumber { get; set; }
}
}