Mejora y protege tus Acciones para casa inteligente

Las Acciones para casa inteligente usan tipos de dispositivo que le avisan a Asistente de Google qué gramática usar con un dispositivo. Las características de dispositivo definen las capacidades de un tipo de dispositivo. Un dispositivo hereda los estados de cada característica de dispositivo agregada a una acción.

dc8dce0dea87cd5c.png

Puedes conectar cualquier característica admitida al tipo de dispositivo que elijas para personalizar la funcionalidad de los dispositivos de tus usuarios. Si quieres implementar características personalizadas en tus acciones que no están disponibles actualmente en el esquema del dispositivo, puedes usar las características Modes y Toggles, que permiten controlar opciones de configuración específicas con un nombre personalizado que definas.

Además de la capacidad de control básica que proporcionan los tipos y las características, la API de Smart Home tiene funciones adicionales para mejorar la experiencia del usuario. Las respuestas de mensajes de error proporcionan comentarios detallados de los usuarios cuando los intents no funcionan. La autenticación de dos factores (2FA) extiende esas respuestas y agrega seguridad adicional a la característica del dispositivo que elijas. Si envías respuestas de error específicas para desafiar bloqueos que emite Asistente, es posible que tu Acción para casa inteligente requiera una autorización adicional a fin de completar un comando.

Requisitos previos

Qué compilarás

En este codelab, usarás Firebase para implementar una integración de casa inteligente compilada previamente y, luego, aprenderás a agregar características no estándares a la lavadora de casa inteligente para controlar el tamaño de la carga y el modo turbo. También implementarás informes de errores y excepciones, y aprenderás a aplicar una confirmación verbal de manera forzosa para activar la lavadora con la autenticación de dos factores.

Qué aprenderás

  • Cómo agregar las características Modes y Toggles a tu acción
  • Cómo crear informes de errores y excepciones
  • Cómo aplicar la autenticación de dos factores

Requisitos

Habilita los Controles de actividad

Habilita los siguientes Controles de actividad en la Cuenta de Google que planeas usar con Asistente:

  • Actividad web y de aplicaciones
  • Información del dispositivo
  • Actividad de voz y audio

Crea un proyecto de Acciones

  1. Ve a Actions on Google Developer Console.
  2. Haz clic en New Project, ingresa un nombre para el proyecto y haz clic en CREATE PROJECT.

AWXw5E1m9zVgvVeyeL3uxwCX6DtWOCK6LRSLmOATFzjMbmE5cSWBdSVhJZDFpEFH2azZTK2eMs6OYYdMJYiGb5bKqFEzxaLyRUYuwVGBlSjXzTyy8Z9CvwpXvRwP7xdycklETzFc7Q

Selecciona la app de casa inteligente

En la pantalla Overview de la Consola de Actions, selecciona Smart home.

36RsBUWBgbgsa5xZ7MJVMm1sIg07nXbfjv0mWCxXViaC5SlbL2gMigw9hgXsZQhNMHLLFOfiKdZsSTNXONFB1i47gksw3SBNpkVYl492WeryOlgxKjpVrLAvg-5cZqu1DI-s5kxM3g

Selecciona la tarjeta de experiencia Smart home y se te dirigirá a la consola de tu proyecto.

pzgHPsmc2LvLoeUvJfkjKQqD_BvO4v8JOPlcrxsmyptFkkjL4PP6LqrM9r5tNvEIfT9HmK-UKw3GWFPXTjqo4nUrhD2o5shUKHBE31OT8iIA69JZCev7_0_nh-lnL2oJHoxGfqqZ4w

Instala Firebase CLI

La interfaz de línea de comandos (CLI) de Firebase te permitirá publicar tus aplicaciones web a nivel local y, luego, implementar tu aplicación web en Firebase Hosting.

Para instalar la CLI, ejecuta el siguiente comando de npm desde la terminal:

npm install -g firebase-tools

Para verificar que la CLI se haya instalado de forma correcta, ejecuta el siguiente comando:

firebase --version

A fin de autorizar Firebase CLI con tu Cuenta de Google, ejecuta el siguiente comando:

firebase login

Habilita la API de HomeGraph

La API de HomeGraph permite almacenar y buscar dispositivos y sus estados en el Home Graph de un usuario. Para usar esta API, primero debes abrir Google Cloud Console y habilitar la API de HomeGraph.

En Google Cloud Console, asegúrate de seleccionar el proyecto que coincida con tu <project-id>. de Acciones. Luego, en la pantalla Biblioteca de la API para la API de HomeGraph, haz clic en Enable.

5SVCzM8IZLi_9DV8M0nEklv16NXkpvM0bIzQK2hSyKyvnFHBxPOz90rbr72ayxzmxd5aNROOqC_Cp4outbdlwJdObDs0DIE_8vYzw6dovoVrP9IZWlWsZxDS7UHOi1jiRbDMG8MqUA

Ahora que ya configuraste tu entorno de desarrollo, puedes implementar el proyecto de inicio a fin de verificar que todo esté configurado de manera correcta.

Obtén el código fuente

Haz clic en el siguiente vínculo para descargar la muestra de este codelab en tu máquina de desarrollo:

Descarga el código fuente

O bien, puedes clonar el repositorio de GitHub desde la línea de comandos.

git clone https://github.com/googlecodelabs/smarthome-traits.git

Descomprime el archivo ZIP descargado.

Acerca del proyecto

El proyecto inicial contiene los siguientes subdirectorios:

  • public: Es una IU de frontend para controlar y supervisar el estado de la lavadora inteligente con facilidad.
  • functions: Es un servicio de nube completamente implementado que administra la lavadora inteligente con Cloud Functions para Firebase y Firebase Realtime Database.

La entrega en la nube proporcionada incluye las siguientes funciones en index.js:

  • fakeauth**:** Extremo de autorización para la vinculación de cuentas
  • faketoken**:** Extremo del token para la vinculación de cuentas
  • smarthome**:** Extremo de entrega de intents de casa inteligente
  • reportstate**:** Invoca la API de Home Graph sobre los cambios de estado del dispositivo
  • requestsync**:** Habilita las actualizaciones del dispositivo del usuario sin solicitar que se vuelva a vincular la cuenta

Cómo conectarse a Firebase

Navega al directorio washer-start y configura Firebase CLI con tu proyecto de Acciones:

cd washer-start
firebase use <project-id>

Cómo implementar en Firebase

Ve a la carpeta functions y, luego, instala todas las dependencias necesarias mediante npm.

cd functions
npm install

Ahora que ya instalaste las dependencias y configuraste tu proyecto, tienes todo listo para ejecutar la app por primera vez.

firebase deploy

Este es el resultado que deberías ver en la consola:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.firebaseapp.com

Este comando implementa una app web, junto con varias Cloud Functions para Firebase.

Abre la URL de Hosting en tu navegador (https://<project-id>.firebaseapp.com) para ver la aplicación web. Verás la siguiente interfaz:

L60eA7MOnPmbBMl2XMipT9MdnP-RaVjyjf0Y93Y1b7mEyIsqZrrwczE7D3RQISRs-iusL1g4XbNmGhuA6-5sLcWefnczwNJEPfNLtwBsO4Tb9YvcAZBI6_rX19z8rxbik9Vq8F2fwg

Esta IU web representa una plataforma de terceros para ver o modificar los estados de los dispositivos. Haz clic en ACTUALIZAR a fin de comenzar a propagar tu base de datos con la información del dispositivo. No verás ningún cambio en la página, pero el estado actual de la lavadora se almacenará en la base de datos.

Es momento de usar la Consola de Actions para conectar el servicio en la nube que implementaste en Asistente de Google.

Configura tu proyecto de la Consola de Actions

En Overview > Build your Action, selecciona Add Action(s). Ingresa la URL de tu Cloud Function que proporciona entregas para los intents de la casa inteligente y haz clic en Save.

https://us-central1-<project-id>.cloudfunctions.net/smarthome

Uso-o00XQXBHvOR9vQq9tmpYDYQJKsFEstsgRFnxPAJf7zJ2FxwhISiodo3dB1Tz49Okd6ivi66fjpo7rarS_GZelglGWCT1r9FzDGUl1r67ddIcIbQrxqN8jG9F9GAKOpk0Ckc-eA

En la pestaña Desarrollo > Invocación, agrega un nombre visible para tu acción y haz clic en Save. Este nombre aparecerá en la app de Google Home.

gvC-TvmKDy-D-xjwkeCjNt__9ErA7DL8hZWa1oH1yPJ9SpYOepDYjxx6WnJ56IG-t37fJ65kmHISQdh72Ot2G-0tu6Flxf4gom5kvx_3hlvFeMqYuFgXr_85pfWWn7VLFHtS55p1zw

s4yc1kOW4XtKUQN1EYegiDLU5oTqmxQ2PNbeaujm26OQmYKKpjug7j5FYmutLSAZ1zBd-ZkcZlL7zyTZqw4bge3_oOeWvJTsqJ-A08vfZwImYQrKiquLskLuTpmMqXEZD1xchhCWGQ

Para habilitar la vinculación de cuentas, selecciona la opción Develop > Account linking en el panel de navegación izquierdo. Usa la siguiente configuración de vinculación de la cuenta:

ID de cliente

ABC123

Secreto del cliente

DEF456

URL de autorización

https://us-central1-.cloudfunctions.net/fakeauth

URL del token

https://us-central1-.cloudfunctions.net/faketoken

rRyZTiBSTuPk3YtJtXjDK1pPftUxsaEhs9jzpvFtbHTD6bEwYxM8jV4MWxiljKA1bKVZrIRoO9O3jtBefLKf_OyMpukPjwIj8zGvyU3UwASzMrnRskl-hVAfAmQVi4sC_zAwgYwRXw

Haz clic en Save para guardar la configuración de vinculación de cuentas y, luego, haz clic en Test a fin de habilitar las pruebas en tu proyecto.

OgUvpQfXioygkRwPcaJpzjyNQDZy6enidUC8YMPaCOrZi0YeWCFsCJV9Gqg-_UfsqTnn4KEg--uE3Ymr0QuamDonF4RyYHtRKcULXABDuaEnj2hq8i20LYj1SrGP_1lQ_UsUB90pGw

Se te redireccionará al simulador. Verifica que se hayan habilitado las pruebas para tu proyecto. Para ello, mueve el mouse sobre el ícono de pruebas en el dispositivo (soCeBB1CkSIEqsBmDc8Cth6EjgcXUnrOHeOpLNlvMiiXM73Rmh8iBK1ZFLFd47kycYqIMq3Fm49ryAGUt79BXVPDyEB1IU3W0fgiL49iqTAVrpRszL10mmxzq_AQTJZVrXor-vne2w).

2zbfeYpG-wEd2SFP07Wc4mJzHakLX7YvrNw3IV0_0Kd-TonfsKIvvjKWlwvrmTm5jLj3XPWqCtcDd5J2z6gwn9fnchpYVraw1j_mE4M0LVppAl5WY5cK7g0uZyhZ3VFFS25yPmyksg

Si deseas probar tu Acción para la casa inteligente, necesitas vincular tu proyecto con una Cuenta de Google. De esta manera, puedes realizar pruebas mediante las superficies de Asistente de Google y la app de Google Home que accedieron a la misma cuenta.

  1. En el teléfono, abre la configuración de Asistente de Google. Ten en cuenta que debes acceder con la misma cuenta que accediste a la consola.
  2. Ve a Asistente de Google > Configuración > Control del hogar (en Asistente).
  3. Selecciona el ícono del signo más en la esquina inferior derecha.
  4. Deberías ver tu app de prueba con el prefijo [test] y el nombre visible que estableciste.
  5. Selecciona ese elemento. Luego, se autenticará Asistente de Google con el servicio y se enviará una solicitud SYNC para que el servicio le proporcione una lista de dispositivos.

Abre la app de Google Home y verifica que puedas ver el dispositivo de la lavadora.

XcWmBVamBZtPfOFqtsr5I38stPWTqDcMfQwbBjetBgxt0FCjEs285pa9K3QXSASptw0KYN2G8yfkT0-xg664V4PjqMreDDs-HPegHjOc4EVtReYPu-WKZyygq9Xmkf8X8z9177nBjQ

Verifica que puedas controlar la lavadora con comandos por voz en la app de Google Home. También deberías ver el cambio de estado del dispositivo en la IU web de frontend de tu entrega en la nube.

Ahora que implementaste una lavadora básica, puedes personalizar los modelos disponibles en tu dispositivo.

La característica a``ction.devices.traits.Modes permite que un dispositivo tenga una cantidad arbitraria de opciones de configuración para un modo, pero solo se puede establecer una a la vez. Agregarás un modo a la lavadora para definir el tamaño de la carga: pequeña, mediana o grande.

Actualiza la respuesta de SYNC

Necesitas agregar información sobre la característica nueva a tu respuesta de SYNC en functions/index.js. Estos datos aparecen en el array de traits y el objeto attributes, como se muestra en el fragmento de código que verás a continuación.

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          // Add Modes trait
          'action.devices.traits.Modes',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          //Add availableModes
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en',
            }],
            settings: [{
              setting_name: 'small',
              setting_values: [{
                setting_synonym: ['small'],
                lang: 'en',
              }]
            }, {
              setting_name: 'medium',
              setting_values: [{
                setting_synonym: ['medium'],
                lang: 'en',
              }]
            }, {
              setting_name: 'large',
              setting_values: [{
                setting_synonym: ['large'],
                lang: 'en',
              }]
            }],
            ordered: true,
          }],
        },
      }],
    },
  };
});

Agrega nuevos comandos del intent EXECUTE

En el intent EXECUTE, agrega el comando action.devices.commands.SetModes como se muestra en el fragmento de código que aparece a continuación.

index.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      Break;
    // Add SetModes command
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
}

Actualiza la respuesta de QUERY

Actualiza tu respuesta de QUERY para informar el estado actual de la lavadora.

Agrega los cambios actualizados a las funciones queryFirebase y queryDevice para obtener el estado como se almacena en Realtime Database.

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    // Add Modes snapshot
    load: snapshotVal.Modes.load,
  };
}

const queryDevice = async (deviceId) => {
  const data = await queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    // Add currentModeSettings
    currentModeSettings: {
      load: data.load,
    },
  };
};

Actualiza el estado del informe

Por último, actualiza tu función reportstate para informar la configuración de carga actual de la lavadora a Home Graph.

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          // Add currentModeSettings
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
        },
      },
    },
  },
};

Cómo implementar en Firebase

Ejecuta el siguiente comando a fin de implementar la acción actualizada:

firebase deploy --only functions

Una vez finalizada la implementación, ve a la IU web y haz clic en el botón Actualizar ae8d3b25777a5e30.png en la barra de herramientas. Se activará una operación de solicitud de sincronización para que Asistente reciba los datos de respuesta de SYNC actualizados.

bf4f6a866160a982.png

Ahora puedes proporcionar un comando para establecer el modo de la lavadora; por ejemplo:

"Hey Google, set the washer load to large" (establece la carga de la lavadora en grande).

Además, puedes hacer preguntas sobre la lavadora. Por ejemplo:

"Hey Google, what is the washer load?" (¿cuál es la carga de la lavadora?).

La característica action.devices.traits.Toggles representa aspectos con un nombre de un dispositivo que tiene un estado verdadero o falso, como el hecho de que el modo turbo esté activado o no.

Actualiza la respuesta de SYNC

En tu respuesta de SYNC, debes agregar información sobre la nueva característica del dispositivo. Aparecerá en el traits y el objeto attributes como se muestra en el fragmento de código que verás a continuación.

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          'action.devices.traits.Modes',
          // Add Toggles trait
          'action.devices.traits.Toggles',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en'
            }],
            settings: [{ ... }],
            ordered: true,
          }],
          //Add availableToggles
          availableToggles: [{
            name: 'Turbo',
            name_values: [{
              name_synonym: ['turbo'],
              lang: 'en',
            }],
          }],
        },
      }],
    },
  };
});

Agrega nuevos comandos del intent EXECUTE

En el intent EXECUTE, agrega el comando action.devices.commands.SetToggles, como se muestra en el fragmento de código que aparece a continuación.

index.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
    // Add SetToggles command
    case 'action.devices.commands.SetToggles':
      state = {Turbo: params.updateToggleSettings.Turbo};
      ref = firebaseRef.child(deviceId).child('Toggles');
      break;
  }

Actualiza la respuesta de QUERY

Por último, debes actualizar tu respuesta de QUERY a fin de informar el modo turbo de la lavadora. Agrega los cambios actualizados a las funciones queryFirebase y queryDevice para obtener el estado del botón de activación como se almacena en Realtime Database.

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    load: snapshotVal.Modes.load,
    // Add Toggles snapshot
    Turbo: snapshotVal.Toggles.Turbo,
  };
}

const queryDevice = async (deviceId) => {
  const data = queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    currentModeSettings: {
      load: data.load,
    },
    // Add currentToggleSettings
    currentToggleSettings: {
      Turbo: data.Turbo,
    },
  };
};

Actualiza el estado del informe

Por último, actualiza tu función reportstate para informar a Home Graph si la lavadora está configurada en turbo.

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
          // Add currentToggleSettings
          currentToggleSettings: {
            Turbo: snapshot.Toggles.Turbo,
          },
        },
      },
    },
  },
};

Cómo implementar en Firebase

Ejecuta el siguiente comando a fin de implementar las funciones actualizadas:

firebase deploy --only functions

En la IU de la Web, haz clic en el botón Actualizar ae8d3b25777a5e30.png para activar una solicitud de sincronización después de que se complete la implementación.

Ahora puedes decir el siguiente comando para configurar el modo turbo de la lavadora:

"Hey Google, turn on turbo for the washer" (activa el modo turbo de la lavadora).

Además, puedes verificar si la lavadora ya está en modo turbo con este comando:

"Hey Google, is my washer in turbo mode?" (¿está activado el modo turbo de la lavadora?).

La administración de errores en tu Acción para casa inteligente te permite informar a los usuarios cuando fallan las respuestas de EXECUTE y QUERY debido a problemas. Las notificaciones crean una experiencia del usuario más positiva cuando este interactúa con tu acción y dispositivo inteligente.

Cada vez que falla una solicitud de EXECUTE o QUERY, tu acción debe mostrar un código de error. Por ejemplo, si quieres arrojar un error cuando un usuario trata de iniciar la lavadora con la puerta abierta, tu respuesta de EXECUTE sería como el siguiente fragmento de código:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "456"
        ],
        "status": "ERROR",
        "errorCode": "deviceLidOpen"
      }
    ]
  }
}

Ahora, cuando un usuario solicita iniciar la lavadora, Asistente responde con lo siguiente:

"The lid is open on the washer. Please close it and try again". (La puerta de la lavadora está abierta. Ciérrala y vuelve a intentarlo).

Las excepciones son similares a los errores, pero indican cuándo una alerta está relacionada con un comando, que puede bloquear la ejecución correcta de la acción o no. Una excepción puede proporcionar información relacionada con la característica StatusReport, como el nivel de la batería o un cambio de estado reciente. Los códigos de excepciones que no generan un bloqueo se muestran con un estado SUCCESS, mientras que los códigos que sí producen un bloqueo se muestran con un estado EXCEPTIONS.

En el fragmento de código que aparece a continuación, se muestra un ejemplo de una respuesta con una excepción:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "SUCCESS",
      "states": {
        "online": true,
        "isPaused": false,
        "isRunning": false,
        "exceptionCode": "runCycleFinished"
      }
    }]
  }
}

Asistente responde lo siguiente:

"The washer has finished running" (terminó el ciclo de la lavadora).

A fin de añadir informes de error para la lavadora, abre functions/index.js y agrega la definición de la clase de error como se muestra en el siguiente fragmento de código:

index.js

app.onQuery(async (body) => {...});

// Add SmartHome error handling
class SmartHomeError extends Error {
  constructor(errorCode, message) {
    super(message);
    this.name = this.constructor.name;
    this.errorCode = errorCode;
  }
}

Actualiza la respuesta de ejecución para que se muestre el código y el estado del error:

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push( ... )
          //Add error response handling
          .catch((error) => {
            functions.logger.error('EXECUTE', device.id, error);
            result.ids.push(device.id);
            if(error instanceof SmartHomeError) {
              result.status = 'ERROR';
              result.errorCode = error.errorCode;
            }
          })
      );
    }
  }
}

Ahora, Asistente puede avisar a los usuarios sobre cualquier código de error que informes. En la próxima sección, encontrarás un ejemplo específico.

Debes implementar la autenticación de dos factores en tu acción si tu dispositivo tiene algún modo que requiera protección o limitarse a un grupo específico de usuarios autorizados, como una actualización de software o la desvinculación de un bloqueo.

Puedes implementar la autenticación de dos factores en todas las características y los tipos de dispositivo, y personalizar si el desafío de seguridad aparece siempre o si se deben cumplir determinados criterios.

Existen tres tipos de desafíos compatibles:

  • No challenge: Es una solicitud y respuesta que no usa un desafío de autenticación (comportamiento predeterminado).
  • ackNeeded: Es una autenticación de dos factores que requiere una confirmación explícita (sí o no).
  • pinNeeded: Es una autenticación de dos factores que requiere un número de identificación personal (PIN).

En este codelab, debes agregar un desafío ackNeeded al comando para encender la lavadora y activar la funcionalidad que muestra un error cuando el desafío de la autenticación de dos factores falla.

Abre functions/index.js y agrega una definición de la clase de error que muestre el código de error y el tipo de desafío como se muestra en el siguiente fragmento de código:

index.js

class SmartHomeError extends Error { ... }

// Add 2FA error handling
class ChallengeNeededError extends SmartHomeError {
  constructor(tfaType) {
    super('challengeNeeded', tfaType);
    this.tfaType = tfaType;
  }
}

Además, debes actualizar la respuesta de ejecución para mostrar el error challengeNeeded de esta manera:

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push( ... )
          .catch((error) => {
            functions.logger.error('EXECUTE', device.id, error);
            result.ids.push(device.id);
            if(error instanceof SmartHomeError) {
              result.status = 'ERROR';
              result.errorCode = error.errorCode;
              //Add 2FA error handling
              if(error instanceof ChallengeNeededError) {
                result.challengeNeeded = {
                  type: error.tfaType
                };
              }
            }
          })
      );
    }
  }
}

Por último, modifica updateDevice para que se requiera la confirmación explícita antes de encender o apagar la lavadora.

index.js

const updateDevice = async (execution,deviceId) => {
  const {challenge,params,command} = execution; //Add 2FA challenge
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      //Add 2FA challenge
      if (!challenge || !challenge.ack) {
        throw new ChallengeNeededError('ackNeeded');
      }
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    ...
  }

  return ref.update(state)
      .then(() => state);
};

Cómo implementar en Firebase

Ejecuta el siguiente comando a fin de implementar la función actualizada:

firebase deploy --only functions

Después de implementar el código actualizado, debes confirmar verbalmente la acción cuando solicitas que Asistente encienda o apague la lavadora, como se ejemplifica a continuación:

Tú: "Hey Google, turn on the washer" (activa la lavadora).

Asistente: "Are you sure you want to turn on the washer?" (¿confirmas que quieres encender la lavadora?).

Tú: "Yes" (sí).

También puedes ver una respuesta detallada para cada paso del flujo de la autenticación de dos factores si abres tus registros de Firebase.

289dbe48f4bb8106.png

674c4f4392e98c1.png

Felicitaciones. Extendiste las funciones de las Acciones para casa inteligente a través de las características Modes y Toggles, y protegiste su ejecución mediante la autenticación de dos factores.

Más información

A continuación, te ofrecemos algunas ideas que puedes implementar para seguir experimentando:

  • Agrega capacidades de ejecución local a tus dispositivos.
  • Usa otro tipo de desafío para la autenticación de dos factores a fin de modificar el estado de tu dispositivo.
  • Actualiza la respuesta de la característica RunCycle de QUERY para que se actualice de forma dinámica.
  • Explora este ejemplo de GitHub.