前言
在日常的环境监控场景中,我们常常需要一种既能实时查看现场数据、又能把历史记录保存下来的工具。无线传感器网络解决了数据采集和传输的问题,但如果没有一个直观好用的上位机软件,那些温度、湿度、光照数据就只能停留在串口调试助手的滚动条里,既不美观也不实用。
本文分享一个基于 WinForms 编写的无线环境监控上位机软件。它能把串口收到的数据变成看得懂的仪表盘、温度计和指示灯,还能每隔一段时间自动存入数据库,方便后续查询和导出。
项目介绍
系统主要配合无线协调器节点使用。协调器通过 USB 转串口连接电脑,把从各个传感器节点收集到的环境数据(温度、湿度、光照状态)以 ASCII 字符串的形式发上来。软件负责接收、解析、展示,顺便把数据存进 SQL Server。
整个界面分成三个区域:顶部是菜单栏和状态信息,中间是仪表盘、温度计和指示灯组成的实时数据显示区,底部则藏着一个可以向上滑出的串口配置面板。这种布局的好处是,日常看数据的时候视线集中在中间,需要调参数或者看串口日志的时候再把面板拉出来,互不干扰。
项目功能
串口通信:支持自动扫描可用串口,可设置波特率(9600 到 115200),支持 ASCII 和 HEX 两种格式的收发显示。
实时数据解析:从收到的 ASCII 数据流中提取温度、湿度、光照状态,并更新到对应的控件上。
可视化展示:使用 HslControls 控件库,温度计显示温度数值,仪表盘展示湿度百分比,指示灯用颜色变化表示光照状态(亮/暗)。
数据自动存储:每隔 30 秒将当前最新的环境数据保存到 SQL Server 数据库中。
历史数据管理:提供独立的历史查询窗口,支持查看、刷新、删除记录,以及导出 CSV 文件。
全屏模式:按 F11 可切换全屏显示,适合需要大屏监控的场景。
项目特点
特点 | 说明 |
界面简洁 | 主界面聚焦实时数据展示,串口配置以滑动面板形式隐藏于底部,减少窗口切换 |
反馈即时 | 收到数据后立即解析并刷新控件,温度计、仪表盘、指示灯同步响应 |
配置灵活 | 串口参数可随时调整,支持 HEX/ASCII 模式切换,方便调试 |
数据持久化 | 自动定时存库,历史数据可查询、可导出,便于后续分析 |
扩展性好 | 代码结构清晰,解析逻辑和数据存储分离,容易适配新的传感器数据格式 |
项目技术
技术点 | 说明 |
开发语言 | C# |
界面框架 | Windows Forms(WinForms) |
控件库 | HslControls(温度计、仪表盘、指示灯等) |
串口通信 | System.IO.Ports(SerialPort 类) |
数据存储 | SQL Server(使用 SqlClient 连接) |
数据解析 | 字符串分割 + float.TryParse 解析数值 |
界面动画 | Timer 控制面板滑动(逐帧改变 Top 属性) |
多线程 | 串口 DataReceived 事件中跨线程更新 UI(Invoke) |
项目代码
挑几个关键部分展开说一下,方便大家理解核心逻辑。
串口数据接收与解析
串口收到数据后,先暂存到一个 StringBuilder 缓冲区里。每次有数据到达,以换行符 \n 作为分隔符切分出完整的行,再逐行解析。这么做的好处是,即使数据一次性来了好几条,或者一条数据被拆成两包接收,也能完整地拼出来。
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){ Thread.Sleep(50); string receivedData = serialPort.ReadExisting(); receivedBytes += receivedData.Length; this.Invoke((MethodInvoker)delegate { UpdateDataStats(); if (rbReceiveAscii.Checked) rtbReceive.AppendText(receivedData); else { byte[] byteBuffer = Encoding.Default.GetBytes(receivedData); string hexData = BitConverter.ToString(byteBuffer).Replace("-", " ") + " "; rtbReceive.AppendText(hexData); } buffer.Append(receivedData); ProcessBuffer(); });}解析逻辑集中在 ParseAndDisplayData 方法里。判断当前行包含哪个关键字(Current Temp:、Current Humidity:、Last Light:),然后取出后面的数值或状态,更新到对应的 UI 控件上。
private void ParseAndDisplayData(string line){ if (line.Contains("Current Temp:")) { string tempStr = line.Split(':')[1].Trim().Split(' ')[0]; if (float.TryParse(tempStr, out float tempValue)) { lbl_Param_Temperature.Text = $"{tempValue:F1}℃"; hslThermometer_Main.Value = tempValue; lastTemperature = tempValue; } } // 湿度和光照类似...}滑动面板动画
面板的显示/隐藏通过一个 Timer 驱动,每次移动 25 像素,直到到达目标位置。这样比直接设置 Visible 属性要平滑得多,视觉上会舒服一些。
private void PanelAnimator_Tick(object sender, EventArgs e){ int targetY = isPanelVisible ? this.ClientSize.Height - PANEL_HEIGHT : this.ClientSize.Height; int step = isPanelVisible ? -ANIMATION_STEP : ANIMATION_STEP; if (Math.Abs(pnlConfig.Top - targetY) > ANIMATION_STEP) pnlConfig.Top += step; else { pnlConfig.Top = targetY; panelAnimator.Stop(); }}定时存库
用一个独立的 Timer,每 30 秒触发一次。只有当串口处于打开状态且已经收到过有效数据时,才会执行插入操作,避免存一堆空值进去。
private void DbSaveTimer_Tick(object sender, EventArgs e){ if (serialPort.IsOpen && lastTemperature > -990 && lastHumidity > -990) { SaveDataToDatabase(lastTemperature, lastHumidity, lastLightStatus); }}项目效果
运行起来之后,主界面大致是这样的效果:
中间区域:一个纵向的温度计实时显示当前温度,右边的仪表盘指针随湿度值摆动,旁边的指示灯在“亮”时变为绿色,“暗”时变为灰色。
底部有一个带“^”符号的小按钮,点击后整个配置面板从下往上滑出,露出串口号、波特率、收发区以及发送输入框。
连接串口后,收到的数据会同时显示在接收区文本框中,同时驱动界面上的控件更新。
按 F11 可以切换到全屏模式,所有控件会自适应填满屏幕,适合在车间或实验室的大屏上展示。
通过菜单"历史数据查询"打开独立窗口,可以查看数据库中的历史记录,支持按条件筛选、删除单条或全部记录,以及一键导出 CSV。
项目源码
完整代码已在本地测试通过,核心类就是 MainForm,包含了串口操作、数据解析、UI 更新、定时存库和面板动画等全部逻辑。数据库表 SensorLog 的结构很简单,包含自增 ID、温度、湿度、光照状态和记录时间戳(默认 getdate())。
需要说明的是,实际使用时要根据自己的数据库地址、账号密码修改 connectionString。如果不需要数据库功能,把 dbSaveTimer.Stop() 注释掉即可。
为了防止丢失,可以在评论区留言关键字「环境监控上位机」,即可获取完整源码地址。
总结
项目从实际需求出发,把无线传感器网络的数据接收、展示、存储串成了一条完整的链路。技术上没有用特别复杂的框架,就是 WinForms 加上一个第三方控件库,但胜在把每个环节都做得比较到位——串口通信稳定、数据解析准确、界面反馈及时、历史数据可追溯。
如果大家也在做类似的环境监控上位机,或者刚好需要一套现成的串口数据接收和展示方案,这个项目应该能给一些参考。当然,它还有不少可以改进的地方,比如增加图表趋势展示、支持多节点数据分流、加入报警阈值设置等,这些都是后续可以继续完善的方向。
关键词
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:小码编匠
出处:gitee.com/smallcore/DotNetCore
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!
方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注【加群】
推荐阅读
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!