C#上位机智能温湿度监控系统

内容分享4天前发布
0 0 0

一、效果展示

启动界面

C#上位机智能温湿度监控系统

上位机采集

C#上位机智能温湿度监控系统

下位机模拟

C#上位机智能温湿度监控系统

导出excel

C#上位机智能温湿度监控系统

C#上位机智能温湿度监控系统

二、VS2022

.net4.8框架

C#上位机智能温湿度监控系统

Nuget安装NModbus

C#上位机智能温湿度监控系统

Nuget安装SQLite

C#上位机智能温湿度监控系统

Nuget安装NPOI

C#上位机智能温湿度监控系统

界面设计

C#上位机智能温湿度监控系统

三、代码展示

Form1.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;


namespace TempHumidityMonitor {
    public partial class Form1 : Form {
        private ModbusHelper _modbusHelper;
        private System.Windows.Forms.Timer _readTimer;
        private AppConfig _appConfig; // 存储当前配置
        private const byte SLAVE_ID = 1// Modbus从站地址


        // --- 新增:用于报警管理 ---
        private string _lastAlarmMessage = ""// 记录上一次的报警内容,用于去重
        private DateTime _lastAlarmTime = DateTime.MinValue;


        public Form1() {
            InitializeComponent();
            InitializeUI();
            SetupTimer();
        }


        private void InitializeUI() {
            // 设置图表
            chartData.Series.Clear();
            var seriesTemp = chartData.Series.Add("温度");
            seriesTemp.ChartType = SeriesChartType.Line;
            seriesTemp.Color = Color.Red;


            var seriesHumi = chartData.Series.Add("湿度");
            seriesHumi.ChartType = SeriesChartType.Line;
            seriesHumi.Color = Color.Blue;


            var chartArea = chartData.ChartAreas[0];


            chartArea.AxisX.LabelStyle.Format = "HH:mm:ss";
            chartArea.AxisX.MajorGrid.Interval = 3;
            chartArea.AxisX.MajorGrid.IntervalType = DateTimeIntervalType.Seconds;
            chartArea.AxisX.LabelStyle.Interval = 3;
            chartArea.AxisX.LabelStyle.IntervalType = DateTimeIntervalType.Seconds;


            chartArea.AxisY.Minimum = 0;
            chartArea.AxisY.Maximum = 100;
            chartArea.AxisY2.Enabled = AxisEnabled.True;
            chartArea.AxisY2.Minimum = 0;
            chartArea.AxisY2.Maximum = 100;


            //chartArea.AxisX.ScaleView.Zoomable = true;


            // 初始化状态标签
            labelStatus.Text = "未连接";
            labelStatus.ForeColor = Color.Red;


            // 初始缩放大小设置为60秒(例如),可以根据需要调整
            //chartArea.AxisX.ScaleView.Size = 10;
            //chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Seconds;


        }


        private void SetupTimer() {
            _readTimer = new System.Windows.Forms.Timer();
            _readTimer.Interval = 2000// 每2秒读取一次
            _readTimer.Tick += ReadTimer_Tick;
        }


        private async void ReadTimer_Tick(object sender, EventArgs e) {
            if (_modbusHelper == null || !_modbusHelper.IsConnected)
                return;


            try {
                // 使用 Task.Run 并传入撤销令牌
                var result = await Task.Run(() => _modbusHelper.ReadData(SLAVE_ID));


                if (result.HasValue) {
                    float temp = result.Value.temperature;
                    float humi = result.Value.humidity;


                    // 更新UI
                    UpdateDisplay(temp, humi);
                    AddToChart(DateTime.Now, temp, humi);
                    DatabaseHelper.SaveData(temp, humi);
                    CheckAlarm(temp, humi);
                }
                else {
                    SetStatus("读取数据失败", Color.Orange);
                }
            }
            catch (Exception ex) {
                this.Invoke((MethodInvoker)delegate {
                    SetStatus($"读取异常: {ex.Message}", Color.Red);
                });
            }
        }


        private void UpdateDisplay(float temp, float humi) {
            labelTemp.Text = $"{temp:F1} °C";
            labelHumi.Text = $"{humi:F1} %";
            SetStatus("连接正常", Color.Green);
        }


        private void AddToChart(DateTime time, float temp, float humi) {
            // 添加数据点
            chartData.Series["温度"].Points.AddXY(time, temp);
            chartData.Series["湿度"].Points.AddXY(time, humi);


            // 限制显示的数据点数量,防止图表过长
            const int maxPoints = 10;
            while (chartData.Series["温度"].Points.Count > maxPoints) {
                chartData.Series["温度"].Points.RemoveAt(0);
                chartData.Series["湿度"].Points.RemoveAt(0);
            }


            // 自动调整 X 轴范围
            var chartArea = chartData.ChartAreas[0];
            if (chartData.Series["温度"].Points.Count > 0) {
                DateTime minTime = DateTime.FromOADate(chartData.Series["温度"].Points[0].XValue);
                DateTime maxTime = time;


                chartArea.AxisX.Minimum = minTime.ToOADate();
                chartArea.AxisX.Maximum = maxTime.ToOADate();
            }


            chartData.Invalidate();
        }


        /// <summary>
        /// 检查温湿度是否超出阈值,并更新UI和报警列表
        /// </summary>
        private void CheckAlarm(float temp, float humi) {
            // 用于收集所有激活的报警
            List<string> activeAlarms = new List<string>();
            Color statusColor = Color.Green; // 默认正常颜色


            // 获取当前阈值
            float highTemp = (float)numericUpDownHighTemp.Value;
            float lowTemp = (float)numericUpDownLowTemp.Value;
            float highHumi = (float)numericUpDownHighHumi.Value;
            float lowHumi = (float)numericUpDownLowHumi.Value;


            // 检查温度
            if (temp > highTemp) {
                activeAlarms.Add($" 高温 {temp:F1}°C");
                if (statusColor == Color.Green)
                    statusColor = Color.Red; // 第一个非正常报警决定主色调
            }
            else if (temp < lowTemp) {
                activeAlarms.Add($"❄️ 低温 {temp:F1}°C");
                if (statusColor == Color.Green)
                    statusColor = Color.Blue;
            }


            // 检查湿度
            if (humi > highHumi) {
                activeAlarms.Add($" 高湿 {humi:F1}%");
                if (statusColor == Color.Green)
                    statusColor = Color.Orange;
            }
            else if (humi < lowHumi) {
                activeAlarms.Add($"️ 低湿 {humi:F1}%");
                if (statusColor == Color.Green)
                    statusColor = Color.Purple;
            }


            // --- 根据结果更新UI ---
            if (activeAlarms.Count > 0) {
                // 将所有报警信息用分号连接
                string combinedMessage = string.Join("; ", activeAlarms);


                // 更新状态栏
                UpdateStatusStrip(combinedMessage, statusColor);


                // 记录到报警列表(避免重复)
                string logKey = string.Join("|", activeAlarms); // 用管道符连接作为唯一键
                if (_lastAlarmMessage != logKey || (DateTime.Now - _lastAlarmTime).TotalSeconds > 60) {
                    LogAlarm(combinedMessage);
                    _lastAlarmMessage = logKey;
                    _lastAlarmTime = DateTime.Now;


                    //  可选:播放提示音
                    if ((DateTime.Now - _lastAlarmTime).TotalSeconds > 300) {
                        System.Media.SystemSounds.Exclamation.Play();
                    }
                }
            }
            else {
                // 所有指标正常
                UpdateStatusStrip("正常", Color.Green);
                _lastAlarmMessage = "";
            }
        }


        /// <summary>
        /// 更新底部状态栏
        /// </summary>
        /// <param>要显示的消息</param>
        /// <param>文本颜色</param>
        private void UpdateStatusStrip(string message, Color color)
        {
            // ✅ 使用 Form (this) 来检查和调用
            if (this.InvokeRequired)
            {
                // 如果在工作线程,需要通过 Invoke 切换到UI线程
                this.Invoke((MethodInvoker)delegate {
                    toolStripStatusLabel1.Text = message;
                    toolStripStatusLabel1.ForeColor = color;
                });
            }
            else
            {
                // 如果已经在UI线程,直接更新
                toolStripStatusLabel1.Text = message;
                toolStripStatusLabel1.ForeColor = color;
            }
        }


        /// <summary>
        /// 记录报警到ListBox
        /// </summary>
        /// <param>报警消息</param>
        private void LogAlarm(string message) {
            string logEntry = $"[{DateTime.Now:HH:mm:ss}{message}";


            // ✅ 最佳实践:用 'this' 检查,用 listBoxAlarms.Invoke 执行
            if (this.InvokeRequired) {
                // 使用 listBoxAlarms 的 Invoke 方法将委托封送到UI线程
                listBoxAlarms.Invoke((MethodInvoker)delegate {
                    listBoxAlarms.Items.Add(logEntry);
                    listBoxAlarms.TopIndex = listBoxAlarms.Items.Count - 1;
                });
            }
            else {
                // 直接在UI线程上操作
                listBoxAlarms.Items.Add(logEntry);
                listBoxAlarms.TopIndex = listBoxAlarms.Items.Count - 1;
            }
        }


        private void SetStatus(string text, Color color) {
            labelStatus.Text = text;
            labelStatus.ForeColor = color;
        }


        // --- UI事件处理 ---
        private void btnConnect_Click(object sender, EventArgs e) {
            if (_modbusHelper?.IsConnected == true) {
                _readTimer.Stop();


                _modbusHelper?.Dispose();
                _modbusHelper = null;


                btnConnect.Text = "连接";
                SetStatus("已断开", Color.Red);
                return;
            }


            string portName = comboBoxPort.Text;
            if (string.IsNullOrEmpty(portName)) {
                MessageBox.Show("请选择串口号!");
                return;
            }


            int baudRate = int.Parse(comboBoxBaudRate.Text);


            _modbusHelper = new ModbusHelper();
            if (_modbusHelper.Connect(portName, baudRate)) {
                _readTimer.Start();
                btnConnect.Text = "断开";
                SetStatus("连接成功", Color.Green);
            }
            else {
                MessageBox.Show("无法打开串口,请检查设备或端口设置。");
                SetStatus("连接失败", Color.Red);
            }
        }


        private void btnLoadHistory_Click(object sender, EventArgs e) {
            DataTable data = DatabaseHelper.GetAllData();
            dataGridViewHistory.DataSource = data;
        }


        private void Form1_Load(object sender, EventArgs e) {


            // --- 加载配置 ---
            _appConfig = JsonHelper.LoadConfig();


            // 自动填充串口号
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            comboBoxPort.Items.AddRange(ports);
            if (!string.IsNullOrEmpty(_appConfig.PortName) && ports.Contains(_appConfig.PortName))
            {
                comboBoxPort.SelectedItem = _appConfig.PortName;
            }
            else if (ports.Length > 0)
            {
                comboBoxPort.SelectedIndex = 0// 默认第一个
            }


            // 设置默认波特率
            comboBoxBaudRate.Items.AddRange(new object[] { "9600""19200""38400""57600""115200" });
            if (_appConfig.BaudRate.ToString() == comboBoxBaudRate.Items.Cast<string>().FirstOrDefault(x => x == _appConfig.BaudRate.ToString()))
            {
                comboBoxBaudRate.SelectedItem = _appConfig.BaudRate.ToString();
            }
            else
            {
                comboBoxBaudRate.SelectedItem = "115200"// 默认
            }


            // 设置报警阈值
            numericUpDownHighTemp.Value = (decimal)_appConfig.HighTemp;
            numericUpDownLowTemp.Value = (decimal)_appConfig.LowTemp;
            numericUpDownHighHumi.Value = (decimal)_appConfig.HighHumi;
            numericUpDownLowHumi.Value = (decimal)_appConfig.LowHumi;
        }


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _readTimer?.Stop();


            // 直接调用 Disconnect,它会安全地清理所有资源
            _modbusHelper?.Dispose();
            _modbusHelper = null;


            // --- 保存当前配置 ---
            _appConfig.PortName = comboBoxPort.Text;
            _appConfig.BaudRate = int.Parse(comboBoxBaudRate.Text);
            _appConfig.HighTemp = (float)numericUpDownHighTemp.Value;
            _appConfig.LowTemp = (float)numericUpDownLowTemp.Value;
            _appConfig.HighHumi = (float)numericUpDownHighHumi.Value;
            _appConfig.LowHumi = (float)numericUpDownLowHumi.Value;


            JsonHelper.SaveConfig(_appConfig);
        }


        private void btnExport_Click(object sender, EventArgs e) {
            // ✅ 直接从数据库获取所有数据,不依赖 DataGridView 的 DataSource
            DataTable allData = DatabaseHelper.GetAllData();


            if (allData == null || allData.Rows.Count == 0) {
                MessageBox.Show("数据库中没有历史数据可导出。""提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }


            using (SaveFileDialog sfd = new SaveFileDialog()) {
                sfd.Filter = "Excel文件|*.xlsx";
                sfd.Title = "导出历史数据";
                if (sfd.ShowDialog() == DialogResult.OK) {
                    ExportToExcel(allData, sfd.FileName);
                }
            }
        }


        // 此方法目前只接收一个 DataTable,不再需要从 DataGridView 取数据
        private void ExportToExcel(DataTable dt, string filePath) {
            try {
                NPOI.XSSF.UserModel.XSSFWorkbook workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
                NPOI.SS.UserModel.ISheet sheet = workbook.CreateSheet("历史数据");


                // 创建表头
                NPOI.SS.UserModel.IRow headerRow = sheet.CreateRow(0);
                for (int i = 0; i < dt.Columns.Count; i++) {
                    headerRow.CreateCell(i).SetCellValue(dt.Columns[i].ColumnName);
                }


                // 填充数据
                for (int i = 0; i < dt.Rows.Count; i++) {
                    NPOI.SS.UserModel.IRow row = sheet.CreateRow(i + 1);
                    for (int j = 0; j < dt.Columns.Count; j++) {
                        row.CreateCell(j).SetCellValue(dt.Rows[i][j]?.ToString());
                    }
                }


                // 自动调整列宽
                for (int i = 0; i < dt.Columns.Count; i++) {
                    sheet.AutoSizeColumn(i);
                }


                using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write)) {
                    workbook.Write(fs);
                }


                MessageBox.Show("导出成功!");
            }
            catch (Exception ex) {
                MessageBox.Show($"导出失败: {ex.Message}");
            }
        }


    }
}

Form1.Designer.cs

namespace TempHumidityMonitor {
    partial class Form1 {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;


        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param>如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }


        #region Windows 窗体设计器生成的代码


        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent() {
            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
            System.Windows.Forms.DataVisualization.Charting.Legend legend2 = new System.Windows.Forms.DataVisualization.Charting.Legend();
            System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
            System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
            this.comboBoxPort = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.comboBoxBaudRate = new System.Windows.Forms.ComboBox();
            this.btnConnect = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.labelTemp = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.labelHumi = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.labelStatus = new System.Windows.Forms.Label();
            this.chartData = new System.Windows.Forms.DataVisualization.Charting.Chart();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.numericUpDownLowHumi = new System.Windows.Forms.NumericUpDown();
            this.numericUpDownHighHumi = new System.Windows.Forms.NumericUpDown();
            this.numericUpDownLowTemp = new System.Windows.Forms.NumericUpDown();
            this.numericUpDownHighTemp = new System.Windows.Forms.NumericUpDown();
            this.label12 = new System.Windows.Forms.Label();
            this.label11 = new System.Windows.Forms.Label();
            this.label10 = new System.Windows.Forms.Label();
            this.label9 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.dataGridViewHistory = new System.Windows.Forms.DataGridView();
            this.btnLoadHistory = new System.Windows.Forms.Button();
            this.btnExport = new System.Windows.Forms.Button();
            this.statusStrip1 = new System.Windows.Forms.StatusStrip();
            this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
            this.listBoxAlarms = new System.Windows.Forms.ListBox();
            this.groupBox1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.chartData)).BeginInit();
            this.groupBox2.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownLowHumi)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownHighHumi)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownLowTemp)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownHighTemp)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridViewHistory)).BeginInit();
            this.statusStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // comboBoxPort
            // 
            this.comboBoxPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBoxPort.FormattingEnabled = true;
            this.comboBoxPort.Location = new System.Drawing.Point(6513);
            this.comboBoxPort.Name = "comboBoxPort";
            this.comboBoxPort.Size = new System.Drawing.Size(10024);
            this.comboBoxPort.TabIndex = 0;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(1216);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(4316);
            this.label1.TabIndex = 1;
            this.label1.Text = "串口号:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(18016);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(4316);
            this.label2.TabIndex = 2;
            this.label2.Text = "波特率:";
            // 
            // comboBoxBaudRate
            // 
            this.comboBoxBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBoxBaudRate.FormattingEnabled = true;
            this.comboBoxBaudRate.Items.AddRange(new object[] {
            "9600",
            "19200",
            "38400",
            "57600",
            "115200"});
            this.comboBoxBaudRate.Location = new System.Drawing.Point(24513);
            this.comboBoxBaudRate.Name = "comboBoxBaudRate";
            this.comboBoxBaudRate.Size = new System.Drawing.Size(10024);
            this.comboBoxBaudRate.TabIndex = 3;
            // 
            // btnConnect
            // 
            this.btnConnect.Location = new System.Drawing.Point(36511);
            this.btnConnect.Name = "btnConnect";
            this.btnConnect.Size = new System.Drawing.Size(8029);
            this.btnConnect.TabIndex = 4;
            this.btnConnect.Text = "连接";
            this.btnConnect.UseVisualStyleBackColor = true;
            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.groupBox1.Controls.Add(this.labelTemp);
            this.groupBox1.Controls.Add(this.label4);
            this.groupBox1.Controls.Add(this.label5);
            this.groupBox1.Controls.Add(this.labelHumi);
            this.groupBox1.Controls.Add(this.label7);
            this.groupBox1.Controls.Add(this.labelStatus);
            this.groupBox1.Location = new System.Drawing.Point(1248);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(77764);
            this.groupBox1.TabIndex = 5;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "实时状态";
            // 
            // labelTemp
            // 
            this.labelTemp.AutoSize = true;
            this.labelTemp.Font = new System.Drawing.Font("微软雅黑"12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.labelTemp.ForeColor = System.Drawing.Color.Red;
            this.labelTemp.Location = new System.Drawing.Point(10027);
            this.labelTemp.Name = "labelTemp";
            this.labelTemp.Size = new System.Drawing.Size(6622);
            this.labelTemp.TabIndex = 7;
            this.labelTemp.Text = "--.-- °C";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(18332);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(3216);
            this.label4.TabIndex = 6;
            this.label4.Text = "湿度:";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(632);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(3216);
            this.label5.TabIndex = 5;
            this.label5.Text = "温度:";
            // 
            // labelHumi
            // 
            this.labelHumi.AutoSize = true;
            this.labelHumi.Font = new System.Drawing.Font("微软雅黑"12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.labelHumi.ForeColor = System.Drawing.Color.Blue;
            this.labelHumi.Location = new System.Drawing.Point(22827);
            this.labelHumi.Name = "labelHumi";
            this.labelHumi.Size = new System.Drawing.Size(6322);
            this.labelHumi.TabIndex = 8;
            this.labelHumi.Text = "--.-- %";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(33032);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(3216);
            this.label7.TabIndex = 9;
            this.label7.Text = "状态:";
            // 
            // labelStatus
            // 
            this.labelStatus.AutoSize = true;
            this.labelStatus.Font = new System.Drawing.Font("微软雅黑"10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.labelStatus.Location = new System.Drawing.Point(37532);
            this.labelStatus.Name = "labelStatus";
            this.labelStatus.Size = new System.Drawing.Size(3720);
            this.labelStatus.TabIndex = 10;
            this.labelStatus.Text = "就绪";
            // 
            // chartData
            // 
            this.chartData.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            chartArea2.AxisX.LabelStyle.Format = "HH:mm:ss";
            chartArea2.AxisX.MajorGrid.Interval = 5D;
            chartArea2.AxisY.Title = "温度 (°C)";
            chartArea2.AxisY2.Enabled = System.Windows.Forms.DataVisualization.Charting.AxisEnabled.True;
            chartArea2.AxisY2.Title = "湿度 (%)";
            chartArea2.Name = "ChartArea1";
            this.chartData.ChartAreas.Add(chartArea2);
            legend2.Name = "Legend1";
            this.chartData.Legends.Add(legend2);
            this.chartData.Location = new System.Drawing.Point(12118);
            this.chartData.Name = "chartData";
            series3.ChartArea = "ChartArea1";
            series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            series3.Legend = "Legend1";
            series3.Name = "温度";
            series4.ChartArea = "ChartArea1";
            series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            series4.Legend = "Legend1";
            series4.Name = "湿度";
            this.chartData.Series.Add(series3);
            this.chartData.Series.Add(series4);
            this.chartData.Size = new System.Drawing.Size(777310);
            this.chartData.TabIndex = 6;
            this.chartData.Text = "chart1";
            // 
            // groupBox2
            // 
            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.groupBox2.Controls.Add(this.numericUpDownLowHumi);
            this.groupBox2.Controls.Add(this.numericUpDownHighHumi);
            this.groupBox2.Controls.Add(this.numericUpDownLowTemp);
            this.groupBox2.Controls.Add(this.numericUpDownHighTemp);
            this.groupBox2.Controls.Add(this.label12);
            this.groupBox2.Controls.Add(this.label11);
            this.groupBox2.Controls.Add(this.label10);
            this.groupBox2.Controls.Add(this.label9);
            this.groupBox2.Controls.Add(this.label8);
            this.groupBox2.Location = new System.Drawing.Point(12438);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(300160);
            this.groupBox2.TabIndex = 7;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "报警设置";
            // 
            // numericUpDownLowHumi
            // 
            this.numericUpDownLowHumi.DecimalPlaces = 1;
            this.numericUpDownLowHumi.Increment = new decimal(new int[] {
            5,
            0,
            0,
            65536});
            this.numericUpDownLowHumi.Location = new System.Drawing.Point(150117);
            this.numericUpDownLowHumi.Name = "numericUpDownLowHumi";
            this.numericUpDownLowHumi.Size = new System.Drawing.Size(8022);
            this.numericUpDownLowHumi.TabIndex = 8;
            this.numericUpDownLowHumi.Value = new decimal(new int[] {
            30,
            0,
            0,
            0});
            // 
            // numericUpDownHighHumi
            // 
            this.numericUpDownHighHumi.DecimalPlaces = 1;
            this.numericUpDownHighHumi.Increment = new decimal(new int[] {
            5,
            0,
            0,
            65536});
            this.numericUpDownHighHumi.Location = new System.Drawing.Point(15085);
            this.numericUpDownHighHumi.Name = "numericUpDownHighHumi";
            this.numericUpDownHighHumi.Size = new System.Drawing.Size(8022);
            this.numericUpDownHighHumi.TabIndex = 7;
            this.numericUpDownHighHumi.Value = new decimal(new int[] {
            80,
            0,
            0,
            0});
            // 
            // numericUpDownLowTemp
            // 
            this.numericUpDownLowTemp.DecimalPlaces = 1;
            this.numericUpDownLowTemp.Increment = new decimal(new int[] {
            5,
            0,
            0,
            65536});
            this.numericUpDownLowTemp.Location = new System.Drawing.Point(15053);
            this.numericUpDownLowTemp.Minimum = new decimal(new int[] {
            100,
            0,
            0,
            -2147483648});
            this.numericUpDownLowTemp.Name = "numericUpDownLowTemp";
            this.numericUpDownLowTemp.Size = new System.Drawing.Size(8022);
            this.numericUpDownLowTemp.TabIndex = 6;
            this.numericUpDownLowTemp.Value = new decimal(new int[] {
            10,
            0,
            0,
            0});
            // 
            // numericUpDownHighTemp
            // 
            this.numericUpDownHighTemp.DecimalPlaces = 1;
            this.numericUpDownHighTemp.Increment = new decimal(new int[] {
            5,
            0,
            0,
            65536});
            this.numericUpDownHighTemp.Location = new System.Drawing.Point(15021);
            this.numericUpDownHighTemp.Name = "numericUpDownHighTemp";
            this.numericUpDownHighTemp.Size = new System.Drawing.Size(8022);
            this.numericUpDownHighTemp.TabIndex = 5;
            this.numericUpDownHighTemp.Value = new decimal(new int[] {
            30,
            0,
            0,
            0});
            // 
            // label12
            // 
            this.label12.AutoSize = true;
            this.label12.Location = new System.Drawing.Point(80123);
            this.label12.Name = "label12";
            this.label12.Size = new System.Drawing.Size(5416);
            this.label12.TabIndex = 4;
            this.label12.Text = "低湿阈值:";
            // 
            // label11
            // 
            this.label11.AutoSize = true;
            this.label11.Location = new System.Drawing.Point(8091);
            this.label11.Name = "label11";
            this.label11.Size = new System.Drawing.Size(5416);
            this.label11.TabIndex = 3;
            this.label11.Text = "高湿阈值:";
            // 
            // label10
            // 
            this.label10.AutoSize = true;
            this.label10.Location = new System.Drawing.Point(8059);
            this.label10.Name = "label10";
            this.label10.Size = new System.Drawing.Size(5416);
            this.label10.TabIndex = 2;
            this.label10.Text = "低温阈值:";
            // 
            // label9
            // 
            this.label9.AutoSize = true;
            this.label9.Location = new System.Drawing.Point(8027);
            this.label9.Name = "label9";
            this.label9.Size = new System.Drawing.Size(5416);
            this.label9.TabIndex = 1;
            this.label9.Text = "高温阈值:";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Font = new System.Drawing.Font("微软雅黑"9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label8.Location = new System.Drawing.Point(1027);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(3217);
            this.label8.TabIndex = 0;
            this.label8.Text = "温度";
            // 
            // dataGridViewHistory
            // 
            this.dataGridViewHistory.AllowUserToAddRows = false;
            this.dataGridViewHistory.AllowUserToDeleteRows = false;
            this.dataGridViewHistory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.dataGridViewHistory.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridViewHistory.Location = new System.Drawing.Point(320434);
            this.dataGridViewHistory.Name = "dataGridViewHistory";
            this.dataGridViewHistory.ReadOnly = true;
            this.dataGridViewHistory.RowTemplate.Height = 23;
            this.dataGridViewHistory.Size = new System.Drawing.Size(469126);
            this.dataGridViewHistory.TabIndex = 8;
            // 
            // btnLoadHistory
            // 
            this.btnLoadHistory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.btnLoadHistory.Location = new System.Drawing.Point(406563);
            this.btnLoadHistory.Name = "btnLoadHistory";
            this.btnLoadHistory.Size = new System.Drawing.Size(10030);
            this.btnLoadHistory.TabIndex = 9;
            this.btnLoadHistory.Text = "加载历史数据";
            this.btnLoadHistory.UseVisualStyleBackColor = true;
            this.btnLoadHistory.Click += new System.EventHandler(this.btnLoadHistory_Click);
            // 
            // btnExport
            // 
            this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.btnExport.Location = new System.Drawing.Point(584564);
            this.btnExport.Name = "btnExport";
            this.btnExport.Size = new System.Drawing.Size(10030);
            this.btnExport.TabIndex = 10;
            this.btnExport.Text = "导出Excel";
            this.btnExport.UseVisualStyleBackColor = true;
            this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
            // 
            // statusStrip1
            // 
            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripStatusLabel1});
            this.statusStrip1.Location = new System.Drawing.Point(0662);
            this.statusStrip1.Name = "statusStrip1";
            this.statusStrip1.Size = new System.Drawing.Size(80122);
            this.statusStrip1.TabIndex = 11;
            this.statusStrip1.Text = "statusStrip1";
            // 
            // toolStripStatusLabel1
            // 
            this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
            this.toolStripStatusLabel1.Size = new System.Drawing.Size(3217);
            this.toolStripStatusLabel1.Text = "就绪";
            // 
            // listBoxAlarms
            // 
            this.listBoxAlarms.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.listBoxAlarms.FormattingEnabled = true;
            this.listBoxAlarms.ItemHeight = 16;
            this.listBoxAlarms.Location = new System.Drawing.Point(320594);
            this.listBoxAlarms.Name = "listBoxAlarms";
            this.listBoxAlarms.Size = new System.Drawing.Size(46984);
            this.listBoxAlarms.TabIndex = 12;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(801684);
            this.Controls.Add(this.listBoxAlarms);
            this.Controls.Add(this.statusStrip1);
            this.Controls.Add(this.btnExport);
            this.Controls.Add(this.btnLoadHistory);
            this.Controls.Add(this.dataGridViewHistory);
            this.Controls.Add(this.chartData);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.btnConnect);
            this.Controls.Add(this.comboBoxBaudRate);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.comboBoxPort);
            this.Font = new System.Drawing.Font("微软雅黑"8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.MinimumSize = new System.Drawing.Size(800680);
            this.Name = "Form1";
            this.Text = "智能温湿度监控系统";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.chartData)).EndInit();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownLowHumi)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownHighHumi)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownLowTemp)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownHighTemp)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridViewHistory)).EndInit();
            this.statusStrip1.ResumeLayout(false);
            this.statusStrip1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();


        }


        #endregion


        private System.Windows.Forms.ComboBox comboBoxPort;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.ComboBox comboBoxBaudRate;
        private System.Windows.Forms.Button btnConnect;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Label labelTemp;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Label labelHumi;
        private System.Windows.Forms.Label label7;
        private System.Windows.Forms.Label labelStatus;
        private System.Windows.Forms.DataVisualization.Charting.Chart chartData;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.NumericUpDown numericUpDownLowHumi;
        private System.Windows.Forms.NumericUpDown numericUpDownHighHumi;
        private System.Windows.Forms.NumericUpDown numericUpDownLowTemp;
        private System.Windows.Forms.NumericUpDown numericUpDownHighTemp;
        private System.Windows.Forms.Label label12;
        private System.Windows.Forms.Label label11;
        private System.Windows.Forms.Label label10;
        private System.Windows.Forms.Label label9;
        private System.Windows.Forms.Label label8;
        private System.Windows.Forms.DataGridView dataGridViewHistory;
        private System.Windows.Forms.Button btnLoadHistory;
        private System.Windows.Forms.Button btnExport;
        private System.Windows.Forms.StatusStrip statusStrip1;
        private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
        private System.Windows.Forms.ListBox listBoxAlarms;
    }
}

SqLiteHelper

using System;
using System.Data.SQLite;




namespace TempHumidityMonitor {


    public static class DatabaseHelper {


        private static string ConnectionString = "Data Source=sensor_data.db;Version=3;";


        /// <summary>
        /// 静态构造函数,在首次使用类时执行一次
        /// </summary>
        static DatabaseHelper() {
            InitializeDatabase();
        }


        private static void InitializeDatabase() {
            using (var connection = new SQLiteConnection(ConnectionString)) {
                connection.Open();
                string createTableSql = @"
                    CREATE TABLE IF NOT EXISTS SensorData (
                        Id INTEGER PRIMARY KEY AUTOINCREMENT,
                        Temperature REAL NOT NULL,
                        Humidity REAL NOT NULL,
                        Timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
                    );";
                using (var command = new SQLiteCommand(createTableSql, connection)) {
                    command.ExecuteNonQuery();
                }
            }
        }


        /// <summary>
        /// 保存一条数据到数据库
        /// </summary>
        public static void SaveData(float temperature, float humidity) {
            using (var connection = new SQLiteConnection(ConnectionString)) {
                connection.Open();
                string insertSql = "INSERT INTO SensorData (Temperature, Humidity) VALUES (@temp, @humi)";
                using (var command = new SQLiteCommand(insertSql, connection)) {
                    command.Parameters.AddWithValue("@temp", temperature);
                    command.Parameters.AddWithValue("@humi", humidity);
                    command.ExecuteNonQuery();
                }
            }
        }


        /// <summary>
        /// 查询所有历史数据
        /// </summary>
        /// <returns>包含历史数据的DataTable</returns>
        public static System.Data.DataTable GetAllData() {
            var dataTable = new System.Data.DataTable();
            using (var connection = new SQLiteConnection(ConnectionString)) {
                connection.Open();
                string selectSql = "SELECT Id, Temperature, Humidity, Timestamp FROM SensorData ORDER BY Timestamp DESC";
                using (var adapter = new SQLiteDataAdapter(selectSql, connection)) {
                    adapter.Fill(dataTable);
                }
            }
            return dataTable;
        }
    }
}

导出Excel

// 此方法目前只接收一个 DataTable,不再需要从 DataGridView 取数据
private void ExportToExcel(DataTable dt, string filePath) {
try {
		NPOI.XSSF.UserModel.XSSFWorkbook workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
		NPOI.SS.UserModel.ISheet sheet = workbook.CreateSheet("历史数据");


// 创建表头
		NPOI.SS.UserModel.IRow headerRow = sheet.CreateRow(0);
for (int i = 0; i < dt.Columns.Count; i++) {
			headerRow.CreateCell(i).SetCellValue(dt.Columns[i].ColumnName);
		}


// 填充数据
for (int i = 0; i < dt.Rows.Count; i++) {
			NPOI.SS.UserModel.IRow row = sheet.CreateRow(i + 1);
for (int j = 0; j < dt.Columns.Count; j++) {
				row.CreateCell(j).SetCellValue(dt.Rows[i][j]?.ToString());
			}
		}


// 自动调整列宽
for (int i = 0; i < dt.Columns.Count; i++) {
			sheet.AutoSizeColumn(i);
		}


		using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write)) {
			workbook.Write(fs);
		}


		MessageBox.Show("导出成功!");
	}
catch (Exception ex) {
		MessageBox.Show($"导出失败: {ex.Message}");
	}
}

Modbus通讯工具下载和测试

C# WinForm +Modbus RTU通讯

© 版权声明

相关文章

暂无评论

none
暂无评论...