智能家居系统
1.项目背景
本项目所完成的是一个智能家居系统,使用Linux操作系统搭建的远程网络视频监控系统的解决方案。着重于实现一个易搭建,易配置,通用性好,能用于临时性监控的网络视频服务器,可以让客户机实时监控远程目标摄像头,实时共享摄像头控制空调、热水器、窗帘等家居智能设备。
智能家居系统让您轻松享受生活。出门在外,您可以通过电话、电脑来远程遥控您的家居各智能系统,例如在回家的路上提前打开家中的空调和热水器;到家开门时,借助门磁或红外传感器,系统会自动打开过道灯,同时打开电子门锁,安防撤防,开启家中的照明灯具和窗帘迎接您的归来;回到家里,使用遥控器您可以方便地控制房间内各种电器设备。
2.硬件说明
本系统采用ARM Cortex-A94-Core核心板和Ubuntu环境开发
开发语言为C语言
(1)温湿度传感器
温湿度传感器可以将采集到的温度实时转换成输出信号,并在终端上显示,当室内温度超过闹值或湿度不在设定范国内,会通过度异常信息。
(2)蜂鸣器
当室内的温度达到火灾值,或有人非法进入时,系统会自动发出报警声。
(3)USB摄像头
网络远程监控摄像头,进行监控并将监视画面录制下来,可实时将影像透过网络传给用户终端,使用户能够随时随地观察家里的情况。
(4)LED 显示电器是否处于工作中
(5)电位器(pm_2.5)
(6)远程终端
由Qt制作的用户界面,来显示实时监控画面、温度数据、PM_2.5数据以及空调、热水器、窗帘控制按键、并且具有异常警报按钮。
3.系统软件设计
(1)系统模块组织
(2)系统模块说明
1系统初始化
对整个系统进行配置及初始化。
2实时监控子系统
系统的实时监控和处理。
A)室内温度监控
B)室内PM_2.5指数监控
C)室内视频监控
3远程服务子系统
A)数据显示请求
B)远程控制
(3)终端软件系统模块设计
(4)软件模块设计说明
主界面
包含:实时温度显示、视频获取、远程家具控制和报警。
4.系统流程
(1)Liunx配置
tftp配置 (文件服务器,传输文件)
$ sudo vi /etc/default/tftpd-hpa
TFTP_USERNAME=“tftp”
TFTP_DIRECTORY="/home/farsight/linux/tftpboot" //指定tftp的共享目录
TFTP_ADDRESS=“0.0.0.0:69” //任意主机都可以通信
TFTP_OPTIONS="-l -c -s" //-c表示可以创建文件,默认情况下tftp只允许覆盖原文件,不能创建新
文件;-s表示只能在tftp指定的共享目录进行上传和下载,增加安全性;
TFTP_DIRECTORY修改tftpboot的服务器目录所在路径(可改)
在/home/farsight/linux目录下,创建文件夹tftpboot,修改文件夹权限为777
启动tftp服务器
sudo /etc/init.d/tftpd-hpa restart;
sudo service tftp-hpa restart
(2)nfs配置
(网络文件系统,将PC机上的目录共享给开发板使用
安装nfs服务器端
安装nfs服务器端
sudo apt-get install nfs-kernel-server
步骤
创建一个目录作为nfs共享目录
$ sudo mkdir /home/nfs
$ chmod 0777 /home/nfs
配置nfs资源
$ sudo vi /etc/exports 添加
/home/board/nfs/ *(rw,sync,no_root_squash,no_subtree_check) //rw表示读写;sync表示
同步;no_root_squash表示登录 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分
享的目录来说,他就具有 root 的权限;no_subtree_check不检查子目录
启动/停止NFS服务器
$ sudo /etc/init.d/nfs-kernel-server restart 重启服务
$ sudo /etc/init.d/nfs-kernel-server stop 停止服务
查看NFS服务器的共享资源
$ showmount -e 192.168.1.10(虚拟机ip) 也可以使用localhost来替换ip地址
挂载共享目录
$ sudo mkdir /mnt/nfs
$ sudo chmod /mnt/nfs 0777 // /mnt/nfs/表示挂载目录,权限改为777
$ sudo mount -t nfs 192.168.1.10:/home/board/nfs /mnt/nfs/ //-t指明类型
这时,在/mnt/nfs/下新建一个文件,abc.txt,在/home/board/nfs/下也可以看到这个文件
在/home/board/nfs/下新建一个文件,hello.c, 在/mnt/nfs下也可以看到这个文件
注意:挂载点必须是一个存在的目录 ,这个目录 以不为空,但,挂载后这个目录下以前的内容将不可用,
umount以后会恢复正常。在linux中如果你要使用储存设备(如:U盘、硬盘、光驱),就得先将它挂载
(mount),然后才能把存储设备当作一个目录进行访问。
卸载共享资源
$ sudo umount -f /mnt/nfs/(-f表示强制卸载)
(3)网络配置
虚拟机->设置->网络适配器->自定义->VMnet0->确定
编辑->虚拟网络编辑器->更改设置->VMnet0->桥接模式->Realetk PCLe GBE family
Controller
(4)Putty挂载
设置启动环境变量
ubuntu -> 192.168.0.116
ARM -> 192.168.0.120
setenv serverip 192.168.0.116;
setenv ipaddr 192.168.0.120
setenv bootcmd tftp 41000000 uImage;tftp 42000000 exynos4412-fs4412.dtb;bootm
41000000 - 42000000
setenv bootargs root=/dev/nfs
nfsroot=192.168.0.116:/home/farsight/Documents/board/nfs/rootfs rw
console=ttySAC2,115200 init=/linuxrc ip=192.168.0.120
5.前端设计
连接:连接到Putty,连通开发板
关闭:断开Putty
温度:连通后,实时显示温度
PM2.5:连通后,实时显示PM2.5值
紧急开关:报警器打开,颜色变红;报警器关闭,颜色变绿
空调:点击后,LED2亮,再次点击,LED2关闭
窗帘:点击后,LED3亮,再次点击,LED3关闭
热水器点击后,LED4亮,再次点击,LED4关闭
报警器:点击后,蜂鸣器响,再次点击,蜂鸣器停止响
6.代码
获取温湿度
int tempProcess()
{
char rbuf[6]="";
char chline=' ';
int i=0;
if (tempFd < 0)
return 0;
while(1)
{
//读取温度
lseek(tempFd,0,SEEK_SET);
while(chline != '\n')
{
read(tempFd,&chline,1);
i++;
}
while(chline != '=')
{
read(tempFd,&chline,1);
i++;
}
read(tempFd,rbuf,sizeof(rbuf));
rbuf[5]='\0';
i=0;
if (NULL == jpg)
continue;
pthread_mutex_lock(&jpg_mutex);
while(rbuf[i]!= '\0')
{
jpg->tp[i]=rbuf[i];
i++;
}
pthread_mutex_unlock(&jpg_mutex);
//printf("%s,%c\n",jpg->tp,jpg->btn);
}
return 0;
}
蜂鸣器
int tempProcess()
{
char rbuf[6]="";
char chline=' ';
int i=0;
if (tempFd < 0)
return 0;
while(1)
{
//读取温度
lseek(tempFd,0,SEEK_SET);
while(chline != '\n')
{
read(tempFd,&chline,1);
i++;
}
while(chline != '=')
{
read(tempFd,&chline,1);
i++;
}
read(tempFd,rbuf,sizeof(rbuf));
rbuf[5]='\0';
i=0;
if (NULL == jpg)
continue;
pthread_mutex_lock(&jpg_mutex);
while(rbuf[i]!= '\0')
{
jpg->tp[i]=rbuf[i];
i++;
}
pthread_mutex_unlock(&jpg_mutex);
//printf("%s,%c\n",jpg->tp,jpg->btn);
}
return 0;
}
LED灯
int ledProcess(int ledNum, int cmd)
{
if (ledFd < 0 || ledNum > 3 || cmd > 1 || cmd < 0)
return -1;
if (AIRCONDITION == ledNum)
{
if (1 == cmd || !isAirConditionOn)
{
printf("open airCondition led0\r\n");
ioctl(ledFd, LED_ON, 0);
isAirConditionOn = TRUE;
}
else
{
printf("close airCondition led0\r\n");
ioctl(ledFd, LED_OFF, 0);
isAirConditionOn = FALSE;
}
}
else if (CURTAIN == ledNum)
{
if (1 == cmd || !isCurtainOn)
{
printf("open Curtain led1\r\n");
ioctl(ledFd, LED_ON, 1);
isCurtainOn = TRUE;
}
else
{
printf("close Curtain led1\r\n");
ioctl(ledFd, LED_OFF, 1);
isCurtainOn = FALSE;
}
}
else if (WATERHEATER == ledNum)
{
if (1 == cmd || !isCurtainOn)
{
printf("open Curtain led1\r\n");
ioctl(ledFd, LED_ON, 2);
isCurtainOn = TRUE;
}
else
{
printf("close Curtain led1\r\n");
ioctl(ledFd, LED_OFF, 2);
isCurtainOn = FALSE;
}
}
else //if (WATERHEATER == ledNum)
{
if (1 == cmd || !isCurtainOn)
{
printf("open Curtain led1\r\n");
ioctl(ledFd, LED_ON, 3);
isCurtainOn = TRUE;
}
else
{
printf("close Curtain led1\r\n");
ioctl(ledFd, LED_OFF, 3);
isCurtainOn = FALSE;
}
}
return 0;
}
PM2.5
int adcProcess()
{
if( 0 > adcFd)
return -1;
int adcValue = 0;
while(1)
{
if (0 > ioctl(adcFd, ADC_CMD_GET, &adcValue))
printf("ioctl adc get failed\n");
//else
//printf("the temp value is: %d\n", adcValue);
//将adcValue转成0~500的数
adcValue = adcValue * 5 / 100;
if (!jpg)
continue;
//将adcValue转成一个字符串
pthread_mutex_lock(&jpg_mutex);
sprintf(jpg->pm2_5, "%d", adcValue);
pthread_mutex_unlock(&jpg_mutex);
//printf("%s,%c\n",jpg->tp,jpg->btn);
}
return 0;
}
按键处理
tatic void sig_handler(int signo)
{
if(signo==SIGIO) {
read(btnFd, &keyID, sizeof(keyID));
printf("key%d pressed\n", keyID);
if (WATERHEATER == keyID)
{
ledProcess(2, 0);
}
else if (3 == keyID)
{
ledProcess(3, 0);
}
else
{
pwmProcess(0);
}
}
}
int keyProcess()
{
signal(SIGIO, sig_handler);
fcntl(btnFd, F_SETOWN, getpid());
fcntl(btnFd, F_SETFL, fcntl(btnFd, F_GETFL) | FASYNC);
while(1);
return 0;
}
客户端
#define MAX_BACKLOG 1024
int tcp_server_init(const char *ip, const char *port)
{
int ret;
int listenfd;
int opt = 1;
struct sockaddr_in srvaddr;
memset(&srvaddr, 0, sizeof(struct sockaddr_in));
srvaddr.sin_family = AF_INET;
if (ip != NULL) {
ret = inet_pton(AF_INET, ip, &srvaddr.sin_addr);
if (ret != 1) {
fprintf(stderr, "server->ip: ip is error\n");
return -1;
}
} else
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (port != NULL)
srvaddr.sin_port = htons(atoi(port));
else {
fprintf(stderr, "server->port: port must be assigned\n");
return -1;
}
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
perror("server->socket");
return -1;
}
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
ret = bind(listenfd, (struct sockaddr *)&srvaddr, sizeof(struct sockaddr_in));
if (ret == -1) {
perror("server->bind");
close(listenfd);
return -1;
}
ret = listen(listenfd, MAX_BACKLOG);
if (ret == -1) {
perror("server->listen");
close(listenfd);
return -1;
}
return listenfd;
}
int tcp_server_wait_connect(int listenfd)
{
int connfd;
socklen_t addrlen;
struct sockaddr_in cliaddr;
addrlen = sizeof(struct sockaddr_in);
memset(&cliaddr, 0, sizeof(struct sockaddr_in));
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &addrlen);
if (connfd == -1) {
perror("server->accept");
return -1;
}
return connfd;
}
ssize_t tcp_server_recv(int connfd, void *buf, size_t count)
{
ssize_t ret;
assert(buf != NULL);
ret = read(connfd, buf, count);
if (ret == -1) {
perror("server->read");
return -1;
} else if (ret == 0) {
fprintf(stderr, "server->read: end-of-file\n");
return 0;
} else
return ret;
}
ssize_t tcp_server_send(int connfd, const void *buf, size_t count)
{
ssize_t ret;
assert(buf != NULL);
ret = write(connfd, buf, count);
if (ret == -1) {
perror("server->read");
return -1;
} else
return ret;
}
ssize_t tcp_server_recv_exact_nbytes(int connfd, void *buf, size_t count)
{
ssize_t ret;
ssize_t total = 0;
assert(buf != NULL);
while (total != count) {
ret = read(connfd, buf + total, count - total);
if (ret == -1) {
perror("server->read");
return -1;
} else if (ret == 0) {
fprintf(stderr, "server->read: end-of-file\n");
return total;
} else
total += ret;
}
return total;
}
ssize_t tcp_server_send_exact_nbytes(int connfd, const void *buf, size_t count)
{
ssize_t ret;
ssize_t total = 0;
assert(buf != NULL);
while (total != count) {
ret = write(connfd, buf + total, count - total);
if (ret == -1) {
perror("server->write");
return total;
} else
total += ret;
}
return total;
}
int tcp_server_disconnect(int connfd)
{
if (close(connfd)) {
perror("server->close");
return -1;
}
return 0;
}
int tcp_server_exit(int listenfd)
{
if (close(listenfd)) {
perror("server->close");
return -1;
}
return 0;
}
int tcp_client_init(void)
{
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("client->socket");
return -1;
}
return sockfd;
}
int tcp_client_connect(int sockfd, const char *ip, const char *port)
{
int ret;
struct sockaddr_in srvaddr;
memset(&srvaddr, 0, sizeof(struct sockaddr_in));
srvaddr.sin_family = AF_INET;
if (ip != NULL) {
ret = inet_pton(AF_INET, ip, &srvaddr.sin_addr);
if (ret != 1) {
fprintf(stderr, "client->ip: server ip is error\n");
return -1;
}
} else
fprintf(stderr, "client->ip: server ip must be assigned\n");
if (port != NULL)
srvaddr.sin_port = htons(atoi(port));
else {
fprintf(stderr, "client->port: server port must be assigned\n");
return -1;
}
ret = connect(sockfd, (struct sockaddr *)&srvaddr, sizeof(struct sockaddr_in));
if (ret == -1) {
perror("client->connect");
return -1;
}
return 0;
}
ssize_t tcp_client_recv(int sockfd, void *buf, size_t count)
{
ssize_t ret;
assert(buf != NULL);
ret = read(sockfd, buf, count);
if (ret == -1) {
perror("server->read");
return -1;
} else if (ret == 0) {
fprintf(stderr, "server->read: end-of-file\n");
return 0;
} else
return ret;
}
ssize_t tcp_client_send(int sockfd, const void *buf, size_t count)
{
ssize_t ret;
assert(buf != NULL);
ret = write(sockfd, buf, count);
if (ret == -1) {
perror("server->read");
return -1;
} else
return ret;
}
ssize_t tcp_client_recv_exact_nbytes(int sockfd, void *buf, size_t count)
{
ssize_t ret;
ssize_t total = 0;
assert(buf != NULL);
while (total != count) {
ret = read(sockfd, buf + total, count - total);
if (ret == -1) {
perror("server->read");
return -1;
} else if (ret == 0) {
fprintf(stderr, "server->read: end-of-file\n");
return total;
} else
total += ret;
}
return total;
}
ssize_t tcp_client_send_exact_nbytes(int sockfd, const void *buf, size_t count)
{
ssize_t ret;
ssize_t total = 0;
assert(buf != NULL);
while (total != count) {
ret = write(sockfd, buf + total, count - total);
if (ret == -1) {
perror("server->read");
return total;
} else
total += ret;
}
return total;
}
int tcp_client_exit(int sockfd)
{
if (close(sockfd)) {
perror("client->close");
return -1;
}
return 0;
}
服务器端
define REQ_DATA_SIZE 32
#define HDR_DATA_SIZE 128
//#define DEBUG
#define CMDLEN 6
extern pthread_mutex_t jpg_mutex;
int processClientCmd(int connfd)
{
//¶ÁÈ¡¿Í»§¶Ë·¢ÀŽµÄÃüÁî
int ret = 0;
char cmd[CMDLEN] = {0};
while (ret < CMDLEN - 1)
{
int tmp = recv(connfd, cmd+ret, CMDLEN - 1 - ret, 0);
if (tmp < 0)
{
perror("recv cmd error");
return -1;
}
else if (0 == tmp)
{
break;
}
ret += tmp;
//int i = 0;
//for (i = 0; i < ret; i++)
//printf("recv: %d ret=%d \r\n", cmd[i],tmp);
}
//printf("recv: %s\r\n", cmd);
//ŽŠÀíÃüÁî
if (cmd[1] < PWM_ID)
{
ledProcess(cmd[1], cmd[2]);
}
else if (cmd[1] == PWM_ID)
{
pwmProcess(cmd[2]);
}
return 0;
}
//int client_process(int connfd, struct jpg_buf_t *jpg)
int client_process(int connfd)
{
/*int ret;
char request[REQ_DATA_SIZE] = {0};
char response[HDR_ DATA_SIZE] = {0};
memset(request, 0, sizeof(request));
ret = tcp_server_recv(connfd, request, sizeof(request));
if (ret <= 0)
return -1;
#ifdef DEBUG
fprintf(stdout, "server->read: the request is\n%s\n", request);
#endif
if (strstr(request, "pic") != NULL) {
int ret;
pthread_mutex_lock(&jpg_mutex);
snprintf(response, sizeof(response), "%dlen", jpg->len);
#ifdef DEBUG
fprintf(stdout, "server->response: the response is: %s\n", response);
#endif
ret = tcp_server_send_exact_nbytes(connfd, response, sizeof(response));
if (ret != sizeof(response)) {
fprintf(stderr, "server->write: send response failed\n");
return -1;
}
ret = tcp_server_send_exact_nbytes(connfd, jpg->buf, jpg->len);
if (ret != jpg->len) {
fprintf(stderr, "server->write: send response failed\n");
return -1;
}
pthread_mutex_unlock(&jpg_mutex);
}
return 0;*/
unsigned int piclen = 0;
unsigned char * buf ;
char response[20] = "";
char msg[3] = {0};
int total = 0;
int ret1 = 0;
if (NULL == jpg)
{
printf("jpg has no memory alloc\r\n");
jpg = (struct jpg_buf_t *)malloc(sizeof(struct jpg_buf_t));
if (!jpg) {
perror("malloc");
exit(EXIT_FAILURE);
}
memset(jpg, 0, sizeof(struct jpg_buf_t));
}
ret1 = read(connfd,msg,3);
printf("msg : %s\n",msg);//ÕâÀïœÓÊÕµœµÄÊÇpic£¬²»ÐèÒª×öÑéÖ€
if (strcmp(msg, "cmd") == 0)
{
return processClientCmd(connfd);
}
pthread_mutex_lock(&jpg_mutex);
piclen = jpg->len;
snprintf(response, sizeof(response), "%d#", piclen);//add length into response
strcat(response,jpg->tp);// add tp to response
strcat(response,"#");
if ('A' == jpg->btn){//add btn to response
strcat(response,"A");
}
else{
strcat(response,"B");
}
strcat(response, "#");
strcat(response, jpg->pm2_5);
buf = (unsigned char *)malloc(piclen);
memset(buf,0,piclen);
memcpy(buf,jpg->buf,piclen);
pthread_mutex_unlock(&jpg_mutex);
ret1 = write(connfd,response,20);
printf("ret = %d response = %s\n",ret1,response);
while(piclen>total)
{
ret1 = write(connfd,buf+total,piclen-total);
if(ret1 < 0)
{
break;
}
total += ret1;
//printf("total = %d\n",total);
}
return 0;
}