Esta é a Central do desenvolvedor do Google Home, a nova plataforma para aprender a desenvolver ações de casa inteligente. Observação: você continua criando ações no Console do Actions.

Implementar o app de fulfillment local

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Para oferecer compatibilidade com o fulfillment local, você precisa criar um app para lidar com essas intents de casa inteligente:

  • IDENTIFY: compatível com a descoberta de dispositivos inteligentes com controle local. O gerenciador de intents extrai dados que o dispositivo inteligente retorna durante a descoberta e os envia em resposta ao Google.
  • EXECUTE: permite a execução de comandos.
  • QUERY: permite consultar o estado do dispositivo.
  • REACHABLE_DEVICES: (opcional) é compatível com a descoberta de dispositivos finais controláveis localmente por trás de um dispositivo de hub (ou ponte).

Este app é executado nos dispositivos Google Home ou Google Nest do usuário e conecta seu dispositivo inteligente ao Google Assistente. Você pode criar o app usando o TypeScript (preferencial) ou o JavaScript.

O TypeScript é recomendado porque você pode usar vinculações para garantir que os dados retornados pelo app correspondam aos tipos esperados pela plataforma.

Para mais detalhes sobre a API, consulte a Referência da API do SDK local do Google Home.

Os snippets a seguir mostram como inicializar o app de fulfillment local e anexar os gerenciadores.

Independente
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Hub
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

Criar seu projeto

Para implantar o app de fulfillment local, você precisa criar um pacote JavaScript para o código e todas as dependências dele.

Use o inicializador do projeto do app de fulfillment local para inicializar a estrutura do projeto adequada com a configuração do seu bundler preferido.

Modelos de projeto

Para selecionar a configuração do bundler, execute o comando npm init conforme mostrado nos exemplos a seguir:

Nenhum

TypeScript sem configuração do bundler:

npm init @google/local-home-app project-directory/ --bundler none

Estrutura do projeto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Substitua project-directory por um novo diretório que conterá o projeto de fulfillment do app local.

Pacote de Web

TypeScript com a configuração do bundler webpack:

npm init @google/local-home-app project-directory/ --bundler webpack

Estrutura do projeto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.web.js
├── webpack.config.node.js
└── serve.js

Substitua project-directory por um novo diretório que conterá o projeto de fulfillment do app local.

Visualização completa

TypeScript com a configuração do bundler Rollup:

npm init @google/local-home-app project-directory/ --bundler rollup

Estrutura do projeto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Substitua project-directory por um novo diretório que conterá o projeto de fulfillment do app local.

Parcel

TypeScript com a configuração do bundler Parcel:

npm init @google/local-home-app project-directory/ --bundler parcel

Estrutura do projeto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Substitua project-directory por um novo diretório que conterá o projeto de fulfillment do app local.

Realizar tarefas comuns no nível do projeto

O projeto gerado é compatível com os seguintes scripts npm:

Pacote
cd project-directory/
npm run build

Esse script compila a fonte do TypeScript e agrupa o app com as dependências para o ambiente de execução do Chrome no subdiretório dist/web e o ambiente de execução Node.js no subdiretório dist/node.

Verificar
cd project-directory/
npm run lint
npm run compile
npm test

Esse script verifica a sintaxe do seu código TypeScript, compila-o sem produzir nenhuma saída no subdiretório dist/ e executa testes automatizados em test.ts.

Exibição
cd project-directory/
npm run start

Durante o desenvolvimento, esse script disponibiliza os pacotes de app para os ambientes de execução do Chrome e do Node.js localmente.

Implementar o gerenciador IDENTIFY

O gerenciador IDENTIFY será acionado quando o dispositivo Google Home ou Google Nest for reiniciado e ver dispositivos locais não verificados, incluindo dispositivos finais conectados a um hub. A plataforma Home Local procurará dispositivos locais usando as informações de configuração de verificação que você especificou anteriormente e chamará o gerenciador IDENTIFY com os resultados da verificação.

O IdentifyRequest da plataforma local do Google Home contém os dados de verificação de uma instância do LocalIdentifiedDevice. Somente uma instância de device é preenchida, com base na configuração de verificação que descobriu o dispositivo.

Se os resultados da verificação corresponderem ao dispositivo, o gerenciador IDENTIFY vai retornar um objeto IdentifyResponsePayload, que inclui um objeto device com metadados de casa inteligente (como tipos, características e estado do relatório).

O Google estabelece uma associação de dispositivos se o verificationId da resposta IDENTIFY corresponder a um dos valores otherDeviceIds retornados pela resposta SYNC.

Exemplo

Os snippets a seguir mostram como criar gerenciadores IDENTIFY para integrações independentes de dispositivo e hub, respectivamente.

Independente
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const verificationId = "local-device-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: device.id || "",
          verificationId, // Must match otherDeviceIds in SYNC response
        },
      },
    };
    return response;
  };
Hub
const identifyHandler = (request: IntentFlow.IdentifyRequest):
  IntentFlow.IdentifyResponse => {

    // Obtain scan data from protocol defined in your scan config
    const device = request.inputs[0].payload.device;
    if (device.udpScanData === undefined) {
      throw Error("Missing discovery response");
    }
    const scanData = device.udpScanData.data;

    // Decode scan data to obtain metadata about local device
    const proxyDeviceId = "local-hub-id";

    // Return a response
    const response: IntentFlow.IdentifyResponse = {
      intent: Intents.IDENTIFY,
      requestId: request.requestId,
      payload: {
        device: {
          id: proxyDeviceId,
          isProxy: true,     // Device can control other local devices
          isLocalOnly: true, // Device not present in `SYNC` response
        },
      },
    };
    return response;
  };

Identificar dispositivos em um hub

Se o Google identificar um dispositivo de hub, ele o tratará como o canal para os dispositivos finais conectados do hub e tentará verificar esses dispositivos.

Para permitir que o Google confirme a presença de um dispositivo hub, siga estas instruções para o gerenciador IDENTIFY:

  • Se a resposta SYNC informar os IDs dos dispositivos finais locais conectados ao hub, defina isProxy como true em IdentifyResponsePayload.
  • Se a resposta SYNC não informar o dispositivo hub, defina isLocalOnly como true em IdentifyResponsePayload.
  • O campo device.id contém o ID do dispositivo local para o próprio dispositivo hub.

Implementar o gerenciador REACHABLE_DEVICES (somente integrações de hub)

A intent REACHABLE_DEVICES é enviada pelo Google para confirmar quais dispositivos finais podem ser controlados localmente. Essa intent é acionada sempre que o Google executa uma verificação de descoberta (cerca de uma vez por minuto), desde que o hub seja detectado como on-line.

Você implementa o gerenciador REACHABLE_DEVICES de forma semelhante ao gerenciador IDENTIFY, mas o gerenciador precisa coletar outros IDs de dispositivos que podem ser acessados pelo dispositivo de proxy local (ou seja, o hub). O campo device.verificationId contém o ID do dispositivo local de um dispositivo final conectado ao hub.

O ReachableDevicesRequest da plataforma local de casas contém uma instância de LocalIdentifiedDevice. Com essa instância, é possível receber o ID do dispositivo proxy, bem como os dados dos resultados da verificação.

Seu gerenciador REACHABLE_DEVICES precisa retornar um objeto ReachableDevicesPayload que inclua um objeto devices que contém uma matriz de valores verificationId que representam os dispositivos finais controlados pelo hub. Os valores verificationId precisam corresponder a um dos otherDeviceIds da resposta SYNC.

O snippet a seguir mostra como criar o gerenciador REACHABLE_DEVICES.

Hub
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest):
  IntentFlow.ReachableDevicesResponse => {

    // Reference to the local proxy device
    const proxyDeviceId = request.inputs[0].payload.device.id;

    // Gather additional device ids reachable by local proxy device
    // ...

    const reachableDevices = [
      // Each verificationId must match one of the otherDeviceIds
      // in the SYNC response
      { verificationId: "local-device-id-1" },
      { verificationId: "local-device-id-2" },
    ];

    // Return a response
    const response: IntentFlow.ReachableDevicesResponse = {
      intent: Intents.REACHABLE_DEVICES,
      requestId: request.requestId,
      payload: {
        devices: reachableDevices,
      },
    };
    return response;
  };

Implementar o gerenciador EXECUTE

O gerenciador EXECUTE no app processa comandos do usuário e usa o SDK da casa local para acessar os dispositivos inteligentes usando um protocolo.

A plataforma Home Local passa o mesmo payload de entrada para a função de gerenciador EXECUTE da intent EXECUTE no fulfillment da nuvem. Da mesma forma, o gerenciador EXECUTE retorna dados de saída no mesmo formato, desde o processamento da intent EXECUTE. Para simplificar a criação da resposta, use a classe Execute.Response.Builder fornecida pelo SDK local do Google Home.

O app não tem acesso direto ao endereço IP do dispositivo. Em vez disso, use a interface CommandRequest para criar comandos com base em um destes protocolos: UDP, TCP ou HTTP. Em seguida, chame a função deviceManager.send() para enviar os comandos.

Ao segmentar comandos para dispositivos, use o ID do dispositivo (e os parâmetros do campo customData, se incluído) da resposta SYNC para se comunicar com o dispositivo.

Exemplo

O snippet de código a seguir mostra como criar o gerenciador EXECUTE.

Independente/Hub
const executeHandler = (request: IntentFlow.ExecuteRequest):
  Promise<IntentFlow.ExecuteResponse> => {

    // Extract command(s) and device target(s) from request
    const command = request.inputs[0].payload.commands[0];
    const execution = command.execution[0];

    const response = new Execute.Response.Builder()
      .setRequestId(request.requestId);

    const result = command.devices.map((device) => {
      // Target id of the device provided in the SYNC response
      const deviceId = device.id;
      // Metadata for the device provided in the SYNC response
      // Use customData to provide additional required execution parameters
      const customData: any = device.customData;

      // Convert execution command into payload for local device
      let devicePayload: string;
      // ...

      // Construct a local device command over TCP
      const deviceCommand = new DataFlow.TcpRequestData();
      deviceCommand.requestId = request.requestId;
      deviceCommand.deviceId = deviceId;
      deviceCommand.data = devicePayload;
      deviceCommand.port = customData.port;
      deviceCommand.operation = Constants.TcpOperation.WRITE;

      // Send command to the local device
      return localHomeApp.getDeviceManager()
        .send(deviceCommand)
        .then((result) => {
          response.setSuccessState(result.deviceId, state);
        })
        .catch((err: IntentFlow.HandlerError) => {
          err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST;
          response.setErrorState(device.id, err.errorCode);
        });
    });

    // Respond once all commands complete
    return Promise.all(result)
      .then(() => response.build());
  };

Implementar o gerenciador QUERY

O gerenciador QUERY no app processa as solicitações do usuário e usa o SDK da casa local para informar o estado dos dispositivos inteligentes.

A plataforma Home Local passa o mesmo payload de solicitação para a função de gerenciador "QUERY" da intent QUERY no fulfillment da nuvem. Da mesma forma, o gerenciador QUERY retorna dados no mesmo formato do processamento da intent QUERY.

Enviar comandos para dispositivos em um hub

Para controlar os dispositivos finais em um hub, talvez seja necessário fornecer mais informações no payload de comando específico do protocolo enviado ao hub para que o hub identifique para qual dispositivo o comando é destinado. Em alguns casos, isso pode ser inferido diretamente do valor device.id, mas quando esse não for o caso, inclua esses dados extras como parte do campo customData.

Se você criou o app usando o TypeScript, lembre-se de compilar o app em JavaScript. Use o sistema de módulos que preferir para escrever seu código. Verifique se o destino é compatível com o navegador Chrome.