智能家居项目开发(二):项目架构建立

一、智能家居项目框架设计

1.代码设计思路草图:
在这里插入图片描述
2.代码思路讲解:

a)一个指令工厂,一个控制工厂,实际上就是通过链表链起来的数据。具体怎么链接起来,就是基于简单工厂模式的类与对象的概念,上一篇文章有学习记录。
b)主函数语音指令程序和tcp指令程序各起一个线程,然后通过指令找到对应的控制程序,实现对应的模块的功能。

二、智能家居架构文件代码工程建立

有了思路之后,我们就可以来建立项目文件代码了。

1.我们先再桌面建立一个项目文件:
在这里插入图片描述
2.然后打开文件,逐个写好先:

在这里插入图片描述
3.然后打开Souce Insight,把文件都导入进去
因为用这个来写,更加的直观和方便。
在这里插入图片描述

三、浴室灯代码实现

1.先看主函数mainPro.c

#include<stdio.h>
#include"controlDevices.h"
#include<string.h>

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;
	   }

}
int main()
{
    char *name  = "bathroomLight";
	if(-1 == wiringPiSetup()){
       return -1;
	}
	
    struct Devices *pdeviceHead = NULL;
	pdeviceHead = addBathroomLightInit(pdeviceHead);

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

2.外设设备的头文件controlDevices.h

#include<wiringPi.h>
#include<stdlib.h>
struct Devices
{
       char deviceName[128];

	   int pinNum;
	   int (*deviceInit)(int pinNum;);   
	   int (*open)(int pinNum;);
	   int (*close)(int pinNum;);
	   
       struct Devices *next;

};

struct Devices *addBathroomLightInit(struct Devices *phead);

3.浴室灯bathroomLight.c

#include"controlDevices.h"

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 Devices bathroomLight = {

       .deviceName = "bathroomLight",
	   .pinNum = 28,
	   .deviceInit = bathroomLightInit,
	   .open = bathroomLightOpen,
	   .close = bathroomLightClose
	   
};

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

4.写完之后,利用FileZilla文件传输软件,将文件smartHouse文件传到树莓派终端:
在这里插入图片描述
5.进行代码编译,然后执行:
在这里插入图片描述
6.测试结果:

在这里插入图片描述

7.继电器其余四盏灯全部实现:
其余三盏灯的代码格式和上面bathroomLight.c的一样,这里就不一一展示,已经实现了。
等所有的模块都测试完,会有整个项目的实现效果和总结。

四、火焰检测和蜂鸣器模块测试

它们也是io口驱动,跟实现灯代码一样,就是要注意模块的使用说明。

1.火焰传感器fire.c

#include"controlDevices.h"

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

    return digitalRead(pinNum);
}

struct Devices fire = {

       .deviceName = "fire",
	   .pinNum = 0,
	   .deviceInit = fireInit,
	   .readStatus = fireStatusRead
	   
};

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

}

2.蜂鸣器buzzer.c

#include"controlDevices.h"

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 Devices buzzer = {

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

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

}

3.外设设备的头文件controlDevices.h

#include<wiringPi.h>
#include<stdlib.h>
struct Devices
{
       char deviceName[128];

	   int pinNum;
	   int (*deviceInit)(int pinNum);   
	   int (*open)(int pinNum);
	   int (*close)(int pinNum);

	   int (*readStatus)(int pinNum);
	   	   
       struct Devices *next;

};

struct Devices *addBathroomLightToDevicesLink(struct Devices *phead);
struct Devices *addLivingroomLightToDevicesLink(struct Devices *phead);
struct Devices *addSwimmingpoolLightToDevicesLink(struct Devices *phead);
struct Devices *addUpstairLightToDevicesLink(struct Devices *phead);
struct Devices *addFireToDevicesLink(struct Devices *phead);
struct Devices *addBuzzerToDevicesLink(struct Devices *phead);

4.主函数测试代码mainPro.c

#include<stdio.h>
#include"controlDevices.h"
#include<string.h>

struct Devices *findDevicesByName(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;
	   }

}
int main()
{

    int status;
    char name[128];
	struct Devices *tmp = NULL;
	
	if(-1 == wiringPiSetup()){
       return -1;
	}
	
    struct Devices *pdeviceHead = NULL;
    pdeviceHead = addBathroomLightToDevicesLink(pdeviceHead);
	pdeviceHead = addLivingroomLightToDevicesLink(pdeviceHead);
	pdeviceHead = addUpstairLightToDevicesLink(pdeviceHead);
	pdeviceHead = addSwimmingpoolLightToDevicesLink(pdeviceHead);	
	pdeviceHead = addFireToDevicesLink(pdeviceHead);
	pdeviceHead = addBuzzerToDevicesLink(pdeviceHead);

	struct Devices *fireDevicesTmp   = NULL;
	struct Devices *buzzerDevicesTmp = NULL;
    

	fireDevicesTmp = findDevicesByName("fire",pdeviceHead);//在设备工厂找到火灾模块
	buzzerDevicesTmp = findDevicesByName("buzzer",pdeviceHead);//在设备工厂找到蜂鸣器模块  
		
	fireDevicesTmp->deviceInit(fireDevicesTmp->pinNum);//火灾模块初始化
	buzzerDevicesTmp->deviceInit(buzzerDevicesTmp->pinNum);//蜂鸣器初始化

	
	while(1){
		
	    status = fireDevicesTmp->readStatus(fireDevicesTmp->pinNum);//不断获取火灾模块的数据
			
	    if(status == 0){
           buzzerDevicesTmp->open(buzzerDevicesTmp->pinNum);
		 		   
	    }else{
           buzzerDevicesTmp->close(buzzerDevicesTmp->pinNum);
           		
		}
   }
	
	return 0;
}

5.测试结果:
编译运行
在这里插入图片描述
运行结果
在这里插入图片描述

五、添加语音模块的串口读取功能

语音模块之前有学过,这里主要通过主控芯片树莓派的串口跟语音模块连接。
树莓派的T接语音模块的R
树莓派的R接语音模块的T
然后就是供电

我们先把语音模块的代码整合到指令链表链表当中去:
1.语音控制设备voicevoiceContrl.c

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

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;
}

int voiceGetCommand(struct InputCommander *voicer)
{
    int nread = 0;
	nread = read(voicer->fd,voicer->command,sizeof(voicer->command));
    if(nread == 0){
	   printf("usart for voice read over timen");
    }else{
       return nread;
	}

}

struct InputCommander voiceContrl = {
       .commandName = "voice",
	   .deviceName = "/dev/ttyAMA0",
	   .command = {''},
	   .Init = voiceInit,
	   .getCommand = voiceGetCommand
	 
	};

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

}

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;

	   struct InputCommander *next;
};

struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead);

3.先运行测试一下:
在这里插入图片描述
代码没问题。

六、添加socket服务器功能

这里跟语音模块一样,我们先把socket服务器加到控制链表中去。
这里也基于语音模块代码来写。

1.socket服务器控制socketContrl.c

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

#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>


int socketInit(struct InputCommander *socketMes,char *ipAdress,char *port)
{
    int s_fd;
	
	s_fd = socket(AF_INET,SOCK_STREAM,0);
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}

	struct sockaddr_in s_addr;
	memset(&s_addr,0,sizeof(struct sockaddr_in));

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

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

	listen(s_fd,10);

	socketMes->sfd = s_fd;

	return s_fd;
}

int socketGetCommand(struct InputCommander *socketMes)
{
   int c_fd;
   int nread = 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);

   nread = read(c_fd,socketMes->command,sizeof(socketMes->command));

   return nread;
   
}

struct InputCommander socketContrl = {
       .commandName = "socketServer",
	   .command = {''},
	   .port = "8088",
	   .ipAdress = "192.168.31.80",
	   .Init = socketInit,
	   .getCommand = socketGetCommand
	 
	};

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

}

2.控制设备的头文件inputCommand.h

#include<wiringPi.h>
#include<stdlib.h>
#include<string.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 ipAdress[32];
	   int sfd;

	   struct InputCommander *next;
};

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

3.编译测试一下:
在这里插入图片描述

七、主程序代码初步编写,实现语音和网络线程

这里还是主要测试主函数。所有控制实现功能都是在主函数里面进行。
我们来测试一下socket服务器的网络功能和树莓派连接语音的串口功能
1.主函数mainPro.c

#include<stdio.h>
#include"controlDevices.h"
#include"inputCommand.h"
#include<string.h>

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


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


struct Devices *findDevicesByName(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 *voice_thread(void *datas)
{
      struct InputCommander *voiceHandler;
	  int nread;

	  voiceHandler = findCommandByName("voice",pcommandHead);
      if(voiceHandler == NULL){
         printf("find voiceHandler errorn");
		 pthread_exit(NULL);
	  }else{
         if(voiceHandler->Init(voiceHandler,NULL,NULL) <0){
            printf("voiceInit errorn");
			pthread_exit(NULL);
		 }else{
            printf("%s Init succcessn",voiceHandler->commandName);
		 }

          while(1){
            nread = voiceHandler->getCommand(voiceHandler);
			if(nread == 0){
               printf("nodata from voicen");
			}else{
               printf("do device contrl:%sn",voiceHandler->command);

			}

		  }	
		  
	  }
	  
}

void *read_thread(void *datas)
{
      int n_read;
	  printf(
"have user connectn");
	  memset(socketHandler->command,'',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("read:%sn",socketHandler->command);
	  }else{
         printf("clien quitn");
	  }
}


void *socket_thread(void *datas)
{

	  
	  int nread = 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 errorn");
			 pthread_exit(NULL);
	  }else{
             printf("%s Init succcessn",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);
	  }
	  

}
int main()
{

    int status;
    char name[128];
	pthread_t voiceThread;
	pthread_t socketThread;
	
	if(-1 == wiringPiSetup()){
       return -1;
	}
	
    //1.指令工厂的初始化
    pcommandHead = addVoiceContrlToInputCommandLink(pcommandHead);
	pcommandHead = addSocketContrlToInputCommandLink(pcommandHead);


	//2.设备工厂的初始化
    pdeviceHead = addBathroomLightToDevicesLink(pdeviceHead);
	pdeviceHead = addLivingroomLightToDevicesLink(pdeviceHead);
	pdeviceHead = addUpstairLightToDevicesLink(pdeviceHead);
	pdeviceHead = addSwimmingpoolLightToDevicesLink(pdeviceHead);	
	pdeviceHead = addFireToDevicesLink(pdeviceHead);
	pdeviceHead = addBuzzerToDevicesLink(pdeviceHead);
    

	//3.线程池的建立
	
	//3.1 语音线程
	pthread_create(&voiceThread,NULL,voice_thread,NULL);
	
	//3.2 socket线程
	pthread_create(&socketThread,NULL,socket_thread,NULL);
	
	//3.3 摄像头线程
	//3.4 火灾线程

    pthread_join(voiceThread,NULL);
	pthread_join(socketThread,NULL);
		
	return 0;
}

2.编译运行网络测试:
在这里插入图片描述
3.串口语音测试:
树莓派连接语音的串口功能。
在这里插入图片描述
测试的结果还不是特别完善,语音模块的口令那块源代码还要改下,然后收到串口的语音指令完善下。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>