智能家居6 -- 配置 ini文件优化设备添加

2024-05-24 22:20

本文主要是介绍智能家居6 -- 配置 ini文件优化设备添加,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

不知道什么是ini的朋友可以先看这篇:一文带你入门ini格式-CSDN博客

准备

如下图:

在src 下面添加 ini.c

在inc 下面添加 ini.h

在 receive_interface.c 里面包含头文件,把之前添加的设备类注释掉

这时候就可以把相关设备的(.c   .h)文件给删掉了

如下图:

  

修改/添加 代码

gdevice.ini

[lock]
key=0x44
gpio_pin=8
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=1
voice_set_status=1[beep]
key=0x45
gpio_pin=9
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=1[BR led]
key=0x42
gpio_pin=5
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0[LV led]
key=0x41
gpio_pin=2
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0[fan]
key=0x43
gpio_pin=7
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0

修改init

我们需要把gdevice.ini 文件传送到arm 设备的 /etc/下面

sudo cp gdevice.ini /etc/

修改后的receive_interface.c

#include <pthread.h>
#include <mqueue.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <wiringPi.h>#include "receive_interface.h"
#include "control.h"
#include "mq_queue.h"
#include "global.h"
#include "face.h"
#include "myoled.h"
//#include "lrled_gdevice.h"
#include "gdevice.h"
// #include "fan_gdevice.h"
// #include "bled_gdevice.h"
// #include "beep_gdevice.h"
// #include "lock_gdevice.h"#include "ini.h"
#include "face.h"#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0/*
接收模块:
对接收到消息做出相应处理
包括 oled 人脸识别 语言播报 GPIO  引脚状态配置*/static int oled_fd = -1;
static struct gdevice *pdevhead = NULL;typedef struct
{int msg_len;unsigned char *buffer;ctrl_info_t *ctrl_info;
} recv_msg_t;static int handler_gdevice(void *user, const char *section, const char *name, const char *value)
{struct gdevice *pdev = NULL;if (NULL == pdevhead){pdevhead = (struct gdevice *)malloc(sizeof(struct gdevice));memset(pdevhead, 0, sizeof(struct gdevice));pdevhead->next = NULL;strcpy(pdevhead->dev_name, section);}// printf("section = %s, name = %s, value = %s\n", section, name, value);else if (0 != strcmp(section, pdevhead->dev_name)) // 当section对不上的时候,表示到了下一个设备{// 把新节点(设备)使用头插法插入pdev = (struct gdevice *)malloc(sizeof(struct gdevice));memset(pdev, 0, sizeof(struct gdevice));strcpy(pdev->dev_name, section);pdev->next = pdevhead;pdevhead = pdev;}if (NULL != pdevhead){if (MATCH(pdevhead->dev_name, "key")){sscanf(value, "%x", &pdevhead->key); // 把value(string)的值 转为int类型 16进行格式 传递给  pdevhead->key)printf("%d  pdevhead->key = 0x%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;}else if (strcmp(value, "INPUT") == 0){pdevhead->gpio_mode = INPUT;}else{printf("gpio_mode error\n");}}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{printf("gpio_status error\n");}}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);}}return 1;
}static int receive_init(void)
{// pdevhead = add_lrled_to_gdevice_list(pdevhead); // 头插法加入 客厅灯// pdevhead = add_bled_to_gdevice_list(pdevhead);  // 加入卧室灯// pdevhead = add_fan_to_gdevice_list(pdevhead);   // 加入风扇// pdevhead = add_beep_to_gdevice_list(pdevhead);  // 蜂鸣器// pdevhead = add_lock_to_gdevice_list(pdevhead);  // 开锁if (ini_parse("/etc/gdevice.ini", handler_gdevice, NULL) < 0) {printf("Can't load 'gdevice.ini'\n");return 1;}struct gdevice *pdev = NULL;pdev = pdevhead;while (pdev != NULL){// printf("inside %d",__LINE__);printf("dev_name:%s\n", pdev->dev_name);printf("key:%x\n", pdev->key);printf("gpio_pin:%d\n", pdev->gpio_pin);printf("gpio_mode:%d\n", pdev->gpio_mode);printf("gpio_status:%d\n", pdev->gpio_status);printf("check_face_status:%d\n", pdev->check_face_status);printf("voice_set_status:%d\n", pdev->voice_set_status);pdev = pdev->next;}// 设备类链表添加oled_fd = myoled_init(); // 初始化oledface_init();             // 初始化人脸识别return oled_fd;
}static void receive_final(void)
{face_final();if (-1 != oled_fd){close(oled_fd); // 关闭oled 打开的文件oled_fd = -1;   // 复位}
}//  处理设备 --  比如打开灯 和风扇等static void *handler_device(void *arg)
{pthread_detach(pthread_self()); // 和主线程(他的父线程)分离recv_msg_t *recv_msg = NULL;struct gdevice *cur_gdev = NULL;char success_or_failed[20] = "success";pthread_t tid = -1;int smoke_status = 0;double face_result = 0.0; //存放人脸匹配度int ret = -1;if (NULL != arg) // 有参数{recv_msg = (recv_msg_t *)arg; // 获取参数printf("recv_len = %d\n", recv_msg->msg_len);printf("%s|%s|%d, handler: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", __FILE__, __func__, __LINE__,recv_msg->buffer[0], recv_msg->buffer[1], recv_msg->buffer[2], recv_msg->buffer[3], recv_msg->buffer[4], recv_msg->buffer[5]);}// need to do somethingif (NULL != recv_msg && NULL != recv_msg->buffer) // if 消息队列非空,并且buffer 里面接收到数据{// recv_msg->buffer[2] -->  第三位 用于存放设备类型cur_gdev = find_device_by_key(pdevhead, recv_msg->buffer[2]);printf("%s|%s|%d,find success   buffer[2] = 0x%x \n", __FILE__, __func__, __LINE__, recv_msg->buffer[2]);}if (NULL != cur_gdev) // if 能找到的这设备 --> 设备存在{printf("%s|%s|%d, cur_gdev \n", __FILE__, __func__, __LINE__);// BUFFER 的第四个参数  用于 存放开关状态 0 表示开, 1 表示关cur_gdev->gpio_status = recv_msg->buffer[3] == 0 ? LOW : HIGH; // 获取状态存入cur_gdev中//人脸识别if(1 == cur_gdev->check_face_status){face_result = face_status(); //得到人脸识别的匹配度if(face_result > 0.6){ //匹配成功ret = set_gpio_device_status(cur_gdev); // 设置电平 --> 开锁recv_msg->buffer[2] = 0x47;  //识别成功的语音播报}else{recv_msg->buffer[2] = 0x46;}}else if( 0 == cur_gdev->check_face_status){// printf("%s|%s|%d,Set  before set_gpio_device_status\n",__FILE__,__func__,__LINE__);ret = set_gpio_device_status(cur_gdev); // 将获取到的状态真正赋值给引脚// printf("%s|%s|%d, after set_gpio_device_status \n",__FILE__,__func__,__LINE__);}printf("%s|%s|%d, = %d\n", __FILE__, __func__, __LINE__,cur_gdev->voice_set_status);// 需要语言播报if (1 == cur_gdev->voice_set_status) {printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);if (NULL != recv_msg && NULL != recv_msg->ctrl_info && NULL != recv_msg->ctrl_info->ctrl_phead){printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);struct control *pcontrol = recv_msg->ctrl_info->ctrl_phead;while (NULL != pcontrol){if (strstr(pcontrol->control_name, "voice")) //匹配到语言播报{if (0x45 == recv_msg->buffer[2] && 0 == recv_msg->buffer[3]) // 语音播报 打开{smoke_status = 1;}pthread_create(&tid, NULL, pcontrol->set, (void *)recv_msg->buffer); // 新开线程区进行语言播报break;}pcontrol = pcontrol->next;}}}printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);if (-1 == ret) // 设置失败{printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);memset(success_or_failed, '\0', sizeof(success_or_failed));strncpy(success_or_failed, "failed", 6);}printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);// 配置OLEDchar oled_msg[512];memset(oled_msg, 0, sizeof(oled_msg));char *change_status = cur_gdev->gpio_status == LOW ? "Open" : "Close";sprintf(oled_msg, "%s %s %s!\n", change_status, cur_gdev->dev_name, success_or_failed);if(smoke_status == 1){memset(oled_msg, 0, sizeof(oled_msg));sprintf(oled_msg, "A risk of fire!\n");}  myoled_show(oled_msg);//让门打开5s自动关闭if(1 == cur_gdev->check_face_status && 0 == ret && face_result >0.6){sleep(5); //开门5s后关门cur_gdev->gpio_status = HIGH; //设置高电平(低电平有效)ret = set_gpio_device_status(cur_gdev); //关门}}pthread_exit(0);
}static void *receive_get(void *arg) // 接收消息队列里面的 数据
{printf("enter receive_get\n");//  通过参数 初始化我们 定义的recv_msg_t 结构体recv_msg_t *recv_msg = NULL;unsigned char *buffer = NULL;struct mq_attr attr;pthread_t tid = -1;ssize_t read_len = -1;if (NULL != arg){recv_msg = (recv_msg_t *)malloc(sizeof(recv_msg_t));recv_msg->ctrl_info = (ctrl_info_t *)arg; // 这里实际上就获取到了mqd 和 phead(我们需要操作的struct control 链表 的头节点)recv_msg->msg_len = 0;recv_msg->buffer = NULL;}elsepthread_exit(0);if (mq_getattr(recv_msg->ctrl_info->mqd, &attr) == -1){ // 获取消息队列失败 -- 异常pthread_exit(0);}// 能获取到消息队列recv_msg->buffer = (unsigned char *)malloc(attr.mq_msgsize); // 分配内存buffer = (unsigned char *)malloc(attr.mq_msgsize);// mq_msgsize -- 每条消息的大小memset(recv_msg->buffer, 0, attr.mq_msgsize); // 初始化memset(buffer, 0, attr.mq_msgsize);           // 初始化pthread_detach(pthread_self()); // 和主线程(他的父线程)分离while (1){read_len = mq_receive(recv_msg->ctrl_info->mqd, buffer, attr.mq_msgsize, NULL);printf("%s|%s|%d, recv: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", __FILE__, __func__, __LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);printf("%s|%s|%d: read_len = %ld\n", __FILE__, __func__, __LINE__, read_len);if (-1 == read_len){ // 接收失败if (errno == EAGAIN){printf("queue is empty\n");}else{break;}}// 以下是接收到正常数据的情况else if (buffer[0] == 0xAA && buffer[1] == 0x55 && buffer[4] == 0x55 && buffer[5] == 0xAA){recv_msg->msg_len = read_len;memcpy(recv_msg->buffer, buffer, read_len);//  创建线程去 处理我们的接收到的信号pthread_create(&tid, NULL, handler_device, (void *)recv_msg);}}if (NULL != recv_msg)free(recv_msg);if (NULL != buffer)free(buffer);pthread_exit(0);
}struct control receive_control = {.control_name = "receive",.init = receive_init,.final = receive_final,.get = receive_get,.set = NULL, // 不需要实现 设置.next = NULL};struct control *add_receive_to_ctrl_list(struct control *phead)
{// 头插法实现 添加链表节点return add_interface_to_ctrl_list(phead, &receive_control);
};

这样要是我们需要对设备进行维护: 

比如添加某个新的设备只需要去 gdevice.ini 里面去添加即可 -->方便维护

这篇关于智能家居6 -- 配置 ini文件优化设备添加的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/999694

相关文章

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

在Spring中配置Quartz的三种方式

《在Spring中配置Quartz的三种方式》SpringQuartz是一个任务调度框架,它允许我们定期执行特定的任务,在Spring中,我们可以通过多种方式来配置Quartz,包括使用​​@Sche... 目录介绍使用 ​​@Scheduled​​ 注解XML 配置Java 配置1. 创建Quartz配置

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

Kibana的安装和配置全过程

《Kibana的安装和配置全过程》Kibana是一个开源的数据分析和可视化平台,它与Elasticsearch紧密集成,提供了一个直观的Web界面,使您可以快速地搜索、分析和可视化数据,在本文中,我们... 目录Kibana的安装和配置1.安装Java运行环境2.下载Kibana3.解压缩Kibana4.配

tomcat在nginx中的配置方式

《tomcat在nginx中的配置方式》文章介绍了如何在Linux系统上安装和配置Tomcat,并通过Nginx进行代理,首先,下载并解压Tomcat压缩包,然后启动Tomcat并查看日志,接着,配置... 目录一、下载安装tomcat二、启动tomcat三、配置nginx总结提示:文章写完后,目录可以自动

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7