整体思路
1, 树莓派实现 DS18B20、并通过socket客户端上报,并存储在sqlite数据库中;
2,客户端每隔60秒采样一次;
3, 采用epoll模型实现socket服务器代码,能够正常获取客户端上报的传感器值。
4, 客户端与服务器端其中上报值包括:设备ID、USER、采样时间、采样温度;
5, 程序要支持命令行参数传参,方便程序部署:
a, 服务器端程序监听端口号由命令行参数解析;
b, 客户端程序 要连接的服务器地址、端口号由命令行参数解析;
客户端流程图
客户端代码:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <signal.h>
static sqlite3 *db;
int g_stop=0;
static inline void print_usage(char *progname);
int get_time(char *tim);
int get_temperature(float *temp);
int callback(void *notused,int argc,char **argv,char **name);
sqlite3 *db_connect(char *db_name);
void db_exec();
void db_insert();
void db_select();
void sig_handle(int signum);
int main(int argc, char **argv)
{
int conn_fd = -1;
int rv = -1;
char buf[1024];
struct sockaddr_in serv_addr;
char *serv_ip=NULL;
int serv_port;
int opt;
float tem;
char tem_s[20];
char tim[32];
char *user="user:yanpan";
char *db_name="TEMPERATURE.db";
struct option long_options[] =
{
{"ip",required_argument,NULL,'i'},
{"port",required_argument, NULL, 'p'},
{"help",no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
/*参数解析*/
while ((opt = getopt_long(argc, argv, "i:p:h", long_options, NULL)) != -1)
{
switch (opt)
{
case 'i':
serv_ip=optarg;
break;
case 'p':
serv_port = atoi(optarg);
break;
case 'h': /* Get help information */
print_usage(argv[0]);
return 0;
default:
break;
}
}
if( !serv_port ||!serv_ip)
{
print_usage(argv[0]);
return -1;
}
/*客户端调用socket函数初始化,并connect服务器*/
conn_fd = socket(AF_INET, SOCK_STREAM, 0);
if(conn_fd < 0)
{
printf("create socket failure: %s\n", strerror(errno));
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(serv_port);
inet_aton( serv_ip, &serv_addr.sin_addr );
if( connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("connect to server [%s:%d] failure: %s\n", serv_ip, serv_port, strerror(errno));
return 0;
}
/*安装信号*/
signal(SIGTERM,sig_handle);
signal(SIGALRM,sig_handle);
signal(SIGINT,sig_handle);
while(!g_stop)
{
get_temperature(&tem);
sprintf(tem_s,"\ttemperature:%5.3f",tem);
get_time(tim);
printf("the temperature is %5.3f\n",tem);
memset(buf, 0, sizeof(buf));
snprintf(buf,sizeof(buf),"%s%s%s",user,tim,tem_s);
db=db_connect(db_name);
db_exec();
db_insert();
db_select();
rv = write(conn_fd, buf, strlen(buf));
if(rv < 0)
{
printf("write data to server by client_fd[%d] failure: %s\n", conn_fd,strerror(errno));
return -1;
close(conn_fd);
}
printf("write to server by client_fd[%d] [%s]successfully!\n",conn_fd,buf);
rv=read(conn_fd,buf,sizeof(buf));
if(rv<0)
{
printf("read data from server by server[%d] failure:%s\n",conn_fd,strerror(errno));
return -1;
}
else if(rv==0)
{
printf("server_fd [%d]get disconnect\n",conn_fd);
return -1;
}
else if(rv>0)
{
printf("Read %d bytes data from server: '%s'\n", rv, buf);
}
sleep(60);
}
}
static inline void print_usage(char *progname)
{
printf("Usage: %s [OPTION]...\n", progname);
printf(" %s is a socket server program, which used to verify client and echo back string from it\n",progname);
printf("\nMandatory arguments to long options are mandatory for short options too:\n");
printf(" -i[ip ] Socket server ip address\n");
printf(" -p[port ] Socket server port address\n");
printf(" -h[help ] Display this help information\n");
printf("\nExample: %s -b -i 192.168.1.2 -p 12345\n", progname);
return ;
}
/*获取时间函数*/
int get_time(char *tim)
{
time_t time_val,time_mk;
struct tm *time_gm,*time_local;
time(&time_val);
//printf("raw time is:%lds\n",time_val);
time_gm=gmtime(&time_val);
sprintf(tim,"\tdate:%04d/%02d/%02d,time:%02d:%02d:%02d",time_gm->tm_year+1900,time_gm->tm_mon+1,time_gm->tm_mday,time_gm->tm_hour,time_gm->tm_min,time_gm->tm_sec);
return 0;
}
/*DS18B20获取温度*/
int get_temperature(float *temp)
{
char w1_path[50]="/sys/bus/w1/devices/";
char f_name[50];
char buf[128];
char *data_p=NULL;
struct dirent *file=NULL;
DIR *dir=NULL;
int data_fd;
int found = -1;
if((dir=opendir(w1_path))<0)
{
printf("open w1_path failure:%s\n",strerror(errno));
return -1;
}
while((file=readdir(dir))!=NULL)
{
if(strstr(file->d_name,"28-"))
{
strncpy(f_name,file->d_name,sizeof(f_name));
found=1;
}
}
closedir(dir);
if(!found)
{
printf("can not found the folder\n");
return 0;
}
strncat(w1_path, f_name, sizeof(w1_path)-strlen(w1_path));
strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path));
printf("folder path is %s\n",w1_path);
data_fd=open(w1_path,O_RDONLY);
if(data_fd<0)
{
printf("open file failure: %s\n",strerror(errno));
return -2;
}
memset(buf,0,sizeof(buf));
if(read(data_fd,buf,sizeof(buf))<0)
{
printf("read temperature from w1_path failure:%s\n",strerror(errno));
return -3;
}
data_p=strstr(buf, "t=");
data_p=data_p+2;
if(!data_p)
{
printf("can't get temperature :%s\n",strerror(errno));
return -4;
}
*temp=atof(data_p)/1000.0;
close(data_fd);
return 0;
}
void sig_handle(int signum)
{
printf("catch signal [%d]\n",signum);
g_stop=1;
}
int callback(void *notused,int argc,char **argv,char **name)
{
for(int i=0;i<argc;i++)
{
printf("%s=%s\n",name[i],argv[i]?argv[i]:"NULL");
}
printf("\n");
return 0;
}
/*下面是关于数据库的创建以及数据上报的实现代码*/
sqlite3 *db_connect(char *db_name)
{
int rc;
rc=sqlite3_open(db_name,&db);
if(rc!=SQLITE_OK)
{
printf("sql connect error:%s\n",strerror(errno));
}
else
{
printf("sql connect success\n");
}
return db;
}
void db_exec()
{
int rc;
char *error=0;
char *sql="CREATE TABLE IF NOT EXISTS TEMPERATURE(""ID INT PRIMARY KEY,"
"USER CHAR(20),"
"TIM CHAR(50),"
"TEMPERATURN CHAR(10));";
rc=sqlite3_exec(db,sql,callback,NULL,&error);
if(rc!=SQLITE_OK)
{
printf("sql exec fail:%s\n",strerror(errno));
sqlite3_close(db);
sqlite3_free(error);
exit(1);
}
else
{
printf("sql exec success\n");
}
}
void db_insert()
{
int rc;
char *error;
char tim[32];
char *user="yanpan";
float temp;
char *sql=(char *)malloc(256);
get_time(tim);
get_temperature(&temp);
snprintf(sql,256,"insert into TEMPERATURE(USER,TIM,TEMPERATURN)values('%s','%s','%f');",user,tim,temp);
rc=sqlite3_exec(db,sql,callback,NULL,&error);
if(rc!=SQLITE_OK)
{
printf("insert error:%s\n",strerror(errno));
sqlite3_close(db);
sqlite3_free(error);
exit(1);
}
else
{
printf("insert successfully!\n");
}
}
void db_select()
{
int rc;
char *error;
char *strsql="select * from TEMPERATURE;";
rc=sqlite3_exec(db,strsql,callback,NULL,&error);
if(rc!=SQLITE_OK)
{
printf("select failure:%s",strerror(errno));
sqlite3_close(db);
sqlite3_free(error);
exit(1);
}
else
{
printf("select successful\n");
}
运行结果如下:
在这里插入图片描述
数据库查看结果