หากต้องการรองรับการตอบสนองในร้าน คุณต้องสร้างแอปเพื่อจัดการ Intent ของสมาร์ทโฮมต่อไปนี้
IDENTIFY
: รองรับการค้นหาอุปกรณ์อัจฉริยะที่ควบคุมจากภายในได้ ตัวแฮนเดิล Intent จะดึงข้อมูลที่อุปกรณ์อัจฉริยะแสดงระหว่างการค้นพบ และส่งข้อมูลนี้เป็นการตอบกลับไปยัง GoogleEXECUTE
: รองรับการดำเนินการตามคําสั่งQUERY
: รองรับการค้นหาสถานะอุปกรณ์REACHABLE_DEVICES
: (ไม่บังคับ) รองรับการค้นหาอุปกรณ์ปลายทางที่ควบคุมจากอุปกรณ์ฮับ (หรือบริดจ์) ได้
แอปนี้ทำงานบนอุปกรณ์ Google Home หรือ Google Nest ของผู้ใช้ และเชื่อมต่ออุปกรณ์อัจฉริยะกับ Assistant คุณสร้างแอปได้โดยใช้ TypeScript (แนะนำ) หรือ JavaScript
เราขอแนะนำให้ใช้ TypeScript เนื่องจากคุณสามารถใช้ประโยชน์จากการเชื่อมโยงแบบคงที่เพื่อให้มั่นใจว่าข้อมูลที่แอปแสดงผลตรงกับประเภทที่แพลตฟอร์มคาดหวัง
ดูรายละเอียดเพิ่มเติมเกี่ยวกับ API ได้ที่ข้อมูลอ้างอิง Local Home SDK API
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเริ่มต้นแอปการดำเนินการตามคำสั่งซื้อในพื้นที่และแนบตัวแฮนเดิล
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"); });
สร้างโปรเจ็กต์
หากต้องการทำให้แอปการดำเนินการตามคำสั่งซื้อในพื้นที่ใช้งานได้ คุณต้องสร้าง App Bundle ของ JavaScript สำหรับโค้ดและทรัพยากร Dependency ทั้งหมด
ใช้แอปการดำเนินการตามคำสั่งซื้อในเครื่อง project initializer เพื่อทำการจัดโครงสร้างโปรเจ็กต์ที่เหมาะสมด้วยการกำหนดค่าเครื่องมือจัดกลุ่มที่ต้องการ
เทมเพลตโปรเจ็กต์
หากต้องการเลือกการกำหนดค่าเครื่องมือจัดกลุ่ม ให้เรียกใช้คำสั่ง npm init
ตามที่แสดงในตัวอย่างต่อไปนี้
TypeScript ที่ไม่มีการกำหนดค่าเครื่องมือจัดกลุ่ม
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
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 ที่มีการกำหนดค่าเครื่องมือรวม 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 ด้วยไดเรกทอรีใหม่ที่จะบรรจุโปรเจ็กต์แอปการดำเนินการตามคำสั่งซื้อในพื้นที่
TypeScript ที่มีการกำหนดค่าเครื่องมือรวมโปรแกรม 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
ในระหว่างการพัฒนา สคริปต์นี้จะแสดงกลุ่มแอปของคุณสำหรับสภาพแวดล้อมรันไทม์ Chrome และ Node.js ในเครื่อง
ใช้ตัวแฮนเดิล IDENTIFY
แฮนเดิล IDENTIFY
จะทริกเกอร์เมื่ออุปกรณ์ Google Home หรือ Google Nest รีบูตและเห็นอุปกรณ์ภายในที่ไม่ได้รับการยืนยัน (รวมถึงอุปกรณ์ปลายทางที่เชื่อมต่อกับฮับ) แพลตฟอร์มบ้านในพื้นที่จะสแกนหาอุปกรณ์ในพื้นที่โดยใช้ข้อมูลการกําหนดค่าการสแกนที่คุณระบุไว้ก่อนหน้านี้ และเรียกใช้ตัวแฮนเดิล IDENTIFY
พร้อมผลลัพธ์การสแกน
ไฟล์ IdentifyRequest
จากแพลตฟอร์ม Home ในพื้นที่มีข้อมูลการสแกนของอินสแตนซ์ LocalIdentifiedDevice
ระบบจะสร้างอินสแตนซ์ device
เพียงรายการเดียวตามการกำหนดค่าการสแกนที่ค้นพบอุปกรณ์
หากผลการสแกนตรงกับอุปกรณ์ของคุณ แฮนเดิล 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
เพื่อยืนยันว่าอุปกรณ์ปลายทางใดบ้างที่ควบคุมจากเครื่องได้ เจตนานี้จะทริกเกอร์ทุกครั้งที่ 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 ในพื้นที่จะส่งข้อมูลพรอมต์อินพุตเดียวกันไปยังฟังก์ชัน EXECUTE
handler
เช่นเดียวกับEXECUTE
intent ไปยังการดําเนินการบนระบบคลาวด์ ในทํานองเดียวกัน แฮนเดิล 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
ในแอปจะประมวลผลคําขอของผู้ใช้ และใช้ Local Home SDK เพื่อรายงานสถานะของอุปกรณ์อัจฉริยะ
แพลตฟอร์ม Home ในพื้นที่จะส่งข้อมูลเพย์โหลดคำขอเดียวกันไปยังฟังก์ชันตัวแฮนเดิล "QUERY" เช่นเดียวกับความตั้งใจสำหรับ QUERY
ไปยังการจำหน่ายในระบบคลาวด์ ในทํานองเดียวกัน แฮนเดิล QUERY
จะแสดงผลข้อมูลในรูปแบบเดียวกับที่ได้จากการดำเนินการตาม Intent QUERY
การส่งคำสั่งไปยังอุปกรณ์ที่อยู่หลังฮับ
หากต้องการควบคุมอุปกรณ์ปลายทางที่อยู่หลังฮับ คุณอาจต้องระบุข้อมูลเพิ่มเติมในเพย์โหลดคําสั่งเฉพาะโปรโตคอลที่ส่งไปยังฮับเพื่อให้ฮับระบุได้ว่าคําสั่งนั้นมุ่งเป้าไปยังอุปกรณ์ใด ในบางกรณี ระบบอาจอนุมานข้อมูลนี้จากค่า device.id
ได้โดยตรง แต่หากไม่ใช่เช่นนั้น คุณควรใส่ข้อมูลเพิ่มเติมนี้เป็นส่วนหนึ่งของฟิลด์ customData
หากคุณสร้างแอปโดยใช้ TypeScript อย่าลืมคอมไพล์แอปเป็น JavaScript คุณใช้ระบบโมดูลที่ต้องการเพื่อเขียนโค้ดได้ ตรวจสอบว่าเบราว์เซอร์ Chrome รองรับเป้าหมายของคุณ