基于树莓派的智能家居控制系统:实现舒适、便捷的生活体验

 一.功能介绍

1.通过手机端网络调试助手,语音识别,对灯光,风扇,等电器进行远程控制。

 2.通过火焰报警,震动报警,视频监控等功能保证家庭的安全。

3.实时将环境温湿度数据,各种安防信息发送到客户端进行显示。

4.通过红外遥控也能对部分家电进行远程控制。

5.通过翔云平台提供的人脸对比识别服务,实现人脸识别开锁功能。

二.实物展示

   

                 人脸识别按钮和门锁                                                433m红外接收模块

                         摄像头                                                        火焰报警和雨滴传感器

    手机端实时显示环境状态            手机端通过指令控制家电                  网页实时视频监控

 三.程序

 编译运行:

 1.mainPro.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>
#include <curl/curl.h>

#include"InputCommand.h"
#include"contrlDevices.h"
//为了线程里能调到链表头,要把这两个表头设置为全局变量
struct Devices *pdeviceHead = NULL;
struct InputCommander *pCommandHead = NULL;

struct InputCommander *socketHandler = NULL;
int c_fd;
//定义互斥量(锁)
pthread_mutex_t mutex;

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef unsigned long uint32;
 
#define HIGH_TIME 32

pthread_t writeThread;
pthread_t voiceThread;
pthread_t socketThread;
pthread_t fireThread;
pthread_t DHT11Thread;
pthread_t readThread;
pthread_t shakeThread;
pthread_t windowThread;
pthread_t keyThread;
pthread_t cameraThread;
pthread_t remoteThread;


int tmp = 0;//设置火灾和振动的标志位
int wintmp1 = 0;
int wintmp2 = 0;
#define key 6 //拍照按键

char Message[4][100] = {"未启用!", "未启用!", "未启用!", "未启用!"};
int write_flag = 0; //标记位,标记通知线程是否打开     1:打开   0:关闭
int a = 0;
int b = 0;

extern uint32 databuf;

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 *window_thread(void *datas)
{
	struct Devices *windowDeviceTmp = NULL;
	windowDeviceTmp = findDeviceByName("window", pdeviceHead);
	if(windowDeviceTmp == NULL)
	{
		printf("find window error\n");
		pthread_exit(NULL);
	}
	windowDeviceTmp->deviceInit(windowDeviceTmp->pinNum);
	
	while(1){
		if(digitalRead(5) == 0){	//没雨 开窗 5引脚就是检测是否有雨水 
			sleep(1);
			b = 1;
			if(a != 0){
				windowDeviceTmp->open(windowDeviceTmp->pinNum);//正转 开窗
				sleep(5);
				windowDeviceTmp->deviceInit(windowDeviceTmp->pinNum);//停
		
				while(digitalRead(5) == 0);
			}
		}
		else if(digitalRead(5) == 1){
			sleep(1);
			a = 1;
			if(b != 0){
				windowDeviceTmp->close(windowDeviceTmp->pinNum);//反转 关窗
				sleep(5);
				windowDeviceTmp->deviceInit(windowDeviceTmp->pinNum);//停
				
				while(digitalRead(5) == 1);
			}
		}
	}

}

void *shake_thread(void *datas) //震动线程
{
	int tmp1 = 0;
	
	struct Devices *shakeDeviceTmp = NULL;
	struct Devices *shakebuzzerDeviceTmp = NULL;  
	shakeDeviceTmp = findDeviceByName("shake", pdeviceHead); //在设备工厂找到震动模块和震动蜂鸣器
	shakebuzzerDeviceTmp = findDeviceByName("shakebuzzer", pdeviceHead);
	if((shakeDeviceTmp == NULL)&&(shakebuzzerDeviceTmp == NULL))
	{
		printf("find shake or shakebuzzer error\n");
		pthread_exit(NULL);
	}
	shakeDeviceTmp->deviceInit(shakeDeviceTmp->pinNum); //震动初始化
	shakebuzzerDeviceTmp->deviceInit(shakebuzzerDeviceTmp->pinNum);//蜂鸣器初始化
	while(1)
	{

			//tmp = 1;
		if(digitalRead(26) == 1)                                                                                          
		{
			
			shakebuzzerDeviceTmp->open(shakebuzzerDeviceTmp->pinNum);		//开震动蜂鸣器
			delay(3);
			shakebuzzerDeviceTmp->close(shakebuzzerDeviceTmp->pinNum);	
			memset(Message[3], 0, sizeof Message[3]);       //清空数组
	        sprintf(Message[3], "无震动 ");       //更新震动信息
	        
		}

		else
		{
			memset(Message[3], 0, sizeof Message[3]);        //清空数组
            sprintf(Message[3], "有震动! ");
			shakebuzzerDeviceTmp->close(shakebuzzerDeviceTmp->pinNum);		//关震动蜂鸣器
		
			
		}
	}

}

void *fire_thread(void *datas) //火灾线程
{
	struct Devices *fireDeviceTmp = NULL;
	struct Devices *buzzerDeviceTmp = NULL;
	fireDeviceTmp = findDeviceByName("fireIfOrNot", pdeviceHead); //在设备工厂找到火焰模块和火焰蜂鸣器
	buzzerDeviceTmp = findDeviceByName("buzzer", pdeviceHead);
	
	if((fireDeviceTmp == NULL)&&(buzzerDeviceTmp == NULL))
	{
		printf("find fire or buzzer error\n");
		pthread_exit(NULL);
	}
	fireDeviceTmp->deviceInit(fireDeviceTmp->pinNum); //火灾模块初始化
	buzzerDeviceTmp->deviceInit(buzzerDeviceTmp->pinNum);//蜂鸣器初始化
	while(1)
	{
		if(digitalRead(25) == 1)
		{

			buzzerDeviceTmp->open(buzzerDeviceTmp->pinNum);		//开火灾蜂鸣器
			memset(Message[2], 0, sizeof Message[2]);       //清空数组
            sprintf(Message[2], "无火灾");       //更新火灾信息
			
		}
		else
		{
			buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum);	//关火灾蜂鸣器
			memset(Message[2], 0, sizeof Message[2]);        //清空数组
            sprintf(Message[2], "有火灾! "); 
			tmp = 0;
            
		}
		
	}
}


void *voice_thread(void* datas)//语音线程
{
	struct InputCommander *voiceHandler;
	struct Devices *deviceTmp = NULL;
	int nread;
	
	voiceHandler = findCommandByName("voice", pCommandHead);//找语音节点
	if(voiceHandler == NULL)
	{
		printf("find voice error\n");
		pthread_exit(NULL);
	}
	else
	{								//找到了
		if(voiceHandler->Init(voiceHandler, NULL, NULL) < 0)
		{	//先初始化
			printf("voice init error\n");
			pthread_exit(NULL);//退出线程
		}
		else
		{
			printf("%s init success\n",voiceHandler->commandName);
		}
		pthread_mutex_lock(&mutex); //加锁
									//语音读取一级指令的时候,为了避免其它线程对于 紧接着读取二级指令的干扰
		while(1)
		{						//读数据
			memset(voiceHandler->command, '\0', sizeof(voiceHandler->command));
			nread = voiceHandler->getCommand(voiceHandler);//获取语音模块发来的数据
			printf("get voice command:%s\n", voiceHandler->command);
			if(nread == 0)
			{
				printf("nodata from voice\n");
			}
			else if(strstr(voiceHandler->command, "kycd") != NULL)		//1如果收到数据
			{
				deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开泳池灯
			}
			else if(strstr(voiceHandler->command, "gycd") != NULL)		
			{
				deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关泳池灯
			}

			else if(strstr(voiceHandler->command, "kwsd") != NULL)		//
			{
				deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开卧室灯
			}
			else if(strstr(voiceHandler->command, "gwsd") != NULL)		
			{
				deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关卧室灯
			}
			
			else if(strstr(voiceHandler->command, "kysd") != NULL)		
			{
				deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开浴室灯
			}
			else if(strstr(voiceHandler->command, "gysd") != NULL)		
			{
				deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关浴室灯
			}

			else if(strstr(voiceHandler->command, "kcfd") != NULL)		
			{
				deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开厨房灯
			}
			else if(strstr(voiceHandler->command, "gcfd") != NULL)		
			{
				deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关厨房灯
			}

			
			else if(strstr(voiceHandler->command, "kfs") != NULL)		//开风扇
			{
				deviceTmp = findDeviceByName("fan",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);
			}
			else if(strstr(voiceHandler->command, "gfs") != NULL)		//关风扇
			{
				deviceTmp = findDeviceByName("fan",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);
			}

			
			else if(strstr(voiceHandler->command, "quankai") != NULL)		
			{
				deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开泳池灯

				deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开卧室灯

				deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开浴室灯

				deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开厨房灯

				deviceTmp = findDeviceByName("fan",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->open(deviceTmp->pinNum);//开风扇
			}
			else if(strstr(voiceHandler->command, "quanguan") != NULL)		//如果收到数据
			{
				deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关泳池灯

				deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关卧室灯

				deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关浴室灯

				deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关厨房灯

				deviceTmp = findDeviceByName("fan",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
				deviceTmp->close(deviceTmp->pinNum);//关风扇
			}
		}
	}

}

void *read_thread(void *datas)
{
 	int n_read;
	struct Devices *deviceTmp = NULL;
	
	while(1)
	{
		memset(socketHandler->command, '\0', sizeof(socketHandler->command));
		n_read = read(c_fd, socketHandler->command, sizeof(socketHandler->command));//客户端发来的数据存到 socketHandler->command
		if(n_read == -1){
			perror("read");
		}
		else if(n_read > 0){
		printf("\nget: %d,%s\n",n_read,socketHandler->command);//打印客户端发来的数据
		//if (strstr(socketHandler->command, "kwsd") != NULL)
		if(strstr(socketHandler->command, "kycd") != NULL)		//1如果收到数据
		{
			deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开泳池灯
		}
		else if(strstr(socketHandler->command, "gycd") != NULL)		
		{
			deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关泳池灯
		}

		else if(strstr(socketHandler->command, "kwsd") != NULL)		//
		{
			deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开卧室灯
		}
		else if(strstr(socketHandler->command, "gwsd") != NULL)		
		{
			deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关卧室灯
		}
		
		else if(strstr(socketHandler->command, "kysd") != NULL)		
		{
			deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开浴室灯
		}
		else if(strstr(socketHandler->command, "gysd") != NULL)		
		{
			deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关浴室灯
		}

		else if(strstr(socketHandler->command, "kcfd") != NULL)		
		{
			deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开厨房灯
		}
		else if(strstr(socketHandler->command, "gcfd") != NULL)		
		{
			deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关厨房灯
		}

		
		else if(strstr(socketHandler->command, "kfs") != NULL)		//开风扇
		{
			deviceTmp = findDeviceByName("fan",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);
		}
		else if(strstr(socketHandler->command, "gfs") != NULL)		//关风扇
		{
			deviceTmp = findDeviceByName("fan",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);
		}

		
		else if(strstr(socketHandler->command, "quankai") != NULL)		
		{
			deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开泳池灯

			deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开卧室灯

			deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开浴室灯

			deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开厨房灯

			deviceTmp = findDeviceByName("fan",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->open(deviceTmp->pinNum);//开风扇
		}
		else if(strstr(socketHandler->command, "quanguan") != NULL)		//如果收到数据
		{
			deviceTmp = findDeviceByName("livingRoomLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关泳池灯

			deviceTmp = findDeviceByName("upstairLight",pdeviceHead);//通过名子找到节点
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关卧室灯

			deviceTmp = findDeviceByName("bathroomLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关浴室灯

			deviceTmp = findDeviceByName("restauranLight",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关厨房灯

			deviceTmp = findDeviceByName("fan",pdeviceHead);
			deviceTmp->deviceInit(deviceTmp->pinNum);//初始化
			deviceTmp->close(deviceTmp->pinNum);//关风扇
		}
	}
		
	else{
		printf("client quit\n");
		write_flag = 0;		
		pthread_cancel(writeThread);
		pthread_exit(NULL);
	}
		}
}
void *write_thread(void *datas) //实时向客户端发送消息
{
    while (1)
    {
        delay(1000);
        write(c_fd, Message, 400);
    }
}

void *socket_thread(void* datas)
{

	int n_read = 0;
	
	
	struct sockaddr_in c_addr;
	memset(&c_addr, 0, sizeof(struct sockaddr_in));
	int clen = sizeof(struct sockaddr_in);
	
	socketHandler = findCommandByName("socketServer", pCommandHead);//找socket节点
	if(socketHandler == NULL){
		printf("find socketHandler error\n");
		pthread_exit(NULL);
	}else{
		printf("%s init success\n",socketHandler->commandName);
	} 
	socketHandler->Init(socketHandler, NULL, NULL);//找到就初始化

	while(1){		//只要有新的客户端接入 就创建新线程去对接
		c_fd = accept(socketHandler->sfd, (struct sockaddr *)&c_addr, &clen);
		
 		pthread_create(&readThread, NULL, read_thread, NULL);//读客户端发来的数据
 		
 		if (write_flag == 0){
			write_flag = 1;
			pthread_create(&writeThread, NULL, write_thread, NULL);//往客户端发数据 比如温湿度
 		}

		
	}
}


void *DHT11_thread(void* datas)
{

	struct Devices *DHT11DeviceTmp = NULL;

	DHT11DeviceTmp = findDeviceByName("DHT11", pdeviceHead); //在设备工厂找到温湿度模块

	DHT11DeviceTmp->deviceInit(DHT11DeviceTmp->pinNum); //温湿度模块初始化


    while (1) 
    {
        //pinMode(7, OUTPUT); // set mode to output
       // digitalWrite(7, 1); // output a high level 
        delay(3000);
        if (DHT11DeviceTmp->deviceInit(DHT11DeviceTmp->pinNum))
        {
           // printf("Sensor data read ok!\n");
			memset(Message[0], 0, sizeof Message[0]); //清空数组
            memset(Message[1], 0, sizeof Message[1]);
		   
            sprintf(Message[0], "湿度:%d.%d ", (databuf >> 24) & 0xff, (databuf >> 16) & 0xff); 
            sprintf(Message[1], "温度:%d.%d ", (databuf >> 8) & 0xff, databuf & 0xff);

			//printf("shidu = %d.%d\n", (databuf >> 24) & 0xff, (databuf >> 16) & 0xff);
			//printf("wendu = %d.%d\n", (databuf >> 8) & 0xff, databuf & 0xff);
			
            databuf = 0;
        }
        else
        {
            printf("Sensor dosent ans!\n");
            databuf = 0;
         }
     }


}
void *remote_thread(void *datas)//433m线程
{
	int val0 = 0, val1 = 0, val2 = 0, val3 = 0;
    int temp0 = 0, temp1 = 0,temp2 = 0,temp3 = 0;
	int count0 = 0, count1 = 0, count2 = 0, count3 = 0;
	
	struct Devices *deviceTmp = NULL;
	wiringPiSetup();
    pinMode(12, INPUT);
    pinMode(13, INPUT);
	pinMode(14, INPUT);
    pinMode(30, INPUT);
	
    digitalWrite(12, LOW);
    digitalWrite(13, LOW);
	digitalWrite(14, LOW);
    digitalWrite(30, LOW);

	while(1)
	{
		val0 = digitalRead(12);
    	val1 = digitalRead(13);
		val2 = digitalRead(14);
    	val3 = digitalRead(30);
		if (val0 == 1) //电风扇遥控信号 	
        {
        	if(count0 == 0)
			{
			 	delay(500);
             	if (temp0 == 0) //打开厨房灯
             	{

                 	printf("433M:open restauranLight\n");
                 	temp0 = 1;
                 	deviceTmp = findDeviceByName("restauranLight", pdeviceHead);
                 	deviceTmp->deviceInit(deviceTmp->pinNum);       
                 	deviceTmp->open(deviceTmp->pinNum);             
                 	while(val0 == 0);
            	 }
             	else if (temp0 == 1) //关闭厨房灯
             	{

                	 printf("433M:close restauranLight\n");
                 	temp0 = 0;
                 	deviceTmp = findDeviceByName("restauranLight", pdeviceHead); 
                 	deviceTmp->deviceInit(deviceTmp->pinNum);         
                 	deviceTmp->close(deviceTmp->pinNum);              
                 
            	 }
				count0 = 1;
        	}
			
        }
		else if (val0 == 0)
        {
            count0 = 0;
        }


		if (val1 == 1) //泳池灯遥控信号
        {
        	if(count1 == 0)
        	{
				delay(500);
	             if (temp1 == 0) //打开泳池灯 
	             {
	                 printf("433M:open livingRoomLight\n");
	                 temp1 = 1;
	                 deviceTmp = findDeviceByName("livingRoomLight", pdeviceHead);
	                 deviceTmp->deviceInit(deviceTmp->pinNum);        
	                 deviceTmp->open(deviceTmp->pinNum);              
	                 while(val1 == 0);
	             }
	             else if (temp1 == 1) //关闭泳池灯
	             {
                 	printf("433M:close livingRoomLight\n");
                 	temp1 = 0;
                 	deviceTmp = findDeviceByName("livingRoomLight", pdeviceHead);
                 	deviceTmp->deviceInit(deviceTmp->pinNum);      
                 	deviceTmp->close(deviceTmp->pinNum);             
	             }
				count1 = 1;
        	}
        }
		else if (val1 == 0)
        {
            count1 = 0;
        }


			
		if (val2 == 1) //卧室灯遥控信号
        {
        	if(count2 == 0)
			{
				delay(500);
	             if (temp2 == 0)   //打开卧室灯
	             {

	                 printf("433M:open upstairLight\n");
	                 temp2 = 1;
	                 deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
	                 deviceTmp->deviceInit(deviceTmp->pinNum);     
	                 deviceTmp->open(deviceTmp->pinNum);             
	                 while(val2 == 0);
	             }
	             else if (temp2 == 1)  //关闭卧室灯
	             {

	                 printf("433M:close upstairLight\n");
	                 temp2 = 0;
	                 deviceTmp = findDeviceByName("upstairLight", pdeviceHead); 
	                 deviceTmp->deviceInit(deviceTmp->pinNum);        
	                 deviceTmp->close(deviceTmp->pinNum);             
	                 
	             }
				 count2 = 1;
        	}
        }
		else if (val2 == 0)
        {
            count2 = 0;
        }


		if (val3 == 1) //浴室灯遥控信号
        {
        	if(count3 == 0)
			{
				delay(500);
	             if (temp3 == 0) //打开浴室灯  
	             {

	                 printf("433M:open bathroomLight\n");
	                 temp3 = 1;
	                 deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
	                 deviceTmp->deviceInit(deviceTmp->pinNum);     
	                 deviceTmp->open(deviceTmp->pinNum);              
	                 while(val3 == 0);
	             }
	             else if (temp3 == 1) //关闭浴室灯
	             {

	                 printf("433M:close bathroomLight\n");
	                 temp3 = 0;
	                 deviceTmp = findDeviceByName("bathroomLight", pdeviceHead); 
	                 deviceTmp->deviceInit(deviceTmp->pinNum);        
	                 deviceTmp->close(deviceTmp->pinNum);            
	                 
	             }
				 count3 = 1;
        	}
        }
		else if (val3 == 0)
        {
            count3 = 0;
        }
	}


}

void *cameraThread_func(void *data) //起线程的函数有格式要求
{
    struct Devices *cameraTemp;

    cameraTemp = findDeviceByName("camera", pdeviceHead); //找到摄像头节点

    if (cameraTemp == NULL)
    { 
        printf("find camera error\n");
        pthread_exit(NULL); //在线程中不用return
    }

    cameraTemp->justDoOnce(); //调用postUrl函数
}

void *key_thread()
{
    // pinMode(door_Lock, OUTPUT); //将门锁端口置为输出
    
    int val;
    while (1)
    {
        val = digitalRead(key);
        // printf("key = %d\n", val);
        if (val == 0) //防止重复检测
        {
            delay(500);
            val = digitalRead(key);
            // printf("key = %d\n", val);
            if (val == 1) //按键按下,启动人脸识别线程
            {
				
                pthread_create(&cameraThread, NULL, cameraThread_func, NULL);
            }
        }
    }
}


int main()
{
	char name[128];
	struct Devices *tmp = NULL;
	
	  
	if(-1 == wiringPiSetup()){
		return -1;
	}

	//1.指令工厂初始化
	pCommandHead = addvoiceContrlToInputCommandLink(pCommandHead);//语音
	pCommandHead = addSocketContrlToInputCommandLink(pCommandHead);//socket

	//2.设备控制工厂初始化
	pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addUpstairLightToDeviceLink(pdeviceHead);
	pdeviceHead = addRestauranLightToDeviceLink(pdeviceHead);
	pdeviceHead = addLivingRoomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addfireToDeviceLink(pdeviceHead);//火灾模块
	
	pdeviceHead = addbuzzerToDeviceLink(pdeviceHead);//火灾蜂鸣器
	
	pdeviceHead = addshakebuzzerToDeviceLink(pdeviceHead);//震动蜂鸣器
	
	pdeviceHead = addfanToDeviceLink(pdeviceHead);
	pdeviceHead = addDHT11ToDeviceLink(pdeviceHead);
	pdeviceHead = addcameraToDeviceLink(pdeviceHead);//摄像头
	pdeviceHead = addShakeToDeviceLink(pdeviceHead);//震动模块
	pdeviceHead = addwindowToDeviceLink(pdeviceHead);
	

	//3.线程池建立
	//int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
		//3.1 语音线程
	pthread_create(&voiceThread, NULL, voice_thread, NULL);

		//3.2 socket线程
	pthread_create(&socketThread, NULL, socket_thread, NULL);

		//3.3火灾线程
	pthread_create(&fireThread, NULL, fire_thread, NULL);     

		//3.4 摄像头线程  这里把摄像头设为了开机自启 

		//3.5 温湿度线程
	pthread_create(&DHT11Thread, NULL, DHT11_thread, NULL);

		//3.6 震动线程
	pthread_create(&shakeThread, NULL, shake_thread, NULL);

		//3.7 窗户线程
	pthread_create(&windowThread, NULL, window_thread, NULL);
		//3.8 按钮线程
	pthread_create(&keyThread, NULL, key_thread, NULL);

		//3.9 433m线程
	pthread_create(&remoteThread, NULL, remote_thread, NULL);	
	


	pthread_join(voiceThread, NULL);
	pthread_join(socketThread, NULL);
	pthread_join(fireThread, NULL);
	pthread_join(DHT11Thread, NULL);
	pthread_join(writeThread, NULL);
	pthread_join(shakeThread, NULL);
	pthread_join(windowThread, NULL);
	pthread_join(keyThread, NULL);
	pthread_join(cameraThread, NULL);
	pthread_join(remoteThread, NULL);
	return 0;
}

contrlDevices.h

#include<stdlib.h>
#include<wiringPi.h>
#include <curl/curl.h>
typedef unsigned int bool;

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 (*justDoOnce)();
		char* (*getFace)(); 
		char* (*getPicFromOCRBase64)(); 
		size_t (*readData)(); 

	struct Devices *next;
};
struct Devices* addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices* addUpstairLightToDeviceLink(struct Devices *phead);
struct Devices* addRestauranLightToDeviceLink(struct Devices *phead);
struct Devices* addLivingRoomLightToDeviceLink(struct Devices *phead);
struct Devices* addfireToDeviceLink(struct Devices *phead);

struct Devices* addfanToDeviceLink(struct Devices *phead);
struct Devices* addDHT11ToDeviceLink(struct Devices *phead);
struct Devices *addShakeToDeviceLink(struct Devices *phead);
struct Devices* addbuzzerToDeviceLink(struct Devices *phead);//火灾蜂鸣器

struct Devices* addshakebuzzerToDeviceLink(struct Devices *phead);//震动蜂鸣器

struct Devices* addwindowToDeviceLink(struct Devices *phead);

struct Devices *addcameraToDeviceLink(struct Devices *phead);//摄像头结点

InputCommand.h

#include<stdlib.h>
#include<wiringPi.h>


struct InputCommander		//
{
	char commandName[128];//名字
	char deviceName[128];//设备名
	char command[32];		//指令
	int (*Init)(struct InputCommander *voicer, char *ipAdress, char *port);//操作函数 : 串口号 ip 端口号 
	int (*getCommand)(struct InputCommander *voicer);//
	char log[1024];		//日志
	int fd;
	char port[12];//端口号
	char ipAddress[32];//ip地址
	int sfd;
	struct InputCommander *next; 
};

struct InputCommander* addvoiceContrlToInputCommandLink(struct InputCommander *phead);
struct InputCommander* addSocketContrlToInputCommandLink(struct InputCommander *phead);

bathroomLight.c(四个房间小灯,风扇代码基本相似,这里只展示其中一个)

#include"contrlDevices.h"
#include<stdlib.h>
#include<fcntl.h>

int bathroomLightOpen(int pinNum)
{
	digitalWrite(pinNum,LOW);

}
int bathroomLightClose(int pinNum)
{
	digitalWrite(pinNum,HIGH);

}

int bathroomLightCloseInit(int pinNum)
{
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);

}

int bathroomLightCloseStatus(int status)
{

}

struct Devices bathroomLight = {		//这里是在定义的同时赋值
	.deviceName = "bathroomLight",
	.pinNum = 22,
	.open = bathroomLightOpen,
	.close = bathroomLightClose,
	.deviceInit = bathroomLightCloseInit,
	.changeStatus = bathroomLightCloseStatus
};

struct Devices* addBathroomLightToDeviceLink(struct Devices *phead)
{
	if(phead == NULL){
		return &bathroomLight;
	}
	else{
		bathroomLight.next = phead;
		phead = &bathroomLight;
		return phead;
	}
}

 window.c

#include"contrlDevices.h"
#include<stdlib.h>
#include<fcntl.h>

int windowOpen(int pinNum)
{
	digitalWrite(2,LOW);
	digitalWrite(3,HIGH);

}
int windowClose(int pinNum)
{
	digitalWrite(2,HIGH);
	digitalWrite(3,LOW);
}

int windowCloseInit(int pinNum)//用的L9110电机实现正反转,所以要初始化两个引脚
{
	pinMode(2,OUTPUT);
	pinMode(3,OUTPUT);
	digitalWrite(2,LOW);
	digitalWrite(3,LOW);//2和3都配置为低电平 默认不转

	pinMode(4,OUTPUT);
	digitalWrite(4,HIGH);
	
	pinMode(0,OUTPUT);			//门锁初始化	
	digitalWrite(0,HIGH);
}

int windowCloseStatus(int status)
{
	
}

struct Devices window = {	
	.deviceName = "window",
	.pinNum = 2,
	.open = windowOpen,
	.close = windowClose,
	.deviceInit = windowCloseInit,
	.changeStatus = windowCloseStatus
};

struct Devices* addwindowToDeviceLink(struct Devices *phead)
{
	if(phead == NULL){
		return &window;
	}
	else{
		window.next = phead;
		phead = &window;
		return phead;
	}
}

DHT11.c

#include"contrlDevices.h"
#include<stdlib.h>
#include<fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef unsigned long uint32;
 
#define HIGH_TIME 32
 
int pinNumber = 7;
uint32 databuf;


int DHT11CloseInit(int pinNum)
{
	uint8 crc; 
    uint8 i;
  
    pinMode(pinNumber, OUTPUT); // set mode to output
    digitalWrite(pinNumber, 0); // output a high level 
    delay(25);
    digitalWrite(pinNumber, 1); // output a low level 
    pinMode(pinNumber, INPUT); // set mode to input
    pullUpDnControl(pinNumber, PUD_UP);
 
    delayMicroseconds(27);
    if (digitalRead(pinNumber) == 0) //SENSOR ANS
    {
        while (!digitalRead(pinNumber))
            ; //wait to high
 
        for (i = 0; i < 32; i++)
        {
            while (digitalRead(pinNumber))
                ; //data clock start
            while (!digitalRead(pinNumber))
                ; //data start
            delayMicroseconds(HIGH_TIME);
            databuf *= 2;
            if (digitalRead(pinNumber) == 1) //1
            {
                databuf++;
            }
        }
 
        for (i = 0; i < 8; i++)
        {
            while (digitalRead(pinNumber))
                ; //data clock start
            while (!digitalRead(pinNumber))
                ; //data start
            delayMicroseconds(HIGH_TIME);
            crc *= 2;  
            if (digitalRead(pinNumber) == 1) //1
            {
                crc++;
            }
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

int DHT11Open(int pinNum)
{

}
int DHT11Close(int pinNum)
{

}

int DHT11CloseStatus(int status)
{
	
}
struct Devices DHT11 = {		//这里是在定义的同时赋值
	.deviceName = "DHT11",
	.pinNum = 7,
	.open = DHT11Open,
	.close = DHT11Close,
	.deviceInit = DHT11CloseInit,
	.changeStatus = DHT11CloseStatus
};

struct Devices* addDHT11ToDeviceLink(struct Devices *phead)
{
	if(phead == NULL){
		return &DHT11;
	}
	else{
		DHT11.next = phead;
		phead = &DHT11;
		return phead;
	}
}

voiceContrl.c

#include<unistd.h>
#include<wiringPi.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

#include<wiringSerial.h>
#include"InputCommand.h"

int voiceGetCommand(struct InputCommander *voicer)
{
	int nread = 0;
	memset(voicer->command, '\0', sizeof(voicer->command));
	nread = read(voicer->fd, voicer->command, sizeof(voicer->command));
	if(nread == 0){
		printf("voice no datas\n");
	}else{
		return nread;
	}
	
}

int voiceInit(struct InputCommander *voicer, char *ipAdress, char *port)
{
	int fd;
	if((fd = serialOpen("/dev/ttyAMA0",9600))==-1)//初始化串口,波特率9600
	{
		printf("voice init error\n");
		exit(-1);
	}
	voicer->fd = fd;
	return fd;

}

struct InputCommander voiceContrl = {
	.commandName = "voice",
	.deviceName = "/dev/ttyAMA0",//设备名
	.command = {'\0'},			//指令
	.Init = voiceInit,//串口初始化
	.getCommand = voiceGetCommand,
	.log = {'\0'},
	.next = NULL

};

struct InputCommander* addvoiceContrlToInputCommandLink(struct InputCommander *phead)
{
	if(phead == NULL){
	return &voiceContrl;
	}
	else{
		voiceContrl.next = phead;
		phead = &voiceContrl;
		return phead;
	}
}

socketContrl.c

#include<unistd.h>
#include<wiringPi.h>
#include<stdlib.h>
#include<stdio.h>
#include<wiringSerial.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>

#include"InputCommand.h"

int socketGetCommand(struct InputCommander *socketMes)
{
	int c_fd;
	int n_read = 0;
	struct sockaddr_in c_addr;
	memset(&c_addr, 0, sizeof(struct sockaddr_in));
	int clen = sizeof(struct sockaddr_in);
	//4. accept
	c_fd = accept(socketMes->sfd, (struct sockaddr *)&c_addr, &clen);
	
	n_read = read(c_fd, socketMes->command, sizeof(socketMes->command));
	 
	if(n_read == -1){
		perror("read");
	}else if(n_read > 0){
		printf("\nget: %d\n",n_read);
	}else{
		printf("client quit\n");
	}
	return n_read;
	
}

int socketInit(struct InputCommander *socketMes, char *ipAdress, char *port)
{
	int s_fd;
	
    struct sockaddr_in s_addr;

    memset(&s_addr, 0, sizeof(struct sockaddr_in));
	
	//1.socket
    s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1)
    {
        perror("socket");
        exit(-1);
    }
	
	 s_addr.sin_family = AF_INET;
	 s_addr.sin_port = htons(atoi(socketMes->port)); //atoi()把ascii转成整形数
	                                         //htons()返回网络字节序的值(大段字节序)
	 inet_aton(socketMes->ipAddress, &(s_addr.sin_addr)); //aton()把字符串形式的IP转换成网络能识别的格式  

	//解决服务器程序结束后端口被占用的情况
	int opt = 1;
	setsockopt(s_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	 
	//2.bind
	bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));

	//3.listen
	listen(s_fd, 10);
	printf("socket server listening...\n");
	socketMes->sfd = s_fd;
	return s_fd;
	
	
}

struct InputCommander socketContrl = {
	.commandName = "socketServer",
	.command = {'\0'},			//指令
	.port = "8083",
	.ipAddress = "192.168.101.223",
	.Init = socketInit,//初始化
	.getCommand = socketGetCommand,
	.log = {'\0'},
	.next = NULL

};

struct InputCommander* addSocketContrlToInputCommandLink(struct InputCommander *phead)
{
	if(phead == NULL){
	return &socketContrl;
	}
	else{
		socketContrl.next = phead;
		phead = &socketContrl;
		return phead;
	}

}

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>

#define door_lock 0 //门锁

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("the same person\n");
						digitalWrite(door_lock, LOW);  //打开门锁
            			delay(3000);                   //等待3s
            			digitalWrite(door_lock, HIGH); //关闭门锁
                }
                else{
                        printf("different person\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;
	}
}

其余代码和上面展示的有些很类似,就不放出了。

四.项目总结

        1.做完后感觉不是很难,主要是要明白这个项目代码的设计结构和里面的一些逻辑。

        2.人脸识别功能的整合是这个项目相对复杂的地方,这里我也参考了其他博客。

        3.前面学到的编写树莓派驱动代码,各种库的使用是重点,以后也会复习。

        4.火焰和震动传感器可以同时只使用一个蜂鸣器,风扇有时会出现一些小bug,代码还有优化的地方。

物联沃分享整理
物联沃-IOTWORD物联网 » 基于树莓派的智能家居控制系统:实现舒适、便捷的生活体验

发表评论