Para oferecer suporte ao fulfillment local, você precisa criar um app para processar estas intents de casa inteligente:
IDENTIFY: permite a descoberta de dispositivos inteligentes controláveis localmente. O gerenciador de intents extrai os dados que o dispositivo inteligente retorna durante a descoberta e os envia em uma resposta ao Google.EXECUTE: permite a execução de comandos.QUERY: permite consultar o estado do dispositivo.REACHABLE_DEVICES: (opcional) permite a descoberta de dispositivos finais controláveis localmente atrás de um dispositivo hub (ou ponte).
Esse app é executado nos dispositivos Google Home ou Google Nest do usuário e conecta o dispositivo inteligente ao Google Assistente. É possível criar o app usando TypeScript (preferencial) ou JavaScript.
O TypeScript é recomendado porque você pode usar vinculações para garantir estaticamente 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 do Local Home.
Os snippets a seguir mostram como inicializar o app de fulfillment local e anexar os gerenciadores.
import App = smarthome.App; const localHomeApp: App = new App("1.0.0"); localHomeApp .onIdentify(identifyHandler) .onExecute(executeHandler) .listen() .then(() => { console.log("Ready"); });
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, é necessário criar um pacote JavaScript para o código e todas as dependências dele.
Use o inicializador de projetos do app de fulfillment local para inicializar a estrutura de projeto adequada com a configuração de bundler preferida.
Modelos de projeto
Para selecionar a configuração do bundler, execute o comando npm init, conforme mostrado nos
exemplos a seguir:
TypeScript sem configuração de 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 vai conter o projeto do app de fulfillment local.
Configuração do TypeScript com o empacotador 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 vai conter o projeto do app de fulfillment local.
TypeScript com 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 vai conter o projeto do app de fulfillment local.
TypeScript com 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 vai conter o projeto do app de fulfillment local.
Realizar tarefas comuns para envolvidos no projeto
O projeto gerado é compatível com os seguintes scripts npm:
cd project-directory/ npm run build
Esse script compila a origem do TypeScript e agrupa o app com as dependências dele para o ambiente de execução do Chrome no subdiretório dist/web e o ambiente de execução do Node.js no subdiretório dist/node.
cd project-directory/ npm run lint npm run compile npm test
Esse script verifica a sintaxe do código TypeScript, compila sem produzir nenhuma saída no subdiretório dist/ e executa testes automatizados de test.ts.
cd project-directory/ npm run start
Durante o desenvolvimento, esse script disponibiliza os pacotes do 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 dispositivo Google Nest for reiniciado e encontrar dispositivos locais não verificados (incluindo dispositivos finais conectados a um hub). A
plataforma de casa local vai procurar dispositivos locais usando as informações de configuração de verificação
especificadas anteriormente e chamar o gerenciador IDENTIFY com os resultados da verificação.
O
IdentifyRequest
da plataforma de casa local contém os dados de verificação de uma instância
LocalIdentifiedDevice. Somente uma instância device é preenchida, com base na configuração de verificação
que descobriu o dispositivo.
Se os resultados da verificação corresponderem ao seu dispositivo, o gerenciador IDENTIFY vai retornar um objeto
IdentifyResponsePayload,
que inclui um objeto device com
metadados de casa inteligente (como tipos, atributos e estado do relatório).
O Google estabelece uma associação de dispositivo 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 de dispositivos e hubs independentes, respectivamente.
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; };
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 atrás de um hub
Se o Google identificar um dispositivo hub, ele vai tratar o hub como o canal para os dispositivos finais conectados ao hub e tentar verificar esses dispositivos finais.
Para permitir que o Google confirme a presença de um dispositivo hub, siga estas
instruções para o gerenciador IDENTIFY:
- Se a resposta
SYNCinformar os IDs dos dispositivos finais locais conectados ao hub, definaisProxycomotruenoIdentifyResponsePayload. - Se a resposta
SYNCnão informar o dispositivo hub, definaisLocalOnlycomotruenoIdentifyResponsePayload. - O campo
device.idcontém o ID do dispositivo local do 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 (aproximadamente uma vez por minuto), desde que o hub seja detectado
como on-line.
Implemente o gerenciador REACHABLE_DEVICES de maneira semelhante ao gerenciador IDENTIFY, mas o gerenciador precisa coletar outros IDs de dispositivos que podem ser acessados pelo dispositivo proxy local (ou seja, o hub). O campo device.verificationId contém o ID do dispositivo local para um dispositivo final conectado ao hub.
O
ReachableDevicesRequest
da plataforma de casa local contém uma instância de
LocalIdentifiedDevice.
Com essa instância, é possível receber o ID do dispositivo proxy e os dados dos
resultados da verificação.
O gerenciador REACHABLE_DEVICES precisa retornar um objeto
ReachableDevicesPayload
que inclua um objeto devices que contenha uma matriz de
valores verificationId que representam os dispositivos finais controlados pelo hub. Os valores de verificationId precisam corresponder a um dos otherDeviceIds da resposta de SYNC.
O snippet a seguir mostra como criar o gerenciador
REACHABLE_DEVICES.
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 os comandos do usuário e usa o
SDK do Local Home para acessar os dispositivos inteligentes por um protocolo atual.
A plataforma Local Home transmite o mesmo payload de entrada para a função de gerenciador EXECUTE
como para a intent EXECUTE
para o fulfillment na nuvem. Da mesma forma, o gerenciador EXECUTE retorna
dados de saída no mesmo formato do processamento da intent EXECUTE.
Para simplificar a criação da resposta, use a classe
Execute.Response.Builder
fornecida pelo SDK do Local Home.
Seu 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 direcionar comandos para dispositivos, use o ID do dispositivo (e os parâmetros do campo customData, se incluídos) da resposta SYNC para se comunicar com o dispositivo.
Exemplo
O snippet de código abaixo mostra como criar o gerenciador EXECUTE.
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 do Google Home local para informar o estado dos dispositivos inteligentes.
A plataforma de casa local transmite o mesmo payload de solicitação para a função de gerenciador "QUERY"
que para a intent QUERY
para o fulfillment na nuvem. Da mesma forma, o gerenciador QUERY retorna dados
no mesmo formato que o processamento da intent QUERY.
Como enviar comandos para dispositivos atrás de um hub
Para controlar dispositivos finais atrás de um hub, talvez seja necessário fornecer mais informações
no payload de comando específico do protocolo enviado ao hub para que ele
identifique o dispositivo de destino do comando. Em alguns casos, isso pode ser
inferido diretamente do valor device.id, mas, quando não for o caso,
inclua esses dados extras como parte do campo customData.
Se você criou o app usando TypeScript, lembre-se de compilá-lo para JavaScript. Você pode usar o sistema de módulos que preferir para escrever seu código. Verifique se o destino é compatível com o navegador Chrome.