Migliora e proteggi le tue azioni per la smart home

1. Prima di iniziare

Le azioni per la smart home utilizzano tipi di dispositivi per comunicare all'Assistente Google le regole grammaticali da utilizzare con un dispositivo. I trait del dispositivo definiscono le funzionalità di un tipo di dispositivo. Un dispositivo eredita gli stati di ogni tratto del dispositivo aggiunto a un'azione.

dc8dce0dea87cd5c.png

Puoi collegare qualsiasi trait supportato al tipo di dispositivo scelto per personalizzare la funzionalità dei tuoi utenti dispositivi mobili. Se vuoi implementare nelle tue Azioni dei trait personalizzati che non sono attualmente disponibili nello schema del dispositivo, i trait Modalità e Attivazione/disattivazione consentono impostazioni specifiche. con un nome personalizzato da te definito.

Oltre alla funzionalità di controllo di base offerta da tipi e caratteristiche, l'API Smart Home ha funzionalità aggiuntive per migliorare l'esperienza utente. Le risposte di errore forniscono un feedback dettagliato all'utente quando gli intent non hanno esito positivo. La verifica utente secondaria estende queste risposte e aggiunge ulteriore sicurezza al tratto del dispositivo che scegli. Inviando risposte di errore specifiche ai blocchi di verifica emessi dall'assistente, l'azione della tua smart home può richiedere un'autorizzazione aggiuntiva per completare un comando.

Prerequisiti

Cosa creerai

In questo codelab, eseguirai il deployment di un'integrazione predefinita per la smart home con Firebase, quindi imparerai ad aggiungere tratti non standard alla smart home per dimensioni di carico e modalità turbo. Implementerai anche la segnalazione di errori ed eccezioni e imparerai a imporre una conferma verbale per attivare la lavatrice utilizzando la verifica utente secondaria.

Obiettivi didattici

  • Come aggiungere le modalità e i trait all'azione
  • Come segnalare errori ed eccezioni
  • Come applicare la verifica utente secondaria

Che cosa ti serve

2. Per iniziare

Attivare Gestione attività

Per poter usare l'Assistente Google, devi condividere con Google determinati dati relativi alle attività. L'Assistente Google ha bisogno di questi dati per funzionare correttamente. Tuttavia, il requisito di condivisione dei dati non è specifico dell'SDK. Per condividere questi dati, crea un Account Google se non ne hai già uno. Puoi utilizzare qualsiasi Account Google, non è necessario che sia il tuo account sviluppatore.

Apri la pagina Gestione attività relativa all'Account Google che vuoi usare con l'assistente.

Assicurati che le seguenti opzioni di attivazione/disattivazione siano attive:

  • Web e Attività nelle app: assicurati inoltre di selezionare la casella di controllo Includi la cronologia di Chrome e le attività svolte su siti, app e dispositivi che usano i servizi Google.
  • Informazioni del dispositivo
  • Voce e Attività audio

Creare un progetto Actions

  1. Vai alla Console per gli sviluppatori di Actions on Google.
  2. Fai clic su Nuovo progetto, inserisci un nome per il progetto e fai clic su CREA PROGETTO.

3d6b68ca79afd54c.png

Seleziona l'app Smart home

Nella schermata Panoramica della console Actions, seleziona Smart home.

2fa4988f44f8914b.png

Scegli la scheda dell'esperienza Smart home, fai clic su Inizia a creare. Si aprirà la console di progetto.

Installa l'interfaccia a riga di comando di Firebase

L'interfaccia a riga di comando di Firebase (CLI) ti consente di pubblicare le app web localmente ed eseguirne il deployment su Firebase Hosting.

Per installare l'interfaccia a riga di comando, esegui questo comando npm dal terminale:

npm install -g firebase-tools

Per verificare che l'interfaccia a riga di comando sia stata installata correttamente, esegui:

firebase --version

Autorizza l'interfaccia a riga di comando di Firebase con il tuo Account Google eseguendo:

firebase login

Abilita l'API HomeGraph

L'API HomeGraph consente di archiviare ed eseguire query sui dispositivi e sul relativo stato all'interno dell'Home Graph di un utente. Per utilizzare questa API, devi prima aprire la console Google Cloud e abilitare l'API HomeGraph.

Nella console Google Cloud, assicurati di selezionare il progetto che corrisponde alle tue azioni <project-id>. Quindi, nella schermata della libreria API per l'API HomeGraph, fai clic su Abilita.

ee198858a6eac112.png

3. Esegui l'app iniziale

Ora che hai configurato l'ambiente di sviluppo, puoi eseguire il deployment del progetto iniziale per verificare che tutto sia configurato correttamente.

Ottieni il codice sorgente

Fai clic sul link seguente per scaricare l'esempio per questo codelab sul tuo computer di sviluppo:

...oppure clonare il repository GitHub dalla riga di comando:

git clone https://github.com/google-home/smarthome-traits.git

Apri il file ZIP scaricato.

Informazioni sul progetto

Il progetto iniziale contiene le seguenti sottodirectory:

  • public: Una UI frontend per controllare e monitorare facilmente lo stato della lavatrice smart.
  • functions: Un servizio cloud completamente implementato che gestisce la lavatrice smart con Cloud Functions for Firebase e Firebase Realtime Database.

Il fulfillment Cloud fornito include le seguenti funzioni in index.js:

  • fakeauth: endpoint di autorizzazione per il collegamento dell'account
  • faketoken: endpoint token per il collegamento dell'account
  • smarthome: endpoint di evasione degli intent per la smart home
  • reportstate: richiama l'API Home Graph quando lo stato del dispositivo cambia
  • requestsync: abilita gli aggiornamenti del dispositivo dell'utente senza richiedere il ricollegamento dell'account.

Connettersi a Firebase

Vai alla directory washer-start, quindi configura l'interfaccia a riga di comando di Firebase con il progetto Actions:

cd washer-start
firebase use <project-id>

Configura un progetto Firebase

Inizializza un progetto Firebase.

firebase init

Seleziona le funzionalità dell'interfaccia a riga di comando, Realtime Database, Funzioni e la funzionalità Hosting che include Firebase Hosting.

? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then
 Enter to confirm your choices.
❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance
 ◯ Firestore: Configure security rules and indexes files for Firestore
 ◉ Functions: Configure a Cloud Functions directory and its files
 ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ◯ Hosting: Set up GitHub Action deploys
 ◯ Storage: Configure a security rules file for Cloud Storage
 ◯ Emulators: Set up local emulators for Firebase products
 ◯ Remote Config: Configure a template file for Remote Config
 ◯ Extensions: Set up an empty Extensions manifest

Verranno inizializzate le API e le funzionalità necessarie per il progetto.

Quando richiesto, inizializza Realtime Database. Puoi utilizzare la località predefinita per l'istanza di database.

? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up?
Yes

? Please choose the location for your default Realtime Database instance:
us-central1

Poiché utilizzi il codice del progetto iniziale, scegli il file predefinito per le regole di sicurezza e assicurati di non sovrascrivere il file delle regole del database esistente.

? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console?
No

Se stai reinizializzando il progetto, seleziona Sovrascrivi quando ti viene chiesto se vuoi inizializzare o sovrascrivere un codebase.

? Would you like to initialize a new codebase, or overwrite an existing one?
Overwrite

Quando configuri le funzioni, devi utilizzare i file predefiniti e assicurarti di non sovrascrivere i file index.js e package.json esistenti nell'esempio del progetto.

? What language would you like to use to write Cloud Functions?
JavaScript

? Do you want to use ESLint to catch probable bugs and enforce style?
No

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

Se stai reinizializzando il progetto, seleziona No quando ti viene chiesto se vuoi inizializzare o sovrascrivere features/.gitignore.

? File functions/.gitignore already exists. Overwrite?
No
? Do you want to install dependencies with npm now?
Yes

Infine, configura la configurazione di Hosting in modo che utilizzi la directory public nel codice del progetto e il file index.html esistente. Seleziona No quando ti viene chiesto di utilizzare ESLint.

? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? Set up automatic builds and deploys with GitHub?
No

? File public/index.html already exists. Overwrite?
 No

Se ESLint è stato abilitato per errore, esistono due metodi per disabilitarlo:

  1. Utilizzando la GUI, vai alla cartella ../functions del progetto, seleziona il file nascosto .eslintrc.js ed eliminalo. Non confonderlo con il nome simile .eslintrc.json.
  2. Tramite la riga di comando:
    cd functions
    rm .eslintrc.js
    

Eseguire il deployment in Firebase

Ora che hai installato le dipendenze e configurato il progetto, puoi eseguire l'app per la prima volta.

firebase deploy

Questo è l'output della console che dovresti vedere:

...

✔ Deploy complete!

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

Questo comando esegue il deployment di un'app web, insieme a diverse Cloud Functions for Firebase.

Apri Hosting URL (URL di hosting) nel browser (https://<project-id>.web.app) per visualizzare l'app web. Verrà visualizzata la seguente interfaccia:

5845443e94705557.png

Questa UI web rappresenta una piattaforma di terze parti per visualizzare o modificare gli stati dei dispositivi. Per iniziare a completare il database con le informazioni del dispositivo, fai clic su AGGIORNA. Non vedrai alcuna modifica nella pagina, ma lo stato attuale della lavatrice verrà memorizzato nel database.

Ora è il momento di connettere il servizio cloud di cui hai eseguito il deployment all'Assistente Google utilizzando la console Actions.

Configura il progetto della console Actions

In Panoramica > Crea la tua azione, seleziona Aggiungi azioni. Inserisci l'URL della funzione Cloud Functions che fornisce il completamento per gli intent della smart home e fai clic su Salva.

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

9d7b223427f587ca.png

Nella scheda Sviluppo > Chiamata, aggiungi un Nome visualizzato per l'azione e fai clic su Salva. Questo nome verrà visualizzato nell'app Google Home.

774d0c40c351c7da.png

a8c4673eb11d76ee.png

Per attivare il collegamento dell'account, seleziona il menu Sviluppo > Collegamento dell'account nel riquadro di navigazione a sinistra. Utilizza queste impostazioni di collegamento dell'account:

ID client

ABC123

Client secret

DEF456

URL autorizzazione

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

URL token

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

9730d20b90bcc038.png

Fai clic su Salva per salvare la configurazione del collegamento dell'account, quindi fai clic su Test per attivare i test sul tuo progetto.

ee0547f05b5efd98.png

Il sistema ti reindirizzerà al Simulatore. Se non visualizzi "Test ora abilitato", fai clic su Reimposta test per verificare che i test siano attivati.

d0495810dbadf059.png

Per testare l'azione per la smart home, devi collegare il tuo progetto a un Account Google. In questo modo è possibile eseguire test tramite le piattaforme dell'Assistente Google e l'app Google Home su cui è stato eseguito l'accesso allo stesso account.

  1. Apri le impostazioni dell'Assistente Google sullo smartphone. Tieni presente che devi aver eseguito l'accesso con lo stesso account della console.
  2. Vai su Assistente Google > Impostazioni > Controllo della casa (nella sezione Assistente).
  3. Fai clic sull'icona di ricerca in alto a destra.
  4. Cerca la tua app di test utilizzando il prefisso [test] per trovare la tua app di test specifica.
  5. Seleziona l'elemento. L'Assistente Google eseguirà quindi l'autenticazione con il tuo servizio e invierà una richiesta SYNC, chiedendo al servizio di fornire un elenco di dispositivi per l'utente.

Apri l'app Google Home e verifica di riuscire a vedere la lavatrice.

ae252220753726f6.png

Verifica di poter controllare la lavatrice tramite i comandi vocali nell'app Google Home. La modifica dello stato del dispositivo dovrebbe essere visualizzata anche nella UI web frontend del tuo fulfillment Cloud.

Ora che hai una lavatrice di base, puoi personalizzare le modalità disponibili sul tuo dispositivo.

4. Aggiungi modalità

Il trait action.devices.traits.Modes consente a un dispositivo di avere un numero arbitrario di impostazioni per una modalità, di cui è possibile configurarne solo una alla volta. Aggiungerai una modalità alla lavatrice per definire le dimensioni del carico della biancheria: piccolo, medio o grande.

Aggiorna risposta SYNC

Devi aggiungere informazioni sul nuovo trait alla tua risposta SYNC in functions/index.js. Questi dati vengono visualizzati nell'array traits e nell'oggetto attributes, come mostrato nel seguente snippet di codice.

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,
          }],
        },
      }],
    },
  };
});

Aggiungi nuovi comandi per intent EXECUTE

Nel tuo intent EXECUTE, aggiungi il comando action.devices.commands.SetModes come mostrato nel seguente snippet di codice.

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;
}

Aggiorna la risposta di QUERY

Dopodiché, aggiorna la tua risposta QUERY per segnalare lo stato attuale della lavatrice.

Aggiungi le modifiche aggiornate alle funzioni queryFirebase e queryDevice per ottenere lo stato archiviato nel 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,
    },
  };
};

Aggiorna stato del report

Infine, aggiorna la funzione reportstate per segnalare l'impostazione di carico attuale della lavatrice in 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,
          },
        },
      },
    },
  },
};

Eseguire il deployment in Firebase

Esegui questo comando per eseguire il deployment dell'azione aggiornata:

firebase deploy --only functions

Al termine del deployment, accedi all'interfaccia utente web e fai clic sul pulsante Aggiorna ae8d3b25777a5e30.png nella barra degli strumenti. Questo attiva una sincronizzazione delle richieste in modo che l'assistente riceva i dati aggiornati per le risposte di SYNC.

bf4f6a866160a982.png

Ora puoi dare un comando per impostare la modalità della lavatrice, ad esempio:

"Hey Google, imposta il carico della lavatrice su grande."

Puoi anche fare domande sulla tua lavatrice, ad esempio:

"Hey Google, qual è il carico della lavatrice?"

5. Aggiungi opzioni di attivazione/disattivazione

Il tratto action.devices.traits.Toggles rappresenta aspetti denominati di un dispositivo in stato vero o falso, ad esempio se la lavatrice è in modalità turbo.

Aggiorna risposta SYNC

Nella risposta di SYNC, devi aggiungere informazioni sul nuovo tratto dispositivo. Verrà visualizzato nell'array traits e nell'oggetto attributes come mostrato nel seguente snippet di codice.

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',
            }],
          }],
        },
      }],
    },
  };
});

Aggiungere nuovi comandi per intent EXECUTE

Nel tuo intent EXECUTE, aggiungi il comando action.devices.commands.SetToggles come mostrato nel seguente snippet di codice.

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;
  }

Aggiorna la risposta di QUERY

Infine, devi aggiornare la risposta QUERY per segnalare la modalità turbo della lavatrice. Aggiungi le modifiche aggiornate alle funzioni queryFirebase e queryDevice per ottenere lo stato di attivazione/disattivazione come archiviato nel 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,
    },
  };
};

Aggiorna stato del report

Infine, aggiorna la funzione reportstate per segnalare a Home Graph se la lavatrice è impostata sulla 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,
          },
        },
      },
    },
  },
};

Eseguire il deployment in Firebase

Esegui questo comando per eseguire il deployment delle funzioni aggiornate:

firebase deploy --only functions

Fai clic sul pulsante Aggiorna ae8d3b25777a5e30.png nella UI web per attivare una sincronizzazione della richiesta al termine del deployment.

Ora puoi dare un comando per impostare la lavatrice in modalità turbo dicendo:

"Hey Google, accendi il turbo della lavatrice."

Puoi anche controllare se la lavatrice è già in modalità turbo chiedendo:

"Hey Google, la mia lavatrice è in modalità turbo?"

6. Segnalare errori ed eccezioni

L'azione Gestione degli errori nell'azione per la smart home ti consente di segnalare agli utenti quando problemi impediscono le risposte di EXECUTE e QUERY. Le notifiche creano un'esperienza più positiva per gli utenti quando interagiscono con il tuo smart device e l'azione.

Ogni volta che una richiesta EXECUTE o QUERY non va a buon fine, l'azione dovrebbe restituire un codice di errore. Se, ad esempio, vuoi generare un errore quando un utente tenta di avviare la lavatrice con il coperchio aperto, la risposta EXECUTE sarà simile al seguente snippet di codice:

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

Ora, quando un utente chiede di accendere la lavatrice, l'assistente risponde dicendo:

"Il coperchio della lavatrice è aperto. Chiudila e riprova."

Le Eccezioni sono simili agli errori, ma indicano quando un avviso è associato a un comando, il che può bloccare o meno l'esecuzione corretta. Un'eccezione può fornire informazioni correlate tramite il tratto StatusReport, ad esempio il livello della batteria o una modifica recente dello stato. I codici di eccezione che non comportano il blocco vengono restituiti con lo stato SUCCESS, mentre i codici di eccezione di blocco vengono restituiti con lo stato EXCEPTIONS.

Un esempio di risposta con un'eccezione è il seguente snippet di codice:

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

L'assistente risponde dicendo:

"La lavatrice non è più in funzione."

Per aggiungere report sugli errori per la tua lavatrice, apri functions/index.js e aggiungi la definizione della classe di errore come visualizzata nel seguente snippet di codice:

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;
  }
}

Aggiorna la risposta di esecuzione in modo che restituisca il codice e lo stato di errore:

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;
            }
          })
      );
    }
  }
}

Ora l'assistente può informare gli utenti di qualsiasi codice di errore che segnali. Troverai un esempio specifico nella prossima sezione.

7. Aggiungere la verifica utente secondaria

Devi implementare la verifica dell'utente secondaria nell'Azione se il tuo dispositivo ha modalità che devono essere protette o devono essere limitate a un determinato gruppo di utenti autorizzati, ad esempio un aggiornamento software o la disattivazione di un blocco.

Puoi implementare la verifica utente secondaria su tutti i tipi e i tratti di dispositivo, personalizzando se la verifica di sicurezza si verifica ogni volta o se devono essere soddisfatti criteri specifici.

Esistono tre tipi di sfide supportati:

  • No challenge: richiesta e risposta che non utilizzano una verifica di autenticazione (questo è il comportamento predefinito)
  • ackNeeded: una verifica utente secondaria che richiede il riconoscimento esplicito (sì o no)
  • pinNeeded: una verifica secondaria dell'utente che richiede un PIN (Personal Identification Number)

Per questo codelab, aggiungi una verifica ackNeeded al comando per attivare la lavatrice e la funzionalità per restituire un errore se la verifica secondaria non va a buon fine.

Apri functions/index.js e aggiungi una definizione della classe di errore che restituisca il codice di errore e il tipo di verifica, come illustrato nello snippet di codice seguente:

index.js

class SmartHomeError extends Error { ... }

// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
  /**
   * Create a new ChallengeNeededError
   * @param {string} suvType secondary user verification challenge type
   */
  constructor(suvType) {
    super('challengeNeeded', suvType);
    this.suvType = suvType;
  }
}

Devi anche aggiornare la risposta di esecuzione per restituire l'errore challengeNeeded come segue:

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 error response handling
              if(error instanceof ChallengeNeededError) {
                result.challengeNeeded = {
                  type: error.suvType
                };
              }
            }
          })
      );
    }
  }
}

Infine, modifica updateDevice in modo che richieda il riconoscimento esplicito per attivare o disattivare la lavatrice.

index.js

const updateDevice = async (execution,deviceId) => {
  const {challenge,params,command} = execution; //Add secondary user challenge
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      //Add secondary user verification 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);
};

Eseguire il deployment in Firebase

Esegui questo comando per eseguire il deployment della funzione aggiornata:

firebase deploy --only functions

Dopo aver implementato il codice aggiornato, devi confermare verbalmente l'operazione quando chiedi all'assistente di accendere o spegnere la lavatrice, nel seguente modo:

Tu: "Hey Google, accendi la lavatrice."

L'assistente: "Vuoi accendere la lavatrice?"

Tu: "Sì".

Puoi anche visualizzare una risposta dettagliata per ogni passaggio del flusso di verifica degli utenti secondario aprendo i log di Firebase.

289dbe48f4bb8106.png

8. Complimenti

674c4f4392e98c1.png

Complimenti! Hai esteso le funzionalità delle Azioni per la smart home tramite i trait Modes e Toggles e ne hai protetto l'esecuzione tramite una verifica utente secondaria.

Scopri di più

Ecco alcune idee che puoi mettere in pratica per approfondire:

  • Aggiungi funzionalità di esecuzione locale ai tuoi dispositivi.
  • Utilizza un tipo di verifica dell'utente secondario diverso per modificare lo stato del dispositivo.
  • Aggiorna la risposta QUERY del trait RunCycle per aggiornarla in modo dinamico.
  • Esplora questo esempio di GitHub.