【AVRCP】Notification PDUs 深入解析与应用

news2025/3/18 9:58:43

目录

一、Notification PDUs 概述

二、GetPlayStatus:同步查询播放状态

2.1 命令功能与应用场景

2.2 请求格式(CT → TG)

2.3 响应格式(TG → CT)

2.4 注意事项

2.5 协议实现示例(伪代码)

三、RegisterNotification:异步事件订阅

3.1 命令概述

3.2 命令格式

3.3 响应格式

①EVENT_PLAYBACK_STATUS_CHANGED(通知播放状态的改变)

②EVENT_TRACK_CHANGED(通知媒体轨道的改变)

③EVENT_TRACK_REACHED_END / START

④EVENT_PLAYBACK_POS_CHANGED(通知播放位置的改变)

⑤EVENT_BATT_STATUS_CHANGED

⑦EVENT_SYSTEM_STATUS_CHANGED

3.4 协议实现的 5 大陷阱

四、GetPlayStatus和RegisterNotification的协同策略

五、总结


AVRCP(音频/视频远程控制协议)中的 Notification PDUs(通知 PDU) 是实现设备间状态同步的核心机制,允许控制器(Controller, CT)主动获取或订阅目标设备(Target, TG)的实时状态变化,无论是同步还是异步更新。本文将深入解析其工作原理、关键命令及实际应用场景。

一、Notification PDUs 概述

  • 作用:通知 PDU(Protocol Data Unit)用于在目标设备(TG)状态改变时,为控制设备(CT)提供同步和异步更新。

  • 应用场景:当控制终端(CT,Control Terminal)想知道媒体轨道的当前状态或其变化情况,以便在控制器显示屏上显示新的媒体信息。CT 可以选择查询播放状态,或者向 TG 注册以接收播放状态通知。当 CT 注册了特定状态变化的通知后,TG 在状态改变时会发送通知 PDU。

  • 实现方式:通知 PDU 分为两种类型:

    • 同步查询:CT 主动向 TG 请求当前状态。

    • 异步订阅:CT 注册特定事件,TG 在状态变化时自动推送通知。

这种机制适用于媒体播放状态更新(如播放/暂停)、电池状态变化等场景,确保 CT 界面信息与 TG 实际状态一致。

二、GetPlayStatus:同步查询播放状态

2.1 命令功能与应用场景

作用:CT 通过此命令实时获取 TG 的播放状态、曲目时长和播放进度典型场景

  • 用户手动点击播放器界面的“刷新”按钮

  • 界面初始化时加载当前播放信息

  • 处理用户操作(如暂停/播放)后验证状态

2.2 请求格式(CT → TG)

  • 无参数:命令本身不携带任何附加数据

  • 传输效率:命令包仅需 3 字节(包括 AVRCP 头部)

HCI LOG:

2.3 响应格式(TG → CT)

响应参数详解:

①曲目时长(SongLength)

字段 值范围 特殊值 处理逻辑
SongLength 0x00000000 ~ 0xFFFFFFFF 0xFFFFFFFF 显示"未知时长",禁用进度条拖拽功能

示例

  • 0x000EA600 → 转换为十进制 60,000 毫秒(1分钟)

  • 0xFFFFFFFF → TG 不支持时长反馈

②播放位置(SongPosition)

字段 值范围 特殊值 处理逻辑
SongPosition 0x00000000 ~ 0xFFFFFFFF 0xFFFFFFFF 显示"未知位置",停止进度条自动更新

动态行为

  • 播放时每秒变化约 1000 次(1秒=1000ms)

  • 快进/快退时数值跳跃变化(需结合 PlayStatus 状态处理)

③播放状态(PlayStatus)

状态码 含义 典型触发场景 界面表现建议
0x00 STOPPED 用户点击停止/播放完成 显示停止图标,进度条归零
0x01 PLAYING 用户点击播放/恢复播放 显示播放图标,进度条持续更新
0x02 PAUSED 用户主动暂停 显示暂停图标,进度条静止
0x03 FWD_SEEK 用户长按快进键 显示快进图标,进度条快速前进
0x04 REV_SEEK 用户长按后退键 显示后退图标,进度条快速回退
0xFF ERROR 设备异常/媒体加载失败 显示错误提示,重置播放控件

HCI LOG:

2.4 注意事项

①字节序处理:所有 4 字节参数需按 大端序(Big-Endian) 解析:

song_length = int.from_bytes(data[0:4], byteorder='big')

②特殊值 0xFFFFFFFF

if (song_length == 0xFFFFFFFF) {
    show_label("时长未知");
    disable_seekbar();
}

③状态同步策略

  • 高频查询限制:建议最小间隔 ≥500ms,避免频繁请求导致设备过载

  • 结合异步通知:与 RegisterNotification(EVENT_PLAYBACK_POS_CHANGED) 配合使用

④错误恢复机制

function handlePlayStatus(response) {
    if (response.playStatus === 0xFF) {
        retryCount++;
        if (retryCount < 3) {
            setTimeout(fetchPlayStatus, 1000);
        } else {
            showErrorMessage("设备连接异常");
        }
    }
}

2.5 协议实现示例(伪代码)

#include <stdio.h>
#include <stdint.h>

// 定义 GetPlayStatus 命令结构体
typedef struct {
    // 该命令无参数
} GetPlayStatusCommand;

// 定义 GetPlayStatus 响应结构体
typedef struct {
    uint32_t songLength;
    uint32_t songPosition;
    uint8_t playStatus;
} GetPlayStatusResponse;

// 模拟 CT 发送 GetPlayStatus 命令
void sendGetPlayStatusCommand() {
    GetPlayStatusCommand command;
    // 这里模拟发送命令到 TG,实际应用中可能通过蓝牙协议栈发送
    printf("CT 发送 GetPlayStatus 命令\n");
    // 假设这里将命令发送到某个函数进行处理
    // send_command_to_tg(&command);
}

// 模拟 TG 接收 GetPlayStatus 命令并返回响应
GetPlayStatusResponse receiveGetPlayStatusCommand() {
    GetPlayStatusResponse response;
    // 模拟获取播放状态信息
    // 假设 TG 支持获取 SongLength 和 SongPosition
    response.songLength = 300000; // 假设歌曲时长为 300000 毫秒
    response.songPosition = 150000; // 假设当前播放位置为 150000 毫秒
    response.playStatus = 0x01; // 假设当前播放状态为 PLAYING

    // 如果 TG 不支持 SongLength 和 SongPosition
    // response.songLength = 0xFFFFFFFF;
    // response.songPosition = 0xFFFFFFFF;

    printf("TG 接收 GetPlayStatus 命令并返回响应\n");
    return response;
}

// 模拟 CT 接收 GetPlayStatus 响应
void receiveGetPlayStatusResponse(GetPlayStatusResponse response) {
    printf("CT 接收 GetPlayStatus 响应\n");
    printf("歌曲总时长: %u 毫秒\n", response.songLength);
    printf("当前播放位置: %u 毫秒\n", response.songPosition);
    switch (response.playStatus) {
        case 0x00:
            printf("播放状态: STOPPED\n");
            break;
        case 0x01:
            printf("播放状态: PLAYING\n");
            break;
        case 0x02:
            printf("播放状态: PAUSED\n");
            break;
        case 0x03:
            printf("播放状态: FWD_SEEK\n");
            break;
        case 0x04:
            printf("播放状态: REV_SEEK\n");
            break;
        case 0xFF:
            printf("播放状态: ERROR\n");
            break;
        default:
            printf("未知播放状态\n");
    }
}

int main() {
    // CT 发送 GetPlayStatus 命令
    sendGetPlayStatusCommand();

    // TG 接收命令并返回响应
    GetPlayStatusResponse response = receiveGetPlayStatusCommand();

    // CT 接收响应
    receiveGetPlayStatusResponse(response);

    return 0;
}    

三、RegisterNotification:异步事件订阅

3.1 命令概述

目的:用于在目标设备(TG)上注册,以便基于特定事件异步接收通知。

双重响应机制:

  • INTERIM 响应(初始响应):接收到命令后,应在TMTP(200ms)时间内返回INTERIM响应(当前状态)。

  • CHANGED 响应(后续响应):异步推送状态变化

  • 错误处理:可能返回 REJECTED(0x0A)/NOT_IMPLEMENTED(0x08)

核心机制图解:

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

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

相关文章

MATLAB 控制系统设计与仿真 - 27

状态空间的标准型 传递函数和状态空间可以相互转换&#xff0c;接下来会举例如何有传递函数转成状态空间标准型。 对角标准型 当 G(s)可以写成&#xff1a; 即&#xff1a; 根据上图可知&#xff1a; 约当标准型 当 G(s)可以写成&#xff1a; 即&#xff1a; 根据上图…

linux 命令 cp

cp 是 Linux 中用于复制文件和目录的命令&#xff0c;基本功能是将源文件或目录复制到目标位置 基本语法 cp [选项] 源文件 目标文件 cp [选项] 源文件1 源文件2 ... 目标目录 常用选项 选项说明-i交互模式&#xff08;覆盖前询问确认&#xff09;-r 或 -R递归复制目录&#…

蓝桥杯高频考点——进制转换

进制转换 二进制转十进制代码演示 十六进制转十进制代码演示 十进制转K进制代码演示 任意进制之间的转换代码演示 二进制转十进制 代码演示 // 定义函数 calc&#xff0c;用于将字符转换为对应的数值 int calc(char c) {// 若字符 c 大于等于 9&#xff08;注&#xff1a;此处…

【算法百题】专题七_分治快排_专题八_分治归并

文章目录 前言分治快排题&#xff1a;043. [颜⾊分类&#xff08;medium&#xff09;](https://leetcode.cn/problems/sort-colors/description/)分析 044. [快速排序&#xff08;medium&#xff09;](https://leetcode.cn/problems/sort-an-array/description/)分析 045. [快速…

使用OBS进行webRTC推流参考

参考腾讯云官方文档&#xff1a; 云直播 OBS WebRTC 推流_腾讯云 说明非常详细&#xff0c;分为通过WHIP和OBS插件的形式进行推流。 注意&#xff1a;通过OBS插件的形式进行推流需要使用较低的版本&#xff0c;文档里有说明&#xff0c;需要仔细阅读。

(链表)面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&#xff…

Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)

1、涟漪特效散点图 from pyecharts.globals import SymbolType from pyecharts.charts import EffectScatter from pyecharts.faker import Faker from pyecharts import options as opts from pyecharts.globals import ThemeType # 绘制图表 es (EffectScatter(init_optsop…

IP风险度自检,互联网的安全“指南针”

IP地址就像我们的网络“身份证”&#xff0c;而IP风险度则是衡量这个“身份证”安全性的重要指标。它关乎着我们的隐私保护、账号安全以及网络体验&#xff0c;今天就让我们一起深入了解一下IP风险度。 什么是IP风险度 IP风险度是指一个IP地址可能暴露用户真实身份或被网络平台…

数据结构与算法-图论-拓扑排序

前置芝士 概念 拓扑排序&#xff08;Topological Sorting&#xff09;是对有向无环图&#xff08;DAG&#xff0c;Directed Acyclic Graph&#xff09;的顶点进行排序的一种算法。它将图中的所有顶点排成一个线性序列&#xff0c;使得对于图中的任意一条有向边 (u, v)&#x…

Gan网络公式了解

Gan网络 生成器和判别器是亦敌亦友的关系 对于生成模型&#xff0c;损失函数很难定义->所以我们可以将生成模型的输出交给判别模型进行处理&#xff0c;来分辨好坏。 生成器的损失是通过判别器的输出来计算的&#xff0c;而判别器的输出是一个概率值&#xff0c;我们可以通过…

解决linux mysql命令 bash: mysql: command not found 的方法

首先得知道mysql命令或mysqladmin命令的完整路径 比如mysql的路径是&#xff1a; /usr/local/mysql/bin/mysql&#xff0c;我们则可以这样执行命令&#xff1a; ln -s /usr/local/mysql/bin/mysql /usr/bin © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点…

微服务存在的问题及解决方案

微服务存在的问题及解决方案 1. 存在问题 1.1 接口拖慢 因为一个接口在并发时&#xff0c;正好执行时长又比较长&#xff0c;那么当前这个接口占用过多的 Tomcat 连接&#xff0c;导致其他接口无法即时获取到 Tomcat 连接来完成请求&#xff0c;导致接口拖慢&#xff0c;甚至…

【css酷炫效果】纯CSS实现立体纸张折叠动效

【css酷炫效果】纯CSS实现悬浮阴影扩散交互 缘创作背景html结构css样式完整代码基础版进阶版(3d 悬浮效果) 效果图 通过CSS box-shadow与transition属性实现悬浮阴影扩散交互&#xff0c;为元素添加细腻的悬浮反馈。 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;htt…

案例5_1:单位数码管显示0

文章目录 文章介绍效果图仿真图5_1放置单位数码管 代码5_1.c 文章介绍 效果图 仿真图5_1 复制案例1_2的仿真图&#xff0c;在此基础上修改 注意&#xff1a;栅格大小需要缩小 放置单位数码管 代码5_1.c #include <reg52.h>#define uchar unsigned char #define uint un…

Linux centos7误删/boot拯救方法

1.进入救援模式 插入CentOS 7安装光盘&#xff0c;重启系统。在开机时按BIOS设置对应的按键&#xff08;通常是F2等&#xff09;&#xff0c;将启动顺序调整为CD - ROM优先。 系统从光盘启动后&#xff0c;选择“Troubleshooting”&#xff0c;然后选择“Rescue a CentOS s…

操作系统八股文整理(一)

操作系统八股文整理 一、进程和线程的区别二、进程与线程的切换过程一、进程切换进程切换的步骤&#xff1a; 二、线程切换线程切换的步骤&#xff1a; 三、进程切换与线程切换的对比四、上下文切换的优化 三、系统调用一、系统调用的触发二、从用户空间切换到内核空间三、执行…

20250317笔记本电脑在ubuntu22.04下使用acpi命令查看电池电量

20250317笔记本电脑在ubuntu22.04下使用acpi命令查看电池电量 2025/3/17 18:05 百度&#xff1a;ubuntu查看电池电量 百度为您找到以下结果 ubuntu查看电池电量 在Ubuntu操作系统中&#xff0c;查看电池电量通常可以通过命令行或者图形界面来完成。下面是一些常见的方法&…

蓝桥杯备考----模拟算法 phone number

嗯。这道题可以在两个和三个数字加-&#xff0c;我们只要随便输出一个奏行 那么&#xff01;我们规范一下&#xff0c;我们尽可能的只在两个数字之间加&#xff0c;但是如果一共奇数个的话&#xff0c;我们就让最后三个成一组&#xff0c;也就是说&#xff0c;我们用的是个小贪…

【数据分享】2000—2024年我国省市县三级逐月归一化植被指数(NDVI)数据(Shp/Excel格式)

之前我们分享过2000—2024年逐月归一化植被指数&#xff08;NDVI&#xff09;栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;该数据来源于NASA定期发布的MOD13A3数据集&#xff01;很多小伙伴拿到数据后反馈栅格数据不太方便使用&#xff0c;问我们能不…

蓝桥杯真题——洛谷 Day10 并查集(枚举)

目录 P8651 [蓝桥杯 2017 省 B] 日期问题 P8635 [蓝桥杯 2016 省 AB] 四平方和 P8651 [蓝桥杯 2017 省 B] 日期问题 思路&#xff1a; 使用scanf读入&#xff0c;枚举从1960到2059&#xff0c;若符合题目形式&#xff0c;加入答案&#xff0c; 从小到大输出&#xff1a;存入结…