您现在的位置是:首页 >技术杂谈 >基于树莓派4B的智能家居网站首页技术杂谈
基于树莓派4B的智能家居
简介基于树莓派4B的智能家居
基于树莓派4B的智能家居
前言
本博文的智能家居使用的树莓派4B作为驱动板,当然也可以使用搭载了freeRtos的STM32驱动板,由于时间匆忙,没办法把从0到1的教程写到博文中,以后有时间的话会出一篇从0到1搭建这个智能家居的博文,到时候也会添加一些新的功能,如触摸屏、红外遥控、等等。
C语言的简单工厂模式
工厂模式介绍
工厂模式就最常用的设计模式之一,属于创建型模式,提供一种创建对象的最佳方式。在工厂模式中,创建对象时,不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。即工厂模式把创建对象和使用对象的两个过程分离,对于使用者无需关心对象时如何创建出来的,直接指定一个对象即可使用该对象的方法。
- C语言不是一门面向对象的语言,而是一门面向过程的语言,但C语言一样支持面向对象编程,即支持简单工厂模式。
- 工厂模式就是类的继承,C语言使用函数指针来实现类的继承,工厂中的设备用链表来链接起来
类和对象
- 类:一种用户定义的数据类型,也称类类型,例如结构体。
- 对象:类的一种实例化,例如结构体赋值。
工厂模式的优缺点
优点
- 在创建对象时,只需要知道对象的名字就行,代码维护性强。
- 需要添加设备时,只需要添加一个对象就行了,代码扩展性。
缺点
- 代码阅读性变复杂。
- 设备增多时会使对象增多,提高了代码复杂度。
智能家居框架
本篇博文介绍的智能家居由两个工厂和若干个设备组成,分别是产品工厂和指令工厂。包含功能如下:
产品工厂
该工厂主要是用来生产一些供人们使用的设备,如灯设备、收集环境数据设备、检测安全设备等等。
#include <stdio.h>
#include <wiringPi.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.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; //链表链接节点
};
/* 告知工厂,对应的设备已经上线成为商品了 */
struct Devices* addBashroomLightToDevicesLink(struct Devices *phead);
struct Devices* addsecondfloorLightToDevicesLink(struct Devices *phead);
struct Devices* addrestaurantLightToDevicesLink(struct Devices *phead);
struct Devices* addlivingroomLightToDevicesLink(struct Devices *phead);
struct Devices* addswimmingLightToDevicesLink(struct Devices *phead);
struct Devices* addlockToDevicesLink(struct Devices *phead);
struct Devices* addfireToDevicesLink(struct Devices *phead);
struct Devices* addbuzzerToDevicesLink(struct Devices *phead);
struct Devices* addishockToDevicesLink(struct Devices *phead);
struct Devices* addfanToDevicesLink(struct Devices *phead);
struct Devices* addsensorToDevicesLink(struct Devices *phead);
.
卫生间灯设备
#include "controlDevices.h"
int bashroomLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int bashroomLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int bashroomLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产卫生间灯设备 */
struct Devices bashroomLight = {
.devicesName = "bathroom",
.pinNum = 23,
.open = bashroomLightOpen,
.close = bashroomLightClose,
.devicesInit = bashroomLightInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addBashroomLightToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &bashroomLight;
return phead;
}else{
bashroomLight.next = phead;
phead = &bashroomLight;
return phead;
}
}
.
二楼灯设备
#include "controlDevices.h"
int secondfloorLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int secondfloorLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int secondfloorLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产二楼灯设备 */
struct Devices secondfloorLight = {
.devicesName = "secondfloor",
.pinNum = 21,
.open = secondfloorLightOpen,
.close = secondfloorLightClose,
.devicesInit = secondfloorLightInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addsecondfloorLightToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &secondfloorLight;
return phead;
}else{
secondfloorLight.next = phead;
phead = &secondfloorLight;
return phead;
}
}
.
餐厅灯设备
#include "controlDevices.h"
int restaurantLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int restaurantLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int restaurantLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产餐厅灯设备 */
struct Devices restaurantLight = {
.devicesName = "restaurant",
.pinNum = 22,
.open = restaurantLightOpen,
.close = restaurantLightClose,
.devicesInit = restaurantLightInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addrestaurantLightToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &restaurantLight;
return phead;
}else{
restaurantLight.next = phead;
phead = &restaurantLight;
return phead;
}
}
.
客厅灯设备
#include "controlDevices.h"
int livingroomLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int livingroomLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int livingroomLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产客厅灯设备 */
struct Devices livingroomLight = {
.devicesName = "livingroom",
.pinNum = 24,
.open = livingroomLightOpen,
.close = livingroomLightClose,
.devicesInit = livingroomLightInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addlivingroomLightToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &livingroomLight;
return phead;
}else{
livingroomLight.next = phead;
phead = &livingroomLight;
return phead;
}
}
.
泳池灯设备
#include "controlDevices.h"
int swimmingLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int swimmingLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int swimmingLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产泳池灯设备 */
struct Devices swimmingLight = {
.devicesName = "swimming",
.pinNum = 25,
.open = swimmingLightOpen,
.close = swimmingLightClose,
.devicesInit = swimmingLightInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addswimmingLightToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &swimmingLight;
return phead;
}else{
swimmingLight.next = phead;
phead = &swimmingLight;
return phead;
}
}
.
风扇设备
#include "controlDevices.h"
int fanOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int fanClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int fanInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产风扇设备 */
struct Devices fan = {
.devicesName = "fan",
.pinNum = 29,
.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 lockOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int lockClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int lockInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
/* 继承产品工厂的类,生产锁设备 */
struct Devices lock = {
.devicesName = "lock",
.pinNum = 28,
.open = lockOpen,
.close = lockClose,
.devicesInit = lockInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addlockToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &lock;
return phead;
}else{
lock.next = phead;
phead = &lock;
return phead;
}
}
.
警报器设备
#include "controlDevices.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 = {
.devicesName = "buzzer",
.pinNum = 27,
.open = buzzerOpen,
.close = buzzerClose,
.devicesInit = buzzerInit,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addbuzzerToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &buzzer;
return phead;
}else{
buzzer.next = phead;
phead = &buzzer;
return phead;
}
}
.
地震监测设备
#include "controlDevices.h"
int shockInit(int pinNum)
{
pinMode(pinNum,INPUT);
digitalWrite(pinNum,HIGH);
}
/* 检测地震发生情况 */
int shockReadStatus(int pinNum)
{
return digitalRead(pinNum);
}
/* 继承产品工厂的类,生产地震监测设备 */
struct Devices shock = {
.devicesName = "shock",
.pinNum = 6,
.devicesInit = shockInit,
.readStatus = shockReadStatus,
.next = NULL,
};
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addishockToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
phead = &shock;
return phead;
}else{
shock.next = phead;
phead = &shock;
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 = 4,
.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 = 1,
.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;
}
}
.
指令工厂
该工厂主要是用来生产一些供人们发出指令控制的设备,如语音设备、server设备、摄像头设备等等,这些设备可以控制产品工厂的设备做出一些控制行为。
#include <wiringPi.h>
#include <stdio.h>
#include <wiringSerial.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <curl/curl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.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; //链表链接节点
};
//告知工厂,对应的设备已经上线成为商品了
struct InputCmd* addvoiceControlToInputCmdLink(struct InputCmd *phead);
struct InputCmd* addserverControlToInputCmdLink(struct InputCmd *phead);
struct InputCmd* addcameraControlToInputCmdLink(struct InputCmd *phead);
.
语音控制设备
该设备通过语音模块su-03获取主人的命令词并通过智能公元平台将相应的命令词转换成字符串通过串口发送给树莓派。
#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,'