You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
797 lines
25 KiB
797 lines
25 KiB
using EC.Util.Common;
|
|
using System.Collections.Concurrent;
|
|
using System.Net;
|
|
using System.Timers;
|
|
using Timer = System.Timers.Timer;
|
|
|
|
namespace JiLinApp.Docking.VibrateAlarm;
|
|
|
|
public class TcpManager
|
|
{
|
|
#region Fields
|
|
|
|
private AsyncTcpServer Server { get; set; }
|
|
|
|
private TcpManagerConfig Config { get; set; }
|
|
|
|
private ConcurrentDictionary<string, ClientMessage> DeviceDict { get; } = new();
|
|
|
|
private Timer HeartTimer { get; } = new();
|
|
|
|
#region Event
|
|
|
|
public delegate void VibrateTcpDeviceStateEvent(ClientMessage device);
|
|
|
|
public delegate void VibrateTcpSensorStateEvent(SensorState sensor);
|
|
|
|
public delegate void VibrateTcpAlarmEvent(TcpAlarmHostMessage msg);
|
|
|
|
public event VibrateTcpDeviceStateEvent? OnVibrateTcpDeviceState;
|
|
|
|
public event VibrateTcpSensorStateEvent? OnVibrateTcpSensorState;
|
|
|
|
public event VibrateTcpAlarmEvent? OnVibrateTcpAlarm;
|
|
|
|
#endregion Event
|
|
|
|
#endregion Fields
|
|
|
|
public TcpManager()
|
|
{
|
|
}
|
|
|
|
#region Server
|
|
|
|
public void Start(TcpManagerConfig config)
|
|
{
|
|
if (IsRunning()) return;
|
|
Server = new(IPAddress.Any, config.ServerPort);
|
|
Server.ClientConnected += Server_ClientConnected;
|
|
Server.ClientDisconnected += Server_ClientDisconnected;
|
|
Server.DatagramReceived += Server_DatagramReceived;
|
|
Server.Start();
|
|
|
|
HeartTimer.Close();
|
|
HeartTimer.Interval = 1000 * config.DeviceHeartKeep;
|
|
HeartTimer.Elapsed += HeartTimer_Elapsed;
|
|
HeartTimer.Start();
|
|
|
|
Config = config;
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
if (!IsRunning()) return;
|
|
try
|
|
{
|
|
Server.Stop();
|
|
}
|
|
finally
|
|
{
|
|
Server.ClientConnected -= Server_ClientConnected;
|
|
Server.ClientDisconnected -= Server_ClientDisconnected;
|
|
Server.DatagramReceived -= Server_DatagramReceived;
|
|
Server = null;
|
|
DeviceDict.Clear();
|
|
HeartTimer.Stop();
|
|
HeartTimer.Elapsed -= HeartTimer_Elapsed;
|
|
}
|
|
}
|
|
|
|
public bool IsRunning()
|
|
{
|
|
return Server != null && Server.IsRunning();
|
|
}
|
|
|
|
#endregion Server
|
|
|
|
#region Events
|
|
|
|
private void HeartTimer_Elapsed(object? sender, ElapsedEventArgs e)
|
|
{
|
|
foreach (var clientMsg in DeviceDict.Values)
|
|
{
|
|
if (!clientMsg.IsOnline) continue;
|
|
SendHostHeart_01(clientMsg);
|
|
}
|
|
}
|
|
|
|
private void Server_ClientConnected(object? sender, TcpClientConnectedEventArgs e)
|
|
{
|
|
string clientAddr = e.TcpClient.ClientAddr();
|
|
if (clientAddr == ":") return;
|
|
string clientIp = clientAddr.Split(':')[0];
|
|
string clientPort = clientAddr.Split(':')[1];
|
|
Console.WriteLine("主机上线:{0}", clientIp);
|
|
if (!TryGetDevice(clientIp, out ClientMessage clientMsg))
|
|
{
|
|
clientMsg = new()
|
|
{
|
|
Client = e.TcpClient,
|
|
Host = new() { Id = -1, Ip = clientIp, Port = clientPort }
|
|
};
|
|
AddDeivce(clientIp, clientMsg);
|
|
}
|
|
else
|
|
{
|
|
ProcessDeviceStateEvent(ref clientMsg, 1);
|
|
}
|
|
}
|
|
|
|
private void Server_ClientDisconnected(object? sender, TcpClientDisconnectedEventArgs e)
|
|
{
|
|
string clientAddr = e.TcpClient.ClientAddr();
|
|
if (clientAddr == ":") return;
|
|
string clientIp = clientAddr.Split(':')[0];
|
|
string clientPort = clientAddr.Split(':')[1];
|
|
Console.WriteLine("主机下线:{0}", clientIp);
|
|
if (TryGetDevice(clientIp, out ClientMessage clientMsg))
|
|
{
|
|
ProcessDeviceStateEvent(ref clientMsg, 0);
|
|
}
|
|
}
|
|
|
|
private void Server_DatagramReceived(object? sender, TcpDatagramReceivedEventArgs<byte[]> e)
|
|
{
|
|
string clientAddr = e.ClientState.Client.ClientAddr();
|
|
if (clientAddr == ":") return;
|
|
string clientIp = clientAddr.Split(':')[0];
|
|
string clientPort = clientAddr.Split(':')[1];
|
|
if (TryGetDevice(clientIp, out ClientMessage clientMsg))
|
|
{
|
|
if (clientMsg.Client == null || !clientMsg.Client.Connected) clientMsg.Client = e.ClientState.Client;
|
|
clientMsg.Host ??= new() { Id = -1, Ip = clientIp, Port = clientPort };
|
|
clientMsg.AddData(e.Datagram);
|
|
ProcessDeviceStateEvent(ref clientMsg, 1);
|
|
AnalysisClientMessage(ref clientMsg);
|
|
}
|
|
}
|
|
|
|
#endregion Events
|
|
|
|
#region Analysis
|
|
|
|
private int SendCmdInterval { get; } = 6000;
|
|
|
|
private void AnalysisClientMessage(ref ClientMessage clientMsg)
|
|
{
|
|
List<byte[]> msgList = clientMsg.GetMessageList();
|
|
ClientMessage taskClientMsg = clientMsg;
|
|
foreach (byte[] msg in msgList)
|
|
{
|
|
bool vaild = msg.Length >= 19 && msg[0] == 0xAA && msg[1] == 0xAA;
|
|
Console.WriteLine("Recv from {0}:{1} => {2}, vaild:{3}", clientMsg.ClientIp, clientMsg.ClientPort, DataMessage.ToHexString(msg), vaild);
|
|
if (!vaild) continue;
|
|
DataMessage mm = new();
|
|
mm.Decode(msg);
|
|
if (clientMsg.Host.Id != mm.DeviceId) clientMsg.Host.Id = mm.DeviceId;
|
|
switch (mm.FunctionNum)
|
|
{
|
|
case 0x00:
|
|
Console.WriteLine("主机登录:{0}", clientMsg.ClientAddr);
|
|
ResponseHostLogin_10(clientMsg, mm);
|
|
|
|
if (clientMsg.Init_0_21) break;
|
|
if (!Monitor.TryEnter(clientMsg.Init_0_21, 500)) break;
|
|
Task.Run(() =>
|
|
{
|
|
while (!taskClientMsg.Init_0_21)
|
|
{
|
|
Thread.Sleep(SendCmdInterval);
|
|
RequestSensorsTurnOn_21(taskClientMsg);
|
|
}
|
|
Monitor.Exit(taskClientMsg.Init_0_21);
|
|
});
|
|
break;
|
|
|
|
case 0x01:
|
|
Console.WriteLine("主机心跳:{0}", clientMsg.ClientAddr);
|
|
break;
|
|
|
|
case 0x12:
|
|
Console.WriteLine("传感器地址设置响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x02);
|
|
break;
|
|
|
|
case 0x13:
|
|
Console.WriteLine("传感器模式设置响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x03);
|
|
break;
|
|
|
|
case 0x14:
|
|
Console.WriteLine("传感器轮询状态响应:{0}", clientMsg.ClientAddr);
|
|
int sensorAddr = mm.Data[0] + mm.Data[1] * 256;
|
|
int state = mm.Data[2] + mm.Data[3] * 256;
|
|
ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state);
|
|
|
|
SetDataResponse(mm, 0x04);
|
|
break;
|
|
|
|
case 0x15:
|
|
Console.WriteLine("传感器复位响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x05);
|
|
break;
|
|
|
|
case 0x17:
|
|
Console.WriteLine("主机返回传感器列表:{0}", clientMsg.ClientAddr);
|
|
clientMsg.Init_2_17 = true;
|
|
for (int j = 0; j < mm.Data.Length; j++)
|
|
{
|
|
sensorAddr = Convert.ToByte((mm.Data[j] + mm.Data[++j] * 256));
|
|
if (clientMsg.SensorDict.ContainsKey(sensorAddr)) continue;
|
|
SensorState sensor = new(mm.DeviceId, sensorAddr, 0, 0);
|
|
clientMsg.SensorDict[sensorAddr] = sensor;
|
|
}
|
|
RequestSensorsState_04(clientMsg);
|
|
|
|
SetDataResponse(mm, 0x07);
|
|
break;
|
|
|
|
case 0x18:
|
|
Console.WriteLine("传感器主动状态响应:{0}", clientMsg.ClientAddr);
|
|
sensorAddr = mm.Data[0] + mm.Data[1] * 256;
|
|
state = mm.Data[2] + mm.Data[3] * 256;
|
|
ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state);
|
|
ResponseHostUploadState_08(clientMsg, mm);
|
|
break;
|
|
|
|
case 0x19:
|
|
Console.WriteLine("传感器关闭响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x09);
|
|
break;
|
|
|
|
case 0x30:
|
|
Console.WriteLine("传感器启动响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x20);
|
|
break;
|
|
|
|
case 0x31:
|
|
Console.WriteLine("传感器全部启动响应:{0}", clientMsg.ClientAddr);
|
|
clientMsg.Init_0_21 = true;
|
|
if (clientMsg.Init_1_24) break;
|
|
if (!Monitor.TryEnter(clientMsg.Init_1_24, 500)) break;
|
|
Task.Run(() =>
|
|
{
|
|
while (!taskClientMsg.Init_1_24)
|
|
{
|
|
Thread.Sleep(SendCmdInterval);
|
|
RequestHostAutoUploadState_24(taskClientMsg);
|
|
}
|
|
Monitor.Exit(taskClientMsg.Init_1_24);
|
|
});
|
|
|
|
SetDataResponse(mm, 0x21);
|
|
break;
|
|
|
|
case 0x34:
|
|
Console.WriteLine("主机启动自动上传响应:{0}", clientMsg.ClientAddr);
|
|
clientMsg.Init_1_24 = true;
|
|
if (clientMsg.Init_2_17) break;
|
|
if (!Monitor.TryEnter(clientMsg.Init_2_17, 500)) break;
|
|
Task.Run(() =>
|
|
{
|
|
while (!taskClientMsg.Init_2_17)
|
|
{
|
|
Thread.Sleep(SendCmdInterval);
|
|
RequestSensorList_07(taskClientMsg);
|
|
}
|
|
Monitor.Exit(taskClientMsg.Init_2_17);
|
|
});
|
|
|
|
SetDataResponse(mm, 0x24);
|
|
break;
|
|
|
|
case 0x35:
|
|
Console.WriteLine("主机关闭自动上传响应:{0}", clientMsg.ClientAddr);
|
|
|
|
SetDataResponse(mm, 0x25);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ProcessDeviceStateEvent(ref ClientMessage device, int online)
|
|
{
|
|
if (device.OnlineState != online)
|
|
{
|
|
device.OnlineState = online;
|
|
ReportDeviceState(device);
|
|
}
|
|
}
|
|
|
|
private void ProcessSensorStateEvent(ref ClientMessage client, DataMessage mm, int sensorAddr, int state)
|
|
{
|
|
int offline = state % 2;
|
|
int alarm = state / 2 % 2;
|
|
if (!client.SensorDict.TryGetValue(sensorAddr, out SensorState? sensor))
|
|
{
|
|
sensor = new(mm.DeviceId, sensorAddr, offline, alarm);
|
|
client.SensorDict[sensorAddr] = sensor;
|
|
ReportSensorState(sensor);
|
|
}
|
|
else if (sensor.OfflineState != offline || sensor.AlarmState != alarm)
|
|
{
|
|
sensor.OfflineState = offline;
|
|
sensor.AlarmState = alarm;
|
|
ReportSensorState(sensor);
|
|
}
|
|
if (alarm == 1)
|
|
{
|
|
ReportAlarm(sensor.DeviceId, sensorAddr);
|
|
RequestSensorReset_05(client, sensorAddr);
|
|
}
|
|
}
|
|
|
|
private void ReportDeviceState(ClientMessage device)
|
|
{
|
|
OnVibrateTcpDeviceState?.Invoke(device);
|
|
}
|
|
|
|
private void ReportSensorState(SensorState sensor)
|
|
{
|
|
OnVibrateTcpSensorState?.Invoke(sensor);
|
|
}
|
|
|
|
private void ReportAlarm(int deviceId, int sensorAddr)
|
|
{
|
|
TcpAlarmHostMessage alarmMsg = new()
|
|
{
|
|
AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
|
CID = "1151",
|
|
DeviceID = deviceId,
|
|
SensorAddr = sensorAddr.ToString()
|
|
};
|
|
OnVibrateTcpAlarm?.Invoke(alarmMsg);
|
|
}
|
|
|
|
#endregion Analysis
|
|
|
|
#region Send
|
|
|
|
/// <summary>
|
|
/// 0x10:主机响应0x00登录
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="mm"></param>
|
|
/// <returns></returns>
|
|
public bool ResponseHostLogin_10(ClientMessage client, DataMessage mm)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x10, 0);
|
|
return SendResponse(msg, mm.FrameNum);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x01:心跳
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool SendHostHeart_01(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x01, 1);
|
|
msg.Data = new byte[] { 0xFF };
|
|
return SendNoRequest(msg);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x02:设置传感器地址
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="newSensorAddr"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorChange_02(ClientMessage client, int newSensorAddr)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x02, 4);
|
|
msg.Data = new byte[] { (byte)(newSensorAddr % 256), (byte)(newSensorAddr / 256), (100 % 256), (100 / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x04:请求传感器状态
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="sensorAddr"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorState_04(ClientMessage client, int sensorAddr)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
if (!client.SensorDict.TryGetValue(sensorAddr, out _)) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x04, 2);
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x04:请求传感器状态
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorsState_04(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x04, 2);
|
|
foreach (var item in client.SensorDict.Values)
|
|
{
|
|
int sensorAddr = item.Addr;
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
SendRequestTry(ref request);
|
|
Thread.Sleep(500);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x05:复位传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="sensorAddr"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorReset_05(ClientMessage client, int sensorAddr)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
if (!client.SensorDict.TryGetValue(sensorAddr, out _)) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x05, 2);
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x07:请求传感器列表
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorList_07(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x07, 0);
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x08:主机响应0x18主动上传状态
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="mm"></param>
|
|
/// <returns></returns>
|
|
public bool ResponseHostUploadState_08(ClientMessage client, DataMessage mm)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x08, 2);
|
|
msg.Data = new byte[] { mm.Data[0], mm.Data[1] };
|
|
return SendResponse(msg, mm.FrameNum);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x09:关闭传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="sensorAddr"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorTurnOff_09(ClientMessage client, int sensorAddr)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 2);
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x09:关闭传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorsTurnOff_09(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 2);
|
|
foreach (var item in client.SensorDict.Values)
|
|
{
|
|
int sensorAddr = item.Addr;
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
SendRequestTry(ref request);
|
|
Thread.Sleep(500);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x20:启动传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <param name="sensorAddr"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorTurnOn_20(ClientMessage client, int sensorAddr)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2);
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x20:启动传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorsTurnOn_20(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2);
|
|
foreach (var item in client.SensorDict.Values)
|
|
{
|
|
int sensorAddr = item.Addr;
|
|
msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) };
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
SendRequestTry(ref request);
|
|
Thread.Sleep(500);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x21:启动全部传感器
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorsTurnOn_21(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x21, 0);
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x24:启动自动上传
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestHostAutoUploadState_24(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x24, 0);
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 0x25:关闭自动上传
|
|
/// </summary>
|
|
/// <param name="client"></param>
|
|
/// <returns></returns>
|
|
public bool RequestSensorsTurnOn_25(ClientMessage client)
|
|
{
|
|
if (!client.IsOnline) return false;
|
|
DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x25, 0);
|
|
DataRequest request = new()
|
|
{
|
|
Request = msg
|
|
};
|
|
return SendRequestTry(ref request);
|
|
}
|
|
|
|
#endregion Send
|
|
|
|
#region ClientMessage
|
|
|
|
public bool ContainsDevice(string clientIp)
|
|
{
|
|
return DeviceDict.ContainsKey(clientIp);
|
|
}
|
|
|
|
public ClientMessage GetDevice(string clientIp)
|
|
{
|
|
return DeviceDict[clientIp];
|
|
}
|
|
|
|
public bool TryGetDevice(string clientIp, out ClientMessage clientMsg)
|
|
{
|
|
return DeviceDict.TryGetValue(clientIp, out clientMsg);
|
|
}
|
|
|
|
public bool TryGetDevice(int deviceId, out ClientMessage clientMsg)
|
|
{
|
|
foreach (var item in DeviceDict.Values)
|
|
{
|
|
if (item.Host.Id == deviceId)
|
|
{
|
|
clientMsg = item;
|
|
return true;
|
|
}
|
|
}
|
|
clientMsg = null;
|
|
return false;
|
|
}
|
|
|
|
private bool AddDeivce(string clientIp, ClientMessage clientMsg)
|
|
{
|
|
if (ContainsDevice(clientIp)) return false;
|
|
DeviceDict[clientIp] = clientMsg;
|
|
return true;
|
|
}
|
|
|
|
private void SetDevice(string clientIp, ClientMessage clientMsg)
|
|
{
|
|
DeviceDict[clientIp] = clientMsg;
|
|
}
|
|
|
|
private bool RemoveDevice(string clientIp)
|
|
{
|
|
return DeviceDict.Remove(clientIp, out _);
|
|
}
|
|
|
|
public List<ClientMessage> GetDeviceList()
|
|
{
|
|
return DeviceDict.Values.ToList();
|
|
}
|
|
|
|
#endregion ClientMessage
|
|
|
|
#region Set
|
|
|
|
private byte Frame { get; set; } = 0;
|
|
|
|
private byte FrameInc
|
|
{ get { return (byte)(++Frame % byte.MaxValue); } }
|
|
|
|
private int SendTryTime { get; set; } = 3;
|
|
|
|
private int SendTryInterval { get; set; } = 500;
|
|
|
|
private int ReqWaitTime { get; set; } = 3;
|
|
|
|
private int ReqWaitInterval { get; set; } = 2000;
|
|
|
|
private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte funNum, byte dataLen)
|
|
{
|
|
DataMessage msg = new()
|
|
{
|
|
DeviceId = deviceId,
|
|
SendIp = client.LocalIp,
|
|
SendPort = client.LocalPort.ToInt(),
|
|
ReceiveIp = client.ClientIp,
|
|
ReceivePort = client.ClientPort.ToInt(),
|
|
FunctionNum = funNum,
|
|
DataLen = dataLen
|
|
};
|
|
return msg;
|
|
}
|
|
|
|
private bool SendMessage(string ip, byte[] bytes)
|
|
{
|
|
if (Server == null || !Server.IsRunning()) return false;
|
|
if (!TryGetDevice(ip, out ClientMessage clientMsg)) return false;
|
|
string cmd = DataMessage.ToHexString(bytes);
|
|
bool send = false;
|
|
for (int i = 0; i < SendTryTime; i++)
|
|
{
|
|
send = Server.SendAsync(clientMsg.Client, bytes);
|
|
if (send) break;
|
|
Thread.Sleep(SendTryInterval);
|
|
}
|
|
Console.WriteLine("Send to {0}:{1} => {2}, send:{3}", clientMsg.ClientIp, clientMsg.ClientPort, cmd, send);
|
|
return send;
|
|
}
|
|
|
|
private bool SendRequestTry(ref DataRequest request)
|
|
{
|
|
if (request.Request == null) return false;
|
|
request.Request.FrameNum = FrameInc;
|
|
SetDataRequest(request);
|
|
bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode());
|
|
RemoveDataRequest(request);
|
|
return send;
|
|
}
|
|
|
|
private bool SendRequestMust(ref DataRequest request)
|
|
{
|
|
if (request.Request == null) return false;
|
|
request.Request.FrameNum = FrameInc;
|
|
SetDataRequest(request);
|
|
bool send, respond = false;
|
|
do
|
|
{
|
|
send = SendMessage(request.Request.ReceiveIp, request.Request.Encode());
|
|
if (!send) { Thread.Sleep(SendTryInterval); continue; }
|
|
for (int i = 0; i < ReqWaitTime; i++)
|
|
{
|
|
respond = IsResponse(request);
|
|
if (respond) break;
|
|
Thread.Sleep(ReqWaitInterval);
|
|
}
|
|
} while (!send || !respond);
|
|
RemoveDataRequest(request);
|
|
return true;
|
|
}
|
|
|
|
private bool SendNoRequest(DataMessage request)
|
|
{
|
|
request.FrameNum = FrameInc;
|
|
bool send = SendMessage(request.ReceiveIp, request.Encode());
|
|
return send;
|
|
}
|
|
|
|
private bool SendResponse(DataMessage request, byte frameNum)
|
|
{
|
|
request.FrameNum = frameNum;
|
|
bool send = SendMessage(request.ReceiveIp, request.Encode());
|
|
return send;
|
|
}
|
|
|
|
private ConcurrentDictionary<string, DataRequest> DataRequestDict { get; } = new();
|
|
|
|
private void SetDataRequest(DataRequest request)
|
|
{
|
|
string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}";
|
|
DataRequestDict[key] = request;
|
|
}
|
|
|
|
private void SetDataResponse(DataMessage msg, byte funcNum)
|
|
{
|
|
string key = $"{funcNum:X}-{msg.FrameNum}";
|
|
if (DataRequestDict.TryGetValue(key, out DataRequest? item)) item.Responce = msg;
|
|
}
|
|
|
|
private void RemoveDataRequest(DataRequest request)
|
|
{
|
|
string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}";
|
|
DataRequestDict.Remove(key);
|
|
}
|
|
|
|
private bool IsResponse(DataRequest request)
|
|
{
|
|
string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}";
|
|
DataRequestDict.TryGetValue(key, out DataRequest? item);
|
|
return item != null && item.Responce != null;
|
|
}
|
|
|
|
#endregion Set
|
|
}
|