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

news2024/10/7 16:24:51

不知道什么是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(); // 初始化oled
  face_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 something
  if (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__);
  // 配置OLED
  char 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;
  }
  else
    pthread_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 里面去添加即可 -->方便维护

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

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

相关文章

CDH6.3.2集成Flink1.17

直接运行脚本即可&#xff0c;一键输出相关依赖包 运行步骤已给到文档 下载地址

更新评估班级、确定评价学生

场景&#xff1a; 义务阶段为何要进行分层分班&#xff0c;这一点大家都心知肚明。你说的答案是不是也和我的一样&#xff1a;为了实行分层教学。"人往高处走&#xff0c;水往低处流"&#xff0c;每次确定分班后&#xff0c;总会有一些学生向上调整&#xff0c;当然也…

python2.x版本安装、安装pip

文章目录 一、安装python二、安装pip2.1、pip简介2.2、pip安装2.3、no such option: -e2.4、pip卸载2.5、pip扩展 本文讲解在windows系统装安装python2.7.13版本 一、安装python 1.下载安装包&#xff0c;官网链接地址&#xff1a;https://www.python.org/downloads/ 直接在…

Pytorch深度学习实践笔记4

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;pytorch深度学习 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 视频来自【b站刘二大人】 1 反向传播 Back propaga…

机器视觉HALCON:2.HALCON的预备环境和数据结构

目录 下载基础语法HALCON的数据结构图像和数据类型区域的存储区域的存储连通区域 亚像素轮廓&#xff08;XLD&#xff09;亚像素轮廓介绍亚像素轮廓数据结构 数组数组的赋值与创建数组的存储与读取 字典字典介绍字典的创建和操作 句柄 下载 HALCON的官方网站 下载时需要注册登…

react antd中transfer穿梭框组件中清除搜索框内容

如图&#xff1a;需要清除search搜索框内容 antd的transfer穿梭框组件未提供入口修改input框的值。 2种方法修改。 1、直接操作dom元素设置值&#xff08;不推荐&#xff09; useEffect(() > {const searchInput document.querySelector(.ant-transfer-list-search input)…

Redis常用命令——String篇

前面我们讲解了一些 Redis 的全局命令&#xff08;Redis常用基本全局命令&#xff09;。所谓全局命令&#xff0c;就是可以匹配任意一个数据结构进行使用。但是不同的数据结构&#xff0c;也有自己的操作命令。本篇文章主要讲解的是 String 的操作命令&#xff0c;希望会对你有…

2024电工杯B题:大学生平衡膳食食谱的优化设计及评价

大学时代是学知识长身体的重要阶段&#xff0c;同时也是良好饮食习惯形成的重要时期。这一特 定年龄段的年轻人&#xff0c;不仅身体发育需要有充足的能量和各种营养素&#xff0c;而且繁重的脑力劳动和 较大量的体育锻炼也需要消耗大量的能源物质。大学生中饮食结构不合理以及…

在抖音怎么开店?抖音小店开店步骤详解!建议收藏!

大家好&#xff0c;我是电商小V 想在抖音上面开一家属于自己的抖音店铺去卖点商品赚取个商品的差价&#xff0c;那么开通抖音小店的步骤是什么呢&#xff1f;主要分为几步呢&#xff1f;关于这个问题咱们就来详细的说一下&#xff1a; 开店之前的准备工作&#xff0c;首先需要准…

核心四:线程的一生

4、核心四&#xff1a;线程的一生&#x1f49f; 4.1 New 已创建但还未启动的新线程。 我们new Thread之后&#xff0c;线程已经实现了一些准备工作。但没有运行run方法&#xff0c;因为没有使用start来开启线程。此时&#xff0c;线程处于New状态。 4.2 Runnable&#xff08…

Python模块、包和异常处理

大家好&#xff0c;在当今软件开发领域&#xff0c;Python作为一种简洁、易读且功能强大的编程语言&#xff0c;被广泛应用于各种领域。作为一名测试开发工程师&#xff0c;熟练掌握Python的模块、包和异常处理是提高代码可维护性和错误处理能力的关键。本文将和大家一起探讨Py…

Linux —— 信号量

Linux —— 信号量 什么是信号量P操作&#xff08;Wait操作&#xff09;V操作&#xff08;Signal操作&#xff09;信号量的类型 一些接口POSIX 信号量接口&#xff1a;其他相关命令&#xff1a; 基于循环队列的生产者和消费者模型同步关系 多生产多消费 我们今天接着来学习信号…

5.22R语言初步学习-1

今天上课讲R语言&#xff0c;要干什么没讲&#xff0c;分析什么&#xff0c;目的是什么没讲。助教基本上就是让我们打开窗口&#xff0c;按要求抄代码指令&#xff0c;代码原理也没讲......再加上最近正好在学概率论与数理统计&#xff0c;肯定是有用的&#xff0c;所以还是学习…

(全面)Nginx格式化插件,Nginx生产工具,Nginx常用命令

目录 &#x1f3ab; 前言 &#x1f389; 开篇福利 &#x1f381; 开篇福利 x2 Double happiness # 介绍 # 地址 # 下载 &#x1f4bb; 命令及解析 # 整个文件系统中搜索名为nginx.conf的文件 # 编辑nginx.conf文件 # 重新加载配置文件 # 快速查找nginx.conf文件并使…

HTTP协议请求报头(header)

目录 目录 User-Agent与Referer User-Agent Referer Cookie HTTP报头&#xff08;header&#xff09;的结构是“键值对”结构&#xff0c;每个键值对占一行&#xff0c;键和值之间使用分号分隔。 报头的种类有很多&#xff0c;本次介绍几个重要的。 Host&#xff1a;表示请…

中电金信:从系统升级入手 看这些银行如何激活信贷业务

近期&#xff0c;我国金融机构围绕科技金融、绿色金融、普惠金融、养老金融、数字金融五篇大文章&#xff0c;持续优化信贷结构&#xff0c;不断增强金融服务实体经济作用。金融业认真落实国家经济发展目标&#xff0c;不断优化资金投向结构&#xff0c;持续加大重大战略、重点…

robosuite导入自定义机器人

目录 目的&#xff1a;案例一&#xff1a;成果展示具体步骤&#xff1a;URDF文件准备xml文件生成xml修改机器人构建 目的&#xff1a; 实现其他标准/非标准机器人的构建 案例一&#xff1a; 成果展示 添加机器人JAKA ZU 7 这个模型 具体步骤&#xff1a; URDF文件准备 从…

解决小皮面版搭建php网站数据库连接不了

首先进入mysql bin目录下 并执行cmd mysql -u root -pCREATE USER userlocalhost IDENTIFIED BY pass;GRANT ALL PRIVILEGES ON *.* TO userlocalhost;GRANT SELECT, INSERT, UPDATE ON database_name.* TO xxwlocalhost;FLUSH PRIVILEGES;select host ,user from mysql.user…

数据防泄漏系统哪个好用,给文件加密的软件

数据防泄露&#xff08;Data Leakage Prevention&#xff0c;DLP&#xff09;是指通过一定的技术手段&#xff0c;防止组织指定&#xff08;重要或敏感的&#xff09;数据或信息资产以违反安全策略规定的形式流出组织的一种策略。 信息防泄露以文档加密技术为核心&#xff0c;…