Tăng cường và bảo mật các hoạt động tích hợp Cloud-to-cloud

1. Trước khi bắt đầu

Các chế độ tích hợp đám mây với đám mây sử dụng các loại thiết bị để cho Trợ lý Google biết nên sử dụng ngữ pháp nào với một thiết bị. Đặc điểm thiết bị xác định các chức năng của một loại thiết bị. Một thiết bị kế thừa trạng thái của từng đặc điểm thiết bị được thêm vào một chế độ tích hợp.

dc8dce0dea87cd5c.png

Bạn có thể kết nối bất kỳ đặc điểm nào được hỗ trợ với loại thiết bị mà bạn đã chọn để tuỳ chỉnh chức năng của thiết bị của người dùng. Nếu bạn muốn triển khai các đặc điểm tuỳ chỉnh trong Hành động hiện không có trong giản đồ thiết bị, thì các đặc điểm Chế độBật/tắt cho phép kiểm soát các chế độ cài đặt cụ thể bằng tên tuỳ chỉnh mà bạn xác định.

Ngoài khả năng điều khiển cơ bản do các loại và đặc điểm cung cấp, Smart Home API còn có các tính năng bổ sung để nâng cao trải nghiệm người dùng. Phản hồi lỗi cung cấp phản hồi chi tiết của người dùng khi ý định không thành công. Bước xác minh người dùng phụ mở rộng các câu trả lời đó và tăng cường bảo mật cho đặc điểm thiết bị mà bạn chọn. Bằng cách gửi phản hồi lỗi cụ thể cho các khối thử thách do Trợ lý đưa ra, tính năng tích hợp từ đám mây đến đám mây của bạn có thể yêu cầu thêm quyền để hoàn tất một lệnh.

Điều kiện tiên quyết

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ triển khai một tính năng tích hợp nhà thông minh tạo sẵn với Firebase, sau đó tìm hiểu cách thêm các đặc điểm không chuẩn vào máy giặt nhà thông minh cho kích thước tải và chế độ tăng tốc. Bạn cũng sẽ triển khai tính năng báo cáo lỗi và ngoại lệ, đồng thời tìm hiểu cách thực thi lời xác nhận bằng lời nói để bật máy giặt bằng cách xác minh người dùng phụ.

Kiến thức bạn sẽ học được

  • Cách thêm các đặc điểm Chế độ và Bật/tắt vào quá trình tích hợp
  • Cách báo cáo lỗi và ngoại lệ
  • Cách đăng ký phương thức xác minh thứ hai khi xác minh người dùng

Bạn cần có

2. Bắt đầu

Bật chế độ Kiểm soát hoạt động

Để sử dụng Trợ lý Google, bạn phải chia sẻ một số dữ liệu hoạt động nhất định với Google. Trợ lý Google cần dữ liệu này để hoạt động đúng cách; tuy nhiên, yêu cầu chia sẻ dữ liệu không dành riêng cho SDK. Để chia sẻ dữ liệu này, hãy tạo một Tài khoản Google nếu bạn chưa có. Bạn có thể sử dụng bất kỳ Tài khoản Google nào, không nhất thiết phải là tài khoản nhà phát triển của bạn.

Mở trang Kiểm soát hoạt động cho Tài khoản Google mà bạn muốn dùng với Trợ lý.

Đảm bảo bạn đã bật các nút bật/tắt sau:

  • Hoạt động trên web và ứng dụng – Ngoài ra, hãy nhớ chọn hộp đánh dấu Bao gồm cả nhật ký duyệt web trên Chrome cũng như hoạt động trên những trang web, ứng dụng và thiết bị sử dụng các dịch vụ của Google.
  • Thông tin thiết bị
  • Hoạt động âm thanh và giọng nói

Tạo dự án Tích hợp đám mây với đám mây

  1. Chuyển đến Developer Console (Bảng điều khiển dành cho nhà phát triển).
  2. Nhấp vào Create Project (Tạo dự án), nhập tên cho dự án rồi nhấp vào Create Project (Tạo dự án).

Đặt tên dự án

Chọn chế độ tích hợp đám mây với đám mây

Trên trang Trang chủ dự án trong Developer Console, hãy chọn Thêm chế độ tích hợp đám mây với đám mây trong phần Đám mây với đám mây.

Thêm tính năng tích hợp từ đám mây sang đám mây

Cài đặt Giao diện dòng lệnh (CLI) của Firebase

Giao diện dòng lệnh (CLI) của Firebase sẽ cho phép bạn phân phát ứng dụng web trên máy và triển khai ứng dụng web lên dịch vụ lưu trữ Firebase.

Để cài đặt CLI, hãy chạy lệnh npm sau đây từ dòng lệnh:

npm install -g firebase-tools

Để xác minh rằng bạn đã cài đặt CLI đúng cách, hãy chạy:

firebase --version

Uỷ quyền cho Firebase CLI bằng tài khoản Google của bạn bằng cách chạy:

firebase login

Tạo dự án Firebase

  1. Chuyển đến Firebase.
  2. Nhấp vào Tạo dự án rồi nhập tên dự án.
  3. Đánh dấu vào hộp đồng ý rồi nhấp vào Tiếp tục. Nếu không có hộp đánh dấu thoả thuận, bạn có thể bỏ qua bước này.
    Tạo dự án Firebase
  4. Sau khi tạo dự án Firebase, hãy tìm mã dự án. Chuyển đến phần Tổng quan về dự án rồi nhấp vào biểu tượng cài đặt > Cài đặt dự án.
    Mở phần cài đặt dự án
  5. Dự án của bạn được liệt kê trong thẻ Chung.
    Cài đặt chung của dự án

Bật HomeGraph API

HomeGraph API cho phép lưu trữ và truy vấn các thiết bị cũng như trạng thái của các thiết bị đó trong Biểu đồ nhà của người dùng. Để sử dụng API này, trước tiên, bạn phải mở Google Cloud Console và bật HomeGraph API.

Trong Google Cloud Console, hãy nhớ chọn dự án khớp với Hành động của bạn <firebase-project-id>.. Sau đó, trong màn hình Thư viện API cho API HomeGraph, hãy nhấp vào Bật.

ee198858a6eac112.png

3. Chạy ứng dụng khởi động

Giờ đây, khi đã thiết lập môi trường phát triển, bạn có thể triển khai dự án khởi động để xác minh mọi thứ đã được định cấu hình đúng cách.

Tải mã nguồn

Nhấp vào đường liên kết sau đây để tải mẫu cho lớp học lập trình này xuống máy phát triển:

...hoặc bạn có thể sao chép kho lưu trữ GitHub từ dòng lệnh:

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

Giải nén tệp zip đã tải xuống.

Giới thiệu về dự án

Dự án khởi động chứa các thư mục con sau:

  • public: Giao diện người dùng phía trước để dễ dàng kiểm soát và theo dõi trạng thái của máy giặt thông minh.
  • functions: Một dịch vụ đám mây được triển khai đầy đủ để quản lý máy giặt thông minh bằng Cloud Functions cho Firebase và Cơ sở dữ liệu theo thời gian thực của Firebase.

Phương thức thực hiện trên đám mây được cung cấp bao gồm các hàm sau trong index.js:

  • fakeauth: Điểm cuối uỷ quyền để liên kết tài khoản
  • faketoken: Điểm cuối mã thông báo để liên kết tài khoản
  • smarthome: Điểm cuối thực hiện ý định nhà thông minh
  • reportstate: Gọi API Biểu đồ nhà khi trạng thái thiết bị thay đổi
  • requestsync: Cho phép người dùng cập nhật thiết bị mà không cần liên kết lại tài khoản

Kết nối với Firebase

Chuyển đến thư mục washer-start, sau đó thiết lập Firebase CLI với dự án tích hợp:

cd washer-start
firebase use <firebase-project-id>

Định cấu hình dự án Firebase

Khởi chạy dự án Firebase.

firebase init

Chọn các tính năng CLI, Cơ sở dữ liệu thời gian thực, Hàm và tính năng Lưu trữ bao gồm cả tính năng Lưu trữ Firebase.

? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then
 Enter to confirm your choices.
❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance
 ◯ Firestore: Configure security rules and indexes files for Firestore
 ◉ Functions: Configure a Cloud Functions directory and its files
 ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ◯ Hosting: 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

Thao tác này sẽ khởi chạy các API và tính năng cần thiết cho dự án của bạn.

Khi được nhắc, hãy khởi chạy Cơ sở dữ liệu theo thời gian thực. Bạn có thể sử dụng vị trí mặc định cho thực thể cơ sở dữ liệu.

? 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

Vì bạn đang sử dụng mã dự án ban đầu, hãy chọn tệp mặc định cho Quy tắc bảo mật và đảm bảo bạn không ghi đè tệp quy tắc cơ sở dữ liệu hiện có.

? 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

Nếu bạn đang khởi tạo lại dự án, hãy chọn Overwrite (Ghi đè) khi được hỏi xem bạn muốn khởi tạo hay ghi đè cơ sở mã.

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

Khi định cấu hình Hàm, bạn nên sử dụng các tệp mặc định và đảm bảo không ghi đè các tệp index.jspackage.json hiện có trong mẫu dự án.

? 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

Nếu bạn đang khởi tạo lại dự án, hãy chọn No (Không) khi được hỏi xem bạn có muốn khởi tạo hay ghi đè các hàm/.gitignore hay không.

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

Cuối cùng, hãy định cấu hình chế độ thiết lập Lưu trữ để sử dụng thư mục public trong mã dự án và sử dụng tệp index.html hiện có. Chọn Không khi được yêu cầu sử dụng 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

Nếu ESLint vô tình được bật, bạn có thể tắt ESLint theo hai cách:

  1. Sử dụng giao diện người dùng, hãy chuyển đến thư mục ../functions trong dự án, chọn tệp .eslintrc.js ẩn rồi xoá tệp đó. Đừng nhầm lẫn với .eslintrc.json có tên tương tự.
  2. Sử dụng dòng lệnh:
    cd functions
    rm .eslintrc.js
    

Triển khai lên Firebase

Giờ đây, khi đã cài đặt các phần phụ thuộc và định cấu hình dự án, bạn đã sẵn sàng chạy ứng dụng lần đầu tiên.

firebase deploy

Đây là kết quả bạn sẽ thấy trên bảng điều khiển:

...

✔ Deploy complete!

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

Lệnh này triển khai một ứng dụng web cùng với một số Cloud Functions cho Firebase.

Mở Hosting URL (URL lưu trữ) trong trình duyệt (https://<firebase-project-id>.web.app) để xem ứng dụng web. Bạn sẽ thấy giao diện sau:

5845443e94705557.png

Giao diện người dùng web này đại diện cho một nền tảng bên thứ ba để xem hoặc sửa đổi trạng thái thiết bị. Để bắt đầu điền thông tin thiết bị vào cơ sở dữ liệu, hãy nhấp vào CẬP NHẬT. Bạn sẽ không thấy thay đổi nào trên trang này, nhưng trạng thái hiện tại của máy giặt sẽ được lưu trữ trong cơ sở dữ liệu.

Bây giờ, bạn có thể kết nối dịch vụ đám mây mà bạn đã triển khai với Trợ lý Google bằng Developer Console (Bảng điều khiển dành cho nhà phát triển).

Định cấu hình dự án trong Developer Console

Trên thẻ Develop (Phát triển), hãy thêm Display Name (Tên hiển thị) cho hoạt động tương tác. Tên này sẽ xuất hiện trong ứng dụng Google Home.

Thêm tên hiển thị

Trong phần Xây dựng thương hiệu ứng dụng, hãy tải tệp png lên cho biểu tượng ứng dụng, có kích thước 144 x 144 px và tên là .png.

Thêm biểu tượng ứng dụng

Để bật tính năng Liên kết tài khoản, hãy sử dụng các chế độ cài đặt liên kết tài khoản sau:

ID khách hàng

ABC123

Mật khẩu ứng dụng khách

DEF456

URL Uỷ quyền

https://us-central1-
.cloudfunctions.net/fakeauth

URL mã thông báo

https://us-central1-
.cloudfunctions.net/faketoken

Cập nhật URL liên kết tài khoản

Trong mục URL thực hiện trên đám mây, hãy nhập URL cho hàm trên đám mây của bạn để thực hiện các ý định về nhà thông minh.

https://us-central1--cloudfunctions.net/smarthome

Thêm URL hàm trên đám mây

Nhấp vào Lưu để lưu cấu hình dự án, sau đó nhấp vào Tiếp theo: Kiểm thử để bật tính năng kiểm thử trên dự án.

Kiểm thử tính năng tích hợp đám mây với đám mây

Giờ đây, bạn có thể bắt đầu triển khai các webhook cần thiết để kết nối trạng thái thiết bị với Trợ lý.

Để kiểm thử tính năng tích hợp đám mây với đám mây, bạn cần liên kết dự án của mình với một Tài khoản Google. Việc này cho phép kiểm thử thông qua các nền tảng Trợ lý Google và ứng dụng Google Home đã đăng nhập vào cùng một tài khoản.

  1. Trên điện thoại, hãy mở phần cài đặt Trợ lý Google. Xin lưu ý rằng bạn phải đăng nhập bằng chính tài khoản mà bạn dùng trong Search Console.
  2. Chuyển đến phần Trợ lý Google > Cài đặt > Điều khiển nhà (trong phần Trợ lý).
  3. Nhấp vào biểu tượng tìm kiếm ở phía trên bên phải.
  4. Tìm ứng dụng kiểm thử bằng tiền tố [test] để tìm ứng dụng kiểm thử cụ thể.
  5. Chọn mục đó. Sau đó, Trợ lý Google sẽ xác thực bằng dịch vụ của bạn và gửi yêu cầu SYNC, yêu cầu dịch vụ của bạn cung cấp danh sách thiết bị cho người dùng.

Mở ứng dụng Google Home và xác minh rằng bạn có thể thấy thiết bị máy giặt.

ae252220753726f6.png

Xác minh rằng bạn có thể điều khiển máy giặt bằng cách sử dụng lệnh thoại trong ứng dụng Google Home. Bạn cũng sẽ thấy trạng thái thiết bị thay đổi trong giao diện người dùng web giao diện người dùng của quy trình thực hiện trên đám mây.

Giờ đây, khi đã triển khai một máy giặt cơ bản, bạn có thể tuỳ chỉnh các chế độ có sẵn trên thiết bị của mình.

4. Thêm chế độ

Thuộc tính action.devices.traits.Modes cho phép thiết bị có số lượng chế độ cài đặt tuỳ ý, trong đó mỗi lần chỉ có thể đặt một chế độ. Bạn sẽ thêm một chế độ vào máy giặt để xác định kích thước của tải quần áo: nhỏ, trung bình hoặc lớn.

Cập nhật phản hồi SYNC

Bạn cần thêm thông tin về đặc điểm mới vào phản hồi SYNC trong functions/index.js. Dữ liệu này xuất hiện trong mảng traits và đối tượng attributes như trong đoạn mã sau.

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,
          }],
        },
      }],
    },
  };
});

Thêm lệnh ý định EXECUTE mới

Trong ý định EXECUTE, hãy thêm lệnh action.devices.commands.SetModes như minh hoạ trong đoạn mã sau.

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;
}

Cập nhật phản hồi QUERY

Tiếp theo, hãy cập nhật phản hồi QUERY để báo cáo trạng thái hiện tại của máy giặt.

Thêm các thay đổi đã cập nhật vào hàm queryFirebasequeryDevice để lấy trạng thái được lưu trữ trong Cơ sở dữ liệu theo thời gian thực.

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,
    },
  };
};

Cập nhật trạng thái báo cáo

Cuối cùng, hãy cập nhật hàm reportstate để báo cáo chế độ cài đặt tải hiện tại của máy giặt cho Biểu đồ nhà.

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,
          },
        },
      },
    },
  },
};

Triển khai lên Firebase

Chạy lệnh sau để triển khai chế độ tích hợp đã cập nhật:

firebase deploy --only functions

Sau khi triển khai xong, hãy chuyển đến giao diện người dùng web rồi nhấp vào nút Refresh (Làm mới) ae8d3b25777a5e30.png trên thanh công cụ. Thao tác này sẽ kích hoạt một Yêu cầu đồng bộ hoá để Trợ lý nhận được dữ liệu phản hồi SYNC đã cập nhật.

bf4f6a866160a982.png

Giờ đây, bạn có thể đưa ra lệnh để đặt chế độ của máy giặt, chẳng hạn như:

"Ok Google, đặt mức tải cho máy giặt thành lớn."

Ngoài ra, bạn có thể đặt câu hỏi về máy giặt, chẳng hạn như:

"Ok Google, máy giặt đang giặt gì?"

5. Thêm nút bật/tắt

Thuộc tính action.devices.traits.Toggles đại diện cho các khía cạnh được đặt tên của một thiết bị có trạng thái đúng hoặc sai, chẳng hạn như máy giặt có ở chế độ tăng tốc hay không.

Cập nhật phản hồi SYNC

Trong phản hồi SYNC, bạn cần thêm thông tin về đặc điểm thiết bị mới. Giá trị này sẽ xuất hiện trong mảng traits và đối tượng attributes như trong đoạn mã sau.

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',
            }],
          }],
        },
      }],
    },
  };
});

Thêm lệnh ý định EXECUTE mới

Trong ý định EXECUTE, hãy thêm lệnh action.devices.commands.SetToggles như minh hoạ trong đoạn mã sau.

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;
  }

Cập nhật phản hồi QUERY

Cuối cùng, bạn cần cập nhật phản hồi QUERY để báo cáo chế độ tăng tốc của máy giặt. Thêm các thay đổi đã cập nhật vào hàm queryFirebasequeryDevice để lấy trạng thái bật/tắt được lưu trữ trong Cơ sở dữ liệu theo thời gian thực.

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,
    },
  };
};

Cập nhật trạng thái báo cáo

Cuối cùng, hãy cập nhật hàm reportstate để báo cáo cho Biểu đồ nhà xem máy giặt có được đặt thành chế độ turbo hay không.

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,
          },
        },
      },
    },
  },
};

Triển khai lên Firebase

Chạy lệnh sau để triển khai các hàm đã cập nhật:

firebase deploy --only functions

Nhấp vào nút Làm mới ae8d3b25777a5e30.png trong giao diện người dùng web để kích hoạt Yêu cầu đồng bộ hoá sau khi triển khai xong.

Giờ đây, bạn có thể ra lệnh đặt máy giặt sang chế độ tăng tốc bằng cách nói:

"Ok Google, bật chế độ turbo cho máy giặt."

Bạn cũng có thể kiểm tra xem máy giặt của mình đã ở chế độ tăng tốc hay chưa bằng cách hỏi:

"Ok Google, máy giặt của tôi có đang ở chế độ tăng tốc không?"

6. Báo cáo lỗi và ngoại lệ

Tính năng xử lý lỗi trong quá trình tích hợp từ đám mây đến đám mây cho phép bạn báo cáo cho người dùng khi các vấn đề khiến phản hồi EXECUTEQUERY không thành công. Thông báo tạo ra trải nghiệm tích cực hơn cho người dùng khi họ tương tác với thiết bị thông minh và tính năng tích hợp của bạn.

Bất cứ khi nào yêu cầu EXECUTE hoặc QUERY không thành công, tính năng tích hợp của bạn sẽ trả về một mã lỗi. Ví dụ: nếu bạn muốn gửi lỗi khi người dùng cố gắng khởi động máy giặt khi nắp đang mở, thì phản hồi EXECUTE của bạn sẽ có dạng như đoạn mã sau:

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

Giờ đây, khi người dùng yêu cầu khởi động máy giặt, Trợ lý sẽ phản hồi bằng cách nói:

"Nắp máy giặt đang mở. Vui lòng đóng rồi thử lại."

Ngoại lệ tương tự như lỗi, nhưng cho biết thời điểm cảnh báo được liên kết với một lệnh. Lệnh này có thể chặn hoặc không chặn việc thực thi thành công. Một ngoại lệ có thể cung cấp thông tin liên quan bằng cách sử dụng đặc điểm StatusReport, chẳng hạn như mức pin hoặc thay đổi trạng thái gần đây. Mã ngoại lệ không chặn được trả về cùng với trạng thái SUCCESS, trong khi mã ngoại lệ chặn được trả về cùng với trạng thái EXCEPTIONS.

Đoạn mã sau đây là ví dụ về phản hồi có ngoại lệ:

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

Trợ lý sẽ trả lời bằng cách nói:

"Máy giặt đã chạy xong."

Để thêm tính năng báo cáo lỗi cho máy giặt, hãy mở functions/index.js và thêm định nghĩa lớp lỗi như trong đoạn mã sau:

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;
  }
}

Cập nhật phản hồi thực thi để trả về mã lỗi và trạng thái lỗi:

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;
          }
        })
      );
    }
  }
}

Giờ đây, Trợ lý có thể cho người dùng biết về mọi mã lỗi mà bạn báo cáo. Bạn sẽ thấy một ví dụ cụ thể trong phần tiếp theo.

7. Thêm phương thức xác minh người dùng thứ hai

Bạn nên triển khai tính năng xác minh người dùng phụ trong quá trình tích hợp nếu thiết bị của bạn có bất kỳ chế độ nào cần được bảo mật hoặc chỉ dành cho một nhóm người dùng được uỷ quyền cụ thể, chẳng hạn như cập nhật phần mềm hoặc mở khoá.

Bạn có thể triển khai phương thức xác minh người dùng phụ trên tất cả các loại thiết bị và đặc điểm, tuỳ chỉnh việc thử thách bảo mật có xuất hiện mỗi lần hay cần đáp ứng các tiêu chí cụ thể.

3 loại thử thách được hỗ trợ:

  • No challenge – Yêu cầu và phản hồi không sử dụng thử thách xác thực (đây là hành vi mặc định)
  • ackNeeded – Bước thứ hai để xác minh người dùng yêu cầu xác nhận rõ ràng (có hoặc không)
  • pinNeeded – Quy trình xác minh người dùng phụ yêu cầu mã số nhận dạng cá nhân (PIN)

Đối với lớp học lập trình này, hãy thêm một thử thách ackNeeded vào lệnh bật máy giặt và chức năng trả về lỗi nếu thử thách xác minh phụ không thành công.

Mở functions/index.js rồi thêm định nghĩa lớp lỗi trả về mã lỗi và loại thử thách như trong đoạn mã sau:

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;
  }
}

Bạn cũng cần cập nhật phản hồi thực thi để trả về lỗi challengeNeeded như sau:

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
              };
            }
          }
        })
      );
    }
  }
}

Cuối cùng, hãy sửa đổi updateDevice để yêu cầu xác nhận rõ ràng về việc bật hoặc tắt máy giặt.

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);
};

Triển khai lên Firebase

Chạy lệnh sau để triển khai hàm đã cập nhật:

firebase deploy --only functions

Sau khi triển khai mã đã cập nhật, bạn phải xác nhận bằng lời nói về hành động khi yêu cầu Trợ lý bật hoặc tắt máy giặt, như sau:

Bạn: "Ok Google, bật máy giặt."

Trợ lý: "Bạn có chắc chắn muốn bật máy giặt không?"

Bạn: "Có."

Bạn cũng có thể xem phản hồi chi tiết cho từng bước trong quy trình xác minh người dùng phụ bằng cách mở nhật ký Firebase.

289dbe48f4bb8106.png

8. Xin chúc mừng

674c4f4392e98c1.png

Xin chúc mừng! Bạn đã mở rộng các tính năng tích hợp Cloud-to-cloud thông qua các đặc điểm ModesToggles, đồng thời bảo mật quá trình thực thi các tính năng đó thông qua quy trình xác minh người dùng phụ.

Tìm hiểu thêm

Sau đây là một số ý tưởng mà bạn có thể triển khai để tìm hiểu sâu hơn:

  • Thêm chức năng thực thi cục bộ vào thiết bị.
  • Sử dụng một loại thử thách xác minh người dùng phụ khác để sửa đổi trạng thái thiết bị.
  • Cập nhật phản hồi QUERY của đặc điểm RunCycle để cập nhật một cách linh động.
  • Khám phá mẫu GitHub này.