Yerel sipariş karşılama uygulamasını uygulayın

Yerel sipariş karşılamayı desteklemek için aşağıdaki akıllı ev amaçlarını işleyecek bir uygulama derlemeniz gerekir:

  • IDENTIFY: Yerel olarak kontrol edilebilen akıllı cihazların keşfedilmesini destekler. Amaç işleyici, akıllı cihazınızın keşif sırasında döndürdüğü verileri çıkarır ve bunu Google'a yanıt olarak gönderir.
  • EXECUTE: Komutların yürütülmesini destekler.
  • QUERY: Cihaz durumunu sorgulamayı destekler.
  • REACHABLE_DEVICES: (İsteğe bağlı) Bir hub (veya köprü) cihazın arkasındaki yerel olarak kontrol edilebilen son cihazların keşfedilmesini destekler.

Bu uygulama, kullanıcının Google Home veya Google Nest cihazlarında çalışır ve akıllı cihazınızı Asistan'a bağlar. Uygulamayı TypeScript (tercih edilen) veya JavaScript kullanarak oluşturabilirsiniz.

Uygulamanızın döndürdüğü verilerin platformun beklediği türlerle eşleştiğinden statik olarak emin olmak için bağlamalardan yararlanabileceğiniz için TypeScript önerilir.

API hakkında daha fazla bilgi için Local Home SDK API referansı sayfasına bakın.

Aşağıdaki snippet'lerde yerel sipariş karşılama uygulamasını nasıl başlatabileceğiniz ve işleyicilerinizi nasıl ekleyebileceğiniz gösterilmektedir.

Bağımsız
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");
  });

Projenizi oluşturun

Yerel sipariş karşılama uygulamanızı dağıtmak için kodunuz ve tüm bağımlılıkları için bir JavaScript paketi oluşturmanız gerekir.

Uygun proje yapısını tercih ettiğiniz paketleyici yapılandırmasıyla önyüklemek için yerel sipariş karşılama uygulaması proje başlatma aracını kullanın.

Proje şablonları

Paketleyici yapılandırmanızı seçmek için npm init komutunu aşağıdaki örneklerde gösterildiği gibi çalıştırın:

Yok

Paketleyici yapılandırması olmayan TypeScript:

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

Proje yapısı:

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

project-directory dosyasını, yerel istek karşılama uygulaması projesini içeren yeni bir dizinle değiştirin.

Web paketi

webpack paketleyici yapılandırması ile TypeScript:

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

Proje yapısı:

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

project-directory dosyasını, yerel istek karşılama uygulaması projesini içeren yeni bir dizinle değiştirin.

Toplayıcı

Toplayıcı paket yapılandırmasıyla TypeScript:

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

Proje yapısı:

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

project-directory dosyasını, yerel istek karşılama uygulaması projesini içeren yeni bir dizinle değiştirin.

Parsel

Parcel paketleyici yapılandırmasıyla TypeScript:

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

Proje yapısı:

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

project-directory dosyasını, yerel istek karşılama uygulaması projesini içeren yeni bir dizinle değiştirin.

Proje düzeyinde yaygın görevleri gerçekleştirme

Oluşturulan proje aşağıdaki npm komut dosyalarını destekler:

Paket
cd project-directory/
npm run build

Bu komut dosyası, TypeScript kaynağını derler ve uygulamanızı dist/web alt dizininde Chrome çalışma zamanı ortamına ve dist/node alt dizinindeki Node.js çalışma zamanı ortamına yönelik bağımlılıklarıyla gruplandırır.

Doğrula
cd project-directory/
npm run lint
npm run compile
npm test

Bu komut dosyası, TypeScript kodunuzun söz dizimini doğrular, dist/ alt dizininde herhangi bir çıkış oluşturmadan derler ve test.ts öğesinden otomatik testler çalıştırır.

Yayınla
cd project-directory/
npm run start

Geliştirme sırasında bu komut dosyası, uygulama paketlerinizi Chrome ve Node.js çalışma zamanı ortamları için yerel olarak sunar.

IDENTIFY işleyicisini uygulama

Google Home veya Google Nest cihazı yeniden başlatıldığında ve doğrulanmamış yerel cihazları (bir merkeze bağlı son cihazlar dahil) gördüğünde IDENTIFY işleyici tetiklenir. Yerel Home platformu, daha önce belirttiğiniz tarama yapılandırması bilgilerini kullanarak yerel cihazları tarar ve tarama sonuçlarıyla birlikte IDENTIFY işleyicinizi çağırır.

Yerel Home platformundaki IdentifyRequest bir LocalIdentifiedDevice örneğine ait tarama verilerini içerir. Cihazı keşfeden tarama yapılandırmasına göre yalnızca bir device örneği doldurulur.

Tarama sonuçları cihazınızla eşleşirse IDENTIFY işleyiciniz, akıllı ev meta verilerine (türler, özellikler ve rapor durumu gibi) sahip device nesnesini içeren bir IdentifyResponsePayload nesnesi döndürecektir.

IDENTIFY yanıtındaki verificationId, SYNC yanıtının döndürdüğü otherDeviceIds değerlerinden biriyle eşleşirse Google bir cihaz ilişkilendirmesi oluşturur.

Örnek

Aşağıdaki snippet'ler bağımsız cihaz ve hub entegrasyonları için sırasıyla nasıl IDENTIFY işleyicileri oluşturabileceğinizi göstermektedir.

Bağımsız
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;
  };

Bir hub'ın arkasındaki cihazları tanımlama

Google bir hub cihazı tanımlarsa hub'ı, hub'ın bağlı uç cihazlarına giden kanal olarak algılar ve bu son cihazları doğrulamaya çalışır.

Google'ın bir hub cihazın mevcut olduğunu doğrulamasını sağlamak için IDENTIFY işleyicinizle ilgili şu talimatları uygulayın:

  • SYNC yanıtınız merkeze bağlı yerel son cihazların kimliklerini bildiriyorsa IdentifyResponsePayload içinde isProxy değerini true olarak ayarlayın.
  • SYNC yanıtınız hub cihazınızı bildirmezse IdentifyResponsePayload içinde isLocalOnly özelliğini true olarak ayarlayın.
  • device.id alanı, hub cihazının yerel cihaz kimliğini içerir.

REACHABLE_DEVICE işleyicisini uygulayın (yalnızca merkez entegrasyonları)

REACHABLE_DEVICES amacı, hangi son cihazların yerel olarak kontrol edilebileceğini onaylamak için Google tarafından gönderilir. Bu amaç, merkezin çevrimiçi olduğu algılandığı sürece Google'ın her keşif taraması yürütmesinde (yaklaşık olarak dakikada bir kez) tetiklenir.

REACHABLE_DEVICES işleyicisini IDENTIFY işleyicisine benzer şekilde uygularsınız, ancak işleyicinizin yerel proxy (yani hub) cihazın erişebileceği ek cihaz kimliklerini toplaması gerekir. device.verificationId alanı, hub'a bağlı bir son cihazın yerel cihaz kimliğini içerir.

Yerel Home platformundaki ReachableDevicesRequest bir LocalIdentifiedDevice örneği içerir. Bu örnek aracılığıyla, proxy cihaz kimliğinin yanı sıra tarama sonuçlarındaki verileri alabilirsiniz.

REACHABLE_DEVICES işleyiciniz, merkezin kontrol ettiği son cihazları temsil eden verificationId değerleri dizisi içeren devices nesnesini içeren bir ReachableDevicesPayload nesnesi döndürmelidir. verificationId değerleri, SYNC yanıtındaki otherDeviceIds değerlerinden biriyle eşleşmelidir.

Aşağıdaki snippet'te REACHABLE_DEVICES işleyicinizi nasıl oluşturabileceğiniz gösterilmektedir.

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

EXECUTE işleyicisini uygulama

Uygulamadaki EXECUTE işleyiciniz, kullanıcı komutlarını işler ve akıllı cihazlarınıza mevcut bir protokol üzerinden erişmek için Local Home SDK'sını kullanır.

Yerel Home platformu, bulut karşılamanıza yönelik EXECUTE amacı ile aynı giriş yükünü EXECUTE işleyici işlevine iletir. Benzer şekilde, EXECUTE işleyiciniz de çıkış verilerini EXECUTE amacını işlemeyle aynı biçimde döndürür. Yanıt oluşturmayı kolaylaştırmak için Yerel Home SDK'nın sağladığı Execute.Response.Builder sınıfını kullanabilirsiniz.

Uygulamanızın, cihazın IP adresine doğrudan erişimi yok. Bunun yerine, CommandRequest arayüzünü kullanarak şu protokollerden birini temel alan komutlar oluşturun: UDP, TCP veya HTTP. Ardından, komutları göndermek için deviceManager.send() işlevini çağırın.

Cihazlara hedefleme komutu verirken, cihazla iletişim kurmak için SYNC yanıtındaki cihaz kimliğini (ve varsa customData alanındaki parametreleri) kullanın.

Örnek

Aşağıdaki kod snippet'inde EXECUTE işleyicinizi nasıl oluşturabileceğiniz gösterilmektedir.

Bağımsız/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());
  };

QUERY işleyicisini uygulayın

Uygulamadaki QUERY işleyiciniz kullanıcı isteklerini işler ve akıllı cihazlarınızın durumunu bildirmek için Yerel Ev SDK'sını kullanır.

Yerel Home platformu, bulut istek karşılamanıza yönelik QUERY amacı ile aynı istek yükünü "QUERY" işleyici işlevine iletir. Benzer şekilde, QUERY işleyiciniz verileri QUERY amacını işlemeyle aynı biçimde döndürür.

Bir hub'ın arkasındaki cihazlara komut gönderme

Bir hub'ın arkasındaki son cihazları kontrol etmek amacıyla, merkezin komutun hangi cihaza yönelik olduğunu belirlemesi için merkeze gönderilen protokole özel komut yükünde ek bilgiler sağlamanız gerekebilir. Bazı durumlarda bu, doğrudan device.id değerinden çıkarılabilir, ancak böyle olmadığında bu ek verileri customData alanına eklemeniz gerekir.

Uygulamanızı TypeScript kullanarak oluşturduysanız uygulamanızı JavaScript'e derlemeyi unutmayın. Kodunuzu yazmak için istediğiniz modül sistemini kullanabilirsiniz. Chrome tarayıcının hedefinizi desteklediğinden emin olun.