# Devices Features

Per-device features applicable to all Socket Mobile barcode scanners and NFC readers. Covers reading firmware version, getting and setting a friendly device name, configuring stand mode (auto-scan when placed in charging stand), selecting device themes (NFC theme, barcode theme, or both for combo devices), and setting up Single Partnership to lock a specific scanner to a specific host. Includes code samples for each feature.

Those features are at the Scanners and Readers level. It means that most of these methods are called on the device object itself — **CaptureHelperDevice** on iOS, C#, JavaScript and Dart, or **DeviceClient** on Android.

You can find more features integrated into our [sample apps on our Github](https://github.com/SocketMobile).

## Get the Firmware Version of a Scanner

## Java

```java
// Retrieve the firmware version of a connected device.
device.getFirmwareVersion((error, property) -> {
    if (error != null) {
        Log.e(TAG, "Get firmware version failed: " + error.getMessage());
        return;
    }
    Version version = property.getVersion();
    Log.d(TAG, "Firmware version: "
            + version.major + "."
            + version.middle + "."
            + version.minor);
});
```

## Kotlin

```kotlin
// Retrieve the firmware version of a connected device.
device.getFirmwareVersion { error, property ->
    if (error != null) {
        Log.e(TAG, "Get firmware version failed: ${error.message}")
        return@getFirmwareVersion
    }
    val version = property.version
    Log.d(TAG, "Firmware version: ${version.major}.${version.middle}.${version.minor}")
}
```

## Swift

```swift
device.getFirmwareVersionWithCompletionHandler({ result, version in
    print("Get Firmware Version: : \(version?.month ?? 0).\(version?.day ?? 0).\(version?.year ?? 0) - Result: \(result.rawValue)")
})
```

## C#

```csharp
// Retrieve the firmware version of a connected device.
// device is of type CaptureHelperDevice retrieved in DeviceArrival event
CaptureHelper.VersionResult result = await device.GetFirmwareVersionAsync();
if (result.IsSuccessful())
{
    Console.WriteLine($"Firmware version: {result.Major}.{result.Middle}.{result.Minor}");
}
```

## Dart

```dart
Future<void> getFirmwareVersion(CaptureHelperDevice device) async {
  try {
    Version version = await device.getFirmwareVersion();
    print('Firmware version: ${version.major}.${version.middle}.${version.minor}');
  } catch (err) {
    print('error while getting the firmware version: $err');
  }
}
```

## JavaScript

```javascript
// Retrieve the firmware version of a connected device.
const version = await device.getFirmwareVersion();
console.log(`Firmware version: ${version.major}.${version.middle}.${version.minor}`);
```

## Get the Friendly Name of a Scanner

In a deployment where multiple scanners are present, it is helpful to identify them with a friendly name. Here is a sample code to get the friendly name:

## Java

```java
// The friendly name is available directly when the device arrives, without a round-trip.
public void onDeviceArrival(DeviceClient device) {
    Log.d(TAG, "didNotifyArrivalForDevice: " + device.getDeviceName());
}

// OR - query the friendly name from the device at any time
device.getProperty(Property.create(Property.DEVICE_FRIENDLY_NAME), (error, property) -> {
    if (error != null) {
        Log.e(TAG, "Get friendly name failed: " + error.getMessage());
        return;
    }
    Log.d(TAG, "Friendly name: " + property.getString());
});
```

## Kotlin

```kotlin
// The friendly name is available directly when the device arrives, without a round-trip.
fun onDeviceArrival(device: DeviceClient) {
    Log.d(TAG, "didNotifyArrivalForDevice: ${device.deviceName}")
}

// OR - query the friendly name from the device at any time
device.getProperty(Property.create(Property.DEVICE_FRIENDLY_NAME)) { error, property ->
    if (error != null) {
        Log.e(TAG, "Get friendly name failed: ${error.message}")
        return@getProperty
    }
    Log.d(TAG, "Friendly name: ${property.string}")
}
```

## Swift

```swift
func didNotifyArrivalForDevice(_ device: CaptureHelperDevice, withResult result: SKTResult) {
    print("didNotifyArrivalForDevice: \(String(describing: device.deviceInfo.name))")
}

// OR - This Get friendly name method is an asynchronous call so unless you need get it at a specific time in your app flow it's better to use the example above

device.getFriendlyNameWithCompletionHandler({ result, name in
    print("Get Friendly Name: \(name ?? "") - Result: \(result.rawValue)")
})
```

## C#

```csharp
// The device name is available directly when the device arrives.
void CaptureDeviceArrival(object sender, CaptureHelper.DeviceArgs e)
{
    Console.WriteLine($"Device arrival: {e.CaptureDevice.GetDeviceInfo().Name}");
}

// OR - query the friendly name from the device at any time
CaptureHelperDevice.FriendlyNameResult result = await device.GetFriendlyNameAsync();
if (result.IsSuccessful())
{
    Console.WriteLine($"Friendly name: {result.FriendlyName}");
}
```

## Dart

```dart
// The friendly name is available directly when the device arrives, without a round-trip.
onDeviceArrival: (CaptureHelperDevice device) {
  print('didNotifyArrivalForDevice: ${device.name}');
},

// OR - query the friendly name from the device at any time
Future<void> getFriendlyName(CaptureHelperDevice device) async {
  try {
    String name = await device.getFriendlyName();
    print('Friendly name: $name');
  } catch (err) {
    print('error while getting the friendly name: $err');
  }
}
```

## JavaScript

```javascript
import { CaptureHelper } from 'react-native-capture';

// The friendly name is available directly when the device arrives, without a round-trip.
const capture = new CaptureHelper({
	onDeviceArrival: (device) => {
		console.log(`Device arrival: ${device.name}`);
	}
});

// OR - query the friendly name from the device at any time
const name = await device.getFriendlyName();
console.log(`Friendly name: ${name}`);
```

## Give a Friendly Name to a Scanner

In a deployment where multiple scanners are present, it is helpful to identify them with a friendly name that makes sense (e.g. "POS 1 Scanner"). Here is a sample code to change the friendly name:

## Java

```java
String friendlyName = "POS 1 Scanner";
Property property = Property.create(Property.DEVICE_FRIENDLY_NAME, friendlyName);
device.setProperty(property, (error, result) -> {
    if (error != null) {
        Log.e(TAG, "Setting friendly name failed: " + error.getMessage());
    }
});
```

## Kotlin

```kotlin
val friendlyName = "POS 1 Scanner"
val property = Property.create(Property.DEVICE_FRIENDLY_NAME, friendlyName)
device.setProperty(property) { error, _ ->
    if (error != null) {
        Log.e(TAG, "Setting friendly name failed: ${error.message}")
    }
}
```

## Swift

```swift
let friendlyName = "POS 1 Scanner"
device.setFriendlyName(friendlyName, withCompletionHandler: { result in
    print("Setting friendly name returned: \(result.rawValue)")
})
```

## C#

```csharp
string friendlyName = "POS 1 Scanner";
CaptureHelper.AsyncResult result = await device.SetFriendlyNameAsync(friendlyName);
if (!result.IsSuccessful())
{
    Console.WriteLine($"Setting friendly name failed: {result.Result}");
}
```

## Dart

```dart
Future<void> setFriendlyName(CaptureHelperDevice device) async {
  try {
    await device.setFriendlyName('POS 1 Scanner');
  } catch (err) {
    print('error while setting the friendly name: $err');
  }
}
```

## JavaScript

```javascript
try {
	await device.setFriendlyName('POS 1 Scanner');
} catch (err) {
	console.error('SetFriendlyName error:', err?.code ?? err?.error?.code);
}
```

## Single Partnership

By default, CaptureSDK automatically connects to available Socket Mobile Readers. However, to prevent connecting to Readers that are already assigned to another host, we have introduced the Single Partnership feature.

This ensures that only the designated host can connect to the assigned Reader, preventing unintended connections from other hosts.

You can enable the Single Partnership feature in different ways.

> **Note**
>
> It is recommended to call those properties once the Device with which you want to enable the feature is already connected to your host and has arrived with the <b>device arrival</b> event

> **Note**
>
> When using a SM Link or a Magic Dock, whatever the Single Partnership method you use, it will show the QRCode of the hardware's UUID to scan with the scanner. The Single Partnership status, in this case, is set to <b>SinglePartnershipUuid</b>. Unpairing is the same process though.

Generate a QRCode to switch the Reader to Single Partnership mode. This can be done with different methods:

### First Method

Directly from the CaptureSDK by setting the Single Partnership property and using the value **SinglePartnershipWebUI** using the following code:

## Java

```java
// Coming soon
```

## Kotlin

```kotlin
// Coming soon
```

## Swift

```swift
captureHelper.setSinglePartnership(.webUI, completionHandler: { result in
    print("setSinglePartnership with WebUI returns: \(result.rawValue)")
})
```

## C#

```csharp
// Coming soon
```

## Dart

```dart
// Coming soon
```

## JavaScript

```javascript
// Coming soon
```

This generates a random QRCode that will be the same for all the Readers for a given application using the same CaptureSDK on the same host.

Then scan the QRCode with the Reader to switch it into Single Partnership mode. Then it will connect automatically to your application.

### Second Method

Directly from the CaptureSDK by typing the information required by the web page (host serial number or any other identifying information) using the value **SinglePartnershipWebUIPrompt** using the following code:

## Java

```java
// Coming soon
```

## Kotlin

```kotlin
// Coming soon
```

## Swift

```swift
captureHelper.setSinglePartnership(.webUIPrompt, completionHandler: { result in
    print("setSinglePartnership with WebUI Prompt returns: \(result.rawValue)")
})
```

## C#

```csharp
// Coming soon
```

## Dart

```dart
// Coming soon
```

## JavaScript

```javascript
// Coming soon
```

This generates a QRCode that will be the same for all the Readers for a given application using the same CaptureSDK on the same host.

Then scan the QRCode with the Reader to switch it into Single Partnership mode. Then it will connect automatically to your application.

### Third Method

You can generate a QRCode based on a regular UUID string (e.g. 9d500cf3-5f06-4c12-9d50-0cf35f062c12).

Then with the CaptureSDK, in a short amount of time, by setting the Single Partnership property and using the value **SinglePartnershipUuid** using the following code:

## Java

```java
// Coming soon
```

## Kotlin

```kotlin
// Coming soon
```

## Swift

```swift
captureHelper.setSinglePartnership(.uuid, uuidString: "9d500cf3-5f06-4c12-9d50-0cf35f062c12", completionHandler: { result in
    print("setSinglePartnership with UUID returns: \(result.rawValue)")
})
```

## C#

```csharp
// Coming soon
```

## Dart

```dart
// Coming soon
```

## JavaScript

```javascript
// Coming soon
```

> **Note**
>
> Here are some useful error codes when using the Single Partnership feature and what you can do:
> <li><b>E_NOTFOUND(-17)</b>: The UUID is not found when using <b>SinglePartnershipWebApi</b>: Use the application Single Partnership to generate a QRCode</li>
> <li><b>E_INVALIDCONFIGURATION(-24)</b>: The device stamp cannot be generated</li>
> <li><b>E_NOTAVAILABLE(-32)</b>: The UUID is not found when using <b>SinglePartnershipWebApi</b> or the internet connection is not established: Use the application Single Partnership to generate a QRCode or enable internet access</li>
> <li><b>E_INVALIDVALUE(-41)</b>: The UUID is not found when using <b>SinglePartnershipWebUI</b>: Retry to set the property <b>SinglePartnershipWebUI</b></li>
> <li><b>E_REQUESTTIMEDOUT(-42)</b>: The device stamp and/or the device host Id are not generated when using <b>SinglePartnershipWebUI</b> or <b>SinglePartnershipWebUIPrompt</b> values: Retry to set the property with <b>SinglePartnershipWebUI</b> or <b>SinglePartnershipWebUIPrompt</b></li>
> <li><b>E_INVALIDFORMAT(-85)</b>: The UUID is not parsed correctly when using <b>SinglePartnershipWebUI</b> or <b>SinglePartnershipWebUIPrompt</b> or <b>SinglePartnershipWebApi</b>: Retry to set the property <b>SinglePartnershipWebUI</b> or <b>SinglePartnershipWebApi</b> or <b>SinglePartnershipWebUIPrompt</b></li>
> <li><b>E_CANCEL(-91)</b>: The user did close the web page. Not really an error, but a warning that the completion of the operation didn't go to the end</li>

### Reset the Single Partnership

To reset the Reader to connect to any host, reset the Single Partnership. This can be done using the following code:

## Java

```java
// Coming soon
```

## Kotlin

```kotlin
// Coming soon
```

## Swift

```swift
device.setResetSinglePartnership { result in
    print("resetSinglePartnership returns: \(result.rawValue)")
}
```

## C#

```csharp
// Coming soon
```

## Dart

```dart
// Coming soon
```

## JavaScript

```javascript
// Coming soon
```

Or you can reset the Single Partnership with 2 other methods that don't require any written code. Both display a QRCode to scan with the Reader:

#### Unpair the Reader

This method resets the scanner, which can then be discovered by any host.

![Unpair the Reader QRCode](/unpair-set-partnership.png)

#### Disconnect the Reader

This method resets the scanner in a Single Partnership mode where it is not discoverable by any host until you set a new Single Partnership QRCode through one of the three methods above.

![Disconnect the Reader QRCode](/disconnect-set-partnership.png)

### Getting the Single Partnership status

To get the status of the Single Partnership in your application use the following code:

## Java

```java
// Coming soon
```

## Kotlin

```kotlin
// Coming soon
```

## Swift

```swift
captureHelper.getSinglePartnershipStatus(withCompletionHandler: { result, status in
    print("getSinglePartnershipStatus result returns: \(result.rawValue)")
    print("getSinglePartnershipStatus status returns: \(status?.rawValue ?? 0)")
})
```

## C#

```csharp
// Coming soon
```

## Dart

```dart
// Coming soon
```

## JavaScript

```javascript
// Coming soon
```

> **Note**
>
> It may be possible that the status can be <b>SinglePartnershipDisable</b> after you set <b>SinglePartnershipWebUI</b> or <b>SinglePartnershipWebApi</b> if those requests take too long to be completed. In this case you have to repeat the preferred method.

## Stand Mode Configuration

Some scanners support the Stand Mode (e.g. S720, S740, S721, S741). The Stand Mode defines the behavior of the scanner when it's on or off the Charge Stand. There are 4 modes: **Mobile Mode**, **Stand Mode**, **Detect Mode**, **Auto Mode**.

Following is a sample code that shows how to read the stand mode of a scanner and to change it to Auto Mode if necessary:

## Java

```java
// Read the current stand mode and switch it to Auto Mode if necessary.
device.getStandConfig((error, property) -> {
    if (error != null) {
        Log.e(TAG, "Getting stand mode failed: " + error.getMessage());
        return;
    }
    if (property.getInt() != StandMode.AUTO_MODE) {
        device.setStandConfig(StandMode.AUTO_MODE, (setError, result) -> {
            if (setError != null) {
                Log.e(TAG, "Setting stand mode failed: " + setError.getMessage());
            }
        });
    }
});
```

## Kotlin

```kotlin
// Read the current stand mode and switch it to Auto Mode if necessary.
device.getStandConfig { error, property ->
    if (error != null) {
        Log.e(TAG, "Getting stand mode failed: ${error.message}")
        return@getStandConfig
    }
    if (property.int != StandMode.AUTO_MODE) {
        device.setStandConfig(StandMode.AUTO_MODE) { setError, _ ->
            if (setError != null) {
                Log.e(TAG, "Setting stand mode failed: ${setError.message}")
            }
        }
    }
}
```

## Swift

```swift
device.getStandConfigWithCompletionHandler({ result, config in
    print("Getting stand mode config returned: \(result.rawValue)")
    if var standMode = config {
        print("Stand mode is not set to auto, do it now")
        if standMode != .autoMode {
            standMode = .autoMode
            device.setStandConfig(standMode, withCompletionHandler: { (result: SKTResult) in
                print("Setting stand mode returned: \(result.rawValue)")
            })
        }
    }
})
```

## C#

```csharp
// Read the current stand mode and switch it to Auto Mode if necessary.
CaptureHelperDevice.StandConfigurationResult standResult = await device.GetStandConfigurationAsync();

if (standResult.IsSuccessful()
    && standResult.StandConfiguration != ICaptureProperty.Values.StandConfig.kAutoMode)
{
    CaptureHelper.AsyncResult result = await device.SetStandConfigurationAsync(
        ICaptureProperty.Values.StandConfig.kAutoMode);

    if (!result.IsSuccessful())
    {
        Console.WriteLine($"Setting stand mode failed: {result.Result}");
    }
}
```

## Dart

```dart
Future<void> configureStandMode(CaptureHelperDevice device) async {
  try {
    int standMode = await device.getStandConfig();
    if (standMode != StandConfig.autoMode) {
      await device.setStandConfig(StandConfig.autoMode);
    }
  } catch (err) {
    print('error while configuring the stand mode: $err');
  }
}
```

## JavaScript

```javascript
import { StandConfig } from 'react-native-capture';

// Read the current stand mode and switch it to Auto Mode if necessary.
const standConfig = await device.getStandConfig();
if (standConfig !== StandConfig.AutoMode) {
	try {
		await device.setStandConfig(StandConfig.AutoMode);
	} catch (err) {
		console.error('SetStandConfig error:', err?.code ?? err?.error?.code);
	}
}
```