using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using System.IO.Ports; using System.Security.Cryptography; using System.Threading; using System.IO; using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolBar; using System.Runtime.ConstrainedExecution; using System.Net; using static System.Net.Mime.MediaTypeNames; namespace NTADCP { public partial class Form1 : Form { ADCP adcp = new ADCP(); //获取当前程序运行路径 private string Save_Path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"数据采集\"; //单线程 private System.Threading.Timer _flash_page; private System.Threading.Timer timer_beckoff_01; DateTime dateTime; //定义全局变量,接收数据返回字段 private static string MessageAll = ""; //定义全局变量,存储上一个数据来源时间节点 private static DateTime TimeOld = System.DateTime.Now; //218.91.223.39:19001 private string main_ip = "218.91.223.39"; private int main_port = 19001; private Client _client = new Client(); //主板客户端 public Form1() { InitializeComponent(); textBox1.Text = main_ip; textBox2.Text = main_port.ToString(); //波特率 string[] btl = new string[] { "110", "300", "600", "1200", "2400", "4800", "9600", "14400", "19200", "38400", "56000", "57600", "115200", "128000", "256000" }; for (int i = 0; i < btl.Length; i++) { comboBox2.Items.Add(btl[i]); } comboBox2.Text = "9600"; //刷新界面的线程 _flash_page = new System.Threading.Timer(new System.Threading.TimerCallback(WritetoPage), null, 2000, 1000); button2.Enabled = false; button3.Enabled = false; } /// /// 获取本机串口号 /// /// /// private void comboBox1_DropDown(object sender, EventArgs e) { comboBox1.Items.Clear(); //获取当前设备所有的串口号 string[] portsname = tools.GetSerialPort(); for (int i = 0; i < portsname.Length; i++) { comboBox1.Items.Add(portsname[i]); } } /// /// 打开串口 /// /// /// private void button1_Click(object sender, EventArgs e) { if (button1.Text == "打开串口") { open_port(); if (serialPort1.IsOpen) { button1.Text = "关闭串口"; comboBox1.Enabled = false; this.comboBox2.Enabled = false; button2.Enabled = true; button3.Enabled = true; } else { MessageBox.Show("串口未打开,请检查串口是已经被占用!"); return; } } else { if (button2.Text == "停止测量") { MessageBox.Show("请先停止测量,后关闭串口!"); return; } else { serialPort1.Close(); if (serialPort1.IsOpen == false) { button1.Text = "打开串口"; comboBox1.Enabled = true; button2.Text = "开始测量"; button2.Enabled = false; button3.Enabled = false; this.comboBox2.Enabled = true; } else { serialPort1.Dispose(); MessageBox.Show("串口未正常关闭,已释放串口的所有资源!"); return; } } } } /// /// Socket连接 /// /// /// private void button3_Click(object sender, EventArgs e) { if (button3.Text == "连接") { //连接Socket _client.InitSocket(textBox1.Text, Convert.ToInt32(textBox2.Text)); bool isConnected = _client.Connect(); if (isConnected) { _client.pushSockets = ReceiveMess;//注册推送器 button3.Text = "断开"; textBox1.Enabled = false; textBox2.Enabled = false; } } else if (button3.Text == "断开") { _client.Stop(); button3.Text = "连接"; textBox1.Enabled = true; textBox2.Enabled = true; } } /// /// socket 重连 /// /// public void DoSocket1Connect(object o) { if (button3.Text == "连接") { Task.Run(new Action(async () => { await Task.Delay(150); //连接Socket _client.InitSocket(textBox1.Text, Convert.ToInt32(textBox2.Text)); bool isConnected = _client.Connect(); if (isConnected) { _client.pushSockets = ReceiveMess;//注册推送器 button3.Text = "断开"; textBox1.Enabled = false; textBox2.Enabled = false; } })); } else if (button3.Text == "断开") { Task.Run(new Action(async () => { await Task.Delay(100); _client.Stop(); button3.Text = "连接"; textBox1.Enabled = true; textBox2.Enabled = true; })); } } /// /// 客户端数据接收 /// /// private void ReceiveMess(Sockets sks) { if (sks.ex != null) { if (sks.ClientDispose == true) { //由于未知原因引发异常.导致客户端下线. 比如网络故障.或服务器断开连接. //wirte_textbox(string.Format("客户端下线.!异常消息:{0}\r\n", sks.ex)); } else { //SetClientState(string.Format("异常消息:{0}\r\n", sks.ex)); } //timerConnect.Enabled = true; } else if (sks.Offset == 0) { //客户端主动下线 //wirte_textbox("客户端下线!"); } else { byte[] buffer = new byte[sks.Offset]; Array.Copy(sks.RecBuffer, buffer, sks.Offset); string str = Encoding.UTF8.GetString(buffer); try { ParsingSocketData(new List(buffer)); } catch (Exception) { return; } } } /// /// 开始测量 /// 流速方向 -> 表面流速 /// /// /// private void button2_Click(object sender, EventArgs e) { if (button2.Text == "开始测量") { timer_beckoff_01 = new System.Threading.Timer(new System.Threading.TimerCallback(receive_timer_01), null, 1000, 30000); button2.Text = "停止测量"; } else if (button2.Text == "停止测量") { timer_beckoff_01.Dispose(); timer_beckoff_01 = null; button2.Text = "开始测量"; } } /// /// 发送数据 /// /// private void receive_timer_01(object sender) { string Direction = "3403000C000141AC"; byte[] bytea = tools.ConvertHexStringToBytes(Direction); tools.Logging_data(Direction); serialPort1.Write(bytea, 0, bytea.Length); Thread.Sleep(1000); string FaceVelocity = "3403000F0002F1AD"; byte[] FaceVelocitybyte = tools.ConvertHexStringToBytes(FaceVelocity); tools.Logging_data(FaceVelocity); serialPort1.Write(FaceVelocitybyte, 0, FaceVelocitybyte.Length); } //数据写入界面 private void WritetoPage(object sender) { Invoke((EventHandler)(delegate { label4.Text = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); label6.Text = adcp.SurfaceVelocity.ToString() + " " + "m/s"; if (adcp.FlowDirection == 1) { label8.Text = "正向"; } else if (adcp.FlowDirection == 0) { label8.Text = "逆向"; } else { label8.Text = ""; } })); } /// /// 打开串口前检查及数据获取 /// public void open_port() { if (string.IsNullOrEmpty(comboBox1.Text)) { Invoke((EventHandler)(delegate { MessageBox.Show("请检查串口名称!!!"); })); return; } if (string.IsNullOrEmpty(comboBox2.Text)) { Invoke((EventHandler)(delegate { MessageBox.Show("请检查波特率!!!"); })); return; } serialPort1.PortName = comboBox1.Text; serialPort1.BaudRate = int.Parse(comboBox2.Text); serialPort1.Parity = Parity.None; serialPort1.DataBits = 8; serialPort1.StopBits = StopBits.One; serialPort1.ReceivedBytesThreshold = 1; serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived); try { serialPort1.Open(); } catch (Exception) { Invoke((EventHandler)(delegate { MessageBox.Show("串口打开失败!请检查串口配置!"); })); return; } } /// /// 串口数据接收 /// /// /// private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try { //将两秒接收的数据作为1组 System.Threading.Thread.Sleep(1000); //将缓冲区内字节数大小设置为数组大小 byte[] byteRead = new byte[serialPort1.BytesToRead]; //将缓冲区内数据写入字节数组中 serialPort1.Read(byteRead, 0, byteRead.Length); //清除串口缓冲区 serialPort1.DiscardInBuffer(); if (byteRead.Length == 0) return; //数据解析 ParsingData(new List(byteRead)); } catch (Exception ex) { Console.WriteLine(ex.Message); } } string diretion; string SurfaceVelocity; float total = 0; // 定义一个List存储流速 List SurfaceVelocityList = new List(); /// /// 串口数据解析及平台发送 /// /// private void ParsingData(List byteList) { string rec_16 = null; for (int i = 0; i < byteList.Count; i++) { rec_16 += byteList[i].ToString("X2"); //16进制显示 } //校验当前List是否为空或者长度 if (byteList == null || byteList.Count == 0) return; //获取当前系统时间 DateTime time_DataBase = System.DateTime.Now; //帧头 byte[] _header = new byte[] { 0X34 }; //功能码 byte _fun_code = 0; //校验帧头 if (byteList[0] != _header[0]) { return; } //功能码 _fun_code = byteList[2]; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 DateTime dt = new DateTime(); switch (_fun_code) { //读取流向 -- 00 01 流速方向为迎水;若为 00 00 则流速方向为顺水 case 0x02: if (byteList[3] == 0x00 && byteList[4] == 0x01) { adcp.FlowDirection = 1; diretion = "正向"; } else if (byteList[3] == 0x00 && byteList[4] == 0x00) { adcp.FlowDirection = 0; diretion = "逆向"; } break; //读取流速 case 0x04: adcp.SurfaceVelocity = BitConverter.ToSingle(new byte[] { byteList[3], byteList[4], byteList[5], byteList[6] }, 0); SurfaceVelocity = adcp.SurfaceVelocity.ToString(); break; default: Console.WriteLine("未能识别功能码!"); break; } if (SurfaceVelocity != "" && diretion != "" && SurfaceVelocity != null) { var text = "测量时间:" + time_DataBase + "," + "流速:" + SurfaceVelocity + "," + "方向:" + diretion; //数据存入 tools.AddLgoToTXT("测量结果.txt", Save_Path + System.DateTime.Now.ToString("yyyy_MM_dd") + @"\", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " ---- " + text + "\r\n"); SurfaceVelocityList.Add(adcp.SurfaceVelocity); if ((SurfaceVelocityList.Count != 0) && (time_DataBase.Hour != TimeOld.Hour)) { foreach (var item in SurfaceVelocityList) { if (SurfaceVelocityList.Count == 1) { total = item; } else { total += item; } } adcp.SurfaceVelocity = total / SurfaceVelocityList.Count(); SurfaceVelocityList.Clear(); tools.Logging(time_DataBase + ": " + "本地开始向平台上发送数据!"); SendMessage(adcp.SurfaceVelocity, adcp.FlowDirection); DoConnect(); } TimeOld = time_DataBase; //判断当前时间是否为整点,如果为整点,就向平台上发送数据 //if (time_DataBase.ToString("mm:ss") == "00:00") //{ // tools.Logging(time_DataBase + ": " + "本地开始向平台上发送数据!"); // SendMessage(adcp.SurfaceVelocity, adcp.FlowDirection); // DoConnect(); //} diretion = ""; SurfaceVelocity = ""; } } /// /// Socket数据解析 /// /// private void ParsingSocketData(List byteList) { string rec_16 = null; for (int i = 0; i < byteList.Count; i++) { rec_16 += byteList[i].ToString("X2"); //16进制显示 } //校验当前List是否为空或者长度 if (byteList == null || byteList.Count == 0) return; MessageAll = rec_16; //232330303737514E3D323032333036323 如果是以这个开头的,说明数据正常反馈 if (rec_16.StartsWith("2323")) { var text = System.DateTime.Now + " " + "接收到一条回复"; tools.Logging(text); } } /// /// 数据平台发送流速及流向 /// /// 流速 /// 流向 private void SendMessage(float SurfaceVelocity, float direction) { //包头 string Head = "##"; //数据域长度 string date_length = ""; //请求编码 string RequestEncoding = "QN=" + DateTime.Now.ToString("yyy-MM-dd HH.mm.ss.fff").Replace("-", "").Replace(" ", "").Replace(".", "") + ";"; //系统编码 string SystemCoding = "ST=21;"; //命令编码 string CommandCode = "CN=2061;"; //访问密码 string AccessPassword = "PW=123456;"; //设备唯一辨识 string DeviceIdentification = "MN=32060020200003;"; //拆分包及应答标志 string Response = "Flag=9;"; //指令参数 string CP = "CP=&&DataTime=" + DateTime.Now.ToString("yyyy-MM-dd HH:00:00").Replace("-", "").Replace(" ", "").Replace(":", "") + ";"; //流速 string Velocity = "w21112-Avg=" + SurfaceVelocity + ",w21112-Flag=N;"; //流向 string dir = "e01205-Avg=" + direction + ",e01205-Flag=N" + "&&"; //数据域 string Data = RequestEncoding + SystemCoding + CommandCode + AccessPassword + DeviceIdentification + Response + CP + Velocity + dir; //更新数据域长度 date_length = "0" + Data.Length; //数据域转化为byte数组 byte[] ByteData = System.Text.Encoding.Default.GetBytes(Data); //计算crc byte[] crc = CRC16_CheckOut(ByteData); string crc1 = crc[0].ToString("X2"); string crc2 = crc[1].ToString("X2"); //完整的数据字符串 string FullData = Head + date_length + Data + crc1 + crc2; //将完整的数据转化为byte数组 byte[] FullByteData = System.Text.Encoding.Default.GetBytes(FullData); //包尾 (回车、换行) byte[] rn = new byte[2]; rn[0] = 0x0D; rn[1] = 0x0A; List data = FullByteData.ToList(); data.AddRange(rn); string list = tools.byteToHexStr(data.ToArray()); byte[] bytea = tools.ConvertHexStringToBytes(list); _client.SendData(bytea); } /// /// CRC16 循环冗余校验算法 /// /// /// private byte[] CRC16_CheckOut(byte[] pushMsg) { int crc_reg, check; crc_reg = 0xFFFF; for (int i = 0; i < pushMsg.Length; i++) { crc_reg = (crc_reg >> 8) ^ pushMsg[i]; for (int j = 0; j < 8; j++) { check = crc_reg & 0x0001; crc_reg >>= 1; if (check == 0x0001) { crc_reg ^= 0xA001; } } } byte[] returnMsg = new byte[2]; returnMsg[0] = (byte)(crc_reg >> 8); returnMsg[1] = (byte)(crc_reg & 0xFF); return returnMsg; } /// /// 检查连接状态 /// /// private async void DoConnect() { int i = 0; await Task.Run(() => { Thread.Sleep(2000); while (i < 3) { Thread.Sleep(2000); if (MessageAll == null || MessageAll == "" || (!MessageAll.StartsWith("2323"))) { tools.Logging("未收到IP:" + main_ip + "端口号:" + main_port + " 回复的信息,开始重新连接"); Thread.Sleep(10000); DoSocket1Connect("连接"); Thread.Sleep(1000); SendMessage(adcp.SurfaceVelocity, adcp.FlowDirection); i++; } else if (MessageAll.StartsWith("2323")) { tools.Logging("收到IP:" + main_ip + "端口号:" + main_port + " 回复的信息,连接成功"); break; } } MessageAll = ""; i = 0; }); } } }