Request Transfer (TSRequestTransfer)
The TSRequestTransfer module provides bidirectional data transfer between the device and the App based on a request-response model. The device can send requests (with parameters and file paths) to the App; the App processes them and sends a response back. The module also includes an audio conversion utility that turns MP3 files into PCM suitable for device playback.
Prerequisites
- TopStepComKit SDK has been successfully initialized
- A Bluetooth connection with the peripheral device has been established
- The peripheral device supports request transfer
Data Models
TSRequestModel
The request model sent from the device to the App.
| Property | Type | Description |
|---|---|---|
requestName | NSString * | Request name identifying the type or purpose |
requestId | NSString * | Unique request identifier used to match requests with responses |
requestUrl | NSString * | Target URL endpoint for the request |
parameters | NSDictionary * | Request parameters as key-value pairs |
appId | NSString * | Identifier of the application issuing the request |
deviceStoragePath | NSString * | Remote path on the device where response files are stored |
remoteFilePaths | NSArray<NSString *> * | Remote file paths on the device that need to be downloaded |
localFilePaths | NSArray<NSString *> * | Local file paths corresponding to remoteFilePaths |
TSRespondModel
The response model sent from the App back to the device.
| Property | Type | Description |
|---|---|---|
requestId | NSString * | Must match the requestId of the original TSRequestModel |
requestName | NSString * | Must match the requestName of the original request |
appId | NSString * | Identifier of the application that originated the request |
responseContent | NSDictionary * | Response payload as key-value pairs |
errorCode | NSInteger | Error code; 0 indicates success, non-zero indicates failure |
errorMessage | NSString * | Error description; nil on success |
deviceStoragePath | NSString * | Remote path on the device where files are stored |
localFilePaths | NSArray<NSString *> * | Local file paths included in the response |
Callback Types
| Callback | Description |
|---|---|
void (^)(TSRequestModel *_Nullable request, NSError *_Nullable error) | Request listener callback, fired when a request from the device is received. A nil error means the request data is valid |
TSCompletionBlock | Generic completion callback; nil error indicates success |
Interface Methods
1. Request Listening
Register Request Listener
Registers a listener to receive requests from the device. Registering again overwrites the previous listener — only the most recently registered callback is active.
- (void)registerRequestListener:(TSRequestListenerBlock)completion;
Parameters
| Name | Type | Description |
|---|---|---|
completion | TSRequestListenerBlock | Callback invoked when a request is received, returning the request model or an error |
Example
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
[requestTransfer registerRequestListener:^(TSRequestModel *_Nullable request, NSError *_Nullable error) {
if (error) {
TSLog(@"Failed to receive request: %@", error.localizedDescription);
return;
}
TSLog(@"Request received - name: %@, id: %@", request.requestName, request.requestId);
TSLog(@"Parameters: %@", request.parameters);
// Handle the request and respond immediately
[self handleRequest:request];
}];
2. Responding to Requests
Respond to a Device Request
Sends a response back to the device after processing an incoming request.
- (void)respondToRequest:(TSRespondModel *)respondModel
completion:(TSCompletionBlock)completion;
Parameters
| Name | Type | Description |
|---|---|---|
respondModel | TSRespondModel * | Response model; its requestId and requestName must match the original request |
completion | TSCompletionBlock | Completion callback for the send operation; a nil error means the response was sent successfully |
Example
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
// Build the response from the received TSRequestModel.
TSRespondModel *respond = [[TSRespondModel alloc] init];
respond.requestId = request.requestId;
respond.requestName = request.requestName;
respond.appId = request.appId;
respond.errorCode = 0; // 0 means success
respond.responseContent = @{
@"status": @"ok",
@"data": @"processed payload"
};
[requestTransfer respondToRequest:respond completion:^(NSError *_Nullable error) {
if (!error) {
TSLog(@"Response sent");
} else {
TSLog(@"Failed to send response: %@", error.localizedDescription);
}
}];
3. Audio Format Conversion
MP3 to PCM
Converts an MP3 file to PCM for device playback. Sample rate and bit depth are configurable.
- (void)convertMP3ToPCM:(NSString *)mp3FilePath
pcmFilePath:(NSString *)pcmFilePath
sampleRate:(NSInteger)sampleRate
bitDepth:(NSInteger)bitDepth
completion:(TSCompletionBlock)completion;
Parameters
| Name | Type | Description |
|---|---|---|
mp3FilePath | NSString * | Local path of the source MP3 file |
pcmFilePath | NSString * | Local path to write the output PCM file |
sampleRate | NSInteger | Target sample rate in Hz (e.g. 8000, 16000, 44100); must match the device |
bitDepth | NSInteger | Target bit depth (e.g. 8, 16, 24); must match the device |
completion | TSCompletionBlock | Completion callback; a nil error means conversion succeeded |
Example
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 conversion done, PCM at: %@", pcmPath);
// On success you can put the PCM path into TSRespondModel.localFilePaths and send it back.
} else {
TSLog(@"Conversion failed: %@", error.localizedDescription);
}
}];
Full Example
The following sample shows the full request-response flow: receiving a request, converting audio, and sending a response.
id<TSRequestTransferInterface> requestTransfer = [TopStepComKit sharedInstance].requestTransfer;
// 1. Register the listener (call once after a successful connection).
[requestTransfer registerRequestListener:^(TSRequestModel *_Nullable request, NSError *_Nullable error) {
if (error || !request) {
TSLog(@"Request reception error: %@", error.localizedDescription);
return;
}
TSLog(@"Received request: %@", request.requestName);
// 2. If the request needs an audio file, convert it first.
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. Build and send the response.
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(@"Response send %@", sendError ? @"failed" : @"succeeded");
}];
}];
}
}];
Notes
- Single listener: Calling
registerRequestListener:multiple times overwrites the previous listener; only the last registration is active. Register it once after the App starts. - requestId must match: When calling
respondToRequest:completion:,TSRespondModel.requestIdmust exactly match the incomingTSRequestModel.requestId; otherwise the device cannot correlate the response. - Respond promptly: Some devices enforce a response timeout, so reply as quickly as possible.
- Sample rate and bit depth: The
sampleRateandbitDepthpassed toconvertMP3ToPCM:must match the device's supported parameters; mismatches can cause playback issues. - Completion callbacks: All callbacks are invoked on the main thread, so you can update the UI directly inside them.