Para oferecer compatibilidade com o fulfillment local, é necessário criar um app para processar 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
: compatível com a execução de comandos.QUERY
: compatível com a consulta do estado do dispositivo.REACHABLE_DEVICES
: (opcional) é compatível com a descoberta de dispositivos finais com controle local por trás de um dispositivo hub (ou de 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 aplicativo usando TypeScript (preferencial) ou JavaScript.
O TypeScript é recomendado porque é possível utilizar vinculações para garantir de forma estática que os dados retornados pelo aplicativo correspondam aos tipos que a plataforma espera.
Para ver mais detalhes sobre a API, consulte a referência da API Local Home SDK.
Os snippets a seguir mostram como você pode 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 do projeto do app de fulfillment local para inicializar a estrutura de projetos adequada com a configuração do bundler de sua preferência.
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 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 aplicativo de fulfillment local.
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 aplicativo de fulfillment local.
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 aplicativo de fulfillment local.
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 aplicativo de fulfillment local.
Executar tarefas comuns no nível do projeto
O projeto gerado é compatível com os seguintes scripts npm:
cd project-directory/ npm run build
Esse script compila a fonte do TypeScript e agrupa o aplicativo com as respectivas dependências no ambiente de execução do Chrome no subdiretório dist/web
e no 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 seu código do TypeScript, compila-o 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 seus pacotes de apps localmente para os ambientes de execução do Chrome e do Node.js.
Implementar o gerenciador de IDENTIFY
O gerenciador IDENTIFY
será acionado quando o dispositivo Google Home ou Google Nest for reiniciado e vir dispositivos locais não verificados, incluindo dispositivos finais conectados a um hub. A plataforma da Página inicial local procura dispositivos locais usando as informações de configuração de verificação especificadas anteriormente e chama 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
. 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
precisará retornar um objeto
IdentifyResponsePayload
,
que inclui um objeto device
com
metadados de casa inteligente (como tipos, características e estado de relatório).
O Google estabelecerá 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 de dispositivo e hub 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 em um hub
Se o Google identificar um dispositivo hub, ele o tratará como o canal para os dispositivos finais conectados do 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
SYNC
informar os IDs dos dispositivos finais locais conectados ao hub, definaisProxy
comotrue
noIdentifyResponsePayload
. - Se a resposta
SYNC
não informar seu dispositivo hub, definaisLocalOnly
comotrue
emIdentifyResponsePayload
. - O campo
device.id
contém o ID do dispositivo local para o 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 por minuto), desde que o hub seja detectado como on-line.
Você implementa o gerenciador REACHABLE_DEVICES
de forma semelhante ao gerenciador IDENTIFY
, exceto pelo fato de que ele precisa coletar IDs de dispositivo adicionais acessíveis 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 Home contém uma instância de
LocalIdentifiedDevice
.
Por meio dessa 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 contenha 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
.
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 local do Google Home para acessar os dispositivos inteligentes por meio de um protocolo existente.
A plataforma da casa local transmite o mesmo payload de entrada para a função de gerenciador EXECUTE
da 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 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
.
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 solicitações de usuário e usa o SDK local do Google Home para informar o estado dos dispositivos inteligentes.
A plataforma da página inicial local transmite o mesmo payload de solicitação para a função de gerenciador "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 atrás de um hub
Para controlar os dispositivos finais em um hub, pode ser necessário fornecer informações extras
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 seu aplicativo usando o TypeScript, lembre-se de compilar o aplicativo em 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.