基于ARM树莓派实现智能家居:语音识别控制,Socket网络控制,火灾报警检测,实时监控

news2025/1/16 3:54:27

目录

一   项目说明

①   设计框架

②   功能说明

③   硬件说明

④   软件说明

二   项目代码

<1> mainPro.c 主函数

<2> InputCommand.h 控制设备头文件

<3> contrlDevices.h 外接设备头文件

<4> bathroomLight.c 泳池灯

<5> livingroomLight.c 卧室灯

<6> restaurantLight.c 餐厅灯

<7> upstairLight.c 二楼灯

<8> fire.c 火焰传感器

<9> beep.c 蜂鸣器

<10> voiceContrl.c 语音模块

<11> socketContrl.c 服务器

三   项目演示

四   项目问题总结

问题一

问题二

问题三

问题四 

五   项目相关知识点整理


一   项目说明

①   设计框架

● 项目架构采用简单工厂模式来设计,将语音识别,TCP服务器设计成链表的每个节点,形成控制工厂。

● 将餐厅灯,卧室灯,二楼灯,泳池灯,蜂鸣器,火焰检测模块,也设计成链表的每个节点,形成设备端工厂。

● 基于这种架构保证项目的稳定性和功能拓展性,在添加新功能的时候,只需要添加一个链表节点文件文件就可以。

● 不管是设备端还是控制端,在实际调试过程中又涉及到临界资源的竞争,所以采用多线程来解决这个问题。

● 语音处理用的是SU-03T模块的二次开发,对串口数据进行修改并整合到树莓派的串口通信中去。

②   功能说明

● 语音模块识别语音来控制各个灯的开关,基于串口通信来配置语音命令的内容。

● 搭建TCP服务器,用socket网络通信的方式控制各个灯的开关,手机客户端发送指令到电脑服务器端来实现控制功能。

● 火灾报警,火焰检测模块结合蜂鸣器开发。接收火焰状态,检测有火源靠近时,蜂鸣器输出低电平发出警报声响,并在终端显示火灾危险提示,检测没有火源时,蜂鸣器输出高电平,停止报警声。

● 实时监控,将摄像头模块安装于树莓并配置树莓派摄像头的接口参数,打开摄像头,写入树莓ip地址及端口即可。

③   硬件说明

树莓派开发板(3B),继电器组,房屋模型,蜂鸣器,语音模块,火焰检测模块,电池盒,摄像头,杜邦线,灯具,USB-TTL模块(串口调试)

④   软件说明

SecureCRT8.0(树莓派终端),sourceinsight(代码编辑),filezilla(文件传输),AiThinker Serial Tool(串口调试),NetAssist(网络调试)。

二   项目代码

<1> mainPro.c 主函数

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

#include "contrlDevices.h"//外接设备
#include "InputCommand.h"//控制

struct InputCommander *pCommandHead = NULL;
struct Devices *pdeviceHead = NULL;
struct InputCommander *socketHandler = NULL;
int c_fd;

//外设的设备查询
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 Command(struct InputCommander *CmdHandler)
{
		struct Devices *tmp =NULL;
	 
		if(strcmp("yo",CmdHandler->command) == 0){
			tmp = findDeviceByName("bathroomLight",pdeviceHead);
			if(tmp != NULL){
				tmp->open(tmp->pinNum);
				printf("已打开泳池灯\n");
			}
		}
		
		if(strcmp("yc",CmdHandler->command) == 0){	
			tmp = findDeviceByName("bathroomLight",pdeviceHead);   
			if(tmp != NULL){      
				tmp->close(tmp->pinNum);      
				printf("已关闭泳池灯\n");   
			}	
		}  

		if(strcmp("eo",CmdHandler->command) == 0){
			tmp = findDeviceByName("upstairLight",pdeviceHead);
			if(tmp != NULL){
				tmp->open(tmp->pinNum);
				printf("已打开二楼灯\n");
			}
		}
		if(strcmp("ec",CmdHandler->command) == 0){	
			tmp = findDeviceByName("upstairLight",pdeviceHead);   
			if(tmp != NULL){      
				tmp->close(tmp->pinNum);      
				printf("已关闭二楼灯\n");   
			}	
		}
		if(strcmp("co",CmdHandler->command) == 0){
			tmp = findDeviceByName("restauranLight",pdeviceHead);
			if(tmp != NULL){
				tmp->open(tmp->pinNum);
				printf("已打开餐厅灯\n");
			}
		}
		if(strcmp("cc",CmdHandler->command) == 0){	
			tmp = findDeviceByName("restauranLight",pdeviceHead);   
			if(tmp != NULL){      
				tmp->close(tmp->pinNum);      
				printf("已关闭餐厅灯\n");   
			}	
		}
		if(strcmp("wo",CmdHandler->command) == 0){
			tmp = findDeviceByName("livingroomLight",pdeviceHead);
			if(tmp != NULL){
				tmp->open(tmp->pinNum);
				printf("已打开卧室灯\n");
			}
		}
		if(strcmp("wc",CmdHandler->command) == 0){	
			tmp = findDeviceByName("livingroomLight",pdeviceHead);   
			if(tmp != NULL){      
				tmp->close(tmp->pinNum);      
				printf("已关闭卧室灯\n");   
			}	
		}
	if(strcmp("ao",CmdHandler->command) == 0){	
			tmp = findDeviceByName("bathroomLight",pdeviceHead);		
		if(tmp != NULL)  tmp->open(tmp->pinNum);	
			tmp = findDeviceByName("upstairLight",pdeviceHead);	
		if(tmp != NULL)  tmp->open(tmp->pinNum);		
			tmp = findDeviceByName("restauranLight",pdeviceHead);	
		if(tmp != NULL)  tmp->open(tmp->pinNum);		
			tmp = findDeviceByName("livingroomLight",pdeviceHead);	
		if(tmp != NULL)  tmp->open(tmp->pinNum);       
			printf("已打开所有灯\n");    
	}    
	if(strcmp("ac",CmdHandler->command) == 0){	
			tmp = findDeviceByName("bathroomLight",pdeviceHead);		
		if(tmp != NULL)  tmp->close(tmp->pinNum);	
			tmp = findDeviceByName("upstairLight",pdeviceHead);	
		if(tmp != NULL)  tmp->close(tmp->pinNum);	
			tmp = findDeviceByName("restauranLight",pdeviceHead);	
		if(tmp != NULL)  tmp->close(tmp->pinNum);		
			tmp = findDeviceByName("livingroomLight",pdeviceHead);	
		if(tmp != NULL)  tmp->close(tmp->pinNum);      
			printf("已关闭所有灯\n");	
	}

}

//语音线程
void *voice_thread(void *datas)
{	
	struct InputCommander *voiceHandler;
	//struct Devices *tmp =NULL;
	
	int nread;
	
	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);
	   while(1){
		   nread = voiceHandler->getCommand(voiceHandler);
		   if(nread == 0){
				printf("nodata form voice\n");
		   }else{
		   		
				printf("do device contrl --> %s\n",voiceHandler->command);	
				Command(voiceHandler);
		   	}			   
		   }	   		   	
	   	}
	 }	   
}

//接收客户端指令
void *read_thread(void *datas)
{
	int n_read;
	struct Devices *tmp =NULL;
	memset(socketHandler->command,'\0',sizeof(socketHandler->command));
	n_read = read(c_fd,socketHandler->command,sizeof(socketHandler->command));
	if(n_read == -1){
            perror("read");
    }else if(n_read>0){
            printf("\nget: %d,%s\n",n_read,socketHandler->command);	
	   
		    if(strcmp("yo",socketHandler->command) == 0){
				tmp = findDeviceByName("bathroomLight",pdeviceHead);
				if(tmp != NULL){
					tmp->open(tmp->pinNum);
					printf("已打开泳池灯\n");
				}
		    }
				   
		    if(strcmp("yc",socketHandler->command) == 0){  
				tmp = findDeviceByName("bathroomLight",pdeviceHead);   
				if(tmp != NULL){ 	 
					tmp->close(tmp->pinNum); 	 
					printf("已关闭泳池灯\n");	 
				}   
			}  
		   
		    if(strcmp("eo",socketHandler->command) == 0){
				tmp = findDeviceByName("upstairLight",pdeviceHead);
				if(tmp != NULL){
					tmp->open(tmp->pinNum);
					printf("已打开二楼灯\n");
				}
			}
		    if(strcmp("ec",socketHandler->command) == 0){  
				tmp = findDeviceByName("upstairLight",pdeviceHead);	 
				if(tmp != NULL){ 	 
					tmp->close(tmp->pinNum); 	 
					printf("已关闭二楼灯\n");	 
				}   
			}
		    if(strcmp("co",socketHandler->command) == 0){
				tmp = findDeviceByName("restauranLight",pdeviceHead);
				if(tmp != NULL){
					tmp->open(tmp->pinNum);
					printf("已打开餐厅灯\n");
				}
			}
		    if(strcmp("cc",socketHandler->command) == 0){  
				tmp = findDeviceByName("restauranLight",pdeviceHead);   
				if(tmp != NULL){ 	 
					tmp->close(tmp->pinNum); 	 
					printf("已关闭餐厅灯\n");	 
				}   
			}
			if(strcmp("wo",socketHandler->command) == 0){
				tmp = findDeviceByName("livingroomLight",pdeviceHead);
				if(tmp != NULL){
					tmp->open(tmp->pinNum);
					printf("已打开卧室灯\n");
				}
			}
			if(strcmp("wc",socketHandler->command) == 0){  
				tmp = findDeviceByName("livingroomLight",pdeviceHead);	
				if(tmp != NULL){ 	 
					tmp->close(tmp->pinNum); 	 
					printf("已关闭卧室灯\n");	 
				}   
			}
			if(strcmp("ao",socketHandler->command) == 0){  
				    tmp = findDeviceByName("bathroomLight",pdeviceHead); 	   
				if(tmp != NULL)	tmp->open(tmp->pinNum);    
				    tmp = findDeviceByName("upstairLight",pdeviceHead); 
				if(tmp != NULL)	tmp->open(tmp->pinNum); 	   
					tmp = findDeviceByName("restauranLight",pdeviceHead);   
				if(tmp != NULL)	tmp->open(tmp->pinNum); 	   
					tmp = findDeviceByName("livingroomLight",pdeviceHead);  
				if(tmp != NULL)	tmp->open(tmp->pinNum); 	  
					printf("已打开所有灯\n");	  
			}	
			if(strcmp("ac",socketHandler->command) == 0){  
					 tmp = findDeviceByName("bathroomLight",pdeviceHead); 	   
				 if(tmp != NULL)	tmp->close(tmp->pinNum);   
					 tmp = findDeviceByName("upstairLight",pdeviceHead); 
				 if(tmp != NULL)	tmp->close(tmp->pinNum);   
					 tmp = findDeviceByName("restauranLight",pdeviceHead);   
				 if(tmp != NULL)	tmp->close(tmp->pinNum);	   
					 tmp = findDeviceByName("livingroomLight",pdeviceHead);  
				 if(tmp != NULL)	tmp->close(tmp->pinNum);	  
					 printf("已关闭所有灯\n"); 
			}
    }else{
           printf("client quit\n");
    }
}

//网络线程
void *socket_thread(void *datas)
{
	int n_read = 0;
	pthread_t readThread;
	
	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(&readThread,NULL,read_thread,NULL);
		
	}
}

//火焰线程
void *fire_thread(void *datas)
{
	int status;
	struct Devices *fireDeviceTmp = NULL;
	struct Devices *beepDeviceTmp = NULL;

	fireDeviceTmp = findDeviceByName("fireIfOrNot",pdeviceHead);
	beepDeviceTmp = findDeviceByName("beep",pdeviceHead);
	
	fireDeviceTmp->deviceInit(fireDeviceTmp->pinNum);
    beepDeviceTmp->deviceInit(beepDeviceTmp->pinNum);
	
	while(1){
		status = fireDeviceTmp->changeStatus(fireDeviceTmp->pinNum);  //读取“火焰传感器”状态
		if(status == 0){	                                          //检测到火焰或强光源 
            printf("fire danger warning!!!\n");		                       
			beepDeviceTmp->open(beepDeviceTmp->pinNum);	 //打开蜂鸣器
			delay(1000);
		}else{						
			beepDeviceTmp->close(beepDeviceTmp->pinNum); //关闭蜂鸣器
		}
	}	  
}
int main()
{
	int status;
	char name[128];
	struct Devices *tmp = NULL;
	
	pthread_t voiceThread;
	pthread_t socketThread;
	pthread_t fireThread;

	if(-1 == wiringPiSetup()){  //初始化wiringPi库
		return -1;
	}
	
	//1.指令工厂
	pCommandHead = addvoiceContrlToInputCommandLink(pCommandHead);//语音
	pCommandHead = addSocketContrlToInputCommandLink(pCommandHead);//网络
	
	//2.设备控制工厂初始化
	pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);//泳池灯
	pdeviceHead = addUpstairLightToDeviceLink(pdeviceHead);//二楼灯
	pdeviceHead = addLivingroomLightToDeviceLink(pdeviceHead);//卧室灯
	pdeviceHead = addRestauranLightToDeviceLink(pdeviceHead);//餐厅灯
	pdeviceHead = addFireToDeviceLink(pdeviceHead);//火灾检测
	pdeviceHead = addBeepToDeviceLink(pdeviceHead);//蜂鸣器

	//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
	//3.线程池建立
	//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);

	/*while(1){  //用于四盏灯的调试
		printf("input:\n");
		scanf("%s",name);
		tmp = findDeviceByName(name,pdeviceHead);

		if(tmp != NULL){
			tmp->deviceInit(tmp->pinNum);
			tmp->open(tmp->pinNum);
		}
	}*/ 
	
	pthread_join(voiceThread,NULL);
	pthread_join(socketThread,NULL);
	pthread_join(fireThread,NULL);
	
	return 0;
}

<2> InputCommand.h 控制设备头文件

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

struct InputCommander{
	char commandName[128];
	char deviceName[128];
	char command[32];
	int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);
	int (*getCommand)(struct InputCommander *voicer);
	char log[1024];
	int fd;
	char port[12];
	char ipAddress[32];
	int sfd;
	
	struct InputCommander *next;
};

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

<3> contrlDevices.h 外接设备头文件

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

struct Devices{
	char deviceName[128];
	int status;
	int pinNum;
	
	int (*open)(int pinNum);
	int (*close)(int pinNum);
	int (*deviceInit)(int pinNum);
	
	int (*changeStatus)(int status);


	struct Devices *next;
};

struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices *addUpstairLightToDeviceLink(struct Devices *phead);
struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead);
struct Devices *addRestauranLightToDeviceLink(struct Devices *phead);
struct Devices *addFireToDeviceLink(struct Devices *phead);
struct Devices *addBeepToDeviceLink(struct Devices *phead);

<4> 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",
	.pinNum = 21,
	.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;
	}
}

<5> 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",
	.pinNum = 24,
	.open = livingroomLightOpen,
	.close = livingroomLightClose,
	.deviceInit = livingroomLightCloseInit,
	.changeStatus = livingroomLightCloseStatus
};

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

<6> restaurantLight.c 餐厅灯

#include "contrlDevices.h"

int restauranLightOpen(int pinNum)
{
	digitalWrite(pinNum,LOW);
}
int restauranLightClose(int pinNum)
{
	digitalWrite(pinNum,HIGH);
}

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

int restauranLightCloseStatus(int status)
{

}
struct Devices restauranLight = {

	.deviceName = "restauranLight",
	.pinNum = 23,
	.open = restauranLightOpen,
	.close = restauranLightClose,
	.deviceInit = restauranLightCloseInit,
	.changeStatus = restauranLightCloseStatus
};

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

<7> 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",
	.pinNum = 22,
	.open = upstairLightOpen,
	.close = upstairLightClose,
	.deviceInit = upstairLightCloseInit,
	.changeStatus = upstairLightCloseStatus
};

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

<8> fire.c 火焰传感器

#include "contrlDevices.h"

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

int fireStatusRead(int pinNum)
{
	return digitalRead(pinNum);
}
struct Devices fireIfOrNot = {
	.deviceName = "fireIfOrNot",
	.pinNum = 25,
	.deviceInit = fireIfOrNotInit,
	.changeStatus = fireStatusRead
};
struct Devices *addFireToDeviceLink(struct Devices *phead)
{
	if(phead == NULL)
	{
		return &fireIfOrNot;
	}else{
		fireIfOrNot.next = phead;
		phead = &fireIfOrNot;
		//return phead;
	}
}

<9> beep.c 蜂鸣器

#include "contrlDevices.h"

//struct Devices *addBeepToDeviceLink(struct Devices *phead);

int beepInit(int pinNum)              //初始化函数
{
        pinMode(pinNum,OUTPUT);       //配置引脚为输出引脚
        digitalWrite(pinNum,HIGH);    //引脚输出高电平,即默认为关闭状态
}

int beepOpen(int pinNum)             //打开蜂鸣器函数
{
        digitalWrite(pinNum,LOW);
}

int beepClose(int pinNum)             //关闭蜂鸣器函数
{
        digitalWrite(pinNum,HIGH);
}

struct Devices beep = {             //蜂鸣器设备链表节点
        .deviceName = "beep",
        .pinNum = 29,                   
        .deviceInit = beepInit,
        .open = beepOpen,
        .close = beepClose,
        //.next = NULL
};


struct Devices* addBeepToDeviceLink(struct Devices *phead)  //头插法将设备节点加入设备工厂链表函数
{
        if(phead == NULL){
                return &beep;
        }else{
                beep.next = phead;
                phead = &beep;
        }
}

<10> voiceContrl.c 语音模块

#include <wiringPi.h>
#include <stdio.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.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));//将串口的指令读到voicer->command中
	return nread;

}
int voiceInit(struct InputCommander *voicer,char *ipAdress,char *port)
{
	int fd;
	
	if((fd = serialOpen(voicer->deviceName,9600))==-1){		//初始化树莓派串口
			perror("serialOpen");
			return -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;
	}
}

<11> socketContrl.c 服务器

#include <wiringPi.h>
#include <stdio.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>    
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.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);
	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) //socket初始化
{
	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));
    inet_aton(socketMes->ipAddress,&s_addr.sin_addr);

	//2. bind
    bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3. listen
    listen(s_fd,10);
	printf("socker Server listening ......\n");	
	socketMes->sfd = s_fd;
	
	return s_fd;  //套接字描述符返回到网络控制链表节点
}

struct InputCommander socketContrl = {
	.commandName = "socketServer",
	.command = {'\0'},
	.port = "8080",
	.ipAddress = "192.168.1.7",
	.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;
	}
}

三   项目演示

四   项目问题总结

通过这个项目,我对于简单工厂模式,Linux操作系统的文件,进程,线程,网络以及Linux字符设备开发都有了比较大的收获。整个项目的逻辑还算简单明了,但在实际开发调试过程中也会遇到一些问题,还好都逐一发现并解决。

问题一

语音控制不了灯

分析解决:串口测试语音能通过,串口命令测试灯也能通过,代码没有任何报错,逻辑也没有任何问题,唯独语音控制不了灯。我的语音逻辑是通过if来判断收到的控制指令从而实现对灯的控制。既然其他方面没有问题,那就是if判断不了收到的控制指令,所以把问题锁定于此。我将语音SDK重新生成配置,将判断条件修改成和语音SDK一致的内容后,继续先用串口测语音,再用串口测灯,最后实现语音控制灯,顺利实现。总结就是:语音配置的参数内容必须和判断条件的内容一致,才能准确判断并执行。之前做过语音控制刷抖音,因为太简单,中间没有任何报错,所以也就没有发现这个问题。笔记于此,当是提醒。

问题二

段错误

分析解决:做火灾检测报警这一块,因为是蜂鸣器和火焰传感器的结合,所以须将蜂鸣器整合在火焰线程中,编译后直接提示段错误,没有其他任何报错。我先检查了火焰,蜂鸣器,外接设备头文件以及火焰线程部分的代码,没有问题,至少肉眼可见的逻辑是没有问题的,然后在检查火焰传感器和蜂鸣器的IO口接线方面,也没有问题。捣鼓了很长时间无果,还好心理素质过硬,面向百度,依然无果。在最后,尝试用printf的方法将问题锁定在火焰线程中蜂鸣器的初始化部分。最后的最后才发现,在主函数int main()中设备控制工厂初始化没有添加蜂鸣器部分代码。

问题三

连接服务器超时

其实这不算什么问题,只是记录下来。通过手机客户端发送指令到服务器端实现控制灯,那么就需要连接服务器,如果出现连接超时或连接错误,首先排查是否能ping通网络,然后检查代码,ip,端口,如果都没问题,就可以考虑端口号是否被占用,修改下端口,多尝试连接几次。

问题四 

线材和模块布局凌乱

前期没注意这个问题,只管接线并测试各模块的功能,到后期快完结时,走线杂乱已无力回天。后面的开发中值得注意!

五   项目相关知识点整理

该项目所涉及到的知识点,我将往期相关的博文都归纳在此:

C语言设计模式:实现简单工厂模式和工程创建

树莓派编程控制继电器及继电器组

通过Linux串口实现树莓派与电脑通信

树莓派+摄像头:mjpg-streamer实现监控功能的配置及调试

基于Linux串口实现语音控制刷抖音

C语言数据结构:链表的增删改查及动态创建

Linux网络编程:Socket服务器和客户端实现双方通信

Linux线程:创建(pthread_create),等待(pthread_join),退出(pthread_exit)

Orangepi Zero2 全志H616:蜂鸣器,链接库,shell脚本

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/491420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【GUI】基于Python的文本数据处理(串口解析 0D 0A结尾)

【GUI】基于Python的文本数据处理&#xff08;串口解析 0D 0A结尾&#xff09; 如有串口数据&#xff1a; [37;22mD/NO_TAG [2023-04-24 23:01:06 ] ------------------------------------------------->>>>>> M_DADAT_GET_DAMAGE_INFO [0m 2023/04/24 2…

200左右什么蓝牙耳机比较好?国产200左右蓝牙耳机推荐

随着不少手机厂商取消3.5mm耳机孔&#xff0c;蓝牙耳机便成为了人们外出的最佳选择。最近看到很多人问&#xff0c;200左右什么蓝牙耳机比较好&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款国产的蓝牙耳机&#xff0c;一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 …

如何防止订单重复支付

想必大家对在线支付都不陌生&#xff0c;今天和大家聊聊如何防止订单重复支付。 看看订单支付流程 我们来看看&#xff0c;电商订单支付的简要流程&#xff1a; 订单钱包支付流程 从下单/计算开始&#xff1a; 下单/结算&#xff1a;这一步虽然不是直接的支付起点&#xff0c;但…

opencv场景识别

opencv场景识别 文章目录 一、需求1、现状2、设想 二、模型使用1、opencv dnn支持的功能2、ANN_MLP相关知识3、MLP图像分类模型训练学习 三、更换方向1、目标检测模型2、darknet网络介绍 四、opencv调用darknet模型1、**darknet模型获取**2、python调用darknet模型3、遇到的一些…

NewBing最新更新使用体验(无需等待人人可用)

NewBing最新更新使用体验 微软Bing爆炸级更新&#xff01;无需等待人人可用&#xff01; 今天&#xff0c;微软突然官宣全面开放BingChat&#xff1a; 无需任何等待。只需注册一个账户&#xff0c;首页即可体验。 NewBing最新更新新特性官方文档 https://www.microsoft.com/en-…

ETL 组件Spark资源设置指导

一、概念介绍 1.RDD RDD&#xff08;Resilient Distributed Dataset&#xff09;:弹性分布式数据集&#xff0c;是Spark中最基础的数据抽象。它本质就是一个类&#xff0c;屏蔽了底层对数据的复杂抽象和处理&#xff0c;为用户提供了一组方便数据转换和求值的方法。 简单来说…

研报精选230505

目录 【行业230505国信证券】风电or电网产业链周评&#xff08;4月第5周&#xff09;&#xff1a;海风开发资源集中释放&#xff0c;黑色类原材料价格持续下行 【行业230505天风证券】通信AI系列之&#xff1a;人工智能之火点燃算力需求&#xff0c;AI服务器迎投资机遇 【行业2…

数字孪生遇上VR:未来的新生态

数字孪生和虚拟现实&#xff08;VR&#xff09;是当今技术领域备受关注的两个概念。 数字孪生作为物理世界的数字映像&#xff0c;已经在许多行业得到了广泛应用。而VR则是一种基于计算机生成的三维交互式虚拟环境&#xff0c;被广泛应用于娱乐、教育和游戏等领域。 数字孪生…

十一、MyBatis的逆向工程

文章目录 十一、MyBatis的逆向工程11.1 (清新简洁版)创建逆向工程的步骤11.2 (奢华尊享版)创建逆向工程的步骤11.3 说明尊享版和简洁版的区别 本人其他相关文章链接 十一、MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库…

Spring MVC程序开发

文章目录 一、什么是 Spring MVC&#xff08;一&#xff09;MVC的定义&#xff08;二&#xff09;MVC 和 Spring MVC 的关系&#xff08;三&#xff09;为什么要学习 Spring MVC 二、Spring MVC使用方法和技巧&#xff08;一&#xff09;Spring MVC 创建和连接&#xff08;二&a…

clonezilla(再生龙)克隆系统操作

一、前言 背景&#xff1a;由于存在对嵌入式设备系统备份的需求&#xff0c;主要使用在对一个嵌入式设备安装好ros以及其他插件&#xff08;安装时间十分冗长&#xff09;&#xff0c;然后对该系统进行备份&#xff0c;快速复制到下一台嵌入式设备中。因此引出了克隆linux系统…

MySQL知识学习08(MySQL自增主键一定是连续的吗)

众所周知&#xff0c;自增主键可以让聚集索引尽量地保持递增顺序插入&#xff0c;避免了随机查询&#xff0c;从而提高了查询效率。 但实际上&#xff0c;MySQL 的自增主键并不能保证一定是连续递增的。 下面举个例子来看下&#xff0c;如下所示创建一张表&#xff1a; 1、自…

C++类与对象(二)——拷贝构造函数

文章目录 拷贝构造函数1.拷贝构造函数的概念2.拷贝构造函数的特性 前言 本章继续学习类的6个默认成员函数——拷贝构造函数 拷贝构造函数 1.拷贝构造函数的概念 拷贝构造函数&#xff1a;使用已经存在的一个对象初始化创建另一个对象。 举例&#xff1a; class Date { publ…

Golang每日一练(leetDay0056) 单个编辑距离、寻找峰值

目录 161. 单个编辑距离 One Edit Distance &#x1f31f;&#x1f31f; 162. 寻找峰值 Find Peak Element &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 …

vmware 安装Kylin-Desktop-V10-SP1-General-Release-2203-X86_64.iso

下载 官网&#xff1a;国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站 (kylinos.cn) 点击桌面操作系统 选择No1 点击申请试用 填写相关信息&#xff0c;点击立即提交&#xff0c;就会获取到下载连接&#xff0c; 点击下载按钮等待下载完成即可 安…

Java中顺序表详解

前言 在Java编程中&#xff0c;顺序表是一种基础且重要的数据结构。它通常用来表示线性结构数据&#xff0c;如数组等。通过使用顺序表&#xff0c;我们可以轻松管理和操作大量的数据&#xff0c;并实现各种算法和功能。本篇博客将详细介绍Java中顺序表相关的原理、方法和实例&…

BRDF

文章目录 0. 写在前面1. 简单理解2. Cook-Torrance BRDF模型2.1 BRDFD 法线分布函数F 菲涅尔G 几何函数1.1.3 L i ( p , ω i ) L_i(p,\omega_i) Li​(p,ωi​)1.1.1 积分框架1.1.2 f r ( p , ω i , ω o ) f_r(p,\omega_i,\omega_o) fr​(p,ωi​,ωo​): 个人疑惑及解答1.…

ESL设计概述

‍‍ ‍‍前言 随着芯片面临着应用场景丰富多变、集成功能模块越来越多、片内通信及模块间接口越来越复杂、设计规模越来越大以及PPA要求越来越高的需求&#xff0c;芯片设计方法面临越来越大的挑战。架构的合理性、完备性和一致性很大程度上决定了芯片设计的成败。基于同样的I…

《基于光电容积图法的两种可穿戴设备在不同身体活动情况下监测心率的一致性:一种新的分析方法》阅读笔记

目录 一、论文摘要 二、论文十问 Q1&#xff1a;论文试图解决什么问题&#xff1f; Q2&#xff1a;这是否是一个新的问题&#xff1f; Q3&#xff1a;这篇文章要验证一个什么科学假设&#xff1f; Q4&#xff1a;有哪些相关研究&#xff1f;如何归类&#xff1f;谁是这一课…

电容笔有必要买最好的吗?推荐的ipad手写笔

随着科技的进步&#xff0c;各种类型的电容笔的生产厂家越来越多。一支好的电容笔&#xff0c;不仅能大大提高我们的工作效率&#xff0c;而且能大大提高我们的学习效果。平替电容笔无论从技术水平&#xff0c;还是从产品品质来看&#xff0c;都具有十分广阔的市场前景。以下是…