【ARM-Linux篇】项目:智能家居

news2024/11/19 22:44:04

一、项目概述

•项目功能

通过语音控制客厅灯、卧室灯、风扇、人脸识别开门等,可以进行火灾险情监测,可以并且实现Sockect发送指令远程控制各类家电等
•项目描述

全志H616通过串口连接各模块硬件,检测语音的识别结果,分析语音识别的结果来对家电设备进行控制。摄像头拍摄到人脸之后通过阿里云平台人脸识别方案对比阿里云人脸数据库来进行人脸识别开锁。该项目采用设计模式中的简单工厂模式,让设备端和控制端都采用链表管理,提高了项目代码的稳定性和拓展性。

二、系统框图

三、硬件搭建

语音模块及人脸识别方案配置参考: 语音模块配置      人脸识别方案

四、软件框架

整个项目开启4个监听线程, 分别是:
1. 语音监听线程:用于监听语音指令, 当有语音指令过来后, 通过消息队列的方式给消息处理线程发送指令
2. 网络监听线程:用于监听网络指令,当有网络指令过来后, 通过消息队列的方式给消息处理线程发送指令
3. 火灾检测线程:当存在煤气泄漏或者火灾闲情时, 发送警报指令给消息处理线程
4. 消息监听线程: 用于处理以上3个线程发过来的指令,并根据指令要求配置GPIO引脚状态,OLED屏显示、语音播报,还有人脸识别开门
上述四个线程采用统一个对外接口接口,同时添加到监听链表中。 

 统一的监听模块接口如下:

struct control
{
    char control_name[128]; //监听模块名称
    int (*init)(void); //初始化函数
    void (*final)(void);//结束释放函数
    void *(*get)(void *arg);//监听函数,如语音监听
    void *(*set)(void *arg); //设置函数,如语音播报
    struct control *next;
};
struct control *add_device_to_ctrl_list(struct control *phead, struct control *device);

统一的设备类接口如下:

struct gdevice
{
    char dev_name[128]; //设备名称
    int key; //key值,用于匹配控制指令的值
    int gpio_pin; //控制的gpio引脚
    int gpio_mode; //输入输出模式
    int gpio_status; //高低电平状态
    int check_face_status; //是否进行人脸检测状态
    int voice_set_status; //是否语音语音播报
    struct gdevice *next;
};
struct gdevice *add_device_to_gdevice_list(struct gdevice *phead, struct gdevice *device);
struct gdevice *find_gdevice_by_key(struct gdevice *pdev, unsigned char key);
int set_gpio_gdevice_status(struct gdevice *pdev);

 五、项目代码

本项目代码量较大,仅展示部分源代码,项目开源地址:https://gitee.com/GeekerGao/smart-home

(一)

监听模块接口加入链表

control.c

#include <stdio.h>
#include "control.h"

struct control *add_interface_to_control_list(struct control *phead,struct control *control_interface)
{
    //头插法添加节点
    if(NULL == phead)
    {   
        phead = control_interface; 
    }
    else
    {
        control_interface->next = phead;
        phead = control_interface;   
    }

    return phead;
};

control.h

#ifndef __CONTROL_H__
#define __CONTROL_H__

struct control
{
    char control_name[128]; //监听模块名称
    int (*init)(void); //初始化函数
    void (*final)(void);//结束释放函数
    void *(*get)(void *arg);//监听函数,如语音监听
    void *(*set)(void *arg); //设置函数,如语音播报
    struct control *next;
};

struct control *add_interface_to_control_list(struct control *phead,struct control *control_interface);

#endif

消息队列的接口 

msg_queue.c

#include <stdio.h>
#include "msg_queue.h"

// 定义消息队列的名称
#define QUEQUE_NAME "/test_queue"
// 创建一个新的消息队列
mqd_t msg_queue_create(void)
{
    // 初始化mqd_t变量mqd为-1,表示未成功打开消息队列
    mqd_t mqd = -1;
    
    // 定义并初始化消息队列的属性结构体
    struct mq_attr attr;
    // 设置消息队列属性:默认为阻塞模式
    attr.mq_flags = 0;           
    // 消息队列最大消息数量为10
    attr.mq_maxmsg = 10;         
    // 每条消息的最大字节数为256
    attr.mq_msgsize = 256;       
    // 当前消息队列中消息数量初始化为0
    attr.mq_curmsgs = 0;         
    // 使用mq_open函数创建消息队列,如果不存在则根据属性创建(O_CREAT),并设置读写权限(O_RDWR)
    // 第三个参数是权限位,0666表示所有用户都有读写权限,实际权限还需参考umask值
    // 第四个参数是指向消息队列属性的指针
    mqd = mq_open(QUEQUE_NAME, O_CREAT | O_RDWR, 0666, &attr);    
    // 打印消息队列描述符,用于调试
    printf("%s | %s | %d:mqd = %d\n", __FILE__,__func__,__LINE__,mqd);
    // 返回创建的消息队列描述符
    return mqd; 
}
// 清理并关闭消息队列
void msg_queue_fianl(mqd_t mqd)
{
    // 如果消息队列描述符有效,则关闭消息队列
    if(-1 != mqd)
        mq_close(mqd);
    
    // 删除消息队列
    mq_unlink(QUEQUE_NAME);    
    
    // 保险起见,再次将mqd设为-1
    mqd = -1;   
}
// 向消息队列发送消息
int send_message(mqd_t mqd,void *msg,int msg_len)
{
    int byte_send = -1;
    // 使用mq_send函数发送消息到消息队列,第四个参数0为消息的优先级,默认情况下优先级不影响消息的发送顺序
    byte_send = mq_send(mqd, (char *)msg, msg_len, 0);   
    // 返回发送的字节数,成功时应等于msg_len,失败时返回-1
    return byte_send;
}

 msg_queue.h

#ifndef __MSG_QUEUE_H__
#define __MSG_QUEUE_H__

#include <mqueue.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

mqd_t msg_queue_create(void);
void msg_queue_fianl(mqd_t mqd);
int send_message(mqd_t mqd,void *msg,int msg_len);

#endif

语音监听接口 

global.h

#ifndef __GLOBAL_H__
#define __GLOBAL_H__    
typedef struct {
    mqd_t mqd;
    struct control *ctrl_phead;
}ctrl_info_t;

#endif

voice_interface.c

#include <stdio.h>
#include <pthread.h> // 线程库
#include "voice_interface.h" // 语音接口头文件
#include "uartTool.h" // 串口操作工具库
#include "msg_queue.h" // 消息队列操作库
#include "global.h" // 全局变量和宏定义头文件

// 串口文件描述符,初始设为-1
static int serial_fd = -1;
// 初始化语音模块
static int voice_init(void)
{
    // 打开指定的串口设备,BAUD为波特率宏定义
    serial_fd = myserialOpen(SERIAL_DEV, BAUD);
    // 打印日志,显示串口文件描述符
    printf("%s|%s|%d:serial_fd = %d\n", __FILE__, __FUNCTION__, __LINE__, serial_fd);
    return serial_fd;
}
// 释放语音模块资源
static void voice_final(void)    
{
    if(-1 != serial_fd) // 如果串口已打开
    {
        // 关闭串口
        close(serial_fd);
        // 重置串口文件描述符为-1
        serial_fd = -1;
    }
}
// 线程函数,用于接收语音指令
static void *voice_get(void *arg)
{
    unsigned char buffer[6] = {0}; // 初始化缓冲区
    int len; // 接收长度
    mqd_t mqd 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1867109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

山东大学多核并行2024年回忆版

2024.6.13回忆版 矩阵向量乘不可整除代码 集合通信与点对点通信的区别 块划分、循环划分、循环块划分&#xff08;14个向量&#xff0c;4个进程&#xff09; 按行访问还是按列访问快 SISD系统问题 循环依赖问题 问题&#xff1a;为什么不能对这个循环并行化&#xff0…

Vue移动端动态表单生成组件

FormCreate 是一个可以通过 JSON 生成具有动态渲染、数据收集、验证和提交功能的表单生成组件。支持6个UI框架&#xff0c;适配移动端&#xff0c;并且支持生成任何 Vue 组件。内置20种常用表单组件和自定义组件&#xff0c;再复杂的表单都可以轻松搞定。 帮助文档 | 源码下载…

科技赋能·创领未来丨智合同和百胜中国就Contract AI Studio项目达成合作

#智合同 #百胜中国 #AIGC #NLP #LLM #Contract AI Studio 近期&#xff0c;国内AIGC和LLM大语言模型发展可谓是如火如荼&#xff0c;其迅速崛起为社会和产业发展起到了非常重要的作用。人们利用AI技术&#xff08;AIGC、LLM大语言模型、NLP等&#xff09;将其赋能到企业生…

【ai】tx2 nx:ubuntu18.04 yolov4-triton-tensorrt 成功部署server 运行

isarsoft / yolov4-triton-tensorrt运行发现插件未注册? 【ai】tx2 nx: jetson Triton Inference Server 部署YOLOv4 【ai】tx2 nx: jetson Triton Inference Server 运行YOLOv4 对main 进行了重新构建 【ai】tx2 nx :ubuntu查找NvInfer.h 路径及哪个包、查找符号【ai】tx2…

Linux系统安装和卸载nginx

&#x1f4d6;Linux系统安装和卸载nginx ✅下载✅安装✅启动nginx✅安装成系统服务✅常见问题&#xff1a;80端口被占用了✅卸载✅目录结构 以下介绍的是以源码编译安装方式&#xff1a; ✅下载 官方地址&#xff1a;https://nginx.org/en/download.html 123云盘地址&#x…

YOLOv8数据集标注

1 简介 数据集是必不可少的部分&#xff0c;数据集的优劣直接影响训练效果。一般来说&#xff0c;一个完整的数据集应该包括训练集、测试集和验证集。通常&#xff0c;数据集会被划分为训练集和测试集&#xff0c;比如将数据集的70%用作训练集&#xff0c;30%用作测试集。在进行…

【知识学习】Unity3D——Surface Shaderlightning的概念及使用方法示例

Unity3D是一个广泛使用的跨平台游戏引擎&#xff0c;它提供了强大的图形渲染功能。在Unity中&#xff0c;Shader是用于控制图形渲染过程的程序&#xff0c;它们运行在GPU上&#xff0c;用于计算屏幕上每个像素的颜色。Surface Shader和Lighting是Unity Shader编程中非常重要的概…

JAVA期末速成库(7)第七、八章

一、习题介绍 第七章 Check Point&#xff1a;P251 7.2&#xff0c;7.4&#xff0c;7.16&#xff0c;8.2 Programming Exercise&#xff1a;7.10&#xff0c;7.14&#xff0c;7.26 二、习题及答案 Check Point&#xff1a; 7.2 When is the memory allocated for an ar…

群体优化算法---石墨烯优化算法介绍以及在期权定价上的应用(Black-Scholes模型来计算欧式期权的理论价格)

介绍 石墨烯算法是一种新兴的优化算法&#xff0c;灵感来自于石墨烯的结构和特性。石墨烯是一种由碳原子构成的二维蜂窝状晶格结构&#xff0c;具有优异的机械、电学和热学性能。石墨烯算法通过模拟石墨烯原子之间的相互作用和迁移&#xff0c;来求解复杂的优化问题 基本概念…

力扣每日一题 特别的排列 DFS 记忆化搜索 位运算 状态压缩DP

Problem: 2741. 特别的排列 &#x1f468;‍&#x1f3eb; 参考题解 &#x1f37b; 暴搜 ⏰ 时间复杂度&#xff1a; O ( N ) O(N) O(N) class Solution {public int specialPerm(int[] nums) {boolean[] visited new boolean[nums.length];return dfs(nums, 0, -1, visit…

一个Mongodb案例-使用地理信息查询酒店

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第79篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

vue3项目登录成功后根据角色菜单来跳转指定页面(无首页)

前言&#xff1a;需求不想要首页&#xff0c;登录什么角色跳转到这个角色经常使用的页面。&#xff08;例如&#xff1a;审核者角色的人输入用户名密码成功后就自动跳转到待审核的页面&#xff0c;仓库管理员登录成功则自动跳转到仓库列表&#xff09; 需要解决的点和想法&…

Linux笔记之Bash脚本中的EOF

Linux笔记之Bash脚本中的EOF code review! 文章目录 Linux笔记之Bash脚本中的EOF基本用法自定义结束符变量替换禁用变量替换用于脚本嵌入重定向到文件与命令组合总结 在 Bash 脚本中&#xff0c; EOF 通常用于定义一个多行字符串或文档块。这种技术被称为“Here Document”&a…

python基础语法 003-3 数据类型元组

1 元组 1.1 元组含义 1.1.1 元组的表示 #元组的表示方法:() names ("xiaoyun", "xiaoming") print(names)--结果------- (xiaoyun, xiaoming) 1.1.2 空元组 #空元组 names () print(type(names)) print(len(names))----------------结果--------- &l…

802.11漫游流程简单解析与笔记_Part2_02_wpa_supplicant、cfg80211、nl80211内核与驱动的关系

wpa、cfg80211、nl80211内核与驱动的关系示意图如下&#xff1a; nl80211和cfg80211都是内核定义的标准接口&#xff0c;目的是规范驱动和应用的统一调用&#xff0c;wpa中常出现nl80211就是通过内核的nl80211接口调用对应cfg80211的部分&#xff0c;进而控制驱动收发数据或切换…

禁止浏览器对input的自动填充和填充提示(适用于谷歌、火狐、Edge(原IE浏览器)等常见浏览器)

目录 1.要解决的问题2.一技能&#xff1a;原生属性&#xff0c;小试牛刀3.二技能&#xff1a;傀儡input&#xff0c;瞒天过海4.三技能&#xff1a;JavaScript出击&#xff0c;直接开大 写在前面&#xff1a; 如有转载&#xff0c;务必注明出处&#xff0c;否则后果自负。 1.要解…

基于STM32设计的智能家居远程调温系统(通过红外线控制空调)_75

文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】ESP8266工作模式配置1.3 设计的意义1.4 开发工具的选择1.5 系统框架图1.6 系统功能总结1.7 原理图二、硬件选型2.1 ESP8266-串口WIFI2.2 STM32F103C8T6开发板2.3 红外学…

已解决java.beans.IntrospectionException: 在Java Beans中内省过程失败的正确解决方法,亲测有效!!!

已解决java.beans.IntrospectionException: 在Java Beans中内省过程失败的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 检查命名规范 验证Getter/Setter匹配性 确认访问权限 审查类型一致性 简…

charls抓包工具 mumu模拟器抓包apk

1.先安装mumu 官网添加链接描述 2.配置 设置&#xff0c;点进互联网&#xff0c;点编辑&#xff0c;选择手动代理 主机名写自己电脑的ip地址&#xff0c;端口随便&#xff0c;只要不被占用&#xff0c;一般参考其他人都是8888 3.下载charls 参考这个添加链接描述 先官网…

静态时序分析:ideal_clock、propagated_clock以及generated_clock的关系及其延迟计算规则(一)

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 理想时钟(ideal_clock)、传播时钟(propagated_clock)是两种相对的时钟&#xff0c;理想时钟用于时钟树综合(CTS)前&#xff0c;而传播时钟用于时钟树综合后。生成…