Device Preferences
Click here to jump to the list of standard Device Preferences.
A Device Preference is a configuration that enables users to customize the behavior of their device. A Device Preference is typically set to provide users with a way to tweak their device, and may optionally include a default value. Users can change a Device Preference to customize their device by tapping their device in the SmartThings app, tapping the overflow (3-dot) menu icon, and tapping settings.
Device Preferences may be defined one of two ways:
- Explicitly, similar to Custom Capabilities, as a standalone entity
- Embedded directly into the Device Profile of the device
Explicit Device Preferences
Explicit Device Preferences allow users to author a single Preference for use by many devices.
Device Preferences defined explicitly will always be namespaced under the author's personal Namespace. Device Preferences that are defined this way are not versioned, and Device Profiles that integrate these Preferences do not get updated if the Preference is updated - the Profile will always have the same version of the Device Preference it had when it was added.
In order to include Explicit Device Preferences for use with a device you will need to tag the profiles that need the Preference as using it. This is done within each profile YAML file in the driver package. Here is a simple profile example using one of these Preferences:
name: preference-profile
components:
- id: main
capabilities:
- id: temperatureMeasurement
version: 1
preferences:
- preferenceId: tempOffset
explicit: true
For common use cases, SmartThings has developed a number of standard Device Preferences that may be integrated into devices. The current set of Standard Device Preferences may be found here.
Standard Device Preferences are contained under the smartthings
namespace. However, when accessing a standard Preference, no namespace is required to be given. Device Preferences authored by users will use the namespace owned by the user.
Embedded Device Preferences
To simplify the process of creating unique Preferences relevant only for a specific model of a device, a Device Preference may be defined directly within a Device Profile.
Embedded Device Preferences are unique to an individual Device Profile. They are defined directly in the Device Profile of the device that will be using the Preference. These Preferences and are not versioned, shareable, or update-able; the Preference exists only within the Device Profile. The Preference also includes additional information about the type and limits of the Preference.
Below is an example profile YAML file using an Embedded Preference:
name: preference-profile
components:
- id: main
capabilities:
- id: switch
version: 1
- id: battery
version: 1
categories:
- name: RemoteController
preferences:
- title: "IP Address"
name: ipAddress
description: "IP address of the Pi-Hole"
required: true
preferenceType: string
definition:
minLength: 7
maxLength: 15
stringType: text
default: localhost
The preferenceId
(and thus what you will use to reference the Preference from the driver) will be the name you define in the Preference definition.
Device Preference Value Types
Visit the Device Preferences Reference section for a list of Preferences and their types.
A Device Preference's value can be one of five types:
- Boolean
- Number
- Integer
- String
- Enumeration
All Device Preferences must have at minimum three required fields:
-
title
: The Device Preference Title must conform to Custom Capability naming conventions. -
preferenceType
: This field is a constant based on the type of Device Preference. Must be one of:boolean
,number
,integer
,string
, orenumeration
-
definition
: This block is required, but may be empty if no further customization is required.
Optional fields that apply to all Preference types include:
-
description
: Describes the Device Preference. -
required
: A Boolean value that represents whether this Preference must be set. Default:false
-
definition.default
: The default value for this Preference if the user does not set the Preference.
Boolean Preference
{
"title": "string",
"description": "string",
"required": "boolean",
"preferenceType": "boolean",
"definition": {
"default": "true" or "false"
}
}
Boolean Preferences must have a preferenceType
of boolean
.
Boolean Preferences must have a definition
block, but may be empty if default
does not need to be set.
Number Preference
{
"title": "string",
"description": "string",
"required": "boolean",
"preferenceType": "number",
"definition": {
"minimum": "a number",
"maximum": "a number",
"default": "a number"
}
}
Number Preferences must have a preferenceType
of number
.
Number Preferences may optionally have a minimum
and maximum
number value, that define the lower and upper bound
constraint this number may be set to.
Integer Preference
{
"title": "string",
"description": "string",
"required": "boolean",
"preferenceType": "integer",
"definition": {
"minimum": "an integer",
"maximum": "an integer",
"default": "an integer"
}
}
Integer Preferences must have a preferenceType
of integer
.
Replace "integer"
with your desired integer value. Integer Preferences may optionally define a minimum
and maximum
number value, that define the lower and upper bound
constraint this integer may be set to.
String Preference
{
"title": "string",
"description": "string",
"required": "boolean",
"preferenceType": "string",
"definition": {
"stringType": "string",
"minLength": "integer",
"maxLength": "integer",
"default": "string"
}
}
String Preferences must have a preferenceType
of string
.
stringType
is a required field, and must be one of 'text', 'paragraph', or 'password'.
String Preferences may optionally define a minLength
and maxLength
integer constraint, defining the minimum length
of this string.
Enumeration Preference
{
"title": "string",
"description": "string",
"required": "boolean",
"preferenceType": "enumeration",
"definition": {
"options": {
"key1": "string",
"key2": "string"
},
"default": "string"
}
}
Enumeration Preferences must have a preferenceType
of enumeration
.
Enumeration Preferences must have an options
block, that defines what enumerated values may be selected.
The options
block must have at least one enumeration defined.
Enumerations are a simple key-value pair, where the key is a unique identifier, and the value is a displayable label
describing the enumeration. Enumeration keys may be a numeric string, such as "1"
, but it is recommended that they be
descriptive, e.g. "lightUrple"
.
If a default
is set, it must match an option
key.
Using Preferences in an Edge Driver
Once you have defined a Device Profile to use a Preference, you will need to access that value from the Edge Driver to modify whatever behavior the Preference is intended to control. In the sections below, we look at some of the ways Preferences are commonly used.
Query Current Value
One common use case is when you need the value at a single point in time to adjust or control a command or event related to the device. For these cases, you can check the value of the Preference as needed. The Preference values will be accessible via the device object in the driver. device.preferences.<preference_id>
will give you the value of that Preference for that device.
Here is a snippet using a levelOffset
Preference value to adjust a value sent to a Zigbee device for the switchLevel.setLevel
command:
local function set_level(driver, device, command)
local raw_level = utils.clamp_value(command.args.level + device.preferences.levelOffset, 0, 100)
local level = math.floor(raw_level/100.0 * 254)
device:send_to_component(command.component, zcl_clusters.Level.server.commands.MoveToLevelWithOnOff(device, level, command.args.rate or 0xFFFF))
End
Handling Changes to Preferences
Another common use case is when a Preference is used to control something directly on the device, and thus a Preference value change needs to generate a message sent to the device to update its behavior. In these cases, you will need to have a handler ready for when a Preference value changes. Since the Preference value is stored on the device object in the cloud, any value changes will be communicated using the device_lifecycle
event of infoChanged
. If you need to send a message to the device, you can register a handler for the infoChanged
event to handle changes.
Below is an example handler that checks if a Preference has changed and sends a command to the device:
local function device_info_changed(driver, device, event, args)
-- Did my preference value change
if args.old_st_store.preferences.sensitivityLevel ~= device.preferences.sensitivityLevel then
device:send(<message_to_control_device>)
end
end
Remember that infoChanged
will not automatically be called when the device is created. If you need to send some of the initial commands for the Preference values on device creation, you should separate out the Preference handling into a function that you can call from both the infoChanged
handler and the deviceAdded
handler.
Handling Changes to Preferences For a Sleepy Z-Wave Device
If Preferences are updated for a sleepy device and commands need to be sent to the device, those commands cannot be sent until the device is awake. Sending the commands in the device infoChanged
lifecycle event handler will not work since the device is likely asleep.
The Z-Wave device object allows a developer to set an update_preferences
function on the device which will automatically get called when the device wakes up. The function is provided args which are similar to the args on the infoChanged
lifecycle event and contain the Preferences that were present the last time the device woke up (args.old_st_store.preferences
). Note that there will still be an infoChanged
event for sleepy devices, and this automatic Preference update mechanism only works for devices that support the WakeUp
command class.
Below is an example of how this functionality should be handled in a driver:
local function update_preferences(device, args)
-- find preference differences between the args.old_st_store.preferences and device.st_store.preferences
device:send(Configuration:Set({parameter_number = 1, size = 2, configuration_value = 600}))
device:send(Configuration:Get({})
end
local function device_init(self, device)
device:set_update_preferences_fn(update_preferences)
end
local function info_changed(self, device, event, args)
-- only update preferences for devices we know are awake
-- if this driver only supports sleepy devices, an infoChanged handler is not needed.
if ~device:is_cc_supported(cc.WAKE_UP) then
update_preferences(device, args)
end
end
local zwave_driver = {
supported_capabilities = {
capabilities.contactSensor,
capabilities.battery
},
lifecycle_handlers = {
init = device_init,
infoChanged = info_changed,
},
}
Testing Device Preference Changes
Verify that the driver behaves as expected when receiving a new device Preference value by creating an infoChanged
test event containing the new Preference value. This event is then sent to the driver. The following snipped below demonstrates creating this test event:
test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({ preferences = { myPreference = 1 } }))
Device Preferences Reference
Here you can find a list of standard Device Preferences maintained by SmartThings.
Use the Preferences API endpoint to retrieve an up-to-date list of preferences available for you to use, create your own preferences, and more.
Preference ID | Type | Description | Built-In Platform Support |
---|---|---|---|
freezeSensitivity | enum (0-2) | Device water freeze detection sensitivity (0: low sensitivity) | No built-in support |
humidityOffset | integer (-10, 10) | The amount to shift humidityMeasurement attribute values | Automatically applied to attribute values emitted by Edge drivers - no support required by driver itself |
leakSensitivity | enum (0-2) | Device leak detection sensitivity (0: low sensitivity) | No built-in support |
motionSensitivity | enum (0-3) | Device motion sensitivity (0: disabled; 1: low sensitivity) | No built-in support |
password | string (password string type) | Password for communicating with the device | No built-in support |
presetPosition | integer (0-100) | Value used for a device-specific purpose | No built-in support |
rainSensitivity | enum (0-2) | Device rain sensor sensitivity (0: low sensitivity) | No built-in support |
reportingInterval | integer (5-1440) | Value used to control the reporting interval of the device in minutes | No built-in support |
reverse | boolean | Reverse the device's operation | No built-in support |
tempOffset | number (-10, 10) | The amount to shift temperatureMeasurement attribute values | Automatically applied to attribute values emmited by Edge drivers - no support required by driver itself |
username | string | A username used for communicating with the device | No built-in support |