智能家居4 -- 添加接收消息的初步处理

这一模块的思路和前面的语言控制模块很相似,差别只是调用TCP 去控制

废话少说,放码过来

增添/修改代码

receive_interface.c

cpp 复制代码
#include <pthread.h>
#include <mqueue.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#include "receive_interface.h"
#include "control.h"
#include "mq_queue.h"
#include "global.h"
#include "face.h"
#include "myoled.h"

/*
接收模块:
对接收到消息做出相应处理
包括 oled 人脸识别 语言播报 GPIO  引脚状态配置

*/

static int oled_fd = -1;

typedef struct  
{
 int msg_len;
 unsigned char*buffer;
 ctrl_info_t *ctrl_info;
}recv_msg_t;



static int  receive_init(void)
{ 
  // 设备类链表添加
  oled_fd = myoled_init(); // 初始化oled
  face_init(); // 初始化人脸识别


    return 0;
}

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;
 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 
 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);

};

receive_interface.h

cpp 复制代码
#ifndef ___RECEIVE_INTERFACE_H___
#define ___RECEIVE_INTERFACE_H___

#include "control.h"
struct control *add_receive_to_ctrl_list(struct control *phead);



#endif

修改的main.c

cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <wiringPi.h>

#include "control.h"
#include "mq_queue.h"
#include "voice_interface.h"
#include "socket_interface.h"
#include "smoke_interface.h"
#include "receive_interface.h"
#include "global.h"

// msg_queue_create



int main() {
    pthread_t thread_id;
    struct control *control_phead = NULL;
    struct control *pointer = NULL;
    ctrl_info_t *ctrl_info = NULL;
    ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));
    ctrl_info->ctrl_phead = NULL;
    ctrl_info->mqd = -1;

    int node_num = 0; // 统计节点数
    if(-1 == wiringPiSetup())// 初始化 wiringPi 库
    {
        perror("wiringPi Init");
        return -1;
    }

    // 创建消息队列
    ctrl_info->mqd = msg_queue_create();
    if(-1 == ctrl_info->mqd)// 创建消息队列失败
    {
        printf("%s|%s|%d, mqd= %d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);
        return -1;
    }
    
    //  头插法插入 , so 头一直在变化
    ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_smoke_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_receive_to_ctrl_list(ctrl_info->ctrl_phead);
  
  

    pointer = ctrl_info->ctrl_phead;

    while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数
    {
        if(NULL != pointer->init)
        {
             printf("%s|%s|%d   control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
             pointer->init();
        }
        pointer = pointer->next;
        node_num++; // 统计节点数
    }

    // 根据节点的总数 --> 创建对应数目的线程
    pthread_t *tid = (pthread_t *)malloc(sizeof(int) *node_num);
    pointer = ctrl_info->ctrl_phead;

    for(int i=0;i<node_num;++i)//遍历所有节点
    {
       if(NULL != pointer->get){
          printf("%s|%s|%d   control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
          pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API
       }
        pointer = pointer->next;
    }
    
     for(int i=0;i<node_num;++i)
     {
     pthread_join(tid[i],NULL);
     }

     for(int i=0;i<node_num;++i)
     {
      if(NULL != pointer->final)
          pointer->final(); // 接打开的使用接口关闭
      pointer = pointer->next;
     }
     
     msq_queue_final(ctrl_info->mqd);

     if(NULL != ctrl_info)
          free(ctrl_info); // 这个是malloc 堆区申请的内存 -->  需要手动的释放

     if(NULL != tid)
          free(tid);


     return 0;
}

编译执行:

编译:

make

发送到arm-64平台

scp ./obj/smarthome orangepi@192.168.1.11:/home/orangepi

// 需要用到阿里云人脸识别接口,需要调用 py文件,一起传过去

scp src/face.py orangepi@192.168.1.11:/home/orangepi

执行:

sudo -E ./smarthome

可以看到我们的 hanler 函数已经接收到对的数据了,剩下的就是对这些数据的处理了,我们将在下一篇实现,让代码和关联设备们起来,进一步完善我们的功能。

相关推荐
码农小钻风12 分钟前
利用Samba实现局域网跨平台共享文件
linux·samba·共享
LN花开富贵32 分钟前
【ROS】鱼香ROS2学习笔记二
linux·笔记·python·学习·嵌入式
GS8FG1 小时前
Busybox生成根文件系统,并移植e2fsprogs:RK3568
linux·驱动开发
Aaron15882 小时前
RFSOC+VU13P+RK3588的核心优势与应用场景分析
嵌入式硬件·算法·matlab·fpga开发·信息与通信·信号处理·基带工程
blevoice2 小时前
JL杰理AC696N开发板常见问题FAQ-问题6:为什么提示“key 不匹配”?杰理的蓝牙芯片的key是什么?以及该如何添加key? 杰理key文件原理?
单片机·嵌入式硬件·物联网·jl杰理蓝牙音频芯片·ac696n·蓝牙音箱方案开发
Cyber4K3 小时前
【Nginx专项】基础入门篇:状态页、微更新、内容替换、读取、压缩及防盗链
linux·运维·服务器·nginx·github
编程之升级打怪3 小时前
常见电路的引脚代号
嵌入式硬件
shining4 小时前
当拿到一个新服务器时所需准备工作
linux·程序员
门思科技4 小时前
LoRaWAN项目无需NS和平台?一体化网关如何简化部署与成本
服务器·网络·物联网
Bruce_Liuxiaowei4 小时前
顺藤摸瓜:一次从防火墙告警到设备实物的溯源实战
运维·网络·网络协议·安全