Implementa l'app di distribuzione locale

Per supportare l'evasione degli ordini locali, devi creare un'app per gestire questi intenti smart home:

  • IDENTIFY: supporta il rilevamento di smart device controllabili localmente. La il gestore di intent estrae i dati che lo smart device restituisce durante il rilevamento e lo invia in risposta a Google.
  • EXECUTE: supporta l'esecuzione di comandi.
  • QUERY: supporta l'esecuzione di query sullo stato del dispositivo.
  • REACHABLE_DEVICES: (facoltativo) supporta il rilevamento di attività controllabili a livello locale dispositivi finali protetti da un dispositivo hub (o bridge).

Questa app viene eseguita sui dispositivi Google Home o Google Nest dell'utente e connette lo smart device a Assistente Google. Puoi creare l'app utilizzando TypeScript (opzione preferita) o JavaScript.

TypeScript è consigliato perché puoi sfruttare associazioni per assicurarti in modo statico che i dati restituiti dall'app corrispondano ai tipi che la piattaforma si aspetta.

Per ulteriori dettagli sull'API, consulta Riferimento API Local Home SDK.

I seguenti snippet mostrano come inizializzare l'app di distribuzione locale e collegare i tuoi gestori.

Autonomi
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });
Hub
import App = smarthome.App;
const localHomeApp: App = new App("1.0.0");
localHomeApp
  .onIdentify(identifyHandler)
  .onReachableDevices(reachableDevicesHandler)
  .onExecute(executeHandler)
  .listen()
  .then(() => {
    console.log("Ready");
  });

Creazione di un progetto

Per eseguire il deployment della tua app di distribuzione locale, devi creare un bundle JavaScript per il codice e tutte le sue dipendenze.

Utilizza il progetto dell'app di distribuzione locale inizializzatore per eseguire il bootstrap della struttura del progetto appropriata con il tuo bundler preferito configurazione.

Modelli di progetto

Per selezionare la configurazione del bundler, esegui il comando npm init come mostrato in i seguenti esempi:

Nessuna

TypeScript senza configurazione del bundler:

npm init @google/local-home-app project-directory/ --bundler none

Struttura del progetto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Sostituisci project-directory con una nuova directory che conterrà progetto app di distribuzione locale.

di Gemini Advanced.
Webpack

TypeScript con bundler webpack configurazione:

npm init @google/local-home-app project-directory/ --bundler webpack

Struttura del progetto:

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

Sostituisci project-directory con una nuova directory che conterrà progetto app di distribuzione locale.

di Gemini Advanced.
Aggregazione

TypeScript con Rollup configurazione bundler:

npm init @google/local-home-app project-directory/ --bundler rollup

Struttura del progetto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
├── rollup.config.js
└── serve.js

Sostituisci project-directory con una nuova directory che conterrà progetto app di distribuzione locale.

di Gemini Advanced.
Pacco

TypeScript con Parcel configurazione bundler:

npm init @google/local-home-app project-directory/ --bundler parcel

Struttura del progetto:

project-directory/
├── node_modules/
├── package.json
├── .gitignore
├── index.ts
├── test.ts
├── tsconfig.json
├── tslint.json
└── serve.js

Sostituisci project-directory con una nuova directory che conterrà progetto app di distribuzione locale.

Eseguire attività comuni a livello di progetto

Il progetto generato supporta i seguenti npm script:

Set
cd project-directory/
npm run build

Questo script compila l'origine TypeScript e raggruppa la tua app con le sue dipendenze per l'ambiente di runtime di Chrome nella sottodirectory dist/web e l'ambiente di runtime Node.js nella sottodirectory dist/node.

di Gemini Advanced.
Verifica
cd project-directory/
npm run lint
npm run compile
npm test

Questo script verifica la sintassi del codice TypeScript, la compila senza produrre alcun output nella sottodirectory dist/ ed esegue test automatici da test.ts.

di Gemini Advanced.
Pubblica
cd project-directory/
npm run start

Durante lo sviluppo, questo script gestisce localmente gli app bundle per gli ambienti di runtime Chrome e Node.js.

Implementare il gestore IDENTIFY

Il gestore IDENTIFY verrà attivato al riavvio del dispositivo Google Home o Google Nest. vede i dispositivi locali non verificati (inclusi i dispositivi finali connessi a un hub). La La piattaforma Home locale cercherà dispositivi locali utilizzando le informazioni di configurazione della scansione specificato in precedenza e richiamare il gestore IDENTIFY con i risultati della scansione.

La IdentifyRequest dalla piattaforma Home locale contiene i dati di scansione di LocalIdentifiedDevice in esecuzione in un'istanza Compute Engine. Viene compilata una sola istanza device in base alla configurazione della scansione che ha rilevato il dispositivo.

Se i risultati della scansione corrispondono al tuo dispositivo, il gestore IDENTIFY dovrebbe restituire un IdentifyResponsePayload , che include un oggetto device con I metadati della smart home (ad esempio tipi, caratteristiche e stato dei report).

Google stabilisce un'associazione del dispositivo se il verificationId della risposta IDENTIFY corrisponde a uno dei Valori otherDeviceIds restituiti dalla risposta SYNC.

Esempio

I seguenti snippet mostrano come potresti creare gestori IDENTIFY per le integrazioni indipendenti di dispositivi e hub.

Autonomi
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;
  };
Hub
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;
  };

Identificare i dispositivi dietro un hub

Se Google identifica un dispositivo hub, l'hub viene considerato come il condotto ai dispositivi finali connessi all'hub e prova a verificarli.

Per consentire a Google di verificare la presenza di un dispositivo hub, segui questi passaggi: Istruzioni per il tuo gestore IDENTIFY:

  • Se la tua risposta SYNC riporta gli ID dei dispositivi finali locali collegati al hub, imposta isProxy come truenel IdentifyResponsePayload.
  • Se la risposta SYNC non segnala il tuo dispositivo hub, imposta isLocalOnly come true in IdentifyResponsePayload.
  • Il campo device.id contiene l'ID dispositivo locale del dispositivo hub stesso.

Implementare il gestore REACHABLE_PAYMENTS (solo integrazioni hub)

L'intent REACHABLE_DEVICES viene inviato da Google per confermare quali dispositivi finali che possono essere controllati localmente. Questo intent viene attivato ogni volta che Google esegue (circa una volta al minuto), purché l'hub venga rilevato essere online.

Implementi il gestore REACHABLE_DEVICES in modo simile al IDENTIFY gestore dell'account, tranne che per il gestore deve raccogliere ID dispositivo aggiuntivi raggiungibile dal dispositivo proxy locale (ossia, dall'hub). La Il campo device.verificationId contiene l'ID dispositivo locale di un dispositivo finale collegato all'hub.

La ReachableDevicesRequest dalla piattaforma Home page locale contiene un'istanza LocalIdentifiedDevice. Tramite questa istanza, puoi ottenere l'ID dispositivo proxy e i dati da i risultati della scansione.

Il tuo gestore REACHABLE_DEVICES deve restituire un ReachableDevicesPayload che include un oggetto devices che contiene un array di Valori verificationId che rappresentano i dispositivi finali controllati dall'hub. La I valori verificationId devono corrispondere a uno dei otherDeviceIds di Risposta SYNC.

Il seguente snippet mostra come creare REACHABLE_DEVICES .

Hub
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;
  };

Implementazione del gestore EXECUTE

Il gestore EXECUTE nell'app elabora i comandi dell'utente e utilizza il metodo SDK Local Home per accedere ai tuoi smart device tramite un protocollo esistente.

La piattaforma Home locale passa lo stesso payload di input al gestore EXECUTE come per EXECUTE per il tuo fulfillment Cloud. Allo stesso modo, il gestore EXECUTE restituisce i dati di output nello stesso formato dell'elaborazione dell'intent EXECUTE. Per semplificare la creazione delle risposte, puoi utilizzare Execute.Response.Builder fornita dall'SDK Local Home.

La tua app non ha accesso diretto all'indirizzo IP del dispositivo. Invece, utilizza la CommandRequest per creare comandi basati su uno di questi protocolli: UDP, TCP o HTTP. Quindi chiama il metodo deviceManager.send() per inviare i comandi.

Quando scegli come target comandi per i dispositivi, utilizza l'ID dispositivo (e i parametri campo customData, se incluso) dalla risposta SYNC per comunicare con il dispositivo.

Esempio

Il seguente snippet di codice mostra come creare il gestore EXECUTE.

Autonomi/Hub
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());
  };

Implementa il gestore QUERY

Il gestore QUERY nell'app elabora le richieste degli utenti e utilizza il metodo SDK Local Home per segnalare lo stato dei tuoi smart device.

La piattaforma Home locale passa lo stesso payload di richiesta a "QUERY" gestore come per QUERY per il tuo fulfillment Cloud. Analogamente, il gestore QUERY restituisce i dati nello stesso formato dell'elaborazione dell'intent QUERY.

Invio di comandi a dispositivi dietro un hub

Per controllare i dispositivi finali dietro un hub, potrebbe essere necessario fornire informazioni aggiuntive nel payload del comando specifico del protocollo inviato all'hub in modo che per identificare il dispositivo a cui punta il comando. In alcuni casi, è possibile dedotto direttamente dal valore device.id, ma quando non è così, devi includere questi dati aggiuntivi nel campo customData.

Se hai creato la tua app utilizzando TypeScript, ricordati di compilare l'app per JavaScript. Puoi utilizzare il sistema di moduli di tua scelta per scrivere il codice. Assicurati che il target sia supportato dal browser Chrome.