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

研究院院长 LV8
2023-05-31 · 58 阅读
一、智能家居项目框架设计
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);
    }

    return0;
}





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)
{

    returndigitalRead(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);

        }
   }

    return0;
}




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 time\n");
    }else{
       return nread;
    }

}

struct InputCommander voiceContrl = {
       .commandName ="voice",
       .deviceName ="/dev/ttyAMA0",
       .command = {'\0'},
       .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服务器加到控制链表中去。
这里也基于语音模块代码来写。

#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 = {'\0'},
       .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);

#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 error\n");
         pthread_exit(NULL);
      }else{
         if(voiceHandler->Init(voiceHandler,NULL,NULL) <0){
            printf("voiceInit error\n");
            pthread_exit(NULL);
         }else{
            printf("%s Init succcess\n",voiceHandler->commandName);
         }

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

            }

          }

      }

}

void*read_thread(void*datas)
{
      int n_read;
      printf(
"have user connect\n");
      memset(socketHandler->command,'\0',sizeof(socketHandler->command));
      n_read =read(c_fd,socketHandler->command,sizeof(socketHandler->command));
      if(n_read ==-1){
         perror("read");
      }elseif(n_read >0){     
         printf("read:%s\n",socketHandler->command);
      }else{
         printf("clien quit\n");
      }
}


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 error\n");
             pthread_exit(NULL);
      }else{
             printf("%s Init succcess\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);
      }


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

    return0;
}





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



1. 本站所有资源来源于用户上传和网络,仅作为演示数据,如有侵权请邮件联系站长!
2. 盗版,破解有损他人权益和违法作为,请各位站长支持正版!
回复

举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则