1. Introduzione
Il programma Accesso ai dispositivi fornisce l'API Smart Device Management, un'API REST che consente agli sviluppatori di controllare i dispositivi Google Nest dalle loro applicazioni. Gli utenti devono dare il consenso per l'accesso di terze parti ai propri dispositivi Nest.
Per una corretta integrazione del programma Accesso ai dispositivi sono necessari tre passaggi fondamentali:
- Creazione di progetti: crea un progetto in Google Cloud e registrati come sviluppatore nella Console Accesso ai dispositivi.
- Collegamento dell'account: indirizza gli utenti tramite il flusso di collegamento dell'account e recupera un codice di accesso. Scambia il codice con un token di accesso.
- Controllo dei dispositivi: invia richieste all'API Smart Device Management per controllare i dispositivi inviando comandi con il token di accesso.
In questo codelab, approfondiremo il funzionamento di Accesso ai dispositivi creando un'applicazione web per la gestione dell'autenticazione ed effettuando chiamate all'API Smart Device Management. Esploreremo inoltre la distribuzione di un server proxy semplice utilizzando Node.js ed Express per indirizzare le richieste di Accesso ai dispositivi.
Prima di iniziare, sarebbe utile ripassare le tecnologie web più comuni che utilizzeremo in questo codelab, come l'autenticazione con OAuth 2.0 o la creazione di un'app web con Node.js, anche se non si tratta di prerequisiti.
Cosa ti serve
- Node.js 8 o versioni successive
- Account Google a un Nest Thermostat collegato
Obiettivi didattici
- Configurare un progetto Firebase che ospita pagine web statiche e funzioni Cloud Functions
- Inviare richieste di accesso ai dispositivi tramite un'applicazione web basata su browser.
- Creazione di un server proxy con Node.js ed Express per il routing delle richieste
2. Creazione progetto
Per configurare l'integrazione Accesso ai dispositivi, gli sviluppatori devono creare un progetto nella piattaforma Google Cloud. Un ID client e un client secret generati all'interno del progetto Google Cloud verranno utilizzati nell'ambito del flusso OAuth tra l'applicazione dello sviluppatore e Google Cloud. Gli sviluppatori devono anche visitare la Console Accesso ai dispositivi per creare un progetto per accedere all'API Smart Device Management.
Piattaforma Google Cloud
Vai a Google Cloud Platform. Fai clic su Crea un nuovo progetto e fornisci un nome per il progetto. Viene visualizzato anche l'ID progetto [GCP-Project-Id] per Google Cloud. Registralo perché lo utilizzeremo durante la configurazione di Firebase. In questo codelab, ci riferiremo a questo ID come [GCP-Project-Id].
Il primo passaggio consiste nell'abilitare la libreria API necessaria sul nostro progetto. Vai ad API e servizi > Libreria e cerca l'API Smart Device Management. Devi abilitare questa API per autorizzare il tuo progetto a effettuare richieste alle chiamate API Device Access.
Prima di passare alla creazione delle credenziali OAuth, dobbiamo configurare la schermata per il consenso OAuth per il nostro progetto. Vai ad API e servizi > Schermata consenso OAuth. Per Tipo di utente, scegli esterno. Fornisci un nome e un indirizzo email di assistenza per la tua app, oltre ai dati di contatto dello sviluppatore per completare la prima schermata. Quando vengono richiesti gli utenti di prova, assicurati di fornire l'indirizzo email con i dispositivi collegati in questo passaggio.
Dopo aver configurato la schermata per il consenso OAuth, vai ad API e servizi > Credenziali. Fai clic su +Crea credenziali e seleziona ID client OAuth. Come tipo di applicazione, seleziona Applicazione web.
Fornisci un nome per il cliente e fai clic su CREA. Aggiungeremo un'origine JavaScript autorizzata e un URI di reindirizzamento autorizzato in seguito. Completando questa procedura, visualizzerai il [Client-Id] e il [Client-Secret] associati a questo client OAuth 2.0.
Console Accesso ai dispositivi
Vai alla Console Accesso ai dispositivi. Se non hai mai utilizzato la Console Accesso ai dispositivi, verranno visualizzati il contratto relativo ai Termini di servizio e una quota di registrazione di $5.
Crea un nuovo progetto e assegnagli un nome. Nella finestra successiva, specifica l'[Client-Id] che hai ricevuto da Google Cloud nel passaggio precedente.
Se abiliti gli eventi e completi i passaggi per la creazione del progetto, verrà visualizzata la home page del progetto. [Project-Id] verrà elencato sotto il nome che hai assegnato al progetto.
Prendi nota del tuo [Project-Id], che lo utilizzeremo per l'invio di richieste all'API Smart Device Management.
3. Configurazione di Firebase
Firebase offre agli sviluppatori un modo rapido e semplice per eseguire il deployment delle applicazioni web. Svilupperemo un'applicazione web lato client per l'integrazione di Accesso ai dispositivi tramite Firebase.
Crea un progetto Firebase
Vai alla Console Firebase. Fai clic su Aggiungi progetto, quindi seleziona il progetto che hai creato nel passaggio Creazione del progetto. Verrà creato un progetto Firebase, che verrà collegato al tuo progetto Google Cloud [GCP-Project-Id].
Una volta creato il progetto Firebase, dovresti visualizzare la seguente schermata:
Installa Firebase Tools
Firebase fornisce una serie di strumenti di interfaccia a riga di comando per creare ed eseguire il deployment della tua app. Per installare questi strumenti, apri una nuova finestra del terminale ed esegui il comando seguente. Gli strumenti Firebase verranno installati a livello globale.
$ npm i -g firebase-tools
Per verificare che gli strumenti Firebase siano installati correttamente, controlla le informazioni sulla versione.
$ firebase --version
Puoi accedere agli strumenti dell'interfaccia a riga di comando di Firebase con il tuo Account Google con il comando di accesso.
$ firebase login
Inizializza progetto di hosting
Quando riesci ad accedere, il passaggio successivo è inizializzare un progetto di hosting per la tua applicazione web. Dal terminale, vai alla cartella in cui vuoi creare il progetto ed esegui questo comando:
$ firebase init hosting
Firebase ti porrà una serie di domande per aiutarti a iniziare con un progetto di hosting:
- Seleziona un'opzione — Utilizza un progetto esistente
- Seleziona un progetto Firebase predefinito per questa directory: scegli***[GCP-Project-Id]***
- Che cosa vuoi utilizzare come directory pubblica? — Pubblico
- Configurare come app a pagina singola? – Sì
- Vuoi configurare build e deployment automatici con GitHub? - No
Una volta inizializzato il progetto, puoi eseguirne il deployment in Firebase con il seguente comando:
$ firebase deploy
Firebase analizzerà il progetto ed eseguirà il deployment dei file necessari su Cloud Hosting.
Quando apri l'URL di Hosting in un browser, dovresti vedere la pagina di cui hai appena eseguito il deployment:
Ora che conosci le nozioni di base su come eseguire il deployment di una pagina web con Firebase, passiamo al deployment del nostro esempio di codelab.
4. Esempio di codelab
Puoi clonare il repository codelab ospitato su GitHub, utilizzando il comando seguente:
$ git clone https://github.com/google/device-access-codelab-web-app.git
In questo repository, forniamo gli esempi in due cartelle separate. La cartella codelab-start
contiene i file necessari per iniziare da quel momento in questo codelab. La cartella codelab-done
contiene una versione completa di questo codelab, con il client e il server node.js completamente funzionali.
In questo codelab utilizzeremo i file della cartella codelab-start
, ma se dovessi sentirti bloccato in qualsiasi momento, puoi fare riferimento anche alla versione realizzata con il codelab.
File di esempio codelab
La struttura dei file della cartella codelab-start è la seguente:
public ├───index.html ├───scripts.js ├───style.css firebase.json
La cartella pubblica contiene pagine statiche della nostra applicazione. firebase.json
è responsabile del routing delle richieste web alla nostra app. Nella versione codelab-done
, vedrai anche una directory functions
contenente la logica del nostro server proxy (espresso) di cui eseguire il deployment su Google Cloud Functions.
Esempio di deployment del codelab
Copia i file da codelab-start
nella directory del progetto.
$ firebase deploy
Al termine del deployment di Firebase, dovresti essere in grado di vedere l'applicazione Codelab:
L'avvio del flusso di autenticazione richiede le credenziali del partner, di cui parleremo nella prossima sezione.
5. Gestione di OAuth
OAuth è lo standard web per la delega dell'accesso, comunemente utilizzato per concedere ad applicazioni di terze parti l'accesso ai dati del proprio account senza condividere le password. Utilizziamo OAuth 2.0 per consentire agli sviluppatori che accedono ai dispositivi degli utenti tramite il programma Accesso ai dispositivi.
Specifica l'URI di reindirizzamento
Il primo passaggio del flusso OAuth prevede il passaggio di un set di parametri all'endpoint OAuth 2.0 di Google. Dopo aver ottenuto il consenso dell'utente, i server OAuth di Google inviano una richiesta con un codice di autorizzazione all'URI di reindirizzamento.
Aggiorna la costante SERVER_URI
(riga 19) con il tuo URL di Hosting in scripts.js
:
const SERVER_URI = "https://[GCP-Project-Id].web.app";
Se esegui nuovamente il deployment dell'app con questa modifica, l'URI di reindirizzamento utilizzato per il progetto verrà aggiornato.
$ firebase deploy
Abilita URI di reindirizzamento
Dopo aver aggiornato l'URI di reindirizzamento nel file di script, devi anche aggiungerlo all'elenco degli URI di reindirizzamento consentiti per l'ID client creato per il progetto. In Google Cloud, vai alla pagina delle credenziali, dove sono elencate tutte le credenziali create per il tuo progetto:
Nell'elenco ID client OAuth 2.0, seleziona l'ID client che hai creato nel passaggio Creazione progetto. Aggiungi l'URI di reindirizzamento della tua app all'elenco degli URI di reindirizzamento autorizzati per il tuo progetto.
Prova ad accedere.
Vai all'URL di Hosting configurato con Firebase, inserisci le credenziali del tuo partner e fai clic sul pulsante ACCEDI. L'ID client e il client secret sono le credenziali ottenute dalla piattaforma Google Cloud, mentre l'ID progetto proviene dalla console Accesso ai dispositivi.
Il pulsante ACCEDI guiderà gli utenti attraverso il flusso OAuth per la tua azienda, a partire dalla schermata di accesso al loro Account Google. Una volta effettuato l'accesso, agli utenti verrà chiesto di fornire le autorizzazioni necessarie per consentire al tuo progetto di accedere ai propri dispositivi Nest.
Poiché si tratta di un'app fittizia, Google emetterà un avviso prima di emettere un reindirizzamento.
Fai clic su "Avanzate", poi seleziona "Vai all'app web.app (non sicura)" per completare il reindirizzamento alla tua app.
Nella richiesta GET in arrivo verrà fornito un codice OAuth, che l'app sostituirà con un token di accesso e un token di aggiornamento.
6. Controllo dei dispositivi
L'app di esempio Accesso ai dispositivi utilizza le chiamate API REST di Smart Device Management per controllare i dispositivi Google Nest. Queste chiamate prevedono il passaggio del token di accesso nell'intestazione di una richiesta GET o POST, insieme a un payload richiesto per determinati comandi.
Per gestire queste chiamate, abbiamo scritto una funzione di richiesta di accesso generica. Tuttavia, dovrai fornire a questa funzione l'endpoint corretto e, se necessario, l'oggetto payload.
function deviceAccessRequest(method, call, localpath, payload = null) {...}
- . Tipo di richiesta HTTP (
GET
oPOST)
) - call: una stringa che rappresenta la nostra chiamata API, utilizzata per indirizzare le risposte (
listDevices
,thermostatMode
,temperatureSetpoint
) - localpath : l'endpoint a cui viene effettuata la richiesta, contenente l'ID progetto e l'ID dispositivo (accodato dopo
https://smartdevicemanagement.googleapis.com/v1
) - payload (*): dati aggiuntivi richiesti per la chiamata API (ad esempio, un valore numerico che rappresenta la temperatura di un set-point)
Creeremo dei controlli dell'interfaccia utente di esempio (Elenco dispositivi, Imposta modalità, Imposta temperatura) per controllare un termostato Nest:
Questi controlli UI chiameranno le funzioni corrispondenti (listDevices()
, postThermostatMode()
, postTemperatureSetpoint()
) da scripts.js
. che possono essere lasciate vuote per consentirti di implementarle. L'obiettivo è scegliere il metodo/percorso corretto e passare il payload alla funzione deviceAccessRequest(...)
.
Elenco dispositivi
La chiamata di Accesso ai dispositivi più semplice è listDevices
. Utilizza una richiesta GET
e non richiede payload. L'endpoint deve essere strutturato utilizzando projectId
. Completa la funzione listDevices()
nel seguente modo:
function listDevices() { var endpoint = "/enterprises/" + projectId + "/devices"; deviceAccessRequest('GET', 'listDevices', endpoint); }
Salva le modifiche ed esegui di nuovo il deployment del progetto Firebase con il seguente comando:
$ firebase deploy
Una volta implementato la nuova versione dell'app, prova a ricaricare la pagina e fai clic su ELENCO DISPOSITIVI. Dovrebbe essere compilato l'elenco della sezione Controllo dispositivi, dove dovresti vedere l'ID del tuo termostato:
Se scegli i dispositivi dall'elenco, il campo deviceId
nel file scripts.js
verrà aggiornato. Per i prossimi due controlli, dovremo specificare deviceId
per il dispositivo specifico che vogliamo controllare.
Controllo del termostato
Esistono due caratteristiche per il controllo di base di un termostato Nest nell'API Smart Device Management. ThermostatMode e TemperatureSetpoint. ThermostatMode imposta la modalità del tuo termostato Nest su una delle seguenti quattro modalità: {Spento, Caldo, Freddo, Caldo Freddo}. Dobbiamo quindi fornire la modalità selezionata come parte del payload.
Sostituisci la funzione postThermostatMode()
in scripts.js
con il seguente codice:
function postThermostatMode() { var endpoint = "/enterprises/" + projectId + "/devices/" + deviceId + ":executeCommand"; var tempMode = id("tempMode").value; var payload = { "command": "sdm.devices.commands.ThermostatMode.SetMode", "params": { "mode": tempMode } }; deviceAccessRequest('POST', 'thermostatMode', endpoint, payload); }
La prossima funzione, postTemperatureSetpoint()
, gestisce l'impostazione della temperatura (in Celsius) di Nest Thermostat. A seconda della modalità del termostato selezionata, è possibile impostare due parametri nel payload, heatCelsius
e coolCelsius
.
function postTemperatureSetpoint() { var endpoint = "/enterprises/" + projectId + "/devices/" + deviceId + ":executeCommand"; var heatCelsius = parseFloat(id("heatCelsius").value); var coolCelsius = parseFloat(id("coolCelsius").value); var payload = { "command": "", "params": {} }; if ("HEAT" === id("tempMode").value) { payload.command = "sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat"; payload.params["heatCelsius"] = heatCelsius; } else if ("COOL" === id("tempMode").value) { payload.command = "sdm.devices.commands.ThermostatTemperatureSetpoint.SetCool"; payload.params["coolCelsius"] = coolCelsius; } else if ("HEATCOOL" === id("tempMode").value) { payload.command = "sdm.devices.commands.ThermostatTemperatureSetpoint.SetRange"; payload.params["heatCelsius"] = heatCelsius; payload.params["coolCelsius"] = coolCelsius; } else { console.log("Off and Eco mode don't allow this function"); return; } deviceAccessRequest('POST', 'temperatureSetpoint', endpoint, payload); }
7. Server Node.js (facoltativo)
Complimenti! Hai creato un'applicazione web lato client in grado di effettuare richieste all'API Smart Device Management da un browser. Per chi di voi voglia creare sul lato server, vogliamo iniziare subito il vostro lavoro con un server proxy in grado di reindirizzare le richieste dal browser.
Per questo server proxy, utilizzeremo Firebase Cloud Functions, Node.js ed Express.
Inizializza Cloud Functions
Apri una nuova finestra del terminale, vai alla directory del progetto ed esegui questo comando:
$ firebase init functions
Firebase ti porrà una serie di domande per inizializzare Cloud Functions:
- Quale linguaggio vuoi utilizzare per scrivere le funzioni Cloud Functions? - JavaScript
- Vuoi utilizzare ESLint per individuare probabili bug e applicare lo stile? - No
- Vuoi installare ora le dipendenze con npm? – Sì
Questa operazione inizializza una cartella functions
nel tuo progetto, oltre a installare le dipendenze necessarie. Vedrai che la cartella del progetto contiene una directory Functions, con un file index.js per definire le nostre funzioni Cloud Functions, package.json per definire le impostazioni e una directory node_modules per contenere le dipendenze.
Utilizzeremo due librerie npm
per creare la funzionalità lato server: express e xmlhttprequest. Dovrai aggiungere le seguenti voci all'elenco delle dipendenze nel file Package.json:
"xmlhttprequest": "^1.8.0", "express": "^4.17.0"
Quindi, l'esecuzione di npm install dalla directory Functions dovrebbe installare le dipendenze per il progetto:
$ npm install
Nel caso in cui si verifichi un problema con npm durante il download dei pacchetti, puoi provare a salvare xmlhttprequest ed esprimere esplicitamente con il seguente comando:
$ npm install express xmlhttprequest --save
Esegui l'upgrade al piano Blaze
Se utilizzi il comando firebase deploy
, dovrai eseguire l'upgrade al piano Blaze, che richiede l'aggiunta di un metodo di pagamento al tuo account. Vai a Panoramica del progetto > Utilizzo e fatturazione e assicurati di selezionare il piano Blaze per il tuo progetto.
Server Express di build
Un server Express segue un framework semplice per rispondere alle richieste GET
e POST
in arrivo. Abbiamo creato un servlet che rimane in ascolto delle richieste POST
, le trasmette a un URL di destinazione specificato nel payload e risponde con la risposta ricevuta dal trasferimento.
Modifica il file index.js
nella directory Functions in modo che abbia il seguente aspetto:
const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; const functions = require('firebase-functions'); const express = require('express'); const http = require('http'); const app = express(); app.use(express.json()); //***** Device Access - Proxy Server *****// // Serving Get Requests (Not used) app.get('*', (request, response) => { response.status(200).send("Hello World!"); }); // Serving Post Requests app.post('*', (request, response) => { setTimeout(() => { // Read the destination address from payload: var destination = request.body.address; // Create a new proxy post request: var xhr = new XMLHttpRequest(); xhr.open('POST', destination); // Add original headers to proxy request: for (var key in request.headers) { var value = request.headers[key]; xhr.setRequestHeader(key, value); } // Add command/parameters to proxy request: var newBody = {}; newBody.command = request.body.command; newBody.params = request.body.params; // Respond to original request with the response coming // back from proxy request (to Device Access Endpoint) xhr.onload = function () { response.status(200).send(xhr.responseText); }; // Send the proxy request! xhr.send(JSON.stringify(newBody)); }, 1000); }); // Export our app to firebase functions: exports.app = functions.https.onRequest(app);
Per indirizzare le richieste al nostro server, dobbiamo modificare le riscritture da firebase.json
come segue:
{ "hosting": { "public": "public", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [{ "source": "/proxy**", "function": "app" },{ "source": "**", "destination": "/index.html" } ] } }
In questo modo, gli URL che iniziano con /proxy
verranno indirizzati al nostro server Express, mentre gli altri continueranno a essere indirizzati al nostro index.html
.
Chiamate API proxy
Ora che il nostro server è pronto, definiamo un URI proxy in scripts.js
per il nostro browser per inviare richieste a questo indirizzo:
const PROXY_URI = SERVER_URI + "/proxy";
A questo punto, aggiungi una funzione proxyRequest
è scripts.js
, che ha la stessa firma della funzione deviceAccessRequest(...)
, per le chiamate indirette di Accesso ai dispositivi.
function proxyRequest(method, call, localpath, payload = null) { var xhr = new XMLHttpRequest(); // We are doing our post request to our proxy server: xhr.open(method, PROXY_URI); xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); xhr.onload = function () { // Response is passed to deviceAccessResponse function: deviceAccessResponse(call, xhr.response); }; // We are passing the device access endpoint in address field of the payload: payload.address = "https://smartdevicemanagement.googleapis.com/v1" + localpath; if ('POST' === method && payload) xhr.send(JSON.stringify(payload)); else xhr.send(); }
L'ultimo passaggio consiste nel sostituire le chiamate deviceAccessRequest(...)
con la funzione proxyRequest(...)
, nelle funzioni postThermostatMode()
e postTemperatureSetpoint()
all'interno di scripts.js
.
Esegui firebase deploy
per aggiornare l'app.
$ firebase deploy
Ora hai un server proxy Node.js in esecuzione che utilizza Express su Cloud Functions.
Fornisci autorizzazioni per la funzione Cloud Functions
L'ultimo passaggio consiste nel rivedere le autorizzazioni di accesso per le funzioni Cloud Functions e nell'assicurarsi che l'applicazione lato client sia in grado di chiamarle.
Da Google Cloud Platform, vai alla scheda Cloud Functions dal menu, quindi seleziona la tua funzione Cloud Functions:
Fai clic su Autorizzazioni e poi su Aggiungi membro. Scrivi allUsers nel campo del nuovo membro e seleziona Cloud Functions > Invoker di Cloud Functions come ruolo. Facendo clic su Salva viene visualizzato un messaggio di avviso:
Se selezioni Consenti accesso pubblico, la tua applicazione lato client potrà utilizzare la funzione Cloud Functions.
Congratulazioni, hai completato tutti i passaggi. Ora puoi accedere alla tua applicazione web e provare a eseguire i controlli dei dispositivi tramite il tuo server proxy.
Passaggi successivi
Sei alla ricerca di modi per ampliare le tue competenze relative al programma Accesso ai dispositivi? Consulta la documentazione relativa ai tratti per scoprire di più sul controllo di altri dispositivi Nest e consulta il processo di certificazione per conoscere i passaggi necessari per lanciare il tuo prodotto nel mondo.
Approfondisci le tue competenze con l'app di esempio di applicazione web Accesso ai dispositivi, che ti consentirà di sviluppare la tua esperienza codelab e di implementare un'applicazione web funzionante per controllare le videocamere, i campanelli e i termostati Nest.