Smart Home Timer Trait Schema

action.devices.traits.Timer - The Timer trait represents a timer on a device, primarily kitchen appliances such as ovens and microwaves, but not limited to them. For instance, a smart sprinkler controller or smart light switch may have a built-in timer. This trait can be used to control a built-in timer on devices, such as starting a new timer as well as pausing and canceling a running timer, and asking how much time is remaining.

Device ATTRIBUTES

Attribute Definition
maxTimerLimitSec Integer. Required. Indicates the longest timer setting in seconds available on the device.
commandOnlyTimer Boolean. Optional. Defaults to false. Indicates if the device control is capable of one-way or two-way communication. Specifically, if the controller is able to confirm the new state of device after sending the request. If there is no way to confirm if the request is successfully executed, or to get the state of the device, set this field to true.

Sample SYNC Request and Response

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.SYNC"
    }]
}
Node.jsResponse
'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.OVEN',
        traits: [
          'action.devices.traits.TemperatureControl',
          'action.devices.traits.StartStop',
          'action.devices.traits.Timer'
        ],
        name: {
          defaultNames: ['AAA Smart Oven'],
          name: 'Oven',
          nicknames: ['conventional oven']
        },
        willReportState: true,
        attributes: {
          temperatureRange: {
            minThresholdCelsius: 65.5,
            maxThresholdCelcius: 288
          },
          temperatureUnitForUX: 'F',
          pausable: false,
          maxTimerLimitSec: 7200,
          commandOnlyTimer: false
        },
        deviceInfo: {
          manufacturer: 'Smart Oven Manufacturers',
          model: 'F600G',
          hwVersion: '3.2',
          swVersion: '11.4'
        },
        customData: {
          fooValue: 74,
          barValue: true,
          bazValue: 'lambtwirl'
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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.OVEN")
          .addTrait("action.devices.traits.TemperatureControl")
          .addTrait("action.devices.traits.StartStop")
          .addTrait("action.devices.traits.Timer")
          .setName(
              Collections.singletonList("AAA Smart Oven"),
              "oven",
              Collections.singletonList("conventional oven")
          )
          .setWillReportState(true)
          .setAttributes(new JSONObject()
              .put("temperatureRange", new JSONObject()
                  .put("minThresholdCelsius", 65.5)
                  .put("maxThresholdCelsius", 288)
              )
              .put("temperatureUnitForUX", "F")
              .put("pausable", true)
              .put("maxTimerLimitSec", 7200)
              .put("commandOnlyTimer", false)
          )
          .setDeviceInfo("Smart Oven Manufacturers", "F600G", "3.2", "11.4")
          .setCustomData(new JSONObject()
              .put("fooValue", 74)
              .put("barValue", true)
              .put("bazValue", "lambtwirl")
              .toString()
          )
          .build()
  });
  return new SyncResponse(syncRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "123",
        "type": "action.devices.types.OVEN",
        "traits": [
          "action.devices.traits.TemperatureControl",
          "action.devices.traits.StartStop",
          "action.devices.traits.Timer"
        ],
        "name": {
          "defaultNames": [
            "AAA Smart Oven"
          ],
          "name": "Oven",
          "nicknames": [
            "conventional oven"
          ]
        },
        "willReportState": true,
        "attributes": {
          "temperatureRange": {
            "minThresholdCelsius": 65.5,
            "maxThresholdCelcius": 288
          },
          "temperatureUnitForUX": "F",
          "pausable": false,
          "maxTimerLimitSec": 7200,
          "commandOnlyTimer": false
        },
        "deviceInfo": {
          "manufacturer": "Smart Oven Manufacturers",
          "model": "F600G",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "lambtwirl"
        }
      }
    ]
  }
}
Validator

Device STATES

State Definition
timerRemainingSec Integer. Required. Current time remaining in seconds, -1 or [0, maxTimerLimitSec]. Set to -1 to indicate no timer is running.
timerPaused Boolean. Optional. True if a running timer exists but is currently paused.

Sample QUERY Request and Response

How many minutes are left on microwave timer?

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.QUERY",
      "payload": {
        "devices": [{
          "id": "123",
          "customData": {
            "fooValue": 74,
            "barValue": true,
            "bazValue": "foo"
          }
        }, {
          "id": "456",
          "customData": {
            "fooValue": 12,
            "barValue": false,
            "bazValue": "bar"
          }
        }]
      }
    }]
}

Response when successful

Node.jsResponse
'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: {
          timerRemainingSec: 60
        }
      }
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 60);
    }});
}});
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "timerRemainingSec": 60
      }
    }
  }
}

Response when a timer is paused

Node.jsResponse
'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: {
          timerRemainingSec: 60,
          timerPaused: true
        }
      }
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 60);
    }});
}});
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "timerRemainingSec": 60,
        "timerPaused": true
      }
    }
  }
}

Response when no timer is running or paused

Node.jsResponse
'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: {
      errorCode: 'noTimerExists'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@NotNull
@Override
public QueryResponse onQuery(@NotNull QueryRequest queryRequest, @Nullable Map<?, ?> map) {
  QueryResponse.Payload payload = new QueryResponse.Payload();
throw new RuntimeException("noTimerExists");
  return new QueryResponse(queryRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "noTimerExists"
  }
}

Device COMMANDS

Command Parameters/Definition
action.devices.commands.TimerStart

Start a new timer.

timerTimeSec Positive integer. Required. In seconds [1, maxTimerLimitSec].

Returns:

  • On SUCCESS: timerRemainingSec set to remaining seconds.
  • On ERROR: valueOutOfRange
action.devices.commands.TimerAdjust

Adjust a running timer.

timerTimeSec Required. Positive or negative integer in seconds [-maxTimerLimitSec, maxTimerLimitSec]. Agent may return valueOutOfRange error if remaining seconds is smaller than the absolute value of the specified timerTimeSec. For instance, agent may return a valueOutOfRange error if remaining seconds is 20 but timerTimeSec is -30.

Returns:

action.devices.commands.TimerPause

Pause the currently running timer.

Returns:

  • On SUCCESS: timerRemainingSec set to remaining seconds, timerPaused set to true.
  • On ERROR: noTimerExists
action.devices.commands.TimerResume

Resume the currently paused timer.

Returns:

  • On SUCCESS: timerRemainingSec set to remaining seconds.
  • On ERROR: noTimerExists
action.devices.commands.TimerCancel

Stop and delete the currently running or paused timer.

Returns:

  • On SUCCESS: timerRemainingSec set to 0.
  • On ERROR: noTimerExists

Sample EXECUTE Request and Response

Run microwave for 5 minutes.

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.TimerStart",
          "params": {
            "timerTimeSec": 300
          }
        }]
      }]
    }
  }]
}

Response when successful

Node.jsResponse
'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: {
          timerRemainingSec: 300
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 300);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 300
        }
      }
    ]
  }
}

Response when timerTimeSec is out of range

Node.jsResponse
'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: {
          /* Added 60s to a timer with 32s remaining */
          timerRemainingSec: 92
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 92); // Added 60s to a timer that had 32s remaining
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 92
        }
      }
    ]
  }
}

Add 1 minute to microwave timer.

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.TimerAdjust",
          "params": {
            "timerTimeSec": 60
          }
        }]
      }]
    }
  }]
}

Response when successful

Node.jsResponse
1
'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: {
          /* Added 60s to a timer with 32s remaining */
          timerRemainingSec: 92
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
1
@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("timerRemainingSec", 92); // Added 60s to a timer that had 32s remaining
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
1
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 92
        }
      }
    ]
  }
}

Response when no timer is running

Node.jsResponse
'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: {
      errorCode: 'noTimerExists'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@NotNull
@Override
public ExecuteResponse onExecute(@NotNull ExecuteRequest executeRequest, @Nullable Map<?, ?> map) {
  ExecuteResponse.Payload payload = new ExecuteResponse.Payload();
throw new RuntimeException("noTimerExists");
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "noTimerExists"
  }
}

Minus 30 seconds from microwave timer.

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.TimerAdjust",
          "params": {
            "timerTimeSec": -30
          }
        }]
      }]
    }
  }]
}

Response when successful

Node.jsResponse
'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: {
          /* Removed 30s from a timer with 45s remaining */
          timerRemainingSec: 15
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 30); // Rremoved 30s from a timer that had 45s left
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 15
        }
      }
    ]
  }
}

Response when remaining time is too short

Node.jsResponse
'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: {
      errorCode: 'valueOutOfRange'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@NotNull
@Override
public ExecuteResponse onExecute(@NotNull ExecuteRequest executeRequest, @Nullable Map<?, ?> map) {
  ExecuteResponse.Payload payload = new ExecuteResponse.Payload();
throw new RuntimeException("valueOutOfRange");
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "valueOutOfRange"
  }
}

Pause the microwave timer.

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.TimerPause"
        }]
      }]
    }
  }]
}
Node.jsResponse
'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: {
          timerRemainingSec: 240,
          timerPaused: true
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 240);
            put("timerPaused", true);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 240,
          "timerPaused": true
        }
      }
    ]
  }
}

Restart the microwave timer.

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.TimerResume"
        }]
      }]
    }
  }]
}

Response when successful (both running and paused)

Node.jsResponse
'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: {
          timerRemainingSec: 129
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 129);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 129
        }
      }
    ]
  }
}

Response when timer does not exist

Node.jsResponse
'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: {
      errorCode: 'noTimerExists'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@NotNull
@Override
public ExecuteResponse onExecute(@NotNull ExecuteRequest executeRequest, @Nullable Map<?, ?> map) {
  ExecuteResponse.Payload payload = new ExecuteResponse.Payload();
throw new RuntimeException("noTimerExists");
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "noTimerExists"
  }
}

Stop microwave timer.

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.TimerCancel"
        }]
      }]
    }
  }]
}

Response when successful (both running and paused)

Node.jsResponse
1
'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: {
          timerRemainingSec: 0
        }
      }]
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 0);
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "timerRemainingSec": 0
        }
      }
    ]
  }
}

Response when timer does not exist

Node.jsResponse
'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: {
      errorCode: 'noTimerExists'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@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("timerRemainingSec", 92); // Added 60s to a timer that had 32s remaining
        }},
        null
    )
});
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "noTimerExists"
  }
}

Response when another error occurs

Node.jsResponse
'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: {
      errorCode: 'unknownError'
    }
  };
});

// ...

exports.smarthome = functions.https.onRequest(app);
JavaResponse
@NotNull
@Override
public ExecuteResponse onExecute(@NotNull ExecuteRequest executeRequest, @Nullable Map<?, ?> map) {
  ExecuteResponse.Payload payload = new ExecuteResponse.Payload();
throw new RuntimeException("unknownError");
  return new ExecuteResponse(executeRequest.getRequestId(), payload);
}
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "unknownError"
  }
}

Device ERRORS

See the full list of errors and exceptions.

noTimerExists User tried to adjust/pause/cancel/resume/query timer, but agent failed to find a timer.