Bật tính năng thực hiện đơn hàng tại địa phương cho Hành động dành cho nhà thông minh

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

Việc tích hợp nhà thông minh cho phép Trợ lý Google điều khiển các thiết bị thông minh trong nhà của người dùng. Để tạo Hành động trong nhà thông minh, bạn cần cung cấp một điểm cuối webhook trên đám mây có khả năng xử lý ý định của nhà thông minh. Ví dụ: khi người dùng nói: "Ok Google, bật đèn", Trợ lý sẽ gửi lệnh đến phương thức thực hiện của bạn trên đám mây để cập nhật trạng thái của thiết bị.

Local Home SDK giúp nâng cao khả năng tích hợp nhà thông minh bằng cách thêm một đường dẫn cục bộ để định tuyến ý định nhà thông minh trực tiếp đến thiết bị Google Home. Việc này giúp tăng cường độ tin cậy và giảm độ trễ khi xử lý lệnh của người dùng. AI của Google cho phép bạn viết và triển khai một ứng dụng thực hiện đơn hàng cục bộ bằng TypeScript hoặc JavaScript giúp nhận dạng thiết bị và thực thi lệnh trên bất kỳ loa thông minh Google Home hoặc màn hình thông minh Google Nest nào. Sau đó, ứng dụng của bạn sẽ giao tiếp trực tiếp với các thiết bị thông minh hiện có của người dùng qua mạng cục bộ bằng cách sử dụng các giao thức tiêu chuẩn hiện có để thực hiện các lệnh.

72ffb320986092c.png.

Đ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 chế độ tích hợp nhà thông minh đã tạo trước đó với Firebase, sau đó áp dụng cấu hình quét trong Bảng điều khiển Actions và tạo một ứng dụng cục bộ bằng TypeScript để gửi các lệnh viết bằng Node.js đến thiết bị máy giặt ảo.

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

  • Cách bật và định cấu hình phương thức thực hiện cục bộ trong bảng điều khiển Actions.
  • Cách sử dụng SDK Local Home để viết ứng dụng thực hiện cục bộ.
  • Cách gỡ lỗi ứng dụng thực hiện đơn hàng cục bộ được tải trên loa Google Home hoặc màn hình thông minh Google Nest.

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.

AWXw5E1m9zVgvVEy

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.

Giao diện người dùng

Chọn thẻ trải nghiệm Nhà thông minh. Sau đó, bạn sẽ được chuyển đến bảng điều khiển dự án.

pzgHPsmc2LvLoeUvJfkjKQqD_BvO4v8JOPlcrxsmyptFkkjL4PP6LqrM9r5tNvEIfT9HmK-UKw3GWFPXTjqo4nUrhD2o5shUKHBE31OT8iIA69JZCev7_0_nh-lnL2oJHoxGfqqZ4w

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.

5SVCzM8IZLi_9DV8M0nEklv16NXkpvM0bIzQK2hSyKyvnFHBxPOz90rbr72ayxzmxd5aNROOqC_Cp4outbdlwJdObDs0DIE_8vYzw6dovoVrP9IZWlWsZxDS7UHOi1jiRbDMG8MqUA

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-local.git

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

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

  • public—Giao diện người dùng web của giao diện người dùng để điều khiển và giám sát máy giặt thông minh
  • functions – Các chức năng trên đám mây triển khai phương thức thực hiện trên đám mây cho Hành động trong nhà thông minh
  • local – Dự án ứng dụng phương thức thực hiện cục bộ Skleton với các trình xử lý ý định được sắp xếp trong index.ts

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 trong nhà thông minh
  • reportstate – Gọi API HomeGraph khi trạng thái thiết bị thay đổi
  • updateDevice – Điểm cuối được thiết bị ảo sử dụng để kích hoạt Trạng thái báo cáo

Kết nối với Firebase

Chuyển đến thư mục app-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 app-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
    

Để đảm bảo rằng bạn có cấu hình Firebase chính xác và hoàn chỉnh, hãy sao chép tệp firebase.json từ thư mục washer-done vào thư mục washer-start, ghi đè tệp trong washer-start.

Trong thư mục washer-start:

cp -vp ../washer-done/firebase.json .

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:

L60eA7MOnPmbBMl2XMipT9MdnP-RaVjyjf0Y93Y1b7mEyIsqZrrwczE7D3RQISRs-iusL1g4XbNmGhuA6-5sLcWefnczwNJEPfNLtwBsO4Tb9YvcAZBI6_rX19z8rxbik9Vq8F2fwg

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

Uso-o00XQXBHvOR9vQq9tmpYDYQJKsFEstsgRFnxPAJf7zJ2FxwhISiodo3dB1Tz49Okd6ivi66fjpo7rarS_GZelglGWCT1r9FzDGUl1r67ddIcIbQrxqN8jG9F9GAKOpk0Ckc-eA

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.

gvC-TvmKDy-D-xjwkeCjNt__9ErA7DL8hZWa1oH1yPJ9SpYOepDYjxx6WnJ56IG-t37fJ65kmHISQdh72Ot2G-0tu6Flxf4gom5kvx_3hlvFeMqYuFgXr_85pfWWn7VLFHtS55p1zw

s4yc1kOW4XtKUQN1EYegiDLU5oTqmxQ2PNbeaujm26OQmYKKpjug7j5FYmutLSAZ1zBd-ZkcZlL7zyTZqw4bge3_oOeWvJTsqJ-A08vfZwImYQrKiquLskLuTpmMqXEZD1xchhCWGQ

Để 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

rRyZTiBSTuPk3YtJtXjDK1pPftUxsaEhs9jzpvFtbHTD6bEwYxM8jV4MWxiljKA1bKVZrIRoO9O3jtBefLKf_OyMpukPjwIj8zGvyU3UwASzMrnRskl-hVAfAmQVi4sC_zAwgYwRXw

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.

OgUvpQfXioygkRwPcaJpzjyNQDZy6enidUC8YMPaCOrZi0YeWCFsCJV9Gqg-_UfsqTnn4KEg--uE3Ymr0QuamDonF4RyYHtRKcULXABDuaEnj2hq8i20LYj1SrGP_1lQ_UsUB90pGw

Bạn sẽ được chuyển hướng đến Trình mô phỏng. Xác minh rằng tính năng kiểm thử đã được bật cho dự án của bạn bằng cách di chuột qua biểu tượng Kiểm thử trên thiết bị ( soCeBB1CkSIEqsBmDc8Cth6EjgcXUnrOHeOpLNlvMiiXM73Rmh8iBK1ZFLFd47kycYqIMq3Fm49ryAGUt79BXVPDyEB1IU3W0fgiT49iqX).

2zbfeYpG-wEd2SFP07Wc4mJzHakLX7YvrNw3IV0_0Kd-TonfsKIvvjKWlwvrmTm5jLj3XPWqCtcDd5J2z6gwn9fnchpYVraw1j_mE4M0LVppAl5WY5cK7g0uZyhZ3VFFS25yPmyksg

Để 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.

XcWmBVamBZtPfOFqtsr5I38stPWTqDcMfQwbBjetBgxt0FCjEs285pa9K3QXSASptw0KYN2G8yfkT0-xg664V4PjqMreDDs-HPegHjOc4EVtReYPu-WKZyygq9Xmkf8X8z9177nBjQ

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 trạng thái thiết bị thay đổi trong giao diện người dùng web của giao diện người dùng của phương thức thực hiện trên đám mây.

Bây giờ, bạn có thể bắt đầu thêm phương thức thực hiện cục bộ vào Hành động của mình.

4. Cập nhật phương thức thực hiện trên đám mây

Để hỗ trợ phương thức thực hiện cục bộ, bạn cần thêm một trường mới cho mỗi thiết bị có tên là otherDeviceIds vào phản hồi SYNC trên đám mây chứa giá trị nhận dạng cục bộ duy nhất của thiết bị. Trường này cũng cho biết khả năng điều khiển cục bộ thiết bị đó.

Thêm trường otherDeviceIds vào phản hồi SYNC như trong đoạn mã sau:

functions/index.js

app.onSync((body) => {
  return {
    requestId: body.requestId,
    payload: {
      agentUserId: '123',
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [ ... ],
        name: { ... },
        deviceInfo: { ... },
        willReportState: true,
        attributes: {
          pausable: true,
        },
        otherDeviceIds: [{
          deviceId: 'deviceid123',
        }],
      }],
    },
  };
});

Triển khai dự án đã cập nhật cho Firebase:

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ụ. Thao tác này sẽ kích hoạt thao tác 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

5. Định cấu hình phương thức thực hiện cục bộ

Trong phần này, bạn sẽ thêm các tuỳ chọn cấu hình cần thiết để thực hiện cục bộ cho Hành động trong nhà thông minh. Trong quá trình phát triển, bạn sẽ xuất bản ứng dụng thực hiện cục bộ lên Lưu trữ Firebase. Tại đây, thiết bị Google Home có thể truy cập và tải ứng dụng xuống.

Trong Bảng điều khiển Actions, hãy chọn Phát triển > Hành động rồi tìm phần Định cấu hình SDK cục bộ cho nhà riêng. Nhập URL sau vào trường URL kiểm thử, chèn mã dự án của bạn, rồi nhấp vào Lưu:

https://<project-id>.web.app/local-home/index.html

7d59b31f8d2a988.pngs

Tiếp theo, chúng ta cần xác định cách thiết bị Google Home sẽ khám phá các thiết bị thông minh cục bộ. Nền tảng Local Home hỗ trợ một số giao thức để khám phá thiết bị, bao gồm cả mDNS, UPnP và truyền phát UDP. Bạn sẽ dùng tính năng truyền phát UDP để khám phá máy giặt thông minh.

Nhấp vào Cấu hình quét mới trong phần Cấu hình quét thiết bị để thêm cấu hình quét mới. Chọn UDP làm giao thức rồi điền vào các thuộc tính sau:

Trường

Mô tả

Giá trị đề xuất

Địa chỉ phát sóng

Địa chỉ truyền phát UDP

255.255.255.255

Cổng phát sóng

Cổng nơi Google Home gửi thông báo UDP

3311

Cổng nghe

Cổng nơi Google Home lắng nghe phản hồi

3312

Gói Khám phá

Tải trọng dữ liệu truyền tin UDP

48656c6c6f4c6f63616c486f6d6553444b

4777bf63c53b6858.pngs

Cuối cùng, hãy nhấp vào Lưu ở đầu cửa sổ để xuất bản các thay đổi.

6. Triển khai phương thức thực hiện cục bộ

Bạn sẽ phát triển ứng dụng thực hiện đơn hàng cục bộ trong TypeScript bằng cách sử dụng gói nhập SDK Local Home. Hãy xem khung xương được cung cấp trong dự án khởi đầu:

local/index.ts

/// <reference types="@google/local-home-sdk" />

import App = smarthome.App;
import Constants = smarthome.Constants;
import DataFlow = smarthome.DataFlow;
import Execute = smarthome.Execute;
import Intents = smarthome.Intents;
import IntentFlow = smarthome.IntentFlow;

...

class LocalExecutionApp {

  constructor(private readonly app: App) { }

  identifyHandler(request: IntentFlow.IdentifyRequest):
      Promise<IntentFlow.IdentifyResponse> {
    // TODO: Implement device identification
  }

  executeHandler(request: IntentFlow.ExecuteRequest):
      Promise<IntentFlow.ExecuteResponse> {
    // TODO: Implement local fulfillment
  }

  ...
}

const localHomeSdk = new App('1.0.0');
const localApp = new LocalExecutionApp(localHomeSdk);
localHomeSdk
  .onIdentify(localApp.identifyHandler.bind(localApp))
  .onExecute(localApp.executeHandler.bind(localApp))
  .listen()
  .then(() => console.log('Ready'))
  .catch((e: Error) => console.error(e));

Thành phần cốt lõi của phương thức thực hiện cục bộ là lớp smarthome.App. Dự án khởi đầu sẽ đính kèm các trình xử lý cho ý định IDENTIFYEXECUTE, sau đó gọi phương thức listen() để thông báo cho SDK Local Home biết rằng ứng dụng đã sẵn sàng.

Thêm trình xử lý IDENTIFY

Local Home SDK kích hoạt trình xử lý IDENTIFY khi thiết bị Google Home phát hiện thấy các thiết bị chưa được xác minh trên mạng cục bộ dựa trên cấu hình quét được cung cấp trong bảng điều khiển Actions.

Trong khi đó, nền tảng sẽ gọi identifyHandler cùng với dữ liệu quét kết quả khi Google phát hiện thấy một thiết bị trùng khớp. Trong ứng dụng của bạn, quá trình quét diễn ra bằng cách sử dụng thông báo truyền tin UDP và dữ liệu quét được cung cấp cho trình xử lý IDENTIFY bao gồm tải trọng phản hồi do thiết bị cục bộ gửi.

Trình xử lý trả về một thực thể IdentifyResponse chứa giá trị nhận dạng duy nhất cho thiết bị cục bộ. Thêm mã sau vào phương thức identifyHandler để xử lý phản hồi UDP từ thiết bị cục bộ và xác định mã thiết bị cục bộ phù hợp:

local/index .ts

identifyHandler(request: IntentFlow.IdentifyRequest):
    Promise<IntentFlow.IdentifyResponse> {
  console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));

  const scanData = request.inputs[0].payload.device.udpScanData;
  if (!scanData) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_request', 'Invalid scan data');
    return Promise.reject(err);
  }

  // In this codelab, the scan data contains only local device id.
  const localDeviceId = Buffer.from(scanData.data, 'hex');

  const response: IntentFlow.IdentifyResponse = {
    intent: Intents.IDENTIFY,
    requestId: request.requestId,
    payload: {
      device: {
        id: 'washer',
        verificationId: localDeviceId.toString(),
      }
    }
  };
  console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));

  return Promise.resolve(response);
}

Lưu ý trường verificationId phải khớp với một trong các giá trị otherDeviceIds trong phản hồi SYNC. Giá trị này sẽ gắn cờ thiết bị để thực hiện nhiệm vụ cục bộ trong Home Graph của người dùng. Sau khi Google tìm thấy thiết bị trùng khớp, thiết bị đó sẽ được coi là đã xác minh và sẵn sàng cho việc thực hiện đơn hàng cục bộ.

Thêm trình xử lý EXECUTE

SDK Home cục bộ kích hoạt trình xử lý EXECUTE khi thiết bị hỗ trợ phương thức thực hiện cục bộ nhận được lệnh. Nội dung của ý định cục bộ tương đương với ý định EXECUTE được gửi đến phương thức thực hiện trên đám mây của bạn. Vì vậy, logic để xử lý ý định cục bộ sẽ giống với cách bạn xử lý ý định trên đám mây.

Ứng dụng có thể sử dụng cổng TCP/UDP hoặc yêu cầu HTTP(S) để giao tiếp với thiết bị cục bộ. Trong lớp học lập trình này, HTTP đóng vai trò là giao thức dùng để điều khiển thiết bị ảo. Số cổng được xác định trong index.ts dưới dạng biến SERVER_PORT.

Thêm mã sau vào phương thức executeHandler để xử lý các lệnh đến và gửi chúng đến thiết bị cục bộ qua HTTP:

local/index.ts

executeHandler(request: IntentFlow.ExecuteRequest):
    Promise<IntentFlow.ExecuteResponse> {
  console.log("EXECUTE intent: " + JSON.stringify(request, null, 2));

  const command = request.inputs[0].payload.commands[0];
  const execution = command.execution[0];
  const response = new Execute.Response.Builder()
    .setRequestId(request.requestId);

  const promises: Array<Promise<void>> = command.devices.map((device) => {
    console.log("Handling EXECUTE intent for device: " + JSON.stringify(device));

    // Convert execution params to a string for the local device
    const params = execution.params as IWasherParams;
    const payload = this.getDataForCommand(execution.command, params);

    // Create a command to send over the local network
    const radioCommand = new DataFlow.HttpRequestData();
    radioCommand.requestId = request.requestId;
    radioCommand.deviceId = device.id;
    radioCommand.data = JSON.stringify(payload);
    radioCommand.dataType = 'application/json';
    radioCommand.port = SERVER_PORT;
    radioCommand.method = Constants.HttpOperation.POST;
    radioCommand.isSecure = false;

    console.log("Sending request to the smart home device:", payload);

    return this.app.getDeviceManager()
      .send(radioCommand)
      .then(() => {
        const state = {online: true};
        response.setSuccessState(device.id, Object.assign(state, params));
        console.log(`Command successfully sent to ${device.id}`);
      })
      .catch((e: IntentFlow.HandlerError) => {
        e.errorCode = e.errorCode || 'invalid_request';
        response.setErrorState(device.id, e.errorCode);
        console.error('An error occurred sending the command', e.errorCode);
      });
  });

  return Promise.all(promises)
    .then(() => {
      return response.build();
    })
    .catch((e) => {
      const err = new IntentFlow.HandlerError(request.requestId,
          'invalid_request', e.message);
      return Promise.reject(err);
    });
}

Biên dịch ứng dụng TypeScript

Chuyển đến thư mục local/ rồi chạy các lệnh sau để tải trình biên dịch TypeScript xuống và biên dịch ứng dụng:

cd local
npm install
npm run build

Thao tác này sẽ biên dịch nguồn index.ts (TypeScript) và đặt các nội dung sau vào thư mục public/local-home/:

  • bundle.js – Đầu ra JavaScript được biên dịch có chứa ứng dụng cục bộ và các phần phụ thuộc.
  • index.html—Trang lưu trữ cục bộ được dùng để phân phát ứng dụng cho việc kiểm thử trên thiết bị.

Triển khai dự án thử nghiệm

Triển khai các tệp dự án đã cập nhật cho Lưu trữ Firebase để bạn có thể truy cập các tệp đó từ thiết bị Google Home.

firebase deploy --only hosting

7. Khởi động máy giặt thông minh

Bây giờ, đã đến lúc kiểm thử hoạt động giao tiếp giữa ứng dụng thực hiện đơn hàng cục bộ và máy giặt thông minh! Dự án khởi đầu của lớp học lập trình này bao gồm một máy giặt thông minh v được viết bằng Node.js. Công cụ này mô phỏng một máy giặt thông minh mà người dùng có thể điều khiển cục bộ.

Định cấu hình thiết bị

Trong bảng điều khiển Actions, bạn cần định cấu hình thiết bị ảo để sử dụng chính các tham số UDP mà bạn đã áp dụng cho cấu hình quét nhằm khám phá thiết bị. Ngoài ra, bạn cần cho thiết bị ảo biết mã thiết bị cục bộ nào cần báo cáo và mã dự án Hành động cần sử dụng cho các sự kiện Trạng thái báo cáo khi trạng thái thiết bị thay đổi.

Tham số

Giá trị đề xuất

deviceId

deviceid123

discoveryPortOut

3311

discoveryPacket

HelloLocalHomeSDK

projectId

Mã dự án Actions của bạn

Khởi động thiết bị

Chuyển đến thư mục virtual-device/ rồi chạy tập lệnh thiết bị, chuyển các tham số cấu hình dưới dạng đối số:

cd virtual-device
npm install
npm start -- \
  --deviceId=deviceid123 --projectId=<project-id> \
  --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK

Xác minh rằng tập lệnh thiết bị chạy với các tham số dự kiến:

(...): UDP Server listening on 3311
(...): Device listening on port 3388
(...): Report State successful

8. Gỡ lỗi ứng dụng TypeScript

Trong phần sau, bạn sẽ xác minh rằng thiết bị Google Home có thể quét, xác định và gửi đúng lệnh đến máy giặt thông minh ảo qua mạng cục bộ. Bạn có thể sử dụng Công cụ dành cho nhà phát triển Google Chrome để kết nối với thiết bị Google Home, xem nhật ký bảng điều khiển và gỡ lỗi ứng dụng TypeScript.

Kết nối Công cụ cho nhà phát triển Chrome

Để kết nối trình gỡ lỗi với ứng dụng thực hiện đơn hàng cục bộ, hãy làm theo các bước sau:

  1. Đảm bảo rằng bạn đã liên kết thiết bị Google Home với người dùng có quyền truy cập vào dự án Actions Console.
  2. Khởi động lại thiết bị Google Home của bạn. Thao tác này sẽ cho phép thiết bị lấy URL của HTML cũng như cấu hình quét mà bạn đặt trong bảng điều khiển Actions.
  3. Chạy Chrome trên máy phát triển của bạn.
  4. Mở một thẻ Chrome mới rồi nhập chrome://inspect vào trường địa chỉ để khởi chạy trình kiểm tra.

Bạn sẽ thấy danh sách thiết bị trên trang và URL ứng dụng của bạn sẽ xuất hiện bên dưới tên của thiết bị Google Home.

567f97789a7d8846.pngs

Khởi động trình kiểm tra

Nhấp vào Kiểm tra trong URL ứng dụng của bạn để chạy Công cụ cho nhà phát triển Chrome. Chọn thẻ Console (Bảng điều khiển) rồi xác minh rằng bạn có thể xem được nội dung của ý định IDENTIFY mà ứng dụng TypeScript in.

6b67ded470a4c8be.png.

Kết quả này có nghĩa là ứng dụng thực hiện cục bộ đã phát hiện và xác định thành công thiết bị ảo.

Kiểm thử phương thức thực hiện cục bộ

Gửi lệnh đến thiết bị của bạn bằng các nút điều khiển cảm ứng trong ứng dụng Google Home hoặc thông qua lệnh thoại đến thiết bị Google Home, chẳng hạn như:

"Ok Google, bật máy giặt của tôi."

"Ok Google, khởi động máy giặt của tôi."

"Ok Google, dừng máy giặt."

Thao tác này sẽ kích hoạt nền tảng để gửi ý định EXECUTE đến ứng dụng TypeScript.

bc030517dacc3ac9.png

Xác minh rằng bạn có thể thấy sự thay đổi trạng thái của máy giặt thông minh cục bộ theo từng lệnh.

...
***** The washer is RUNNING *****
...
***** The washer is STOPPED *****

9. Xin chúc mừng

764dbc83b95782a.pngs

Xin chúc mừng! Bạn đã sử dụng Local Home SDK để tích hợp phương thức thực hiện cục bộ vào Hành động dành cho nhà thông minh.

Tìm hiểu thêm

Dưới đây là một số thao tác khác mà bạn có thể thử:

  • Thay đổi cấu hình quét để chế độ quét hoạt động. Ví dụ: thử sử dụng cổng UDP hoặc gói khám phá khác.
  • Sửa đổi cơ sở mã thiết bị thông minh ảo để chạy trên một thiết bị được nhúng (chẳng hạn như Rassberry Pi) và sử dụng đèn LED hoặc màn hình để trực quan hoá trạng thái hiện tại.