Show / Hide Table of Contents

# Device Operations

## Taking measurements

Once the device is connected and in an `Idle` state, it is possible to take measurements using `MeasureAsync()`:

- The variable number of arguments `modes` argument may be omitted to run measurements in all modes supported by the device. This is the recommended option.
- If `modes` arguments are supplied, measurements will be provided only for the specified scan modes. In most cases, this will not speed up the measurement cycle time, so this is not recommended.
- The measurement operation is asynchronous. While the measurement is in progress, no other commands can be sent to the Nix device.
- Results of the measurement operation are provided as a `DeviceResult` containing two properties:
  - A `CommandStatus` enum, which will be `Success` for a successful operation.
  - A dictionary containing the measurement values as `IMeasurementData` instances. The keys of this dictionary correspond to the `ScanMode` for each measurement value.
  - Refer to Handling Measurement Data for notes on interpreting the measurement data.
  - The supported scan modes for a particular device are provided in the `SupportedModes` list, or can be checked by calling `IsModeSupported()`. The expected results by device are shown below:

Device Type | M0 | M1 | M2
--- | --- | --- | ---
Mini | ☐ | ☐ | ☑
Mini 2 | ☐ | ☐ | ☑
Mini 3 | ☐ | ☐ | ☑
Pro | ☐ | ☐ | ☑
Pro 2 | ☐ | ☐ | ☑
QC | ☐ | ☐ | ☑
Spectro 2 (F1.0.0) | ☑ | ☑ | ☐
Spectro 2 (F2.0.0) | ☑ | ☑ | ☑
Spectro L | ☑ | ☑ | ☑

    // Connected device instance
    IDeviceCompat Device;

    // Start the measurement
    var measureTask = Device.MeasureAsync();

    // Show progress indicator here if desired
    // ...

    // Wait for completion
    var result = await measureTask;

    // Handle status
    switch (result.Status)
    {
        case CommandStatus.Success:
            // Successful operation, handle measurement data here
            // Measurements are available via result.Measurements
            // ...
            break;
        case CommandStatus.ErrorNotReady:
            // Scan did not complete because the device was busy
            // ...
            break;
        case CommandStatus.ErrorNotSupported:
            // Scan did not complete because this device does not
            // support this command
            // ...
            break;
        case CommandStatus.ErrorLowPower:
            // Scan did not complete because the battery level is
            // too low
            // ...
            break;
        case CommandStatus.ErrorTimeout:
            // Timeout when waiting for result
            // ...
            break;
        case CommandStatus.ErrorAmbientLight:
            // Scan did not complete because ambient light leakage
            // was detected
            // ...
            break;
        case CommandStatus.ErrorLicense:
            // Scan did not complete because of a license issue
            // Check LicenseManager.State
            // ...
        default:
            // Did not complete because of other internal error
            // ...
            break;
    }

## Performing in-field profiling / calibration with reference tile

Certain device types support in-field profiling or calibration using a provided reference tile. This process requires first decoding a string from the QR code attached to the reference tile and then directing the user to measure the same tile. Any necessary adjustments/corrections are performed internally by the SDK and/or the Nix device firmware itself.

- The in-field calibration procedure may be performed as often or seldom as desired by the user. However, the `FieldCalibrationDue` flag indicates whether or not in-field calibration is recommended for the connected device.
  - This flag is updated after each regular measurement
  - This flag is determined automatically by both elapsed time and ambient temperature change
- The `SupportsFieldCalibration` property indicates whether or not a connected device supports this feature. The expected result by device are shown below:

Device Type | Supported
--- | ---
Mini | ☐
Mini 2 | ☐
Mini 3 | ☑
Pro | ☐
Pro 2 | ☐
QC | ☑
Spectro 2 | ☑
Spectro L | ☑

The steps to perform in-field profiling include:

1. Decode the QR code printed on the device reference tile and interpret as a string. Do not parse this data further.
   - Note: In addition to the string encoded in the tile QR code, Spectro 2 devices can also use the last five characters of the code printed inside the reference tile case as the `tileString`.
2. Check if the parsed data is valid using `IsTileStringValid()`. If valid, continue to the next step.
3. Instruct the user to place the device on the reference tile.
4. Using the tile string, run the in-field calibration routine using `RunFieldCalibration()` and await task completion.

- While the operation is in progress, no other commands can be sent to the Nix device (wait for task to finish).

    // Connected device instance
    IDeviceCompat Device;

    // String decoded from the reference tile. Note that Spectro 2 devices
    // can also use the last 5 characters printed inside the tile case
    string tileString;

    if (Device.IsTileStringValid(tileString)
    {
        // Tile string is valid, prompt user to place device on tile
        // ...

        // Start operation
        var calibrationTask = Device.RunFieldCalibrationAsync(tileString);

        // Show progress indicator here if desired
        // ...

        // Wait for completion
        var result = await calibrationTask;

        // Handle status
        switch (result.Status)
        {
            case CommandStatus.Success:
                // Successful operation
                // ...
                break;
            case CommandStatus.WarningTemperature:
                // Completed successfully, but ambient temperature is outside
                // of the recommended range
                // ...
                break;
            case CommandStatus.ErrorScanDelta:
                // Operation failed because the measured value of the
                // reference tile is too far from the expected value
                // (high delta E)
                // ...
                break;
            case CommandStatus.ErrorNotReady:
                // Scan did not complete because the device was busy
                // ...
                break;
            case CommandStatus.ErrorNotSupported:
                // Scan did not complete because this device does not
                // support this command
                // ...
                break;
            case CommandStatus.ErrorInvalidArgument:
                // Scan did not complete because the tileString is
                // invalid
                // ...
                break;
            case CommandStatus.ErrorLowPower:
                // Scan did not complete because the battery level is
                // too low
                // ...
                break;
            case CommandStatus.ErrorTimeout:
                // Timeout when waiting for result
                // ...
                break;
            case CommandStatus.ErrorAmbientLight:
                // Scan did not complete because ambient light leakage
                // was detected
                // ...
                break;
            case CommandStatus.ErrorLicense:
                // Scan did not complete because of a license issue
                // Check LicenseManager.State
                // ...
            default:
                // Other internal error
                // ...
                break;
        }
    }
    else
    {
        // Tile string is not valid, try again
        // ...
    }

## Other device options

Some Nix devices support certain `boolean` options. These options are set to be enabled by default (if supported) and do not usually need to be changed:

- Applying temperature compensation
  - Current state: `TemperatureCompensationEnabled`
  - Is supported?: `SupportsTemperatureCompensation`
- Applying in-field calibration
  - Current state: `FieldCalibrationEnabled`
  - Is supported?: `SupportsFieldCalibration`
- Using on-device haptic feedback
  - Current state: `HapticFeedbackEnabled`
  - Is supported?: `SupportsHapticFeedback`
- Using on-device RGB feedback
  - Current state: `RgbFeedbackEnabled`
  - Is supported?: `SupportsRgbFeedback`

A summary of device support is shown below, but can be checked at runtime (see notes above).

Device type | Temp comp. | Field cal. | Haptic | RGB
--- | --- | --- | --- | ---
Mini | ☐ | ☐ | ☐ | ☐
Mini 2 | ☑ | ☐ | ☐ | ☐
Mini 3 | ☑ | ☑ | ☐ | ☑
Pro | ☐ | ☐ | ☐ | ☐
Pro 2 | ☑ | ☐ | ☐ | ☐
QC | ☑ | ☑ | ☐ | ☐
Spectro 2 | ☑ | ☑ | ☑ | ☑
Spectro L | ☑ | ☑ | ☑ | ☑

Changing any of these options may require communication with the device itself and is an asynchronous operation, with the status of the operation provided via a `DeviceResult`.

- To enable or bypass temperature compensation, see `SetTemperatureCompensationEnabledAsync`
- To enable or bypass applying in-field calibration, see `SetFieldCalibrationEnabledAsync`
- To enable or disable haptic feedback, see `SetHapticFeedbackEnabledAsync`
- To enable or disable RGB feedback, see `SetRgbFeedbackEnabledAsync`

## Other device properties

The `IDeviceCompat` interface defines other fixed properties that can be read once the device has connected and reached an idle state. These include, but are not limited to:

- `ExtPowerState`: status of external power connection / charging
- `BatteryLevel`: current battery level, `null` is not available
- `FirmwareVersion`: device firmware revision
- `HardwareVersion`: device hardware revision
- `SoftwareVersion`: device software revision
- `SerialNumber`: device serial number
- `Note`: device allocation / production code
- `ProvidesSpectral`: indicates whether or not this device provides spectral data
- `ProvidesDensity`: indicates whether or not this device provides density data
- `SupportedModes`: list of supported measurement modes for this device
- `SupportedReferences`: list of supported reference white values provided by the measurement data from this device

##### Important

The `ProvidesDensity` and `ProvidesSpectral` properties indicate whether or not the hardware device is capable of providing these data types. However, these measurements will only be available if these features are enabled by the current license. See Other license properties for more details.

## Next steps

- Handling Measurement Data