请求传输(TSRequestTransfer)
TSRequestTransfer 模块提供设备与 App 之间基于请求-响应模型的双向数据传输能力。设备可以向 App 发起请求(携带参数和文件路径),App 接收后进行处理并回传响应。此外,该模块还提供音频格式转换工具,将 MP3 文件转换为设备可播放的 PCM 格式。
前提条件
- 已成功初始化 TopStepComKit SDK
- 已建立与外围设备的蓝牙连接
- 外围设备支持请求传输功能
数据模型
TSRequestModel
设备发送给 App 的请求数据模型。
| 属性名 | 类型 | 说明 |
|---|---|---|
requestName | NSString * | 请求名称,标识请求的类型或用途 |
requestId | NSString * | 请求唯一标识符,用于匹配请求与响应 |
requestUrl | NSString * | 请求目标 URL 端点 |
parameters | NSDictionary * | 请求参数字典,键值对形式 |
appId | NSString * | 发起请求的应用标识符 |
deviceStoragePath | NSString * | 设备端文件存储路径(响应文件所在的远程路径) |
remoteFilePaths | NSArray<NSString *> * | 设备端需要下载的文件路径数组 |
localFilePaths | NSArray<NSString *> * | 本地文件路径数组(与 remoteFilePaths 对应) |
TSRespondModel
App 回传给设备的响应数据模型。
| 属性名 | 类型 | 说明 |
|---|---|---|
requestId | NSString * | 对应的请求 ID,必须与 TSRequestModel.requestId 一致 |
requestName | NSString * | 对应的请求名称 |
appId | NSString * | 发起原始请求的应用标识符 |
responseContent | NSDictionary * | 响应数据字典,键值对形式 |
errorCode | NSInteger | 错误码,0 表示成功,非 0 表示各类错误 |
errorMessage | NSString * | 错误描述,成功时为 nil |
deviceStoragePath | NSString * | 设备端文件存储路径 |
localFilePaths | NSArray<NSString *> * | 响应中包含的本地文件路径数组 |
回调类型
| 回调类型 | 说明 |
|---|---|
void (^)(TSRequestModel *_Nullable request, NSError *_Nullable error) | 请求监听回调,收到设备请求时触发;error 为 nil 表示请求数据有效 |
TSCompletionBlock | 通用完成回调,error 为 nil 表示操作成功 |
接口方法
1. 请求监听
注册请求监听器
注册一个监听器,用于接收设备发来的请求。多次注册会覆盖上一次注册的监听器,只有最后注册的监听器会生效。
- (void)registerRequestListener:(TSRequestListenerBlock)completion;
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
completion | TSRequestListenerBlock | 收到请求时调用的回调,返回请求模型或错误 |
代码示例
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
[requestTransfer registerRequestListener:^(TSRequestModel *_Nullable request, NSError *_Nullable error) {
if (error) {
TSLog(@"接收请求失败: %@", error.localizedDescription);
return;
}
TSLog(@"收到请求 - 名称: %@, ID: %@", request.requestName, request.requestId);
TSLog(@"请求参数: %@", request.parameters);
// 处理请求后立即响应
[self handleRequest:request];
}];
2. 请求响应
响应设备请求
处理完设备发来的请求后,使用该方法向设备回传响应结果。
- (void)respondToRequest:(TSRespondModel *)respondModel
completion:(TSCompletionBlock)completion;
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
respondModel | TSRespondModel * | 响应数据模型,requestId 和 requestName 须与原始请求一致 |
completion | TSCompletionBlock | 响应发送完成回调,error 为 nil 表示发送成功 |
代码示例
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
// 构建响应模型(基于收到的 TSRequestModel)
TSRespondModel *respond = [[TSRespondModel alloc] init];
respond.requestId = request.requestId;
respond.requestName = request.requestName;
respond.appId = request.appId;
respond.errorCode = 0; // 0 表示成功
respond.responseContent = @{
@"status": @"ok",
@"data": @"处理结果数据"
};
[requestTransfer respondToRequest:respond completion:^(NSError *_Nullable error) {
if (!error) {
TSLog(@"响应发送成功");
} else {
TSLog(@"响应发送失败: %@", error.localizedDescription);
}
}];
3. 音频格式转换
MP3 转 PCM
将 MP3 音频文件转换为 PCM 格式,供设备播放使用。转换支持自定义采样率和位深度。
- (void)convertMP3ToPCM:(NSString *)mp3FilePath
pcmFilePath:(NSString *)pcmFilePath
sampleRate:(NSInteger)sampleRate
bitDepth:(NSInteger)bitDepth
completion:(TSCompletionBlock)completion;
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
mp3FilePath | NSString * | 源 MP3 文件的本地路径 |
pcmFilePath | NSString * | 输出 PCM 文件的目标本地路径 |
sampleRate | NSInteger | 目标采样率(Hz),如 8000、16000、44100 等,须与设备支持的采样率匹配 |
bitDepth | NSInteger | 目标位深度(bit),如 8、16、24,须与设备支持的位深度匹配 |
completion | TSCompletionBlock | 转换完成回调,error 为 nil 表示转换成功 |
代码示例
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *mp3Path = [documentsPath stringByAppendingPathComponent:@"ringtone.mp3"];
NSString *pcmPath = [documentsPath stringByAppendingPathComponent:@"ringtone.pcm"];
[requestTransfer convertMP3ToPCM:mp3Path
pcmFilePath:pcmPath
sampleRate:16000
bitDepth:16
completion:^(NSError *_Nullable error) {
if (!error) {
TSLog(@"MP3 转换完成,PCM 文件路径: %@", pcmPath);
// 转换成功后可将 PCM 文件路径填入 TSRespondModel.localFilePaths 回传给设备
} else {
TSLog(@"转换失败: %@", error.localizedDescription);
}
}];
完整使用示例
以下示例演示完整的请求-响应流程,包括接收请求、转换音频、回传响应:
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
// 1. 注册监听器(建议在连接成功后调用一次)
[requestTransfer registerRequestListener:^(TSRequestModel *_Nullable request, NSError *_Nullable error) {
if (error || !request) {
TSLog(@"请求接收异常: %@", error.localizedDescription);
return;
}
TSLog(@"收到请求: %@", request.requestName);
// 2. 如果请求需要音频文件,先进行格式转换
if ([request.requestName isEqualToString:@"playRingtone"]) {
NSString *mp3Path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tone.mp3"];
NSString *pcmPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tone.pcm"];
[requestTransfer convertMP3ToPCM:mp3Path
pcmFilePath:pcmPath
sampleRate:16000
bitDepth:16
completion:^(NSError *convertError) {
// 3. 构建响应并发送
TSRespondModel *respond = [[TSRespondModel alloc] init];
respond.requestId = request.requestId;
respond.requestName = request.requestName;
respond.appId = request.appId;
respond.errorCode = convertError ? -1 : 0;
respond.errorMessage = convertError.localizedDescription;
respond.localFilePaths = convertError ? nil : @[pcmPath];
[requestTransfer respondToRequest:respond completion:^(NSError *sendError) {
TSLog(@"响应发送%@", sendError ? @"失败" : @"成功");
}];
}];
}
}];
注意事项
- 监听器唯一性:
registerRequestListener:多次调用会覆盖之前注册的监听器,每次只有最后一个注册的回调生效,建议在应用启动后仅注册一次 - requestId 必须匹配:调用
respondToRequest:completion:时,TSRespondModel.requestId必须与收到的TSRequestModel.requestId完全一致,否则设备无法匹配响应 - 及时响应:收到请求后应尽快响应,部分设备对响应超时有限制
- 采样率与位深度:调用
convertMP3ToPCM:时,sampleRate和bitDepth须与目标设备支持的参数一致,不匹配可能导致音频播放异常 - 完成回调:所有操作的回调均在主线程执行,可直接更新 UI