20230614_SZLS_upperpc/NTADCP/Form1.cs

679 lines
22 KiB
C#
Raw Normal View History

2023-07-24 07:35:05 +00:00
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;
});
}
}
}