文章目录
一、功能介绍
二、设计框图
三、实物展示
四、程序
一、功能介绍
基于树莓派的智能家居。智能家居用到的硬件有:树莓派4B、LD3320语音识别模块、pi 摄像头、继电器组、小灯、火焰传感器、蜂鸣器、电磁锁
采用了简单工厂模式的一个设计方式。稳定,拓展性更强,在C语言中,因为没有接口、类这一说法,所以这里采用了结构体来“等效替换”。有四个灯,所以我创建了四个灯控制.c程序。每一个程序文件中,都有一个设备结构体,每个程序文件的函数实现方法不同,当有新设备进入只需要在创建一个.c文件,改变函数实现方法即可。初始化的时候,通过链表将各个模块连接起来(头插法)。在要使用某个模块时,只需要使用链表遍历,找到所需模块去调用功能
具体功能是:
1、可通过ld3320语音模块的口令模式,口令+具体控制,通过串口把控制指令传给树莓派,来控制客厅、餐厅、二楼、浴室的灯
2、也可以通过socket客户端来发指令来控制灯的开关
3、火灾报警,当火焰传感器检测到火焰的时候,蜂鸣器会报警。
4、视频监控采用开源mjpg-Streamer来实现的,程序执行时创建一个视频监控的线程,用system函数调用启动脚本运行,监控画面可在http://172.20.10.8:8080去看到
5、人脸识别开锁,人脸识别功能是使用的翔云平台的人脸识别解决方案,需要安装libcurl 和 openSSl库来支持https协议,通过系统调用wget +http://172.20.10.8:8080/?action=snapshot -O ./huyu1.jpg 指令到树莓派的监控页面"去截取一帧保存到本地,获取图片的base64编码,工程文件夹下也有一张照片,huyu.jpg格式,相当于采集的人脸。也是获取图片的base64编码,通过sprintf函数将访问翔云需要的两张图片的base64编码与Key、secret、typeId、format拼接在一起,通过https协议去访问翔云平台, 识别成功后会将识别结果返回,通过回调函数readData将返回的字符串读到readBuff里,通过strstr去readbuff里找有没有字符’是’,如果识别成功就去控制电磁锁打开。
二、设计框图
*效果展示:*https://www.bilibili.com/video/BV1uD4y1C7PH?share_source=copy_web&vd_source=5e457ac82f63b0e36b8b9e2708807f31
三、实物展示
四、程序
1、InputCommand.h
#include <wiringPi.h>
#include <stddef.h>
struct InputCommander
{
char commandName[128];
char deviceName[128];
char command[32];
int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);
int (*getCommand)(struct InputCommander *voicer);
char log[1024];
int fd;
char port[12];
char ipAddress[32];
int sfd;
struct InputCommander *next;
};
struct InputCommander *addVoiceControlToInputCommandLink(struct InputCommander *phead);
struct InputCommander *addSocketControlToInputCommandLink(struct InputCommander *phead);
2、controlDevices .h
#include <wiringPi.h>
#include <stdio.h>
struct Devices
{
char deviceName[128];
int status;
int pinNum;
int (*open)(int pinNum);
int (*close)(int pinNum);
int (*deviceInit)(int pinNum);
int (*readStatus)(int pinNum);
int (*changeStatus)(int status);
void (*faceRecognition)(); //人脸识别
char *(*takePictureInit)();//用于摄像头
char *(*getPicBase64)(); //用于摄像头
size_t (*readData)(); //用于摄像头
struct Devices *next;
};
struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices *addUpstairLightToDeviceLink(struct Devices *phead);
struct Devices *addDiningroomLightToDeviceLink(struct Devices *phead);
struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead);
struct Devices *addFireAlarmToDeviceLink(struct Devices *phead);
struct Devices* addBeepToDeviceLink(struct Devices *phead);
struct Devices *addLookToDeviceLink(struct Devices *phead);
struct Devices *addCameraToDeviceLink(struct Devices *phead);
3、mainPro.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "controlDevices.h"
#include "InputCommand.h"
struct InputCommander *pCommandHead = NULL;
struct Devices *pdeviceHead = NULL;
struct InputCommander *socketHandler = NULL;
int c_fd;
char *name = NULL;
pthread_t cameraThread;
struct Devices *findDeviceByName(char *name,struct Devices *phead)
{
struct Devices *tmp = phead;
if(phead == NULL)
{
return NULL;
}
else{
while(tmp != NULL){
if(strcmp(tmp->deviceName,name) == 0)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
struct InputCommander *findCommandByName(char *name,struct InputCommander *phead)
{
struct InputCommander *tmp = phead;
if(phead == NULL)
{
return NULL;
}
else
{
while(tmp != NULL){
if(strcmp(tmp->commandName,name) == 0)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
void *camera_thread(void *datas) //摄像头线程
{
struct Devices *cameraTemp;
cameraTemp = findDeviceByName("camera", pdeviceHead); //设备都要从工厂里面取出来
if (cameraTemp == NULL)
{
//防止段错误的必需判断,当给指针赋值是,一定要考虑NULL的情况
printf("find camera error\n");
pthread_exit(NULL); //在线程中不用return
}
cameraTemp->faceRecognition(); //调用人脸识别函数
}
void * voice_thread(void *datas) //语音线程
{
int nread;
struct InputCommander *voiceHandler = NULL;
struct Devices *linkHandler = NULL;
voiceHandler = findCommandByName("voice",pCommandHead);
if(voiceHandler == NULL){
printf("find voicehandler error\n");
pthread_exit(NULL);
}else{
if(voiceHandler->Init(voiceHandler,NULL,NULL)<0){
printf("voice init error\n");
pthread_exit(NULL);
}else{
printf(