主頁 >  其他 > 樹莓派-智能家居-擴展是wemosD1

樹莓派-智能家居-擴展是wemosD1

2021-07-27 09:07:53 其他

目錄

1、主函式

mainPro.c

2、分檔案(所有的外設設備都是物件)

bathroomLight.c (浴室燈)

livingroomLight.c (睡房燈)

restaurantLight.c (廚房燈)

upstairLight.c (客廳燈)

buzzer.c(蜂鳴器)

fire.c (火焰傳感器)

camera.c (攝像頭)

client_wemos.c (樹莓派作為客戶端 連接wemos D1服務器)

socketContrl.c (socket控制)

voiceContrl.c(語音控制設備)

3、頭檔案

contrlDevices.h(外設設備的頭檔案)

inputCommand.h (控制的頭檔案)


本文只是匆匆的上傳一下代碼而已,很多細節并沒有涉及,主要是方便以后自己撰寫代碼時整體思路的參考,

運用的是簡單工廠設計模式(普通編碼,仿內核設計模式),簡化main函式代碼,便于閱讀,所有控制以及外設的設備都做成一個個物件(java思想),分別將命令控制的連成一個控制鏈表,外設設備做成一個外設設備的鏈表,這樣做是為了方便以后功能模塊的添加,其中為了能分別做好控制,我們采用多執行緒來實作,

控制端:

語音控制,socket控制

硬體設備:

樹莓派、語音模塊、wemos D1、繼電器組、433M 射頻模塊、攝像頭、火焰傳感器、電磁鎖、蜂鳴器,

專案描述:

樹莓派通過串口連接各模塊硬體,檢測語音的識別結果,分析語音識別的結果來對家電設備進行控制,樹莓派攝像頭拍攝到人臉之后通過HTTPS訪問翔云平臺的人臉識別方案對比照片的base64編碼來進行人臉識別開鎖,由于語音模塊占用了樹莓派唯一的串口位,為了保留語音控制,所以,我將Wemos D1做成了服務器,讓樹莓派變為客戶端使用socket和wemos進行連接,wemos通過讀取樹莓派作為客戶端發送過來的資料來控制家電設備,完成了對于樹莓派的介面拓展,以便控制更多的設備,

紅外控制想做的,但是我的辣雞雜牌空調不支持我的這個紅外編解碼板子,所以這算是個小遺憾,

1、主函式

mainPro.c

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

#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "contrlDevices.h"
#include "inputCommand.h"

pthread_t voiceThread; 	//注意:定義執行緒不使用指標以免空指標例外
pthread_t socketThread;	//注意:不建議執行緒傳參(鏈表頭)所以定為全域變數
pthread_t fireThread;
pthread_t cameraThread;
pthread_t clientWemosThread;

struct InputCommander *pCommandHead = NULL;  
struct Devices		  *pdeviceHead = NULL;
struct InputCommander *socketHandler = NULL; 
struct InputCommander *clientHandler = NULL;

pthread_mutex_t mutex;  //定義互斥量(鎖)
//pthread_cond_t  cond;   //條件 

int c_fd;			    //注意:涉及到多執行緒不要輕易的去傳參

//攝像頭相關
#define true 1
#define false 0
typedef unsigned int bool;
char buf[1024] = {'\0'};

struct Devices *findDeviceByName(char *name,struct Devices *phead)
{
	if(phead == NULL){
		return NULL;
	}
	while(phead != NULL){
		if(strstr(phead->deviceName,name) != NULL){
			return phead;
		}
		phead = phead->next;
	}
	
	return NULL;
}

struct InputCommander *findCommandByName(char *name,struct InputCommander *phead)
{
	if(phead == NULL){
		return NULL;
	}
	while(phead != NULL){
		if(strcmp(phead->commandName,name) == 0){
			return phead;
		}
		phead = phead->next;
	}
	return NULL;
}


void *voice_thread(void *arg)
{
	int i = 0;
	int nread;
	struct InputCommander *voiceHandler = NULL;
	struct Devices *deviceTmp = 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("%s init success\n",voiceHandler->commandName);
		} //語音初始化完成

pthread_mutex_lock(&mutex);    //加鎖    
                               //為什么加這個鎖呢,我的想法是在語音讀取一級指令的時候,為了避免其它執行緒對于 緊接著讀取二級指令的干擾

		while(1){			
			memset(voiceHandler->comand,'\0',sizeof(voiceHandler->comand));
		
			nread = voiceHandler->getCommand(voiceHandler);	
			if(nread == 0){
				//printf("noData from voice,please say again\n");
			}else if(strstr(voiceHandler->comand,"all") != NULL){
				printf("close all light\n");
				deviceTmp = findDeviceByName("yu",pdeviceHead);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("ke",pdeviceHead);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("chu",pdeviceHead);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("shui",pdeviceHead);
				deviceTmp->close(deviceTmp->pinNum);
			}
			else{ 
				deviceTmp = findDeviceByName(voiceHandler->comand,pdeviceHead);
				if(deviceTmp == NULL){
					printf("findDeviceByName error\n");
				}
				else{
					printf("findDevice = %s\n",deviceTmp->deviceName);
					deviceTmp->deviceInit(deviceTmp->pinNum);
					deviceTmp->open(deviceTmp->pinNum);
				}
			}			
			
		}
		
pthread_mutex_unlock(&mutex);    //解鎖

	}
}



size_t readData1( void *ptr, size_t size, size_t nmemb, void *stream)
{
	memset(buf,'\0',1024);
	strncpy(buf,ptr,1024);

}

char *getBase641(char *picture)
{
	int fd;
	int len;
	char cmd[256] = {'\0'};	

	sprintf(cmd,"base64 %s > pictureBase64File",picture);
	system(cmd);

	fd = open("./pictureBase64File",O_RDWR);
	len = lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);

	char *readBuf = (char *)malloc(len);	//如果不是用動態,當我們將這個readBuf指標回傳去,則會段錯誤
	read(fd,readBuf,len);			//因為,readBuf是區域變數,靜態記憶體,程式一運行完畢,里面的內容被釋放(C語言基礎)
	close(fd);
	system("rm ./pictureBase64File");

	return readBuf;
}

bool cameraContrlPostUrl()
{
	CURL *curl;
	CURLcode res;
	char *postString;
	struct Devices *deviceTmp = NULL;

	char *img1;
	char *img2;
	char *key = "用自己的";
	char *secret = "用自己的";
	int typeId = 21;
	char *format = "xml";

	
	chdir("/home/pi/mjpg-streamer/mjpg-streamer-experimental");
 	system("./start.sh");    //運行攝像頭
	chdir("/home/pi/yu/smartHome5_camera+face");
	system("wget  http://172.20.10.2:8080/?action=snapshot -O ./visitor.jpg"); 	//截圖實時視頻的照片

	img1 = getBase641("./visitor.jpg");
	img2 = getBase641("./me1.jpg");

	int len = strlen(key)+strlen(secret)+strlen(img1)+strlen(img2)+124;
	postString = (char *)malloc(strlen(key)+strlen(secret)+strlen(img1)+strlen(img2)+124);
	memset(postString,'\0',len);

	sprintf(postString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",  //postString
			img1,img2,key,secret,typeId,format);

	system("rm visitor.jpg");

	curl = curl_easy_init();

	if (curl)
	{
		curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie檔案
		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); //將回傳的http頭輸出到fp指向的檔案
		res = curl_easy_perform(curl);
		printf("ok = %d\n",res);

		curl_easy_cleanup(curl);

		
		printf("%s\n",buf);
		
		if(strstr(buf,"是") != NULL){
				deviceTmp = findDeviceByName("chu",pdeviceHead);
				deviceTmp->open(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("yu",pdeviceHead);
				deviceTmp->open(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("ke",pdeviceHead);
				deviceTmp->open(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("shui",pdeviceHead);	
				deviceTmp->open(deviceTmp->pinNum);					
		}else{
			printf("not a same of man\n");		
		}
		
	}
	return true;	
}

void *read_thread(void *datas)
{
	int n_read;
	struct Devices *deviceTmp = NULL;
	
	while(1){
		memset(socketHandler->comand,'\0',sizeof(socketHandler->comand));

		n_read = read(c_fd,socketHandler->comand,sizeof(socketHandler->comand));
		if(n_read == -1){
			perror("read_thread");
		}else if(n_read > 0){
			//printf("getCommand:%s\n",socketHandler->comand);
		
			//處理客戶端讀到的命令
			if(strstr(socketHandler->comand,"op_shui") != NULL){
				deviceTmp = findDeviceByName("shui",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->open(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"cl_shui") != NULL){
				deviceTmp = findDeviceByName("shui",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"op_yu") != NULL){
				deviceTmp = findDeviceByName("yu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->open(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"cl_yu") != NULL){
				deviceTmp = findDeviceByName("yu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"op_ke") != NULL){
				deviceTmp = findDeviceByName("ke",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->open(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"cl_ke") != NULL){
				deviceTmp = findDeviceByName("ke",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
			}						
			if(strstr(socketHandler->comand,"op_chu") != NULL){
				deviceTmp = findDeviceByName("chu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->open(deviceTmp->pinNum);
			}
			if(strstr(socketHandler->comand,"cl_chu") != NULL){
				deviceTmp = findDeviceByName("chu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
			}
            if(strcmp(socketHandler->comand,"1") == 0){    //發送資料給wemos
                                memset(clientHandler,'\0',sizeof(clientHandler));
                                strcpy(clientHandler->comand,"1");
                                write(clientHandler->sfd,clientHandler->comand,strlen(clientHandler->comand));     
                        }
            if(strcmp(socketHandler->comand,"2") == 0){    //發送資料給wemos
                                memset(clientHandler,'\0',sizeof(clientHandler));
                                strcpy(clientHandler->comand,"2");
                                write(clientHandler->sfd,clientHandler->comand,strlen(clientHandler->comand));     
                        }
			if(strstr(socketHandler->comand,"face") != NULL){    //進行人臉識別
				//deviceTmp = findDeviceByName("face",pdeviceHead);
				//deviceTmp->cameraInit(deviceTmp);
				cameraContrlPostUrl();
			}
			if(strstr(socketHandler->comand,"cl_all") != NULL){
				deviceTmp = findDeviceByName("chu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("yu",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("ke",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);
				deviceTmp = findDeviceByName("shui",pdeviceHead);
				deviceTmp->deviceInit(deviceTmp->pinNum);
				deviceTmp->close(deviceTmp->pinNum);				
			}

		}
		else{
			printf("client quit\n");
			exit(-1);				//客戶端退出,服務器程式退出
			//pthread_exit(NULL);  //退出執行緒
		}
	}
	
}

void *socket_thread(void *datas)
{
	int n_read = 0;
	pthread_t readPthread;
	
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	int clen = sizeof(struct sockaddr_in);
	
	socketHandler = findCommandByName("socketServer",pCommandHead);
	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(&readPthread,NULL,read_thread,NULL);
	}
	
}

void *fire_thread(void *datas)
{
	int status;
	struct Devices *fireDeviceTmp = NULL;
	struct Devices *buzzerDeviceTmp = NULL;

	fireDeviceTmp = findDeviceByName("fire",pdeviceHead);
	buzzerDeviceTmp = findDeviceByName("buzzser",pdeviceHead);
	
	fireDeviceTmp->deviceInit(fireDeviceTmp->pinNum);
	buzzerDeviceTmp->deviceInit(buzzerDeviceTmp->pinNum);
	printf("fire_thread init\n");

   	while(1){
		delay(2000);
		status = fireDeviceTmp->readStatus(fireDeviceTmp->pinNum);
		//printf("fire get data = %d\n",status);

		if(status == 0){
			buzzerDeviceTmp->open(buzzerDeviceTmp->pinNum);
		}else{
			buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum);
		}
    }
}

void *camera_thread(void *datas)
{
	
}

void *clientWemos_Thread(void *datas)    //連接wemos
{
	char *p;
	//struct InputCommander *clientHandler = NULL;    //放到全域,因為我要在socket那里接收用戶客戶端client的資料,然后發給wemos

	//做客戶端連接wemosD1服務器
	clientHandler = findCommandByName("client",pCommandHead);
	if(clientHandler == NULL){
		printf("find clientHandler error\n");
		exit(-1);
	}else{
		clientHandler->Init(clientHandler,NULL,NULL);
	}
	
	while(1){		
		memset(clientHandler,'\0',sizeof(clientHandler));
        printf("input your contrl wemosD1 command::\n");
        fgets(clientHandler->comand,sizeof(clientHandler->comand),stdin);  //不用gets,有警告
		if((p = strchr(clientHandler->comand,'\n')) != NULL)
        *p = '\0';		//手動將\n位置處的值變為0
        
        write(clientHandler->sfd,clientHandler->comand,strlen(clientHandler->comand));     //向wemosD1發送資料
	}
}

int main()
{
	char name[32] = {'\0'};

	//樹莓派庫初始化
	if(wiringPiSetup() == -1){     
          printf("硬體介面初始化失敗\n");
          return -1;
    }
	
	pthread_mutex_init(&mutex,NULL);  //初始化互斥量(鎖)
	//pthread_cond_init(&cond,NULL);      //條件的創建(動態初始化)

	//1、指令工廠初始化
	pCommandHead = addVoiceContrlToInputCommanderLink(pCommandHead);
    pCommandHead = addsocketContrlToInputCommanderLink(pCommandHead);
	pCommandHead = addclientContrlToInputCommanderLink(pCommandHead);

	//2、設備控制工程初始化
	pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addupStairLightToDeviceLink(pdeviceHead);
	pdeviceHead = addlivingroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addrestaurantLightToDeviceLink(pdeviceHead);
	pdeviceHead = addFireToDeviceLink(pdeviceHead);
	pdeviceHead = addBuzzerToDeviceLink(pdeviceHead);
	//pdeviceHead = addcameraContrlToDeviceLink(pdeviceHead);


	//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
	//3、執行緒池的建立
		//3.1、語音執行緒
	pthread_create(&voiceThread,NULL,voice_thread,NULL); //引數2:執行緒屬性,一般設定為NULL,引數3:執行緒干活的函式,引數4:往voice_thread執行緒里面傳送資料,
		//3.2、socket服務器執行緒
	pthread_create(&socketThread,NULL,socket_thread,NULL); 
		//3.3、火災執行緒
	pthread_create(&fireThread,NULL,fire_thread,NULL); 
		//3.4、攝像頭執行緒
	//pthread_create(&cameraThread,NULL,camera_thread,NULL); 
		//3.5、作為客戶端連接wemosD1服務器
	pthread_create(&clientWemosThread,NULL,clientWemos_Thread,NULL); 


	//等待執行緒
	pthread_join(voiceThread,NULL);	
	pthread_join(socketThread,NULL);	
	pthread_join(fireThread,NULL);	
	pthread_join(cameraThread,NULL);	
	pthread_join(clientWemosThread,NULL);

	pthread_mutex_destroy(&mutex);	//銷毀互斥量
	//pthread_cond_destroy(&cond);        //條件的銷毀


	/*開始創建設備工廠的除錯代碼
	while(1){
		printf("input:\n");
		memset(name,'\0',sizeof(name));
		gets(name);

		tmp = findDeviceByName(name,pdeviceHead);
		if(tmp != NULL){
			tmp->deviceInit(tmp->pinNum);
			tmp->open(tmp->pinNum);
		}
		
	}
*/	

	return 0;
}

2、分檔案(所有的外設設備都是物件)

bathroomLight.c (浴室燈)


#include "contrlDevices.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",
	.deviceName = "yu",
	.pinNum = 22,
	.open = bathroomLightOpen,
	.close = bathroomLightClose,
	.deviceInit = bathroomLightCloseInit,
	.changStatus = bathroomLightCloseStatus
};

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

livingroomLight.c (睡房燈)


#include "contrlDevices.h"

int livingroomLightOpen(int pinNum)
{
	digitalWrite (pinNum,LOW);
}

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

int livingroomLightCloseInit(int pinNum)
{
	pinMode (pinNum, OUTPUT);
	digitalWrite (pinNum,HIGH);
}

int livingroomLightCloseStatus(int status)
{

}

struct Devices livingroomLight = {
	//.deviceName = "livingroomLight",
	.deviceName = "shui",
	.pinNum = 21,
	.open = livingroomLightOpen,
	.close = livingroomLightClose,
	.deviceInit = livingroomLightCloseInit,
	.changStatus = livingroomLightCloseStatus
};

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


restaurantLight.c (廚房燈)


#include "contrlDevices.h"

int restaurantLightOpen(int pinNum)
{
	digitalWrite (pinNum,LOW);
}

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

int restaurantLightCloseInit(int pinNum)
{
	pinMode (pinNum, OUTPUT);
	digitalWrite (pinNum,HIGH);
}

int restaurantLightCloseStatus(int status)
{

}

struct Devices restaurantLight = {
	//.deviceName = "restaurantLight",
	.deviceName = "chu",
	.pinNum = 23,
	.open = restaurantLightOpen,
	.close = restaurantLightClose,
	.deviceInit = restaurantLightCloseInit,
	.changStatus = restaurantLightCloseStatus
};

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


upstairLight.c (客廳燈)


#include "contrlDevices.h"

int upStairLightOpen(int pinNum)
{
	digitalWrite (pinNum,LOW);
}

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

int upStairLightCloseInit(int pinNum)
{
	pinMode (pinNum, OUTPUT);
	digitalWrite (pinNum,HIGH);
}

int upStairLightCloseStatus(int status)
{

}

struct Devices upStairLight = {
	//.deviceName = "upStairLight",
	.deviceName = "ke",
	.pinNum = 24,
	.open = upStairLightOpen,			
	.close = upStairLightClose,
	.deviceInit = upStairLightCloseInit,
	.changStatus = upStairLightCloseStatus
};

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


buzzer.c(蜂鳴器)


#include "contrlDevices.h"

int buzzerOpen(int pinNum)
{
	digitalWrite (pinNum,LOW);
}

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

int buzzerInit(int pinNum)
{
	pinMode (pinNum, OUTPUT);
	digitalWrite (pinNum,HIGH);
}


struct Devices buzzer = {
	.deviceName = "buzzser",
	.pinNum = 7,
	.open = buzzerOpen,
	.close = buzzerClose,
	.deviceInit = buzzerInit
};

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


fire.c (火焰傳感器)


#include "contrlDevices.h"

int fireInit(int pinNum)
{
	pinMode (pinNum,INPUT);
	digitalWrite (pinNum,HIGH);
}

int readFireStatus(int pinNum)
{
	return digitalRead(pinNum);
}


struct Devices fire = {
	.deviceName = "fire",
	.pinNum = 25,
	.deviceInit = fireInit,
	.readStatus = readFireStatus
};

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



camera.c (攝像頭)

#include "contrlDevices.h"

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#define true 1
#define false 0
typedef unsigned int bool;

char resultBuf[1024] = {'\0'};

size_t readData( void *ptr, size_t size, size_t nmemb, void *stream)    //回呼函式
{
	strncpy(resultBuf,ptr,1024);
	//printf("%s\n",resultBuf);
}	

char *getBase64(char *picture)    //獲取圖片的base64流
{
	int fd;
	int len;
	char cmd[256] = {'\0'};	

	sprintf(cmd,"base64 %s > pictureBase64File",picture);
	system(cmd);

	fd = open("./pictureBase64File",O_RDWR);
	len = lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);

	char *readBuf = (char *)malloc(len);	//如果不是用動態,當我們將這個readBuf指標回傳去,則會段錯誤
	read(fd,readBuf,len);			//因為,readBuf是區域變數,靜態記憶體,程式一運行完畢,里面的內容被釋放(C語言基礎)
	close(fd);
	system("rm ./pictureBase64File");

	return readBuf;
}

bool cameraContrl_postUrl(struct Devices *camera)
{
	CURL *curl;
	CURLcode res;
	char *postString;

	char *img1;
	char *img2;

	system("raspistill -w 700 -h 525 -o ./visitor.jpg");

	img1 = getBase64("./visitor.jpg");
	img2 = getBase64("./me1.jpg");

	int len = strlen(camera->key)+strlen(camera->secret)+strlen(img1)+strlen(img2)+124;
	postString = (char *)malloc(strlen(camera->key)+strlen(camera->secret)+strlen(img1)+strlen(img2)+124);
	memset(postString,'\0',len);

	sprintf(postString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",  
			img1,img2,camera->key,camera->secret,camera->typeId,camera->format);

	system("rm visitor.jpg");

	curl = curl_easy_init();

	if (curl)
	{
		curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie檔案
		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); //將回傳的http頭輸出到fp指向的檔案
		res = curl_easy_perform(curl);
		res = curl_easy_perform(curl);
		//printf("ok = %d\n",res);
	


		printf("%s\n",resultBuf);
		if(strstr(resultBuf,"是") != NULL){
				printf("ok\n");
		}else{
				printf("no\n");
		}

		curl_easy_cleanup(curl);
	}
	return true;
}


struct Devices cameraContrl = {
	.deviceName = "camera",
	.key = "用自己的",
	.secret = "用自己的",
	.typeId = 21,
	.format = "xml",
	.cameraInit = cameraContrl_postUrl,

	.next = NULL
};

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


client_wemos.c (樹莓派作為客戶端 連接wemos D1服務器

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

#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "inputCommand.h"

int clientInit(struct InputCommander *client,char *ipAdress,char *port)
{
        struct sockaddr_in addr;
 
        memset(&addr,0,sizeof(struct sockaddr_in));
 
        //1.socket 創建套接字
        int s_fd=socket(AF_INET, SOCK_STREAM,0);        
        if (s_fd==-1)
        {
                perror("socket");
                exit(-1);
        }
 
        addr.sin_family=AF_INET;
        addr.sin_port=htons(atoi(client->port));
        inet_aton(client->ipAdress,&addr.sin_addr);
 
        //2.connect 連接服務器
        if(connect(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr))==-1)  //這里是連接wemosD1
        {
                perror("connect");
                exit(-1);
        }
        printf("client wemosD1 connect....\n");

		client->sfd = s_fd;
		return s_fd;

}

struct InputCommander clientContrl = {
	.commandName = "client",       //加入到控制鏈表的名字
	.comand = {'\0'},              //命令
	.port = "8888",                //wemosD1 埠號
	.ipAdress = "172.20.10.12",    //wemosD1 IP地址
	.Init = clientInit,            //樹莓派客戶端初始化
	.next = NULL
};

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

socketContrl.c (socket控制)

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

#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#include "inputCommand.h"

int socketgetCommand(struct InputCommander *socketMes)
{
	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);

	//4.accept ����
	c_fd = accept(socketMes->sfd,(struct sockaddr *)&c_addr, &clen);

	n_read = read(c_fd,socketMes->comand,sizeof(socketMes->comand));
	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("socked");
		exit(-1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(socketMes->port));
	inet_aton(socketMes->ipAdress,&s_addr.sin_addr);

	//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",
	.comand = {'\0'},
	.port = "8083",             
	.ipAdress = "172.20.10.2",
	.Init = socketInit,
	.getCommand = socketgetCommand,
	.log = {'\0'},
	.next = NULL
};

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



voiceContrl.c(語音控制設備)

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

#include "inputCommand.h"

int getCommand(struct InputCommander *voicer)
{
	int nread = 0;
	memset(voicer->comand,'\0',sizeof(voicer->comand));

	 nread = read(voicer->fd,voicer->comand,sizeof(voicer->comand));

	 return nread;

}

int voiceInit(struct InputCommander *voicer,char *ipAdress,char *port)
{
	/*形參雖然定多了,用不上,咱不管*/
	
	int fd;

	 if((fd = serialOpen(voicer->deviceName,9600)) == -1){
		exit(-1);
	 }
	 voicer->fd = fd;
	 
	 return fd;
}


struct InputCommander voiceContrl = {
	.commandName = "voice",
	.deviceName = "/dev/ttyAMA0",
									//.boTelv = "9600";
	.comand = {'\0'},
	.Init = voiceInit,
	.getCommand = getCommand,
	.log = {'\0'},
	.next = NULL
};

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


3、頭檔案

contrlDevices.h(外設設備的頭檔案)

#include <wiringPi.h>
#include <stdio.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 (*changStatus)(int status);    //改變資料函式指標

	//攝像頭相關的
	CURL *curl;
	char *key;
	char *secret;
	int typeId;
	char *format;
	bool (*cameraInit)(struct Devices *camera);
	int yesNum;
	int noNum;

	struct Devices *next;
};

//每個設備加到鏈表函式的宣告
struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices *addupStairLightToDeviceLink(struct Devices *phead);
struct Devices *addlivingroomLightToDeviceLink(struct Devices *phead);
struct Devices *addrestaurantLightToDeviceLink(struct Devices *phead);
struct Devices *addFireToDeviceLink(struct Devices *phead);
struct Devices *addBuzzerToDeviceLink(struct Devices *phead);
struct Devices *addcameraContrlToDeviceLink(struct Devices *phead);

inputCommand.h (控制的頭檔案)

#include <wiringPi.h>
#include <stdio.h>

struct InputCommander
{
	char commandName[128];		//socket名
	char deviceName[128];		//串口名
	char comand[32];			//控制命令

	int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);	//socket初始化
	int (*getCommand)(struct InputCommander *voicer);						//讀取資料

	char log[1024];
	int fd;
	char port[12];     //埠號
	char ipAdress[32]; //IP地址
	int sfd;
	int cfd;		   
	
	struct InputCommander *next;
};

//每個控制添加到控制鏈表的函式宣告
struct InputCommander *addVoiceContrlToInputCommanderLink(struct InputCommander *phead);
struct InputCommander *addsocketContrlToInputCommanderLink(struct InputCommander *phead);
struct InputCommander *addclientContrlToInputCommanderLink(struct InputCommander *phead);

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290380.html

標籤:其他

上一篇:【OpenCV】QT編譯opencv與opencv_contrib

下一篇:Python實時音頻識別與處理——讓上網課不再單調

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more