Smart Home Rotation Trait Schema

action.devices.traits.Rotation - This trait belongs to devices that support rotation, such as blinds with rotatable slats. The rotation can be specified in either percent or degrees and if the device supports rotation by degrees, the default direction of rotation is clockwise.

Device ATTRIBUTES

Attribute Definition
commandOnlyRotation 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.
supportsContinuousRotation Boolean. Optional. Defaults to false. Set to true if the device allows continuous rotation. When given a relative command, the device can rotate beyond [0, 100] for percent and [0, 360] for degrees. For example, a device currently at 270 degrees, rotated by 100 degrees clockwise, would go to 10 degrees.
supportsDegrees Boolean. Required. Set to true if the device allows rotation by degree.
supportsPercent Boolean. Required. Set to true if device allows rotation by percent. Note that one device may support either or both of these attributes (degrees and percent).
rotationDegreesRange Contains rotationDegreesMin float, and rotationDegreesMax float. Required if supportsDegrees is true. These represent the minimum and maximum degrees that a device can rotate. Must be positive values. For example:
"rotationDegreesRange": {
  "rotationDegreesMin": <float>,
  "rotationDegreesMax": <float>,
}

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.BLINDS',
        traits: [
          'action.devices.traits.Rotation'
        ],
        name: {
          defaultNames: ['Blinds window'],
          name: 'Kitchen window',
          nicknames: ['Sink window']
        },
        willReportState: true,
        attributes: {
          supportsDegrees: true,
          supportsPercent: true,
          rotationDegreesRange: {
            rotationDegreesMin: 0.0,
            rotationDegreesMax: 180.0
          }
        },
        deviceInfo: {
          manufacturer: 'AAA',
          model: 'xyz',
          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 Device[] {
      new Device.Builder()
          .setId("123")
          .setType("action.devices.types.BLINDS")
          .addTrait("action.devices.traits.Rotation")
          .setName(
              Collections.singletonList("Blinds window"),
              "Kitchen window",
              Collections.singletonList("Sink window")
          )
          .setWillReportState(true)
          .setAttributes(new JSONObject()
              .put("supportsDegrees", true)
              .put("supportsPercent", true)
              .put("rotationDegreesRange", new JSONObject()
                  .put("rotationDegreesMin", 0)
                  .put("rotationDegreesMax", 0)
              )
          )
          .setDeviceInfo("AAA", "xyz", "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.BLINDS",
        "traits": [
          "action.devices.traits.Rotation"
        ],
        "name": {
          "defaultNames": [
            "Blinds window"
          ],
          "name": "Kitchen window",
          "nicknames": [
            "Sink window"
          ]
        },
        "willReportState": true,
        "attributes": {
          "supportsDegrees": true,
          "supportsPercent": true,
          "rotationDegreesRange": {
            "rotationDegreesMin": 0,
            "rotationDegreesMax": 180
          }
        },
        "deviceInfo": {
          "manufacturer": "AAA",
          "model": "xyz",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "lambtwirl"
        }
      }
    ]
  }
}
Validator

Device STATES

State Definition
rotationPercent Float. Current level [0.0, 100.0] that indicates what percent the device is currently rotated. 0.0 corresponds to closed and 100.0 to open.
rotationDegrees Float. Current level [rotationDegreesMin, rotationDegreesMax] that indicates how many degrees the device is rotated. This value should always be relative to the clockwise rotation.

Sample QUERY Request and Response

User How much are the blinds rotated?
Google Assistant The blinds are rotated to 25 percent.
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,
          rotationPercent: 25.0
        }
      }
    }
  };
});

// ...

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("online", true);
put("rotationPercent", 25.0);
      }});
  }});
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "online": true,
        "rotationPercent": 25
      }
    }
  }
}
User How many degrees is the fan rotated?
Google Assistant The fan is rotated to 90 degrees.
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,
          rotationDegrees: 90.0
        }
      }
    }
  };
});

// ...

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("online", true);
put("rotationDegrees", 90.0);
      }});
  }});
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "online": true,
        "rotationDegrees": 90
      }
    }
  }
}

Device COMMANDS

Command Parameters/Definition
action.devices.commands.RotateAbsolute

rotationPercent Float. An absolute value, in percentage, that specifies the final rotation of the device. Value must be in the range [0.0, 100.0].

rotationDegrees Float. An absolute value, in degrees, that specifies the final rotation of the device. Value must be in the range [rotationDegreesMin, rotationDegreesMax]. This value should always be relative to the clockwise rotation.

Note that if a device only supports degrees, commands may be given with percentages relative to the supported range of the device. For example, with a range of [0.0, 90.0], Rotate the blinds to 50% would result in 45.0 degrees.

Sample EXECUTE Request and Response

User Tilt the blinds to 50 percent.
Google Assistant Ok, rotating the blinds to 50 percent.
Request
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "inputs": [{
    "intent": "action.devices.EXECUTE",
    "payload": {
      "commands": [{
        "devices": [{
          "id": "456",
          "customData": {
            "fooValue": 74,
            "barValue": true,
            "bazValue": "lambtwirl"
          }
        }],
        "execution": [{
          "command": "action.devices.commands.RotateAbsolute",
          "params": {
            "rotationPercent": 50.0
          }
        }]
      }]
    }
  }]
}
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: {
          rotationPercent: 50.0
        }
      }]
    }
  };
});

// ...

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("rotationPercent", 50.0);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "rotationPercent": 50
        }
      }
    ]
  }
}
User Rotate the fan 15 degrees counterclockwise.
Google Assistant Sure, rotating the fan clockwise to 15 degrees.
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.RotateAbsolute",
          "params": {
            "rotationDegrees": 15.0
          }
        }]
      }]
    }
  }]
}
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: {
          rotationDegrees: 15.0,
          online: true
        }
      }]
    }
  };
});

// ...

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("rotationDegrees", 15.0);
            put("online", true);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "rotationDegrees": 15,
          "online": true
        }
      }
    ]
  }
}

Device ERRORS

These are some error codes that can be returned with your responses:

  • deviceJammingDetected The device is jammed.

See the full list of errors and exceptions.