Expand Minimize Picture-in-picture Power Device Status Voice Recognition Skip Back Skip Forward Minus Plus Play Search
Internet Explorer alert
This browser is not recommended for use with smartdevicelink.com, and may not function properly. Upgrade to a different browser to guarantee support of all features.
close alert
To Top Created with Sketch. To Top
To Bottom Created with Sketch. To Bottom
JavaEE Guides
Remote Control Vehicle Features

Remote Control Vehicle Features

The remote control framework allows apps to control modules such as climate, radio, seat, lights, etc., within a vehicle. Newer head units can support multi-zone modules that allow customizations based on seat location.

Note

If you are using this feature in your app, you will most likely need to request permission from the vehicle manufacturer. Not all head units support the remote control framework and only the newest head units will support multi-zone modules.

Why Use Remote Control?

Consider the following scenarios:

  • A radio application wants to use the in-vehicle radio tuner. It needs the functionality to select the radio band (AM/FM/XM/HD/DAB), tune the radio frequency or change the radio station, as well as obtain general radio information for decision making.
  • A climate control application needs to turn on the AC, control the air circulation mode, change the fan speed and set the desired cabin temperature.
  • A user profile application wants to remember users' favorite settings and apply it later automatically when the users get into the same/another vehicle.

Supported Modules

Currently, the remote control feature supports these modules:

Remote Control Modules RPC Version
Climate v4.5+
Radio v4.5+
Seat v5.0+
Audio v5.0+
Light v5.0+
HMI Settings v5.0+

The following table lists which items are in each control module.

Climate

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Climate Enable climateEnable on, off Get/Set/Notification Enabled to turn on the climate system, Disabled to turn off the climate system. All other climate items need climate enabled to work. Since v6.0
Current Cabin Temperature currentTemperature N/A Get/Notification Read only, value range depends on OEM Since v4.5
Desired Cabin Temperature desiredTemperature N/A Get/Set/Notification Value range depends on OEM Since v4.5
AC Setting acEnable on, off Get/Set/Notification Since v4.5
AC MAX Setting acMaxEnable on, off Get/Set/Notification Since v4.5
Air Recirculation Setting circulateAirEnable on, off Get/Set/Notification Since v4.5
Auto AC Mode Setting autoModeEnable on, off Get/Set/Notification Since v4.5
Defrost Zone Setting defrostZone front, rear, all, none Get/Set/Notification Since v4.5
Dual Mode Setting dualModeEnable on, off Get/Set/Notification Since v4.5
Fan Speed Setting fanSpeed 0%-100% Get/Set/Notification Since v4.5
Ventilation Mode Setting ventilationMode upper, lower, both, none Get/Set/Notification Since v4.5
Heated Steering Wheel Enabled heatedSteeringWheelEnable on, off Get/Set/Notification Since v5.0
Heated Windshield Enabled heatedWindshieldEnable on, off Get/Set/Notification Since v5.0
Heated Rear Window Enabled heatedRearWindowEnable on, off Get/Set/Notification Since v5.0
Heated Mirrors Enabled heatedMirrorsEnable on, off Get/Set/Notification Since v5.0

Radio

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Radio Enabled radioEnable true, false Get/Set/Notification Read only, all other radio control items need radio enabled to work Since v4.5
Radio Band band AM, FM, XM Get/Set/Notification Since v4.5
Radio Frequency frequencyInteger / frequencyFraction 0-1710, 0-9 Get/Set/Notification Value range depends on band Since v4.5
Radio RDS Data rdsData RdsData struct Get/Notification Read only Since v4.5
Available HD Channels availableHdChannels Array size 0-8, values 0-7 Get/Notification Read only Since v6.0, replaces availableHDs
Available HD Channels (DEPRECATED) availableHDs 1-7 (Deprecated in v6.0) (1-3 before v5.0) Get/Notification Read only Since v4.5, updated in v5.0, deprecated in v6.0
Current HD Channel hdChannel 0-7 (1-3 before v.5.0) (1-7 between v.5.0-6.0) Get/Set/Notification Since v4.5, updated in v5.0, updated in v6.0
Radio Signal Strength signalStrength 0-100% Get/Notification Read only Since v4.5
Signal Change Threshold signalStrengthThreshold 0-100% Get/Notification Read only Since v4.5
Radio State state Acquiring, acquired, multicast, not_found Get/Notification Read only Since v4.5
SIS Data sisData SisData struct Get/Notification Read only Since v5.0

Seat

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Seat Heating Enabled heatingEnabled true, false Get/Set/Notification Indicates whether heating is enabled for a seat Since v5.0
Seat Cooling Enabled coolingEnabled true, false Get/Set/Notification Indicates whether cooling is enabled for a seat Since v5.0
Seat Heating level heatingLevel 0-100% Get/Set/Notification Level of the seat heating Since v5.0
Seat Cooling level coolingLevel 0-100% Get/Set/Notification Level of the seat cooling Since v5.0
Seat Horizontal Position horizontalPosition 0-100% Get/Set/Notification Adjust a seat forward/backward, 0 means the nearest position to the steering wheel, 100% means the furthest position from the steering wheel Since v5.0
Seat Vertical Position verticalPosition 0-100% Get/Set/Notification Adjust seat height (up or down) in case there is only one actuator for seat height, 0 means the lowest position, 100% means the highest position Since v5.0
Seat-Front Vertical Position frontVerticalPosition 0-100% Get/Set/Notification Adjust seat front height (in case there are two actuators for seat height), 0 means the lowest position, 100% means the highest position Since v5.0
Seat-Back Vertical Position backVerticalPosition 0-100% Get/Set/Notification Adjust seat back height (in case there are two actuators for seat height), 0 means the lowest position, 100% means the highest position Since v5.0
Seat Back Tilt Angle backTiltAngle 0-100% Get/Set/Notification Backrest recline, 0 means the angle that back top is nearest to the steering wheel, 100% means the angle that back top is furthest from the steering wheel Since v5.0
Head Support Horizontal Position headSupportHorizontalPosition 0-100% Get/Set/Notification Adjust head support forward/backward, 0 means the nearest position to the front, 100% means the furthest position from the front Since v5.0
Head Support Vertical Position headSupportVerticalPosition 0-100% Get/Set/Notification Adjust head support height (up or down), 0 means the lowest position, 100% means the highest position Since v5.0
Seat Massaging Enabled massageEnabled true, false Get/Set/Notification Indicates whether massage is enabled for a seat Since v5.0
Massage Mode massageMode MassageModeData struct Get/Set/Notification List of massage mode of each zone Since v5.0
Massage Cushion Firmness massageCushionFirmness MassageCushionFirmness struct Get/Set/Notification List of firmness of each massage cushion Since v5.0
Seat memory memory SeatMemoryAction struct Get/Set/Notification Seat memory Since v5.0

Audio

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Audio Volume volume 0%-100% Get/Set/Notification The audio source volume level Since SDL v5.0
Audio Source source PrimaryAudioSource enum Get/Set/Notification Defines one of the available audio sources Since SDL v5.0
Keep Context keepContext true, false Set only Controls whether the HMI will keep the current application context or switch to the default media UI/APP associated with the audio source Since SDL v5.0
Equalizer Settings equalizerSettings EqualizerSettings struct Get/Set/Notification Defines the list of supported channels (band) and their current/desired settings on HMI Since SDL v5.0

Light

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Light State lightState Array of LightState struct Get/Set/Notification Since SDL v5.0

HMI Settings

Control Item RPC Item Name Value Range Type Comments RPC Version Changes
Display Mode displayMode Day, Night, Auto Get/Set/Notification Current display mode of the HMI display Since SDL v5.0
Distance Unit distanceUnit Miles, Kilometers Get/Set/Notification Distance Unit used in the HMI (for maps/tracking distances) Since SDL v5.0
Temperature Unit temperatureUnit Fahrenheit, Celsius Get/Set/Notification Temperature Unit used in the HMI (for temperature measuring systems) Since SDL v5.0

Remote Control Button Presses

The remote control framework also allows mobile applications to send simulated button press events for the following common buttons in the vehicle.

RC Module Control Button
Climate AC
AC MAX
RECIRCULATE
FAN UP
FAN DOWN
TEMPERATURE UP
TEMPERATURE DOWN
DEFROST
DEFROST REAR
DEFROST MAX
UPPER VENT
LOWER VENT
Radio VOLUME UP
VOLUME DOWN
EJECT
SOURCE
SHUFFLE
REPEAT

Integration

For remote control to work, the head unit must support SDL RPC v4.4+. In addition, your app's appHMIType must include REMOTE_CONTROL.

Multiple Modules (RPC v6.0+)

Each module type can have multiple modules in RPC v6.0+. In previous versions, only one module was available for each module type. A specific module is controlled using the unique id assigned to the module. When sending remote control RPCs to a RPC v6.0+ head unit, the moduleInfo.moduleId must be stored and provided to control the desired module. If no moduleId is set, the HMI will use the default module of that module type. When connected to <6.0 systems, the moduleInfo struct will be null, and only the default module will be available for control.

Getting Remote Control Module Information

Prior to using any remote control RPCs, you must check that the head unit has the remote control capability. As you will encounter head units that do not support remote control, or head units that do not give your application permission to read and write remote control data, this check is important.

Note

This check can be performed once your SDL app has left the HMI state of NONE. More information on how to monitor the HMI status can be found in the Understanding Permissions guide.

When connected to head units supporting RPC v6.0+, you should save this information for future use. The moduleId contained within the moduleInfo struct on each capability is necessary to control that module.

sdlManager.getSystemCapabilityManager().addOnSystemCapabilityListener(SystemCapabilityType.REMOTE_CONTROL, new OnSystemCapabilityListener() {
    @Override
    public void onCapabilityRetrieved(Object capability) {
        RemoteControlCapabilities remoteControlCapabilities = (RemoteControlCapabilities) capability;
        // Save the remote control capabilities
    }

    @Override
    public void onError(String info) {
        // Handle Error
    }
});

Getting Module Data Location and Service Areas (RPC v6.0+)

With the saved remote control capabilities struct you can get the location of the each module and the area that it services. This will map to the grid graphic below. This information is useful for creating a custom UI.

Note

This data is only available when connected to SDL RPC v6.0+ systems. On previous systems, only one module per module type was available, so the module's location didn't matter. You will not be able to build a custom UI for those cases and should use a generic UI instead.

// Get the first climate module's information
ClimateControlCapabilities firstClimateModule = remoteControlCapabilities.getClimateControlCapabilities().get(0);

String climateModuleId = firstClimateModule.getModuleInfo().getModuleId();
Grid climateModuleLocation = firstClimateModule.getModuleInfo().getModuleLocation();

You can also get an array of seats in the SeatLocationCapability.seats array. Each SeatLocation object within the seats array will have a grid parameter. The grid will tell you the location of that particular seat in the vehicle (See the graphic below).

sdlManager.getSystemCapabilityManager().addOnSystemCapabilityListener(SystemCapabilityType.SEAT_LOCATION, new OnSystemCapabilityListener() {
    @Override
    public void onCapabilityRetrieved(Object capability) {
        SeatLocationCapability seatLocationCapability = (SeatLocationCapability) capability;
        if (seatLocationCapability.getSeats() != null && seatLocationCapability.getSeats().size() > 0){
            List<SeatLocation> seats = seatLocationCapability.getSeats();
                // Save seat location capabilities
        }
    }

    @Override
    public void onError(String info) {
        // Handle Error
    }
});

The Grid

The grid system starts with the front left corner of the bottom level of the vehicle being (col=0, row=0, level=0). For example, assuming a vehicle manufactured for sale in the United States with three seats in the backseat, (0, 0, 0) would be the drivers' seat. The front passenger location would be at (2, 0, 0) and the rear middle seat would be at (1, 1, 0). The colspan and rowspan properties tell you how many rows and columns that module or seat takes up. The level property tells you how many decks the vehicle has (i.e. a double-decker bus would have 2 levels).

Car

col=0 col=1 col=2
row=0 driver's seat: {col=0, row=0, level=0, colspan=1, rowspan=1, levelspan=1} front passenger's seat : {col=2, row=0, level=0, colspan=1, rowspan=1, levelspan=1}
row=1 rear-left seat : {col=0, row=1, level=0, colspan=1, rowspan=1, levelspan=1} rear-middle seat : {col=1, row=1, level=0, colspan=1, rowspan=1, levelspan=1} rear-right seat : {col=2, row=1, level=0, colspan=1, rowspan=1, levelspan=1}

Getting Module Data

Seat location does not affect the ability to get data from a module. Once you know you have permission to use the remote control feature and you have moduleIds (when connected to RPC v6.0+ systems), you can retrieve the data for any module. The following code is an example of how to subscribe to the data of a climate module.

When connected to head units that only support RPC versions older than v6.0, there can only be one module for each module type (e.g. there can only be one climate module, light module, radio module, etc.), so you will not need to pass a moduleId.

Subscribing to Module Data

You can either subscribe to module data or receive it one time. If you choose to subscribe to module data you will receive continuous updates on the vehicle data you have subscribed to.

Note

Subscribing to the OnInteriorVehicleData notification must be done before sending the GetInteriorVehicleData request.

sdlManager.addOnRPCNotificationListener(FunctionID.ON_INTERIOR_VEHICLE_DATA, new OnRPCNotificationListener() {
    @Override
    public void onNotified(RPCNotification notification) {
        OnInteriorVehicleData onInteriorVehicleData = (OnInteriorVehicleData) notification;
        if (onInteriorVehicleData != null){
            // NOTE: If you subscribe to multiple modules, all the data will be sent here. You will have to
            // split it out based on `onInteriorVehicleData.getModuleData().getModuleType()` yourself.
            // Code
        }
    }
});

After you subscribe to the InteriorVehicleDataNotification you must also subscribe to the module you wish to receive updates for. Subscribing to a module will send a notification when that particular module is changed.

RPC < v6.0
GetInteriorVehicleData getInteriorVehicleData = new GetInteriorVehicleData(ModuleType.CLIMATE)
    .setSubscribe(true);
getInteriorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // This can now be used to retrieve data
        <#Code#>
    }
});
sdlManager.sendRPC(getInteriorVehicleData);
RPC v6.0+
GetInteriorVehicleData getInteriorVehicleData = new GetInteriorVehicleData(ModuleType.CLIMATE)
    .setModuleId(moduleID)
    .setSubscribe(true);
getInteriorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // This can now be used to retrieve data
        // Code
    }
});
sdlManager.sendRPC(getInteriorVehicleData);

After you subscribe to the InteriorVehicleDataNotification you must also subscribe to the module you wish to receive updates for. Subscribing to a module will send a notification when that particular module is changed.

Getting One-Time Data

To get data from a module without subscribing send a GetInteriorVehicleData request with the subscribe flag set to false.

RPC < v6.0
GetInteriorVehicleData interiorVehicleData = new GetInteriorVehicleData(ModuleType.CLIMATE);
interiorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // This can now be used to retrieve data
        // Code
    }
});
sdlManager.sendRPC(interiorVehicleData);
RPC 6.0+
GetInteriorVehicleData interiorVehicleData = new GetInteriorVehicleData(ModuleType.CLIMATE)
    .setModuleId("<#ModuleID#>");
interiorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // This can now be used to retrieve data
        // Code
    }
});
sdlManager.sendRPC(interiorVehicleData);

Setting Module Data

Not only do you have the ability to get data from these modules, but, if you have the right permissions, you can also set module data.

Setting The User's Seat (RPC v6.0+)

Before you attempt to take control of any module, you should have your user select their seat location as this affects which modules they have permission to control. You may wish to show the user a map or list of all available seats in your app in order to ask them where they are located. See Getting Module Data Location and Service Areas for information useful in creating a custom UI showing module location and service area. The following example is only meant to show you how to access the available data and not how to build your UI/UX.

When the user selects their seat, you must send an SetGlobalProperties RPC with the appropriate userLocation property in order to update that user's location within the vehicle (The default seat location is Driver).

SetGlobalProperties seatLocation = new SetGlobalProperties()
    .setUserLocation(selectedSeat);
seatLocation.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Seat location updated
    }
});
sdlManager.sendRPC(seatLocation);

Some OEMs may wish to ask the driver for consent before a user can control a module. The GetInteriorVehicleDataConsent RPC will alert the driver in some OEM head units if the module is not free (another user has control) and allowMultipleAccess (multiple users can access/set the data at the same time) is true. The allowMultipleAccess property is part of the moduleInfo in the module object.

Check the allowed property in the GetInteriorVehicleDataConsentResponse to see what modules can be controlled. Note that the order of the allowed array is 1-1 with the moduleIds array you passed into the GetInteriorVehicleDataConsent RPC.

Note

You should always try to get consent before setting any module data. If consent is not granted you should not attempt to set any module's data.

GetInteriorVehicleDataConsent getInteriorVehicleDataConsent = new GetInteriorVehicleDataConsent(moduleType, moduleIDs);
getInteriorVehicleDataConsent.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        GetInteriorVehicleDataConsentResponse getInteriorVehicleDataConsentResponse = (GetInteriorVehicleDataConsentResponse) response;
        List<Boolean> allowed = getInteriorVehicleDataConsentResponse.getAllowances();
        // Allowed is an array of true or false values
    }
});
sdlManager.sendRPC(getInteriorVehicleDataConsent);

Controlling a Module

Below is an example of setting climate control data. It is likely that you will not need to set all the data as in the code example below. When connected to RPC v6.0+ systems, you must set the moduleId in SetInteriorVehicleData.setModuleData. When connected to < v6.0 systems, there is only one module per module type, so you must only pass the type of the module you wish to control.

When you received module information above in Getting Remote Control Module Information on RPC v6.0+ systems, you received information on the location and serviceArea of the module. The permission area of a module depends on that serviceArea. The location of a module is like the seats array: it maps to the grid to tell you the physical location of a particular module. The serviceArea maps to the grid to show how far that module's scope reaches.

For example, a radio module usually serves all passengers in the vehicle, so its service area will likely cover the entirety of the vehicle grid, while a climate module may only cover a passenger area and not the driver or the back row. If a serviceArea is not included, it is assumed that the serviceArea is the same as the module's location. If neither is included, it is assumed that the serviceArea covers the whole area of the vehicle. If a user is not sitting within the serviceArea's grid, they will not receive permission to control that module (attempting to set data will fail).

RPC < v6.0
Temperature temp = new Temperature(TemperatureUnit.FAHRENHEIT, 74.1f);

ClimateControlData climateControlData = new ClimateControlData()
    .setAcEnable(true)
    .setAcMaxEnable(true)
    .setAutoModeEnable(false)
    .setCirculateAirEnable(true)
    .setCurrentTemperature(temp)
    .setDefrostZone(DefrostZone.FRONT)
    .setDualModeEnable(true)
    .setFanSpeed(2)
    .setVentilationMode(VentilationMode.BOTH)
    .setDesiredTemperature(temp);

ModuleData moduleData = new ModuleData(ModuleType.CLIMATE)
    .setClimateControlData(climateControlData);

SetInteriorVehicleData setInteriorVehicleData = new SetInteriorVehicleData(moduleData);
setInteriorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Code
    }
});
sdlManager.sendRPC(setInteriorVehicleData);
RPC 6.0+
Temperature temp = new Temperature(TemperatureUnit.FAHRENHEIT, 74.1f);

ClimateControlData climateControlData = new ClimateControlData()
    .setAcEnable(true)
    .setAcMaxEnable(true)
    .setAutoModeEnable(false)
    .setCirculateAirEnable(true)
    .setCurrentTemperature(temp)
    .setDefrostZone(DefrostZone.FRONT)
    .setDualModeEnable(true)
    .setFanSpeed(2)
    .setVentilationMode(VentilationMode.BOTH)
    .setDesiredTemperature(temp);

ModuleData moduleData = new ModuleData(ModuleType.CLIMATE)
    .setModuleId(moduleId)
    .setClimateControlData(climateControlData);

SetInteriorVehicleData setInteriorVehicleData = new SetInteriorVehicleData(moduleData);
setInteriorVehicleData.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Code
    }
});
sdlManager.sendRPC(setInteriorVehicleData);

Button Presses

Another unique feature of remote control is the ability to send simulated button presses to the associated modules, imitating a button press on the hardware itself. Simply specify the module, the button, and the type of press you would like to simulate.

RPC < 6.0
ButtonPress buttonPress = new ButtonPress(ModuleType.CLIMATE, ButtonName.EJECT, ButtonPressMode.SHORT);
buttonPress.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Code
    }
});
sdlManager.sendRPC(buttonPress);
RPC 6.0+
ButtonPress buttonPress = new ButtonPress(ModuleType.CLIMATE, ButtonName.EJECT, ButtonPressMode.SHORT)
    .setModuleId("<#ModuleID#>");
buttonPress.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Code
    }
});
sdlManager.sendRPC(buttonPress);

Releasing the Module (RPC v6.0+)

When the user no longer needs control over a module, you should release the module so other users can control it. If you do not release the module, other users who would otherwise be able to control the module may be rejected from doing so.

ReleaseInteriorVehicleDataModule releaseInteriorVehicleDataModule = new ReleaseInteriorVehicleDataModule(<#ModuleType#>)
    .setModuleId(moduleID);
releaseInteriorVehicleDataModule.setOnRPCResponseListener(new OnRPCResponseListener() {
    @Override
    public void onResponse(int correlationId, RPCResponse response) {
        // Module Was Released
    }
});
sdlManager.sendRPC(releaseInteriorVehicleDataModule);
View on GitHub.com
Previous Section Next Section