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

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

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

dc8dce0dea87cd5c.png

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

เลือกการผสานรวมแบบคลาวด์ต่อคลาวด์

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

เพิ่มการผสานรวมแบบคลาวด์ต่อคลาวด์

ติดตั้ง 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 Developer Console แล้วคลิกต่อไป
    เลือกโปรเจ็กต์ที่อยู่ใน Google Cloud

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

firebase projects:addfirebase

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

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

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

เปิดใช้ HomeGraph API

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

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

ee198858a6eac112.png

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

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

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

คลิกลิงก์ต่อไปนี้เพื่อดาวน์โหลดตัวอย่างสำหรับ Codelab นี้ในเครื่องพัฒนาของคุณ

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

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

คลายไฟล์ ZIP ที่ดาวน์โหลด

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

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

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

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

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

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

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

cd washer-start
firebase use <project-id>

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

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

firebase init

เลือกฟีเจอร์ CLI, Realtime Database และฟีเจอร์ Functions

? 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

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

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

หากเปิดใช้ 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 หลายรายการ

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

5845443e94705557.png

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

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

กำหนดค่าโปรเจ็กต์ใน 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 การลิงก์บัญชี

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

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

เพิ่ม URL ของ Cloud Function

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

ทดสอบการผสานรวมแบบคลาวด์ต่อคลาวด์

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

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

  1. เปิดการตั้งค่า Google Assistant ในโทรศัพท์ โปรดทราบว่าคุณควรลงชื่อเข้าใช้บัญชีเดียวกับที่ใช้ในคอนโซล
  2. ไปที่ Google Assistant > การตั้งค่า > การควบคุมบ้าน (ในส่วน Assistant)
  3. คลิกไอคอนค้นหาที่ด้านขวาบน
  4. ค้นหาแอปทดสอบโดยใช้คำนำหน้า [ทดสอบ] เพื่อค้นหาแอปทดสอบที่ต้องการ
  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 ใหม่

ในความตั้งใจ 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 เพื่อรายงานการตั้งค่าการโหลดปัจจุบันของเครื่องซักผ้าไปยัง Home Graph

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 ใหม่

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

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 รวมถึงรักษาความปลอดภัยในการดำเนินการผ่านการยืนยันผู้ใช้รอง

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

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

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