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 { /// /// DiscoveredDevice class is used by the multicast autodiscovery mechanism to describe response payload from devices /// public class DiscoveredDevice : IDiscoveredDevice, IComparable { //Addresses are strings so SortableBindingList can be used unmodified #region UDP payload properties /// /// Device Serial Number /// public string Serial { get; set; } /// /// Device type /// public MultiCastDeviceClasses DevClass { get; set; } /// /// Device Mac /// 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 _orderedList = null; public int GetSlot(IDiscoveredDevice child, Dictionary lookup) { if (null == _orderedList) { _orderedList = new List(); 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 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; } /// /// so what we want here is first alphabetic by ultimate parent, then /// by slot within each parent /// /// /// 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 { int IComparer.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; } /// /// if I'm on a SLICE6DB, what port am I on /// public int Port { get; set; } /// /// 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 /// public int PositionOnDistributor { get; set; } /// /// where is this device in a chain of devices, only used for SLICE6 on a SLICE6Db right now /// public int PositionOnChain { get; set; } /// /// Is DHCP enabled /// public bool Dhcp { get; set; } /// /// Device IP /// public string Ip { get; set; } /// /// Device Subnet /// public string Subnet { get; set; } /// /// Device Gateway /// public string Gateway { get; set; } /// /// Device DNS Sever /// public string Dns { get; set; } /// /// Is Device connected to another host /// public bool Connected { get; set; } /// /// Host IP that device is connected to /// public string ConnectedIp { get; set; } /// /// Host Name Resolution that device is connected to /// public string ConnectedHost { get; set; } /// /// User entry for Distributor ID that device is connected to /// public ushort SystemId { get; set; } /// /// User entry for location of device /// public string Location { get; set; } /// /// Firmware version string /// [Product Name]-[FW/BL]-[REL/DBG]-[Board #]-[FW Ver Name] /// public string FirmwareVersion { get; set; } /// /// Build Server number for the firmware /// 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; } } }