Smart Home Volume Trait Schema

action.devices.traits.Volume - This trait belongs to devices which are able to change volume (for example, setting the volume to a certain level, mute, or unmute).

Device ATTRIBUTES

Devices with the action.devices.traits.Volume trait may report the following attributes as part of SYNC:

Attributes Type Description
volumeMaxLevel Integer

Required.

The maximum volume level, assuming a baseline of 0 (mute). Assistant will adjust adverbial commands (e.g. 'make the tv a little louder') accordingly.

volumeCanMuteAndUnmute Boolean

Required.

Indicates if the device can mute and unmute the volume. Mute is a separate option as the 'mute' behavior takes the volume to 0 while remembering the previous volume, so that unmute restores it. This is reflected in volume state—if volume is 5, and the user mutes, the volume remains 5 and isMuted is true.

volumeDefaultPercentage Integer

(Default: 40)

The volume (in percentage) for the default volume defined by user or manufacturer. The scale must be 0-100.

levelStepSize Integer

(Default: 1)

The default step size for relative volume queries like 'volume up on <device_name>.

commandOnlyVolume Boolean

(Default: 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 (for example, if the device is a traditional infrared remote), set this field to true.

Examples

{
  "$comment": "Speaker device that can be muted and reports current state",
  "volumeMaxLevel": 11,
  "volumeCanMuteAndUnmute": true,
  "levelStepSize": 2,
  "commandOnlyVolume": false,
  "volumeDefaultPercentage": 6
}

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.TV',
        traits: [
          'action.devices.traits.Volume'
        ],
        name: {
          defaultNames: ['TV'],
          name: 'Office TV',
          nicknames: ['TV']
        },
        willReportState: true,
        attributes: {
          volumeMaxLevel: 11,
          volumeCanMuteAndUnmute: true,
          levelStepSize: 2,
          commandOnlyVolume: false,
          volumeDefaultPercentage: 6
        },
        deviceInfo: {
          manufacturer: "ACME Inc.",
          model: "TV-R",
          hwVersion: "PVT-2",
          swVersion: "1.0.1"
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
@SmartHomeSnippetJson("smart-home-traits-volume_sync.json")
public SyncResponse onSync(@NotNull SyncRequest syncRequest, @Nullable Map<?, ?> headers) {
  Payload payload = new Payload();
  payload.setAgentUserId("1836.15267389");

  payload.setDevices(
      new Device[] {
        new Device.Builder()
            .setId("123")
            .setType("action.devices.types.TV")
            .addTrait("action.devices.traits.Volume")
            .setName(
                Collections.singletonList("TV"), "Office TV", Collections.singletonList("TV"))
            .setWillReportState(true)
            .setAttributes(
                new JSONObject()
                    .put("volumeMaxLevel", 11)
                    .put("volumeCanMuteAndUnmute", true)
                    .put("levelStepSize", 2)
                    .put("commandOnlyVolume", false)
                    .put("volumeDefaultPercentage", 6))
            .setDeviceInfo("ACME Inc.", "TV-R", "PVT-2", "1.0.1")
            .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.TV",
        "traits": [
          "action.devices.traits.Volume"
        ],
        "name": {
          "defaultNames": [
            "TV"
          ],
          "name": "Office TV",
          "nicknames": [
            "TV"
          ]
        },
        "willReportState": true,
        "attributes": {
          "volumeMaxLevel": 11,
          "volumeCanMuteAndUnmute": true,
          "levelStepSize": 2,
          "commandOnlyVolume": false,
          "volumeDefaultPercentage": 6
        },
        "deviceInfo": {
          "manufacturer": "ACME Inc.",
          "model": "TV-R",
          "hwVersion": "PVT-2",
          "swVersion": "1.0.1"
        }
      }
    ]
  }
}
Validator

Device STATES

States Type Description
currentVolume Integer

Required.

The current volume percentage. It must be between >0 and volumeMaxLevel.

isMuted Boolean

Required if volumeCanMuteAndUnmute attribute is set to true. True if the device is muted; false otherwise. If isMuted is true, the device still returns currentVolume for the remembered point.

Request
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "inputs": [{
    "intent": 'action.devices.QUERY',
    "payload": {
      "devices": [{
        "id": "123",
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "foo"
        }
      }]
    }
  }]
}
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: {
          online: true,
          currentVolume: 5,
          isMuted: false,
          status: 'SUCCESS'
        }
      }
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
@SmartHomeSnippetJson("smart-home-traits-volume_query.json")
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("online", true);
                  put("currentVolume", 5);
                  put("isMuted", false);
                  put("status", "SUCCESS");
                }
              });
        }
      });
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "online": true,
        "currentVolume": 5,
        "isMuted": false,
        "status": "SUCCESS"
      }
    }
  }
}

Device COMMANDS

action.devices.commands.mute

Mutes (sets the volume to 0) or unmutes the device.

Parameters Type Description
mute Boolean

Required.

Whether to mute a device or unmute a device.

action.devices.commands.setVolume

Set volume to the requested level, based on volumeMaxLevel.

Parameters Type Description
volumeLevel Integer

Required.

New volume, from 0 to volumeMaxLevel.

Devices in command-only mode

For devices in command-only mode (for example, an infrared device), no state query is possible, and an additional relative command is used. Mute, being stateless, remains as above.

action.devices.commands.volumeRelative

Set volume up or down n steps, based on volumeMaxLevel. For commands that use a relative scale, the Assistant will select n appropriately to scale to the available steps. For example, Make the TV much louder will set a higher number of steps than Make the TV a tiny bit louder.

Parameters Type Description
relativeSteps Integer

Required.

negative for 'decrease'.

Sample EXECUTE Request and Response

Example 1: Set volume to 50%.

Request
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "inputs": [{
    "intent": "action.devices.EXECUTE",
    "payload": {
      "commands": [{
        "devices": [{
          "id": "123"
        }],
        "execution": [{
          "command": "action.devices.commands.setVolume",
          "params": {
            "volumeLevel": 6
          }
        }]
      }]
    }
  }]
}
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: {
          online: true,
          currentVolume: 6
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
@SmartHomeSnippetJson("smart-home-traits-volume_execute_1.json")
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("online", true);
                put("currentVolume", 6);
              }
            },
            null,
            null)
      });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "online": true,
          "currentVolume": 6
        }
      }
    ]
  }
}

Example 2: Make the TV a little quieter. (Command-only mode)

Request
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "inputs": [{
    "intent": "action.devices.EXECUTE",
    "payload": {
      "commands": [{
        "devices": [{
          "id": "123"
        }],
        "execution": [{
          "command": "action.devices.commands.volumeRelative",
          "params": {
            "relativeSteps": -1
          }
        }]
      }]
    }
  }]
}
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: {
          online: true,
          currentVolume: 5
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
Java
@NotNull
@Override
@SmartHomeSnippetJson("smart-home-traits-volume_execute_2.json")
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("online", true);
                put("currentVolume", 5);
              }
            },
            null,
            null)
      });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "online": true,
          "currentVolume": 5
        }
      }
    ]
  }
}

Device ERRORS

See the full list of errors and exceptions.
  • volumeAlreadyMax: Device receives VolumeUp command when it is already at highest volume.
  • volumeAlreadyMin: Device receives VolumeDown command when it is already at lowest volume.