阅读量:4
控件:chart1(图表),cartesianChart1(第三方添加图表),timer(时间)
添加第三方:
效果:图标会根据连接的温度,湿度用timer时间进行改变
Chart1控件样式:Series添加线条,颜色,名称等数据
public partial class Form1 : Form { public Form1() { InitializeComponent(); //1 安装livecharts第三方; 安装livechartswinform第三方; timer1.Interval = 1000; timer1.Start(); //给图表添加系列 //new LineSeries() 添加一个线性的系列 // values 指的是线性系列图表值是 ChartValues类型当中的float类型 cartesianChart1.Series.Add(new LineSeries() { Values = new ChartValues<double>() }); //温度 cartesianChart1.Series.Add(new LineSeries() { Values = new ChartValues<double>() });//湿度 //给x轴加时间 cartesianChart1.AxisX.Add(new LiveCharts.Wpf.Axis() { Labels = times }); //创建客户端对象 tcp = new TcpClient();//创建客户端对象 tcp.Connect("192.168.107.5", 8014); stream = tcp.GetStream(); //获取网络基础流 } TcpClient tcp; NetworkStream stream; public List<string> times = new List<string>(); Random r = new Random();// 随机数对象 double 温度; double 湿度; //实时更新数据 private void timer1_Tick(object sender, EventArgs e) { // 模拟数据 //float 温度 = r.Next(-100, 410) / 10F;//模拟请求 请求温度数据 //float 湿度 = r.Next(-100, 410) / 10F; //读取湿度 refresh(); //给chart1 添加数据 // 给系列1添加xy轴 ,x轴是时间,y轴是温度数据 chart1.Series[0].Points.AddXY(DateTime.Now.ToString("HH:mm:ss"), 温度); chart1.Series[1].Points.AddXY(DateTime.Now.ToString("HH:mm:ss"), 湿度); //超出一定数值之后 删除一部分图表? if (chart1.Series[0].Points.Count>=10) { chart1.Series[0].Points.RemoveAt(0); chart1.Series[1].Points.RemoveAt(0); } // 给cartesianChart1添加数据 times.Add(DateTime.Now.ToString()); cartesianChart1.Series[0].Values.Add(温度); cartesianChart1.Series[1].Values.Add(湿度); } async void refresh() { try { //请求帧 byte[] buffer = null; //响应帧 byte[] res = null; //设备地址 byte address = Convert.ToByte("1"); //响应数据的个数 int resCount = -1; //响应帧的crc byte[] crc; buffer = new byte[] { address, 0x03, 0x00, 0x02, 0x00, 0x02 }; buffer = buffer.Concat(CRCCalc(buffer)).ToArray(); //异步发请求。发送请求帧 await stream.WriteAsync(buffer, 0, buffer.Length); //接收数据 响应帧。[地址码 功能码 有效个数,0x00,0x01,0x00,0x01,高位 地位] res = new byte[9]; resCount = await stream.ReadAsync(res, 0, res.Length); //数据验证 // 数据验证 if (resCount == 0 || resCount != res.Length) { Console.WriteLine("读取湿度、温度时,数据长度不正确"); return; } // 验证地址码和功能码 if (res[0] != buffer[0] || res[1] != buffer[1]) { Console.WriteLine("读取湿度、温度时,设备地址或功能码不匹配"); return; } // 验证CRC crc = CRCCalc(res, 0, res.Length - 2); if (crc[0] != res[res.Length - 2] || crc[1] != res[res.Length - 1]) { Console.WriteLine("读取湿度、温度时,CRC验证失败"); return; } //数据解析 读取数据 double humidity = (res[3] * 256 + res[4]) * 0.1; //湿度 double wendu = (res[5] * 256 + res[6]) * 0.1; 湿度 = humidity; 温度 = wendu; } catch { MessageBox.Show("获取数据失败"); } } public static byte[] CRCCalc(byte[] data) { //crc计算赋初始值 int crc = 0xffff; for (int i = 0; i < data.Length; i++) { //XOR //(1) 0^0=0,0^1=1 0异或任何数=任何数 //(2) 1 ^ 0 = 1,1 ^ 1 = 0 1异或任何数-任何数取反 //(3) 1 ^ 1 = 0,0 ^ 0 = 0 任何数异或自己=把自己置0 //异或操作符是^。异或的特点是相同为false,不同为true。 crc = crc ^ data[i]; //和^表示按位异或运算。 //0x0fff ^ 0x01 Console.WriteLine(result.ToString("X")); // 输出结果为4094,即十六进制数1001 for (int j = 0; j < 8; j++) { int temp; temp = crc & 1; // & 运算符(与) 1 & 0 为 0 ;0 & 0 为0;1 & 1 为1 //右移 (>>) 将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。 //int i = 7; //int j = 2; //Console.WriteLine(i >> j); //输出结果为1 crc = crc >> 1; crc = crc & 0x7fff; if (temp == 1) { crc = crc ^ 0xa001; } crc = crc & 0xffff; } } //CRC寄存器的高低位进行互换 byte[] crc16 = new byte[2]; //CRC寄存器的高8位变成低8位, crc16[1] = (byte)((crc >> 8) & 0xff); //CRC寄存器的低8位变成高8位 crc16[0] = (byte)(crc & 0xff); return crc16; } public static byte[] CRCCalc(byte[] data, int offset, int length) { byte[] Tdata = data.Skip(offset).Take(length).ToArray(); return CRCCalc(Tdata); } }