เพิ่มประสิทธิภาพและรักษาความปลอดภัยในการผสานรวมระบบคลาวด์กับระบบคลาวด์

เกี่ยวกับ Codelab นี้
schedule50 นาที
subjectอัปเดตล่าสุดเมื่อ 8 เมษายน 2568
account_circleเขียนโดย Googler

1. ก่อนเริ่มต้น

การผสานรวมระบบคลาวด์กับระบบคลาวด์ใช้ประเภทอุปกรณ์เพื่อให้ Google Assistant ทราบว่าควรใช้ไวยากรณ์ใดกับอุปกรณ์ ลักษณะของอุปกรณ์จะกำหนดความสามารถของประเภทอุปกรณ์ อุปกรณ์จะรับค่าสถานะของลักษณะของอุปกรณ์แต่ละรายการที่เพิ่มลงในการผสานรวม

dc8dce0dea87cd5c.png

คุณสามารถเชื่อมต่อลักษณะที่รองรับกับประเภทอุปกรณ์ที่เลือกเพื่อปรับแต่งฟังก์ชันการทำงานของอุปกรณ์ของผู้ใช้ หากต้องการใช้ลักษณะที่กำหนดเองในการดำเนินการซึ่งปัจจุบันไม่มีในสคีมาอุปกรณ์ คุณสามารถใช้ลักษณะโหมดและปุ่มเปิด/ปิดเพื่อควบคุมการตั้งค่าที่เฉพาะเจาะจงด้วยชื่อที่กำหนดเอง

นอกจากความสามารถในการควบคุมพื้นฐานที่ประเภทและลักษณะการทํางานมอบให้ Smart Home API ยังมีฟีเจอร์เพิ่มเติมเพื่อปรับปรุงประสบการณ์ของผู้ใช้ การตอบกลับข้อผิดพลาดจะแสดงความคิดเห็นโดยละเอียดของผู้ใช้เมื่อความตั้งใจไม่สำเร็จ การยืนยันผู้ใช้รองจะขยายคำตอบเหล่านั้นและเพิ่มความปลอดภัยให้กับลักษณะของอุปกรณ์ที่คุณเลือก การส่งคำตอบข้อผิดพลาดที่เฉพาะเจาะจงไปยังบล็อกการตรวจสอบที่ออกโดย Assistant อาจทำให้การผสานรวมระบบคลาวด์ต่อคลาวด์ของคุณต้องได้รับสิทธิ์เพิ่มเติมเพื่อดำเนินการตามคำสั่งให้เสร็จสมบูรณ์

ข้อกำหนดเบื้องต้น

สิ่งที่คุณจะสร้าง

ในโค้ดแล็บนี้ คุณจะใช้การผสานรวมสมาร์ทโฮมที่สร้างไว้ล่วงหน้ากับ Firebase จากนั้นดูวิธีเพิ่มลักษณะที่ไม่เป็นไปตามมาตรฐานลงในเครื่องซักผ้าสมาร์ทโฮมสำหรับขนาดการซักและโหมดเทอร์โบ นอกจากนี้ คุณยังใช้การรายงานข้อผิดพลาดและการยกเว้น รวมถึงเรียนรู้วิธีบังคับใช้การยอมรับด้วยวาจาเพื่อเปิดเครื่องซักผ้าโดยใช้การยืนยันผู้ใช้สำรอง

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเพิ่มลักษณะของโหมดและปุ่มสลับในการผสานรวม
  • วิธีรายงานข้อผิดพลาดและข้อยกเว้น
  • วิธีใช้การยืนยันผู้ใช้รอง

สิ่งที่คุณต้องมี

2. เริ่มต้นใช้งาน

เปิดใช้ส่วนควบคุมกิจกรรม

หากต้องการใช้ Google Assistant คุณต้องแชร์ข้อมูลกิจกรรมบางอย่างกับ Google Google Assistant ต้องใช้ข้อมูลนี้จึงจะทำงานได้อย่างถูกต้อง แต่ข้อกำหนดในการแชร์ข้อมูลไม่ได้เจาะจงสำหรับ SDK เท่านั้น หากต้องการแชร์ข้อมูลนี้ ให้สร้างบัญชี Google หากยังไม่มี คุณใช้บัญชี Google บัญชีใดก็ได้ ไม่จำเป็นต้องเป็นบัญชีนักพัฒนาแอป

เปิดหน้าส่วนควบคุมกิจกรรมของบัญชี Google ที่ต้องการใช้กับ Assistant

ตรวจสอบว่าได้เปิดใช้สวิตช์เปิด/ปิดต่อไปนี้

  • กิจกรรมบนเว็บและแอป - นอกจากนี้ อย่าลืมเลือกช่องทำเครื่องหมายรวมประวัติการเข้าชมใน Chrome และกิจกรรมจากเว็บไซต์ แอป และอุปกรณ์ที่ใช้บริการต่างๆ ของ Google
  • ข้อมูลอุปกรณ์
  • กิจกรรมเสียงพูดและเสียง

สร้างโปรเจ็กต์การผสานรวมระบบคลาวด์กับระบบคลาวด์

  1. ไปที่คอนโซลนักพัฒนาแอป
  2. คลิกสร้างโปรเจ็กต์ ป้อนชื่อโปรเจ็กต์ แล้วคลิกสร้างโปรเจ็กต์

ตั้งชื่อโปรเจ็กต์

เลือกการผสานรวมระบบคลาวด์กับระบบคลาวด์

ในหน้าแรกของโปรเจ็กต์ในคอนโซลของนักพัฒนาซอฟต์แวร์ ให้เลือกเพิ่มการผสานรวมระบบคลาวด์กับระบบคลาวด์ในส่วนระบบคลาวด์กับระบบคลาวด์

เพิ่มการผสานรวมระบบคลาวด์สู่ระบบคลาวด์

ติดตั้ง Firebase CLI

อินเทอร์เฟซบรรทัดคำสั่ง (CLI) ของ Firebase จะช่วยให้คุณแสดงเว็บแอปในเครื่องและทำให้เว็บแอปใช้งานได้ในโฮสติ้งของ Firebase

หากต้องการติดตั้ง CLI ให้เรียกใช้คำสั่ง npm ต่อไปนี้จากเทอร์มินัล

npm install -g firebase-tools

หากต้องการยืนยันว่าติดตั้ง CLI อย่างถูกต้องแล้ว ให้เรียกใช้คำสั่งต่อไปนี้

firebase --version

ให้สิทธิ์ Firebase CLI ด้วยบัญชี Google โดยเรียกใช้คำสั่งต่อไปนี้

firebase login

เพิ่ม Firebase ไปยังโปรเจ็กต์ Google Home Developer Console

วิธีที่ 1: ผ่านคอนโซล Firebase

  1. ไปที่ Firebase
  2. คลิกสร้างโปรเจ็กต์ Firebase
    สร้างโปรเจ็กต์ Firebase
  3. ในหน้าจอสร้างโปรเจ็กต์ ให้คลิกเพิ่ม Firebase ไปยังโปรเจ็กต์ Google Cloud
    เพิ่ม Firebase ไปยังโปรเจ็กต์ Google Cloud
  4. ในหน้าจอเริ่มต้นใช้งาน ให้เลือกโปรเจ็กต์ Google Cloud ที่คุณเพิ่งสร้างในคอนโซลนักพัฒนาแอป Google Home แล้วคลิกต่อไป
    เลือกโปรเจ็กต์ Google Cloud

วิธีที่ 2: ผ่าน Firebase CLI

firebase projects:addfirebase

เลือกโปรเจ็กต์ Google Home Developer Console ที่คุณเพิ่งสร้างขึ้นเพื่อเพิ่ม Firebase

เมื่อเพิ่ม Firebase ลงในโปรเจ็กต์ Google Home Developer Console แล้ว โปรเจ็กต์ดังกล่าวจะปรากฏในคอนโซล Firebase รหัสโปรเจ็กต์ของโปรเจ็กต์ Firebase จะสอดคล้องกับรหัสโปรเจ็กต์ในคอนโซลนักพัฒนาแอป Google Home

เพิ่มโปรเจ็กต์ที่อยู่ในระบบคลาวด์แล้ว

เปิดใช้ HomeGraph API

HomeGraph API ช่วยให้สามารถจัดเก็บและค้นหาอุปกรณ์และสถานะของอุปกรณ์ภายใน Home Graph ของผู้ใช้ หากต้องการใช้ API นี้ คุณต้องเปิดคอนโซล Google Cloud ก่อนแล้วเปิดใช้ HomeGraph API

ในคอนโซล Google Cloud ให้เลือกโปรเจ็กต์ที่ตรงกับการดำเนินการของคุณ <firebase-project-id>. จากนั้นคลิกเปิดใช้ในหน้าจอคลัง API สำหรับ HomeGraph API

ee198858a6eac112.png

3. เรียกใช้แอปเริ่มต้น

เมื่อตั้งค่าสภาพแวดล้อมการพัฒนาซอฟต์แวร์แล้ว คุณสามารถทําให้การเผยแพร่โปรเจ็กต์เริ่มต้นเพื่อยืนยันว่าทุกอย่างได้รับการกําหนดค่าอย่างถูกต้อง

รับซอร์สโค้ด

คลิกลิงก์ต่อไปนี้เพื่อดาวน์โหลดตัวอย่างสําหรับโค้ดแล็บนี้ในเครื่องพัฒนาซอฟต์แวร์

หรือจะโคลนที่เก็บ GitHub จากบรรทัดคำสั่งก็ได้ โดยทำดังนี้

git clone https://github.com/google-home/smarthome-traits.git

แตกไฟล์ ZIP ที่ดาวน์โหลด

เกี่ยวกับโครงการนี้

โปรเจ็กต์เริ่มต้นมีไดเรกทอรีย่อยต่อไปนี้

  • public: UI ด้านหน้าสำหรับควบคุมและตรวจสอบสถานะของเครื่องซักผ้าอัจฉริยะได้อย่างง่ายดาย
  • functions: บริการระบบคลาวด์ที่ติดตั้งใช้งานอย่างเต็มรูปแบบซึ่งจัดการเครื่องซักผ้าอัจฉริยะด้วย Cloud Functions for Firebase และ Firebase Realtime Database

การจำหน่ายสินค้าผ่านระบบคลาวด์ที่ระบุมีฟังก์ชันต่อไปนี้ใน index.js

  • fakeauth: ปลายทางการให้สิทธิ์สำหรับการลิงก์บัญชี
  • faketoken: ปลายทางโทเค็นสำหรับการลิงก์บัญชี
  • smarthome: ปลายทางการดำเนินการตาม Intent สมาร์ทโฮม
  • reportstate: เรียกใช้ Home Graph API เมื่อสถานะอุปกรณ์มีการเปลี่ยนแปลง
  • requestsync: เปิดใช้การอัปเดตอุปกรณ์ของผู้ใช้โดยไม่ต้องลิงก์บัญชีอีกครั้ง

เชื่อมต่อกับ Firebase

ไปที่ไดเรกทอรี washer-start แล้วตั้งค่า Firebase CLI ด้วยโปรเจ็กต์การผสานรวมโดยทำดังนี้

cd washer-start
firebase use <project-id>

กําหนดค่าโปรเจ็กต์ Firebase

เริ่มต้นโปรเจ็กต์ Firebase

firebase init

เลือกฟีเจอร์ CLI, ฐานข้อมูลเรียลไทม์, ฟังก์ชัน และฟีเจอร์โฮสติ้งที่มีโฮสติ้งของ Firebase

? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter
 to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to
 proceed)
>( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore
 ( ) Genkit: Setup a new Genkit project with Firebase
 (*) Functions: Configure a Cloud Functions directory and its files
 ( ) App Hosting: Configure an apphosting.yaml file for App Hosting
 (*) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ( ) Storage: Configure a security rules file for Cloud Storage
 ( ) Emulators: Set up local emulators for Firebase products
 ( ) Remote Config: Configure a template file for Remote Config
 ( ) Extensions: Set up an empty Extensions manifest
 (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision
default instance
 ( ) Data Connect: Set up a Firebase Data Connect service
 ( ) Firestore: Configure security rules and indexes files for Firestore

ซึ่งจะเริ่มต้น API และฟีเจอร์ที่จําเป็นสําหรับโปรเจ็กต์

เริ่มต้น Realtime Database เมื่อได้รับข้อความแจ้ง คุณใช้ตำแหน่งเริ่มต้นสำหรับอินสแตนซ์ฐานข้อมูลได้

? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up?
Yes

? Please choose the location for your default Realtime Database instance:
us-central1

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

? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console?
No

หากจะเริ่มต้นโปรเจ็กต์ใหม่ ให้เลือกเขียนทับเมื่อระบบถามว่าคุณต้องการเริ่มต้นหรือเขียนทับโค้ดเบส

? Would you like to initialize a new codebase, or overwrite an existing one?
Overwrite

เมื่อกําหนดค่าฟังก์ชัน คุณควรใช้ไฟล์เริ่มต้น และตรวจสอบว่าคุณไม่ได้เขียนทับไฟล์ index.js และ package.json ที่มีอยู่เดิมในตัวอย่างโปรเจ็กต์

? What language would you like to use to write Cloud Functions?
JavaScript

? Do you want to use ESLint to catch probable bugs and enforce style?
No

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

หากจะเริ่มต้นโปรเจ็กต์ใหม่ ให้เลือกไม่เมื่อระบบถามว่าคุณต้องการเริ่มต้นหรือเขียนทับ functions/.gitignore

? File functions/.gitignore already exists. Overwrite?
No
? Do you want to install dependencies with npm now?
Yes

สุดท้าย ให้กําหนดค่าการตั้งค่าโฮสติ้งให้ใช้ไดเรกทอรี public ในโค้ดโปรเจ็กต์ และใช้ไฟล์ index.html ที่มีอยู่ เลือกไม่เมื่อระบบขอให้ใช้ ESLint

? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? Set up automatic builds and deploys with GitHub?
No

? File public/index.html already exists. Overwrite?
 No

หากเปิดใช้ ESLint โดยไม่ได้ตั้งใจ คุณปิดใช้ได้ 2 วิธีดังนี้

  1. ใช้ GUI ไปที่โฟลเดอร์ ../functions ใต้โปรเจ็กต์ เลือกไฟล์ .eslintrc.js ที่ซ่อนอยู่ แล้วลบออก อย่าสับสนกับ .eslintrc.json ที่มีชื่อคล้ายกัน
  2. การใช้บรรทัดคำสั่ง
    cd functions
    rm .eslintrc.js
    

ทำให้ใช้งานได้กับ Firebase

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

firebase deploy

นี่คือเอาต์พุตคอนโซลที่คุณควรเห็น

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.web.app

คำสั่งนี้จะทําให้เว็บแอปพร้อมใช้งานพร้อมกับ Cloud Functions for Firebase หลายรายการ

เปิด Hosting URL ในเบราว์เซอร์ (https://<firebase-project-id>.web.app) เพื่อดูเว็บแอป คุณจะเห็นอินเทอร์เฟซต่อไปนี้

5845443e94705557.png

เว็บ UI นี้แสดงแพลตฟอร์มของบุคคลที่สามเพื่อดูหรือแก้ไขสถานะของอุปกรณ์ หากต้องการเริ่มป้อนข้อมูลอุปกรณ์ลงในฐานข้อมูล ให้คลิกอัปเดต คุณจะไม่เห็นว่าหน้าเว็บมีการเปลี่ยนแปลงใดๆ แต่ระบบจะจัดเก็บสถานะปัจจุบันของเครื่องซักผ้าไว้ในฐานข้อมูล

ตอนนี้ถึงเวลาเชื่อมต่อบริการระบบคลาวด์ที่คุณติดตั้งใช้งานกับ Google Assistant โดยใช้ Developer Console

กำหนดค่าโปรเจ็กต์คอนโซลนักพัฒนาซอฟต์แวร์

ในแท็บพัฒนา ให้เพิ่มชื่อที่แสดงสำหรับการโต้ตอบ ชื่อนี้จะปรากฏในแอป Google Home

เพิ่มชื่อที่แสดง

ในส่วนการสร้างแบรนด์แอป ให้อัปโหลดไฟล์ png สำหรับไอคอนแอปขนาด 144 x 144 พิกเซล และตั้งชื่อว่า .png

เพิ่มไอคอนแอป

หากต้องการเปิดใช้การลิงก์บัญชี ให้ใช้การตั้งค่าการลิงก์บัญชีต่อไปนี้

รหัสลูกค้า

ABC123

รหัสลับไคลเอ็นต์

DEF456

URL สำหรับการอนุญาต

https://us-central1-<project-id>.cloudfunctions.net/fakeauth

URL โทเค็น

https://us-central1-<project-id>.cloudfunctions.net/faketoken

อัปเดต URL การลิงก์บัญชี

ในส่วน Cloud fulfillment URL ให้ป้อน URL ของ Cloud Functions ที่ดำเนินการตามคำสั่งสำหรับสมาร์ทโฮม

https://us-central1-<project-id>.cloudfunctions.net/smarthome

เพิ่ม URL ของ Cloud Function

คลิกบันทึกเพื่อบันทึกการกําหนดค่าโปรเจ็กต์ แล้วคลิกถัดไป: ทดสอบเพื่อเปิดใช้การทดสอบในโปรเจ็กต์

ทดสอบการผสานรวมระบบคลาวด์กับระบบคลาวด์

ตอนนี้คุณเริ่มใช้ Webhooks ที่จําเป็นต่อการเชื่อมต่อสถานะของอุปกรณ์กับ Assistant ได้แล้ว

หากต้องการทดสอบการผสานรวมระบบคลาวด์กับระบบคลาวด์ คุณต้องลิงก์โปรเจ็กต์กับบัญชี Google ซึ่งจะช่วยให้ทดสอบผ่านแพลตฟอร์มต่างๆ ของ Google Assistant และแอป Google Home ที่ลงชื่อเข้าใช้บัญชีเดียวกันได้

  1. เปิดการตั้งค่า Google Assistant ในโทรศัพท์ โปรดทราบว่าคุณควรลงชื่อเข้าใช้ด้วยบัญชีเดียวกับในคอนโซล
  2. ไปที่ Google Assistant > การตั้งค่า > การควบคุมอุปกรณ์สมาร์ทโฮม (ในส่วน Assistant)
  3. คลิกไอคอนค้นหาที่ด้านขวาบน
  4. ค้นหาแอปทดสอบโดยใช้คำนำหน้า [test] เพื่อค้นหาแอปทดสอบที่ต้องการ
  5. เลือกรายการนั้น จากนั้น Google Assistant จะตรวจสอบสิทธิ์กับบริการของคุณและส่งคําขอ SYNC โดยขอให้บริการของคุณระบุรายการอุปกรณ์สําหรับผู้ใช้

เปิดแอป Google Home และตรวจสอบว่าคุณเห็นอุปกรณ์เครื่องซักผ้า

ae252220753726f6.png

ยืนยันว่าคุณสามารถควบคุมเครื่องซักผ้าโดยใช้คำสั่งเสียงในแอป Google Home นอกจากนี้ คุณควรเห็นสถานะอุปกรณ์เปลี่ยนแปลงใน UI เว็บส่วนหน้าของการดำเนินการตามคำสั่งซื้อจากระบบคลาวด์ด้วย

เมื่อติดตั้งเครื่องซักผ้าพื้นฐานแล้ว คุณจะปรับแต่งโหมดที่ใช้ได้บนอุปกรณ์ได้

4. เพิ่มโหมด

ลักษณะ action.devices.traits.Modes ช่วยให้อุปกรณ์มีการตั้งค่าสำหรับโหมดได้ไม่จำกัดจำนวน แต่ตั้งค่าได้ครั้งละ 1 รายการเท่านั้น คุณจะเพิ่มโหมดลงในเครื่องซักผ้าเพื่อกำหนดขนาดของผ้าที่จะซักได้ ซึ่งได้แก่ เล็ก กลาง หรือใหญ่

อัปเดตการตอบสนองการซิงค์

คุณต้องเพิ่มข้อมูลเกี่ยวกับลักษณะใหม่ลงในSYNCคําตอบในfunctions/index.js ข้อมูลนี้จะปรากฏในอาร์เรย์ traits และออบเจ็กต์ attributes ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          // Add Modes trait
          'action.devices.traits.Modes',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          //Add availableModes
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en',
            }],
            settings: [{
              setting_name: 'small',
              setting_values: [{
                setting_synonym: ['small'],
                lang: 'en',
              }]
            }, {
              setting_name: 'medium',
              setting_values: [{
                setting_synonym: ['medium'],
                lang: 'en',
              }]
            }, {
              setting_name: 'large',
              setting_values: [{
                setting_synonym: ['large'],
                lang: 'en',
              }]
            }],
            ordered: true,
          }],
        },
      }],
    },
  };
});

เพิ่มคำสั่ง Intent ใหม่สำหรับ EXECUTE

ใน Intent EXECUTE ให้เพิ่มคําสั่ง action.devices.commands.SetModes ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      Break;
    // Add SetModes command
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
  }
};

อัปเดตคำตอบ QUERY

จากนั้นอัปเดตคําตอบ QUERY เพื่อรายงานสถานะปัจจุบันของเครื่องซัก

เพิ่มการเปลี่ยนแปลงที่อัปเดตแล้วลงในฟังก์ชัน queryFirebase และ queryDevice เพื่อรับสถานะที่จัดเก็บไว้ใน Realtime Database

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    // Add Modes snapshot
    load: snapshotVal.Modes.load,
  };
};

const queryDevice = async (deviceId) => {
  const data = await queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    // Add currentModeSettings
    currentModeSettings: {
      load: data.load,
    },
  };
};

อัปเดตสถานะรายงาน

สุดท้าย ให้อัปเดตฟังก์ชัน reportstate เพื่อรายงานการตั้งค่าน้ำหนักปัจจุบันของเครื่องซักผ้าไปยังกราฟในบ้าน

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          // Add currentModeSettings
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
        },
      },
    },
  },
};

เผยแพร่ไปยัง Firebase

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

firebase deploy --only functions

หลังจากการทําให้ใช้งานได้เสร็จสมบูรณ์แล้ว ให้ไปที่ UI ของเว็บ แล้วคลิกปุ่มรีเฟรช ae8d3b25777a5e30.png ในแถบเครื่องมือ ซึ่งจะทริกเกอร์การซิงค์คำขอเพื่อให้ Assistant ได้รับข้อมูลคำตอบ SYNC ที่อัปเดตแล้ว

bf4f6a866160a982.png

ตอนนี้คุณออกคำสั่งเพื่อตั้งค่าโหมดของเครื่องซักผ้าได้แล้ว เช่น

"Ok Google ตั้งค่าปริมาณผ้าในเครื่องซักผ้าเป็น "มาก""

นอกจากนี้ คุณยังถามคำถามเกี่ยวกับเครื่องซักผ้าได้ เช่น

"Ok Google ปริมาณผ้าในเครื่องซักผ้าคือเท่าไหร่"

5. เพิ่มปุ่มเปิด/ปิด

ลักษณะ action.devices.traits.Toggles แสดงถึงแง่มุมที่มีชื่อของอุปกรณ์ซึ่งมีสถานะเป็นจริงหรือเท็จ เช่น เครื่องซักผ้าอยู่ในโหมดเทอร์โบหรือไม่

อัปเดตการตอบสนองการซิงค์

ในการตอบกลับ SYNC คุณจะต้องเพิ่มข้อมูลเกี่ยวกับลักษณะของอุปกรณ์ใหม่ ซึ่งจะปรากฏในอาร์เรย์ traits และออบเจ็กต์ attributes ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

app.onSync(body => {
  return {
    requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
    payload: {
      agentUserId: USER_ID,
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [
          'action.devices.traits.OnOff',
          'action.devices.traits.StartStop',
          'action.devices.traits.RunCycle',
          'action.devices.traits.Modes',
          // Add Toggles trait
          'action.devices.traits.Toggles',
        ],
        name: { ... },
        deviceInfo: { ... },
        attributes: {
          pausable: true,
          availableModes: [{
            name: 'load',
            name_values: [{
              name_synonym: ['load'],
              lang: 'en'
            }],
            settings: [{ ... }],
            ordered: true,
          }],
          //Add availableToggles
          availableToggles: [{
            name: 'Turbo',
            name_values: [{
              name_synonym: ['turbo'],
              lang: 'en',
            }],
          }],
        },
      }],
    },
  };
});

เพิ่มคำสั่ง Intent ใหม่สำหรับ EXECUTE

ใน Intent EXECUTE ให้เพิ่มคําสั่ง action.devices.commands.SetToggles ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

const updateDevice = async (execution,deviceId) => {
  const {params,command} = execution;
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    case 'action.devices.commands.StartStop':
      state = {isRunning: params.start};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      state = {isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.SetModes':
      state = {load: params.updateModeSettings.load};
      ref = firebaseRef.child(deviceId).child('Modes');
      break;
    // Add SetToggles command
    case 'action.devices.commands.SetToggles':
      state = {Turbo: params.updateToggleSettings.Turbo};
      ref = firebaseRef.child(deviceId).child('Toggles');
      break;
  }

อัปเดตคำตอบ QUERY

สุดท้าย คุณต้องอัปเดตคําตอบ QUERY เพื่อรายงานโหมดเทอร์โบของเครื่องซัก เพิ่มการเปลี่ยนแปลงที่อัปเดตแล้วลงในฟังก์ชัน queryFirebase และ queryDevice เพื่อรับสถานะเปิด/ปิดตามที่จัดเก็บไว้ใน Realtime Database

index.js

const queryFirebase = async (deviceId) => {
  const snapshot = await firebaseRef.child(deviceId).once('value');
  const snapshotVal = snapshot.val();
  return {
    on: snapshotVal.OnOff.on,
    isPaused: snapshotVal.StartStop.isPaused,
    isRunning: snapshotVal.StartStop.isRunning,
    load: snapshotVal.Modes.load,
    // Add Toggles snapshot
    Turbo: snapshotVal.Toggles.Turbo,
  };
}

const queryDevice = async (deviceId) => {
  const data = queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{ ... }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
    currentModeSettings: {
      load: data.load,
    },
    // Add currentToggleSettings
    currentToggleSettings: {
      Turbo: data.Turbo,
    },
  };
};

อัปเดตสถานะรายงาน

สุดท้าย ให้อัปเดตฟังก์ชัน reportstate เพื่อรายงานไปยังกราฟในบ้านว่าตั้งค่าเครื่องซักผ้าเป็นโหมดเทอร์โบหรือไม่

index.js

const requestBody = {
  requestId: 'ff36a3cc', /* Any unique ID */
  agentUserId: USER_ID,
  payload: {
    devices: {
      states: {
        /* Report the current state of your washer */
        [context.params.deviceId]: {
          on: snapshot.OnOff.on,
          isPaused: snapshot.StartStop.isPaused,
          isRunning: snapshot.StartStop.isRunning,
          currentModeSettings: {
            load: snapshot.Modes.load,
          },
          // Add currentToggleSettings
          currentToggleSettings: {
            Turbo: snapshot.Toggles.Turbo,
          },
        },
      },
    },
  },
};

เผยแพร่ไปยัง Firebase

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

firebase deploy --only functions

คลิกปุ่มรีเฟรช ae8d3b25777a5e30.png ใน UI ของเว็บเพื่อเรียกให้ส่งคำขอซิงค์หลังจากการทำให้ใช้งานได้เสร็จสมบูรณ์

ตอนนี้คุณออกคำสั่งให้ตั้งค่าเครื่องซักผ้าเป็นโหมดเทอร์โบได้โดยพูดว่า

"Ok Google ตั้งค่าเครื่องซักผ้าเป็นโหมดเทอร์โบ"

นอกจากนี้ คุณยังตรวจสอบได้ว่าเครื่องซักผ้าอยู่ในโหมดเทอร์โบอยู่แล้วหรือไม่โดยทำดังนี้

"Ok Google เครื่องซักผ้าของฉันอยู่ในโหมดเทอร์โบไหม"

6. การรายงานข้อผิดพลาดและข้อยกเว้น

การจัดการข้อผิดพลาดในการผสานรวมระบบคลาวด์กับระบบคลาวด์ช่วยให้คุณรายงานให้ผู้ใช้ทราบได้เมื่อเกิดปัญหาที่ทำให้การตอบกลับ EXECUTE และ QUERY ไม่สำเร็จ การแจ้งเตือนจะสร้างประสบการณ์การใช้งานที่ดียิ่งขึ้นให้แก่ผู้ใช้เมื่อโต้ตอบกับอุปกรณ์อัจฉริยะและการผสานรวม

เมื่อคำขอ EXECUTE หรือ QUERY ไม่สำเร็จ การผสานรวมควรแสดงรหัสข้อผิดพลาด เช่น หากต้องการแสดงข้อผิดพลาดเมื่อผู้ใช้พยายามเปิดเครื่องซักผ้าโดยที่ฝาเปิดอยู่ การตอบกลับ EXECUTE จะมีลักษณะดังนี้

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "456"
        ],
        "status": "ERROR",
        "errorCode": "deviceLidOpen"
      }
    ]
  }
}

ตอนนี้เมื่อผู้ใช้ขอให้เริ่มเครื่องซักผ้า Assistant จะตอบกลับด้วยข้อความว่า

"ฝาเครื่องซักผ้าเปิดอยู่ โปรดปิดแล้วลองอีกครั้ง"

ข้อยกเว้นคล้ายกับข้อผิดพลาด แต่ระบุเมื่อการแจ้งเตือนเชื่อมโยงกับคําสั่ง ซึ่งอาจบล็อกการดำเนินการให้สำเร็จหรือไม่ก็ได้ ข้อยกเว้นสามารถให้ข้อมูลที่เกี่ยวข้องได้โดยใช้ลักษณะ StatusReport เช่น ระดับแบตเตอรี่หรือการเปลี่ยนแปลงสถานะล่าสุด ระบบจะแสดงรหัสข้อยกเว้นที่ไม่บล็อกพร้อมกับสถานะ SUCCESS ส่วนรหัสข้อยกเว้นที่บล็อกจะแสดงพร้อมกับสถานะ EXCEPTIONS

ตัวอย่างคำตอบที่มีข้อยกเว้นอยู่ในข้อมูลโค้ดต่อไปนี้

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [{
      "ids": ["123"],
      "status": "SUCCESS",
      "states": {
        "online": true,
        "isPaused": false,
        "isRunning": false,
        "exceptionCode": "runCycleFinished"
      }
    }]
  }
}

Assistant จะตอบกลับโดยพูดว่า

"เครื่องซักผ้าทำงานเสร็จแล้ว"

หากต้องการเพิ่มการรายงานข้อผิดพลาดสำหรับเครื่องซักผ้า ให้เปิด functions/index.js แล้วเพิ่มคําจํากัดความของคลาสข้อผิดพลาดตามที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

app.onQuery(async (body) => {...});

// Add SmartHome error handling
class SmartHomeError extends Error {
  constructor(errorCode, message) {
    super(message);
    this.name = this.constructor.name;
    this.errorCode = errorCode;
  }
}

อัปเดตการตอบกลับการดำเนินการเพื่อแสดงรหัสข้อผิดพลาดและสถานะข้อผิดพลาด

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push(
        updateDevice(execution, device.id)
        .then((data) => {
          ...
        })
        //Add error response handling
        .catch((error) => {
          functions.logger.error('EXECUTE', device.id, error);
          result.ids.push(device.id);
          if (error instanceof SmartHomeError) {
            result.status = 'ERROR';
            result.errorCode = error.errorCode;
          }
        })
      );
    }
  }
}

ตอนนี้ Assistant สามารถบอกผู้ใช้เกี่ยวกับรหัสข้อผิดพลาดที่คุณรายงานได้แล้ว คุณจะเห็นตัวอย่างที่เฉพาะเจาะจงในส่วนถัดไป

7. เพิ่มการยืนยันผู้ใช้รอง

คุณควรใช้การยืนยันผู้ใช้รองในการผสานรวมหากอุปกรณ์มีโหมดที่ต้องรักษาความปลอดภัยหรือควรจำกัดไว้สำหรับผู้ใช้ที่ได้รับอนุญาตบางกลุ่มเท่านั้น เช่น การอัปเดตซอฟต์แวร์หรือการปลดล็อก

คุณสามารถใช้การยืนยันผู้ใช้รองในอุปกรณ์ทุกประเภทและลักษณะทั้งหมด โดยปรับแต่งได้ว่าจะให้แสดงภารกิจด้านความปลอดภัยทุกครั้งหรือต้องมีคุณสมบัติตรงตามเกณฑ์ที่เฉพาะเจาะจง

คำถามยืนยันที่รองรับมี 3 ประเภท ได้แก่

  • No challenge - คำขอและการตอบกลับที่ไม่ได้ใช้คำขอตรวจสอบสิทธิ์ (นี่คือลักษณะการทำงานเริ่มต้น)
  • ackNeeded - วิธีการยืนยันผู้ใช้สำรองที่ต้องมีการรับทราบอย่างชัดแจ้ง (ใช่หรือไม่)
  • pinNeeded - การยืนยันผู้ใช้รองที่ต้องใช้หมายเลขประจำตัวส่วนบุคคล (PIN)

สําหรับโค้ดแล็บนี้ ให้เพิ่มภารกิจ ackNeeded ลงในคําสั่งสําหรับการเปิดเครื่องซักผ้าและฟังก์ชันการคืนค่าข้อผิดพลาดหากภารกิจยืนยันรองไม่สําเร็จ

เปิด functions/index.js แล้วเพิ่มคําจํากัดความของคลาสข้อผิดพลาดที่แสดงรหัสข้อผิดพลาดและประเภทการยืนยันตามที่แสดงในข้อมูลโค้ดต่อไปนี้

index.js

class SmartHomeError extends Error { ... }

// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
  /**
   * Create a new ChallengeNeededError
   * @param {string} suvType secondary user verification challenge type
   */
  constructor(suvType) {
    super('challengeNeeded', suvType);
    this.suvType = suvType;
  }
}

นอกจากนี้ คุณยังต้องอัปเดตการตอบสนองการเรียกใช้เพื่อแสดงข้อผิดพลาด challengeNeeded ดังนี้

index.js

const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
  for (const device of command.devices) {
    for (const execution of command.execution) {
      executePromises.push(

        updateDevice(execution, device.id)
        .then((data) => {
          ...
        })
        .catch((error) => {
          functions.logger.error('EXECUTE', device.id, error);
          result.ids.push(device.id);
          if (error instanceof SmartHomeError) {
            result.status = 'ERROR';
            result.errorCode = error.errorCode;
            //Add error response handling
            if (error instanceof ChallengeNeededError) {
              result.challengeNeeded = {
                type: error.suvType
              };
            }
          }
        })
      );
    }
  }
}

สุดท้าย ให้แก้ไข updateDevice เพื่อกำหนดให้ต้องมีการรับทราบอย่างชัดเจนเพื่อเปิดหรือปิดเครื่องซักผ้า

index.js

const updateDevice = async (execution,deviceId) => {
  const {challenge,params,command} = execution; //Add secondary user challenge
  let state, ref;
  switch (command) {
    case 'action.devices.commands.OnOff':
      //Add secondary user verification challenge
      if (!challenge || !challenge.ack) {
        throw new ChallengeNeededError('ackNeeded');
      }
      state = {on: params.on};
      ref = firebaseRef.child(deviceId).child('OnOff');
      break;
    ...
  }

  return ref.update(state)
      .then(() => state);
};

เผยแพร่ไปยัง Firebase

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

firebase deploy --only functions

หลังจากติดตั้งใช้งานโค้ดที่อัปเดตแล้ว คุณต้องยอมรับการดำเนินการด้วยวาจาเมื่อขอให้ Assistant เปิดหรือปิดเครื่องซักผ้า ดังนี้

คุณ: "Ok Google เปิดเครื่องซักผ้า"

Assistant: "คุณแน่ใจไหมว่าต้องการเปิดเครื่องซักผ้า"

คุณ: "ใช่"

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

289dbe48f4bb8106.png

8. ขอแสดงความยินดี

674c4f4392e98c1.png

ยินดีด้วย คุณได้ขยายฟีเจอร์ของการผสานรวมระบบคลาวด์กับระบบคลาวด์ผ่านลักษณะ Modes และ Toggles และทำให้การดำเนินการปลอดภัยผ่านการยืนยันผู้ใช้รอง

ดูข้อมูลเพิ่มเติม

ต่อไปนี้คือแนวคิดบางส่วนที่คุณนำไปใช้เพื่อเจาะลึกได้