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