Cải thiện và bảo vệ Hành động thông minh trong nhà của bạn

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

Hành động trong nhà thông minh sử dụng loại thiết bị để cho Trợ lý Google biết ngữ pháp nào nên dùng với một thiết bị. Trait của thiết bị xác định chức năng của một loại thiết bị. Thiết bị sẽ kế thừa các trạng thái của từng đặc điểm thiết bị được thêm vào Hành động.

dc8dce0dea87cd5c.png

Bạn có thể kết nối mọi trait được hỗ trợ với loại thiết bị mà bạn đã chọn để tuỳ chỉnh chức năng trên 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 chưa có trong giản đồ thiết bị, thì các trait Modes (Chế độ) và Toggles (Bật/tắt) sẽ cho phép kiểm soát các chế độ cài đặt cụ thể bằng tên tuỳ chỉnh do bạn xác định.

Ngoài khả năng điều khiển cơ bản theo loại và đặc điểm, 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 về lỗi cung cấp ý kiến phản hồi chi tiết của người dùng khi ý định không thành công. Phương thức xác minh thứ hai khi xác minh người dùng sẽ mở rộng những phản hồi đó và tăng cường bảo mật cho đặc điểm của 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 lệnh chặn thử thách do Trợ lý đưa ra, Hành động trong nhà thông minh của bạn có thể cần bạn cho phép thêm để hoàn thành 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 quá trình tích hợp nhà thông minh được tạo sẵn với Firebase, sau đó tìm hiểu cách thêm các đặc điểm không tiêu chuẩn vào máy giặt nhà thông minh để đo kích thước tải trọng và chế độ tăng áp. Bạn cũng sẽ triển khai báo cáo lỗi và ngoại lệ, đồng thời tìm hiểu cách xác nhận bằng lời nói để bật máy giặt thông qua phương thức xác minh thứ hai khi xác minh người dùng.

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 Hành động của bạn
  • Cách báo cáo lỗi và trường hợp ngoại lệ
  • Cách áp dụng 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 các 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 với Google. Trợ lý Google cần có dữ liệu này để hoạt động bình thường; tuy nhiên, yêu cầu chia sẻ dữ liệu không chỉ 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ể 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.

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

Đảm bảo các nút chuyển sau đây đã được bật:

  • 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 Actions

  1. Truy cập vào Actions on Google Developer Console.
  2. Nhấp vào New Project (Dự án mới), nhập tên cho dự án rồi nhấp vào TẠO DỰ ÁN.

3d6b68ca79afd54c.png.

Chọn ứng dụng Nhà thông minh

Trên màn hình Tổng quan trong bảng điều khiển Actions, hãy chọn Nhà thông minh.

2fa4988f44f8914b.png.

Chọn thẻ trải nghiệm Nhà thông minh, nhấp vào Bắt đầu xây dựng rồi bạn sẽ được chuyển đến bảng điều khiển dự án.

Cài đặt Firebase CLI

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

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

npm install -g firebase-tools

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

firebase --version

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

firebase login

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 Home Graph của người dùng. Để sử dụng API này, trước tiên, bạn phải mở bảng điều khiển Google Cloud và bật API HomeGraph.

Trong bảng điều khiển Google Cloud, hãy nhớ chọn dự án khớp với Hành động <project-id>. của bạn. Sau đó, trên 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 đầu

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

Lấy 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 của bạ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 đầu chứa các thư mục con sau:

  • public: Một giao diện người dùng giao diện người dùng giúp dễ dàng điều khiển 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 đủ giúp quản lý máy giặt thông minh bằng Chức năng đám mây 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 của đá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 cho việc 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 cho nhà thông minh
  • reportstate: Gọi Home Graph API khi trạng thái thiết bị thay đổi
  • requestsync: Cho phép cập nhật thiết bị của người dùng 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 Giao diện dòng lệnh (CLI) của Firebase bằng dự án Hành động của bạn:

cd washer-start
firebase use <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 theo thời gian thực, Hàm và tính năng Lưu trữ bao gồm cả 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

Do bạn đang sử dụng mã dự án khởi đầu, hãy chọn tệp mặc định cho các 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 chạy lại dự án, hãy chọn Ghi đè khi được hỏi xem bạn muốn khởi chạy 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 bạn 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 bạn muốn khởi chạy hay ghi đè hàm/.gitignore.

? 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 phần 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, có hai phương pháp để vô hiệu hoá ESLint:

  1. Sử dụng GUI (Giao diện người dùng đồ hoạ), chuyển đến thư mục ../functions trong dự án, chọn tệp ẩn .eslintrc.js rồi xoá tệp đó. Đừng nhầm lẫn thuộc tính này 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 cho Firebase

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

firebase deploy

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

...

✔ Deploy complete!

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

Lệnh này sẽ triển khai một ứng dụng web, cùng với một số Chức năng đám mây cho Firebase.

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

5845443e94705557.pngs

Giao diện người dùng web này đại diện cho nền tảng của 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ị cho cơ sở dữ liệu của bạn, hãy nhấp vào CẬP NHẬT. Bạn sẽ không thấy bất kỳ thay đổi nào trên trang. Tuy nhiên, 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.

Giờ là lúc kết nối dịch vụ đám mây mà bạn đã triển khai với Trợ lý Google bằng Bảng điều khiển Actions.

Định cấu hình dự án trên bảng điều khiển Actions

Trong phần Tổng quan > Xây dựng hành động của bạn, hãy chọn Thêm(các) hành động. Nhập URL cho hàm đám mây của bạn nhằm thực hiện ý định cho nhà thông minh rồi nhấp vào Lưu.

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

9d7b223427f587ca.png.

Trên thẻ Develop > Invocation (Phát triển > Gọi), thêm Display Name (Tên hiển thị) cho Hành động của bạn và nhấp vào Save (Lưu). Tên này sẽ xuất hiện trong ứng dụng Google Home.

774d0c40c351c7da.png.

a8c4673eb11d76ee.png

Để bật tính năng Liên kết tài khoản, hãy chọn tuỳ chọn Phát triển > Liên kết tài khoản trong bảng điều hướng bên trái. Sử dụng các chế độ cài đặt liên kết tài khoản sau:

Client ID

ABC123

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

DEF456

URL Uỷ quyền

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

URL mã thông báo

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

9730d20b90bcc038.pngs

Nhấp vào Save (Lưu) để lưu cấu hình liên kết tài khoản, sau đó nhấp vào Test (Kiểm thử) để bật tính năng kiểm thử trên dự án.

ee0547f05b5efd98.png

Bạn sẽ được chuyển hướng đến Trình mô phỏng. Nếu bạn không thấy thông báo "Thử nghiệm hiện đã được bật", hãy nhấp vào Đặt lại thử nghiệm để xác minh rằng hoạt động thử nghiệm đã được bật.

d0495810dbadf059.png

Để thử nghiệm Hành động trong nhà thông minh, 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 thử nghiệm trên các nền tảng của Trợ lý Google và ứng dụng Google Home mà bạn đã đă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 như trong bảng điều khiển.
  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 thử nghiệm bằng tiền tố [test] để tìm ứng dụng thử nghiệm cụ thể.
  5. Chọn mục đó. Sau đó, Trợ lý Google sẽ xác thực với dịch vụ của bạn rồi 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 của mình.

ae252220753726f6.png

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

Giờ đây, bạn đã 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ế độ

Trait action.devices.traits.Modes cho phép thiết bị có số lượng chế độ cài đặt tuỳ ý cho một chế độ, trong đó mỗi chế độ chỉ có thể đặt một chế độ cài đặt. Bạn sẽ thêm một chế độ vào máy giặt để xác định kích thước của khối lượng giặt: 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ề trait 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ư minh hoạ 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 câu trả lời QUERY

Tiếp theo, hãy cập nhật phản hồi của 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 như đượ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 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,
          },
        },
      },
    },
  },
};

Triển khai cho Firebase

Chạy lệnh sau để triển khai hành động đã 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 Làm mới ae8d3b25777a5e30.png trên thanh công cụ. Hành động đó sẽ kích hoạt một Yêu cầu đồng bộ hoá để Trợ lý nhận dữ liệu phản hồi SYNC đã cập nhật.

bf4f6a866160a982.png

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

"Ok Google, đặt tải trọng của máy giặt ở mức lớn."

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

"Ok Google, máy giặt đang tải bao nhiêu?"

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

Trait action.devices.traits.Toggles thể hiện các khía cạnh đã đặt tên của một thiết bị có trạng thái true hoặc false, chẳng hạn như máy giặt có đang ở chế độ tăng áp 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ề trait mới của thiết bị. Mã 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 câu trả lời QUERY

Cuối cùng, bạn cần cập nhật phản hồi của QUERY để báo cáo chế độ tăng áp 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 như đượ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 Home Graph xem máy giặt có được đặt ở chế độ tăng áp 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 cho 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 Refresh (Làm mới) ae8d3b25777a5e30.png trong giao diện người dùng web để kích hoạt tính năng 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 ở chế độ tăng áp bằng cách nói:

"Ok Google, bật chế độ tăng tốc cho máy giặt."

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

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

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

Tính năng xử lý lỗi trong Hành động cho nhà thông minh cho phép bạn báo cáo cho người dùng khi các sự cố khiến EXECUTEQUERY không phản hồi được. Các 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 Hành động và thiết bị thông minh của bạn.

Mỗi khi yêu cầu EXECUTE hoặc QUERY không thành công, Hành động của bạn sẽ trả về một mã lỗi. Ví dụ: nếu bạn muốn báo 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 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 đang mở trên máy giặt. Vui lòng đóng lại rồi thử lại."

Ngoại lệ cũng tương tự như các 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 (có thể chặn hoặc không chặn thực thi thành công). Một trường hợp ngoại lệ có thể cung cấp thông tin liên quan bằng cách sử dụng trait StatusReport, chẳng hạn như mức pin hoặc sự 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ề với trạng thái EXCEPTIONS.

Đoạn mã sau đây có một ví dụ về phản hồi có trường hợp 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ý trả lời bằng cách nói:

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

Để thêm báo cáo lỗi cho máy giặt, hãy mở functions/index.js rồi 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( ... )
          //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ể thông báo cho người dùng 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 thứ hai khi xác minh người dùng

Bạn nên triển khai quy trình xác minh người dùng phụ trong Hành động của mình 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ụ thể được uỷ quyền, chẳng hạn như khi cập nhật phần mềm hoặc khoá lại.

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

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

  • No challenge—Một 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—Phương thức xác minh thứ hai của người dùng, yêu cầu xác nhận rõ ràng (có hoặc không)
  • pinNeeded—Phương thức xác minh thứ hai khi xác minh người dùng 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 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 quy trình xác minh phụ không thành công.

Mở functions/index.js và 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( ... )
          .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 thông báo xác nhận rõ ràng để 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 cho 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ã mới cập nhật, bạn phải xác nhận hành động đó bằng lời nói khi yêu cầu Trợ lý bật hoặc tắt máy giặt, chẳng hạn 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.pngs

8. Xin chúc mừng

674c4f4392e98c1.png.

Xin chúc mừng! Bạn đã mở rộng các tính năng của Hành động trong nhà thông minh thông qua các trait ModesToggles, đồng thời bảo vệ quá trình thực thi các hành độ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 để hiểu rõ hơn:

  • Thêm chức năng thực thi cục bộ vào thiết bị của bạn.
  • Hãy 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 của thiết bị.
  • Cập nhật phản hồi QUERY trait RunCycle để cập nhật linh động.
  • Hãy khám phá mẫu GitHub này.