# Lovense Toy component for Android

## Getting Started

### Installation Via Source

1. Add the file of `lovense.aar` to libs file on your app module.
2. Add the following lines to `build.gradle` on your app module:

```gradle
dependencies {  
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
  
    // toy sdk need implementation all kits of below 
    implementation 'org.greenrobot:eventbus:3.3.1'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.tencent:mmkv:1.3.7'
    implementation 'androidx.room:room-runtime:2.5.0-alpha01'
    implementation 'com.github.getActivity:XXPermissions:18.3'

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
    implementation 'me.jessyan:retrofit-url-manager:1.4.0'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.20'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

    implementation 'androidx.core:core-ktx:1.13.1'
}
```

#### ProGuard

Add proguard in your `proguard-rules.pro`

##### SDK

```
# Lovense-SDK
-keep class com.lovense.sdklibrary.** { *; }
-keep class com.component.** { *; }
```

##### Third-party libraries

```
#eventBus
-keep class org.greenrobot.eventbus.** { *; }
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(Java.lang.Throwable);
}

# Gson
-keep class com.google.gson.** { *; }
-keepattributes *Annotation*
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
}

# MMKV
-keep class com.tencent.mmkv.** { *; }

# Room Database
-keep class androidx.room.** { *; }
-keep @androidx.room.* class * { *; }
-keepclassmembers class * {
    @androidx.room.ColumnInfo <fields>;
    @androidx.room.PrimaryKey <fields>;
}

# XXPermissions
-keep class com.github.getactivity.xxpermissions.** { *; }

# Retrofit
-keep interface com.squareup.retrofit2.** { *; }
-keepattributes *Annotation*
-keepattributes Signature,Exceptions
-keep class com.squareup.retrofit2.converter.gson.** { *; }

# RxJava & RxAndroid
-keep class io.reactivex.** { *; }
-keep class io.reactivex.android.** { *; }

# AndroidX
-keep class androidx.core.** { *; }
```

### Quick Tutorial

Init the sdk with token(apply from lovense)

```kotlin
Lovense.getInstance(application).setDeveloperToken("Your Token")
```

Enable or disable logging (default: false)

```kotlin
Lovense.getInstance(application).setLogEnable(true)
```

Start or Stop search toy

```kotlin
Lovense.getInstance(application).searchToys(object : OnSearchToyListener {
    override fun onSearchToy(toy: LovenseToy) {
      
    }

    override fun finishSearch() {
  
    }

    override fun onError(msg: LovenseError) {

    }
})
      
Lovense.getInstance(application).stopSearching()      
```

Request Connected or Disconnect toy

```kotlin
Lovense.getInstance(application).connectToy(toyId, object : OnConnectListener {
    override fun onConnect(toyId: String, status: String) {
         when (status) {
             LovenseToy.STATE_CONNECTING -> {}
             LovenseToy.STATE_CONNECTED -> {}
             LovenseToy.STATE_FAILED -> {}
             LovenseToy.SERVICE_DISCOVERED -> {}
         }
    }

    override fun onError(msg: LovenseError) {

    }
})
      
Lovense.getInstance(application).disconnect(toyId)      
```

Send command to toy

```kotlin
// Send command that no need params
Lovense.getInstance(application).sendCommand(toyId, CommandType.ROTATE)

// Send command with one param
Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE1, 20) 

// Send command with multily params
Lovense.getInstance(application).sendCommand(toyId, CommandType.SPEED, intArrayOf(level, minPos, maxPos)) 
```

Get supported commands of toy

```kotlin
Lovense.getInstance(application).getSupportedCommands(toyId): ArrayList<CommandType>?
```

### Command list

From the SDK version of 1.4.5, we suggest to use CommandType which contain all toy's commands


| Command               | Description                                                                                                                                                                                                                                                                                                                  |
| --------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| VIBRATE               | Vibrate the toy. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                                     |
| ROTATE                | Rotate the toy. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                                      |
| ROTATE_CLOCKWISE      | Rotate clockwise. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                                    |
| ROTATE_ANTI_CLOCKWISE | Rotate anti-clockwise. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                               |
| ROTATE_CHANGE         | Change the rotation direction                                                                                                                                                                                                                                                                                                |
| AIR_IN                | Airbag inflation for n seconds. The parameter must be between 1 and 3.                                                                                                                                                                                                                                                       |
| AIR_OUT               | Airbag deflation for n seconds. The parameter must be between 1 and 3.                                                                                                                                                                                                                                                       |
| AIR_AUTO              | Cycle airbag inflation for n seconds and air deflation for n seconds. The parameter must be between 0 and 3 (0 means stop).                                                                                                                                                                                                  |
| VIBRATE1              | Activate the first vibrator at level n. The parameter must be between 0 and 20.                                                                                                                                                                                                                                              |
| VIBRATE2              | Activate the second vibrator at level n. The parameter must be between 0 and 20.                                                                                                                                                                                                                                             |
| VIBRATE_FLASH         | Vibrate the toy at level n and flash the light at the same time.                                                                                                                                                                                                                                                             |
| FLASH                 | Flash the light 3 times                                                                                                                                                                                                                                                                                                      |
| LIGHT_OFF             | Turn off the light (saved permanently).                                                                                                                                                                                                                                                                                      |
| LIGHT_ON              | Turn on the light (saved permanently).                                                                                                                                                                                                                                                                                       |
| GET_LIGHT_STATUS      | Get the light's status (1: on, 0: off)                                                                                                                                                                                                                                                                                       |
| ALIGHT_OFF            | Turn off Domi/Domi 2 light (saved permanently)                                                                                                                                                                                                                                                                               |
| ALIGHT_ON             | Turn on the Domi/Domi 2 light (saved permanently)                                                                                                                                                                                                                                                                            |
| GET_ALIGHT_STATUS     | Get the Domi/Domi 2 light status (1: on, 0: off)                                                                                                                                                                                                                                                                             |
| GET_BATTERY           | Get battery status                                                                                                                                                                                                                                                                                                           |
| GET_DEVICE_TYPE       | Get device/toy information                                                                                                                                                                                                                                                                                                   |
| START_MOVE            | Start tracking the toy movement (0-4)                                                                                                                                                                                                                                                                                        |
| STOP_MOVE             | Stop tracking the toy movement                                                                                                                                                                                                                                                                                               |
| PRESET                | Vibrate with a preset pattern. Patterns range from 1 to 10. n=0 will stop vibrations.                                                                                                                                                                                                                                        |
| FLEXER_VIBRATE        | Control the vibration of Flexer. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                     |
| FLEXER_FINGER         | Control the fingering motion of Flexer. The parameter must be between 0 and 20.                                                                                                                                                                                                                                              |
| VIBRATE3              | Activate the third vibrator at level n. The parameter must be between 0 and 20.                                                                                                                                                                                                                                              |
| THRUST                | Thrust the toy. The parameter must be between 0 and 20.                                                                                                                                                                                                                                                                      |
| MULTIPLY              | Control three vibrators with different strength level for Lapis. Level range is 0 - 20, set level to -1 for remaining strength level from previous function.                                                                                                                                                                 |
| SOLACE                | Control thrust and depth level separately for Solace. Level range is 0 - 20 for thrusting, and 1-3 for depth. Set level to 0 for thrusting will make the toy stop no matter what is the level value for depth. If the depth is not specified, the toy will act with the set thrusting level and default depth level value 1. |
| GET_TOUCH_MODE        | Get current mode from 'mission2' toy. The result will be one of [0, 1, 2, 3, 5].                                                                                                                                                                                                                                             |
| SET_TOUCH_MODE        | Set current mode to 'mission2' toy. The parameter must be one of [0, 1, 2, 3, 5]                                                                                                                                                                                                                                             |
| GET_TOUCH_VALUE       | Get touch attenuation value from 'mission2' toy. That will return all level.                                                                                                                                                                                                                                                 |
| SET_TOUCH_VALUE       | Set touch attenuation value to 'mission2' toy. The parameter level must be between 1 and 3, attenuation value must be between 0 and 100.                                                                                                                                                                                     |
| GET_TOUCH_LEVEL       | Get touch attenuation level from 'mission2' toy. The result will be between 1 and 3.                                                                                                                                                                                                                                         |
| SET_TOUCH_LEVEL       | Set touch attenuation level to 'mission2' toy. The parameter must be between 1 and 3.                                                                                                                                                                                                                                        |
| GET_SITE              | Get current position from the 'solacePro' toy.                                                                                                                                                                                                                                                                               |
| SET_SITE              | Set position to the 'solacePro' toy. The parameter must be between 0 and 100.                                                                                                                                                                                                                                                |
| SPEED                 | Thrust the 'solacePro' toy with fixed interval and a certain speed. Three parameters: speed, start and end. The parameter must be between 0 and 20.                                                                                                                                                                          |
| START_FEEDBACK        | Start tracking the 'solacePro' toy movement. Return data : speed, direction and position.                                                                                                                                                                                                                                    |
| STOP_FEEDBACK         | Stop tracking the 'solacePro' toy movement.                                                                                                                                                                                                                                                                                  |
| GET_AUTO_SWITCH       | Get auto switch status via OnCallBackGetAutoSwitchListener. Returns two Int parameters: autoStop and reconnectToLastLevel, where each value is either 1 (on) or 0 (off)                                                                                                                                                      |
| SET_AUTO_SWITCH       | Set auto switch status with two parameters: 1 (on) or 0 (off). The IntArray consists of two values: [autoStop, reconnectToLastLevel].                                                                                                                                                                                        |
| OSCILLATE             | Oscillate the toys of 'gush2' and 'osic3'. The parameter must be between 0 and 20.                                                                                                                                                                                                                                           |
| SET_LIGHT_COLOR       | Set the led light color to the 'lush4' toy. The parameter is LushLightColorType.value.                                                                                                                                                                                                                                       |
| GET_LIGHT_COLOR       | Get the led light color from the 'lush4' toy.                                                                                                                                                                                                                                                                                |

### Callback list


| Callback                         | Description                                                                                    |
| -------------------------------- |------------------------------------------------------------------------------------------------|
| OnSearchToyListener              | Found toy list                                                                                 |
| OnConnectListener                | Toy connected status                                                                           |
| OnSendCommandErrorListener       | Send Command error, extends OnCallBack                                                         |
| OnCallBackBatteryListener        | Battery status, extends OnCallBack @Deprecated("", ReplaceWith("OnCallBackBatteryV2Listener")) |
| OnCallBackBatteryV2Listener      | This callback returns the current battery level and the working status of the device (isWork). |
| OnCallBackDeviceTypListener      | Device information, extends OnCallBack                                                         |
| OnCallBackLightStatusListener    | Light indicator, extends OnCallBack                                                            |
| OnCallBackAidLightStatusListener | Domi/Domi 2 light indicator, extends OnCallBack                                                |
| OnCallBackMoveListener           | Toy movement updates, extends OnCallBack                                                       |
| OnCommandSuccessListener         | Command success, extends OnCallBack                                                            |
| OnCommandErrorListener           | Command Error, extends OnCallBack                                                              |
| OnCallBackMission2Listener       | All command callbacks from 'mission2' toy                                                      |
| OnCallBackSolaceProListener      | All command callbacks from 'solacePro' toy                                                     |
| OnCallBackGetAutoSwitchListener  | Get auto switch status, extends OnCallBack                                                     |
| OnLightColorListener             | Get toy's led light colorType, extends OnCallBack (Lush4)                                      |

#### 1、OnCallBackBatteryV2Listener

This callback returns the current battery level and the working status of the device (isWork).

* battery: The current battery level.
* isWork: Indicates whether the device is currently working (e.g., vibrating).
  When isWork is true, the battery level might be inaccurate due to ongoing device activity. In this case, the battery property of the Toy class will not be updated. When isWork is false, the battery level is considered accurate, and the Toy's battery property will be updated accordingly.

### Toy Supported Commands list


| Name         | VIBRATE | VIBRATE1 | VIBRATE2 | VIBRATE3 | ROTATE | ROTATE_CLOCKWISE | ROTATE_ANTI_CLOCKWISE | ROTATE_CHANGE | AIR_IN | AIR_OUT | AIR_AUTO | VIBRATE_FLASH | FLASH | LIGHT_OFF | LIGHT_ON | GET_LIGHT_STATUS | ALIGHT_OFF | ALIGHT_ON | GET_ALIGHT_STATUS | GET_BATTERY | GET_DEVICE_TYPE | START_MOVE | STOP_MOVE | PRESET | FLEXER_VIBRATE | FLEXER_FINGER | THRUST | MULTIPLY | GET_TOUCH_MODE | SET_TOUCH_MODE | GET_TOUCH_VALUE | SET_TOUCH_VALUE | GET_TOUCH_LEVEL | SET_TOUCH_LEVEL | SPEED | OSCILLATE | SET_LIGHT_COLOR | GET_LIGHT_COLOR | GET_SITE | SET_SITE | START_FEEDBACK | STOP_FEEDBACK | GET_AUTO_SWITCH | SET_AUTO_SWITCH  |
| ------------ | ------- | -------- | -------- | -------- | ------ | ---------------- | --------------------- | ------------- | ------ | ------- | -------- | ------------- | ----- | --------- | -------- | ---------------- | ---------- | --------- | ----------------- | ----------- | --------------- | ---------- | --------- | ------ | -------------- | ------------- | ------ | -------- | -------------- | -------------- | --------------- | --------------- | --------------- | --------------- | ----- | --------- | --------------- | --------------- | -------- | -------- | -------------- | ------------- | --------------- |------------------|
| Ambi         | ✓       |          |          |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Calor        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          | ✓              | ✓             | ✓               | ✓                |
| Diamo        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Dolce        | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Domi         | ✓       |          |          |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                | ✓          | ✓         | ✓                 | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Domi2        | ✓       |          |          |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                | ✓          | ✓         | ✓                 | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Edge         | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Edge2        | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Exomoon      | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Ferri        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Flexer       | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      | ✓              | ✓             |        | ✓        |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Gemini       | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Gravity      | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               | ✓      |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Gush         | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Gush2        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       | ✓         |                 |                 |          |          |                |               | ✓               | ✓                |
| Hush         | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Hush2        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Hyphy        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Lapis        | ✓       | ✓        | ✓        | ✓        |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        | ✓        |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Lush         | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Lush2        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Lush3        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Lush4        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           | ✓               | ✓               |          |          |                |               | ✓               | ✓                |
| Max          | ✓       |          |          |          |        |                  |                       |               | ✓      | ✓       | ✓        |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               | ✓          | ✓         | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Max2         | ✓       |          |          |          |        |                  |                       |               | ✓      | ✓       | ✓        |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               | ✓          | ✓         | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          | ✓              | ✓             | ✓               | ✓                |
| MiniXMachine | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               | ✓      |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Mission      | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Mission2     | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          | ✓              | ✓              | ✓               | ✓               | ✓               | ✓               |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Nora         | ✓       |          |          |          | ✓      | ✓                | ✓                     | ✓             |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               | ✓          | ✓         | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Osci         | ✓       |          |          |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Osci2        | ✓       |          |          |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Osci3        | ✓       | ✓        | ✓        |          |        |                  |                       |               |        |         |          | ✓             | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        | ✓        |                |                |                 |                 |                 |                 |       | ✓         |                 |                 |          |          |                |               | ✓               | ✓                |
| Ridge        | ✓       |          |          |          | ✓      | ✓                | ✓                     | ✓             |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        | ✓        |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Solace       | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           |        |                |               | ✓      | ✓        |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          | ✓              | ✓             | ✓               | ✓                |
| SolacePro    | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           |        |                |               | ✓      | ✓        |                |                |                 |                 |                 |                 | ✓     |           |                 |                 | ✓        | ✓        | ✓              | ✓             |                 |                  |
| Tenera       | ✓       | ✓        |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Tenera2      | ✓       | ✓        |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |
| Vulse        | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               |        |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          | ✓              | ✓             | ✓               | ✓                |
| XMachine     | ✓       |          |          |          |        |                  |                       |               |        |         |          |               | ✓     | ✓         | ✓        | ✓                |            |           |                   | ✓           | ✓               |            |           | ✓      |                |               | ✓      |          |                |                |                 |                 |                 |                 |       |           |                 |                 |          |          |                |               | ✓               | ✓                |