1. Prima di iniziare
In qualità di sviluppatore di Internet of Things (IoT), puoi creare integrazioni cloud-to-cloud che consentono agli utenti di controllare i propri dispositivi tramite i controlli touch nell'app Google Home e i comandi vocali con l'assistente.
Le integrazioni cloud-to-cloud si basano su Home Graph per fornire dati contestuali sulla casa e sui suoi dispositivi, creando una mappa logica della casa. Questo contesto consente all'assistente di comprendere in modo più naturale le richieste dell'utente in relazione alla sua posizione in casa. Ad esempio, Home Graph può memorizzare il concetto di un soggiorno che contiene più tipi di dispositivi di produttori diversi, come un termostato, una lampada, un ventilatore e un aspirapolvere.
Prerequisiti
- Crea un'integrazione cloud-to-cloud Guida per gli sviluppatori
Cosa creerai
In questo codelab, pubblicherai un servizio cloud che gestisce una lavatrice smart virtuale, quindi creerai un'integrazione cloud-to-cloud e la connetterai all'assistente.
Obiettivi didattici
- Come eseguire il deployment di un servizio cloud per la smart home
- Come collegare il servizio all'assistente
- Come pubblicare le modifiche dello stato del dispositivo su Google
Che cosa ti serve
- Un browser web, ad esempio Google Chrome
- Un dispositivo iOS o Android con l'app Google Home installata
- Node.js versione 10.16 o successive
- Un account di fatturazione Google Cloud.
2. Per iniziare
Attivare Gestione attività
Per utilizzare l'Assistente Google, devi condividere determinati dati sulle attività con Google. 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à dell'Account Google che vuoi utilizzare con l'assistente.
Assicurati che i seguenti pulsanti di attivazione/disattivazione siano abilitati:
- Attività web e app: inoltre, assicurati 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 sul dispositivo
- Attività vocale e audio
Crea un progetto di integrazione cloud-to-cloud
- Vai a Google Play Console.
- Fai clic su Crea progetto, inserisci un nome per il progetto e fai clic su Crea progetto.
Seleziona l'integrazione da cloud a cloud
Nella Home page del progetto nella Developer Console, seleziona Aggiungi integrazione cloud-to-cloud in Cloud-to-cloud.
Installa l'interfaccia a riga di comando di Firebase
L'interfaccia a riga di comando (CLI) di Firebase ti consentirà di pubblicare le tue app web in locale e di eseguirne il deployment su Firebase Hosting.
Per installare la CLI, esegui questo comando npm dal terminale:
npm install -g firebase-tools
Per verificare che la CLI sia stata installata correttamente, esegui:
firebase --version
Autorizza l'interfaccia a riga di comando di Firebase con il tuo Account Google eseguendo:
firebase login
3. Esegui l'app di base
Ora che hai configurato l'ambiente di sviluppo, puoi eseguire il deployment del progetto iniziale per verificare che tutto sia configurato correttamente.
Recupera il codice sorgente
Fai clic sul seguente link per scaricare l'esempio per questo codelab sul tuo computer di sviluppo:
Puoi anche clonare il repository GitHub dalla riga di comando:
git clone https://github.com/google-home/smarthome-washer.git
Informazioni sul progetto
Il progetto iniziale contiene le seguenti sottodirectory:
public:
Un'interfaccia utente 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 per Firebase e Firebase Realtime Database.
Aggiungere Firebase al progetto della console per gli sviluppatori di Google Home
Metodo 1: tramite la console Firebase
- Vai a Firebase.
- Fai clic su Crea un progetto Firebase.
- Nella schermata Crea un progetto, fai clic su Aggiungi Firebase al progetto Google Cloud.
- Nella schermata Inizia, seleziona il progetto Google Cloud che hai appena creato nella console Google Home Developer e poi fai clic su Continua.
Metodo 2: tramite l'interfaccia a riga di comando di Firebase
firebase projects:addfirebase
Seleziona il progetto della console per gli sviluppatori Google Home che hai appena creato per aggiungere Firebase.
Quando Firebase viene aggiunto al progetto Google Home Developer Console, viene visualizzato nella console Firebase. L'ID progetto Firebase corrisponderà all'ID progetto della console per gli sviluppatori Google Home.
Connessione a Firebase
Vai alla directory washer-start
, quindi configura l'interfaccia a riga di comando di Firebase con il tuo progetto di integrazione:
cd washer-start firebase use <project-id>
Configura il progetto Firebase
Inizializza un progetto Firebase.
firebase init
Seleziona le funzionalità della CLI, Realtime Database e Functions.
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed) >( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore ( ) Genkit: Setup a new Genkit project with Firebase (*) Functions: Configure a Cloud Functions directory and its files ( ) App Hosting: Configure an apphosting.yaml file for App Hosting ( ) Hosting: Configure files for Firebase Hosting and (optionally) 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 (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore
Verranno inizializzate le API e le funzionalità necessarie per il progetto.
Quando richiesto, inizializza Realtime Database. Puoi utilizzare la posizione predefinita per l'istanza del 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 una 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 di 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 functions/.gitignore.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Se ESLint è stato attivato per errore, esistono due metodi per disattivarlo:
- Utilizzando la GUI, vai alla cartella
../functions
nel progetto, seleziona il file nascosto.eslintrc.js
ed eliminalo. Non confonderlo con.eslintrc.json
, che ha un nome simile. - Utilizzo della riga di comando:
cd functions rm .eslintrc.js
Nel file washer-start/firebase.json
, completa il codice con:
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"headers": [{
"source" : "**/*.@(js|html)",
"headers" : [ {
"key" : "Cache-Control",
"value" : "max-age=0"
} ]
}],
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
]
}
]
}
Esegui 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 l'URL di hosting nel browser (https://<project-id>.web.app
) per visualizzare l'app web. Vedrai la seguente interfaccia:
Questa UI web rappresenta una piattaforma di terze parti per visualizzare o modificare gli stati dei dispositivi. Per iniziare a compilare il database con le informazioni sul 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 che hai implementato all'Assistente Google utilizzando la console per sviluppatori Google Home.
Configura il progetto Developer Console
Nella scheda Sviluppa, aggiungi un Nome visualizzato per l'interazione. Questo nome verrà visualizzato nell'app Google Home.
In Branding dell'app, carica un file png
per l'icona dell'app, di dimensioni 144 x 144 px e denominato
.
Per attivare il collegamento degli account, utilizza queste impostazioni:
ID client |
|
Client secret |
|
URL autorizzazione |
|
URL del token |
|
In URL di Cloud Fulfillment, inserisci l'URL della tua funzione Cloud Functions che fornisce il fulfillment per gli intent per la smart home.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
Fai clic su Salva per salvare la configurazione del progetto, poi fai clic su Avanti: test per attivare i test sul progetto.
Ora puoi iniziare a implementare i webhook necessari per connettere lo stato del dispositivo all'assistente.
4. Crea una lavatrice
Ora che hai configurato l'integrazione, puoi aggiungere dispositivi e inviare dati. Il tuo servizio cloud deve gestire i seguenti intent:
- L'intent
SYNC
si verifica quando l'assistente vuole sapere quali dispositivi ha connesso l'utente. Viene inviato al tuo servizio quando l'utente collega un account. Devi rispondere con un payload JSON di tutti i dispositivi dell'utente e delle relative funzionalità. - Un intent
QUERY
si verifica quando l'assistente vuole conoscere lo stato attuale di un dispositivo. Devi rispondere con un payload JSON con lo stato di ogni dispositivo richiesto. - Un intent
EXECUTE
si verifica quando l'assistente vuole controllare un dispositivo per conto di un utente. Devi rispondere con un payload JSON con lo stato di esecuzione di ogni dispositivo richiesto. - Un intent
DISCONNECT
si verifica quando l'utente scollega il proprio account dall'assistente. Devi interrompere l'invio di eventi per i dispositivi di questo utente all'assistente.
Nelle sezioni successive aggiornerai le funzioni di cui hai eseguito il deployment in precedenza per gestire questi intent.
Aggiorna la risposta SYNC
Apri functions/index.js
, che contiene il codice per rispondere alle richieste dell'assistente.
Dovrai gestire un intent SYNC
restituendo i metadati e le funzionalità del dispositivo. Aggiorna il codice JSON nell'array onSync
in modo da includere le informazioni sul dispositivo e le caratteristiche consigliate per una lavatrice.
index.js
app.onSync((body) => {
return {
requestId: body.requestId,
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',
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer'],
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1',
},
willReportState: true,
attributes: {
pausable: true,
},
}],
},
};
});
Esegui il deployment in Firebase
Esegui il deployment dell'intent integrato aggiornato utilizzando l'interfaccia a riga di comando di Firebase:
firebase deploy --only functions
Collegamento all'Assistente Google
Per testare l'integrazione cloud-to-cloud, devi collegare il tuo progetto a un Account Google. Ciò consente di eseguire test tramite le piattaforme dell'Assistente Google e l'app Google Home in cui è stato eseguito l'accesso allo stesso account.
- Apri le impostazioni dell'Assistente Google sullo smartphone. Tieni presente che devi aver eseguito l'accesso con lo stesso account della console.
- Vai a Assistente Google > Impostazioni > Controllo della casa (in Assistente).
- Fai clic sull'icona di ricerca in alto a destra.
- Cerca la tua app di test utilizzando il prefisso [test] per trovare l'app di test specifica.
- Seleziona l'elemento. L'Assistente Google si autenticherà con il tuo servizio e invierà una richiesta
SYNC
, chiedendo al tuo servizio di fornire un elenco di dispositivi per l'utente.
Apri l'app Google Home e verifica di poter vedere la tua lavatrice.
5. Gestire comandi e query
Ora che il tuo servizio cloud segnala correttamente la lavatrice a Google, devi aggiungere la possibilità di richiedere lo stato del dispositivo e inviare comandi.
Gestire l'intent QUERY
Un intent QUERY
include un insieme di dispositivi. Per ogni dispositivo, devi rispondere con il suo stato attuale.
In functions/index.js
, modifica l'handler QUERY
per elaborare l'elenco dei dispositivi di destinazione contenuti nella richiesta di intent.
index.js
app.onQuery(async (body) => {
const {requestId} = body;
const payload = {
devices: {},
};
const queryPromises = [];
const intent = body.inputs[0];
for (const device of intent.payload.devices) {
const deviceId = device.id;
queryPromises.push(queryDevice(deviceId)
.then((data) => {
// Add response to device payload
payload.devices[deviceId] = data;
}
));
}
// Wait for all promises to resolve
await Promise.all(queryPromises);
return {
requestId: requestId,
payload: payload,
};
});
Per ogni dispositivo contenuto nella richiesta, restituisce lo stato attuale memorizzato nel database in tempo reale. Aggiorna le funzioni queryFirebase
e queryDevice
per restituire i dati sullo stato della lavatrice.
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,
};
};
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
};
};
Gestire l'intent EXECUTE
L'intent EXECUTE
gestisce i comandi per aggiornare lo stato del dispositivo. La risposta restituisce lo stato di ogni comando, ad esempio SUCCESS
, ERROR
o PENDING
, e il nuovo stato del dispositivo.
In functions/index.js
, modifica il gestore EXECUTE
per elaborare l'elenco delle caratteristiche che richiedono aggiornamenti e l'insieme dei dispositivi di destinazione per ogni comando:
index.js
app.onExecute(async (body) => {
const {requestId} = body;
// Execution results are grouped by status
const result = {
ids: [],
status: 'SUCCESS',
states: {
online: true,
},
};
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(
updateDevice(execution, device.id)
.then((data) => {
result.ids.push(device.id);
Object.assign(result.states, data);
})
.catch(() => functions.logger.error('EXECUTE', device.id)));
}
}
}
await Promise.all(executePromises);
return {
requestId: requestId,
payload: {
commands: [result],
},
};
});
Per ogni comando e dispositivo di destinazione, aggiorna i valori nel database in tempo reale che corrispondono al tratto richiesto. Modifica la funzione updateDevice
per aggiornare il riferimento Firebase appropriato e restituire lo stato del dispositivo aggiornato.
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let 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 = params.start
? {isRunning: true, isPaused: false}
: {isRunning: false, isPaused: false};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
const data = await queryDevice(deviceId);
state = (data.isPaused === false && data.isRunning === false)
? {isRunning: false, isPaused: false}
: {isRunning: !params.pause, isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
6. Testare l'integrazione
Dopo aver implementato tutti e tre gli intent, puoi verificare che l'integrazione controlli la lavatrice.
Esegui il deployment in Firebase
Esegui il deployment dell'intent integrato aggiornato utilizzando l'interfaccia a riga di comando di Firebase:
firebase deploy --only functions
Testare la lavatrice
Ora puoi vedere la variazione del valore quando provi uno dei seguenti comandi vocali tramite lo smartphone:
"Hey Google, accendi la lavatrice."
"Hey Google, metti in pausa la lavatrice."
"Hey Google, ferma la lavatrice."
Puoi anche vedere lo stato attuale della lavatrice ponendo domande.
"Hey Google, la mia lavatrice è accesa?"
"Hey Google, la mia lavatrice è in funzione?"
"Hey Google, a che ciclo è la mia lavatrice?"
Puoi visualizzare queste query e questi comandi nei log visualizzati sotto la funzione nella sezione Funzioni della console Firebase. Scopri di più sui log di Firebase in Scrivere e visualizzare i log.
Puoi trovare queste query e questi comandi anche nella console Google Cloud andando a Logging > Esplora log. Scopri di più sulla registrazione di Google Cloud in Log eventi di accesso con Cloud Logging.
7. Segnalare aggiornamenti a Google
Hai integrato completamente il tuo servizio cloud con gli intent per la smart home, consentendo agli utenti di controllare e interrogare lo stato attuale dei loro dispositivi. Tuttavia, l'implementazione non prevede ancora un modo per il tuo servizio di inviare in modo proattivo all'assistente informazioni sugli eventi, ad esempio modifiche alla presenza o allo stato del dispositivo.
Con Richiedi sincronizzazione, puoi attivare una nuova richiesta di sincronizzazione quando gli utenti aggiungono o rimuovono dispositivi oppure quando le funzionalità del dispositivo cambiano. Con Report State, il tuo servizio cloud può inviare in modo proattivo lo stato di un dispositivo a Home Graph quando gli utenti cambiano fisicamente lo stato di un dispositivo, ad esempio accendendo un interruttore della luce, o lo cambiano utilizzando un altro servizio.
In questa sezione, aggiungerai il codice per chiamare questi metodi dall'app web di frontend.
Abilita l'API HomeGraph
L'API HomeGraph consente di archiviare ed eseguire query sui dispositivi e sui relativi stati all'interno di Home Graph di un utente. Per utilizzare questa API, devi prima aprire la console Google Cloud e attivare l'API HomeGraph.
Nella console Google Cloud, assicurati di selezionare il progetto corrispondente all'integrazione <project-id>.
. Poi, nella schermata della libreria API per l'API HomeGraph, fai clic su Abilita.
Abilita lo stato del report
Le scritture nel trigger Realtime Database attivano la funzione reportstate
nel progetto iniziale. Aggiorna la funzione reportstate
in functions/index.js
per acquisire i dati scritti nel database e pubblicarli in Home Graph utilizzando Report State.
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
functions.logger.info('Firebase write event triggered Report State');
const snapshot = change.after.val();
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
},
},
},
},
};
const res = await homegraph.devices.reportStateAndNotification({
requestBody,
});
functions.logger.info('Report state response:', res.status, res.data);
});
Abilita la sincronizzazione delle richieste
L'aggiornamento dell'icona nell'interfaccia utente web frontend attiva la funzione requestsync
nel progetto iniziale. Implementa la funzione requestsync
in functions/index.js
per chiamare l'API HomeGraph.
index.js
exports.requestsync = functions.https.onRequest(async (request, response) => {
response.set('Access-Control-Allow-Origin', '*');
functions.logger.info(`Request SYNC for user ${USER_ID}`);
try {
const res = await homegraph.devices.requestSync({
requestBody: {
agentUserId: USER_ID,
},
});
functions.logger.info('Request sync response:', res.status, res.data);
response.json(res.data);
} catch (err) {
functions.logger.error(err);
response.status(500).send(`Error requesting sync: ${err}`);
}
});
Esegui il deployment in Firebase
Esegui il deployment del codice aggiornato utilizzando la CLI Firebase:
firebase deploy --only functions
Verificare la tua implementazione
Fai clic sul pulsante Aggiorna nell'interfaccia utente web e verifica di visualizzare una richiesta di sincronizzazione nel log della console Firebase.
A questo punto, modifica gli attributi del dispositivo di lavaggio nella UI web frontend e fai clic su Aggiorna. Verifica di poter visualizzare la modifica dello stato segnalata a Google nei log della console Firebase.
8. Complimenti
Complimenti! Hai integrato correttamente l'assistente con un servizio cloud del dispositivo utilizzando le integrazioni da cloud a cloud.
Scopri di più
Ecco alcune idee che puoi implementare per approfondire l'argomento:
- Aggiungi modalità e pulsanti di attivazione/disattivazione al tuo dispositivo.
- Aggiungi altri trait supportati al tuo dispositivo.
- Scopri l'esecuzione locale per la smart home.
- Dai un'occhiata al nostro esempio GitHub per saperne di più.
Puoi anche scoprire di più su come testare e inviare un'integrazione per la revisione, incluso il processo di certificazione per pubblicarla per gli utenti.