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