基于树莓派4B的智能家居系统设计-2

简介: 基于树莓派4B的智能家居系统设计

基于树莓派4B的智能家居系统设计-1

https://developer.aliyun.com/article/1508008


五、智能家居设计框架

该智能家居由两个工厂和若干个设备组成,分别是产品工厂和指令工厂。包含功能如下:

1.产品工厂

该工厂主要是用来生产一些供人们使用的设备,如各种灯设备、OLED屏幕显示设备、环境数据检测设备、检测安全设备等等。

创建产品工厂的类,即产品工厂的生产线:

  • 设备名称
  • 设备状态
  • 设备引脚
  • 设备数据存储区
  • 设备功能
  • 打开
  • 关闭
  • 设备初始化
  • 读状态位
  • 改变状态位
  • 读数据
  • 链表链接节点,使对应的设备上线成为商品


controlDevices.h

struct Devices
{
  char devicesName[128];  // 设备名称
  int status;  // 设备状态
  int pinNum;  // 设备引脚
  unsigned long databuf;  // 设备数据存储区
  
  /* 设备功能 */
  int (*open)(int pinNum);
  int (*close)(int pinNum);
  int (*devicesInit)(int pinNum);
  int (*readStatus)(int pinNum);
  int (*changeStatus)(int status);
  int (*readData)(struct Devices *devices,int pinNum);
  
  struct Devices *next;  // 链表链接节点
};

具体产品设备有:

  • 一楼灯设备
  • 二楼灯设备
  • 餐厅灯设备
  • 卧室灯设备
  • OLED屏幕显示设备
  • 风扇设备
  • 锁设备
  • 警报器设备
  • 地震监测设备
  • 火灾监测设备
  • 烟雾监测设备
  • 温湿度监测设备

四盏灯设备代码示例:代码基本相同,只列举一个

#include "controlDevices.h"
 
int bathroomLightOpen(int pinNum)
{ 
  digitalWrite(pinNum,LOW);
}
  
int bathroomLightClose(int pinNum)
{
  digitalWrite(pinNum,HIGH);
}
 
int bathroomLightInit(int pinNum)
{
  pinMode(pinNum,OUTPUT);
  digitalWrite(pinNum,HIGH);
}
 
struct Devices bathroomLight = {
  .devicesName = "bathroom",
  .pinNum    = 21,
  .open    = bathroomLightOpen,
  .close     = bathroomLightClose,
  .devicesInit = bathroomLightInit,
  .next        = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addBathroomLightToDevicesLink(struct Devices *phead) {
  if (phead == NULL) {
    phead = &bathroomLight;
    return phead;
  } else {
    bathroomLight.next = phead;
    phead = &bathroomLight;
    return phead;
  }
}

风扇设备代码示例:

#include "controlDevices.h"
 
int fanOpen(int pinNum)
{ 
  digitalWrite(27,LOW);
  digitalWrite(28,HIGH);  
}
  
int fanClose(int pinNum)
{
  digitalWrite(27,LOW);
  digitalWrite(28,LOW); 
}
 
int fanInit(int pinNum)
{
  pinMode(27,OUTPUT);
  pinMode(28,OUTPUT);
  
  digitalWrite(27,LOW);
  digitalWrite(28,LOW);
 
}
 
struct Devices fan = {
  .devicesName = "fan",
  .pinNum    = 27,
  .open    = fanOpen,
  .close     = fanClose,
  .devicesInit = fanInit,
  .next        = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addfanToDevicesLink(struct Devices *phead) {
  if (phead == NULL) {
    phead = &fan;
    return phead;
  } else {
    fan.next = phead;
    phead = &fan;
    return phead;
  }
}

火灾、地震、烟雾监测设备代码示例:代码基本相同,只列举一个

#include "controlDevices.h"
 
int fireInit(int pinNum)
{
  pinMode(pinNum,INPUT);
  digitalWrite(pinNum,HIGH);
}
 
/* 检测火灾发生情况 */
int fireReadStatus(int pinNum)
{
  return digitalRead(pinNum);
}
 
struct Devices fire = {
  .devicesName = "fire",
  .pinNum    = 0,
  .devicesInit = fireInit,
  .readStatus  = fireReadStatus,
  .next        = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addfireToDevicesLink(struct Devices *phead) {
  if (phead == NULL) {
    phead = &fire;
    return phead;
  } else {
    fire.next = phead;
    phead = &fire;
    return phead;
  }
}

温湿度监测代码示例:

#include "controlDevices.h"
 
int sensorInit(int pinNum)
{
  pinMode(pinNum,OUTPUT);
  digitalWrite(pinNum,HIGH);
}
 
/* 获取温度传感器的数据 */
int sensorReadData(struct Devices *sensorMsg,int pinNum)
  {
    char crc;
    char i;
    unsigned long databuf;  // 温湿度存储地址
    
    pinMode(pinNum, OUTPUT); 
    digitalWrite(pinNum, 0); 
    delay(25);
    digitalWrite(pinNum, 1); 
    
    pinMode(pinNum, INPUT); 
    pullUpDnControl(pinNum, PUD_UP); // 启用上拉电阻,引脚电平拉倒3.3v
  
    delayMicroseconds(27);
    if (digitalRead(pinNum) == 0) 
    {
      while (!digitalRead(pinNum));
  
      for (i = 0; i < 32; i++)
      {
        while (digitalRead(pinNum));
           
        while (!digitalRead(pinNum));
  
        delayMicroseconds(32);
        databuf *= 2;
        if (digitalRead(pinNum) == 1)
        {
          databuf++;
        }
      }
  
      for (i = 0; i < 8; i++)
      {
        while (digitalRead(pinNum));
  
        while (!digitalRead(pinNum));
  
        delayMicroseconds(32);
        crc *= 2;
        if (digitalRead(pinNum) == 1) 
        {
          crc++;
        }
      }
      sensorMsg->databuf = databuf;
      return 1;
    }
    else
    {
      return 0;
    }
  }
 
/* 继承产品工厂的类,生产温度检测设备 */
struct Devices sensor = {
  .devicesName = "sensor",
  .pinNum = 7,
  .devicesInit = sensorInit,
  .readData = sensorReadData,
  .next = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addsensorToDevicesLink(struct Devices *phead)
{
  if(phead == NULL){
    phead = &sensor;
    return phead;
  }else{
    sensor.next = phead;
    phead = &sensor;
    return phead;
  }
}

2.指令工厂

该工厂主要是用来生产一些供人们发出指令控制的设备,如语音设备、蓝牙设备、server设备、人脸识别设备等等,这些设备可以控制产品工厂的设备做出一些控制行为。

创建指令工厂的类,即指令工厂的生产线:

  • 指令内容
  • 指令名称
  • 日志
  • 语言模块或蓝牙模块
  • 文件的fd
  • 设备名称
  • 网络通信
  • server的fd
  • 端口号
  • IP地址
  • 人脸识别
  • 指向主人的人脸图片
  • 指向临时的人脸图片
  • 人脸识别匹配度
  • 设备功能
  • 指令设备初始化
  • 获取指令设备
  • 处理函数
  • 链表链接节点,使对应的设备上线成为商品


nputCmd.h

struct InputCmd
{
  int fd;  //文件的fd
  char deviceName[128];  //设备名称
  char cmd[64];  //指令内容
  char cmdName[128];  //指令名称
  char log[1024];  //日志
  
  int sfd;  //server的fd
  char port[12];  //端口号
  char ipAress[32];  //IP地址
 
  char *img_buf;  //指向主人的人脸图片数据存储区的指针
  char *camera_buf;  //指向临时的人脸图片数据存储区的指针
  float face_data;  //人脸识别匹配度
 
  /* 设备功能 */
  int (*Init)(struct InputCmd *voicer,char *ipAdress,char *port);
  int (*getCmd)(struct InputCmd *voicer);
  int (*ReadHandle)(void *ptr, size_t size, size_t nmemb, void *stream);
 
  struct InputCmd *next;  //链表链接节点
};

具体指令设备有:

  • 语音设备
  • 蓝牙设备
  • server设备
  • 人脸识别设备

树莓派串口通信详细介绍可看我之前写过的文章,链接如下:树莓派串口通信

语音设备、蓝牙设备代码示例:代码基本相同,只列举一个。

#include "inputCmd.h"
 
/* 语音控制设备初始化,启用串口 */
int voiceInit(struct InputCmd *voicer,char *ipAdress,char *port)
{
  int fd;
  if((fd = serialOpen(voicer->deviceName,9600))==-1){  //打开串口
    exit(-1);
  }
  voicer->fd = fd;  
  return fd;
}
 
/* 读取来自语音控制设备的命令 */
int voiceGetCmd(struct InputCmd *voicer)
{
  char tmp[128];
  int nread;
  memset(tmp,'\0',sizeof(tmp));
  nread = read(voicer->fd,tmp,sizeof(tmp));  // 一切皆文件,串口也是文件,读串口数据
 
  if(nread == 0){
    printf("usart for voice read overtime\n");
  }else if(nread > 0){
    memset(voicer->cmd,'\0',sizeof(voicer->cmd)); 
    
    /* 对串口数据进行优化 */
    if(strstr(tmp,"open ba") != NULL){
      strcat(voicer->cmd,"open bathroom light");
    }
    if(strstr(tmp,"close ba") != NULL){
      strcat(voicer->cmd,"close bathroom light");
    }
    if(strstr(tmp,"open li") != NULL){
      strcat(voicer->cmd,"open livingroom light");
    }
    if(strstr(tmp,"close li") != NULL){
      strcat(voicer->cmd,"close livingroom light");
    }
    if(strstr(tmp,"open re") != NULL){
      strcat(voicer->cmd,"open restaurant light");
    }
    if(strstr(tmp,"close re") != NULL){
      strcat(voicer->cmd,"close restaurant light");
    }
    if(strstr(tmp,"open se") != NULL){
      strcat(voicer->cmd,"open secondfloor light");
    }
    if(strstr(tmp,"close se") != NULL){
      strcat(voicer->cmd,"close secondfloor light");
    }
    if(strstr(tmp,"open bu") != NULL){
      strcat(voicer->cmd,"open buzzer light");
    }
    if(strstr(tmp,"close bu") != NULL){
      strcat(voicer->cmd,"close buzzer light");
    }
    if(strstr(tmp,"open fn") != NULL){
      strcat(voicer->cmd,"open fan light");
    }
    if(strstr(tmp,"close fn") != NULL){
      strcat(voicer->cmd,"close fan light");
    }
    if(strstr(tmp,"open fac") != NULL){
      strcat(voicer->cmd,"open face light");
    }
    if(strstr(tmp,"open lo") != NULL){
      strcat(voicer->cmd,"open lock light");
    }
    if(strstr(tmp,"close lo") != NULL){
      strcat(voicer->cmd,"close lock light");
    }
 
    return nread;
  }else{
    printf("read is fali\n");
  }
 
}
 
/* 继承指令工厂的类,生产语音控制设备 */
struct InputCmd voiceControl = {
  .cmdName = "voice",
  .deviceName = "/dev/ttyAMA0",
  .cmd = {'\0'},
  .Init = voiceInit,
  .getCmd = voiceGetCmd,
  .next = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addvoiceControlToInputCmdLink(struct InputCmd *phead)
{
  if(phead == NULL){
    phead = &voiceControl;
    return phead;
  }else{
    voiceControl.next = phead;
    phead = &voiceControl;
    return phead;
  }
}

网络通信详细介绍和编程可看我之前写过的文章,链接如下:

网络通信TCP、UDP介绍

网络通信TCP、UDP编程详解

server设备代码示例:

#include "inputCmd.h"
 
/* server控制设备初始化,为套接字绑定端口号和IP地址 */
int serverInit(struct InputCmd *serverMsg,char *ipAdress,char *port)
{
  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("socket");
    exit(-1);
  }
 
  s_addr.sin_family = AF_INET;
  s_addr.sin_port = htons(atoi(serverMsg->port));
  inet_aton(serverMsg->ipAress,&s_addr.sin_addr);
 
  bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
 
  listen(s_fd,10);  
  
  serverMsg->sfd = s_fd;
  return s_fd;
}
 
/* 继承指令工厂的类,生产server控制设备 */
struct InputCmd serverControl = {
  .cmdName = "server",
  .cmd = {'\0'},
  .log = {'\0'},
  .Init = serverInit,
  .port = "8888",
  .ipAress = "192.168.137.115", // 树莓派ip地址
  .next = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addserverControlToInputCmdLink(struct InputCmd *phead)
{
  if(phead == NULL){
    phead = &serverControl;
    return phead;
  }else{
    serverControl.next = phead;
    phead = &serverControl;
    return phead;
  }
}

人脸识别设备代码示例:该设备通过使用 curl 第三方库访问网站,调用祥云人脸识别平台进行人脸识别。

#include "inputCmd.h"
 
char post_info[500];
 
/* 人脸识别设备初始化 */
int cameraInit(struct InputCmd *camera,char *ipAdress,char *port)
{
  int fd;
  int imgSize=0;
  char cmd[30];
  
  memset(post_info,'\0',500);
  curl_global_init(CURL_GLOBAL_ALL);  //curl库初始化
  
  /* 获取主人的人脸图片的base64编码 */
  fd = open("imgfile.txt",O_RDWR,0666);  //打开用来存放主人的人脸图片的base64编码的文件
  imgSize = lseek(fd,0,SEEK_END);  
  camera->img_buf = (char *)malloc(imgSize + 8);
  memset(camera->img_buf,'\0',imgSize + 8);
  lseek(fd,0,SEEK_SET);
  read(fd,camera->img_buf,imgSize);  //将主人的人脸图片的base64编码读到img_buf数据存储区
  close(fd);
 
  system("raspistill -q 5 -o haozi.jpg");  //调用树莓派摄像头拍摄图片,-q 5为降低画质
  while(access("./haozi.jpg",F_OK) != 0);  //等待拍摄完成
  
  sprintf(cmd,"base64 %s >camerafile.txt","haozi.jpg");  //字符串拼接
  if(system(cmd) == 256){  //生成摄像头拍摄图片的base64编码的图像地址
    return -1;
  }
 
  /* 获取临时拍摄的人脸图片的base64编码 */
  fd = open("camerafile.txt",O_RDWR,0666);  //打开用来存放临时拍摄的人脸图片的base64编码的文件
  imgSize = lseek(fd,0,SEEK_END);
  camera->camera_buf = (char *)malloc(imgSize + 8);
  memset(camera->camera_buf,'\0',imgSize + 8);
  lseek(fd,0,SEEK_SET);
  read(fd,camera->camera_buf,imgSize);  //将临时拍摄的人脸图片的base64编码读到camera_buf数据存储区
  close(fd);
 
  system("rm camerafile.txt");
  system("rm haozi.jpg");
  
  if((camera->img_buf == NULL)||(camera->camera_buf == NULL)){
    printf("img dont exist!\n");
    return -1;
  }
  return 0;
}
 
/* 获取祥云平台的人脸识别结果数据 */
int cameraReadHandle( void *ptr, size_t size, size_t nmemb, void *stream)
{
  int buf_size=size*nmemb;
  char *buf=malloc(buf_size+1);
  memset(buf,'\0',buf_size+1);
  strncpy(buf,ptr,buf_size);  //获取祥云平台的人脸识别结果
  memset(post_info,'\0',sizeof(post_info));
  strcat(post_info,buf);
  free(buf);
  return buf_size;
}
 
/* 调用祥云平台进行人脸识别 */
int cameraGetCmd(struct InputCmd *camera)
{
  CURL *curl;
  CURLcode res;
  char *PostString;
  
  /* 祥云平台的个人基本信息 */
  char *key="6M9M9rFAa3DuG33Awu9hKq";
  char *secret="db56882c3a0b4a3dbeeaed2af79f026c";
  int typeId=21;
  char *format="xml";
 
  char *result_str = NULL;
  float result_data;
  int len = strlen(camera->img_buf)+strlen(camera->camera_buf)+strlen(key)+strlen(secret)+sizeof(typeId)+strlen(format) + 24;
 
  PostString=malloc(len);
  
  sprintf(PostString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",camera->img_buf,camera->camera_buf,key,secret,typeId,format);  //设置需要发送给祥云平台的数据格式
 
  curl = curl_easy_init();  //获取句柄
  if (curl){
    
    curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");  //设置访问的URL,即祥云人脸识别的接口地址
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS,PostString);  //向祥云平台发送数据,调用人脸识别功能
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, camera->ReadHandle);  //设置回调函数,该函数用来接收人脸识别的结果
 
    res = curl_easy_perform(curl);//错误检测,0没有错误,非0出现错误
    curl_easy_cleanup(curl);
 
    /* 处理人脸识别的结果数据 */
    result_str = strstr(post_info,"CDATA");
    if(result_str != NULL){
      result_str += 6;
      result_str = strtok(result_str,"]");
      result_data = atof(result_str);
    }else{
      printf("get result error!\n");
    }
  }else{
    printf("get result error!\n");
  }
  camera->face_data = result_data;
  
  return result_data;
}
 
/* 继承指令工厂的类,生产人脸识别设备 */
struct InputCmd cameraControl = {
  .cmdName = "camera",
  .cmd = {'\0'},
  .log = {'\0'},
  .Init = cameraInit,
  .getCmd = cameraGetCmd,
  .ReadHandle = cameraReadHandle,
  .next = NULL,
  .img_buf = NULL,
  .camera_buf = NULL,
};
 
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addcameraControlToInputCmdLink(struct InputCmd *phead)
{
  if(phead == NULL){
    phead = &cameraControl;
    return phead;
  }else{
    cameraControl.next = phead;
    phead = &cameraControl;
    return phead;
  }
}

完整代码我后续再上传到资源

编译时要链接 wiringPi 库跟线程库:gcc *.c *.h -lwiringPi -lpthread

编译调试图示:

六、项目总结

总体来说,只要掌握好C语言、裸机外设和Linux,整个项目做下来其实难度并不大,从这个项目中我们可以学到面向对象的编程思想和练习对多个外设模块进行控制。


该项目还有很多可以扩展的地方,后续我打算用IMX6ULL 加 MQTT 重新实现一下智能家居,再用QT作为上位机控制下位机(选择 IMX6ULL),使用 OpenCV 进行人脸识别从而进行开关锁,计划在暑假实现全部扩展功能,让不同的开发板也可以完美实现该项目。

相关文章
|
7月前
|
传感器 监控 安全
基于STM32的智能家居安防系统设计与实现
基于STM32的智能家居安防系统设计与实现
605 1
|
7月前
|
传感器 人工智能 智能硬件
基于树莓派4B的智能家居系统设计-1
基于树莓派4B的智能家居系统设计
基于树莓派4B的智能家居系统设计-1
|
7月前
|
传感器 存储 监控
毕业设计 基于51单片机WIFI智能家居系统设计
毕业设计 基于51单片机WIFI智能家居系统设计
142 0
|
监控 安全 网络协议
【毕业设计之Android系列】智能家居远程控制系统设计
【毕业设计之Android系列】智能家居远程控制系统设计
515 1
|
2月前
|
传感器 监控 搜索推荐
探索智能家居技术的未来
【10月更文挑战第6天】 本文深入探讨了智能家居技术的发展历程、当前应用及其未来前景。通过分析物联网(IoT)的基本原理和智能家居设备的实际应用案例,揭示了该领域面临的挑战与机遇,并提出了未来发展的趋势和可能性。
57 3
|
2月前
|
传感器 人工智能 物联网
探索智能家居技术:现状与未来
本文深入探讨了智能家居技术的发展历程、当前主要技术和应用,并展望了其未来的发展趋势。通过对现有技术的详细解析和案例分析,揭示了智能家居在提升生活品质、节能减排等方面的潜力,同时指出了目前面临的挑战和可能的解决方案。
|
3月前
|
机器学习/深度学习 人工智能 物联网
智能家居技术的未来:从自动化到智能化的跨越
本文将探讨智能家居技术的发展趋势,从早期的自动化设备到现代的智能系统,分析其背后的技术驱动因素和市场动态。文章将详细讨论物联网(IoT)、人工智能(AI)、机器学习等技术如何推动智能家居的发展,并展望智能家居未来的发展方向。
|
3月前
|
监控 物联网 数据安全/隐私保护
智能家居包含了众多设备,在通过智能化技术提升居家生活的便利性、安全性、节能性和舒适度
智能家居系统包含了众多设备,旨在通过智能化技术提升居家生活的便利性、安全性、节能性和舒适度。以下是一些智能家居系统中常见的设备类别及其基本操作简述:
|
2月前
|
传感器 人工智能 语音技术
探索AI技术在智能家居中的应用
【8月更文挑战第78天】本文将探讨人工智能(AI)技术在智能家居领域的应用。我们将从AI技术的基本概念入手,介绍其在智能家居中的作用,并通过代码示例展示如何实现一个简单的智能照明系统。最后,我们将总结AI技术在智能家居领域的优势和挑战。
|
3月前
|
人工智能 监控 物联网
智能家居技术的未来趋势
随着科技的飞速发展,智能家居已经从概念变成了现实。本文将探讨智能家居技术的最新进展,包括物联网(IoT)的集成、人工智能(AI)的应用、以及5G网络对智能家居的影响。我们将一起看看这些技术如何使家居生活更加便捷、安全和节能,并展望未来可能带来的改变。
89 4