c# 从0实现一个温湿度监测的小工具 (6)

607 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

概述:

实际软件使用中,很多场景需要使用数据库。常用的数据库种类很多。针对我们这个小软件,我们选取微型数据库sqllite。
SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。\

安装sqlite扩展

选择项目nuget包管理,搜索 System.Data.SQLite,并安装扩展包

image.png

新建文件夹,DataBase

在dataBase中新建sqlite操作接口

在database文件夹下,新增加一个类:MySqliteAPI,用来对sqlite的增删改查进行封装。 c#操作sqlite的文章很多,我们这里直接上代码
其中:Data_DB_Name表示我们的数据库存放路径。

using System;
using System.Data;
using System.Data.SQLite;

namespace THSensor
{
    /// <summary>
    /// 后台服务不修改配置数据库 conf.db
    /// 仅仅修改数据存储库 data.db
    /// </summary>
    internal class MySqliteAPI
    {
        /// <summary>
        /// 数据库名称 
        /// </summary>
        private static string Data_DB_Name = $"{AppDomain.CurrentDomain.BaseDirectory}Conf\\Data.db";

        #region 删除
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="sqlcmd"></param>
        /// <returns></returns>
        public static bool DelInfoFromDB(string sqlcmd)
        {
            try
            {
                string connectionString = "data source = " + Data_DB_Name;
                SQLiteConnection dbConnection = new SQLiteConnection(connectionString);
                dbConnection.Open();
                using (SQLiteCommand cmd = new SQLiteCommand())
                {
                    //数据
                    cmd.Connection = dbConnection;
                    cmd.CommandText = sqlcmd;
                    cmd.ExecuteNonQuery();
                }
                dbConnection.Close();
            }
            catch (Exception e)
            {
                MyLogger._.Error(e.Message + e.StackTrace);
                return false;
            }
            return true;
        }
        #endregion

        #region 查询
        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="sqlcmd"></param>
        /// <returns></returns>
        public static DataTable GetDataFromDB(string sqlcmd)
        {
            DataTable res = new DataTable();
            SQLiteConnection dbConnection = null;
            try
            {
                //打开连接
                string connectionString = "data source = " + Data_DB_Name;
                dbConnection = new SQLiteConnection(connectionString);
                dbConnection.Open();
                //查询
                SQLiteDataAdapter mAdapter = new SQLiteDataAdapter(sqlcmd, dbConnection); ;
                mAdapter.Fill(res);
            }
            catch (Exception ex)
            {
                MyLogger._.Error(ex.StackTrace + ex.Message);
                return null;
            }
            finally
            {
                if (dbConnection != null)
                    dbConnection.Close();
            }
            return res;
        }
        #endregion

        #region 修改
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="sqlcmd"></param>
        /// <returns></returns>
        public static int UPdateDataToDB(string sqlcmd)
        {
            int num = 0;
            try
            {
                string connectionString = "data source = " + Data_DB_Name;
                SQLiteConnection dbConnection = new SQLiteConnection(connectionString);
                dbConnection.Open();
                using (SQLiteCommand cmd = new SQLiteCommand())
                {
                    //数据
                    cmd.Connection = dbConnection;
                    cmd.CommandText = sqlcmd;
                    num = cmd.ExecuteNonQuery();
                }
                dbConnection.Close();
            }
            catch (Exception e)
            {
                MyLogger._.Error(e.StackTrace + e.Message);
                return -1;
            }
            return num;
        }
        #endregion

        #region 插入
        /// <summary>
        /// 增加信息到数据库
        /// </summary>
        /// <param name="sqlcmd"></param>
        /// <returns></returns>
        public static bool InsertDataToDB(string sqlcmd)
        {
            try
            {
                string connectionString = "data source = " + Data_DB_Name;
                SQLiteConnection dbConnection = new SQLiteConnection(connectionString);
                dbConnection.Open();
                using (SQLiteCommand cmd = new SQLiteCommand())
                {
                    //数据
                    cmd.Connection = dbConnection;
                    cmd.CommandText = sqlcmd;
                    cmd.ExecuteNonQuery();
                }
                dbConnection.Close();
            }
            catch (Exception e)
            {
                MyLogger._.Error(e.StackTrace + e.Message);
                return false;
            }
            return true;
        }
        #endregion
    }
}

创建一个数据库文件Data.db

我们在项目的bin目录下,新建一个文件夹conf,下面新建一个数据库文件data.db(数据库可以通过软件,实现创建。也可以通过数据库工具创建。
在这里,我选取的是使用数据库工具nvcat创建的数据库文件。

image.png 创建表THData image.png

创建字段
id为主键,自增,类型为整形数据
temp 存储温度,文本
humi存储湿度,文本
intime表示入库时间,文本
image.png 完成后如下:

image.png

新建一个专注业务逻辑的数据库操作类

在database下新增加一个类,db_serAPI.cs,用来进行业务逻辑的处理 针对我们这个小软件,在此实现一个简单的功能: 点击按钮获取完毕温湿度以后,存储数据库中。

代码:

using System;
using System.Data;

namespace THSensor
{
    internal static class DB_SerAPI
    {
        #region 存储温湿度信息
        /// <summary>
        /// 存储温湿度信息
        /// </summary>
        /// <param name="temp"></param>
        /// <param name="humi"></param>
        /// <returns></returns>
        public static bool SaveTHData(string temp, string humi)
        {
            string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string sqlcmd = $"insert into THData (temp,humi,intime) values('{temp}','{humi}','{time}')";

            return MySqliteAPI.InsertDataToDB(sqlcmd);
        }
        #endregion
    }
}

修改页面点击按钮回调,增加入库操作

我们实现的数据库逻辑类为静态类,直接使用类名+方法调用,调用方法如下:

//增加入库操作
if (DB_SerAPI.SaveTHData(temp, humi))
{
    MessageBox.Show("入库成功");
    }

完整方法如下:
form1.cs

        /// <summary>
        /// 获取温湿度数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonget_Click(object sender, EventArgs e)
        {
            if (Runport.IsOpen)
            {
                //获取地址
                byte addr = byte.Parse(this.textBox1.Text);
                //string ret = THSensor.ReadTHDataFromSensor(Runport, 0x03);
                string ret = THSensor.ReadTHDataFromSensor(Runport, addr);
                if (!string.IsNullOrEmpty(ret))
                {
                    string temp = ret.Split('&')[0];
                    string humi = ret.Split('&')[1];
                    //赋值
                    textboxhumi.Text = humi;
                    textboxtemp.Text = temp;
                    //增加入库操作
                    if (DB_SerAPI.SaveTHData(temp, humi))
                    {
                        MessageBox.Show("入库成功");
                    }
                }
                else
                {
                    MessageBox.Show("无数据,请检查配置参数");
                }
            }
            else
            {
                MessageBox.Show("串口没有打开");
            }
        }

测试

image.png

获取到的温度:36.4 湿度 30.9 时间 8:55
使用数据库工具查看

image.png

解决一些小问题

串口打开后,更新打开按钮状态

在之前我们的代码中,点击确定打开串口后,没有任何的提示。不够人性化。 我们增加一个messagebox告知用户打开成功,同时按钮状态变为关闭

form1.cs

  • 新增一个串口打开状态
        /// <summary>
        /// 串口状态
        /// </summary>
        private bool portopened = false;
  • 修改button1的回调函数
               /// <summary>
        /// 配置确定按钮回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (portopened)
                {
                    if (Runport.IsOpen)
                    {
                        Runport.Close();
                        MessageBox.Show("串口已关闭");
                        this.button1.Text = "打  开  串  口";
                        this.button1.BackColor = Color.LightGreen;
                        portopened = false;
                    }
                }
                else
                {
                    //串口
                    string comname = this.comboBox1.Text;
                    //波特率
                    int baudrate = int.Parse(this.comboBox2.Text);
                    //打开串口
                    Runport = ComPort.V_OpenPort8N1(comname, baudrate);
                    if (Runport != null)
                    {
                        MessageBox.Show("打开串口成功");
                        this.button1.Text = "关  闭  串  口";
                        this.button1.BackColor = Color.DarkGray;
                        portopened = true;
                    }
                    else
                        MessageBox.Show("打开串口失败");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace +"\r\n"+ ex.Message);
            }
        }

效果如下:

  • 打开 image.png
  • 关闭

image.png

下一节将实现利用 dataGridView &定时器 技术实现温湿度的表格显示和定时采集