add:增加文档和上位机

This commit is contained in:
2026-05-21 12:56:29 +08:00
parent 8ee0849831
commit a1d1f19585
95 changed files with 8594 additions and 43 deletions

170
上位机/YKC/UdpClient.cs Normal file
View File

@@ -0,0 +1,170 @@
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YKC
{
public class UdpClient : IDisposable
{
private Socket _sock;
private readonly object _lock = new object();
private readonly ConcurrentDictionary<string, Action<JObject>> _callbacks = new ConcurrentDictionary<string, Action<JObject>>();
private bool _running;
private const int FixedId = 7;
public event Action<JObject> OnActiveReport;
public UdpClient()
{
try
{
_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_sock.Bind(new IPEndPoint(IPAddress.Any, Config.LocalPort));
_sock.ReceiveTimeout = 1000;
_running = true;
Console.WriteLine($"[UDP] 监听端口 {Config.LocalPort}");
Task.Run(() => ListenLoop());
}
catch (Exception e)
{
Console.WriteLine($"[UDP] 初始化失败: {e.Message}");
}
}
private void ListenLoop()
{
var buffer = new byte[4096];
EndPoint remoteEp = new IPEndPoint(IPAddress.Any, 0);
while (_running)
{
try
{
int recv = _sock.ReceiveFrom(buffer, ref remoteEp);
string json = Encoding.UTF8.GetString(buffer, 0, recv);
var msg = JObject.Parse(json);
Dispatch(msg);
}
catch (SocketException) { }
catch (Exception e)
{
Console.WriteLine($"[UDP] 接收异常: {e.Message}");
}
}
}
private void Dispatch(JObject msg)
{
string reqId = msg.Value<string>("request_id");
Console.WriteLine($"[UDP] 收到回复: {msg}");
if (reqId != null && _callbacks.TryRemove(reqId, out var cb))
{
try { cb(msg); }
catch (Exception e) { Console.WriteLine($"[UDP] 回调异常: {e.Message}"); }
}
else
{
HandleActiveReport(msg);
}
}
private void HandleActiveReport(JObject msg)
{
string cmd = msg.Value<string>("cmd");
if (cmd == "report_data" || cmd == "pile_metrics" || cmd == "real_time_data")
{
Console.WriteLine($"[UDP] 收到主动上报, cmd={cmd}");
OnActiveReport?.Invoke(msg);
}
}
public void Send(JObject payload, Action<JObject> callback = null, string requestId = null)
{
if (requestId == null)
requestId = $"{payload.Value<string>("cmd")}_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
payload["id"] = FixedId;
payload["request_id"] = requestId;
if (callback != null)
{
_callbacks[requestId] = callback;
StartTimeoutCleaner(requestId);
}
try
{
if (_sock == null)
{
Console.WriteLine("[UDP] 套接字未就绪");
callback?.Invoke(new JObject { ["success"] = false, ["error"] = "socket_not_ready", ["request_id"] = requestId });
return;
}
byte[] data = Encoding.UTF8.GetBytes(payload.ToString(Formatting.None));
_sock.SendTo(data, new IPEndPoint(IPAddress.Parse(Config.TargetIp), Config.TargetPort));
Console.WriteLine($"[UDP] 发送: {payload}");
}
catch (Exception e)
{
Console.WriteLine($"[UDP] 发送失败: {e.Message}");
_callbacks.TryRemove(requestId, out _);
}
}
public JObject SendSync(JObject payload, int timeoutSec = 4)
{
JObject result = null;
var evt = new ManualResetEvent(false);
Send(payload, (msg) =>
{
result = msg;
evt.Set();
});
evt.WaitOne(TimeSpan.FromSeconds(timeoutSec));
return result ?? new JObject { ["success"] = false, ["error"] = "设备无响应" };
}
private void StartTimeoutCleaner(string requestId)
{
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(Config.UdpTimeout));
if (_callbacks.TryRemove(requestId, out var cb))
{
Console.WriteLine($"[UDP] 请求超时: {requestId}");
try
{
cb(new JObject
{
["success"] = false,
["error"] = "timeout",
["request_id"] = requestId
});
}
catch { }
}
});
}
public void Dispose()
{
_running = false;
_sock?.Close();
}
}
public static class UdpClientHolder
{
public static readonly UdpClient Instance = new UdpClient();
}
}