Using Contactless Reader/Writer with Capture Helper

Initializing Capture Helper

Please refer to Capture Helper initialization.

Device Manager

The Socket Mobile contactless reader/writer (D600) uses Bluetooth Low Energy (BLE) to communicate with the host.

Capture SDK provides a new Device Manager object in order to provide some control over the BLE transport.

The Device Manager reference is received in the 2 delegates didNotifyArrivalForDeviceManager and didNotifyRemovalForDeviceManager defined in the SKTCaptureHelperDelegate.

Here is an example of such delegate handler in a sample app:

-(void)didNotifyArrivalForDeviceManager:(SKTCaptureHelperDeviceManager*) deviceManager withResult:(SKTResult) result{
  NSLog(@"didNotifyArrivalForDeviceManager %@", deviceManager.friendlyName);
  _deviceManager = deviceManager;
  [deviceManager getFavoriteDevicesWithCompletionHandler:^(SKTResult result, NSString *favorites) {
      NSLog(@"current favorite set to: %@", favorites);
      _currentFavorite = favorites;
      dispatch_async(dispatch_get_main_queue(), ^{
          _d600SupportSwitch.on = favorites.length > 0;
      });
  }];
}

-(void)didNotifyRemovalForDeviceManager:(SKTCaptureHelperDeviceManager*) deviceManager withResult:(SKTResult) result{
    NSLog(@"didNotifyRemovalForDeviceManager %@", deviceManager.friendlyName);
    _deviceManager = nil;
}

In this example a UI switch is activated in the function of the content of the favorite devices and its function is described below.

Favorite Devices

To faciliate the operations of discovering and connecting to a contactless reader/writer, a concept of favorite devices has been introduced.

The Device Manager has a property to configure in a persistent way the favorite device.

As soon as the Device Manager favorite devices is set to either a device identifier or "*" the auto discovery and connect mode starts automatically.

In this mode the Device Manager starts a discovery and connects to the contactless reader/writer corresponding to the identifier found in the favorite devices property or to the first contactless reader/writer it finds in case where the favorites device is set to "*".

Note

Using auto discovery and connect mode can increase the power consumption. Once the contactless reader/writer is connected, the consumption level drops. But as soon as the discovery restarts when by example the contactless reader/writer is no longer ON or in range, then the power consumption increases slightly. Setting the favorite devices to an empty string will stop the auto discovery and connect mode, and BLE discovery won’t happen again until the favorite devices is set or the discovery is implicitly started by using the BLE Device Manager startDiscovery property.

Starting Contactless Reader/Writer Auto Discovery Mode

The following code sample shows how to turn on by default in an app the auto discovery and connect mode to support contactless reader/writer, so that as soon as there is such device turned on in the vicinity, the app will automatically connect to it:

-(void) didNotifyArrivalForDeviceManager:(SKTCaptureHelperDeviceManager *)deviceManager withResult:(SKTResult)result {
  NSLog(@"Device Manager arrival");
  if (result == SKTCaptureE_NOERROR){
      [deviceManager getFavoriteDevicesWithCompletionHandler:^(SKTResult result, NSString *favorites) {
          NSLog(@"Getting favorite devices returns %ld", result);
          if (result == SKTCaptureE_NOERROR){
              if (favorites.length == 0 ){
                  [deviceManager setFavoriteDevices:@"*" completionHandler:^(SKTResult result) {
                      NSLog(@"Setting favorite devices returns %ld", result);
                  }];
              }
          }
      }];
  };
}

To turn off this feature, just set the favorite devices to an empty string:

NSLog(@"Turning OFF the Contactless Reader/Writer support");
[_deviceManager setFavoriteDevices:@"" completionHandler:^(SKTResult result) {
    NSLog(@"setting the favorites returns: %ld", (long)result);
    _currentFavorite=@"";
}];

Presence of a Contactless Reader/Writer

The presence of contactless reader/write device reference is handled by the application by implementing the didNotifyArrivalForDevice and didNotifyRemovalForDevice delegates from the SKTCaptureHelperDelegate protocol.

Here is an example of such handlers:

-(void)didNotifyArrivalForDevice:(SKTCaptureHelperDevice*) device withResult:(SKTResult) result{
  [self updateStatusFromDevices:[_capture getDevicesList]];
}

-(void)didNotifyRemovalForDevice:(SKTCaptureHelperDevice*) device withResult:(SKTResult) result{
    [self updateStatusFromDevices:[_capture getDevicesList]];
}

To keep a particular device a favorite devices, its device unique identifier can be retrieved using the Device Manager getDeviceUniqueIdentifierFromDeviceGuid API and it can then be used to set the Device Manager favorite devices with it as shown below:

-(void)didNotifyArrivalForDevice:(SKTCaptureHelperDevice*) device withResult:(SKTResult) result{
  [self updateStatusFromDevices:[_capture getDevicesList]];

  NSLog(@"Device arrival for %@ and favorite is %@", device.friendlyName, _currentFavorite);
  // set this scanner has favorite if favorite is still set as *
  if([_currentFavorite compare:@"*"] == NSOrderedSame){
      [_deviceManager getDeviceUniqueIdentifierFromDeviceGuid:device.guid completionHandler:^(SKTResult result, NSString *deviceUniqueIdentifier) {
          NSLog(@"asking for the device unique identifier returns %ld with value: %@", (long)result, deviceUniqueIdentifier);
          if(SKTSUCCESS(result)){
              _currentFavorite = deviceUniqueIdentifier;
              NSString* favorite = deviceUniqueIdentifier;
              [_deviceManager setFavoriteDevices:_currentFavorite completionHandler:^(SKTResult result) {
                  NSLog(@"new favorite returns %ld and is set to %@", (long)result, favorite);
              }];
          }
      }];
  }
}

This example set the device favorite to the first contactless reader/writer that connects to the host if the device favorite was set with a *. By doing so, this contactless reader/writer becomes the preferred device to connect to this host, until the favorite device string is reset to either an empty string to stop the auto discovery and connect mode, or to * to connect to another or the same contactless reader/writer device.

Contactless Reader/Writer discovery

The Device Manager offers an API to discover the contactless reader/writer devices that are in the vicinity.

Once a device has been discovered, its identifier UUID can be used to set the Device Manager favorite devices with. As soon as the Device Manager favorite devices is set with this UUID, the Device Manager will then connects to this particular contactless reader/writer device.

Here is an example showing how to start the device discovery:

- (IBAction)onPressDiscoveryButton:(id)sender {
  if(_bleDeviceManager) {
      [_bleDeviceManager startDiscoveryWithTimeout:5000 completionHandler:^(SKTResult result) {
          NSLog(@"Discovery starts with result: %ld", result);
      }];
  }
}

This example assumes the _bleDeviceManager has been set during the didNotifyArrivalForDeviceManager delegate call.

Then for each discovered device the didDiscoverDevice delegate is called:

-(void)didDiscoverDevice:(NSString*) device fromDeviceManager:(SKTCaptureHelperDeviceManager*) deviceManager{
  NSLog(@"%@",device);
  NSDictionary *newDevice = [NSPropertyListSerialization
                        propertyListWithData:[device dataUsingEncoding:NSUTF8StringEncoding]
                        options:kNilOptions
                        format:NULL
                        error:NULL];
  NSLog(@"device Name: %@", newDevice[@"name"]);
  NSLog(@"device UUID: %@", newDevice[@"identifierUUID"]);
  if ([ViewController addDevice:newDevice inTheArray:_devices]) {
      dispatch_async(dispatch_get_main_queue(), ^{
          [_discoveredDevicesTableView reloadData];
      });
  }
}

In this case an table view is updated with the newly discovered device information. The device identifierUUID is what can be used to set the favorite devices with in order to connect to that particular contactless reader/writer device.

Here is an example of how the device NSString object might look like:

{
  identifierUUID = "BE495AA0-A93C-4274-9006-F3BC2428ACDF";
  name = "Socket D600 [7EF619]";
  serviceUUID = "6CB501B7-96F6-4EEF-ACB1-D7535F153CF0";
}

The device discovery ends once the time out has elapsed and notifies the app by calling the didDiscoveryEndWithResult delegate of the SKTCaptureHelperDelegate:

-(void)didDiscoveryEndWithResult:(SKTResult)result fromDeviceManager:(SKTCaptureHelperDeviceManager*) deviceManager{
  NSLog(@"Discovery ends with result: %ld", result);
}

Now setting a particular contactless reader/writer is simply a matter of calling the setFavoriteDevices method of the device manager with the device identifierUUID as a string. Here is an example of such code:

- (IBAction)onPressSetFavoriteButton:(id)sender {
  if ((_deviceIdentifierToConnectTo != nil) &&(_bleDeviceManager != nil)){
      [_bleDeviceManager setFavoriteDevices:_deviceIdentifierToConnectTo completionHandler:^(SKTResult result) {
          NSLog(@"Setting favorite devices returns: %ld", result);
      }];
  }
}

The _deviceIdentifierToConnectTo has been previously set when the user has selected the device from a UITableView by example:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  _deviceIdentifierToConnectTo = _devices[indexPath.row][@"identifierUUID"];
}

The _devices is a mutable array of NSDictionary*.

Contactless Reader/Writer Data Format

When the contactless reader/writer reads data from a card, it can display this data in four different formats:

  • Tag Type and ID: SKTCaptureDataFormatTagTypeAndId

    This Data Format will display the type of card (NFC Forum, etc.) as well as the unique identifier associated with the card.


  • ID Only: SKTCaptureDataFormatIdOnly

    This Data Format will only display the unique identifier from the card. (This format is not supported)


  • Tag Type and Data: SKTCaptureDataFormatTagTypeAndData

    This Data Format will display the type of card (NFC Forum, etc.) as well as the expected data on the card. This data can be translated into a String format or otherwise if expected.


  • Data Only SKTCaptureDataFormatDataOnly

    This Data Format will display only the data from the card. (This format is not supported)


Setting and Getting the current Data Format

You can change the current data format by using one of the aforementioned data format types. Example of setting to SKTCaptureDataFormatTagTypeAndData:

[device setDataFormat:SKTCaptureDataFormatTagTypeAndData completionHandler:^(SKTResult result) {
    if(SKTSUCCESS(result)) {
        // Success!
    } else {
        // Error!
    }
}];

Getting the current data format is similar to setting:

[device getDataFormatWithCompletionHandler:^(SKTResult result, SKTCaptureDataFormat dataFormat) {
    if(SKTSUCCESS(result)) {
        // Success!
        if(dataFormat == SKTCaptureDataFormatTagTypeAndId) {
            // Update the UI in some way...
        } else {
            // Update the UI in some other way...
        }
    } else {
        // Error!
    }
}];