Smart Home OpenClose Trait Schema

action.devices.traits.OpenClose - This trait belongs to devices that support opening and closing, and in some cases opening and closing partially or potentially in more than one direction.

Device ATTRIBUTES

Devices with this trait may report the following attributes as part of the SYNC operation. To learn more about handling SYNC intents, see Intent fulfillment.

Attributes Type Description
discreteOnlyOpenClose Boolean

(Default: false)

When set to true, this indicates that the device must either be fully open or fully closed (that is, it does not support values between 0% and 100%).

openDirection Array <String>

List of supported directions in which the device can open or close. Include this attribute if the device supports opening and closing in more than one direction.

Supported direction.

Supported values:

UP
DOWN
LEFT
RIGHT
IN
OUT
commandOnlyOpenClose Boolean

(Default: false)

Indicates if the device supports using one-way (true) or two-way (false) communication. Set this attribute to true if the device cannot respond to a QUERY intent or Report State for this trait.

queryOnlyOpenClose Boolean

(Default: false)

Indicates if the device can only be queried for state information and cannot be controlled. Sensors that can only report open state should set this field to true.

Examples

Simple open-close device.

{
  "discreteOnlyOpenClose": true
}

Top-down bottom-up device. Can be opened in either direction.

{
  "openDirection": [
    "UP",
    "DOWN"
  ]
}

Command-only device.

{
  "commandOnlyOpenClose": true
}
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.OpenClose'
        ],
        name: {
          defaultNames: [
            'Blinds'
          ],
          name: 'Kitchen window',
          nicknames: [
            'Sink window'
          ]
        },
        willReportState: true,
        attributes: {
          openDirection: ['UP', 'DOWN']
        },
        deviceInfo: {
          manufacturer: 'ACME',
          model: '492134',
          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.OpenClose")
            .setName(
                Collections.singletonList("Blinds"),
                "Kitchen window",
                Collections.singletonList("Sink window"))
            .setWillReportState(true)
            .setAttributes(new JSONObject().put("openDirection", new String[] {"UP", "DOWN"}))
            .setDeviceInfo("ACME", "492134", "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.OpenClose"
        ],
        "name": {
          "defaultNames": [
            "Blinds"
          ],
          "name": "Kitchen window",
          "nicknames": [
            "Sink window"
          ]
        },
        "willReportState": true,
        "attributes": {
          "openDirection": [
            "UP",
            "DOWN"
          ]
        },
        "deviceInfo": {
          "manufacturer": "ACME",
          "model": "492134",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "lambtwirl"
        }
      }
    ]
  }
}
Validator

Device STATES

Devices with this trait may report the following states as part of the QUERY operation. To learn more about handling QUERY intents, see Intent fulfillment.

The payload has exactly one of these:

Single direction open-close
States Type Description
openPercent Number

Indicates the percentage that a device is opened, where 0 is closed and 100 is fully open.

Required:

  • openPercent
Multiple direction open-close
States Type Description
openState Array <Object>

List of states for each supported open direction.

Properties:

Current state for the given open direction.

openPercent Number

Indicates the percentage that a device is opened, where 0 is closed and 100 is fully open.

openDirection String

Direction in which the device is opened.

Supported values:

UP
DOWN
LEFT
RIGHT
IN
OUT

Required:

  • openPercent
  • openDirection

Required:

  • openState
Examples

Simple open-close device.

{
  "openPercent": 100
}

Open device by 30% in down direction, and by 50% in up direction.

{
  "openState": [
    {
      "openPercent": 30,
      "openDirection": "DOWN"
    },
    {
      "openPercent": 50,
      "openDirection": "UP"
    }
  ]
}
Figure 1 shows an example of a top-down bottom-up blind where the UP direction raises the bottom portion of the blinds by 50 percent and the DOWN direction lowers the top portion of the blinds by 30 percent.

Figure 1. Top-down bottom-up blind

Sample QUERY Request and Response

User Are my blinds open?
Google Assistant The kitchen blinds are open.
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: {
          on: true,
          online: true,
          openState: [{
            openPercent: 40.0,
            openDirection: 'DOWN'
          }]
        }
      }
    }
  };
});

// ...

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(
                    "openState",
                    new HashMap[] {
                      new HashMap<String, Object>() {
                        {
                          put("openPercent", 40);
                          put("openDirection", "DOWN");
                        }
                      }
                    });
                put("status", "SUCCESS");
              }
            });
      }
    });
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "on": true,
        "online": true,
        "openState": [
          {
            "openPercent": 40,
            "openDirection": "DOWN"
          }
        ]
      }
    }
  }
}

Example: Single opening direction

User Are my blinds open?
Google Assistant The kitchen blinds are open.
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: {
          on: true,
          online: true,
          openPercent: 100.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("on", true);
                put("online", true);
                put(
                    "openState",
                    new HashMap[] {
                      new HashMap<String, Object>() {
                        {
                          put("openPercent", 40);
                          put("openDirection", "DOWN");
                        }
                      }
                    });
                put("status", "SUCCESS");
              }
            });
      }
    });
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "on": true,
        "online": true,
        "openPercent": 100
      }
    }
  }
}

Device COMMANDS

Devices with this trait may respond to the following commands as part of the EXECUTE operation. To learn more about handling EXECUTE intents, see Intent fulfillment.

action.devices.commands.OpenClose

Parameters

Set the open-close state of the device.

Parameters Type Description
openPercent Number

Indicates the percentage that a device is opened, where 0 is closed and 100 is fully open.

openDirection String

Direction in which to open. Only present if device supports multiple directions, as indicated by the openDirection attribute, and a direction is specified by the user.

Supported values:

UP
DOWN
LEFT
RIGHT
IN
OUT

Required:

  • openPercent
Examples

Open the device.

{
  "openPercent": 100
}

Open device 50 percent down.

{
  "openPercent": 50,
  "openDirection": "DOWN"
}

An error occurred setting the open-close state of the device.

Supported values:

lockedState
deviceJammingDetected

action.devices.commands.OpenCloseRelative

Parameters

Adjust the open-close state of the device relative to the current state. This command is only available if commandOnlyOpenClose is set to true.

Parameters Type Description
openRelativePercent Number

The exact percentage to change open-close state. Ambigous relative commands will be converted to an exact percentage parameter (for example, "Open the blinds a little more" vs "Open the blinds by 5%").

openDirection String

Direction in which to open. Only present if device supports multiple directions, as indicated by the openDirection attribute, and a direction is specified by the user.

Supported values:

UP
DOWN
LEFT
RIGHT
IN
OUT

Required:

  • openRelativePercent
Examples

Open the device a little more

{
  "openRelativePercent": 5
}

Close the device 10% more

{
  "openRelativePercent": -10
}

Open device 50% more, downward.

{
  "openRelativePercent": 50,
  "openDirection": "DOWN"
}

An error occurred setting the open-close state of the device.

Supported values:

lockedState
deviceJammingDetected

Sample EXECUTE Request and Response

User Open the garage door.
Google Assistant Opening the garage door.
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.OpenClose",
          "params": {
            "openPercent": 100
          }
        }]
      }]
    }
  }]
}
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: {
          openPercent: 100.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("openPercent", 100);
              put("online", true);
            }
          },
          null,
          null)
    });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "openPercent": 100,
          "online": true
        }
      }
    ]
  }
}
User Open blinds 50 percent down.
Google Assistant Opening the blinds downward 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.OpenClose",
          "params": {
            "openPercent": 50,
            "openDirection": "DOWN"
          }
        }]
      }]
    }
  }]
}
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: {
          openState: [{
            openPercent: 50.0,
            openDirection: 'DOWN'
          }, {
            // Returns the position of the other blind section
            openPercent: 30.0,
            openDirection: 'UP'
          }],
          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(
                  "openState",
                  new HashMap[] {
                    new HashMap<String, Object>() {
                      {
                        put("openPercent", 50);
                        put("openDirection", "DOWN");
                      }
                    },
                    new HashMap<String, Object>() {
                      {
                        put("openPercent", 30);
                        put("openDirection", "UP");
                      }
                    }
                  });
              put("online", true);
            }
          },
          null,
          null)
    });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "openState": [
            {
              "openPercent": 50,
              "openDirection": "DOWN"
            },
            {
              "openPercent": 30,
              "openDirection": "UP"
            }
          ],
          "online": true
        }
      }
    ]
  }
}

Device ERRORS

See the full list of errors and exceptions.