using Logger; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Net.Http; using System.Net.Sockets; using System.Reflection; using System.Runtime.Remoting.Contexts; using System.Security.Cryptography; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using WebApi.Helpers; using WebApi.Models; namespace WebApi.Tighten { public class TightenServer { Dictionary SendCode = new Dictionary { { "connect", "0020 0001 0050 0001 0000" }, // 建立通讯 { "heart", "00209999001000010000" }, // 心跳 { "curve", "00200900000000000000" }, // 曲线 { "result", "00200060001000010000" }, // 订阅结果 { "tightenOk", "00200062001000000000" } // 确认收到结果 }; public static event Action ShowMsg; // 记录日志事件 private bool _heartbeatRunning = false; public void InitTightenList() { RedTightenList(); //Connect(); StartHeartbeatLoop(); StartReadData(); } public void Connect() { try { foreach (KeyValuePair kvp in Gl.TightenList) { if (!kvp.Value.IsConnected) { kvp.Value.TcpClient.Connect(kvp.Value.IP, Convert.ToInt32(kvp.Value.Port)); if (kvp.Value.IsConnected) { string ErrMsg; // 创建工具连接 if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["connect"], out ErrMsg)) { Log.Error(kvp.Value.IP + ":" + ErrMsg); return; } // 心跳 if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["heart"], out ErrMsg)) { Log.Error(kvp.Value.IP + ":" + ErrMsg); return; } // 订阅结果 if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["result"], out ErrMsg)) { Log.Error(kvp.Value.IP + ":" + ErrMsg); return; } } } } } catch (Exception ex) { Log.FunError(ex, MethodBase.GetCurrentMethod().Name); } } private void RedTightenList() { SqlServer.ExecuteSql("SELECT * FROM PTCHV_基础表_拧紧枪", out DataTable dt, out string err); if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { var tool = new TightenTool(); tool.OpName = dr["OpName"].ToString(); tool.Name = dr["Name"].ToString(); tool.IP = dr["IP"].ToString(); tool.Port = dr["Port"].ToString(); tool.TcpClient = new System.Net.Sockets.TcpClient(); Gl.TightenList.TryAdd(tool.IP, tool); } } } private bool SaveTightenData(string opName,string toolName,string max,string min,string OkValue,string value) { bool isOk = false; var param = new Dictionary{ { "工位号", opName }, { "拧紧枪名称", toolName }, { "上限值", max }, { "下限值", min }, { "标准值", OkValue }, { "值", value } }; SqlServer.ExecuteProcedure("PTCHV_质量数据_增加", param, out DataTable dt, out string err); if (dt.Rows.Count > 0) { if(dt.Rows[0]["result"].ToString() == "1") { isOk = true; } } return isOk; } // 开启心跳轮询 同时监听数据 public void StartHeartbeatLoop() { foreach (var kvp in Gl.TightenList) { var tool = kvp.Value; Task.Run(async () => { while (true) { try { if (tool.TcpClient == null) tool.TcpClient = new TcpClient(); if (!tool.IsConnected) { try { tool.TcpClient.Close(); } catch { } tool.TcpClient = new TcpClient(); // 连接加超时 var connectTask = tool.TcpClient.ConnectAsync(tool.IP, Convert.ToInt32(tool.Port)); if (await Task.WhenAny(connectTask, Task.Delay(3000)) == connectTask) { // 连接成功 string errMsg; TightenHelpers.Send(tool.TcpClient, SendCode["connect"], out errMsg); TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg); TightenHelpers.Send(tool.TcpClient, SendCode["result"], out errMsg); if(errMsg == "") { Log.Info($"拧紧枪【{tool.Name}】 连接成功!"); } } else { //Log.Error($"{tool.IP} 连接超时"); } } else { string errMsg; TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg); } } catch (Exception ex) { Log.FunError(ex, "HeartbeatLoop"); } await Task.Delay(10000); } }); } } public void StartReadData() { foreach (var kvp in Gl.TightenList) { Task.Run(async () => { while (true) { var tool = kvp.Value; string ErrMsg = ""; try { var client = tool.TcpClient; bool isConnected = false; try { isConnected = client?.Client?.Connected ?? false; } catch (ObjectDisposedException) { isConnected = false; } catch (Exception ex) { Log.Error($"检查连接状态时发生意外错误 for {tool.IP}: {ex.Message}"); isConnected = false; } if (isConnected) { string command = ""; try { if(client != null) command = TightenHelpers.Read(client, out ErrMsg); else continue; if(ErrMsg != "") { Log.Error("【ReadErr】"+kvp.Value.IP + ":" + ErrMsg); } if (command.Length == 232) { TightenHelpers.ParseTorqueData(command, out double min, out double max, out double target, out double actual); ShowMsg?.Invoke($"【{tool.OpName}{tool.Name} 拧紧数据】最小扭矩: {min}, 最大扭矩: {max}, 目标扭矩: {target}, 实际扭矩: {actual}"); SaveTightenData(tool.OpName, tool.Name, max.ToString(), min.ToString(), target.ToString(), actual.ToString()); await MqttServer.SendMqttMessageToOp(tool.OpName, "TightenOk", "1"); // 发送确认前再次检查连接状态 bool canSend = false; try { canSend = client?.Client?.Connected ?? false; } catch { /* ignore */ } if (canSend) { TightenHelpers.Send(client, SendCode["tightenOk"], out ErrMsg); } } } catch (Exception readSendEx) // 捕获读取或发送过程中的异常 { Log.Error($"读取或发送数据时出错 for {tool.IP}: {readSendEx.Message}"); try { client?.Close(); } catch { } tool.TcpClient = null; // 标记以便下次循环重建 } } } catch (Exception outerEx) { Log.FunError(outerEx, MethodBase.GetCurrentMethod().Name); } await Task.Delay(50); } }); } } } }