ยินดีต้อนรับสู่ Google Home Developer Center แหล่งใหม่เรียนรู้วิธีพัฒนาการดําเนินการในบ้านอัจฉริยะ หมายเหตุ: คุณจะสร้างการดําเนินการต่างๆ ต่อไปในคอนโซลการดําเนินการ

ใช้แอปการดําเนินการตามคําสั่งซื้อในพื้นที่

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

หากต้องการรองรับการดําเนินการตามคําสั่งซื้อในพื้นที่ คุณต้องสร้างแอปเพื่อจัดการ Intent ของสมาร์ทโฮมเหล่านี้

  • IDENTIFY: รองรับการค้นพบอุปกรณ์อัจฉริยะที่ควบคุมได้ในพื้นที่ เครื่องจัดการ Intent จะดึงข้อมูลที่อุปกรณ์อัจฉริยะกลับมาระหว่างที่ค้นพบและส่งข้อมูลนี้ตามการตอบกลับ Google
  • EXECUTE: รองรับการเรียกใช้คําสั่ง
  • QUERY: รองรับการค้นหาสถานะอุปกรณ์
  • REACHABLE_DEVICES: (ไม่บังคับ) รองรับการค้นพบอุปกรณ์ปลายทางที่ควบคุมในเครื่องได้หลังฮับ (หรือบริดจ์)

แอปนี้ทํางานในอุปกรณ์ Google Home หรือ Google Nest ของผู้ใช้และเชื่อมต่ออุปกรณ์อัจฉริยะกับ Assistant คุณสร้างแอปได้โดยใช้ TypeScript (แนะนํา) หรือ JavaScript

ขอแนะนําให้ใช้ TypeScript เนื่องจากคุณใช้ประโยชน์จากการเชื่อมโยงเพื่อให้ข้อมูลที่แอปแสดงเป็นไปตามประเภทที่แพลตฟอร์มคาดหวัง

ดูรายละเอียดเพิ่มเติมเกี่ยวกับ API ดังกล่าวได้ในข้อมูลอ้างอิง API ของ Home Home

ข้อมูลโค้ดต่อไปนี้แสดงวิธีเริ่มต้นแอปสําหรับการดําเนินการตามคําสั่งซื้อในพื้นที่และแนบเครื่องจัดการ

สแตนด์อโลน
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");
  });

สร้างโปรเจ็กต์

หากต้องการทําให้แอปดําเนินการตามคําสั่งซื้อในเครื่องใช้งานได้ คุณจะต้องสร้างแพ็กเกจ JavaScript สําหรับโค้ดและทรัพยากร Dependency ทั้งหมด

ใช้ project initializer ของแอปการดําเนินการตามคําสั่งซื้อในพื้นที่เพื่อเริ่มโครงสร้างโครงสร้างโปรเจ็กต์ที่เหมาะสมด้วยการกําหนดค่า Bundler ที่คุณต้องการ

เทมเพลตโปรเจ็กต์

หากต้องการเลือกการกําหนดค่า Bundler ให้เรียกใช้คําสั่ง npm init ดังที่แสดงในตัวอย่างต่อไปนี้

ไม่มี

TypeScript ที่ไม่มีการกําหนดค่า Bundler

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

โครงสร้างโปรเจ็กต์

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

แทนที่ project-directory ด้วยไดเรกทอรีใหม่ที่มีโปรเจ็กต์แอปสําหรับการดําเนินการตามคําสั่งซื้อในพื้นที่

แพ็กเกจเว็บ

TypeScript ที่มีการกําหนดค่า webpack ของ Bundler

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

โครงสร้างโปรเจ็กต์

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 ด้วยไดเรกทอรีใหม่ที่มีโปรเจ็กต์แอปสําหรับการดําเนินการตามคําสั่งซื้อในพื้นที่

ควบรวม

TypeScript ที่มีการกําหนดค่า Bundle Rollup:

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

โครงสร้างโปรเจ็กต์

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

แทนที่ project-directory ด้วยไดเรกทอรีใหม่ที่มีโปรเจ็กต์แอปสําหรับการดําเนินการตามคําสั่งซื้อในพื้นที่

Parcel

TypeScript ที่มีการกําหนดค่า Bundler Parcel

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

โครงสร้างโปรเจ็กต์

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

แทนที่ project-directory ด้วยไดเรกทอรีใหม่ที่มีโปรเจ็กต์แอปสําหรับการดําเนินการตามคําสั่งซื้อในพื้นที่

ทํางานทั่วไประดับโปรเจ็กต์

โปรเจ็กต์ที่สร้างขึ้นรองรับสคริปต์ npm ต่อไปนี้

แพ็กเกจ
cd project-directory/
npm run build

สคริปต์นี้จะรวบรวมแหล่งที่มาของ TypeScript และรวมแอปของคุณกับทรัพยากร Dependency สําหรับสภาพแวดล้อมรันไทม์ของ Chrome ในไดเรกทอรีย่อย dist/web และสภาพแวดล้อมรันไทม์ของ Node.js ในไดเรกทอรีย่อย dist/node

ยืนยัน
cd project-directory/
npm run lint
npm run compile
npm test

สคริปต์นี้จะยืนยันไวยากรณ์ของโค้ด TypeScript คอมไพล์โดยไม่ต้องสร้างเอาต์พุตในไดเรกทอรีย่อยของ dist/ และเรียกใช้การทดสอบอัตโนมัติจาก test.ts

แสดง
cd project-directory/
npm run start

ในระหว่างการพัฒนา สคริปต์นี้จะให้บริการ App Bundle สําหรับสภาพแวดล้อมรันไทม์ของ Chrome และ Node.js ในเครื่อง

ติดตั้งใช้งานเครื่องจัดการ IDENTIFY

ระบบจะทริกเกอร์เครื่องจัดการ IDENTIFY เมื่ออุปกรณ์ Google Home หรือ Google Nest รีบูตและเห็นอุปกรณ์ในเครือข่ายที่ไม่ได้รับการยืนยัน (รวมถึงอุปกรณ์ปลายทางที่เชื่อมต่อกับฮับ) แพลตฟอร์ม Home จะสแกนหาอุปกรณ์ในเครื่องโดยใช้ข้อมูลการกําหนดค่าการสแกนที่คุณระบุไว้ก่อนหน้านี้ และเรียกเครื่องจัดการ IDENTIFY ด้วยผลการสแกน

IdentifyRequest จากแพลตฟอร์ม Home Home มีข้อมูลการสแกนอินสแตนซ์ LocalIdentifiedDevice ระบบป้อนข้อมูลอินสแตนซ์ device เพียง 1 รายการเท่านั้น โดยอิงตามการกําหนดค่าการสแกนที่ค้นพบอุปกรณ์

หากผลการสแกนตรงกับอุปกรณ์ของคุณ เครื่องจัดการ IDENTIFY ควรแสดงผลออบเจ็กต์ IdentifyResponsePayload ซึ่งประกอบด้วยออบเจ็กต์ device ที่มีข้อมูลเมตาของบ้านอัจฉริยะ (เช่น ประเภท ลักษณะเฉพาะ และสถานะรายงาน)

Google จะตั้งการเชื่อมโยงอุปกรณ์หาก verificationId จากการตอบกลับ IDENTIFY ตรงกับค่า otherDeviceIds ค่าใดค่าหนึ่งซึ่งตอบกลับโดย SYNC

ตัวอย่าง

ข้อมูลโค้ดต่อไปนี้แสดงวิธีการสร้างเครื่องจัดการ IDENTIFY สําหรับการผสานรวมอุปกรณ์แบบสแตนด์อโลนและฮับ

สแตนด์อโลน
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;
  };

ระบุอุปกรณ์ที่อยู่ภายใต้ฮับ

หาก Google ระบุอุปกรณ์ฮับ ระบบจะคิดว่าฮับเป็นเหมือนอุปกรณ์ปลายทางที่เชื่อมต่อของฮับและพยายามยืนยันอุปกรณ์ปลายทางเหล่านั้น

หากต้องการให้ Google ยืนยันว่ามีอุปกรณ์ฮับอยู่ ให้ทําตามวิธีการต่อไปนี้สําหรับเครื่องจัดการ IDENTIFY ของคุณ

  • หากการตอบกลับของ SYNC รายงานรหัสของอุปกรณ์ปลายทางในพื้นที่ที่เชื่อมต่อกับฮับ ให้ตั้งค่า isProxy เป็น true ใน IdentifyResponsePayload
  • หากการตอบกลับ SYNC ไม่รายงานอุปกรณ์ฮับ ให้ตั้งค่า isLocalOnly เป็น true ใน IdentifyResponsePayload
  • ช่อง device.id มีรหัสอุปกรณ์ในเครื่องสําหรับอุปกรณ์ฮับ

ใช้ตัวแฮนเดิล REACHABLE_DEVICES (การผสานรวมฮับเท่านั้น)

Google จะส่ง Intent ของ REACHABLE_DEVICES เพื่อยืนยันว่าอุปกรณ์ปลายทางใดที่ควบคุมในเครื่องได้ จะมีการทริกเกอร์ Intent นี้ทุกครั้งที่ Google สแกนการสแกน (ประมาณทุก 1 นาที) ตราบใดที่มีการตรวจพบฮับออนไลน์

คุณใช้เครื่องจัดการ REACHABLE_DEVICES คล้ายกับเครื่องจัดการ IDENTIFY เว้นแต่ว่าเครื่องจัดการจะต้องรวบรวมรหัสอุปกรณ์เพิ่มเติมที่เข้าถึงได้โดยพร็อกซีพร็อกซีในเครื่อง (ซึ่งก็คือฮับ) ช่อง device.verificationId มีรหัสอุปกรณ์ในเครื่องสําหรับอุปกรณ์ปลายทางที่เชื่อมต่อกับฮับ

ReachableDevicesRequest จากแพลตฟอร์ม Home จะมีอินสแตนซ์ของ LocalIdentifiedDevice ผ่านอินสแตนซ์นี้ คุณจะได้รับรหัสอุปกรณ์พร็อกซีและข้อมูลจากผลการสแกน

เครื่องจัดการ REACHABLE_DEVICES ควรแสดงผลออบเจ็กต์ ReachableDevicesPayload ที่มีออบเจ็กต์ devices ที่มีอาร์เรย์ของค่า verificationId ที่แสดงถึงอุปกรณ์ปลายทางที่ฮับควบคุม ค่า verificationId ต้องตรงกับ otherDeviceIds ค่าใดค่าหนึ่งในการตอบกลับ SYNC

ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีสร้างแฮนเดิล 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;
  };

ติดตั้งใช้งานเครื่องจัดการ EXECUTE

เครื่องจัดการ EXECUTE ในแอปจะประมวลผลคําสั่งของผู้ใช้และใช้ Local Home SDK เพื่อเข้าถึงอุปกรณ์อัจฉริยะผ่านโปรโตคอลที่มีอยู่

แพลตฟอร์ม Home Home ส่งเพย์โหลดอินพุตเดียวกันไปยังฟังก์ชันตัวแฮนเดิล EXECUTE สําหรับ Intent ของ EXECUTE สําหรับการดําเนินการตามระบบคลาวด์ ในทํานองเดียวกัน เครื่องจัดการ EXECUTE จะแสดงผลข้อมูลเอาต์พุตในรูปแบบเดียวกับการประมวลผล Intent ของ EXECUTE คุณสามารถใช้คลาส Execute.Response.Builder ที่ Local Home SDK มีให้เพื่อลดความซับซ้อนของการสร้างการตอบกลับ

แอปของคุณไม่มีสิทธิ์เข้าถึงที่อยู่ IP ของอุปกรณ์โดยตรง แต่ให้ใช้อินเทอร์เฟซ CommandRequest แทนเพื่อสร้างคําสั่งตามโปรโตคอลใดโปรโตคอลหนึ่งต่อไปนี้ ได้แก่ UDP, TCP หรือ HTTP จากนั้นเรียกใช้ฟังก์ชัน deviceManager.send() เพื่อส่งคําสั่ง

เมื่อกําหนดเป้าหมายคําสั่งไปยังอุปกรณ์ ให้ใช้รหัสอุปกรณ์ (และพารามิเตอร์จากช่อง customData หากรวมอยู่ใน) จากการตอบกลับ SYNC เพื่อสื่อสารกับอุปกรณ์

ตัวอย่าง

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างแฮนเดิล 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());
  };

ใช้เครื่องจัดการ QUERY

เครื่องจัดการ QUERY ในแอปจะประมวลผลคําขอผู้ใช้และใช้ SDK ในเครื่องเพื่อรายงานสถานะอุปกรณ์อัจฉริยะ

แพลตฟอร์ม Local Home จะส่งเพย์โหลดคําขอเดียวกันไปยังฟังก์ชันเครื่องจัดการ "QUERY" สําหรับ Intent ของ QUERY สําหรับการดําเนินการตามระบบคลาวด์ ในทํานองเดียวกัน เครื่องจัดการ QUERY จะแสดงผลข้อมูลในรูปแบบเดียวกับการประมวลผล Intent ของ QUERY

การส่งคําสั่งไปยังอุปกรณ์หลังฮับ

หากต้องการควบคุมอุปกรณ์ปลายทางหลังฮับ คุณอาจต้องให้ข้อมูลเพิ่มเติมในเพย์โหลดคําสั่งเฉพาะโปรโตคอลที่ส่งไปยังฮับเพื่อให้ฮับระบุว่าอุปกรณ์มีเป้าหมายเป็นคําสั่งใด ในบางกรณี ระบบอาจอนุมานจากค่า device.id โดยตรง แต่เมื่อไม่ใช่กรณีดังกล่าว คุณควรใส่ข้อมูลเพิ่มเติมนี้ในช่อง customData

หากคุณสร้างแอปโดยใช้ TypeScript อย่าลืมรวบรวมแอปเป็น JavaScript คุณสามารถใช้ระบบโมดูลที่ต้องการเพื่อเขียนโค้ดได้ ตรวจสอบว่าเบราว์เซอร์ Chrome รองรับเป้าหมาย