天天看點

智能家居 (8) ——智能家居項目整合(網絡控制線程、語音控制線程,火災報警線程)mainPro.c(主函數)指令工廠控制工廠測試驗證往期文章

目錄

  • mainPro.c(主函數)
  • 指令工廠
    • inputCommand.h
    • voiceControl.c(語音控制)
    • socketControl.c(網絡線程)
  • 控制工廠
    • contrlEquipments.h
    • bathroomLight.c(浴室燈)
    • secondfloorLight.c(二樓燈)
    • livingroomLight.c(客廳燈)
    • restaurantLight.c(餐廳燈)
    • fireDetection.c(火焰傳感器)
    • buzzer.c 檔案(蜂鳴器)
  • 測試驗證
  • 往期文章

mainPro.c(主函數)

#include <stdio.h>
#include <string.h>
#include "contrlEquipments.h"
#include "inputCommand.h"
#include <pthread.h>
#include <unistd.h>

struct Equipment *findEquipByName(char *name,struct Equipment *phead);		//一些函數聲明
struct Command *findCommandByName(char *name,struct Command *phead);
void *voiceControlThread(void *data);
void *socketControlThread(void *data);
void *socketReadThread(void *data);
void *fireAlarmThread(void *data);

struct Equipment *equiphead = NULL;			//裝置工廠連結清單頭節點
struct Command *cmdhead = NULL;				//指令控制工廠連結清單節點頭
struct Command *socketHandler = NULL;		//“網絡控制線程”執行的函數使用到的全局變量


int main()
{
	if(wiringPiSetup() == -1){					//使用wiringPi庫需要初始化
		printf("wiringPiSetup failed!\n");
		return -1; 
	}

	pthread_t voiceControl_thread;
	pthread_t socketControl_thread;
	pthread_t fireAlarm_thread;

	//1、裝置工廠初始化
	equiphead = addBathroomLightToEquipmentLink(equiphead);			//各裝置加入裝置工廠
	equiphead = addSecondfloorLightToEquipmentLink(equiphead);	
	equiphead = addLivingroomLightToEquipmentLink(equiphead);
	equiphead = addRestaurantLightToEquipmentLink(equiphead);
	equiphead = addFireDetectionToEquipmentLink(equiphead);
	equiphead = addBuzzerToEquipmentLink(equiphead);

	struct Equipment *tmpequiphead = equiphead;
	while(tmpequiphead != NULL){						//裝置工廠所有裝置初始化
		tmpequiphead->Init(tmpequiphead->pinNum);
		tmpequiphead = tmpequiphead->next;
	}


	//2、指令工廠初始化
	cmdhead = addVoiceControlToCommandLink(cmdhead);				//各指令控制加入指令控制工廠
	cmdhead = addSocketControlToCommandLink(cmdhead);



	//3、線程池建立
	//3.1 語音線程   
	//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);  
	pthread_create(&voiceControl_thread,NULL,voiceControlThread,NULL);		//建立線程:語音控制
	//3.2 網絡線程 		
	pthread_create(&socketControl_thread,NULL,socketControlThread,NULL);	//建立線程:網絡控制
	//3.3 火災線程 	
	pthread_create(&fireAlarm_thread,NULL,fireAlarmThread,NULL);			//建立線程:火災報警系統
	//3.4 攝像頭線程 

	pthread_join(voiceControl_thread, NULL);		//主函數等待線程退出
	pthread_join(socketControl_thread, NULL);		//主函數等待線程退出
	pthread_join(fireAlarm_thread, NULL);			//主函數等待線程退出
	return 0;
}



void *voiceControlThread(void *data)			//“語音控制線程”執行的函數
{
	int nread;
	char *temName = NULL;
	struct Command *voiceHandler = NULL;
	struct Equipment *linkHandler;


	voiceHandler = findCommandByName("voiceControl",cmdhead);		//尋找“語音控制”所在節點,傳回給voiceHandler
	if(voiceHandler == NULL){
		printf("find voiceHandler error\n");
		pthread_exit(NULL);
	}
	if(voiceHandler->Init(voiceHandler) < 0){				//“語音控制”功能初始化
		printf("voiceControl init error\n");
		pthread_exit(NULL);
	}


	while(1){
		nread = voiceHandler->getCommand(voiceHandler);			//擷取指令
		if(nread == 0){											//沒有擷取到指令
			printf("No voiceCommand received\n");
		}else{													//擷取到指令
			printf("Get voice command:%s\n",voiceHandler->command);

			//以下為根據不用指令執行相應操作

			//語音子產品序列槽傳出來的後面帶\r\n,不加對比不出來
			if(strcmp("kysd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
				printf("已打開浴室燈\n");
			}

			if(strcmp("gysd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
				printf("已關閉浴室燈\n");
			}

			if(strcmp("keld\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("geld\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kktd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gktd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kctd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gctd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kqbd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gqbd\r\n",voiceHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

		}
	}
}


void *socketControlThread(void *data)				//“網絡控制線程”執行的函數
{
	int c_fd;
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	socklen_t clen = sizeof(struct sockaddr_in);
	pthread_t socketRead_thread; //線程裡面套線程,網絡連接配接後資訊通信


	socketHandler = findCommandByName("socketControl",cmdhead);		//尋找“網絡控制”所在節點,傳回給socketHandler
	if(socketHandler == NULL){
		printf("find socketHandler error\n");
		pthread_exit(NULL);
	}
	if(socketHandler->Init(socketHandler) < 0){				//“網絡控制”功能初始化
		printf("socketControl init error\n");
		pthread_exit(NULL);
	}


	while(1){
		c_fd = accept(socketHandler->s_fd,(struct sockaddr*)&c_addr,&clen);		//接收連接配接請求,阻塞至有用戶端完成三次握手
		socketHandler->fd = c_fd;					//将套接字描述符傳回給“網絡控制”連結清單節點

		pthread_create(&socketRead_thread,NULL,socketReadThread,NULL);			//建立新線程:用于讀取TCP端口指令
		//隻要有連接配接,就建立線程去對接。線程共用記憶體資源,同一時刻,所有裝置隻有一種狀态。也可PV操作
		//所有線程 隻操控一個結構體 c_fd  再新來一個線程(新的手機用戶端接入),前一個用戶端失效了,因為 c_fd被改了。fork()可實作多個用戶端同時控制
		//不過好像寄存器和記憶體不是完全同步的 可能緩存沒改?還可以多個用戶端同時控制?
		//如果直接把socketReadThread()拿過來循環的話,則同時刻不能接受新的用戶端接入了,因為循環卡在了socketReadThread()函數裡面了
	}
}


void *socketReadThread(void *data)				//“讀取tcp端口指令線程”執行的函數
{

	int nread;
	struct Equipment *linkHandler;
	//這裡沒加while循環,用戶端隻能發送一次

	printf("socketConnect...");
	while(1){
		memset(socketHandler->command,'\0',sizeof(socketHandler->command));		//将指令存放的空間置空
	
		nread = read(socketHandler->fd,socketHandler->command,sizeof(socketHandler->command));		//讀取指令
	
		if(nread == 0){
			printf("No socketCommand received\n");			//沒有讀取到指令
		}else{
			printf("Get socketCommand:%s\n",socketHandler->command);		//讀取到指令

			//以下為根據不用指令執行相應操作

			if(strcmp("kysd",socketHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gysd",socketHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("keld",socketHandler->command) == 0){
				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("geld",socketHandler->command) == 0){
				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kktd",socketHandler->command) == 0){
				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gktd",socketHandler->command) == 0){
				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kctd",socketHandler->command) == 0){
				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gctd",socketHandler->command) == 0){
				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

			if(strcmp("kqbd",socketHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->open(linkHandler->pinNum);

				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->open(linkHandler->pinNum);
			}

			if(strcmp("gqbd",socketHandler->command) == 0){
				linkHandler = findEquipByName("bathroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("secondfloorLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("livingroomLight",equiphead);
				linkHandler->close(linkHandler->pinNum);

				linkHandler = findEquipByName("restaurantLight",equiphead);
				linkHandler->close(linkHandler->pinNum);
			}

		}
	}
}


void *fireAlarmThread(void *data)				//“火災報警器線程”執行的函數
{
	int status;
	struct Equipment *firetmp = NULL;
	struct Equipment *buztmp = NULL;

	firetmp = findEquipByName("fireDetection",equiphead);		//尋找“火焰傳感器”連結清單節點,傳回給firetmp
	buztmp = findEquipByName("buzzer",equiphead);				//尋找“蜂鳴器”連結清單節點,傳回給buztmp

	while(1){
		status = firetmp->readStatus(firetmp->pinNum);			//讀取“火焰傳感器”狀态

		if(status == 0){						//檢測到火焰或強光源
			buztmp->open(buztmp->pinNum);		//打開蜂鳴器
			delay(1000);						//延時1000毫秒=1秒
		}

		if(status == 1){						//未檢測到火焰、強光源或解除警報
			buztmp->close(buztmp->pinNum);		//關閉蜂鳴器
		}
	}
}


struct Equipment *findEquipByName(char *name,struct Equipment *phead)		//根據名字尋找裝置工廠連結清單鍊節函數,并傳回鍊節
{
	struct Equipment *tmp = phead;

	if(phead == NULL){
		return NULL;
	}

	while(tmp != NULL){
		if(strcmp(name,tmp->equipName) == 0){
			return tmp;
		}
		tmp = tmp->next;
	}
	return NULL;
}


struct Command *findCommandByName(char *name,struct Command *phead)			//根據名字尋找指令控制工廠連結清單鍊節函數,并傳回鍊節
{
	struct Command *tmp = phead;

	if(phead == NULL){
		return NULL;
	}

	while(tmp != NULL){
		if(strcmp(name,tmp->commandName) == 0){
			return tmp;
		}
		tmp = tmp->next;
	}
	return NULL;
}
           

指令工廠

inputCommand.h

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

struct Command								//指令控制工廠連結清單節點定義
{
	char commandName[128];					//“控制方式”名字
	char deviceFilesName[128];				//存放初始化功能需要打開的檔案的路徑
	char command[32];						//存放指令
	int fd;									//存放檔案描述符 用于序列槽/用戶端fd
	int (*Init)(struct Command *file);		//“初始化”函數指針
	int s_fd;								//存放套接字描述符
	char ipAdress[32];						//存放IP位址
	char port[12];							//存放端口号
	int (*getCommand)(struct Command *cmd);	//“擷取指令”函數指針
	char log[1024];							//日志(暫未使用)

	struct Command *next;
};

struct Command *addVoiceControlToCommandLink(struct Command *phead);		//“語音控制”加入指令控制工廠連結清單函數聲明
struct Command *addSocketControlToCommandLink(struct Command *phead);		//“網絡控制”加入指令控制工廠連結清單函數聲明
           

voiceControl.c(語音控制)

#include "inputCommand.h"
#include <unistd.h>

int voiceControlInit(struct Command *file);							//“語音控制”功能初始化函數聲明
int voiceControlGetCommand(struct Command *cmd);					//“擷取指令”函數聲明
//struct Command *addVoiceControlToLink(struct Command *phead);		//“語音控制”加入指令控制工廠連結清單函數聲明


struct Command voiceControl = {				//“語音控制”連結清單節點
	.commandName = "voiceControl",
	.deviceFilesName = "/dev/ttyAMA0",
	.command = {'\0'},
	.Init = voiceControlInit,             //這裡隻是定義,還未調用改函數
	.getCommand = voiceControlGetCommand,
	.log = {'\0'},
};


int voiceControlInit(struct Command *file)
{
	int fd;
	if((fd = serialOpen(file->deviceFilesName,9600)) == -1){		//打開樹莓派序列槽,波特率為9600
		exit(-1);
	}
	file->fd = fd;				//打開序列槽檔案成功,傳回“檔案描述符”到“語音控制”連結清單節點中
}


int voiceControlGetCommand(struct Command *cmd)					//“擷取指令”函數
{
	int nread = 0;
	memset(cmd->command,'\0',sizeof(cmd->command));					//防止老的消息影響新的消息
	nread = read(cmd->fd,cmd->command,sizeof(cmd->command));		//傳回讀取到資料的位元組數
	return nread;
}


struct Command *addVoiceControlToCommandLink(struct Command *phead)		//頭插法将“語音控制”連結清單節點加入指令控制工廠連結清單函數
{
	if(phead == NULL){
		return &voiceControl;
	}else{
		voiceControl.next = phead;
		phead = &voiceControl;
		return phead;
	}
}
           

socketControl.c(網絡線程)

#include "inputCommand.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>


int socketControlInit(struct Command *file);					//“網絡控制”功能初始化函數聲明
//struct Command *addSocketControlToLink(struct Command *phead);	//“網絡控制”加入指令控制工廠連結清單函數聲明


struct Command socketControl = {		//“網絡控制”連結清單節點
	.commandName = "socketControl",
	.command = {'\0'},
	.Init = socketControlInit,
	.ipAdress = "192.168.0.19",		//樹莓派連接配接網絡時的IP位址
	.port = "8088",						//樹莓派打開待外界連接配接的端口号
	.log = {'\0'},
};


int socketControlInit(struct Command *file)
{
	int s_fd;											//套接字描述符
	struct sockaddr_in s_addr;
	memset(&s_addr,0,sizeof(struct sockaddr_in));

	s_fd = socket(AF_INET,SOCK_STREAM,0);				//建立套接字
    if(s_fd == -1){										//建立套接字失敗時
            perror("socketControl error");
            exit(-1);
    }

	s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(file->port));
    inet_aton(file->ipAdress,&s_addr.sin_addr);
	if(bind(s_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in)) == -1){		//套接字與端口号綁定
    	perror("bind error");
    	exit(-1);
    }

	if(listen(s_fd,10) == -1){		//打開監聽 accept放到主函數線程裡
    	perror("listen error");
    	exit(-1);
    }

	file->s_fd = s_fd;						//套接字描述符傳回到“網絡控制”連結清單節點
}


struct Command *addSocketControlToCommandLink(struct Command *phead)			//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &socketControl;
	}else{
		socketControl.next = phead;
		phead = &socketControl;
		return phead;
	}
}
           

控制工廠

contrlEquipments.h

#include <wiringPi.h>				//wiringPi庫
#include <stdio.h>
#include <stdlib.h>

struct Equipment								//裝置工廠連結清單節點定義
{
	char equipName[128];						//裝置名
	int pinNum;									//引腳号
	int status;									//“初始化裝置”函數指針
	int (*Init)(int pinNum);					//“打開裝置”函數指針
	int (*open)(int pinNum);					//“關閉裝置”函數指針
	int (*close)(int pinNum);

	int (*readStatus)(int pinNum);				//“讀取裝置狀态”函數指針
	int (*changeStatus)(int status);			//“改變裝置狀态函數指針”

	struct Equipment *next;
};

struct Equipment *addBathroomLightToEquipmentLink(struct Equipment *phead);			//“浴室燈”裝置節點加入裝置工廠連結清單函數聲明
struct Equipment *addSecondfloorLightToEquipmentLink(struct Equipment *phead);		//“二樓燈”裝置節點加入裝置工廠連結清單函數聲明
struct Equipment *addLivingroomLightToEquipmentLink(struct Equipment *phead);		//“客廳燈”裝置節點加入裝置工廠連結清單函數聲明
struct Equipment *addRestaurantLightToEquipmentLink(struct Equipment *phead);		//“餐廳燈”裝置節點加入裝置工廠連結清單函數聲明
struct Equipment *addFireDetectionToEquipmentLink(struct Equipment *phead);			//“火焰傳感器”裝置節點加入裝置工廠連結清單函數聲明
struct Equipment *addBuzzerToEquipmentLink(struct Equipment *phead);					//“蜂鳴器”裝置節點加入裝置工廠連結清單函數聲明
           

bathroomLight.c(浴室燈)

#include "contrlEquipments.h"

int bathroomLightInit(int pinNum);				//一些函數聲明
int bathroomLightOpen(int pinNum);
int bathroomLightClose(int pinNum);
//struct Equipment *addBathroomLightToLink(struct Equipment *phead);


struct Equipment bathroomLight = {		//“浴室燈”裝置連結清單節點
	.equipName = "bathroomLight",
	.pinNum = 26,						//樹莓派gpio引腳21
	.Init = bathroomLightInit,         
	.open = bathroomLightOpen,
	.close = bathroomLightClose,
};


int bathroomLightInit(int pinNum)			//初始化函數
{
	pinMode(pinNum,OUTPUT);					//配置引腳為輸出引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int bathroomLightOpen(int pinNum)			//打開函數
{
	digitalWrite(pinNum,LOW);
}

int bathroomLightClose(int pinNum)			//關閉函數
{
	digitalWrite(pinNum,HIGH);
}


struct Equipment *addBathroomLightToEquipmentLink(struct Equipment *phead)		//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &bathroomLight;
	}else{
		bathroomLight.next = phead;
		phead = &bathroomLight;
		return phead;
	}
}
           

secondfloorLight.c(二樓燈)

#include "contrlEquipments.h"

int secondfloorLightInit(int pinNum);				//一些函數聲明
int secondfloorLightOpen(int pinNum);
int secondfloorLightClose(int pinNum);

struct Equipment *addSecondfloorLightToEquipmentLink(struct Equipment *phead);
struct Equipment secondfloorLight = {		//“二樓燈”裝置連結清單節點
	.equipName = "secondfloorLight",
	.pinNum = 27,							//樹莓派gpio引腳22
	.Init = secondfloorLightInit,
	.open = secondfloorLightOpen,
	.close = secondfloorLightClose,
//	.changeStatus = secondfloorLightChangeStatus,
};


int secondfloorLightInit(int pinNum)			//初始化函數
{
	pinMode(pinNum,OUTPUT);					//配置引腳為輸出引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int secondfloorLightOpen(int pinNum)			//打開函數
{
	digitalWrite(pinNum,LOW);
}

int secondfloorLightClose(int pinNum)			//關閉函數
{
	digitalWrite(pinNum,HIGH);
}


struct Equipment *addSecondfloorLightToEquipmentLink(struct Equipment *phead)		//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &secondfloorLight;
	}else{
		secondfloorLight.next = phead;
		phead = &secondfloorLight;
		return phead;
	}
}
           

livingroomLight.c(客廳燈)

#include "contrlEquipments.h"

int livingroomLightInit(int pinNum);				//一些函數聲明
int livingroomLightOpen(int pinNum);
int livingroomLightClose(int pinNum);
//struct Equipment *addLivingroomLightToLink(struct Equipment *phead);


struct Equipment livingroomLight = {		//“客廳燈”裝置連結清單節點
	.equipName = "livingroomLight",
	.pinNum = 28,							//樹莓派gpio引腳23
	.Init = livingroomLightInit,
	.open = livingroomLightOpen,
	.close = livingroomLightClose,
};


int livingroomLightInit(int pinNum)				//初始化函數
{
	pinMode(pinNum,OUTPUT);					//配置引腳為輸出引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int livingroomLightOpen(int pinNum)				//打開函數
{
	digitalWrite(pinNum,LOW);
}

int livingroomLightClose(int pinNum)			//關閉函數
{
	digitalWrite(pinNum,HIGH);
}


struct Equipment *addLivingroomLightToEquipmentLink(struct Equipment *phead)			//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &livingroomLight;
	}else{
		livingroomLight.next = phead;
		phead = &livingroomLight;
		return phead;
	}
}
           

restaurantLight.c(餐廳燈)

#include "contrlEquipments.h"

int restaurantLightInit(int pinNum);				//一些函數聲明
int restaurantLightOpen(int pinNum);
int restaurantLightClose(int pinNum);
//struct Equipment *addRestaurantLightToLink(struct Equipment *phead);


struct Equipment restaurantLight = {		//“餐廳燈”裝置連結清單節點
	.equipName = "restaurantLight",
	.pinNum = 29,							//樹莓派gpio引腳24
	.Init = restaurantLightInit,
	.open = restaurantLightOpen,
	.close = restaurantLightClose,
};


int restaurantLightInit(int pinNum)				//初始化函數
{
	pinMode(pinNum,OUTPUT);					//配置引腳為輸出引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int restaurantLightOpen(int pinNum)				//打開函數
{
	digitalWrite(pinNum,LOW);
}

int restaurantLightClose(int pinNum)			//關閉函數
{
	digitalWrite(pinNum,HIGH);
}


struct Equipment *addRestaurantLightToEquipmentLink(struct Equipment *phead)			//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &restaurantLight;
	}else{
		restaurantLight.next = phead;
		phead = &restaurantLight;
		return phead;
	}
}
           

fireDetection.c(火焰傳感器)

#include "contrlEquipments.h"

int fireDetectionInit(int pinNum);					//一些函數聲明
int readFireDetectionStatus(int pinNum);
//struct Equipment *addFireDetectionToLink(struct Equipment *phead);


struct Equipment fireDetection = {			//“火焰傳感器”裝置連結清單節點
	.equipName = "fireDetection",
	.pinNum = 21,							//樹莓派gpio引腳25
	.Init = fireDetectionInit,
	.readStatus = readFireDetectionStatus,
};


int fireDetectionInit(int pinNum)			//初始化函數
{
	pinMode(pinNum,INPUT);					//配置引腳為輸入引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int readFireDetectionStatus(int pinNum)		//讀取“火焰傳感器”狀态函數
{
	return digitalRead(pinNum);
}


struct Equipment *addFireDetectionToEquipmentLink(struct Equipment *phead)
{
	if(phead == NULL){
		return &fireDetection;
	}else{
		fireDetection.next = phead;
		phead = &fireDetection;
		return phead;
	}
}
           

buzzer.c 檔案(蜂鳴器)

#include "contrlEquipments.h"

int buzzerInit(int pinNum);					//一些函數聲明
int buzzerOpen(int pinNum);
int buzzerClose(int pinNum);
struct Equipment *addBuzzerToEquipmentLink(struct Equipment *phead);


struct Equipment buzzer = {			//“蜂鳴器”裝置連結清單節點
	.equipName = "buzzer",
	.pinNum = 22,					//樹莓派gpio引腳29
	.Init = buzzerInit,
	.open = buzzerOpen,
	.close = buzzerClose,
};


int buzzerInit(int pinNum)					//初始化函數
{
	pinMode(pinNum,OUTPUT);					//配置引腳為輸出引腳
	digitalWrite(pinNum,HIGH);				//引腳輸出高電平,即預設為關閉狀态
}

int buzzerOpen(int pinNum)					//打開函數
{
	digitalWrite(pinNum,LOW);
}

int buzzerClose(int pinNum)					//關閉函數
{
	digitalWrite(pinNum,HIGH);
}


struct Equipment *addBuzzerToEquipmentLink(struct Equipment *phead)			//頭插法将裝置節點加入裝置工廠連結清單函數
{
	if(phead == NULL){
		return &buzzer;
	}else{
		buzzer.next = phead;
		phead = &buzzer;
		return phead;
	}
}
           

測試驗證

所有代碼均可編譯運作,3個線程均通過實驗驗證。

後期将網絡線程整合在手機app上,進而實作手機端遠端控制和監測智能家居,需要繼續學習JAVA以及Android知識。

往期文章

智能家居 (1) ——智能家居整體功能架構

智能家居 (2) ——設計模式的引入

智能家居 (3) ——工廠模式繼電器控制燈

智能家居 (4) ——工廠模式火焰報警

智能家居 (5) —— LD3320語音子產品二次開發

智能家居 (6) ——語音識别線程控制

智能家居 (7) ——網絡伺服器線程控制

智能家居 (8) ——智能家居項目整合(網絡控制線程、語音控制線程,火災報警線程)

網絡程式設計知識預備(1) ——了解OSI網絡模型

網絡程式設計知識預備(2) ——淺顯易懂的三次握手與四次揮手

網絡程式設計知識預備(3) ——SOCKET、TCP、HTTP之間的差別與聯系

網絡程式設計知識預備(4) ——了解HTTP協定與HTTPS協定

網絡程式設計知識預備(5) ——libcurl庫簡介及其程式設計使用

智能家居 (9) ——人臉識别攝像頭安裝實作監控功能

智能家居 (10) ——人臉識别祥雲平台程式設計使用

智能家居 (11) ——樹莓派攝像頭捕捉人臉并識别

智能家居 (12) ——人臉識别整合到智能家居系統

智能家居 (13) ——智能家居加入手機app端控制

繼續閱讀