智能家居项目的软件实现
紧接上文 基于OrangePi Zero2的智能家居项目(准备阶段)-CSDN博客
目录
参考:自己创建Makefile文件管理项目工程-CSDN博客
一、项目整体设计
1.1项目整体设计
1.2具体划分
定义两个统一特征的结构体(控制与被控),都是通过链表进行连接
控制设备
被控设备
二、开发工作的前期准备
1、进行分类,并用Makefile文件进行管理
参考:自己创建Makefile文件管理项目工程-CSDN博客
三、具体开发项目
1、添加语音监听接口
1.1 消息队列的实现
1.2语音控制模块的实现
.
头插法的实现,串成一个一个的设备节点
main.c
1.3 消息队列函数的继续实现(在main函数里面实现)
main.c里面继续封装消息队列的实现
终于知道voice_get里面的mqd怎么传参了
编译通过
1.4 放到香橙派上面进交叉编译
再用mqtest传到香橙派进行测试
2、添加网络监听接口
2.1增加文件
2.2整理框架
2.3 优化细节,注意改动
2.4、编译好传送过去执行找问题
2.5 网络调试助手启动!
上面这张图的结果其实是错误的!!!
3、添加烟雾监听的接口
3.1 增加相应的文件
smoke.h
补全一部分的smoke_interface.c
额外补充
3.2 补全smoke_interface.c
3.3 编译并发送
3.4 具体演示(见后续安装)
ps:优化之前写的代码(语音,socket,火灾)
4、添加消息接收监听接口
4.1 添加相应的文件
4.2 补全一部分代码,初始化消息,关闭消息
4.3 receive_get函数的实现
4.4 实现控制 设备(灯、风扇)线程的功能函数
4.5 编译测试成功
5、添加设备类结点接口(用消息接收监听队列去控制设备)
5.1 创建被控设备的链表结点
5.2 添加相应的文件(毕竟是个被控设备链表)
5.3 具体实现控制的设备要怎么控制
6、添加各类的被控设备结点
6.1 添加被控设备----客厅灯
往消息接收线程函数里面,声明客厅灯的初始化
ps:对oled显示做一个处理
编译测试.....(待补充)
6.2 添加卧室灯控制代码
编译测试.....(待补充)
6.3 添加风扇控制代码
编译测试.....(待补充)
6.4添加火灾报警(烟雾报警)检测功能
这里补充一下,蜂鸣器报警的流程:先是烟雾传感器检测到有烟雾时,将数据发送给板子,板子接收到发过来的数据之后,再去触发蜂鸣器
添加对应的文件
这里的.voice_set_status 其实是“1” 要设置的
修改一下smoke_interface.c里面的值
增加蜂鸣器的报警
pthread_create就这样就行了,不用在添加其他的东西
编译测试.....(待补充)
6.5 增加OLED显示功能
编译测试.....(待补充)
7 添加人脸识别开锁
7.1 添加对应的文件
7.2判断人脸的数据才能开门
7.3 开门之后也要关门
7.4 配置摄像头
参考文章:
基于OrangePi的智能垃圾桶(全程可实现)-CSDN博客
7.5 报错
记录关于智能家居的路程的一个bug___Segmentation fault(段错误)-CSDN博客
7.6 编译测试
四、ini文件解析本次项目
前言
上述的项目的基本功能都已实现,但是存在值得优化的地方
解决办法:写一个固定的配置文件,直接添加设备就行了
所以就引入了 ini文件配置格式
1、什么是 ini文件配置格式
关键就是 键值对
2、下载源码和解析文件
apt-cache search libinih
一个简单的ini文件的一个解析
sudo apt source libinih-dev
安装源码包(此时可以尝试使用root权限来安装)
进入文件夹
查看 示例代码
3、在项目中运用ini文件
3.1 编译运行
这里补充一点:代码中没有循环语句,说明这个handle是多次调用的
3.2 项目优化
把文件添加到ini文件夹进行测试
ini_test.c
/* Example: parse a simple configuration file */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ini.h"
#include "gdevice.h"
#ifndef OUTPUT
#define OUTPUT 1
#define INPUT 0
#endif
#ifndef LOW
#define LOW 0
#define HIGH 1
#endif
//像receive文件里面那样添加被控设备链表
static struct gdevice *pdevhead = NULL;
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
// if (MATCH("protocol", "version"))
static int handler_gdevice(void* user, const char* section, const char* name,
const char* value)
{
//创建被控设备的临时的指针
struct gdevice *pgdev = NULL;
//找设备的逻辑就是:如果section都是一个字段,那么其他的东西(name value)肯定都是一个设备的
//所以,我们只要找到一个section,那么这个section下面的所有name value就是同一个设备的
//先找到section,再找name value,或者创建一个结构体,存放name value这些值
if(NULL == pdevhead)
{
pdevhead = (struct gdevice *)malloc(sizeof(struct gdevice));
pdevhead->next = NULL;
memset(pdevhead, 0, sizeof(struct gdevice));
strcpy(pdevhead->dev_name, section); //把section赋值给当前设备的名字
}
//第一个添加结点是没错这样,但是第二个结点添加进来的时候就有空间了
else if (0 != strcmp(pdevhead->dev_name, section))
{
pgdev = (struct gdevice *)malloc(sizeof(struct gdevice));
memset(pgdev, 0, sizeof(struct gdevice));
strcpy(pgdev->dev_name, section);
//头插法
pgdev->next = pdevhead;
pdevhead = pgdev;
}
if(NULL != pdevhead)
{
if(MATCH(pdevhead->dev_name, "key")) //假如第一个进来的是lock,就是挨着挨揍去比对他的key、gpio_pin、gpio_mode、gpio_status、check_face_status、voice_set_status这些值
{
sscanf(value , "%x" , &pdevhead->key); //value是一个作为输入的值,想让其输出为16进制变成指令,所以%x
printf("%d | pdevhead->key = %x\n" , __LINE__,pdevhead->key);
}
else if (MATCH(pdevhead->dev_name, "gpio_pin"))
{
pdevhead->gpio_pin = atoi(value); //把字符串转换成整数
}
else if(MATCH(pdevhead->dev_name, "gpio_mode"))
{
if(strcmp(value, "OUTPUT") == 0)
{
pdevhead->gpio_mode = OUTPUT; //OUTPUT
}
else if(strcmp(value, "INPUT") == 0)
{
pdevhead->gpio_mode = INPUT; //INPUT
}
}
else if(MATCH(pdevhead->dev_name, "gpio_status"))
{
if(strcmp(value, "LOW") == 0)
{
pdevhead->gpio_mode = LOW;
}
else if(strcmp(value, "HIGH") == 0)
{
pdevhead->gpio_mode = HIGH;
}
}
else if(MATCH(pdevhead->dev_name, "check_face_status"))
{
pdevhead->check_face_status = atoi(value); //把字符串转换成整数
}
else if(MATCH(pdevhead->dev_name, "voice_set_status"))
{
pdevhead->voice_set_status = atoi(value); //把字符串转换成整数
}
}
//打印有多少个ini文件里面的设备
printf("---secition: %s, name: %s, value: %s\n", section, name, value);
return 1;
}
int main(int argc, char* argv[])
{
if (ini_parse("gdevice.ini", handler_gdevice, NULL) < 0) {
printf("Can't load 'gdevice.ini'\n");
return 1;
}
//测试
struct gdevice *pdev = pdevhead;
while(pdev)
{
printf("pdev->dev_name = %s\n", pdev->dev_name);
printf("pdev->key = %x\n", pdev->key);
printf("pdev->gpio_pin = %d\n", pdev->gpio_pin);
printf("pdev->gpio_mode = %d\n", pdev->gpio_mode);
printf("pdev->gpio_status = %d\n", pdev->gpio_status);
printf("pdev->check_face_status = %d\n", pdev->check_face_status);
printf("pdev->voice_set_status = %d\n", pdev->voice_set_status);
pdev = pdev->next;
}
return 0;
}
编译运行: