Para oferecer suporte ao fulfillment local, você precisa criar um app para processar estas intents de casa inteligente:
IDENTIFY
: oferece suporte à descoberta de dispositivos inteligentes controláveis localmente. O gerenciador de intent extrai os dados que o dispositivo inteligente retorna durante a descoberta e os envia em uma resposta ao Google.EXECUTE
: oferece suporte à execução de comandos.QUERY
: oferece suporte a consultas ao estado do dispositivo.REACHABLE_DEVICES
: (opcional) oferece suporte à 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 (recomendado) ou JavaScript.
O TypeScript é recomendado porque você pode aproveitar vinculações para garantir estaticamente que os dados retornados pelo app correspondam aos tipos que a plataforma espera.
Para mais detalhes sobre a API, consulte a referência da API Local Home SDK.
Os snippets a seguir mostram como inicializar o app de fulfillment local e anexar seus 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, você precisa criar um pacote JavaScript para o código e todas as dependências dele.
Use o inicializador de projeto 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 abaixo:
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.
TypeScript com configuração de bundler do 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 de agrupamento 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 do 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 no nível do projeto
O projeto gerado oferece suporte aos 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, o 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 serve 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 Google Nest for reinicializado e
identificar dispositivos locais não verificados (incluindo dispositivos finais conectados a um hub). A
plataforma de casa local vai verificar 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 Home contém os dados de verificação de uma
instância LocalIdentifiedDevice
. Apenas 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 seu 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 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 manipuladores IDENTIFY
para
integrações de dispositivos independentes e hubs, 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 por trás de um hub
Se o Google identificar um dispositivo hub, ele vai tratar o hub como o canal para os dispositivos finais conectados e tentar verificar esses dispositivos finais.
Para permitir que o Google confirme se um dispositivo hub está presente, siga estas
instruções para o gerenciador IDENTIFY
:
- Se a resposta
SYNC
informar os IDs dos dispositivos finais locais conectados ao hub, definaisProxy
comotrue
naIdentifyResponsePayload
. - Se a resposta
SYNC
não informar o dispositivo hub, definaisLocalOnly
comotrue
noIdentifyResponsePayload
. - 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 (aproximadamente uma vez a cada minuto), desde que o hub seja detectado
como on-line.
Você implementa o gerenciador REACHABLE_DEVICES
de maneira semelhante ao gerenciador IDENTIFY
, exceto que ele precisa coletar outros IDs de dispositivo
acessíveis 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 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 de EXECUÇÃO
O gerenciador EXECUTE
no app processa os comandos do usuário e usa o
SDK local do Google Home para acessar seus dispositivos inteligentes por um protocolo.
A plataforma Local Home transmite o mesmo payload de entrada para a função do gerenciador EXECUTE
como para a intent EXECUTE
para o fulfillment da 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 de respostas, 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 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 de QUERY
O gerenciador QUERY
no app processa as solicitações do usuário e usa o
SDK da casa inteligente para informar o estado dos dispositivos inteligentes.
A plataforma Local Home transmite o mesmo payload de solicitação para a função de manipulador QUERY
da intent QUERY
para o fulfillment da nuvem. Da mesma forma, o gerenciador QUERY
retorna dados
no mesmo formato do processamento da intent QUERY
.
Como enviar comandos para dispositivos por trás de um hub
Para controlar os dispositivos finais por trás de um hub, talvez seja necessário fornecer informações extras
no payload de comando específico do protocolo enviado ao hub para que ele
identifique para qual dispositivo o comando é destinado. Em alguns casos, isso pode ser
inferido diretamente do valor device.id
, mas, quando isso não acontece,
inclua esses dados extras como parte do campo customData
.
Se você criou o app usando TypeScript, lembre-se de fazer a compilação para JavaScript. Você pode usar o sistema de módulos que preferir para escrever o código. Verifique se o destino é compatível com o navegador Chrome.