233 lines
8.8 KiB
C#
233 lines
8.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using DTS.DASLib.Command.Classes;
|
|
using DTS.Common.Utilities.Logging;
|
|
using DTS.Common.Interface.DASFactory;
|
|
using DTS.Common.Enums.DASFactory;
|
|
|
|
namespace DTS.DASLib.Command.SLICE.MulticastCommands
|
|
{
|
|
/// <summary>
|
|
/// 10558 Auto-discovery to add cmd/res support for MAC table
|
|
/// </summary>
|
|
public class MulticastDiscoverSlice6 : MulticastCommandBase
|
|
{
|
|
#region constants and enums
|
|
private const int COMMAND_PAYLOAD_SIZE = 80;
|
|
private const int DEVICE_CLASS_OFFSET = 36;
|
|
private const int NUMBER_OF_RECORDS_OFFSET = 40;
|
|
private const int RESERVED_OFFSET = 42;
|
|
private const int START_OF_MAC_TABLE = 48;
|
|
private const int SIZE_OF_MAC_RECORD = 12;//bytes
|
|
private const int PORT_OFFSET = 2;
|
|
private const int FILTER_OFFSET = 4;
|
|
private const int MAC_OFFSET = 6;
|
|
#endregion
|
|
|
|
#region private properties
|
|
protected override Commands Command => Commands.GetMACTable;
|
|
protected override bool StopAfterFirstMessage => false;
|
|
|
|
private uint _deviceClass;
|
|
private byte _responseOption;
|
|
private IPAddress _address;
|
|
private const string RX_MULTICAST_ADDRESS = "239.4.5.6";
|
|
private void SetMulticastConfig()
|
|
{
|
|
IPAddress.TryParse(RX_MULTICAST_ADDRESS, out _address);
|
|
}
|
|
#endregion
|
|
|
|
#region public properties
|
|
|
|
public DeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
|
|
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
|
|
|
|
public uint DesiredPort
|
|
{
|
|
set => command.SetParameter(41, value);
|
|
}
|
|
|
|
public byte[] MACFilter
|
|
{
|
|
set => command.SetParameter(45, value);
|
|
}
|
|
public TextLogger Logger { get; set; }
|
|
public Dictionary<string, IDiscoveredDevice> MACAddressToDevice { get; set; }
|
|
private readonly List<DiscoveredConnectedSlice> _connectedDevices = new List<DiscoveredConnectedSlice>();
|
|
public DiscoveredConnectedSlice[] ConnectedDevices => _connectedDevices.ToArray();
|
|
#endregion
|
|
|
|
#region constructors and initializers
|
|
public MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)
|
|
: base(null)
|
|
{
|
|
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
|
|
HostMac = hostMac;
|
|
DeviceClass = deviceClass;
|
|
ResponseOption = ResponseOptions.AlwaysRespond;
|
|
SetMulticastConfig();
|
|
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;
|
|
|
|
MACFilter = new[]
|
|
{
|
|
Convert.ToByte(0x00),
|
|
Convert.ToByte(0x19),
|
|
Convert.ToByte(0x9b),
|
|
byte.MaxValue,
|
|
byte.MaxValue,
|
|
byte.MaxValue
|
|
};
|
|
}
|
|
|
|
public MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)
|
|
: base(null, timeoutMillisec)
|
|
{
|
|
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
|
|
HostMac = hostMac;
|
|
DeviceClass = DeviceClasses.Any;
|
|
ResponseOption = ResponseOptions.AlwaysRespond;
|
|
SetMulticastConfig();
|
|
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;//ports 1-4
|
|
|
|
MACFilter = new[]
|
|
{
|
|
Convert.ToByte(0x00),
|
|
Convert.ToByte(0x19),
|
|
Convert.ToByte(0x9b),
|
|
byte.MaxValue,
|
|
byte.MaxValue,
|
|
byte.MaxValue
|
|
};
|
|
}
|
|
#endregion
|
|
|
|
#region methods
|
|
protected override CommandReceiveAction WholePackage()
|
|
{
|
|
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
|
|
return CommandReceiveAction.StopReceiving;
|
|
|
|
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
|
|
|
|
if (null == ResponseHostMac || !HostMac.Equals(ResponseHostMac))
|
|
{
|
|
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
|
|
return CommandReceiveAction.StopReceiving;
|
|
}
|
|
|
|
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
|
|
response.GetParameter(DEVICE_CLASS_OFFSET, out _deviceClass);
|
|
ushort numberOfEntries;
|
|
response.GetParameter(NUMBER_OF_RECORDS_OFFSET, out numberOfEntries);
|
|
var list = new List<MACTableEntry>();
|
|
for (var i = 0; i < numberOfEntries; i++)
|
|
{
|
|
try
|
|
{
|
|
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD, out ushort age);
|
|
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + PORT_OFFSET, out ushort port);
|
|
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + FILTER_OFFSET, out ushort filter);
|
|
var mac = new byte[6];
|
|
for (var b = 0; b < mac.Length; b++)
|
|
{
|
|
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + MAC_OFFSET + b, out byte thisByte);
|
|
mac[b] = thisByte;
|
|
}
|
|
list.Add(new MACTableEntry(age, port, filter, mac));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log($"MulticastDiscoverSlice6 failed to get entry - ignoring entry", ex.Message);
|
|
}
|
|
}
|
|
_connectedDevices.Add(new DiscoveredConnectedSlice(ResponseClientMac, list.ToArray()));
|
|
|
|
var responseMac = ResponseClientMac.Replace('-', ':').ToUpper();
|
|
|
|
var serialNumber = "N/A";
|
|
if (null != MACAddressToDevice && MACAddressToDevice.ContainsKey(responseMac))
|
|
{
|
|
serialNumber = MACAddressToDevice[responseMac].Serial;
|
|
}
|
|
Log(ResponseHostMac, ResponseClientMac, list.ToArray(), serialNumber);
|
|
//Log(response.Parameter);
|
|
|
|
return CommandReceiveAction.StopReceiving;
|
|
}
|
|
|
|
private static string ByteToHex(byte b)
|
|
{
|
|
return $"{b:x2}";
|
|
}
|
|
private void Log(IReadOnlyList<byte> parameter)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
sb.Append("msg: ");
|
|
foreach (var b in parameter)
|
|
{
|
|
sb.Append(ByteToHex(b));
|
|
}
|
|
sb.AppendLine();
|
|
|
|
//var bytes = new List<byte>(parameter);
|
|
|
|
sb.Append("header: ");
|
|
for (var i = 0; i < START_OF_MAC_TABLE; i++)
|
|
{
|
|
sb.Append(ByteToHex(parameter[i]));
|
|
}
|
|
sb.AppendLine();
|
|
|
|
for (var i = START_OF_MAC_TABLE; i < parameter.Count; i += SIZE_OF_MAC_RECORD)
|
|
{
|
|
sb.Append("Record: ");
|
|
for (var idx = 0; idx < SIZE_OF_MAC_RECORD; idx++)
|
|
{
|
|
sb.Append(ByteToHex(parameter[i + idx]));
|
|
}
|
|
sb.AppendLine();
|
|
}
|
|
|
|
Log(sb.ToString());
|
|
}
|
|
private void Log(string responseHostMac, string responseClientMac, MACTableEntry[] entries, string serialNumber)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
sb.AppendFormat("Host: {0}, Client: {1}, SerialNumber: {2}", responseHostMac, responseClientMac, serialNumber);
|
|
sb.AppendLine();
|
|
sb.AppendLine("Age\tFilter\tMAC\t\t\tPort");
|
|
foreach (var entry in entries)
|
|
{
|
|
sb.AppendFormat("{0}\t{1}\t{2}\t{3}", entry.Age, entry.Filter, MACAddressToString(entry.MAC), entry.Port);
|
|
sb.AppendLine();
|
|
}
|
|
|
|
Log(sb.ToString());
|
|
}
|
|
|
|
public static string MACAddressToString(IEnumerable<byte> mac)
|
|
{
|
|
var list = mac.Select(b => $"{b:x2}").ToList();
|
|
return string.Join(":", list.ToArray()).ToUpper();
|
|
}
|
|
public override void CommandToString(ref List<List<string>> lines)
|
|
{
|
|
base.CommandToString(ref lines);
|
|
lines.Add(new List<string> { $"AutoDiscover: [{HostMac}]" });
|
|
}
|
|
private void Log(string msg)
|
|
{
|
|
if (null == Logger) { return; }
|
|
Logger.LogMessage($"====={DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}=====\r\n");
|
|
Logger.LogMessage(msg);
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
} |