赞
踩
写在最前:智能家居项目已经搁置了有一段时间,现在已经有了初步的成果,代码基于wiringPi库来进行,原来一直希望可以通过树莓派来完成,但是后来设想希望后期能够在原先代码的基础上舍弃wiringPi库,自行编写驱动程序以及设备树文件来进行,现在树莓派的价格居高不下,手上仅有一块树莓派4b(是朋友借给我学习的),想到战线较长,故索性选择成本更加低的香橙派zero 2来继续完成这个项目。双方都是基于wiringpi库,因此换到新的平台无需做过多更改,只需重新选择合适的引脚以及串口节点即可。这将会是一系列博文,记录自己在制作过程中遇到的问题,日后也会对功能逐渐完善。
此次的项目,我暂时设定如下功能:
程序框架分析:
由上,我需要用到的模块是:四路/多路的继电器(用于灯光控制)、烟雾报警器(火灾报警)、温湿度传感器(检测环境温度)、甲醛传感器(检测房间内的甲醛含量)、摄像头(人脸识别、室内监控)、语音模块(室内语音控制)。以及需要用到socket编程使用网络来发送指令进行控制灯光等设备。主函数的实现无非是多线程进行,对于不同的模块的管理则需要用到链表,可以使用面向对象编程的思想,对于不同的模块去构造出相应的对象。通过链表对相同类型的模块设备进行管理,以访问该模块。
相应的结构体设计:
- struct controlDev
- {
- char devName[128];
- int status;
- int pinNum;
-
- int (*open)(int pinNum);
- int (*close)(int pinNum);
- int (*devInit)(int pinNum);
-
-
- int (*readStatus)(int pinNum, struct controlDev* str_Dev);
- int (*changeStatus)(int status, struct controlDev* str_Dev);
- //char *(*getPhoto)();
- //char* (*getBaseFaData)(char* dataPhotoPath);
- //int (*getOnce)();
- //size_t (*getDif)(void *ptr, size_t size, size_t nmemb,void *stream);
-
- struct controlDev* next;
- };
devName:设备名(用于模块的检索)
status:设备的状态
pinNum:引脚号
函数指针: open、close、devInit(用于设备的开启、关闭、初始化)
readStatus、changeStatus(设备状态的读取、改变设备的状态)
如上结构体用于管理模块设备
- struct InputCommander
- {
- char comName[128];
- char devName[128];
- char command[32];
- char port[12];
- int sfd;
- int fd;
- int (*init)(struct InputCommander* comstr, char *ipAdress, char* port);
- int (*getCommand)(struct InputCommander* comstr);
- char log[1024];
- struct InputCommander* next;
- };
此结构体用于管理输入指令的接收:语音模块、socket编程的代码管理。
这次我将对灯光控制部分进行分析,因为这部分相较之下比较简单,抛开驱动部分直接使用wiringpi库编程,无非就是相应的引脚控制,对于程序相对比较简单。
示例代码如下:
- int lightDevOpen(int pinNum)
- {
- digitalWrite(pinNum,LOW);
- }
-
- int lightDevClose(int pinNum)
- {
- digitalWrite(pinNum,HIGH);
- }
-
- int lightDevInit(int pinNum)
- {
- pinMode(pinNum,OUTPUT);
- digitalWrite(pinNum,HIGH);
- }
-
- int lightDevChangeSta(int status, struct controlDev* str_Dev)
- {
- str_Dev->status = status;
- return 0;
- }
-
- int lightDevReadSta(int pinNum, struct controlDev* str_Dev)
- {
- int pin_status;
- pin_status = digitalRead(pinNum);
- if(pin_status != str_Dev->status)
- str_Dev->status = pin_status;
-
- return pin_status;
- }
-
-
- struct controlDev light_dev= {
- .devName = "lightDevName",
- .pinNum = PIN_NUM,
- .status = HIGH,
- .open = lightDevOpen,
- .close = lightDevClose,
- .devInit = lightDevInit,
- .changeStatus = lightDevChangeSta,
- .readStatus = lightDevReadSta,
- };
随后将该模块添加进链表:
- struct controlDev* addLightDevInLink(struct controlDev* phead)
- {
- if(phead == NULL){
- phead = &light_dev;
- }else{
- light_dev.next = phead;
- phead = &light_dev;
- }
- return phead;
- }
这样就可以对灯光类型的模块进行添加,通过主函数中findDevName函数来找到相应的模块信息。通过结构体指针访问相应的模块成员。
- findDevName函数
-
- struct controlDev* findDevName(char *devName, struct controlDev* pheadDev)
- {
- struct controlDev* str = pheadDev;
- if(pheadDev == NULL){
- printf("NULL\n");
- }else{
- while(str != NULL){
- if(strcmp(str->devName,devName) == 0){
- return str;
- }
- str = str->next;
- }
- }
- return NULL;
- }
如上就是对灯光的控制,单个灯光会对应各自相应结构体,但是此类代码相对来说比较繁琐,不难看出如上对于灯光的代码大部分都是重复的,但以实现功能为前提,先将上述基本功能实现,随后可以慢慢精进。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。