1. Antes de começar
As integrações de casa inteligente permitem que o Google Assistente controle os dispositivos conectados nas casas dos usuários. Para criar uma integração entre nuvens, você precisa fornecer um endpoint do webhook na nuvem capaz de processar intents de casa inteligente. Por exemplo, quando o usuário diz "Ok Google, acenda as luzes", o Google Assistente envia o comando ao fulfillment da nuvem para atualizar o estado do dispositivo.
Para integrar sua integração de casa inteligente, o SDK local do Google Home adiciona um caminho local para encaminhar as intents de casa inteligente diretamente para um dispositivo Google Home. Isso aumenta a confiabilidade e reduz a latência no processamento dos comandos dos usuários. Assim, é possível criar e implantar um app fulfillment local no TypeScript ou JavaScript que identifique dispositivos e execute comandos em qualquer alto-falante inteligente do Google Home ou smart display do Google Nest. O app se comunica diretamente com os dispositivos inteligentes dos usuários na rede local usando protocolos padrão para executar comandos.
Pré-requisitos
- Criar uma integração entre nuvens (em inglês) Guia para desenvolvedores
- Codelab: lavadora de casa inteligente
- Guia para desenvolvedores: fulfillment local
O que você vai criar
Neste codelab, você vai implantar uma integração de casa inteligente criada com o Firebase, aplicar uma configuração de verificação no Console do desenvolvedor e criar um app local usando o TypeScript para enviar comandos escritos em Node.js para um dispositivo virtual da lavadora.
O que você vai aprender
- Como ativar e configurar o fulfillment local no Play Console.
- Como usar o SDK local do Google Home para escrever um app de fulfillment local.
- Como depurar o app de fulfillment local carregado no alto-falante do Google Home ou no smart display do Google Nest.
O que é necessário
- A versão mais recente do Google Chrome
- Um dispositivo iOS ou Android com o app Google Home
- Um alto-falante inteligente do Google Home ou smart display do Google Nest
- Node.js versão 10.16 ou mais recente
- Uma Conta do Google
- Uma conta de faturamento do Google Cloud
2. Primeiros passos
Ativar os Controles de atividade
Para usar o Google Assistente, você precisa compartilhar determinados dados de atividade com o Google. O Google Assistente precisa desses dados para funcionar corretamente. No entanto, esse requisito não é específico do SDK. Para compartilhar esses dados, crie uma Conta do Google, caso ainda não tenha uma. Você pode usar qualquer Conta do Google. Ela não precisa ser sua conta de desenvolvedor.
Abra a página Controles de atividade da Conta do Google que você quer usar com o Google Assistente.
Verifique se os botões a seguir estão ativados:
- Atividade na Web e de apps: também marque a caixa de seleção Incluir o histórico do Chrome e a atividade em sites, apps e dispositivos que usam serviços do Google.
- Informações do dispositivo
- Atividade de voz e áudio
Criar um projeto de integração entre nuvens
- Acesse o console do desenvolvedor.
- Clique em Criar projeto, insira um nome e clique em Criar projeto.
Selecionar a integração entre nuvens
Na página Início do projeto do console do desenvolvedor, selecione Adicionar integração entre nuvens em Entre nuvens.
Instalar a CLI do Firebase
A interface de linha de comando (CLI, na sigla em inglês) do Firebase permite veicular seus apps da Web localmente e implantá-los no Firebase Hosting.
Para instalar a CLI, execute o seguinte comando NPM no terminal:
npm install -g firebase-tools
Para verificar se a CLI foi instalada corretamente, execute o seguinte:
firebase --version
Autorize a CLI do Firebase com sua Conta do Google executando o seguinte comando:
firebase login
Ativar a API HomeGraph
A API HomeGraph permite armazenar e consultar dispositivos e os estados deles no Home Graph de um usuário. Para usar essa API, primeiro abra o console do Google Cloud e ative a API HomeGraph.
No console do Google Cloud, selecione o projeto que corresponde ao <project-id>.
da sua integração. Em seguida, na tela da biblioteca da API HomeGraph, clique em Ativar.
3. Executar o app inicial
Após configurar o ambiente para desenvolvedores, implante o projeto inicial para verificar se a configuração está correta.
Faça o download do código-fonte
Clique neste link para fazer o download do exemplo deste codelab na máquina de desenvolvimento:
…ou clone o repositório do GitHub da linha de comando:
git clone https://github.com/google-home/smarthome-local.git
Sobre o projeto
O projeto inicial contém os seguintes subdiretórios:
public
: IU da Web de front-end para controlar e monitorar a lavadora inteligentefunctions
: funções do Cloud para implementar o fulfillment em nuvem para a integração entre nuvenslocal
: esqueleto do projeto do app de fulfillment local com gerenciadores de intent emindex.ts
O fulfillment da nuvem fornecido inclui as seguintes funções em index.js
:
fakeauth
: endpoint de autorização para vinculação de contafaketoken
: endpoint de token para vinculação de contasmarthome
: endpoint de fulfillment da intent de casa inteligentereportstate
: invoca a API HomeGraph nas alterações de estado do dispositivoupdateDevice
: endpoint usado pelo dispositivo virtual para acionar o estado do relatório
Conectar-se ao Firebase
Acesse o diretório app-start
e configure a CLI do Firebase com seu projeto de integração entre nuvens:
cd app-start firebase use <project-id>
Configurar o projeto do Firebase
Inicialize um projeto do Firebase.
firebase init
Selecione os recursos da CLI, Realtime Database, Functions e Hosting, que inclui o 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
Isso inicializará as APIs e os recursos necessários para seu projeto.
Quando solicitado, inicialize o Realtime Database. É possível usar o local padrão para a instância do banco de dados.
? 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
Como você está usando o código do projeto inicial, escolha o arquivo padrão para as regras de segurança e tome cuidado para não substituir o arquivo de regras do banco de dados.
? 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 você estiver reinizializando o projeto, selecione Substituir quando for solicitado que você inicialize ou substitua uma base de código.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
Ao configurar as funções, use os arquivos padrão e não substitua os arquivos index.js e package.json da amostra do projeto.
? 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 você estiver reduzindo o projeto, selecione Não quando for perguntado se você quer inicializar ou substituir o arquivo functions/.gitignore.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Por fim, defina a configuração do Hosting para usar o diretório public
no código do projeto e use o arquivo index.html. Selecione Não quando for solicitado usar o 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 o ESLint foi ativado acidentalmente, há dois métodos disponíveis para desativá-lo:
- Usando a GUI, acesse a pasta
../functions
no projeto, selecione o arquivo oculto.eslintrc.js
e exclua-o. Não confunda com.eslintrc.json
, que tem um nome parecido. - Usando a linha de comando:
cd functions rm .eslintrc.js
Para garantir que você tenha uma configuração correta e completa do Firebase, copie o arquivo firebase.json
do diretório washer-done
para o diretório washer-start
, substituindo o arquivo em washer-start
.
No diretório washer-start
:
cp -vp ../washer-done/firebase.json .
Implantar no Firebase
Após instalar as dependências e configurar o projeto, você já pode executar o app pela primeira vez.
firebase deploy
Esta é a resposta do console que você deverá ver:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
O comando implanta um app da Web, além de várias Cloud Functions para Firebase.
Abra o URL de hospedagem no navegador (https://<project-id>.web.app
) para ver o app da Web. Aparecerá a seguinte interface:
Essa IU da Web representa uma plataforma de terceiros para exibir ou modificar estados do dispositivo. Para começar a preencher seu banco de dados com informações do dispositivo, clique em ATUALIZAR. Você não verá mudanças na página, mas o estado atual da lavadora será armazenado no banco de dados.
Agora, conecte o serviço em nuvem que você implantou ao Google Assistente usando o console do desenvolvedor.
Configurar seu projeto do console para desenvolvedores
Na guia Develop, adicione um nome de exibição para a interação. Esse nome aparecerá no app Google Home.
Em Marca do app, faça upload de um arquivo png
para o ícone do app, com tamanho de 144 x 144 px e nome
.
Para ativar a vinculação de contas, use estas configurações:
ID do cliente |
|
Chave secreta do cliente |
|
URL de autorização |
|
URL do token |
|
Em URL de fulfillment do Cloud, insira o URL da função do Cloud que oferece fulfillment para as intents de casa inteligente.
https://us-central1-
Clique em Salvar para salvar a configuração do projeto e, depois, em Próxima: Testar para ativar os testes no projeto.
Agora, você pode começar a implementar os webhooks necessários para conectar o estado do dispositivo ao Google Assistente.
Vincular ao Google Assistente
Para testar a integração entre nuvens, você precisa vincular seu projeto a uma Conta do Google. Isso permite realizar testes usando as plataformas do Google Assistente e o app Google Home, desde que estejam conectados à mesma conta.
- No smartphone, abra as configurações do Google Assistente. Você precisa fazer login na mesma conta que no console.
- Acesse Google Assistente > Configurações > Automação residencial (em Google Assistente).
- Clique no ícone de pesquisa no canto superior direito.
- Pesquise o app de teste usando o prefixo [test] para encontrar o app de teste específico.
- Selecione esse item. O Google Assistente será autenticado com seu serviço e enviará uma solicitação
SYNC
para que o serviço forneça uma lista de dispositivos para o usuário.
Abra o app Google Home e verifique se aparece o dispositivo da lavadora.
Verifique se é possível controlar a lavadora usando comandos de voz no app Google Home. Você também deve ver a mudança de estado do dispositivo na IU da Web de front-end do seu fulfillment na nuvem.
Agora, você pode começar a adicionar o fulfillment local à sua integração.
4. Atualizar o fulfillment da nuvem
Para oferecer compatibilidade com o fulfillment local, você precisa adicionar um novo campo por dispositivo chamado otherDeviceIds
à resposta da nuvem SYNC
que contém um identificador local exclusivo para o dispositivo. Esse campo também indica se é possível controlar esse dispositivo localmente.
Adicione o campo otherDeviceIds
à resposta SYNC
, como mostrado no snippet de código a seguir:
functions/index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: '123',
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [ ... ],
name: { ... },
deviceInfo: { ... },
willReportState: true,
attributes: {
pausable: true,
},
otherDeviceIds: [{
deviceId: 'deviceid123',
}],
}],
},
};
});
Implante o projeto atualizado no Firebase:
firebase deploy --only functions
Após a conclusão da implantação, acesse a interface da Web e clique no botão Atualizar na barra de ferramentas. Isso vai acionar uma operação de sincronização de solicitações para que o Google Assistente receba os dados de resposta SYNC
atualizados.
5. Configurar o fulfillment local
Nesta seção, você vai adicionar as opções de configuração necessárias para o fulfillment local à integração entre nuvens. Durante o desenvolvimento, você publicará o app de fulfillment local no Firebase Hosting, onde o dispositivo Google Home poderá acessar e fazer o download dele.
No console do desenvolvedor do Google Home, acesse Project > Cloud-to-cloud no lado esquerdo da tela e selecione Edit para a integração. Na página Configuração e configuração, role até Fulfillment local e ative a configuração. Digite o seguinte URL em cada campo do URL de teste, insira o ID do projeto e clique em Salvar:
https://<project-id>.web.app/local-home/index.html
Em seguida, precisamos definir como o dispositivo Google Home deve descobrir os dispositivos inteligentes locais. A plataforma local do Google Home é compatível com vários protocolos de descoberta de dispositivos, incluindo mDNS, UPnP e transmissão UDP. Você usará a transmissão UDP para descobrir a lavadora inteligente.
Clique em + Adicionar configuração de verificação em Detecção de dispositivos para adicionar uma nova configuração. Selecione UDP como o protocolo e preencha os seguintes atributos:
Campo | Descrição | Valor sugerido |
Endereço de descoberta | Endereço de descoberta UDP |
|
Porta de transmissão | Porta em que o Google Home envia a transmissão UDP |
|
Porta de escuta | Porta em que o Google Home ouve uma resposta |
|
Pacote Discovery | Payload de dados de transmissão UDP |
|
Por fim, clique em Salvar na parte de baixo da janela para publicar as alterações.
6. Implementar o fulfillment local
Você vai desenvolver seu app de fulfillment local no TypeScript usando o pacote de scripts do SDK local do Google Home. Veja o esqueleto do projeto inicial:
local/index.ts
/// <reference types="@google/local-home-sdk" />
import App = smarthome.App;
import Constants = smarthome.Constants;
import DataFlow = smarthome.DataFlow;
import Execute = smarthome.Execute;
import Intents = smarthome.Intents;
import IntentFlow = smarthome.IntentFlow;
...
class LocalExecutionApp {
constructor(private readonly app: App) { }
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
// TODO: Implement device identification
}
executeHandler(request: IntentFlow.ExecuteRequest):
Promise<IntentFlow.ExecuteResponse> {
// TODO: Implement local fulfillment
}
...
}
const localHomeSdk = new App('1.0.0');
const localApp = new LocalExecutionApp(localHomeSdk);
localHomeSdk
.onIdentify(localApp.identifyHandler.bind(localApp))
.onExecute(localApp.executeHandler.bind(localApp))
.listen()
.then(() => console.log('Ready'))
.catch((e: Error) => console.error(e));
O componente principal do fulfillment local é a classe smarthome.App
. O projeto inicial anexa gerenciadores às intents IDENTIFY
e EXECUTE
e, em seguida, chama o método listen()
para informar ao SDK do Local Home que o app está pronto.
Adicionar o gerenciador de IDENTIFICAÇÃO
O SDK do Local Home aciona seu gerenciador IDENTIFY
quando o dispositivo Google Home descobre dispositivos não verificados na rede local com base na configuração de verificação fornecida no console do desenvolvedor.
Enquanto isso, a plataforma invoca identifyHandler
com os dados de verificação resultantes quando o Google descobre um dispositivo correspondente. No app, a verificação ocorre usando uma transmissão UDP e os dados da verificação fornecidos ao gerenciador IDENTIFY
incluem o payload de resposta enviado pelo dispositivo local.
O gerenciador retorna uma instância de IdentifyResponse
que contém um identificador exclusivo para o dispositivo local. Adicione o seguinte código ao seu método identifyHandler
para processar a resposta UDP proveniente do dispositivo local e determinar o ID do dispositivo local apropriado:
local/index .ts
identifyHandler(request: IntentFlow.IdentifyRequest):
Promise<IntentFlow.IdentifyResponse> {
console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));
const scanData = request.inputs[0].payload.device.udpScanData;
if (!scanData) {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', 'Invalid scan data');
return Promise.reject(err);
}
// In this codelab, the scan data contains only local device ID.
const localDeviceId = Buffer.from(scanData.data, 'hex');
const response: IntentFlow.IdentifyResponse = {
intent: Intents.IDENTIFY,
requestId: request.requestId,
payload: {
device: {
id: 'washer',
verificationId: localDeviceId.toString(),
}
}
};
console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));
return Promise.resolve(response);
}
O campo verificationId
precisa corresponder a um dos valores otherDeviceIds
na resposta SYNC
, que sinaliza o dispositivo como disponível para fulfillment local no Home Graph do usuário. Depois que o Google encontra uma correspondência, esse dispositivo é considerado verificado e pronto para fulfillment local.
Adicionar o gerenciador de EXECUÇÃO
O SDK local do Google Home aciona o gerenciador EXECUTE
quando um dispositivo compatível com o fulfillment local recebe um comando. O conteúdo da intent local é equivalente à intent EXECUTE
enviada ao fulfillment da nuvem. Portanto, a lógica para processar localmente a intent é semelhante ao processamento na nuvem.Ações
O app pode usar soquetes TCP/UDP ou HTTP(S) para se comunicar com dispositivos locais. Neste codelab, HTTP é o protocolo usado para controlar o dispositivo virtual. O número da porta é definido em index.ts
como a variável SERVER_PORT
.
Adicione o seguinte código ao seu método executeHandler
para processar comandos de entrada e enviá-los ao dispositivo local por HTTP:
local/index.ts
executeHandler(request: IntentFlow.ExecuteRequest):
Promise<IntentFlow.ExecuteResponse> {
console.log("EXECUTE intent: " + JSON.stringify(request, null, 2));
const command = request.inputs[0].payload.commands[0];
const execution = command.execution[0];
const response = new Execute.Response.Builder()
.setRequestId(request.requestId);
const promises: Array<Promise<void>> = command.devices.map((device) => {
console.log("Handling EXECUTE intent for device: " + JSON.stringify(device));
// Convert execution params to a string for the local device
const params = execution.params as IWasherParams;
const payload = this.getDataForCommand(execution.command, params);
// Create a command to send over the local network
const radioCommand = new DataFlow.HttpRequestData();
radioCommand.requestId = request.requestId;
radioCommand.deviceId = device.id;
radioCommand.data = JSON.stringify(payload);
radioCommand.dataType = 'application/json';
radioCommand.port = SERVER_PORT;
radioCommand.method = Constants.HttpOperation.POST;
radioCommand.isSecure = false;
console.log("Sending request to the smart home device:", payload);
return this.app.getDeviceManager()
.send(radioCommand)
.then(() => {
const state = {online: true};
response.setSuccessState(device.id, Object.assign(state, params));
console.log(`Command successfully sent to ${device.id}`);
})
.catch((e: IntentFlow.HandlerError) => {
e.errorCode = e.errorCode || 'invalid_request';
response.setErrorState(device.id, e.errorCode);
console.error('An error occurred sending the command', e.errorCode);
});
});
return Promise.all(promises)
.then(() => {
return response.build();
})
.catch((e) => {
const err = new IntentFlow.HandlerError(request.requestId,
'invalid_request', e.message);
return Promise.reject(err);
});
}
Compile o app do TypeScript
Acesse o diretório local/
e execute os seguintes comandos para fazer o download do compilador TypeScript e compilar o app:
cd local npm install npm run build
Isso compila a origem index.ts
(TypeScript) e coloca o seguinte conteúdo no diretório public/local-home/
:
bundle.js
: saída de JavaScript compilada que contém o app local e as dependências.index.html
: página de hospedagem local usada para veicular o app para testes no dispositivo.
Implantar o projeto de teste
Implante os arquivos de projeto atualizados no Firebase Hosting para acessá-los do dispositivo Google Home.
firebase deploy --only hosting
7. Iniciar a lavadora inteligente
Depois, teste a comunicação entre o app de fulfillment local e a lavadora inteligente. O projeto inicial do codelab inclui uma lavadora inteligente virtual, escrita em Node.js, que simula uma lavadora inteligente que pode ser controlada localmente pelos usuários.
Configure o dispositivo
É preciso configurar o dispositivo virtual para usar os mesmos parâmetros UDP aplicados à configuração de verificação para a descoberta de dispositivos no console do desenvolvedor. Além disso, você precisa informar ao dispositivo virtual o ID do dispositivo local e o ID do projeto da integração entre nuvens para usar em eventos de estado do relatório quando o estado do dispositivo mudar.
Parâmetro | Valor sugerido |
ID do dispositivo |
|
Porta de saída de descoberta |
|
Pacote de descoberta |
|
projectId | O ID do projeto da sua integração entre nuvens |
Iniciar o dispositivo
Acesse o diretório virtual-device/
e execute o script do dispositivo, transmitindo os parâmetros de configuração como argumentos:
cd virtual-device npm install npm start -- \ --deviceId=deviceid123 --projectId=<project-id> \ --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK
Verifique se o script de dispositivo é executado com os parâmetros esperados:
(...): UDP Server listening on 3311 (...): Device listening on port 3388 (...): Report State successful
8. Depurar o app TypeScript
Na seção a seguir, você vai conferir se o dispositivo Google Home pode verificar, identificar e enviar comandos corretamente à lavadora inteligente virtual usando a rede local. Você pode usar as Ferramentas para desenvolvedores do Google Chrome para se conectar ao dispositivo Google Home, visualizar os registros do console e depurar o app TypeScript.
Conectar as ferramentas para desenvolvedores do Chrome
Para conectar o depurador ao seu app de fulfillment local, siga estas etapas:
- Verifique se você vinculou seu dispositivo Google Home a um usuário com permissão para acessar o projeto do Console do desenvolvedor.
- Reinicie o dispositivo Google Home para que ele receba o URL do HTML e a configuração de verificação colocada no Console do desenvolvedor.
- Inicie o Chrome na sua máquina de desenvolvimento.
- Abra uma nova guia do Chrome e digite
chrome://inspect
no campo de endereço para iniciar o inspetor.
Você verá uma lista de dispositivos na página e o URL do aplicativo aparecerá abaixo do nome do dispositivo Google Home.
Iniciar o inspetor
Clique em Inspecionar abaixo do URL do aplicativo para iniciar as Ferramentas para desenvolvedores do Chrome. Selecione a guia Console e confirme se aparece o conteúdo da intent IDENTIFY
impresso pelo app do TypeScript.
Isso significa que o app de fulfillment local descobriu e identificou o dispositivo virtual.
Testar o fulfillment local
Envie comandos para seu dispositivo usando os controles de toque no app Google Home ou pelos comandos de voz para o dispositivo do Google Home, como:
"Ok Google, ligar minha lavadora."
"Ok Google, iniciar minha lavadora."
"Ok Google, parar minha lavadora."
Isso acionará a plataforma para enviar uma intent EXECUTE
ao seu app TypeScript.
Verifique se aparece a mudança de estado da lavadora inteligente local com cada comando.
... ***** The washer is RUNNING ***** ... ***** The washer is STOPPED *****
9. Parabéns
Parabéns! Você usou o SDK local do Google Home para integrar o fulfillment local a uma integração entre nuvens.
Saiba mais
Veja o que mais você pode fazer:
- Alterar a configuração da verificação para que ela funcione. Por exemplo, tente usar outra porta UDP ou outro pacote de descoberta.
- Modifique a base do código do dispositivo inteligente virtual para executá-lo em um dispositivo incorporado, como um Raspberry Pi, e use LEDs ou uma tela para visualizar o estado atual.