树莓派加上温度传感器实现室内温度监控。可用于家庭,轿车,工业,农业 等许多方面。可做温度预警,自动降温等操作。各位小伙伴可自行脑补发挥。
1.硬件准备
a.树莓派(Raspberry Pi)一个
b.DS18B20温度传感器一个
c.4.7kΩ电阻一个 或 DS18B20模块一个
d.杜邦线(双头母)
2.软件准备
a.sqlite3数据库
b.socket编程
c.多路复用编程
d.json数据传输格式
3.流程图**
**
服务器程序主要源码
int main(int argc, char **argv)
{ int listenfd, connfd;
int serv_port = 0;
int daemon_run = 0;
int opt;
fd_set rdset;
int rv;
int i, j;
int found;
int maxfd=0;
int time = 1;
char buf[1024];
int fds_array[1024];
int flag = 0;
char *progname = basename(argv[0]);
struct timeval t1;
char *zErrMsg =NULL;
t1.tv_usec = 10;
t1.tv_sec = 0;
cJSON *json,*json1,*json2,*json3;
struct option long_options[] = {
{"daemon", no_argument, NULL, 'b'},
{"port", required_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
{"time",no_argument,NULL,'t'}
};
sqlite3 *db = NULL;
int leni = 0;
int len = sqlite3_open("ds18b20",&db);
char *pazResult =NULL;
if( len )
{
/* fprintf鍑芥暟鏍煎紡鍖栬緭鍑洪敊璇俊鎭埌鎸囧畾鐨剆tderr鏂囦欢娴佷腑 */
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));//sqlite3_errmsg(db)鐢ㄤ互鑾峰緱鏁版嵁搴撴墦寮€閿欒鐮佺殑鑻辨枃鎻忚堪銆?
sqlite3_close(db);
}
else printf("You have opened a sqlite3 database named user successfully!\n");
char *sql = " CREATE TABLE liu(\
ID VARCHAR(12) PRIMARY KEY NOT NULL,\
Time VARCHAR(12),\
Temp VARCHAR(14) DEFAULT 0\
);";
printf("1\n");
sqlite3_exec(db,sql,NULL,NULL,&zErrMsg);
printf("%s\n",zErrMsg);
sqlite3_free(zErrMsg);
progname = basename(argv[0]);
/* Parser the command line parameters */
while ((opt = getopt_long(argc, argv, "bp:ht:", long_options, NULL)) != -1)
{
switch (opt)
{
case 'b': daemon_run=1;
break;
case 'p': serv_port = atoi(optarg);
break;
case 't': time = atoi(optarg);
break;
case 'h': /* Get help information */
print_usage(progname);
return EXIT_SUCCESS; default: break;
}
}
if( !serv_port )
{
print_usage(progname);
return -1;
}
if( (listenfd=socket_server_init(NULL, serv_port)) < 0 )
{
printf("ERROR: %s server listen on port %d failure\n", argv[0],serv_port);
return -2;
}
printf("%s server start to listen on port %d\n", argv[0],serv_port);
/* set program running on background */
if( daemon_run )
{
daemon(1, 1);
}
openlog("server", LOG_CONS | LOG_PID, 0);
for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
{
fds_array[i]=-1;
}
syslog(LOG_NOTICE, "Program '%s'start running\n", progname);
fds_array[0] = listenfd;
for ( ; ; )
{
FD_ZERO(&rdset);
for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
{
if( fds_array[i] < 0 )
continue;
maxfd = fds_array[i]>maxfd ? fds_array[i] : maxfd;
FD_SET(fds_array[i], &rdset);
}
/* program will blocked here */
rv = select(maxfd+1, &rdset, NULL, NULL, &t1);
if(rv < 0)
{
printf("select failure: %s\n", strerror(errno));
break;
}
else if(rv == 0)
{
// printf("select get timeout\n");
continue;
}
/* listen socket get event means new client start connect now */
if ( FD_ISSET(listenfd, &rdset) )
{
if( (connfd=accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
{
printf("accept new client failure: %s\n", strerror(errno));
flag = 0;
continue;
}
found = 0;
for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
{
if( fds_array[i] < 0 )
{
printf("accept new client[%d] and add it into array\n", connfd );
fds_array[i] = connfd;
found = 1;
break;
}
}
if( !found )
{
printf("accept new client[%d] but full, so refuse it\n", connfd);
close(connfd);
}
}
else /* data arrive from already connected client */
{
for(i=0; i<ARRAY_SIZE(fds_array); i++)
{
if( fds_array[i]<0 || !FD_ISSET(fds_array[i], &rdset) )
continue;
if( (rv=read(fds_array[i], buf, sizeof(buf))) <= 0)
{
printf("socket[%d] read failure or get disconncet.\n", fds_array[i]);
close(fds_array[i]);
fds_array[i] = -1;
}
else
{
flag = 1;
sleep(time);
printf("socket[%d] read get %d bytes data\n", fds_array[i], rv);
printf("%s\n",buf);
json = cJSON_Parse(buf); //瑙f瀽鎴恓son褰㈠紡
json1 = cJSON_GetObjectItem( json , "ID" ); //鑾峰彇閿€煎唴瀹?
json2 = cJSON_GetObjectItem( json , "Time" );
json3 = cJSON_GetObjectItem( json , "Temporary" );
printf("ID:%s,Time:%s,Temporary:%s\n",json1->valuestring,json2->valuestring,json3->valuestring);
/*鎻掑叆鏁版嵁 */
char sql1[100]="\"INSERT INTO 'liu'VALUES(10,2,201430506201);\"";
snprintf(sql1,100,"INSERT INTO 'liu'VALUES(\"%s\",\"%s\",\"%s\");",json1->valuestring,json2->valuestring,json3->valuestring);
printf("%s\n",sql1);
sqlite3_exec(db,sql1,NULL,NULL,&zErrMsg);
/* if(zErrMsg != NULL)
{
sqlite3_free(zErrMsg);
zErrMsg = NULL;
} */
/* convert letter from lowercase to uppercase */
for(j=0; j<rv; j++)
buf[j]=toupper(buf[j]);
syslog(LOG_NOTICE, "%s\n", buf);
if( write(fds_array[i], buf, rv) < 0 )
{
printf("socket[%d] write failure: %s\n", fds_array[i], strerror(errno));
close(fds_array[i]);
fds_array[i] = -1;
}
}
}
}
}
syslog(LOG_NOTICE, "Program '%s' stop running\n", progname);
closelog();
CleanUp:
close(listenfd);
return 0;
}
客户端程序
int main(int argc, char *argv[])
{
struct tm *t;
time_t tt;
char buf[100];
float temp = 0;
char path[100] = "/sys/bus/w1/devices/";
int ch;
char ip[20];
int dy_time;
int flag=0;
int daemon_flag = 0;
int daemon1;
struct option opts[] = {
{"ip", required_argument, NULL, 'i'},
{"dy_time", required_argument, NULL, 't'},
{"daemon1", no_argument,NULL,'d'},
{NULL, 0, NULL, 0}
};
time(&tt);
t = localtime(&tt);
memset(buf, 0, sizeof(buf));
memset(ip,0,sizeof(ip));
while( (ch=getopt_long(argc, argv, "i:t:d", opts, NULL)) != -1 )
{ switch(ch)
{
case 'i': strcpy(ip, optarg);
break;
case 't':
dy_time = atoi(optarg);
break;
case 'd': daemon_flag = 1;
break;
}
}
if(daemon_flag)
{
daemon(1,1);
}
printf("%s,%d",ip,dy_time);
temp = Get_temp(path);
sprintf(buf,"{\"ID\":\"RP10001\",\"Time\":\"%d-%d-%d %02d:%02d:%02d\",\"Temporary\":\"%f\"}"
,t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,temp);
printf("%s\n",buf);
while(1)
{
if((Init_socket(ip)) < 0)
{
printf("connect to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
continue;
}
if(conn_fd >0)
{
if( write(conn_fd, buf, strlen(buf)) < 0 )
{
printf("Write data to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
goto cleanup;
}
}
}
cleanup:
close(conn_fd);
return 0;
}
总结
本次项目学习了socket编程,多路复用,json数据格式,sqlite3数据库与c的搭配使用。接下来希望能够实现可视化界面。