Skip to main content

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​

  1. TopStepComKit SDK has been successfully initialized
  2. A Bluetooth connection with the peripheral device has been established
  3. The peripheral device supports request transfer

Data Models​

TSRequestModel​

The request model sent from the device to the App.

PropertyTypeDescription
requestNameNSString *Request name identifying the type or purpose
requestIdNSString *Unique request identifier used to match requests with responses
requestUrlNSString *Target URL endpoint for the request
parametersNSDictionary *Request parameters as key-value pairs
appIdNSString *Identifier of the application issuing the request
deviceStoragePathNSString *Remote path on the device where response files are stored
remoteFilePathsNSArray<NSString *> *Remote file paths on the device that need to be downloaded
localFilePathsNSArray<NSString *> *Local file paths corresponding to remoteFilePaths

TSRespondModel​

The response model sent from the App back to the device.

PropertyTypeDescription
requestIdNSString *Must match the requestId of the original TSRequestModel
requestNameNSString *Must match the requestName of the original request
appIdNSString *Identifier of the application that originated the request
responseContentNSDictionary *Response payload as key-value pairs
errorCodeNSIntegerError code; 0 indicates success, non-zero indicates failure
errorMessageNSString *Error description; nil on success
deviceStoragePathNSString *Remote path on the device where files are stored
localFilePathsNSArray<NSString *> *Local file paths included in the response

Callback Types​

CallbackDescription
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
TSCompletionBlockGeneric 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

NameTypeDescription
completionTSRequestListenerBlockCallback 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

NameTypeDescription
respondModelTSRespondModel *Response model; its requestId and requestName must match the original request
completionTSCompletionBlockCompletion 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

NameTypeDescription
mp3FilePathNSString *Local path of the source MP3 file
pcmFilePathNSString *Local path to write the output PCM file
sampleRateNSIntegerTarget sample rate in Hz (e.g. 8000, 16000, 44100); must match the device
bitDepthNSIntegerTarget bit depth (e.g. 8, 16, 24); must match the device
completionTSCompletionBlockCompletion 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​

  1. Single listener: Calling registerRequestListener: multiple times overwrites the previous listener; only the last registration is active. Register it once after the App starts.
  2. requestId must match: When calling respondToRequest:completion:, TSRespondModel.requestId must exactly match the incoming TSRequestModel.requestId; otherwise the device cannot correlate the response.
  3. Respond promptly: Some devices enforce a response timeout, so reply as quickly as possible.
  4. Sample rate and bit depth: The sampleRate and bitDepth passed to convertMP3ToPCM: must match the device's supported parameters; mismatches can cause playback issues.
  5. Completion callbacks: All callbacks are invoked on the main thread, so you can update the UI directly inside them.