本文讲述树莓派用C语言程序采集温度传感器DS18B20数据,并存入SQLite和MySQL数据库。之前我们已经用Shell脚本程序实现了这些功能。
为顺利阅读本文,应先看后面参考文档中的相关内容。
《树莓派采集温度数据并存入数据库(Shell版)》https://blog.csdn.net/chentuo2000/article/details/108723075
- 硬件连接和基本操作
细节请看参考文档《树莓派+温度传感器DS18B20》一文。
https://blog.csdn.net/chentuo2000/article/details/81051701
- 查看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官网下载。
https://www.sqlite.org/download.html
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
-
-
-
-
-
-
-
-
-
-
// 保存数据到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》
https://blog.csdn.net/chentuo2000/article/details/108682421
查看最后一条数据:
select * from temperature where id=(select max(id) from temperature);
- 查看MySQL数据库
具体操作请看《树莓派安装使用数据库MariaDB (MySQL)》https://blog.csdn.net/chentuo2000/article/details/108702880
参考文档
- 树莓派采集温度数据并存入数据库(Shell版) https://blog.csdn.net/chentuo2000/article/details/108723075
- 树莓派安装使用数据库SQLite https://blog.csdn.net/chentuo2000/article/details/108682421
- 树莓派安装使用数据库MariaDB (MySQL) https://blog.csdn.net/chentuo2000/article/details/108702880
- 树莓派+温度传感器DS18B20 https://blog.csdn.net/chentuo2000/article/details/81051701
- ESP8266_SDK发送温度数据到阿里云 https://blog.csdn.net/chentuo2000/article/details/105592791
- 树莓派系列教程14:单总线控制DS18B20 https://www.waveshare.net/study/article-607-1.html
评论(0)
您还未登录,请登录后发表或查看评论