一、智能家居功能细节拆分
控制区:
外设区:
继电器组控制灯,远程终端子系统控制灯,窗帘等,火灾报警,摄像头。
面向对象类和对象的概念
类:是一种用户定义的引用的数据类型,也称类类型,(结构体)
对象:类的一种具象
struct Animal {
char name[128];
int age;
int sex; //成员属性
void *peat();
void *pbeat(); //成员方法
};
对象是类的一种具象,如 struct Animal dog ;struct Animal cat;struct Animal person;
dog 就是类的具体的对象,dog是Animal类的对象。
C语言面向对象的代码
#include<stdio.h>
//类:抽象的
struct Animal {
char name[128];
int age;
int sex; //成员属性
void (*peat)();
void (*pbeat)(); //成员方法
};
void dogEat()
{
printf("狗吃骨头\n");
}
void catEat()
{
printf("猫吃鱼\n");
}
void personEat()
{
printf("人吃饭\n");
}
void dongBeat()
{
printf("咬人\n");
}
void dogBeat()
{
printf("咬人\n");
}
void catBeat()
{
printf("抓人\n");
}
void personBeat()
{
printf("打人\n");
}
int main()
{
struct Animal dog;
struct Animal cat;
struct Animal person; //对象,事物的具象
dog.peat = dogEat;
cat.peat = catEat;
person.peat = personEat;
dog.pbeat = dogBeat;
cat.pbeat= catBeat;
person.pbeat= personBeat;
dog.peat();
cat.peat();
person.peat();
dog.pbeat();
cat.pbeat();
person.pbeat();
return 0;
}
结构体新玩法
内核的方式给结构体赋值:
struct Animal dog2 = {
.name = "阿黄",
.peat = dogEat,
.pbeat = dogBeat
};
新玩法代码
#include<stdio.h>
//类:抽象的
struct Animal {
char name[128];
int age;
int sex; //成员属性
void (*peat)();
void (*pbeat)(); //成员方法
};
void dogEat()
{
printf("狗吃骨头\n");
}
void dongBeat()
{
printf("咬人\n");
}
int main()
{
//以前我们写结构体赋值时,是这样按顺序怼进去
struct Animal dog1 = {
"阿黄",1,1,dogEat,dogBeat};
//有时候我们只是想给单个赋值,我们怎么写呢?
struct Animal dog2 = {
.name = "阿黄",
.peat = dogEat,
.pbeat = dogBeat
};
dog.peat();
dog.pbeat();
return 0;
}
二、工厂模式
1. 工厂模式的概念
工厂模式(Factory Pattern)是最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口(API)来指向新创建的对象。
2. 工厂模式的实现
创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口(API)来指向新创建的对象。
暴漏逻辑代码例如:
#include<stdio.h>
//类:抽象的
struct Animal {
char name[128];
int age;
int sex; //成员属性
void (*peat)();
void (*pbeat)(); //成员方法
};
void dogEat()
{
printf("狗吃骨头\n");
}
void dongBeat()
{
printf("咬人\n");
}
int main()
{
struct Animal dog= {
.name = "阿黄",
.peat = dogEat,
.pbeat = dogBeat
};
dog.peat();
dog.pbeat();
return 0;
}
暴漏了逻辑
void dogEat()
{
printf("狗吃骨头\n");
}
void dongBeat()
{
printf("咬人\n");
}
struct Animal dog2 = {
.name = "阿黄",
.peat = dogEat,
.pbeat = dogBeat
};
设计思路图
-
首先在选定位置新建一个文件夹,然后在文件夹里面新建dog.c、animal.h、cat.c和mainPro.c 然后再新建一个文件夹存放sourceInsight的工程文件(有关sourceInsight的用法),如下图所示:
-
先写下4个分文件,animal.h 、cat.c 、dog.c 、person.c(一个功能一个文件) 然后将对应的代码写入对应的文件,比如:dog.c这个文件就是存放dog这个对象的相关行为,并且提供让主程序调用的函数API将dog这个对象添加到链表中去(这个就像是以后的智能家居为实现整个控制系统,需要添加的各个功能模块,一个供能模块就是一个文件),
putdogInLink
函数是将dog对象插入进链表的API接口,这里采用头插法进行插入,即:先插入的在后边。 -
mainPro.c 主程序要调用这三个文件组成链表。 最后就是编写mainpro.c主函数,下面函数还编写了一个可供用户输入的然后查找响应节点的函数
findUtilByName
,用户输入要查找的节点名称,找到后返回指向该节点的指针,通过指针就可以对该节点进行操作,就把它当做链表的一个节点即可。
#include"animal.h"
#include<string.h>
//查找响应节点的函数 功能:链表的遍历查找结点
struct Animal *findUtilByName(char *str,struct Animal *phead)
{
struct Animal *tmp = phead;
if(phead == NULL){
return NULL;
}
else{
while(tmp != NULL){
if(strcmp(tmp->name,str)==0){
//若s1、s2字符串相等,则返回零
return tmp;//返回指向要找节点的指针
}
tmp = tmp->next;
}
return NULL;
}
}
int main()
{
char buf[128]={
'\0'};
struct Animal *phead = NULL;
struct Animal *ptmp;
//把文件都连接起来(链表)
phead = putCatInLink(phead);
phead = putDogInLink(phead);
phead = putPersonInLink(phead);
//业务代码
while(1){
puts("please input Tom ,pipi,CONG");
scanf("%s",buf);
ptmp = findUtilByName(buf,phead);//查找响应节点的函数
if(ptmp != NULL){
ptmp->pbeat();
ptmp->peat();
}
memset(buf,'\0',sizeof(buf));
}
return 0;
}
他们之间的关联就是链表一样,一个文件加入链表,要加功能(就是加文件)就把文件当成元素插入链表中。
3. 工厂模式使用及功能验证
把文件中的cat ,dog, person 换成 卧室灯,餐厅灯,客厅灯,不就是功能性文件嘛, 要在来个卫生间灯,就在加一个文件。
- 添加XXX功能文件:
在目录下添加文件XXX.c
,再在animal.h
中把struct Animal * putXXXInLink(struct Animal *phead);
(接口)暴露出来,暴露出来目的是给mainPro
添加,加入功能链表中。
三、智能家居项目框架设计
- 根据以上简单工厂模式,智能家居设计的时候,就可以设计为指令工厂、main函数、控制工厂,指令工厂面就存放指令(比如:语音指令、客户端指令等,将这些指令串为一个链表),控制工厂就是控制一些家庭设备(比如:各个房间的灯,门锁、串口等,创建一个链表,然后根据指令,去查找对应的控制结点),main函数里面
首先创建两个链表
(指令工厂、控制工厂),然后接下来创建两个线程
(一个是语音的、一个是客户端的),在每个线程里面在接受到指令后去控制工厂里面去查找对应的控制设备然后进行一系列操作
。
1. 智能家居架构代码文件工程建立
- 根据上面的叙述,我们可以创建以下架构的代码文件工程,指令工场和控制工场的头文件就是以下图片中的两个头文件。然后将这些文件导入到
sourceInsight
里面进行代码的编写。
以上是智能家居开发的软件框架构建准备工作,接下来开始代码的编写。
2. 主流程设计和浴室灯框架编写
主流程设计框架
指令工厂框架
设备控制工厂框架
四、基于设备控制工厂—实现灯,火灾
1. 浴室灯控制框架设计
#include"contrlDevice.h"
int bathroomLightOPen()
{
}
int bathroomLightClose()
{
}
int bathroomLightInit()
{
}
int bathroomLightStatus(int status)
{
}
//Devices类 bathroomLight对象
struct Devices bathroomLight = {
.name = "bathroomLight",
.open = bathroomLightOPen,
.close = bathroomLightClose,
.deviceInit = bathroomLightInit,
.changStatus = bathroomLightStatus
};
//(插入设备链表)函数
struct Devices * addBathroomLightToDeviceLink(struct Devices *phead)
{
if(phead == NULL){
return &bathroomLight;
}
else{
bathroomLight.next = phead;
phead = &bathroomLight;
}
};
根据上面内容的代码框架开始编写代码:
- 首先编写
controlDevices.h
这个头文件里面的代码,这个是设备工厂每一个结点的结构体类型,而且 还要在这个头文件里面进行函数的声明,也就是创建的那些设备.c文件里面的函数(为了将设备添加至设备链表的函数
),其中这个头文件里面的结构体内容根据功能提前设定。 - 然后再编写
inputCommand.h
这个头文件里面的内容,这个是指令工厂里面的头文件,也是指令链表里面的每一个结点的类型。编写完这两个头文件, - 然后再进行设备工厂
设备文件xxxx.c
、指令工厂指令文件xxxx.c
和mainPro.c
文件的编写。
2. 浴室灯代码实现和测试
先写一些硬件测试代码,如继电器组的代码,来测试接线问题。
controlDevices.h
是设备控制工厂头文件代码,结点结构体的声明,这里面的东西不一定够用,可以先写上,等不够的时候在进行添加。
#include<wiringPi.h> //包含wiringPi库
#include<string.h>
#include<stdio.h>
struct Devices
{
int status; //表示开关的状态
int pinNum; //引脚数
char devicesName[128]; //存放设备的名称
int (*open)(int pinNum);
int (*close)(int pinNum);
int