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
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.SYNC"
}]
}
'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);
@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);
}
{
"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"
}
}
]
}
}
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. |
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": 'action.devices.QUERY',
"payload": {
"devices": [{
"id": "123",
"customData": {
"fooValue": 74,
"barValue": true,
"bazValue": "foo"
}
}]
}
}]
}
'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
},
status: 'SUCCESS'
}
}
};
});
// ...
exports.smarthome = functions.https.onRequest(app);
@NotNull
@Override
public QueryResponse onQuery(@NotNull QueryRequest queryRequest, @Nullable Map<?, ?> map) {
QueryResponse.Payload payload = new QueryResponse.Payload();
payload.setDevices(new HashMap<String, Object>() {{ put("123", new HashMap<String, Object>() {{ put("online", true);
put("rotationPercent", 25.0);
}});
put("status", "SUCCESS");
}});
return new QueryResponse(queryRequest.getRequestId(), payload);
}
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"devices": {
"123": {
"online": true,
"rotationPercent": 25
},
"status": "SUCCESS"
}
}
}
User | How many degrees is the fan rotated? |
Google Assistant | The fan is rotated to 90 degrees. |
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": 'action.devices.QUERY',
"payload": {
"devices": [{
"id": "123",
"customData": {
"fooValue": 74,
"barValue": true,
"bazValue": "foo"
}
}]
}
}]
}
'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
},
status: 'SUCCESS'
}
}
};
});
// ...
exports.smarthome = functions.https.onRequest(app);
@NotNull
@Override
public QueryResponse onQuery(@NotNull QueryRequest queryRequest, @Nullable Map<?, ?> map) {
QueryResponse.Payload payload = new QueryResponse.Payload();
payload.setDevices(new HashMap<String, Object>() {{ put("123", new HashMap<String, Object>() {{ put("online", true);
put("rotationDegrees", 90.0);
}});
put("status", "SUCCESS");
}});
return new QueryResponse(queryRequest.getRequestId(), payload);
}
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"devices": {
"123": {
"online": true,
"rotationDegrees": 90
},
"status": "SUCCESS"
}
}
}
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. |
{
"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
}
}]
}]
}
}]
}
'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);
@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);
}
{
"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. |
{
"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
}
}]
}]
}
}]
}
'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);
@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);
}
{
"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.