Smart Home Modes Trait Schema

action.devices.traits.Modes - This trait covers all available modes and mode-specific settings for a device.

This trait belongs to any devices with an arbitrary number of "n-way" modes in which the modes and settings for each mode are arbitrary and unique to each device or device type. Each mode has multiple possible settings, but only one can be selected at a time; a dryer cannot be in "delicate," "normal," and "heavy duty" mode simultaneously. A setting that simply can be turned on or off belongs in the Toggles trait.

For instance, a washing machine can have settings for load size and temperature. These would both be modes because they are independent of each other, but each can be in only one state at a time. The user can set a mode such as temperature explicitly with a command like Set the washer’s temperature to cold.

Some modes are "ordered" and can also be adjusted with up/down, increase/decrease verbiage. For example, load size (small, medium, large) and temperature are clearly ordered (note that temperature is not an actual thermostat with a numeric target, as on other devices), but load type (delicates, normal, wool, etc) may not be.

This trait covers one or more individual modes which users can set. In general, these modes should be used for functionality that is unlinked from other device behavior. Linked behavior, such as turning the device itself on or off, should use more specific traits (for example, the thermostatMode in the trait TemperatureSetting).

Device ATTRIBUTES

Attribute Definition
availableModes Each mode has a name and at least 2 settings:
  • name String. Internal name of the mode, which will be used in commands and states. This can be non-user-friendly, and will be shared across all languages.
  • name_values Contains names and supported languages:
    • name_synonym Strings. User-friendly names for the mode, in each language supported.
    • lang String. Supported language for the names (see Supported Languages/Language Codes).
  • settings Contains setting names and supported languages:
    • setting_name String. Internal name of the setting, which will be used in commands and states. This can be non-user-friendly, and will be shared across all languages. Currently, you must use the setting names in the example JSON; custom names are not yet supported.
    • setting_values Contains setting synonyms in the supported languages:
      • setting_synonym Strings. User-friendly names for the setting, in each language supported. Currently, you must use the setting synonyms in the example JSON; custom setting synonyms are not yet supported.
      • lang String. Supported language for the setting names (see Supported Languages/Language Codes).
  • ordered If this is set to true, additional grammar for increase/decrease logic will apply, in the order (increasing) of the settings array.
commandOnlyModes Boolean. Optional. Defaults to false. Indicates if the device operates using one-way (true) or two-way (false) communication. For example, if the controller can confirm the new device state after sending the request, this field would be false. If it's not possible to confirm if the request is successfully executed or to get the state of the device, set this field to true.
The following is an example for a clothes washer:
{
  "availableModes": [{
    "name": "load",
    "name_values": [{
      "name_synonym": ["load", "size", "load size"],
      "lang": "en"
    }],
    "settings": [{
      "setting_name": "small",
      "setting_values": [{
        "setting_synonym": ["small", "half"],
        "lang": "en"
       }]
     },
     {
       "setting_name": "large",
       "setting_values": [{
         "setting_synonym": ["large", "full"],
         "lang": "en"
       }]
     }],
     "ordered": true
  }]
}

Sample SYNC Request and Response

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.SYNC"
    }]
}
Node.js
'use strict';

const {smarthome} = require('actions-on-google');
const functions = require('firebase-functions');

const app = smarthome();

app.onSync((body, headers) => {
  return {
    requestId: body.requestId,
    payload: {
      agentUserId: '1836.15267389',
      devices: [{
        id: '123',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.Modes'
        ],
        name: {
          defaultNames: ['AAA Cybernetics Corporation Washer 3421'],
          name: 'Washer',
          nicknames: ['clothes washer']
        },
        willReportState: false,
        attributes: {
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load', 'size', 'load size'],
              lang: 'en'
            }],
            settings: [{
              setting_name: 'small',
              setting_values: [{
                setting_synonym: ['small', 'half'],
                lang: 'en'
              }]
            }, {
              setting_name: 'large',
              setting_values: [{
                setting_synonym: ['large', 'full'],
                lang: 'en'
              }]
            }],
            ordered: true
          }]
        },
        deviceInfo: {
          manufacturer: 'AAA Cybernetics Corporation',
          model: '233451',
          hwVersion: '3.2',
          swVersion: '11.4'
        },
        customData: {
          fooValue: 74,
          barValue: true,
          bazValue: 'lambtwirl'
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
public SyncResponse onSync(@NotNull SyncRequest syncRequest, @Nullable Map<?, ?> headers) {
  Payload payload = new Payload();
  payload.setAgentUserId("1836.15267389");
  payload.setDevices(new SyncResponse.Payload.Device[] {
      new SyncResponse.Payload.Device.Builder()
          .setId("123")
          .setType("action.devices.types.WASHER")
          .addTrait("action.devices.traits.Modes")
          .setName(
              Collections.singletonList("AAA Cybernetics Corp Washer 3421"),
              "Washer",
              Collections.singletonList("clothes washer")
          )
          .setWillReportState(true)
          .setAttributes(new JSONObject()
              .put("availableModes", new JSONObject[] {
                  new JSONObject()
                      .put("name", "load")
                      .put("name_values", new JSONObject[] {
                          new JSONObject()
                              .put("name_synonym", new String[] {"load", "size", "load size"})
                              .put("lang", "en")
                      })
                      .put("settings", new JSONObject[] {
                          new JSONObject()
                              .put("setting_name", "small")
                              .put("setting_values", new JSONObject[] {
                              new JSONObject()
                                  .put("setting_synonym", new String[] {"small", "half"})
                                  .put("lang", "en")
                          }),
                          new JSONObject()
                              .put("setting_name", "large")
                              .put("setting_values", new JSONObject[] {
                              new JSONObject()
                                  .put("setting_synonym", new String[] {"large", "full"})
                                  .put("lang", "en")
                          })
                      })
                      .put("ordered", true)
              })
          )
          .setDeviceInfo("AAA Cybernetics Corporation", "233451", "3.2",
              "11.4")
          .setCustomData(new JSONObject()
              .put("fooValue", 74)
              .put("barValue", true)
              .put("bazValue", "lambtwirl")
              .toString()
          )
          .build()
  });
  return new SyncResponse(syncRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "123",
        "type": "action.devices.types.WASHER",
        "traits": [
          "action.devices.traits.Modes"
        ],
        "name": {
          "defaultNames": [
            "AAA Cybernetics Corporation Washer 3421"
          ],
          "name": "Washer",
          "nicknames": [
            "clothes washer"
          ]
        },
        "willReportState": false,
        "attributes": {
          "availableModes": [
            {
              "name": "load",
              "name_values": [
                {
                  "name_synonym": [
                    "load",
                    "size",
                    "load size"
                  ],
                  "lang": "en"
                }
              ],
              "settings": [
                {
                  "setting_name": "small",
                  "setting_values": [
                    {
                      "setting_synonym": [
                        "small",
                        "half"
                      ],
                      "lang": "en"
                    }
                  ]
                },
                {
                  "setting_name": "large",
                  "setting_values": [
                    {
                      "setting_synonym": [
                        "large",
                        "full"
                      ],
                      "lang": "en"
                    }
                  ]
                }
              ],
              "ordered": true
            }
          ]
        },
        "deviceInfo": {
          "manufacturer": "AAA Cybernetics Corporation",
          "model": "233451",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "lambtwirl"
        }
      }
    ]
  }
}
Validator

Device STATES

State Definition
currentModeSettings Object containing a string for each mode defined on the object, representing setting_name. For example:
"currentModeSettings": {
     "temperature": "hot",
     "load": "large"
}

Sample QUERY Request and Response

What mode is the dryer in?
Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.QUERY",
      "payload": {
        "devices": [{
          "id": "123",
          "customData": {
            "fooValue": 74,
            "barValue": true,
            "bazValue": "foo"
          }
        }, {
          "id": "456",
          "customData": {
            "fooValue": 12,
            "barValue": false,
            "bazValue": "bar"
          }
        }]
      }
    }]
}
Node.js
'use strict';

const {smarthome} = require('actions-on-google');
const functions = require('firebase-functions');

const app = smarthome();

app.onQuery((body, headers) => {
  return {
    requestId: body.requestId,
    payload: {
      devices: {
        123: {
          on: true,
          online: true,
          currentModeSettings: {
            drytype: 'permpress',
            load: 'large'
          }
        },
        456: {
          on: true,
          online: true,
          isPaused: true,
          isRunning: false,
          currentModeSettings: {
            temperature: 'hot',
            load: 'large'
          }
        }
      }
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
public QueryResponse onQuery(@NotNull QueryRequest queryRequest, @Nullable Map<?, ?> map) {
  QueryResponse.Payload payload = new QueryResponse.Payload();
  payload.setDevices(new HashMap<String, Map<String, Object>>() {{      put("123", new HashMap<String, Object>() {{          put("on", true);
          put("online", true);
          put("currentModeSettings", new HashMap<String, Object>() {{              put("drytype", "permpress");
              put("load", "large");
          }});
      }});
      put("456", new HashMap<String, Object>() {{          put("on", true);
          put("online", true);
          put("isPaused", true);
          put("isRunning", false);
          put("currentModeSettings", new HashMap<String, Object>() {{              put("temperature", "hot");
              put("load", "large");
          }});
      }});
  }});

  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "on": true,
        "online": true,
        "currentModeSettings": {
          "drytype": "permpress",
          "load": "large"
        }
      },
      "456": {
        "on": true,
        "online": true,
        "isPaused": true,
        "isRunning": false,
        "currentModeSettings": {
          "temperature": "hot",
          "load": "large"
        }
      }
    }
  }
}

Device COMMANDS

Command Parameters/Definition
action.devices.commands.SetModes updateModeSettings Object containing the new string value (setting_name) for each mode that's being set.

Sample EXECUTE Request and Response

Set the dryer to permanent press.
Request
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "inputs": [{
    "intent": "action.devices.EXECUTE",
    "payload": {
      "commands": [{
        "devices": [{
          "id": "123",
          "customData": {
            "fooValue": 74,
            "barValue": true,
            "bazValue": "lambtwirl"
          }
        }],
        "execution": [{
          "command": "action.devices.commands.SetModes",
          "params": {
            "updateModeSettings": {
              "drytype": "permpress"
            }
          }
        }]
      }]
    }
  }]
}
Node.js
'use strict';

const {smarthome} = require('actions-on-google');
const functions = require('firebase-functions');

const app = smarthome();

app.onExecute((body, headers) => {
  return {
    requestId: body.requestId,
    payload: {
      commands: [{
        ids: ['123'],
        status: 'SUCCESS',
        states: {
           currentModeSettings: {
             drytype: 'permpress',
             load: 'large'
           }
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
public ExecuteResponse onExecute(@NotNull ExecuteRequest executeRequest, @Nullable Map<?, ?> map) {
  ExecuteResponse.Payload payload = new ExecuteResponse.Payload();

  payload.setCommands(new Commands[] {
      new Commands(
          new String[] {"123"},
          "SUCCESS",
          new HashMap<String, Object>() {{              put("currentModeSettings", new HashMap<String, Object>() {{                  put("drytype", "permpress");
                  put("load", "large");
              }});
          }},
          null
      )
  });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "currentModeSettings": {
            "drytype": "permpress",
            "load": "large"
          }
        }
      }
    ]
  }
}