1. ก่อนเริ่มต้น
ในฐานะนักพัฒนา Internet of Things (IoT) คุณสามารถสร้างการผสานรวมแบบคลาวด์ต่อคลาวด์ที่ช่วยให้ผู้ใช้ควบคุมอุปกรณ์ผ่านการควบคุมแบบสัมผัสในแอป Google Home และคำสั่งเสียงด้วย Assistant ได้

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

ข้อกำหนดเบื้องต้น
- คู่มือสำหรับนักพัฒนาซอฟต์แวร์สร้างการผสานรวมแบบคลาวด์ต่อคลาวด์
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะได้เผยแพร่บริการระบบคลาวด์ที่จัดการเครื่องซักผ้าอัจฉริยะเสมือน จากนั้นสร้างการผสานรวมแบบคลาวด์ต่อคลาวด์และเชื่อมต่อกับ Assistant
สิ่งที่คุณจะได้เรียนรู้
- วิธีติดตั้งใช้งานบริการระบบคลาวด์สำหรับบ้านอัจฉริยะ
- วิธีเชื่อมต่อบริการกับ Assistant
- วิธีเผยแพร่การเปลี่ยนแปลงสถานะอุปกรณ์ไปยัง Google
สิ่งที่คุณต้องมี
- เว็บเบราว์เซอร์ เช่น Google Chrome
- อุปกรณ์ iOS หรือ Android ที่ติดตั้งแอป Google Home
- Node.js เวอร์ชัน 10.16 ขึ้นไป
- บัญชีสำหรับการเรียกเก็บเงินของ Google Cloud
2. เริ่มต้นใช้งาน
เปิดใช้ส่วนควบคุมกิจกรรม
หากต้องการใช้ Google Assistant คุณต้องแชร์ข้อมูลกิจกรรมบางอย่างกับ Google Google Assistant ต้องใช้ข้อมูลนี้เพื่อให้ทำงานได้อย่างถูกต้อง แต่ข้อกำหนดในการแชร์ข้อมูลไม่ได้เจาะจงไปที่ SDK หากต้องการแชร์ข้อมูลนี้ ให้สร้างบัญชี Google หากยังไม่มี คุณใช้บัญชี Google ใดก็ได้ ไม่จำเป็นต้องเป็นบัญชีนักพัฒนาแอป
เปิดหน้าส่วนควบคุมกิจกรรมสำหรับบัญชี Google ที่ต้องการใช้กับ Assistant
ตรวจสอบว่าได้เปิดใช้สวิตช์เปิด/ปิดต่อไปนี้แล้ว
- กิจกรรมบนเว็บและแอป - นอกจากนี้ อย่าลืมเลือกช่องทําเครื่องหมายรวมประวัติการเข้าชมใน Chrome และกิจกรรมจากเว็บไซต์ แอป และอุปกรณ์ที่ใช้บริการต่างๆ ของ Google
- ข้อมูลอุปกรณ์
- กิจกรรมเสียงพูดและเสียง
สร้างโปรเจ็กต์การผสานรวมแบบคลาวด์ต่อคลาวด์
- ไปที่แผงควบคุมสำหรับนักพัฒนาแอป
- คลิกสร้างโปรเจ็กต์ ป้อนชื่อโปรเจ็กต์ แล้วคลิกสร้างโปรเจ็กต์

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

ติดตั้ง Firebase CLI
อินเทอร์เฟซบรรทัดคำสั่ง (CLI) ของ Firebase จะช่วยให้คุณแสดงเว็บแอปในเครื่องและทําให้เว็บแอปใช้งานได้ในโฮสติ้งของ Firebase
หากต้องการติดตั้ง CLI ให้เรียกใช้คำสั่ง npm ต่อไปนี้จากเทอร์มินัล
npm install -g firebase-tools
หากต้องการยืนยันว่าได้ติดตั้ง CLI อย่างถูกต้องแล้ว ให้เรียกใช้คำสั่งต่อไปนี้
firebase --version
ให้สิทธิ์ Firebase CLI ด้วยบัญชี Google โดยการเรียกใช้คำสั่งต่อไปนี้
firebase login
3. เรียกใช้แอปเริ่มต้น
ตอนนี้คุณได้ตั้งค่าสภาพแวดล้อมในการพัฒนาแล้ว คุณสามารถติดตั้งใช้งานโปรเจ็กต์เริ่มต้นเพื่อยืนยันว่าทุกอย่างได้รับการกำหนดค่าอย่างถูกต้อง
รับซอร์สโค้ด
คลิกลิงก์ต่อไปนี้เพื่อดาวน์โหลดตัวอย่างสำหรับ Codelab นี้ในเครื่องพัฒนาของคุณ
คุณยังโคลนที่เก็บ GitHub จากบรรทัดคำสั่งได้ด้วย
git clone https://github.com/google-home/smarthome-washer.git
เกี่ยวกับโครงการนี้
โปรเจ็กต์เริ่มต้นมีไดเรกทอรีย่อยต่อไปนี้
- public:UI ส่วนหน้าเพื่อควบคุมและตรวจสอบสถานะของเครื่องซักผ้าอัจฉริยะได้อย่างง่ายดาย
- functions:บริการระบบคลาวด์ที่ใช้งานอย่างเต็มรูปแบบซึ่งจัดการเครื่องซักผ้าอัจฉริยะด้วย Cloud Functions for Firebase และฐานข้อมูลเรียลไทม์ของ Firebase
เพิ่ม Firebase ลงในโปรเจ็กต์ Google Home Developer Console
วิธีที่ 1: ผ่านคอนโซล Firebase
- ไปที่ Firebase
- คลิกสร้างโปรเจ็กต์ Firebase  
- ในหน้าจอสร้างโปรเจ็กต์ ให้คลิกเพิ่ม Firebase ไปยังโปรเจ็กต์ Google Cloud  
- ในหน้าจอเริ่มต้นใช้งาน ให้เลือกโปรเจ็กต์ Google Cloud ที่คุณเพิ่งสร้างใน Google Home Developer Console แล้วคลิกต่อไป  
วิธีที่ 2: ผ่าน Firebase CLI
firebase projects:addfirebase
เลือกโปรเจ็กต์ Google Home Developer Console ที่คุณเพิ่งสร้างเพื่อเพิ่ม Firebase
เมื่อเพิ่ม Firebase ลงในโปรเจ็กต์ Google Home Developer Console แล้ว Firebase จะปรากฏในคอนโซล Firebase รหัสโปรเจ็กต์ของโปรเจ็กต์ Firebase จะสอดคล้องกับรหัสโปรเจ็กต์ Google Home Developer Console

เชื่อมต่อกับ 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 วิธีดังนี้
- ใช้ GUI เพื่อไปที่โฟลเดอร์ ../functionsในโปรเจ็กต์ เลือกไฟล์ที่ซ่อน.eslintrc.jsแล้วลบ อย่าสับสนกับ.eslintrc.jsonที่มีชื่อคล้ายกัน
- โดยใช้บรรทัดคำสั่ง ให้ทำดังนี้cd functions rm .eslintrc.js 
ในไฟล์ washer-start/firebase.json ให้เขียนโค้ดให้เสร็จสมบูรณ์โดยใช้ข้อมูลต่อไปนี้
{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
    "headers": [{
      "source" : "**/*.@(js|html)",
      "headers" : [ {
        "key" : "Cache-Control",
        "value" : "max-age=0"
      } ]
    }],
  "functions": [
    {
      "source": "functions",
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log",
        "*.local"
      ]
    }
  ]
}
ทําให้ใช้งานได้กับ 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://<project-id>.web.app) เพื่อดูเว็บแอป คุณจะเห็นอินเทอร์เฟซต่อไปนี้

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

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

หากต้องการเปิดใช้การลิงก์บัญชี ให้ใช้การตั้งค่าการลิงก์บัญชีต่อไปนี้
| รหัสลูกค้า | 
 | 
| รหัสลับไคลเอ็นต์ | 
 | 
| URL สำหรับการอนุญาต | 
 | 
| URL โทเค็น | 
 | 

ในส่วน URL การดำเนินการตามคำสั่งในระบบคลาวด์ ให้ป้อน URL สำหรับ Cloud Functions ที่ให้การดำเนินการตามคำสั่งสำหรับ Intent ของสมาร์ทโฮม
https://us-central1-<project-id>.cloudfunctions.net/smarthome

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

ตอนนี้คุณเริ่มใช้ Webhook ที่จำเป็นเพื่อเชื่อมต่อสถานะอุปกรณ์กับ Assistant ได้แล้ว
4. สร้างเครื่องซักผ้า
เมื่อกำหนดค่าการผสานรวมแล้ว คุณจะเพิ่มอุปกรณ์และส่งข้อมูลได้ บริการระบบคลาวด์ของคุณต้องจัดการ Intent ต่อไปนี้
- SYNCความตั้งใจจะเกิดขึ้นเมื่อ Assistant ต้องการทราบว่าผู้ใช้เชื่อมต่ออุปกรณ์ใดไว้ ระบบจะส่งข้อมูลนี้ไปยังบริการของคุณเมื่อผู้ใช้ลิงก์บัญชี คุณควรตอบกลับด้วยเพย์โหลด JSON ของอุปกรณ์ทั้งหมดของผู้ใช้และความสามารถของอุปกรณ์
- QUERYเจตนาจะเกิดขึ้นเมื่อ Assistant ต้องการทราบสถานะปัจจุบันของอุปกรณ์ คุณควรตอบกลับด้วยเพย์โหลด JSON ที่มีสถานะของอุปกรณ์แต่ละเครื่องที่ขอ
- EXECUTEเจตนาจะเกิดขึ้นเมื่อ Assistant ต้องการควบคุมอุปกรณ์ในนามของผู้ใช้ คุณควรตอบกลับด้วยเพย์โหลด JSON ที่มีสถานะการดำเนินการของอุปกรณ์แต่ละเครื่องที่ขอ
- DISCONNECTเจตนาจะเกิดขึ้นเมื่อผู้ใช้ยกเลิกการลิงก์บัญชีกับ Assistant คุณควรหยุดส่งเหตุการณ์สำหรับอุปกรณ์ของผู้ใช้รายนี้ไปยัง Assistant
คุณจะอัปเดตฟังก์ชันที่เคยติดตั้งใช้งานเพื่อจัดการเจตนาเหล่านี้ในส่วนต่อไปนี้
อัปเดตการตอบสนองการซิงค์
เปิด functions/index.js ซึ่งมีโค้ดเพื่อตอบสนองต่อคำขอจาก Assistant
คุณจะต้องจัดการSYNC Intent โดยการส่งคืนข้อมูลเมตาและความสามารถของอุปกรณ์ อัปเดต JSON ในอาร์เรย์ onSync เพื่อรวมข้อมูลอุปกรณ์และลักษณะที่แนะนำสำหรับเครื่องซักผ้า
index.js
app.onSync((body) => {
  return {
    requestId: body.requestId,
    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',
        ],
        name: {
          defaultNames: ['My Washer'],
          name: 'Washer',
          nicknames: ['Washer'],
        },
        deviceInfo: {
          manufacturer: 'Acme Co',
          model: 'acme-washer',
          hwVersion: '1.0',
          swVersion: '1.0.1',
        },
        willReportState: true,
        attributes: {
          pausable: true,
        },
      }],
    },
  };
});
ทําให้ใช้งานได้กับ Firebase
ทำให้การประมวลผลคำสั่งบนระบบคลาวด์ที่อัปเดตใช้งานได้โดยใช้ Firebase CLI ดังนี้
firebase deploy --only functions
ลิงก์กับ Google Assistant
หากต้องการทดสอบการผสานรวมแบบคลาวด์ต่อคลาวด์ คุณต้องลิงก์โปรเจ็กต์กับบัญชี Google ซึ่งจะช่วยให้ทดสอบผ่านแพลตฟอร์ม Google Assistant และแอป Google Home ที่ลงชื่อเข้าใช้บัญชีเดียวกันได้
- เปิดการตั้งค่า Google Assistant ในโทรศัพท์ โปรดทราบว่าคุณควรลงชื่อเข้าใช้บัญชีเดียวกับที่ใช้ในคอนโซล
- ไปที่ Google Assistant > การตั้งค่า > การควบคุมบ้าน (ในส่วน Assistant)
- คลิกไอคอนค้นหาที่ด้านขวาบน
- ค้นหาแอปทดสอบโดยใช้คำนำหน้า [ทดสอบ] เพื่อค้นหาแอปทดสอบที่ต้องการ
- เลือกรายการนั้น จากนั้น Google Assistant จะตรวจสอบสิทธิ์กับบริการของคุณและส่งคำขอ SYNCโดยขอให้บริการของคุณแสดงรายการอุปกรณ์สำหรับผู้ใช้
เปิดแอป Google Home แล้วตรวจสอบว่าคุณเห็นอุปกรณ์เครื่องซักผ้า

5. จัดการคำสั่งและการค้นหา
ตอนนี้บริการระบบคลาวด์รายงานอุปกรณ์เครื่องซักผ้าให้ Google อย่างถูกต้องแล้ว คุณต้องเพิ่มความสามารถในการขอสถานะอุปกรณ์และส่งคำสั่ง
จัดการ Intent QUERY
QUERY เจตนาประกอบด้วยชุดอุปกรณ์ คุณควรตอบกลับพร้อมสถานะปัจจุบันของอุปกรณ์แต่ละเครื่อง
ใน functions/index.js ให้แก้ไขแฮนเดิล QUERY เพื่อประมวลผลรายการอุปกรณ์เป้าหมายที่มีอยู่ในคำขอ Intent
index.js
app.onQuery(async (body) => {
  const {requestId} = body;
  const payload = {
    devices: {},
  };
  const queryPromises = [];
  const intent = body.inputs[0];
  for (const device of intent.payload.devices) {
    const deviceId = device.id;
    queryPromises.push(queryDevice(deviceId)
        .then((data) => {
        // Add response to device payload
          payload.devices[deviceId] = data;
        }
        ));
  }
  // Wait for all promises to resolve
  await Promise.all(queryPromises);
  return {
    requestId: requestId,
    payload: payload,
  };
});
สำหรับอุปกรณ์แต่ละเครื่องที่อยู่ในคำขอ ให้แสดงสถานะปัจจุบันที่จัดเก็บไว้ใน Realtime Database อัปเดตฟังก์ชัน queryFirebase และ queryDevice เพื่อแสดงผลข้อมูลสถานะของเครื่องซักผ้า
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,
  };
};
const queryDevice = async (deviceId) => {
  const data = await queryFirebase(deviceId);
  return {
    on: data.on,
    isPaused: data.isPaused,
    isRunning: data.isRunning,
    currentRunCycle: [{
      currentCycle: 'rinse',
      nextCycle: 'spin',
      lang: 'en',
    }],
    currentTotalRemainingTime: 1212,
    currentCycleRemainingTime: 301,
  };
};
จัดการ Intent EXECUTE
EXECUTE เจตนาจะจัดการคำสั่งเพื่ออัปเดตสถานะอุปกรณ์ การตอบกลับจะแสดงสถานะของแต่ละคำสั่ง เช่น SUCCESS, ERROR หรือ PENDING และสถานะใหม่ของอุปกรณ์
ใน functions/index.js ให้แก้ไขแฮนเดิล EXECUTE เพื่อประมวลผลรายการลักษณะที่ต้องอัปเดตและชุดอุปกรณ์เป้าหมายสำหรับแต่ละคำสั่ง
index.js
app.onExecute(async (body) => {
  const {requestId} = body;
  // Execution results are grouped by status
  const result = {
    ids: [],
    status: 'SUCCESS',
    states: {
      online: true,
    },
  };
  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) => {
                  result.ids.push(device.id);
                  Object.assign(result.states, data);
                })
                .catch(() => functions.logger.error('EXECUTE', device.id)));
      }
    }
  }
  await Promise.all(executePromises);
  return {
    requestId: requestId,
    payload: {
      commands: [result],
    },
  };
});
สำหรับแต่ละคำสั่งและอุปกรณ์เป้าหมาย ให้อัปเดตค่าใน Realtime Database ที่สอดคล้องกับลักษณะที่ขอ แก้ไขฟังก์ชัน updateDevice เพื่ออัปเดตการอ้างอิง Firebase ที่เหมาะสมและแสดงผลสถานะอุปกรณ์ที่อัปเดตแล้ว
index.js
const updateDevice = async (execution, deviceId) => {
  const {params, command} = execution;
  let state; let 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 = params.start
      ? {isRunning: true, isPaused: false}
      : {isRunning: false, isPaused: false};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
    case 'action.devices.commands.PauseUnpause':
      const data = await queryDevice(deviceId);
      state = (data.isPaused === false && data.isRunning === false)
        ? {isRunning: false, isPaused: false}
        : {isRunning: !params.pause, isPaused: params.pause};
      ref = firebaseRef.child(deviceId).child('StartStop');
      break;
  }
  return ref.update(state)
      .then(() => state);
};
6. ทดสอบการผสานรวม
หลังจากติดตั้งใช้งานทั้ง 3 เจตนาแล้ว คุณจะทดสอบได้ว่าการผสานรวมควบคุมเครื่องซักผ้าได้
ทําให้ใช้งานได้กับ Firebase
ทำให้การประมวลผลคำสั่งบนระบบคลาวด์ที่อัปเดตใช้งานได้โดยใช้ Firebase CLI ดังนี้
firebase deploy --only functions
ทดสอบเครื่องซักผ้า
ตอนนี้คุณจะเห็นการเปลี่ยนแปลงค่าเมื่อลองใช้คำสั่งเสียงต่อไปนี้ผ่านโทรศัพท์
"Ok Google เปิดเครื่องซักผ้า"
"Ok Google หยุดเครื่องซักผ้าชั่วคราว"
"Ok Google หยุดเครื่องซักผ้า"
นอกจากนี้ คุณยังดูสถานะปัจจุบันของเครื่องซักผ้าได้ด้วยการถามคำถาม
"Ok Google เครื่องซักผ้าเปิดอยู่ไหม"
"Ok Google เครื่องซักผ้าของฉันทำงานอยู่ไหม"
"Ok Google เครื่องซักผ้าของฉันกำลังซักรอบไหน"
คุณดูการค้นหาและคำสั่งเหล่านี้ได้ในบันทึกที่ปรากฏใต้ฟังก์ชันในส่วนฟังก์ชันของ Firebase Console ดูข้อมูลเพิ่มเติมเกี่ยวกับบันทึก Firebase ได้ที่เขียนและดูบันทึก
นอกจากนี้ คุณยังดูการค้นหาและคำสั่งเหล่านี้ได้ใน Google Cloud Console โดยไปที่การบันทึก > Logs Explorer ดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกของ Google Cloud ในบันทึกเหตุการณ์การเข้าถึงด้วย Cloud Logging
7. รายงานการอัปเดตให้ Google ทราบ
คุณได้ผสานรวมบริการระบบคลาวด์กับ Intent สมาร์ทโฮมอย่างเต็มรูปแบบแล้ว ซึ่งช่วยให้ผู้ใช้ควบคุมและค้นหาสถานะปัจจุบันของอุปกรณ์ได้ อย่างไรก็ตาม การติดตั้งใช้งานยังไม่มีวิธีให้บริการของคุณส่งข้อมูลเหตุการณ์ เช่น การเปลี่ยนแปลงสถานะหรือสถานะของอุปกรณ์ ไปยัง Assistant โดยอัตโนมัติ
ขอซิงค์ช่วยให้คุณทริกเกอร์คำขอซิงค์ใหม่ได้เมื่อผู้ใช้เพิ่มหรือนำอุปกรณ์ออก หรือเมื่อความสามารถของอุปกรณ์เปลี่ยนแปลงไป เมื่อใช้รายงานสถานะ บริการระบบคลาวด์จะส่งสถานะของอุปกรณ์ไปยังกราฟบ้านได้โดยอัตโนมัติเมื่อผู้ใช้เปลี่ยนสถานะของอุปกรณ์ด้วยตนเอง เช่น เปิดสวิตช์ไฟ หรือเปลี่ยนสถานะโดยใช้บริการอื่น
ในส่วนนี้ คุณจะเพิ่มโค้ดเพื่อเรียกใช้เมธอดเหล่านี้จากเว็บแอปฟรอนท์เอนด์
เปิดใช้ HomeGraph API
HomeGraph API ช่วยให้จัดเก็บและค้นหาอุปกรณ์และสถานะของอุปกรณ์ภายใน Home Graph ของผู้ใช้ได้ หากต้องการใช้ API นี้ คุณต้องเปิด Google Cloud Console และเปิดใช้ HomeGraph API ก่อน
ใน Google Cloud Console ให้เลือกโปรเจ็กต์ที่ตรงกับการผสานรวม <project-id>. จากนั้นในหน้าจอคลัง API สำหรับ HomeGraph API ให้คลิกเปิดใช้

เปิดใช้สถานะรายงาน
การเขียนไปยัง Realtime Database จะทริกเกอร์ฟังก์ชัน reportstate ในโปรเจ็กต์เริ่มต้น อัปเดตฟังก์ชัน reportstate ใน functions/index.js เพื่อบันทึกข้อมูลที่เขียนลงในฐานข้อมูลและโพสต์ไปยัง Home Graph โดยใช้รายงานสถานะ
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
    async (change, context) => {
      functions.logger.info('Firebase write event triggered Report State');
      const snapshot = change.after.val();
      const requestBody = {
        requestId: 'ff36a3cc', /* Any unique ID */
        agentUserId: USER_ID,
        payload: {
          devices: {
            states: {
              /* Report the current state of our washer */
              [context.params.deviceId]: {
                on: snapshot.OnOff.on,
                isPaused: snapshot.StartStop.isPaused,
                isRunning: snapshot.StartStop.isRunning,
              },
            },
          },
        },
      };
      const res = await homegraph.devices.reportStateAndNotification({
        requestBody,
      });
      functions.logger.info('Report state response:', res.status, res.data);
    });
เปิดใช้การซิงค์คำขอ
การรีเฟรชไอคอนใน UI เว็บส่วนหน้าจะทริกเกอร์ฟังก์ชัน requestsync ในโปรเจ็กต์เริ่มต้น ใช้ฟังก์ชัน requestsync ใน functions/index.js เพื่อเรียก HomeGraph API
index.js
exports.requestsync = functions.https.onRequest(async (request, response) => {
  response.set('Access-Control-Allow-Origin', '*');
  functions.logger.info(`Request SYNC for user ${USER_ID}`);
  try {
    const res = await homegraph.devices.requestSync({
      requestBody: {
        agentUserId: USER_ID,
      },
    });
    functions.logger.info('Request sync response:', res.status, res.data);
    response.json(res.data);
  } catch (err) {
    functions.logger.error(err);
    response.status(500).send(`Error requesting sync: ${err}`);
  }
});
ทําให้ใช้งานได้กับ Firebase
ทําให้โค้ดที่อัปเดตใช้งานได้โดยใช้ Firebase CLI ดังนี้
firebase deploy --only functions
ทดสอบการใช้งาน
คลิกปุ่มรีเฟรช  ใน Web UI และตรวจสอบว่าคุณเห็นคำขอซิงค์ในบันทึกคอนโซล Firebase
ใน Web UI และตรวจสอบว่าคุณเห็นคำขอซิงค์ในบันทึกคอนโซล Firebase
จากนั้นปรับแอตทริบิวต์ของอุปกรณ์เครื่องซักผ้าใน UI เว็บส่วนหน้า แล้วคลิกอัปเดต ตรวจสอบว่าคุณเห็นการเปลี่ยนแปลงสถานะที่รายงานไปยัง Google ในบันทึกของคอนโซล Firebase
8. ขอแสดงความยินดี

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