智能家居项目
项目概况
项目材料:小房子模型,树莓派,Wemos D1,继电器组,继电器,语音模块LDV7,连接线,电池电源。
项目效果:可以通过网络远程控制树莓派服务器,让树莓派用wiringPi库控制不同针脚(GPIO)输出电压,让小房子搭建的别墅模型里不同位置灯的开关。
因为是做测试项目,所以在继电器组的口子用完后,就在加了一个单独的继电器控制屋外的泳池灯,是通过远程发送控制指令达到树莓派网络服务器,在树莓派解析指令后,在启动一个客户端服务器,给Wemos发控制指令,让Wemos对发来的控制指令解析后,在做最后的具体执行开关灯。
设计模式1
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
工厂模式:
在开始编写代码时,沿用了设计模式里的工厂模式。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
设备工厂的设备数据对象
struct Devices
{
char deviceName[128];
int status;
int pinNum;
int (*open)(int pinNum);
int (*close)(int pinNum);
int (*deviceInit)(int pinNum);
int (*readStatus)();
int (*changeStatus)(int status);
struct Devices *next;
};
配置设备:
struct InputCommandr voiceContrl =
{
.commandName = "voice",
.deviceName = "/dev/ttyAMA0",
.command = {'\0'},
.init = voiceInit,
.getCommand = voiceGetCommand,
.log = {'\0'},
.next = NULL
};
指令工厂的指令数据对象
struct InputCommandr
{
char commandName[128];
char deviceName[128];
char command[32];
int (*init)(struct InputCommandr *voices, char *ipAderss, char *port);
int (*getCommand)(struct InputCommandr *voices);
char log[1024];
int fd;
char port[12];
char ipAddress[32];
int sfd;
struct InputCommandr *next;
};
配置指令:
struct InputCommandr socketContrl =
{
.commandName = "socketServer",
.command = {'\0'},
.init = socketInit,
.getCommand = socketGetCommand,
.log = {'\0'},
.port = "8890",
.ipAddress = "192.168.1.220",
.next = NULL
};
项目结构搭建
contrlDevices.h—— 设备工厂
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wiringPi.h>
//定义需要被用到的设备数据表
struct Devices
{
char deviceName[128];
int status;
int pinNum;
int (*open)(int pinNum);
int (*close)(int pinNum);
int (*deviceInit)(int pinNum);
int (*readStatus)();
int (*changeStatus)(int status);
struct Devices *next;
};
//声明添加设备模块配置信息的函数,好被主程序调用
struct Devices* addBathroomLightToDeviceLink(struct Devices *phand);
struct Devices* addUpstairsLightToDeviceLink(struct Devices* phand);
struct Devices* addRestaurantLightToDeviceLink(struct Devices* phand);
struct Devices* addRoomLightToDeviceLink(struct Devices* phand);
struct Devices* addFireToDeviceLink(struct Devices* phand);
inputCommand.h—— 指令工厂
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
//配置好解析指令的宏定义
#define WSD 1 //打开卧室灯
#define KTD 2 //打开客厅灯
#define CFD 3 //打开厨房灯
#define CSD 4 //打开厕所灯
#define YCD 5 //打开泳池灯
#define ALLON 6 //打开所有灯
#define WS 7 //关闭卧室灯
#define KT 8 //关闭客厅灯
#define CF 9 //关闭厨房灯
#define CS 10 //关闭厕所灯
#define YC 11 //关闭泳池灯
#define ALLOFF 12 //关闭所有灯
//定义控制继电器组引脚的宏定义
#define SWI1 23 //厕所
#define SWI2 25 //卧室
#define SWI3 24 //客厅
#define SWI4 22 //厨房
//定义需要被用到的设备数据表
struct InputCommandr
{
char commandName[128];
char deviceName[128];
char command[32];
int (*init)(struct InputCommandr *voices, char *ipAderss, char *port);
int (*getCommand)(struct InputCommandr *voices);
char log[1024];
int fd;
char port[12];
char ipAddress[32];
int sfd;
struct InputCommandr *next;
};
//声明添加指令模块配置信息的函数,好被主程序调用
struct InputCommandr* addVoiceContrlInputCommandLink(struct InputCommandr* phand);
struct InputCommandr* addSocketContrlInputCommandLink(struct InputCommandr* phand);
mainPro.c—— 主程序
//连接设备工厂,指令工厂的头文件
#include "contrlDevices.h"
#include "inputCommand.h"
//定义指令工厂,设备工厂文件头的全局变量,便于函数调用
struct InputCommandr* pcommandHand = NULL;
struct Devices* pdevicesHand = NULL;
struct InputCommandr* socketHandler = NULL;
int c_fd;
//查找设备工厂对应的设备结构体数据函数
struct Devices *findDeviceByName(char *name,struct Devices *phand)
{
struct Devices *tmp = phand;
if(phand == NULL){
return NULL;
}else{
while(tmp !=NULL){
if(strcmp(name,tmp->deviceName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
//查找指令工厂对应的指令结构体数据的函数
struct InputCommandr *findCommandByName(char *name,struct InputCommandr *phand)
{
struct InputCommandr *tmp = phand;
if(phand == NULL){
return NULL;
}else{
while(tmp !=NULL){
if(strcmp(name,tmp->commandName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
//给Wemos发指令信息函数
void writeWemosSignal(char* command)
{
int s_fd=socket(AF_INET, SOCK_STREAM,0);//配置通信模式
if (s_fd==-1)
{
perror("socket");
exit(-1);
}
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_port=htons(atoi("8898"));
inet_aton("192.168.1.104",&addr.sin_addr);
if(connect(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr))==-1)//连接wemos版
{
perror("connect");
exit(-1);
}
write(s_fd,command,strlen(command));//向wemos版发送信息
close(s_fd);
}
//解析收到的指令
int get_cmd_type(char *cmd)
{
if(strcm