Pour prendre en charge le traitement en local, vous devez créer une application capable de gérer les intents de la maison connectée suivants:
IDENTIFY
: permet de découvrir des appareils connectés contrôlables localement. Le gestionnaire d'intent extrait les données que votre appareil connecté renvoie lors de la détection, puis les envoie en réponse à Google.EXECUTE
: prend en charge l'exécution de commandes.QUERY
: permet d'interroger l'état de l'appareil.REACHABLE_DEVICES
(facultatif) : permet de découvrir les appareils finaux contrôlables localement derrière un appareil hub (ou pont).
Cette application s'exécute sur les appareils Google Home ou Google Nest de l'utilisateur et connecte votre appareil connecté à l'Assistant. Vous pouvez créer l'application à l'aide de TypeScript (recommandé) ou de JavaScript.
TypeScript est recommandé, car vous pouvez utiliser des liaisons pour vous assurer que les données renvoyées par votre application correspondent aux types attendus par la plate-forme.
Pour en savoir plus sur l'API, consultez la documentation de référence de l'API Local Home SDK.
Les extraits de code suivants montrent comment initialiser l'application de traitement en local et associer vos gestionnaires.
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"); });
Créer un projet
Pour déployer votre application de traitement en local, vous devez créer un bundle JavaScript pour votre code et toutes ses dépendances.
Utilisez l'initialiseur de projet de l'application de traitement en local pour amorcer la structure de projet appropriée avec la configuration de bundle de votre choix.
Modèles de projet
Pour sélectionner votre configuration de bundle, exécutez la commande npm init
comme indiqué dans les exemples suivants:
TypeScript sans configuration de bundler:
npm init @google/local-home-app project-directory/ --bundler none
Structure du projet:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Remplacez project-directory par un nouveau répertoire contenant le projet d'application de traitement en local.
TypeScript avec configuration de bundle webpack:
npm init @google/local-home-app project-directory/ --bundler webpack
Structure du projet:
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
Remplacez project-directory par un nouveau répertoire contenant le projet d'application de traitement en local.
TypeScript avec configuration de bundle Rollup:
npm init @google/local-home-app project-directory/ --bundler rollup
Structure du projet:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── rollup.config.js └── serve.js
Remplacez project-directory par un nouveau répertoire contenant le projet d'application de traitement en local.
TypeScript avec configuration de bundle Parcel:
npm init @google/local-home-app project-directory/ --bundler parcel
Structure du projet:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Remplacez project-directory par un nouveau répertoire contenant le projet d'application de traitement en local.
Effectuer des tâches courantes au niveau du projet
Le projet généré est compatible avec les scripts npm suivants:
cd project-directory/ npm run build
Ce script compile la source TypeScript et regroupe votre application avec ses dépendances pour l'environnement d'exécution Chrome dans le sous-répertoire dist/web
et l'environnement d'exécution Node.js dans le sous-répertoire dist/node
.
cd project-directory/ npm run lint npm run compile npm test
Ce script vérifie la syntaxe de votre code TypeScript, le compile sans générer de sortie dans le sous-répertoire dist/
et exécute des tests automatisés à partir de test.ts
.
cd project-directory/ npm run start
Lors du développement, ce script diffuse vos app bundles pour les environnements d'exécution Chrome et Node.js en local.
Implémenter le gestionnaire IDENTIFY
Le gestionnaire IDENTIFY
est déclenché lorsque l'appareil Google Home ou Google Nest redémarre et voit les appareils locaux non validés (y compris les appareils finaux connectés à un hub). La plate-forme Local Home recherche des appareils locaux à l'aide des informations de configuration de recherche que vous avez spécifiées précédemment et appelle votre gestionnaire IDENTIFY
avec les résultats de l'analyse.
Le IdentifyRequest
de la plate-forme Local Home contient les données d'analyse d'une instance LocalIdentifiedDevice
. Une seule instance device
est renseignée en fonction de la configuration d'analyse ayant détecté l'appareil.
Si les résultats de l'analyse correspondent à votre appareil, votre gestionnaire IDENTIFY
doit renvoyer un objet IdentifyResponsePayload
, qui inclut un objet device
avec des métadonnées de maison connectée (telles que les types, les caractéristiques et l'état du rapport).
Google établit une association d'appareils si verificationId
de la réponse IDENTIFY
correspond à l'une des valeurs otherDeviceIds
renvoyées par la réponse SYNC
.
Exemple
Les extraits de code suivants montrent respectivement comment créer des gestionnaires IDENTIFY
pour les intégrations d'appareils et de hub autonomes.
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; };
Identifier les appareils derrière un hub
Si Google identifie un appareil hub, il le considère comme le canal reliant les appareils finaux du hub et tente de valider ces appareils finaux.
Pour permettre à Google de confirmer la présence d'un appareil hub, suivez ces instructions pour votre gestionnaire IDENTIFY
:
- Si votre réponse
SYNC
indique les ID des appareils finaux locaux connectés au hub, définissezisProxy
surtrue
dansIdentifyResponsePayload
. - Si la réponse
SYNC
ne signale pas votre appareil hub, définissezisLocalOnly
en tant quetrue
dansIdentifyResponsePayload
. - Le champ
device.id
contient l'ID de l'appareil local lui-même.
Implémenter le gestionnaire REACHABLE_DEVICES (intégrations Hub uniquement)
L'intent REACHABLE_DEVICES
est envoyé par Google pour confirmer les appareils finaux qui peuvent être contrôlés localement. Cet intent est déclenché chaque fois que Google effectue une analyse de découverte (environ une minute), à condition que le hub soit en ligne.
Vous allez implémenter le gestionnaire REACHABLE_DEVICES
de la même manière que le gestionnaire IDENTIFY
, sauf qu'il doit collecter des ID d'appareils supplémentaires accessibles par l'appareil proxy local (c'est-à-dire le hub). Le champ device.verificationId
contient l'ID d'appareil local connecté au hub.
Le ReachableDevicesRequest
de la plate-forme Local Home contient une instance de LocalIdentifiedDevice
.
Cette instance vous permet d'obtenir l'ID de l'appareil proxy et les données des résultats de l'analyse.
Votre gestionnaire REACHABLE_DEVICES
doit renvoyer un objet ReachableDevicesPayload
qui inclut un objet devices
contenant un tableau de valeurs verificationId
représentant les appareils finaux contrôlés par le hub. Les valeurs verificationId
doivent correspondre à l'un des otherDeviceIds
de la réponse SYNC
.
L'extrait de code suivant montre comment créer un gestionnaire 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; };
Implémenter le gestionnaire EXECUTE
Le gestionnaire EXECUTE
de l'application traite les commandes utilisateur et utilise le SDK Local Home pour accéder à vos appareils connectés via un protocole existant.
La plate-forme Local Home transmet la même charge utile d'entrée à la fonction de gestionnaire EXECUTE
que l'intent EXECUTE
dans votre traitement cloud. De même, votre gestionnaire EXECUTE
renvoie des données de sortie au même format que lors du traitement de l'intent EXECUTE
.
Pour simplifier la création des réponses, vous pouvez utiliser la classe Execute.Response.Builder
fournie par le SDK Local Home.
Votre application n'a pas d'accès direct à l'adresse IP de l'appareil. Utilisez plutôt l'interface CommandRequest
pour créer des commandes basées sur l'un de ces protocoles: UDP, TCP ou HTTP. Appelez ensuite la fonction deviceManager.send()
pour envoyer les commandes.
Lorsque vous ciblez des appareils avec des commandes, utilisez l'ID d'appareil (et les paramètres du champ customData
, le cas échéant) de la réponse SYNC
pour communiquer avec l'appareil.
Exemple
L'extrait de code suivant montre comment créer un gestionnaire 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()); };
Implémenter le gestionnaire QUERY
Le gestionnaire QUERY
de l'application traite les requêtes des utilisateurs et utilise le SDK Local Home pour signaler l'état de vos appareils connectés.
La plate-forme Local Home transmet la même charge utile de requête à la fonction de gestionnaire "QUERY" que l'intent QUERY
vers votre traitement cloud. De même, votre gestionnaire QUERY
renvoie des données dans le même format que celui utilisé pour traiter l'intent QUERY
.
Envoyer des commandes aux appareils situés derrière un hub
Pour contrôler les appareils finaux derrière un hub, vous devrez peut-être fournir des informations supplémentaires dans la charge utile de commande spécifique au protocole envoyée au hub afin que celui-ci puisse identifier l'appareil auquel la commande est destinée. Dans certains cas, la valeur peut être directement déduite de la valeur device.id
. Si ce n'est pas le cas, vous devez inclure ces données supplémentaires dans le champ customData
.
Si vous avez créé votre application à l'aide de TypeScript, n'oubliez pas de la compiler en JavaScript. Vous pouvez utiliser le système de modules de votre choix pour écrire votre code. Assurez-vous que votre cible est compatible avec le navigateur Chrome.