接上一篇
[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 集合(OTA、透传、电量、设备信息、HID)
[单片机框架] [queue] 实现一个简易的消息队列

文章目录

  • 一、 透传服务,加入队列机制
  • 问题1:为什么会使用消息队列?
  • 问题2:消息队列的优缺点?
  • 问题3:如何增强消息队列使用的稳定性?
  • 二、示例程序

一、 透传服务,加入队列机制

问题1:为什么会使用消息队列?

  1. 由于业务划分有用户层,中间层和系统层。要保证用户层的多个用户对中间层的不同模块之间的访问,以及多个中间层的模块要访问系统层的不同模块,选择client-server模型来满足设计需求。
  2. 要完成client-server之间的通信有多种途径,选择消息队列一方面是为了将系统的耦合性降低,
  3. 另一方面是为了保持模块异步运行,减少阻塞。

问题2:消息队列的优缺点?

  1. 消息队列出问题将会引起整个系统紊乱,因为在client-server模型中通信都是采用的消息队列,所以要是消息队列出问题就会引起整个系统的紊乱。

  2. 消息有可能会丢失,重复使用等问题

问题3:如何增强消息队列使用的稳定性?

  1. 为了防止消息重复使用,一方面不同client有各自的标志,防止特定的消息被其它模块使用;
  2. 另一方面消息在接收完成之后将会被删除。对消息队列的消息长度要多适当调整,避免有些消息过长而被丢弃。
  3. 至于消息队列本身的问题,需要从系统层面去多分析和优化。

二、示例程序

/********************************************************************************
* @file    biz_ble_nus.c
* @author  jianqiang.xue
* @Version V1.0.0
* @Date    2022-03-16
* @brief   [业务] ble数据透传服务(从机)https://blog.csdn.net/weixin_41572450/article/details/84036968
********************************************************************************/
/* Private Includes ----------------------------------------------------------*/
#include "queue.h"#include "business_function.h"
#include "log.h"
#include "biz_ble_cfg.h"
#include "biz_ble.h"
#include "biz_ble_nus.h"
/* Private Define ------------------------------------------------------------*/
/* External Variables --------------------------------------------------------*/
/* Private Macro -------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
#if BLE_NUS_ENABLED
ble_nus_t m_nus; /**< Structure to identify the Nordic UART Service. */
typedef void(*ble_rx_event_callback)(uint8_t *data, uint16_t len);
static ble_rx_event_callback g_rx_dispose_callback;/***************消息队列定义**************/// 用于BLE数据发送消息队列总缓存区
static uint8_t m_ble_q_buff[BLE_BUFF_Q_ITEM_CNT * BLE_BUFF_Q_ITEM_SIZE] = {0};
queue_t m_ble_buff_q =
{.pbuff     = m_ble_q_buff,.front     = 0,.rear      = 0,.item_cnt  = BLE_BUFF_Q_ITEM_CNT,.item_size = BLE_BUFF_Q_ITEM_SIZE
};
uint8_t g_ble_single_buff_data[BLE_BUFF_Q_ITEM_SIZE]    = {0}; // 用于单个BLE数据临时缓存区// 如果发送失败,则组合上次数据一并发送。最大程度利用带宽,使数据正常发送。
uint8_t ble_send_buff[BLE_BUFF_SEND_MAX_SIZE] = {0};  // 用于组合多个BLE数据// 记录当前发送长度
uint16_t ble_send_len = 0;
#endif
/* Private Function Prototypes -----------------------------------------------*/
#if BLE_NUS_ENABLED
/*** @brief  [透传数据服务][接收事件] 接收数据事件  [处理通过BLE接收的数据]* @param  p_nus: 透传服务结构体,包含一些回调函数。(本接收事件,没有使用)* @param  p_data: 数据包指针头* @param  length: 数据长度*/
static void nus_data_handler(ble_nus_t * p_nus, uint8_t *p_data, uint16_t length)
{LOG_D("<DEBUG> RX:%02x %02x %02x %02x %02x|%d\r\n", p_data[0], p_data[1], p_data[2], p_data[3], p_data[4], length);// 将数据传给外部[业务层]处理if (g_rx_dispose_callback){g_rx_dispose_callback(p_data, length);}
}
#endif/* Public Function Prototypes ------------------------------------------------*/
#if BLE_NUS_ENABLEDvoid biz_ble_nus_init(void)
{uint32_t err_code;/**** NUS 串口透传服务 ****/ble_nus_init_t nus_init;memset(&nus_init, 0, sizeof(nus_init));nus_init.data_handler = nus_data_handler;err_code = ble_nus_init(&m_nus, &nus_init);LOG_D("<DEBUG> NUS INIT:%x\r\n", err_code);APP_ERROR_CHECK(err_code);queue_init(&m_ble_buff_q, m_ble_q_buff, BLE_BUFF_Q_ITEM_CNT, BLE_BUFF_Q_ITEM_SIZE);memset(m_ble_q_buff, 0, BLE_BUFF_Q_ITEM_CNT * BLE_BUFF_Q_ITEM_SIZE);memset(g_ble_single_buff_data, 0, BLE_BUFF_Q_ITEM_SIZE);
}/*** @brief  [串口透传服务] 注册接收回调* @param  *event: 格式 -- func(uint8_t *data, uint16_t len);* @retval false--失败  true--成功*/
bool biz_ble_nus_rx_reg_callback(void *event)
{if (g_rx_dispose_callback != NULL){return false;}else{g_rx_dispose_callback = (ble_rx_event_callback)event;}return true;
}/*** @brief  [数据透传] 将队列数据依次发送 (本函数建议放在空闲函数使用)* @retval 0--成功 1--失败*/
bool ble_data_send_dispose(void)
{static bool old_send_fail = false;static uint8_t msg_mem_num = 0;if (!old_send_fail){msg_mem_num = queue_get_space(&m_ble_buff_q);if (msg_mem_num != 0){ble_send_len = 0;// 将队列数据,取出进行组合。msg_mem_num = msg_mem_num > (BLE_NUS_MAX_DATA_LEN / BLE_BUFF_Q_ITEM_SIZE) ? (BLE_NUS_MAX_DATA_LEN / BLE_BUFF_Q_ITEM_SIZE) : msg_mem_num;for (uint8_t i = 0; i < msg_mem_num; i++){if (!queue_de(&m_ble_buff_q, g_ble_single_buff_data)){break;}memcpy(ble_send_buff + ble_send_len, g_ble_single_buff_data, m_ble_buff_q.item_size);ble_send_len += m_ble_buff_q.item_size;}}}if (ble_send_len > 0){if (get_ble_conn_state()){ret_code_t ble_send_err_code;
#if NRF51ble_send_err_code = ble_nus_string_send(&m_nus, ble_send_buff, ble_send_len);
#elif NRF52ble_send_err_code = ble_nus_data_send(&m_nus, ble_send_buff, &ble_send_len, m_conn_handle);
#endifif (ble_send_err_code == NRF_SUCCESS){old_send_fail = false;ble_send_len = 0;}else{old_send_fail = true;}return true;}else{// 蓝牙断开,则清除所有队列数据queue_init(&m_ble_buff_q, m_ble_q_buff, BLE_BUFF_Q_ITEM_CNT, BLE_BUFF_Q_ITEM_SIZE);old_send_fail = false;ble_send_len = 0;return false;}}else{return false;}}/*** @brief  [数据透传] 发送数据 (非实时,数据入队列)* @param  *data: 数据头指针* @param  len: 数据长度* @retval 0--成功 1--失败*/
bool biz_ble_data_send(uint8_t *data, uint8_t len)
{if (get_ble_conn_state()){if (len > BLE_NUS_MAX_DATA_LEN){LOG_E("<ERR> [biz_ble_data_send] Len > 20 , Fail\r\n");}if (queue_is_null(&m_ble_buff_q)){ret_code_t ble_send_err_code;
#if NRF51ble_send_err_code = ble_nus_string_send(&m_nus, data, len);
#elif NRF52ble_send_err_code = ble_nus_data_send(&m_nus, data, &len, m_conn_handle);
#endifif (ble_send_err_code == NRF_SUCCESS){return true;}}if (m_conn_handle == BLE_CONN_HANDLE_INVALID){return false;}if (!queue_en(&m_ble_buff_q, data, len)){LOG_D("<DEBUG> [biz_ble_data_send] queue_en fail\r\n");return false;}}return true;
}
#else
void biz_ble_nus_init(void)
{}
bool biz_ble_nus_rx_reg_callback(void *event)
{return false;
}
bool ble_data_send_dispose(void)
{return false;
}
bool biz_ble_data_send(uint8_t *data, uint8_t len)
{return false;
}
#endif
/********************************************************************************
* @file    biz_ble_nus.h
* @author  jianqiang.xue
* @Version V1.0.0
* @Date    2022-03-16
* @brief   [业务] ble数据透传服务(从机)
********************************************************************************/
#ifndef __BIZ_BLE_NUS_H
#define __BIZ_BLE_NUS_H/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>#include "biz_ble_cfg.h"
#include "ble_nus.h"
/* Define --------------------------------------------------------------------*/
/* External Variables --------------------------------------------------------*/
#if BLE_NUS_ENABLED
extern ble_nus_t m_nus;
#endif
/* Public Function Prototypes ------------------------------------------------*/
void biz_ble_nus_init(void);bool biz_ble_data_send(uint8_t *data, uint8_t len);
bool ble_data_send_dispose(void);bool biz_ble_nus_rx_reg_callback(void *event);
#endif

[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 NUS 透传数据队列发送,提升带宽利用率相关推荐

  1. [嵌入式框架][nrf51822][SDK12.3] BLE分层设计 DFU OTA 透传(NUS) 电量 设备信息 BLE_HID

    一. 目录结构如下 将每个功能抽离处理,使文件起步代码显得干净清晰.官方提供的文件,行数1000+起步. 二. BLE服务创建和事件管理 简化后只有700+,仅保留协议栈事件处理,白名单,对等管理器, ...

  2. BLE 协议栈之 主机透传

      主机发送信息使用的是:bStatus_t GATT_WriteCharValue( uint16 connHandle, attWriteReq_t *pReq, uint8 taskId ); ...

  3. 数据仓库架构分层设计

    数据仓库架构分层设计包括STG(数据缓冲层).ODS(数据操作层).DWD(数据明细层).DWS(主题汇总层)和ADM(数据应用层). 1.STG层 主要完成业务系统结构化数据引入到数据中台,保留业务 ...

  4. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED驱动框架--面向对象、分层设计思想

    文章目录 前言 1.LED驱动程序框架 1.1.对于LED驱动,我们想要什么样的接口? 1.2.LED驱动要怎么写,才能支持多个板子?分层写 1.3.程序分析 驱动程序 应用程序 Makefile 1 ...

  5. 嵌入式软件架构设计之分层设计

    在实际的项目开发中,项目往往是并行开发的,也就是说硬件设计,底层软件设计,应用软件设计是同步进行的.比如说在开发板上调试模块驱动,在其他平台上调试应用再移植到目前这个平台等.这里又涉及到如何提高嵌入式 ...

  6. RSF 分布式 RPC 服务框架的分层设计

    RSF 是个什么东西? 一个高可用.高性能.轻量级的分布式服务框架.支持容灾.负载均衡.集群.一个典型的应用场景是,将同一个服务部署在多个Server上提供 request.response 消息通知 ...

  7. 一种基于分层设计的小家电控制板通用程序框架

    本文设计了一种基于分层设计的小家电控制板通用程序框架.分层设计有以下优点: (1)降低系统复杂度.由于每层都是相对独立的,每层可以单独实现. (2)隔离变化.通过分层设计,可以把变化的部分独立出来,让 ...

  8. 我对软件分层设计的思考

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 在日常开发中,经 ...

  9. 源码解读Dubbo分层设计思想

    I作者:vivo互联网服务器团队-Wang Genfu 一.Dubbo分层整体设计概述 我们先从下图开始简单介绍Dubbo分层设计概念: (引用自Duboo开发指南-框架设计文档) 如图描述Dubbo ...

最新文章

  1. php 偷偷转移别人权重,判断百度蜘蛛偷偷进行301转移权重 给新站提权
  2. php把字符串转为utf-8
  3. java简单纸牌游戏_2020年最佳2人棋盘游戏:拼凑,Kingdomino等
  4. 清除浏览器缓存之后为什么还是显示旧的html页面_Web缓存控制策略详解
  5. 最长公共子序列及其引申问题
  6. Java程序设计语言基础05:Java的类和对象
  7. PKU 3273  PKU 3258  pku 1905 PKU 3122 二分运用题目
  8. JDK11竟然不支持字体斜体
  9. C语言贴图图片路径不对,backgroundImage 路径问题 vue 图片的引入方式
  10. 量子计算机慕课,计算机组成原理-中国大学mooc-题库零氪
  11. hbase官方文档中文版0.97
  12. java 罗马数字_罗马数字 | 学步园
  13. 呼和浩特php平均工资,2019年内蒙古平均工资出炉
  14. LOVE2D中实现一个简单的摇杆
  15. 公众号如何向用户发送重要的服务通知?
  16. linux网络编程tcp和udp基本函数调用过程及如何选择
  17. 主板没有rgb接口怎么接灯_想拥有RGB灯效,不懂这些怎么行!
  18. Oracle网址大全
  19. PyQT6的从零开始(三):在pyqt桌面程序简单内置网页浏览器
  20. p20华为云电脑白屏_华为云电脑让P20如虎添翼,连接键鼠秒变办公利器

热门文章

  1. 问题“ConnectionString属性尚未初始化”之解决办法
  2. 51单片机(8051系列)最小系统图--内部时钟
  3. 美国次级抵押贷款市场的来龙去脉(转)
  4. chrome浏览器F12调试模式network不显示接口请求地址解决办法
  5. python下载文件并改名_用 Python 给下载的 B 站视频文件批量改名
  6. 软件运行的好好的,突然黑屏啥也进不去了
  7. 怎么取名都不队-DevOps
  8. RT-Thread 软件包制作及发布流程
  9. Oracle卸载不干净?看这篇就够了
  10. 计算机进入睡眠状态网络还通么,电脑休眠模式怎么正常连接网络