简单介绍
通过语音和网络的方式控制灯光的开关;并设置火灾报警装置,智能门锁通过翔云人脸识别进行判断,与通过红外设备控制智能家电;
设计思路
指令工厂
commandFactory
#include <wiringPi.h>
#include <stdlib.h>
struct InputCommander
{
char commandName[128]; //设备名
char deviceName[128]; //语音通过串口发送,这边是/dev/ttyAMA0
char command[48];//命令
int baud;//波特率
int (*init)(struct InputCommander *InputCommander); //初始化函数
int (*getCommand)(struct InputCommander *cmd); //获取命令
char log[1024];
int fd; //句柄
char ipAdress[32]; //ip地址
char iPort[12]; //端口号
struct InputCommander *next; //通过结构体指针进行链表
};
struct InputCommander *voiceCommandToLink(struct InputCommander* phead);
struct InputCommander *socketCommandToLink(struct InputCommander* phead);
设备工厂
devicesFactory
#include <wiringPi.h>
#include <stdlib.h>
struct Devices
{
char devicesName[128]; //设备名称
int status; //设备状态
int pinNum; //引脚
int ret; //存放人脸识别结果
char localAmgAddress[32]; //人俩脸识别本地图片地址
int (*open)(int pinNum); //设备开管指令
int (*close)(int pinNum);
int (*devicesInit)(int pinNum); //初始化指令
int (*readStatus)(int pinNum); //当前引脚的状态
int (*changeStatus)(int status);
int (*postUrl)(struct Devices* Devices);//人脸识别post请求
struct Devices *next;
};
struct Devices *toiletLightToLink(struct Devices* phead);
struct Devices *secondFloorLightToLink(struct Devices* phead);
struct Devices *livingRoomLightToLink(struct Devices* phead);
struct Devices *restaurantLightToLink(struct Devices* phead);
struct Devices *fireToLink(struct Devices* phead);
struct Devices *cameraToLink(struct Devices* phead);
struct Devices *buzzerToLink(struct Devices* phead);
struct Devices *lockToLink(struct Devices* phead);
主程序
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "contrlDevices.h"
#include "inputCommand.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <wiringSerial.h>
#include <arpa/inet.h>
static struct InputCommander *cmdPhead = NULL;//main中的指令工厂
static struct Devices *devPhead = NULL;//main中的设备工厂
static struct InputCommander *socketHandeler;//为socket_thread的定义
static unsigned int c_fd; //存放需要accept返回句柄
//寻找设备
struct Devices *findDeviceByName(char *name,struct Devices *phead)
{
struct Devices *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(name,tmp->devicesName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
//寻找语音或网络
struct InputCommander *findCmmandByName(char *name,struct InputCommander *phead)
{
struct InputCommander *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(name,tmp->commandName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
//火灾线程
//如果发生火灾,输出低电平,未发生火灾输出高电平
void* fire_thread(void *data){
int status = 1;
struct Devices * fire;
struct Devices * buzzer;
//火灾模块初始化
fire = findDeviceByName("fire",devPhead);
fire->devicesInit(fire->pinNum);
//报警器初始化
buzzer = findDeviceByName("buzzer",devPhead);
buzzer->devicesInit(buzzer->pinNum);
buzzer->close(buzzer->pinNum);
while(1){
status = fire->readStatus(fire->pinNum);
printf("fire output data:%d\n",status);
if(status == 0){
buzzer->open(buzzer->pinNum);
printf("have fire\n");
sleep(5);
}
if(status == 1){
buzzer->close(buzzer->pinNum);
printf("no fire\n");
}
sleep(5);
}
}
//开启摄像头/人脸识别开锁
void* camera_thread(void *data){
//system("./home/pi/mjpg-streamer/mjpg-streamer-experimental/start.sh");
char cmd;
struct Devices * camera;
struct Devices * lock;
lock = findDeviceByName("lock",devPhead);
lock->devicesInit(lock->pinNum);
while(1){
//手动开锁,时间原因,未优化
printf("can you open door?:Y or N\n");
scanf("%s",&cmd);
getchar();
if(strcmp(&cmd,"Y") == 0){
camera = findDeviceByName("camera",devPhead);
camera->devicesInit(camera->pinNum);
camera->postUrl(camera);
if(camera->ret == 1){
lock->open(lock->pinNum);
sleep(5);
lock->close(lock->pinNum);
}
}
}
}
//语音回调函数
void* voice_thread(void *data)
{
int nread;
struct InputCommander *voiceHandeler;
struct Devices * dev;
voiceHandeler = findCmmandByName("voice",cmdPhead);
if(voiceHandeler == NULL){
printf("find voiceHandeler error\n");
pthread_exit(NULL);
}
if((voiceHandeler->init(voiceHandeler)) < 0){
printf("voice init fail\n");
serialClose (voiceHandeler->fd);
pthread_exit(NULL);
}
printf("%s voice_thread init success!\n",voiceHandeler->commandName);
while(serialDataAvail(voiceHandeler->fd) != -1){
nread = voiceHandeler->getCommand(voiceHandeler);
if(nread == 0)
printf("nodata from voice\n");
printf("voice read :%d,%s\n",nread,voiceHandeler->command);
if(strcmp(voiceHandeler->command,"A") == 0){
dev = findDeviceByName("toiletLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strcmp(voiceHandeler->command,"B") == 0){
dev = findDeviceByName("toiletLight",devPhead);
dev->close(dev->pinNum);
}
if(strcmp(voiceHandeler->command,"C") == 0){
dev = findDeviceByName("secondFloorLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strcmp(voiceHandeler->command,"D") == 0){
dev = findDeviceByName("secondFloorLight",devPhead);
dev->close(dev->pinNum);
}
if(strcmp(voiceHandeler->command,"E") == 0){
dev = findDeviceByName("restaurantLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strcmp(voiceHandeler->command,"F") == 0){
dev = findDeviceByName("restaurantLight",devPhead);
dev->close(dev->pinNum);
}
if(strcmp(voiceHandeler->command,"G") == 0){
dev = findDeviceByName("livingRoomLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strcmp(voiceHandeler->command,"H") == 0){
dev = findDeviceByName("livingRoomLight",devPhead);
dev->close(dev->pinNum);
}
if(strcmp(voiceHandeler->command,"I") == 0){
dev = findDeviceByName("toiletLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("livingRoomLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("restaurantLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("secondFloorLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strcmp(voiceHandeler->command,"J") == 0){
dev = findDeviceByName("toiletLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("livingRoomLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("restaurantLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("secondFloorLight",devPhead);
dev->close(dev->pinNum);
}
}
}
void* socket_read_thread(void *data)//读取客户端发送的指令
{
int n_read;
struct Devices * dev;
while(1){
memset(socketHandeler->command,'\0',sizeof(socketHandeler->command));
n_read = read(c_fd, socketHandeler->command, sizeof(socketHandeler->command));
if(n_read == 0){
printf("client quit!\n");
pthread_exit(NULL);
}else if(n_read < 0){
perror("socket read");
pthread_exit(NULL);
}
printf("socket read:%d, %s \n",n_read,socketHandeler->command);
if(strstr(socketHandeler->command,"kysd") != NULL){ //浴室灯
dev = findDeviceByName("toiletLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strstr(socketHandeler->command,"gysd") != NULL){
dev = findDeviceByName("toiletLight",devPhead);
dev->close(dev->pinNum);
}
if(strstr(socketHandeler->command,"kktd") != NULL){ //客厅灯
dev = findDeviceByName("livingRoomLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strstr(socketHandeler->command,"gktd") != NULL){
dev = findDeviceByName("livingRoomLight",devPhead);
dev->close(dev->pinNum);
}
if(strstr(socketHandeler->command,"kctd") != NULL){ //餐厅灯
dev = findDeviceByName("restaurantLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strstr(socketHandeler->command,"gctd") != NULL){
dev = findDeviceByName("restaurantLight",devPhead);
dev->close(dev->pinNum);
}
if(strstr(socketHandeler->command,"keld") != NULL){ //二楼灯
dev = findDeviceByName("secondFloorLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strstr(socketHandeler->command,"geld") != NULL){
dev = findDeviceByName("secondFloorLight",devPhead);
dev->close(dev->pinNum);
}
if(strstr(socketHandeler->command,"kqbd") != NULL){ //所有灯
dev = findDeviceByName("toiletLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("livingRoomLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("restaurantLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
dev = findDeviceByName("secondFloorLight",devPhead);
dev->devicesInit(dev->pinNum);
dev->open(dev->pinNum);
}else if(strstr(socketHandeler->command,"gqbd") != NULL){
dev = findDeviceByName("toiletLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("livingRoomLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("restaurantLight",devPhead);
dev->close(dev->pinNum);
dev = findDeviceByName("secondFloorLight",devPhead);
dev->close(dev->pinNum);
}
}
}
void* socket_thread(void *data)
{
pthread_t socketReadThread;
//返回已连接的客户端的地址和端口号
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
//在指令工厂中寻找
socketHandeler = findCmmandByName("socketServer",cmdPhead);
if(socketHandeler == NULL){
printf("find socketHandeler error\n");
pthread_exit(NULL);
}
socketHandeler->init(socketHandeler);
printf("%s socket_thread init success!\n",socketHandeler->commandName);
while(1){//不断地检测是否有客户端接入
c_fd = accept(socketHandeler->fd,(struct sockaddr *)&c_addr,&clen);
printf("客户端的地址:%d",inet_ntoa(c_addr.sin_addr));
if(c_fd == -1){
perror("accept");
}
//如果有,去创建线程读取客户端发送的指令
pthread_create(&socketReadThread,NULL,socket_read_thread,NULL);
}
}
int main()
{
char name[128] = {'\0'};
pthread_t voiceThread;
pthread_t socketThread;
pthread_t cameraThread;
pthread_t fireThread;
if(wiringPiSetup() == -1){
printf("硬件初始化失败\n");
return -1;
}
struct Devices *tmp = NULL;
//1.指令工厂初始化
cmdPhead = voiceCommandToLink(cmdPhead);
cmdPhead = socketCommandToLink(cmdPhead);
//2.设备控制工厂初始化
devPhead = toiletLightToLink(devPhead);
devPhead = secondFloorLightToLink(devPhead);
devPhead = livingRoomLightToLink(devPhead);
devPhead = restaurantLightToLink(devPhead);
devPhead = fireToLink(devPhead);
devPhead = cameraToLink(devPhead);
devPhead = buzzerToLink(devPhead);
devPhead = lockToLink(devPhead);
//3.线程池建立
//3.1 语音线程
pthread_create(&voiceThread,NULL,voice_thread,NULL);
//3.2 socket 线程
pthread_create(&socketThread,NULL,socket_thread,NULL);
//3.3 摄像头线程
pthread_create(&cameraThread,NULL,camera_thread,NULL);
//3.4 火灾线程
pthread_create(&fireThread,NULL,fire_thread,NULL);
//线程等待
pthread_join(voiceThread,NULL);
pthread_join(socketThread,NULL);
pthread_join(cameraThread,NULL);
pthread_join(fireThread,NULL);
return 0;
}
SU-03T语音控制模块设置
人脸识别模块
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "contrlDevices.h"
char buf[1024] = {'\0'};
size_t readData( void *ptr, size_t size, size_t nmemb, void *stream){
memset(buf,'\0',sizeof(buf));
strncpy(buf,ptr,nmemb);
printf("====================================get data===========================\n");
printf("%s",buf);
}
int cameraInit(int pinNum)
{
curl_global_init(CURL_GLOBAL_ALL);
}
//将图片转化为base64编码格式
char* imgBase64FromFile(char* str){
int fd;
int len;
char* img = NULL;
char cmd[124] = {'\0'};
sprintf(cmd,"base64 %s > fileImg.txt",str);
system(cmd);
fd = open("./fileImg.txt",O_RDWR);
len = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
img = (char*)malloc(len+2);
memset(img,'\0',len);
read(fd,img,len);
close(fd);
system("rm -r fileImg.txt");
return img;
}
//人脸识别采集照片
char* getFaceBase64FromNet()
{
char *getFaceBase64Img;
system("raspistill -t 2000 -o /home/pi/smartHose/person.jpg -q 5");//采集照片
//-q 是图片质量,在0~100之间,我们调成5,压缩图片质量
//-t 是拍照延时
while(access("/home/pi/smartHose/person.jpg",F_OK) == -1);
getFaceBase64Img = imgBase64FromFile("/home/pi/smartHose/person.jpg");
system("rm -r /home/pi/smartHose/person.jpg");
return getFaceBase64Img;
}
int cameraPostUrl(struct Devices *camera)
{
CURL *curl;
CURLcode res;
char *postString = NULL;
int len;
char *img1;
char *img2;
char *key = "DAG*****************Hz";//用自己的
char *secret = "58*****************e0";//用自己的
int typeId = 21;
char *format = "xml";
img1 = getFaceBase64FromNet();
//img1 = imgBase64FromFile("./person.jpg");
img2 = imgBase64FromFile(camera->localAmgAddress);
len = strlen(key)+strlen(secret)+strlen(img1)+strlen(img2)+128;
postString = (char*)malloc(len);
memset(postString,'\0',len);
sprintf(postString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",img1,img2,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, readData);
res = curl_easy_perform(curl);
printf("OK:%d\n",res);
if(strstr(buf,"是") != NULL){ //我这里用source insight 写的 ,到树莓派中去这个 '是' 为乱码,利用nano 文件名.c 去修改
printf("the same person!\n");
camera->ret = 1;
}else{
printf("Face recognition is not the person!\n");
camera->ret = 0;
}
curl_easy_cleanup(curl);
}
free(postString);
free(img1);
free(img2);
return 0;;
}
struct Devices camera =
{
.devicesName = "camera",
.devicesInit = cameraInit,
.postUrl = cameraPostUrl,
.localAmgAddress = "./img3.jpg",
};
struct Devices *cameraToLink(struct Devices* phead)
{
if(phead == NULL){
phead = &camera;
}else{
camera.next = phead;
phead = &camera;
}
return phead;
}
网络
#include <stdio.h>
#include "inputCommand.h"
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
int socketInit(struct InputCommander *socketContrl)
{
int s_fd;
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket why");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(socketContrl->iPort));
inet_aton(socketContrl->ipAdress,&addr.sin_addr);
bind(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in));
listen(s_fd,10);
socketContrl->fd = s_fd;
return s_fd;
}
int socketGetCommand(struct InputCommander *socketContrl)
{
int c_fd;
int n_read;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
c_fd = accept(socketContrl->fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
n_read = read(c_fd, socketContrl->command, sizeof(socketContrl->command));
return n_read;
}
struct InputCommander socketContrl =
{
.commandName = "socketServer",
.command = {"\0"},
.ipAdress = "192.168.0.145",
.iPort = "9999",
.init = socketInit,
.getCommand = socketGetCommand,
.log = {'\0'},
.next = NULL
};
struct InputCommander *socketCommandToLink(struct InputCommander* phead)
{
if(phead == NULL){
phead = &socketContrl;
}else{
socketContrl.next = phead;
phead = &socketContrl;
}
return phead;
}
语音控制
#include "inputCommand.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <wiringSerial.h>
int voiceInit(struct InputCommander *voice)
{
int v_fd;
if((v_fd = serialOpen(voice->deviceName,voice->baud)) == -1){
exit(-1);
}
voice->fd = v_fd;
return v_fd;
}
int voiceGetCommand(struct InputCommander *voice)
{
int nread = 0;
memset(voice->command,'\0',sizeof(voice->command));
nread = read(voice->fd,voice->command,sizeof(voice->command));
return nread;
}
struct InputCommander voicesContrl =
{
.commandName = "voice",
.deviceName = "/dev/ttyAMA0",
.baud = 115200,
.command = {'\0'},
.init = voiceInit,
.getCommand = voiceGetCommand,
.log = {'\0'},
.next = NULL
};
struct InputCommander *voiceCommandToLink(struct InputCommander* phead)
{
if(phead == NULL){
phead = &voicesContrl;
}else{
voicesContrl.next = phead;
phead = &voicesContrl;
}
return phead;
}
灯光(代码类似,只写其中一个)
#include <stdio.h>
#include "inputCommand.h"
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
int socketInit(struct InputCommander *socketContrl)
{
int s_fd;
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket why");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(socketContrl->iPort));
inet_aton(socketContrl->ipAdress,&addr.sin_addr);
bind(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in));
listen(s_fd,10);
socketContrl->fd = s_fd;
return s_fd;
}
int socketGetCommand(struct InputCommander *socketContrl)
{
int c_fd;
int n_read;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
c_fd = accept(socketContrl->fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
n_read = read(c_fd, socketContrl->command, sizeof(socketContrl->command));
return n_read;
}
struct InputCommander socketContrl =
{
.commandName = "socketServer",
.command = {"\0"},
.ipAdress = "192.168.0.145",
.iPort = "9999",
.init = socketInit,
.getCommand = socketGetCommand,
.log = {'\0'},
.next = NULL
};
struct InputCommander *socketCommandToLink(struct InputCommander* phead)
{
if(phead == NULL){
phead = &socketContrl;
}else{
socketContrl.next = phead;
phead = &socketContrl;
}
return phead;
}
火灾模块
#include "contrlDevices.h"
int fireCloseInit(int pinNum)
{
pinMode(pinNum,INPUT);
digitalWrite(pinNum,HIGH);
}
int fireReadStatus(int pinNum)
{
return digitalRead(pinNum);
}
struct Devices fire =
{
.devicesName = "fire",
.pinNum = 21,
.devicesInit = fireCloseInit,
.readStatus = fireReadStatus
};
struct Devices *fireToLink(struct Devices* phead)
{
if(phead == NULL){
phead = &fire;
}else{
fire.next = phead;
phead = &fire;
}
return phead;
}
其余代码都类似,可自行补充!!!!!!!!!!
用到的库 mjpg-streamer openssl-1.1.1a.tar.gz curl-7.71.1.tar.bz2
安装curl库
./configure --prefix=/路径 --with-ssl(支持https) --host arm-linux-...(交叉编译的工具) 表示你要安装的路径进行配置
make 进行编译
make install 进行安装
缺少OpenSSL时,卸载源有的curl,先安装openssl,再去装curl
./configure --prefix=/路径 --with-ssl(支持https)
--with-ssl was given but OpenSSL could not be detected :问题
缺少OpenSSL.tar 的库(注意!!!!!!!!!!!!!!!!!!尽量装到默认路径,别去指定路径)
可以尝试wget OpenSSL.tar 去linux的开源库去找
make
make install
如果以上操作均已完成,编译成报错
./curl-7.71.1/_install/lib//libcurl.so: undefined reference to `SSL_CTX_set_keylog_callback@OPENSSL_1_1_1'
./curl-7.71.1/_install/lib//libcurl.so: undefined reference to `SSL_CTX_set_post_handshake_auth@OPENSSL_1_1_1'
./curl-7.71.1/_install/lib//libcurl.so: undefined reference to `SSL_CTX_set_ciphersuites@OPENSSL_1_1_1'
在指令上加上 -lssl -lcrypto 就可以啦
/home/pi/httpHandler/curl-7.71.1/_install/include -L /home/pi/httpHandler/curl-7.71.1/_install/lib -lwiringPi -lpthread -lcurl -lssl -lcrypto