Para oferecer suporte ao fulfillment local, você precisa criar um app que processe estas intents de casa inteligente:
IDENTIFY
: oferece suporte à descoberta de dispositivos inteligentes controláveis localmente. O processador de intents extrai os dados que seu 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 sobre o estado do dispositivo.REACHABLE_DEVICES
: (opcional) oferece suporte à descoberta de dispositivos finais controláveis localmente por trás de um hub (ou ponte).
Esse app é executado nos dispositivos Google Home ou Google Nest do usuário e conecta o dispositivo inteligente ao Assistente. É possível criar o app usando TypeScript (preferencial) ou JavaScript.
O TypeScript é recomendado porque você pode usar vinculações para garantir de forma estática 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 Home.
Os snippets a seguir mostram como inicializar o app de fulfillment local e anexar seus manipuladores.
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 atendimento local, é necessário criar um pacote JavaScript para seu código e todas as dependências dele.
Use o inicializador de projeto do app de atendimento local para inicializar a estrutura de projeto adequada com a configuração do bundler preferido.
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 atendimento local.
TypeScript com configuração do agrupador 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 atendimento local.
TypeScript com configuração do pacote 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 atendimento local.
TypeScript com configuração do empacotador 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 atendimento local.
Realizar 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 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 seu código TypeScript, o compila sem produzir saída no subdiretório dist/
e executa testes automatizados de test.ts
.
cd project-directory/ npm run start
Durante o desenvolvimento, esse script veicula os pacotes de apps para os ambientes de execução do Chrome e do Node.js localmente.
Implementar o gerenciador de IDENTIFICAÇÃO
O manipulador IDENTIFY
será acionado quando o dispositivo Google Home ou Google Nest for reinicializado e
detectar dispositivos locais não verificados (incluindo dispositivos finais conectados a um hub). A plataforma Local Home vai procurar dispositivos locais usando as informações de configuração de verificação especificadas anteriormente e chamar seu manipulador 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 manipulador 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 de IDENTIFY
para
integrações de dispositivos autônomos 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 conectados a um hub
Se o Google identificar um dispositivo hub, ele vai tratar o hub como o condutor para os dispositivos finais conectados a ele e tentar verificar esses dispositivos finais.
Para permitir que o Google confirme a presença de um dispositivo hub, siga estas
instruções para seu manipulador IDENTIFY
:
- Se a resposta do
SYNC
informar os IDs dos dispositivos finais locais conectados ao hub, definaisProxy
comotrue
noIdentifyResponsePayload
. - 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 manipulador REACHABLE_DEVICES (somente integrações de hub)
O Google envia a intent REACHABLE_DEVICES
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 esteja on-line.
Você implementa o gerenciador REACHABLE_DEVICES
de maneira semelhante ao gerenciador IDENTIFY
, exceto que ele precisa coletar outros IDs de dispositivos 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 Local Home 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 manipulador REACHABLE_DEVICES
precisa retornar um objeto
ReachableDevicesPayload
que inclua um objeto devices
com 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 seu manipulador de 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 manipulador EXECUTE
no app processa comandos do usuário e usa o SDK Local Home para acessar seus dispositivos inteligentes por um protocolo existente.
A plataforma Local Home transmite o mesmo payload de entrada para a função do gerenciador EXECUTE
que a intent EXECUTE
para o fulfillment na nuvem. Da mesma forma, o manipulador 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.
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 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 seu manipulador 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 manipulador QUERY
no app processa solicitações do usuário e usa o SDK local do Google Home para informar o estado dos dispositivos inteligentes.
A plataforma Local Home transmite a mesma carga útil de solicitação para a função de manipulador "QUERY"
que a intent QUERY
para o fulfillment na nuvem. Da mesma forma, o manipulador QUERY
retorna dados
no mesmo formato do processamento da intent QUERY
.
Como enviar comandos para dispositivos conectados a 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 a qual dispositivo o comando se destina. Em alguns casos, isso pode ser inferido diretamente do valor device.id
, mas, quando não for possível, inclua esses dados extras como parte do campo customData
.
Se você criou o app usando TypeScript, não se esqueça de compilá-lo para JavaScript. Você pode usar o sistema de módulos de sua preferência para escrever o código. Verifique se o destino é compatível com o navegador Chrome.