Mengimplementasikan aplikasi fulfillment lokal

Untuk mendukung fulfillment lokal, Anda perlu membangun aplikasi untuk menanganinya intent smart home:

  • IDENTIFY: Mendukung penemuan perangkat smart yang dapat dikontrol secara lokal. Tujuan pengendali intent mengekstrak data yang dikembalikan oleh perangkat smart Anda selama penemuan dan mengirimkannya sebagai respons ke Google.
  • EXECUTE: Mendukung eksekusi perintah.
  • QUERY: Mendukung kueri status perangkat.
  • REACHABLE_DEVICES: (Opsional) Mendukung penemuan objek yang dapat dikontrol secara lokal perangkat akhir di belakang perangkat hub (atau jembatan).

Aplikasi ini berjalan di perangkat Google Home atau Google Nest pengguna dan menghubungkan perangkat smart Anda ke Google. Anda dapat membuat aplikasi menggunakan TypeScript (lebih disukai) atau JavaScript.

TypeScript direkomendasikan karena Anda dapat memanfaatkan binding untuk memastikan secara statis bahwa data yang ditampilkan aplikasi Anda cocok dengan jenis yang diharapkan oleh platform.

Untuk detail selengkapnya tentang API, lihat Referensi Local Home SDK API.

Cuplikan berikut menunjukkan cara melakukan inisialisasi aplikasi fulfillment lokal dan pasang pengendali.

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

Buat project Anda

Untuk men-deploy aplikasi fulfillment lokal, Anda harus membangun paket JavaScript untuk kode Anda dan semua dependensinya.

Menggunakan project aplikasi fulfillment lokal penginisialisasi untuk mem-bootstrap struktur project yang sesuai dengan pemaket pilihan Anda konfigurasi Anda.

Template project

Untuk memilih konfigurasi pemaket Anda, jalankan perintah npm init seperti yang ditunjukkan di contoh berikut:

Tidak ada

TypeScript tanpa konfigurasi pemaket:

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

{i>Project structure<i} (Struktur proyek):

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

Ganti project-directory dengan direktori baru yang akan berisi project aplikasi fulfillment lokal.

Webpack

TypeScript dengan pemaket webpack konfigurasi:

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

{i>Project structure<i} (Struktur proyek):

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

Ganti project-directory dengan direktori baru yang akan berisi project aplikasi fulfillment lokal.

Gabungan

TypeScript dengan Rollup konfigurasi pemaket:

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

{i>Project structure<i} (Struktur proyek):

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

Ganti project-directory dengan direktori baru yang akan berisi project aplikasi fulfillment lokal.

Paket

TypeScript dengan Parcel konfigurasi pemaket:

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

{i>Project structure<i} (Struktur proyek):

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

Ganti project-directory dengan direktori baru yang akan berisi project aplikasi fulfillment lokal.

Melakukan tugas umum level project

Project yang dihasilkan mendukung npm berikut skrip:

Paket
cd project-directory/
npm run build

Skrip ini mengompilasi sumber TypeScript, dan memaketkan aplikasi dengan dependensinya untuk lingkungan runtime Chrome di subdirektori dist/web dan lingkungan runtime Node.js di subdirektori dist/node.

Verifikasi
cd project-directory/
npm run lint
npm run compile
npm test

Skrip ini memverifikasi sintaksis kode TypeScript Anda, mengompilasinya tanpa menghasilkan output apa pun di subdirektori dist/, dan menjalankan pengujian otomatis dari test.ts.

Tayangkan
cd project-directory/
npm run start

Selama pengembangan, skrip ini menyalurkan app bundle Anda untuk lingkungan runtime Chrome dan Node.js secara lokal.

Menerapkan pengendali IDENTIFY

Pengendali IDENTIFY akan dipicu saat perangkat Google Home atau Google Nest dimulai ulang dan melihat perangkat lokal yang belum diverifikasi (termasuk perangkat akhir yang terhubung ke hub). Tujuan Platform Local Home akan memindai perangkat lokal menggunakan informasi konfigurasi pemindaian yang Anda tentukan sebelumnya dan memanggil pengendali IDENTIFY dengan hasil pemindaian.

Tujuan IdentifyRequest dari platform Local Home berisi data pemindaian LocalIdentifiedDevice di instance Compute Engine. Hanya satu instance device yang diisi, berdasarkan konfigurasi pemindaian yang menemukan perangkat itu.

Jika hasil pemindaian cocok dengan perangkat Anda, pengendali IDENTIFY akan menampilkan IdentifyResponsePayload , yang menyertakan objek device dengan metadata smart home (seperti jenis, karakteristik, dan status laporan).

Google membuat pengaitan perangkat jika verificationId dari respons IDENTIFY cocok dengan salah satu Nilai otherDeviceIds yang ditampilkan oleh respons SYNC.

Contoh

Cuplikan berikut menunjukkan cara membuat pengendali IDENTIFY untuk perangkat mandiri dan integrasi hub.

Mandiri
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;
  };
Pusat
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;
  };

Mengidentifikasi perangkat di belakang hub

Jika Google mengidentifikasi perangkat hub, Google akan memperlakukan hub tersebut sebagai saluran ke perangkat akhir yang terhubung ke {i>hub<i} dan mencoba memverifikasi perangkat akhir tersebut.

Agar Google dapat mengonfirmasi bahwa perangkat hub tersedia, ikuti untuk pengendali IDENTIFY Anda:

  • Jika respons SYNC Anda melaporkan ID perangkat akhir lokal yang terhubung ke setel isProxy sebagai true di IdentifyResponsePayload
  • Jika respons SYNC Anda tidak melaporkan perangkat hub Anda, setel isLocalOnly sebagai true dalam IdentifyResponsePayload
  • Kolom device.id berisi ID perangkat lokal untuk perangkat hub itu sendiri.

Menerapkan pengendali REACHABLE_devices (khusus integrasi hub)

Intent REACHABLE_DEVICES dikirim oleh Google untuk mengonfirmasi perangkat akhir yang dapat dikontrol secara lokal. Intent ini dipicu setiap kali Google menjalankan pemindaian penemuan (sekitar sekali setiap menit), selama hub terdeteksi online.

Anda menerapkan pengendali REACHABLE_DEVICES mirip dengan IDENTIFY kecuali pengendali Anda perlu mengumpulkan ID perangkat tambahan yang dapat dijangkau oleh {i>proxy<i} lokal (yaitu, {i>hub<i}) perangkat. Tujuan Kolom device.verificationId berisi ID perangkat lokal untuk perangkat akhir yang terhubung ke hub.

Tujuan ReachableDevicesRequest dari platform Local Home berisi instance LocalIdentifiedDevice Melalui {i>instance<i} ini, Anda bisa mendapatkan ID perangkat {i>proxy<i} serta data dari hasil pemindaian.

Pengendali REACHABLE_DEVICES Anda harus menampilkan ReachableDevicesPayload yang menyertakan objek devices yang berisi array Nilai verificationId yang mewakili perangkat akhir yang dikontrol hub. Tujuan Nilai verificationId harus cocok dengan salah satu nilai otherDeviceIds dari SYNC respons.

Cuplikan berikut menunjukkan cara membuat REACHABLE_DEVICES sebagai pengendali

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

Mengimplementasikan pengendali EXECUTE

Pengendali EXECUTE Anda di aplikasi memproses perintah pengguna dan menggunakan Local Home SDK untuk mengakses perangkat smart Anda melalui protokol yang ada.

Platform Local Home meneruskan payload input yang sama ke pengendali EXECUTE seperti untuk EXECUTE intent ke fulfillment cloud Anda. Demikian pula, pengendali EXECUTE Anda akan menampilkan data output dalam format yang sama dengan dari pemrosesan intent EXECUTE. Untuk menyederhanakan pembuatan respons, Anda dapat menggunakan Execute.Response.Builder yang disediakan oleh Local Home SDK.

Aplikasi Anda tidak memiliki akses langsung ke alamat IP perangkat. Sebagai gantinya, gunakan CommandRequest antarmuka untuk membuat perintah berdasarkan salah satu protokol berikut: UDP, TCP, atau HTTP. Kemudian, panggil metode deviceManager.send() untuk mengirimkan perintah.

Saat menargetkan perintah ke perangkat, gunakan ID perangkat (dan parameter dari customData, jika disertakan) dari respons SYNC untuk berkomunikasi dengan perangkat.

Contoh

Cuplikan kode berikut menunjukkan cara membuat pengendali EXECUTE.

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

Mengimplementasikan pengendali QUERY

Pengendali QUERY Anda di aplikasi memproses permintaan pengguna dan menggunakan Local Home SDK untuk melaporkan status perangkat smart Anda.

Platform Local Home meneruskan payload permintaan yang sama ke 'QUERY' pengendali berfungsi seperti untuk QUERY intent ke fulfillment cloud Anda. Demikian pula, pengendali QUERY Anda menampilkan data dalam format yang sama dengan dari pemrosesan intent QUERY.

Mengirimkan perintah ke perangkat di belakang hub

Untuk mengontrol perangkat akhir di belakang hub, Anda mungkin perlu memberikan informasi tambahan dalam {i>payload<i} perintah khusus protokol yang dikirim ke hub agar hub untuk mengidentifikasi perangkat yang menjadi tujuan perintah. Dalam beberapa kasus, hal ini dapat berupa disimpulkan langsung dari nilai device.id, tetapi jika tidak, Anda harus menyertakan data tambahan ini sebagai bagian dari kolom customData.

Jika Anda membuat aplikasi menggunakan TypeScript, ingatlah untuk mengompilasi aplikasi Anda ke pada JavaScript. Anda dapat menggunakan sistem modul pilihan Anda untuk menulis kode. Pastikan target Anda didukung oleh browser Chrome.