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, 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.

72ffb320986092c.png

Depurar as ações de casa inteligente é uma etapa essencial para criar 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 casa inteligente do Google Cloud Platform (GCP) estão disponíveis para ajudar você a identificar e resolver problemas das 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. Depois, vai depurar o app Local Home usando o pacote de teste para casas inteligentes e métricas e Logging do Google Cloud Platform (GCP).

O que você vai aprender

  • Como usar as métricas e o Logging do GCP para identificar e resolver problemas de produção.
  • Como usar o Pacote de testes para identificar problemas funcionais e de 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 do Cloud semelhantes ao codelab Ativar o fulfillment local para ações de casa inteligente. Mas, em vez de app-start, temos app-faulty aqui. Vamos começar com um app de início local que funcione, mas não tão bem.

Conectar-se ao Firebase

Vamos usar o mesmo projeto que você criou no codelab Ativar o fulfillment local para ações de casa inteligente, mas implantar os arquivos transferidos por download neste codelab.

Acesse o diretório app-faulty e configure a CLI do Firebase com o 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, ignore e continue. O aviso se deve a algumas dependências mais antigas. Confira mais detalhes neste link.

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 você deverá ver:

...

✔ 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 o HomeGraph

Abra o URL de hospedagem no navegador (https://<project-id>.web.app) para acessar o app da Web. Na IU da Web, clique no botão Atualizar ae8d3b25777a5e30.png para atualizar o HomeGraph pela sincronização de solicitações com os metadados mais recentes do dispositivo provenientes do app da lavadora com defeito:

fa3c47f293cfe0b7.png

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

2a082ee11d47ad1a.png

3. Iniciar a lavadora inteligente

Se você executou o codelab Ativar o fulfillment local para ações de casa inteligente, já deve ter iniciado a lavadora inteligente virtual. Se ele tiver sido interrompido, reinicie o dispositivo virtual.

Ligar 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 Home

Envie 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."

Você vai notar que o Google Assistente responde com "Parece que a lavadora com defeito não está disponível no momento" quando você tenta controlar a lavadora após "forçar local".

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

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

5. Depurar o app Local Home

Na seção a seguir, você vai usar as ferramentas fornecidas pelo 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, ver os registros do console e depurar o app Local Home. Também é possível enviar registros personalizados ao Cloud Logging para identificar os principais erros encontrados pelos usuários no app Local Home.

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 o 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 HomeGraph. Vamos adicionar alguns registros personalizados para descobrir o motivo.

Adicionar registros personalizados

Embora haja um erro DEVICE_VERIFICATION_FAILED mostrado pelo SDK local do Google Home, ele não ajuda muito a encontrar a causa raiz. Vamos adicionar alguns registros personalizados para ler e processar os dados da verificação corretamente. 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 de início 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, será preciso compilar o app e reimplantá-lo no Firebase.

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

Agora, reinicie o dispositivo Google Home para que ele possa carregar o app de casa local atualizado. É possível verificar se o dispositivo Google Home está usando a versão esperada nos registros do Console nas Ferramentas para desenvolvedores do Chrome.

ecc56508ebcf9ab.png

Acessar o Cloud Logging

Vamos aprender a usar o Cloud Logging para encontrar erros. Para acessar o Cloud Logging no seu projeto:

  1. No console do Cloud Platform, acesse a página Projetos.
  2. Selecione seu 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 usuários do projeto do Actions. Para mais detalhes sobre papéis e permissões para dados de registro, consulte Controle de acesso do Cloud Logging.

Usar filtros avançados

Sabemos que estão ocorrendo erros na intent IDENTIFY, porque 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.

Clique no botão Mostrar consulta. Ele vai se transformar em uma caixa do 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ê vai encontrar o errorCode e o debugString que acabou de definir ao rejeitar a promessa no gerenciador IDENTIFY.

71f2f156c6887496.png

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

Corrigir o erro

Voltando ao código-fonte em que analisamos o ID do dispositivo local nos dados de verificação, notamos 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 de início 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 reimplante no Firebase. Em app-faulty/local, execute:

$ npm run build
$ firebase deploy --only hosting

Testar sua correção

Após a implantação, reinicie o dispositivo Google Home para que ele possa carregar o app de casa local atualizado. Verifique se a versão do app de início local é a 1.0.2 para que não haja erros no Console de Ferramentas para Desenvolvedores do Chrome.

c8456f7b5f77f894.png

Agora você pode tentar enviar comandos para o dispositivo novamente.

"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 casa inteligente

Depois de verificar seu dispositivo usando os controles por toque no app Google Home ou por comandos de voz, você pode usar o Pacote de testes para casas inteligentes automatizado para validar casos de uso com base nos tipos de dispositivos e características associados à ação. O pacote de testes executa uma série de testes para detectar problemas na ação e mostra mensagens informativas em casos de teste com falha para acelerar a depuração antes de analisar os 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 Test Suite envie os comandos diretamente ao 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 máquina de lavar com falha deverá aparecer na seção Dispositivos e Trais.
  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, é necessário 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, já que vamos testar os caminhos local e da nuvem.
  7. Clique em Próximo: ambiente de teste 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 passando.

d1ebd5cfae2a2a47.png

Analisar mensagem de erro

Analise mais de perto 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 "Pausar a lavadora", o estado esperado é isPaused: true, mas no estado real temos isPaused: false. Da mesma forma, para "Pausar a lavadora", o estado esperado é isPaused: true, mas no estado real recebemos isPaused: false.

6bfd3acef9c16b84.png

A partir das mensagens de erro, parece que, no caminho local, estamos definindo o estado isPaused de forma inversa.

Identifique e corrija 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 {};
    }
}

Estamos realmente definindo o isPause no estado inverso. Ele precisa ser definido como true quando params.pause for true. Caso contrário, ele 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 implantá-lo outra vez no Firebase. Em app-faulty/local, execute:

$ npm run build
$ firebase deploy --only hosting

Agora, reinicie o dispositivo Google Home para que ele possa carregar o app de casa local atualizado. Confira se a versão do app de início local é a 1.0.3.

Testar sua correção

Agora, execute novamente o pacote de teste para casas inteligentes com as mesmas configurações. Você verá que todos os casos de teste foram aprovados.

b7fc8c5d3c727d8d.png

7. Parabéns

764dbc83b95782a.png

Parabéns! Você aprendeu a resolver problemas em um app de casa local no Pacote de testes para casas inteligentes e o Cloud Logging.

Saiba mais

Veja o que mais você pode fazer:

Saiba mais sobre como testar e enviar uma ação para revisão, incluindo o processo de certificação para publicá-la aos usuários.