Smart Home Fill Trait Schema

action.devices.traits.Fill - This trait applies to devices that support being filled, such as a bathtub. A device supporting this trait may support filling to various levels.

Device ATTRIBUTES

Attribute Definition
availableFillLevels Object. Optional. Describes different levels of filling the device.
  • levels: Array containing the name of each level and a subarray for level_values with language-specific synonyms.

    • level_name: String. Internal name of the level, which will be used in commands and states. This can be non-user-friendly, and will be shared across all languages.
    • level_values Contains names and supported languages:
      • level_synonym: Array of strings. User-friendly synonyms for the level, in each language supported.
      • lang: String. Supported language for the synonym (see Supported languages).
  • ordered: Boolean. If true, additional grammar for increase or decrease logic will apply, in the order (increasing) of the levels array. For example, the phrase Increase my fill level by 1 can be supported by looking at the current fill level and moving over in the ordered levels array by one.

The following example shows how you might specify these attributes:

{
  "availableFillLevels": {
    "levels": [{
      "level_name": "quarter",
      "level_values": [{
        "level_synonym": ["quarter", "a fourth", ...],
        "lang": "en"
      }]
    }, {
      "level_name": "half",
      "level_values": [{
        "level_synonym": ["half", "halfway", ...],
        "lang": "en"
      }]
    }],
    "ordered": true
  }
}

Sample SYNC Request and Response

This is an example using the device type and traits above. It is intended to give an idea of how to build a SYNC response. If you add or remove traits, this will need to be modified to reflect those changes.

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.BATHTUB',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.Fill'
        ],
        name: {
          defaultNames: ['Smart Tub'],
          name: 'Tub',
          nicknames: ['Master Bathtub', 'Rubber Duck Pond']
        },
        willReportState: true,
        attributes: {
          availableFillLevels: {
            levels: [{
              level_name: 'half_key',
              level_values: [{
                level_synonym: ['half', 'halfway', 'one half'],
                lang: 'en'
              }]
            }],
            ordered: true
          }
        },
        deviceInfo: {
          manufacturer: 'Sirius Cybernetics Corporation',
          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 SyncResponse.Payload.Device[] {
      new SyncResponse.Payload.Device.Builder()
          .setId("123")
          .setType("action.devices.types.BATHTUB")
          .addTrait("action.devices.traits.OnOff")
          .addTrait("action.devices.traits.Fill")
          .setName(
              Collections.singletonList("Smart Tub"),
              "Bathtub",
              Collections.singletonList("Master Bathtub")
          )
          .setWillReportState(true)
          .setAttributes(new JSONObject()
              .put("availableFillLevels", new JSONObject()
                  .put("levels", new JSONObject[]{
                      new JSONObject()
                          .put("level_name", "half_key")
                          .put("level_values", new JSONObject[]{
                              new JSONObject()
                                  .put("level_synonym",
                                      new String[] {"half", "halfway", "one half"})
                                  .put("lang", "en")
                          })
                  })
                  .put("ordered", true)
              )
          )
          .setDeviceInfo("Sirius Cybernetics Corporation", "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.BATHTUB",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Fill"
        ],
        "name": {
          "defaultNames": [
            "Smart Tub"
          ],
          "name": "Tub",
          "nicknames": [
            "Master Bathtub",
            "Rubber Duck Pond"
          ]
        },
        "willReportState": true,
        "attributes": {
          "availableFillLevels": {
            "levels": [
              {
                "level_name": "half_key",
                "level_values": [
                  {
                    "level_synonym": [
                      "half",
                      "halfway",
                      "one half"
                    ],
                    "lang": "en"
                  }
                ]
              }
            ],
            "ordered": true
          }
        },
        "deviceInfo": {
          "manufacturer": "Sirius Cybernetics Corporation",
          "model": "492134",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "lambtwirl"
        }
      }
    ]
  }
}
Validator

Device STATES

State Definition
isFilled Boolean. Required. True if the device is filled, and if the device supports levels, currentFillLevel indicates which one. If false, the device is drained.
currentFillLevel String. Required if availableFillLevels is reported. Indicates the current level (level_name) at which the device is filled.

Sample QUERY Request and Response

Is the bathtub filled?

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,
          currentFillLevel: 'half',
          isFilled: true
        },
        status: 'SUCCESS'
      }
    }
  };
});

// ...

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, Object>() {{      put("123", new HashMap<String, Object>() {{          put("on", true);
          put("online", true);
          put("currentFillLevel", "half");
          put("isFilled", true);
      }});
      put("status", "SUCCESS");
  }});

  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "on": true,
        "online": true,
        "currentFillLevel": "half",
        "isFilled": true
      },
      "status": "SUCCESS"
    }
  }
}

Device COMMANDS

Command Parameters/Definition
action.devices.commands.Fill

Fills or drains a device.

fill: Boolean. Required. Set to true when command is to fill, false to drain.

fillLevel: String. Optional. Indicates the name of the fill level (level_name) to set. If unspecified, fill to the default level.

Sample EXECUTE Request and Response

Fill the bathtub halfway.

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.Fill",
          "params": {
            "fill": true,
            "fillLevel": "half"
          }
        }]
      }]
    }
  }]
}
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: {
          currentFillLevel: 'half',
          isFilled: 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("currentFillLevel", "half");
              put("isFilled", true);
          }},
          null
      )
  });
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSON
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "currentFillLevel": "half",
          "isFilled": true
        }
      }
    ]
  }
}