20230614_SZLS_upperpc/NTADCP/Form1.cs
2023-07-24 15:35:05 +08:00

679 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
/// <summary>
/// 获取本机串口号
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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]);
}
}
/// <summary>
/// 打开串口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
}
}
}
/// <summary>
/// Socket连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
}
/// <summary>
/// socket 重连
/// </summary>
/// <param name="o"></param>
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;
}));
}
}
/// <summary>
/// 客户端数据接收
/// </summary>
/// <param name="sks"></param>
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<byte>(buffer));
}
catch (Exception)
{
return;
}
}
}
/// <summary>
/// 开始测量
/// 流速方向 -> 表面流速
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 = "开始测量";
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sender"></param>
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 = "";
}
}));
}
/// <summary>
/// 打开串口前检查及数据获取
/// </summary>
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;
}
}
/// <summary>
/// 串口数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<byte>(byteRead));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
string diretion;
string SurfaceVelocity;
float total = 0;
// 定义一个List存储流速
List<float> SurfaceVelocityList = new List<float>();
/// <summary>
/// 串口数据解析及平台发送
/// </summary>
/// <param name="byteList"></param>
private void ParsingData(List<byte> 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 = "";
}
}
/// <summary>
/// Socket数据解析
/// </summary>
/// <param name="byteList"></param>
private void ParsingSocketData(List<byte> 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);
}
}
/// <summary>
/// 数据平台发送流速及流向
/// </summary>
/// <param name="SurfaceVelocity">流速</param>
/// <param name="direction">流向</param>
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<byte> data = FullByteData.ToList();
data.AddRange(rn);
string list = tools.byteToHexStr(data.ToArray());
byte[] bytea = tools.ConvertHexStringToBytes(list);
_client.SendData(bytea);
}
/// <summary>
/// CRC16 循环冗余校验算法
/// </summary>
/// <param name="pushMsg"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 检查连接状态
/// </summary>
/// <param name="Message"></param>
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;
});
}
}
}