功能描述
- 实现安卓App对外设的控制,如灯光、人脸识别开启等。
- App上能显示监控视频内容、显示温湿度、是否发生火灾等。
- 守护进程,保证不退出;树莓派开机自启等。
硬件图

项目整体思路
- 项目代码规范:整体采用工厂模式去对项目进行开发;主要分为指令工厂和设备工厂。
- 使用树莓派作为主控。
- 使用守护进程udev去守护智能家居进程(防止程序意外),实现系统上电就能启动项目,不需要手动运行。
- 基于祥云平台OCR + 树莓派摄像头实现的人脸识别。
- 基于Java 去开发安卓App。
- 使用Socket 网络通信,实现App 控制外设。
代码如下
守护进程:
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
static bool flag = true;
void handler(int sig)
{
printf("I got a signal %d\nI'm quitting.\n", sig);
flag = false;
}
int judMent()
{
FILE *file;
char buffer[128] = {'\0'};
char *cmd = "ps -elf |grep SmartHome|grep -v grep";
file = popen(cmd, "r");
fgets(buffer, 128, file);
if(strstr(buffer, "SmartHome") != NULL){
return 0;
}else{
return -1;
}
printf("BUFFER:%s\n",buffer);
}
int main()
{
time_t t;
int fd;
//创建守护进程
if(-1 == daemon(0, 0)){
printf("daemon error\n");
exit(1);
}
//设置信号处理函数
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGQUIT, &act, NULL)){
printf("sigaction error.\n");
exit(0);
}
sleep(30);
//进程工作内容
while(flag){
if( judMent() == -1){
system("/home/pi/SmartHome &");
}
sleep(5);
}
return 0;
}
人脸识别:(Camera.c)
#include "contrlDevices.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
void postUrl();
size_t readData1(void *ptr, size_t size, size_t nmemb, void *stream);
char* getFace1();
char* getPicFromOCRBase641(char *Filepath);
struct Devices* addcameraToDeviceLink(struct Devices *phead);
int cameraInit(int pinNum);
char ocrRetBuf[1024] = {'\0'};
size_t readData1(void *ptr, size_t size, size_t nmemb, void *stream)
//回调函数,把从后台的数据拷贝给ocrRetBuf
{
strncpy(ocrRetBuf,ptr,1024);//ocrRetBuf接收从OCR后台返回的数据,并打印
printf("%s\n",ocrRetBuf);
}
char* getFace1()
{
printf("pai zhao zhong\n");
//system("raspistill -q 5 -t 1 -o image.jpg");
system("wget http://192.168.101.223:8080/?action=snapshot -O ./image.jpg ");
while(access("./image.jpg",F_OK) != 0); //判断是否拍照完毕
printf("paizhao wanbi\n");
char* base64BufFaceRec = getPicFromOCRBase641("./image.jpg");
//system("rm image.jpg");
return base64BufFaceRec; //返回刚才拍照的base64
}
char *getPicFromOCRBase641(char *Filepath)
{
int fd;
int filelen;
char cmd[128]={'\0'};
sprintf(cmd,"base64 %s > tmpFile",Filepath);
system(cmd);
fd=open("./tmpFile",O_RDWR);
filelen=lseek(fd,0,SEEK_END);//计算文件大小
lseek(fd,0,SEEK_SET); //移动光标到头
char *bufpic=(char *)malloc(filelen+2);
memset(bufpic,'\0',filelen+2);
read(fd,bufpic,filelen+128); //把内容读到bufpic内
system("rm -rf tmpFile");//删除这个临时文件
close(fd);
return bufpic; //返回bufpic这个地址
}
void postUrl()
{
CURL *curl;
CURLcode res;
char* key = "5xxxsWxxxGfP2pmxxxchSJ"; //翔云平台购买人脸识别后的key
char* secret = "396xxxd33xxx487exxxf139axxx6d789"; //翔云平台购买人脸识别后的secret
int typeId = 21;
char* format = "xml";
char* base64BufPic1 = getFace1();
char* base64BufPic2 = getPicFromOCRBase641("lit1.jpg");
int len = strlen(key)+strlen(secret)+strlen(base64BufPic1)+strlen(base64BufPic2)+128;
char* postString = (char* )malloc(len);
memset(postString,'\0',len);
sprintf(postString,"img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",base64BufPic1,base64BufPic2,key,secret,typeId,format);//根据平台的传参格式编写
curl = curl_easy_init();
if(curl){
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString); //指定post内容,传入参数
curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");// 指定url
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,readData1); //回调函数readDate读取返回值
res = curl_easy_perform(curl);
printf("OK:%d\n",res);
if(strstr(ocrRetBuf,"是") != NULL){ //判断翔云后台返回的字符串中有没有“是”
printf("是同一个人\n");
// 这里可以开锁,上锁的操作
}
else{
printf("不是同一个人\n");
}
curl_easy_cleanup(curl);
}
}
int cameraInit(int pinNum)//该函数无用
{
pinMode(0,OUTPUT);
digitalWrite(0,HIGH);
}
struct Devices camera = {
.deviceName = "camera",
.deviceInit = cameraInit,
.pinNum = 0, //此引脚号无用
.justDoOnce = postUrl,
.getFace = getFace1,
.getPicFromOCRBase64 = getPicFromOCRBase641,
.readData = readData1
};
struct Devices* addcameraToDeviceLink(struct Devices *phead)
{
if(phead == NULL){
return &camera;
}
else{
camera.next = phead;
phead = &camera;
}
}
了解到门锁的玩法,低电平 LOW开锁,HIGH:上锁,暂时不打算买这个硬件了哈,这里的思路已经调通了的。



APP端展示
- 显示温湿度,视频监控
- 按键控制灯、人脸识别开启
视频监控脚本 (start_web_video.sh)
cd ../mjpg-streamer/mjpg-streamer-experimental/
./mjpg_streamer -i "./input_raspicam.so" -o "./output_http.so -w ./www"
注意: 写好脚本后,记得给该脚本文件加上可执行权限。

app控制外设
该博客介绍了智能家居项目,基于Java开发安卓App实现对外设控制,如灯光、人脸识别开启等,还能显示监控视频、温湿度等信息。采用工厂模式开发,用树莓派为主控,通过守护进程保证程序不退出,使用Socket网络通信实现App与外设交互。
2023

被折叠的 条评论
为什么被折叠?



