当前位置:   article > 正文

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

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

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

废话少说,放码过来

增添/修改代码

receive_interface.c

  1. #include <pthread.h>
  2. #include <mqueue.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "receive_interface.h"
  8. #include "control.h"
  9. #include "mq_queue.h"
  10. #include "global.h"
  11. #include "face.h"
  12. #include "myoled.h"
  13. /*
  14. 接收模块:
  15. 对接收到消息做出相应处理
  16. 包括 oled 人脸识别 语言播报 GPIO 引脚状态配置
  17. */
  18. static int oled_fd = -1;
  19. typedef struct
  20. {
  21. int msg_len;
  22. unsigned char*buffer;
  23. ctrl_info_t *ctrl_info;
  24. }recv_msg_t;
  25. static int receive_init(void)
  26. {
  27. // 设备类链表添加
  28. oled_fd = myoled_init(); // 初始化oled
  29. face_init(); // 初始化人脸识别
  30. return 0;
  31. }
  32. static void receive_final(void)
  33. {
  34. face_final();
  35. if(-1 != oled_fd)
  36. {
  37. close(oled_fd); // 关闭oled 打开的文件
  38. oled_fd = -1; //复位
  39. }
  40. }
  41. // 处理设备 -- 比如打开灯 和风扇等
  42. static void*handler_device(void *arg)
  43. {
  44. pthread_detach(pthread_self()); // 和主线程(他的父线程)分离
  45. recv_msg_t *recv_msg = NULL;
  46. if(NULL != arg)
  47. {
  48. recv_msg = (recv_msg_t *)arg;
  49. printf("recv_len = %d\n",recv_msg->msg_len);
  50. printf("%s|%s|%d, handler: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,
  51. recv_msg->buffer[0],recv_msg->buffer[1],recv_msg->buffer[2],recv_msg->buffer[3],recv_msg->buffer[4],recv_msg->buffer[5]);
  52. }
  53. // need to do something
  54. pthread_exit(0);
  55. }
  56. static void* receive_get(void *arg) // 接收消息队列里面的 数据
  57. {
  58. printf("enter receive_get\n");
  59. // 通过参数 初始化我们 定义的recv_msg_t 结构体
  60. recv_msg_t *recv_msg = NULL;
  61. unsigned char*buffer = NULL;
  62. struct mq_attr attr;
  63. pthread_t tid = -1;
  64. ssize_t read_len = -1;
  65. if(NULL != arg)
  66. {
  67. recv_msg = (recv_msg_t *)malloc(sizeof(recv_msg_t));
  68. recv_msg->ctrl_info = (ctrl_info_t *)arg;// 这里实际上就获取到了mqd 和 phead(我们需要操作的struct control 链表 的头节点)
  69. recv_msg->msg_len = 0;
  70. recv_msg->buffer = NULL;
  71. }
  72. else
  73. pthread_exit(0);
  74. if(mq_getattr(recv_msg->ctrl_info->mqd,&attr) == -1)
  75. { // 获取消息队列失败 -- 异常
  76. pthread_exit(0);
  77. }
  78. // 能获取到消息队列
  79. recv_msg->buffer = (unsigned char *)malloc(attr.mq_msgsize); // 分配内存
  80. buffer = (unsigned char *)malloc(attr.mq_msgsize);
  81. // mq_msgsize -- 每条消息的大小
  82. memset(recv_msg->buffer,0,attr.mq_msgsize); // 初始化
  83. memset(buffer,0,attr.mq_msgsize); // 初始化
  84. pthread_detach(pthread_self()); // 和主线程(他的父线程)分离
  85. while (1)
  86. {
  87. read_len = mq_receive(recv_msg->ctrl_info->mqd,buffer,attr.mq_msgsize,NULL) ;
  88. 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]);
  89. printf("%s|%s|%d: read_len = %ld\n",__FILE__,__func__,__LINE__,read_len);
  90. if(-1 == read_len)
  91. {// 接收失败
  92. if(errno == EAGAIN)
  93. {
  94. printf("queue is empty\n");
  95. }
  96. else
  97. {
  98. break;
  99. }
  100. }
  101. // 以下是接收到正常数据的情况
  102. else if(buffer[0] == 0xAA && buffer[1] == 0x55
  103. &&buffer[4]==0x55 && buffer[5]==0xAA)
  104. {
  105. recv_msg->msg_len = read_len;
  106. memcpy(recv_msg->buffer,buffer,read_len);
  107. // 创建线程去 处理我们的接收到的信号
  108. pthread_create(&tid,NULL,handler_device,(void*)recv_msg);
  109. }
  110. }
  111. if(NULL != recv_msg)
  112. free(recv_msg);
  113. if(NULL != buffer)
  114. free(buffer);
  115. pthread_exit(0);
  116. }
  117. struct control receive_control ={
  118. .control_name = "receive",
  119. .init = receive_init,
  120. .final = receive_final,
  121. .get = receive_get,
  122. .set = NULL, //不需要实现 设置
  123. .next = NULL
  124. };
  125. struct control *add_receive_to_ctrl_list(struct control *phead)
  126. {
  127. //头插法实现 添加链表节点
  128. return add_interface_to_ctrl_list(phead,&receive_control);
  129. };



receive_interface.h

  1. #ifndef ___RECEIVE_INTERFACE_H___
  2. #define ___RECEIVE_INTERFACE_H___
  3. #include "control.h"
  4. struct control *add_receive_to_ctrl_list(struct control *phead);
  5. #endif

修改的main.c

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <stdlib.h>
  4. #include <wiringPi.h>
  5. #include "control.h"
  6. #include "mq_queue.h"
  7. #include "voice_interface.h"
  8. #include "socket_interface.h"
  9. #include "smoke_interface.h"
  10. #include "receive_interface.h"
  11. #include "global.h"
  12. // msg_queue_create
  13. int main() {
  14. pthread_t thread_id;
  15. struct control *control_phead = NULL;
  16. struct control *pointer = NULL;
  17. ctrl_info_t *ctrl_info = NULL;
  18. ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));
  19. ctrl_info->ctrl_phead = NULL;
  20. ctrl_info->mqd = -1;
  21. int node_num = 0; // 统计节点数
  22. if(-1 == wiringPiSetup())// 初始化 wiringPi 库
  23. {
  24. perror("wiringPi Init");
  25. return -1;
  26. }
  27. // 创建消息队列
  28. ctrl_info->mqd = msg_queue_create();
  29. if(-1 == ctrl_info->mqd)// 创建消息队列失败
  30. {
  31. printf("%s|%s|%d, mqd= %d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);
  32. return -1;
  33. }
  34. // 头插法插入 , so 头一直在变化
  35. ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
  36. ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);
  37. ctrl_info->ctrl_phead = add_smoke_to_ctrl_list(ctrl_info->ctrl_phead);
  38. ctrl_info->ctrl_phead = add_receive_to_ctrl_list(ctrl_info->ctrl_phead);
  39. pointer = ctrl_info->ctrl_phead;
  40. while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数
  41. {
  42. if(NULL != pointer->init)
  43. {
  44. printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
  45. pointer->init();
  46. }
  47. pointer = pointer->next;
  48. node_num++; // 统计节点数
  49. }
  50. // 根据节点的总数 --> 创建对应数目的线程
  51. pthread_t *tid = (pthread_t *)malloc(sizeof(int) *node_num);
  52. pointer = ctrl_info->ctrl_phead;
  53. for(int i=0;i<node_num;++i)//遍历所有节点
  54. {
  55. if(NULL != pointer->get){
  56. printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
  57. pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API
  58. }
  59. pointer = pointer->next;
  60. }
  61. for(int i=0;i<node_num;++i)
  62. {
  63. pthread_join(tid[i],NULL);
  64. }
  65. for(int i=0;i<node_num;++i)
  66. {
  67. if(NULL != pointer->final)
  68. pointer->final(); // 接打开的使用接口关闭
  69. pointer = pointer->next;
  70. }
  71. msq_queue_final(ctrl_info->mqd);
  72. if(NULL != ctrl_info)
  73. free(ctrl_info); // 这个是malloc 堆区申请的内存 --> 需要手动的释放
  74. if(NULL != tid)
  75. free(tid);
  76. return 0;
  77. }

编译执行:

编译:

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 函数已经接收到对的数据了,剩下的就是对这些数据的处理了,我们将在下一篇实现,让代码和关联设备们起来,进一步完善我们的功能。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/567949
推荐阅读
相关标签
  

闽ICP备14008679号