树莓派采集温度数据并存入数据库(C语言版)

陈拓 2020.09.22/2020.09.24

1. 概述

本文讲述树莓派用C语言程序采集温度传感器DS18B20数据,并存入SQLite和MySQL数据库。之前我们已经用Shell脚本程序实现了这些功能。

为顺利阅读本文,应先看后面参考文档中的相关内容。

《树莓派采集温度数据并存入数据库(Shell版)》树莓派采集温度数据并存入数据库(Shell版)_shell 读取 dth11 温湿度 到数据库-CSDN博客

  • 硬件连接和基本操作

细节请看参考文档《树莓派+温度传感器DS18B20》一文。

树莓派+温度传感器DS18B20_设备树dtb中 温度传感器-CSDN博客

  • 查看DS18B20序列号

每个传感器有一个唯一的序列号。

ls /sys/bus/w1/devices/

我的DS18B20温度传感器序列号是28-000004d6162f。下面我们通过序列号读传感器的温度值。

  • 读温度值

cat /sys/bus/w1/devices/28-000004d6162f/w1_slave

第二行的t=23125就是当前的温度值,要換算成攝氏度,除以1000,即当前温度为23125/1000=23.125攝氏度。

2. 获取数据库编程头文件和链接库

我们的温度数据将写入SQLite和MySQL两个数据库,需要相应的文件。

2.1 SQLite头文件和库文件

在C语言编程时需要头文件sqlite3.h和动态链接库文件libsqlite3.so。

  • 下载sqlite3.h

在编译时会用到sqlite3.h,可以到SQLite官网下载。

SQLite Download Page

SQLite目前最新版本是3.33.0。

右击sqlite-autoconf-3330000.tar.gz(2.78 MiB),复制链接地址:

https://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz

下载:

wget -c https://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz

安装ca-certificates包:

sudo apt-get install -y ca-certificates

重新下载:sqlite-autoconf-3330000.tar.gz

解压缩:

tar zxvf sqlite-autoconf-3330000.tar.gz

复制sqlite3.h到当前目录:

cp sqlite-autoconf-3330000/sqlite3.h .

  • 查看sqlite3动态链接库

 libsqlite3.so.0是一个指向libsqlite3.so.0.8.6的软链接,也就是一个快捷方式。

  • 再创建一个libsqlite3.so.0.8.6的软链接libsqlite3.so

sudo ln -s libsqlite3.so.0.8.6 /usr/lib/arm-linux-gnueabihf/libsqlite3.so

3.2 MySQL头文件和库文件

在C语言编程时需要头文件mysql.h和动态链接库文件libmariadbclient.so。

  • 安装库文件

sudo apt-get install libmariadb-dev

  • 查找mysql.h

sudo find / -name mysql.h

/usr/include/mariadb/mysql.h

  • 查找libmariadbclient.so

sudo find / -name libmariadbclient.so

/usr/lib/arm-linux-gnueabihf/libmariadbclient.so

4. 编写C程序

在《树莓派采集温度数据并存入数据库(Shell版)》一文中我们用Shell程序实现了温度采样和数据存储功能,在本文中我们用C语言实现同样的功能。

4.1 创建数据库

  • 进入工作目录

cd idata

在《树莓派安装使用数据库SQLite》一文中我们已经创建了SQLite的数据库文件:smarthome.db。

在《树莓派安装使用数据库MariaDB (MySQL)》一文中我们也已经创建了数据库smarthome。

read_data.sh是我们在《树莓派采集温度数据并存入数据库(Shell版)》一文中写的shell脚本程序。

4.2 写C程序

nano read_data.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include "sqlite3.h"
#include <mysql.h>

// 保存数据到SQLite数据库
int save_data_sqlite(char sql[]) {
    sqlite3 *pdb = NULL;    /*数据库连接指针*/
    char *error_msg = 0;    /*错误信息指针*/
    int rc, return_value;

    rc=sqlite3_open("smarthome.db",&pdb);
    if(rc) {
        fprintf(stderr , "can't open database: %s\n",sqlite3_errmsg(pdb));
        return_value = -1;
    } else {
        // 插入或更新命令
        rc = sqlite3_exec(pdb,sql,0,0,&error_msg);  // sqlite3_exec()是sqlite3_ prepare(), sqlite3_step(), and sqlite3_finalize() 三个函数的一个封装,最好的方法是直接使用sqlite3_exec()。
        if (rc == SQLITE_OK) {
            //printf("Insert data OK! rc=%d\n", rc);    //测试
            return_value = 0;
        } else {
            //printf("Insert data Error! rc=%d\n", rc); //测试
            return_value = -2;
        }
    }
    sqlite3_close(pdb);
    return return_value;
}

static inline void _mysql_check(MYSQL * con) {
    fprintf(stderr, "%s\n", mysql_error(con));
    mysql_close(con);
    exit(EXIT_FAILURE);
}
// 保存数据到MySQL数据库
void save_data_mysql(char sql[]) {
    int rc;
    // 创建数据连接对象,需要和 mysql_close成对出现
    MYSQL *con = mysql_init(NULL);
    if (con == NULL) {
        fprintf(stderr, "%s\n", mysql_error(con));
        exit(EXIT_FAILURE);
    }
    // 创建TCP常连接对象
    if (!mysql_real_connect(con, "127.0.0.1", "ct", "ct", "smarthome", 0, NULL, 0)) {
        _mysql_check(con);
    }
    //puts("mariadb is connect and run succesed!");
    // 插入或更新命令
    rc = mysql_real_query(con, sql, strlen(sql));
    if (0 != rc) {
        _mysql_check(con);
    }

    mysql_close(con);
}

int main(int argc, char *argv[])
{
    char itime[255];
    char buf[128];
    char path[64] = "/sys/bus/w1/devices/28-000004d6162f/w1_slave";
    char *itemp;
    float ftemp;
    int fd = -1;

    char sql[256];
    char deviceid[10] = "temp001";
    int ibattery_voltage = 3333;

    // 设置时区
    setenv("TZ", "GMT-8", 1);

    while(1) {
        // 取系统时间
        time_t t = time( 0 );
        strftime(itime, 255, "%Y-%m-%d %H:%M:%S", localtime(&t)); //format date and time.
        printf("%s\n", itime);

        // 读传感器数据
        if((fd = open(path, O_RDONLY)) < 0) {
            printf("Open temperature file error! Please check /sys/bus/w1/devices/28-00000xxxxxxx file! \n");
        } else {
            if(read(fd, buf, sizeof(buf)) < 0) {
                printf("Read temperature error!\n");
            } else {
                itemp = strchr(buf,'t');
                sscanf(itemp, "t=%s", itemp);
                ftemp = atof(itemp)/1000;
                printf(" temp=%3.2f°C\n", ftemp);

                // 构造SQL语句
                sprintf(sql, "INSERT INTO temperature(deviceid, time, battery_voltage, celsius_temp) VALUES('%s', '%s', %d, %f);", deviceid, itime, ibattery_voltage, ftemp);
                puts(sql);
                puts(" ");

                // 保存数据到SQLite数据库
                save_data_sqlite(sql);

                // 保存数据到MySQL数据库
                save_data_mysql(sql);

                sleep(300); // 延时300秒
            }
        }
    }

    return 0;
}

数据同时写入SQLite和MySQL数据库,具体项目可根据情况取舍。

  • 编译

gcc -I /usr/include/mariadb read_data.c -o read_data -lmariadbclient -lsqlite3

3.3 运行C程序

./read_data

3.4 查看数据库

  • 查看SQLite数据库

具体操作请看《树莓派安装使用数据库SQLite》
树莓派安装使用数据库SQLite_树莓派 sqlite 客户端-CSDN博客

查看最后一条数据:

select * from temperature where id=(select max(id) from temperature);

  • 查看MySQL数据库

具体操作请看《树莓派安装使用数据库MariaDB (MySQL)》树莓派安装使用数据库MariaDB (MySQL)_树莓派5代 5数据库-CSDN博客

参考文档

  1. 树莓派采集温度数据并存入数据库(Shell版) 树莓派采集温度数据并存入数据库(Shell版)_shell 读取 dth11 温湿度 到数据库-CSDN博客
  2. 树莓派安装使用数据库SQLite 树莓派安装使用数据库SQLite_树莓派 sqlite 客户端-CSDN博客
  3. 树莓派安装使用数据库MariaDB (MySQL) 树莓派安装使用数据库MariaDB (MySQL)_树莓派5代 5数据库-CSDN博客
  4. 树莓派+温度传感器DS18B20 树莓派+温度传感器DS18B20_设备树dtb中 温度传感器-CSDN博客
  5. ESP8266_SDK发送温度数据到阿里云 ESP8266_SDK发送温度数据到阿里云_单片机向阿里云发送json格式数据-CSDN博客
  6. 树莓派系列教程14:单总线控制DS18B20 树莓派系列教程14:单总线控制DS18B20 - 树莓派入门教程 微雪课堂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨之清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值