Como depurar a casa local

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 ação de casa inteligente, forneça um endpoint de 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.

72ffb320986092c.png

A depuração das ações de casa inteligente é uma etapa essencial para criar suas ações com qualidade de produção. No entanto, é desafiador e demorado sem ferramentas de teste e solução de problemas informativas e fáceis de usar. Para facilitar a depuração das ações de casa inteligente, as Métricas, o Logging e o Pacote de testes para casas inteligentes do Google Cloud Platform (GCP) estão disponíveis para ajudar você a identificar e resolver problemas nas suas ações.

Pré-requisitos

O que você vai criar

Neste codelab, você vai criar um fulfillment local para ações de casa inteligente e conectá-lo ao Google Assistente. Em seguida, você vai depurar o app Casa local usando o pacote de teste para casas inteligentes e métricas e geração de registros do Google Cloud Platform (GCP).

Neste curso, você vai aprender a:

  • Como usar as métricas do GCP e o Logging para identificar e resolver problemas de produção.
  • Como usar o pacote de testes para identificar problemas funcionais e da API.
  • Como usar o Chrome Dev Tools ao desenvolver o app Local Home.

O que é necessário

2. Executar o app da lavadora

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-debug-local.git

Sobre o projeto

O app inicial contém subdiretórios e funções de nuvem semelhantes ao do codelab Ativar o fulfillment local para ações de casa inteligente. Mas, em vez de app-start, temos app-faulty aqui. Começaremos com um app de casa local que funciona, mas não tão bem.

Conectar-se ao Firebase

Vamos usar o mesmo projeto criado no codelab Ativar o fulfillment local para ações de casa inteligente, mas implantaremos os arquivos transferidos por download neste codelab.

Navegue até o diretório app-faulty e configure a CLI do Firebase com seu projeto do Actions criado no codelab Ativar o fulfillment local para ações de casa inteligente:

$ cd app-faulty
$ firebase use <project-id>

Implantar no Firebase

Navegue até a pasta app-faulty/functions e instale todas as dependências necessárias usando npm:

$ cd functions
$ npm install

Observação: se a mensagem abaixo aparecer, você pode ignorar e continuar. O aviso se deve a algumas dependências mais antigas. Confira mais detalhes.

found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details

Acesse o diretório app-faulty/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 app-faulty/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.

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 deverá aparecer:

...

✔ Deploy complete!

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

Esse comando implanta um app da Web, além de várias funções do Cloud para Firebase.

Atualizar HomeGraph

Abra o URL de hospedagem no navegador (https://<project-id>.web.app) para abrir o app da Web. Na interface da Web, clique no botão Atualizar ae8d3b25777a5e30.png para atualizar o HomeGraph via Request Sync com os metadados mais recentes do dispositivo referentes ao app com falha da lavadora:

fa3c47f293cfe0b7.png

Abra o app Google Home e verifique se o dispositivo da sua lavadora aparece com o nome "Lavadora com defeito". Atribua o dispositivo a um ambiente que tenha um dispositivo Nest.

2a082ee11d47ad1a.png

3. Iniciar a lavadora inteligente

Se você já executou o codelab Ativar o fulfillment local para ações de casa inteligente, provavelmente já iniciou a lavadora inteligente virtual. Se ele tiver sido interrompido, lembre-se de reiniciar o dispositivo virtual.

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

4. Testar o app local do Google Home

Envie comandos para seu dispositivo por comandos de voz para o dispositivo Google Home, como:

"Ok Google, ligar minha lavadora."

"Ok Google, iniciar minha lavadora."

"Ok Google, forçar local."

"Ok Google, parar minha lavadora."

O Google Assistente vai responder com a mensagem "Parece que a lavadora com defeito não está disponível no momento" quando você tentar controlar a lavadora depois de "forçar a localização".

Isso significa que o dispositivo não pode ser acessado por um caminho local. Isso funcionou antes de emitir "Ok Google, forçar local", porque voltaremos a usar o caminho da nuvem quando o dispositivo não estiver acessível por um caminho local. No entanto, depois de "forçar o local", a opção de voltar ao caminho da nuvem é desativada.

Para descobrir qual é o problema, vamos usar as ferramentas que temos: Métricas e Logging do Google Cloud Platform (GCP), além das Ferramentas para desenvolvedores do Chrome.

5. Depurar o app Local Home

Na seção a seguir, você vai usar as ferramentas do Google para descobrir por que o dispositivo não pode ser acessado pelo caminho local. Use as Ferramentas para desenvolvedores do Google Chrome para se conectar ao dispositivo Google Home, conferir os registros do console e depurar o app Local Home. Também é possível enviar registros personalizados ao Cloud Logging para que você saiba quais são os principais erros que os usuários encontram no app Casa local.

Conectar as ferramentas para desenvolvedores do Chrome

Para conectar o depurador ao seu app de fulfillment local, siga estas etapas:

  1. Confira se você vinculou seu dispositivo Google Home a um usuário com permissão para acessar o projeto do Console do Actions.
  2. Reinicie o dispositivo Google Home, para que ele receba o URL do HTML e a configuração de verificação colocada no Console do Actions.
  3. Inicie o Chrome na sua máquina de desenvolvimento.
  4. 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.

567f97789a7d8846.png

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.

774c460c59f9f84a.png

Essa saída significa que o gerenciador IDENTIFICAR foi acionado, mas o verificationId retornado no IdentifyResponse não corresponde a nenhum dos dispositivos no Home Graph. Vamos adicionar alguns registros personalizados para descobrir o motivo.

Adicionar registros personalizados

Embora haja um erro DEVICE_VERIFICATION_FAILED gerado pelo SDK local do Google Home, ele não ajuda muito a encontrar a causa raiz. Vamos adicionar alguns registros personalizados para garantir que estamos lendo e processando os dados da verificação corretamente. Observe que, se rejeitarmos a promessa com um erro, a mensagem de erro também será enviada para o Cloud Logging.

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.
  // Is there something wrong here?
  const localDeviceId = Buffer.from(scanData.data);
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  // Add custom logs
  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_device', 'Invalid device id from scan data ' +
        localDeviceId);
    return Promise.reject(err);
  }

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

Além disso, mude a versão do app Google Home local para que possamos identificar se estamos usando a versão correta.

local/index.ts

const localHomeSdk = new App('1.0.1');

Depois de adicionar os registros personalizados, você precisa compilar o app novamente e reimplantá-lo no Firebase.

$ cd ../app-faulty/local
$ npm run build
$ firebase deploy --only hosting

Agora, reinicialize o dispositivo Google Home para que ele carregue o app de casa local atualizado. Para ver se o dispositivo Google Home está usando a versão esperada, consulte os registros do Console nas Ferramentas para desenvolvedores do Chrome.

ecc56508ebcf9ab.png

Acessar o Cloud Logging

Vamos conferir como usar o Cloud Logging para encontrar erros. Para acessar o Cloud Logging do seu projeto:

  1. No console do Cloud Platform, acesse a página Projetos.
  2. Selecione o projeto de casa inteligente.
  3. Em Operações, selecione Logging > Análise de registros.

O acesso aos dados de registro é gerenciado pelo Identity and Access Management (IAM) para os usuários do seu projeto do Actions. Saiba mais sobre os papéis e as permissões dos dados de registro em Controle de acesso do Cloud Logging.

Usar filtros avançados

Sabemos que estão ocorrendo erros na intent IDENTIFY, já que o caminho local não está funcionando porque o dispositivo local não é identificado. No entanto, queremos saber exatamente qual é o problema, então, vamos filtrar primeiro os erros que ocorrem no gerenciador IDENTIFY.

Expanda a caixa Visualização da consulta. Ela se transformará em uma caixa Criador de consultas. Insira jsonPayload.intent="IDENTIFY" na caixa Criador de consultas e clique no botão Executar consulta.

4c0b9d2828ee2447.png

Como resultado, você recebe todos os registros de erros gerados no gerenciador IDENTIFY. Em seguida, expanda o último erro. Você encontrará o errorCode e o debugString que acabou de definir ao rejeitar a promessa no gerenciador IDENTIFY.

71f2f156c6887496.png

No debugString, podemos dizer que o ID do dispositivo local não está no formato esperado. O app local espera receber o ID do dispositivo local como uma string que começa com deviceid seguida por três dígitos, mas esse ID é uma string hexadecimal.

Corrigir o erro

Voltando ao código-fonte, onde analisamos o ID do dispositivo local nos dados de verificação, percebemos que não fornecemos a codificação ao converter a string em bytes. Os dados de verificação são recebidos como uma string hexadecimal. Portanto, transmita hex como a codificação de caracteres ao chamar Buffer.from().

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');
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
      'invalid_device', 'Invalid device id from scan data ' +
      localDeviceId);
    return Promise.reject(err);
  }

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

Além disso, mude a versão do app Google Home local para que possamos identificar se estamos usando a versão correta.

local/index.ts

const localHomeSdk = new App('1.0.2');

Depois de corrigir o erro, compile o app e implante-o novamente no Firebase. Em app-faulty/local, execute:

$ npm run build
$ firebase deploy --only hosting

Testar a correção

Após a implantação, reinicialize o dispositivo Google Home para que ele possa carregar o app de casa local atualizado. Verifique se a versão do app é a 1.0.2. Desta vez, não haverá erros no console das Ferramentas para desenvolvedores do Chrome.

c8456f7b5f77f894.png

Agora você pode tentar enviar comandos para o dispositivo de novo.

"Ok Google, forçar local".

"Ok Google, parar minha lavadora."

"Ok Google, ligar minha lavadora."

...

"Ok Google, forçar padrão".

6. Executar o pacote de testes para casas inteligentes

Depois de verificar seu dispositivo usando os controles por toque no app Google Home ou por comandos de voz, você poderá usar o Pacote de testes para casa inteligente automatizado para validar casos de uso com base nos tipos e características de dispositivos associados à sua Ação. O Test Suite executa uma série de testes para detectar problemas na sua Ação e mostra mensagens informativas sobre casos de teste com falha para acelerar a depuração antes de se aprofundar nos logs de eventos.

Executar o pacote de testes para casa inteligente

Siga estas instruções para testar a ação de casa inteligente do pacote de testes:

  1. No navegador da Web, abra o Pacote de testes para casa inteligente.
  2. Faça login no Google usando o botão no canto superior direito. Isso permite que o pacote de testes envie os comandos diretamente para o Google Assistente.
  3. No campo ID do projeto, insira o ID do projeto da ação de casa inteligente. Clique em PRÓXIMA para continuar.
  4. Na etapa Configurações de teste, a lavadora com falha aparece na seção Dispositivos e bandejas.
  5. Desative a opção Test Request Sync, já que o app de exemplo da lavadora não tem interface para adicionar, remover ou renomear a lavadora. Em um sistema de produção, é preciso acionar a sincronização de solicitações sempre que o usuário adicionar / remover / renomear dispositivos.
  6. Deixe a opção Local Home SDK ativada porque vamos testar os caminhos local e da nuvem.
  7. Clique em PRÓXIMA para começar a executar o teste.

67433d9190fa770e.png

Quando os testes forem concluídos, você vai perceber que os testes de pausa/retomada no caminho local estão falhando enquanto os testes de pausa/retomada no caminho da nuvem estão sendo aprovados.

d1ebd5cfae2a2a47.png

Analisar mensagem de erro

Confira com mais detalhes as mensagens de erro nos casos de teste com falha. Eles informam qual é o estado esperado para o teste e qual era o estado real. Nesse caso, para "Pause the Washer", o estado esperado é isPaused: true, mas o estado real é isPaused: false. Da mesma forma, para "Pause the Washer", o estado esperado é isPaused: true, mas no estado real recebemos isPaused: false.

6bfd3acef9c16b84.png

Pelas mensagens de erro, parece que estamos definindo o estado isPaused inversamente no caminho local.

Identificar e corrigir o erro

Vamos encontrar o código-fonte para onde o app Local Home envia o comando de execução para o dispositivo. getDataCommand() é a função chamada pelo executeHandler() para definir o payload no comando de execução enviado ao dispositivo.

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                // Is there something wrong here?
                isPaused: params.pause ? false : true
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

De fato, estamos definindo a isPause no estado inverso. Ele precisa ser definido como true quando params.pause for true. Caso contrário, será false. Vamos corrigir isso.

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                isPaused: params.pause ? true : false
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

Mude a versão do app de início local para que possamos identificar se estamos usando a versão correta.

local/index.ts

const localHomeSdk = new App('1.0.3');

Não se esqueça de compilar o app e reimplantá-lo no Firebase. Em app-faulty/local, execute:

$ npm run build
$ firebase deploy --only hosting

Agora, reinicialize o dispositivo Google Home para que ele possa carregar o app de casa local atualizado. Verifique se a versão do app é a 1.0.3.

Testar a correção

Agora, execute novamente o pacote de testes para casas inteligentes com as mesmas configurações. Todos os casos de teste foram aprovados.

b7fc8c5d3c727d8d.png

7. Parabéns

764dbc83b95782a.png

Parabéns! Você aprendeu a resolver problemas de um app de casa local usando o pacote de testes para casa inteligente e o Cloud Logging.

Saiba mais

Veja o que mais você pode fazer:

Saiba mais sobre como testar e enviar uma ação para análise, incluindo o processo de certificação para publicar a ação aos usuários.