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

Các công cụ tích hợp nhà thông minh cho phép Trợ lý Google kiểm soát các thiết bị thông minh trên trang web của người dùng nhà. Để tạo một 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 nhà thông minh. Ví dụ: khi người dùng nói "Ok Google, bật đèn lên" Trợ lý 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 tăng cường khả năng tích hợp nhà thông minh bằng cách thêm đường dẫn cục bộ để định tuyến ý định nhà thông minh trực tiếp đến một thiết bị Google Home. Việc này giúp nâng cao độ tin cậy và giảm độ trễ khi xử lý dữ liệu của người dùng các lệnh. Công cụ này cho phép bạn viết và triển khai một ứng dụng thực hiện cục bộ trong TypeScript hoặc JavaScript giúp xác định các thiết bị và thực thi các lệnh trên mọi loa thông minh Google Home hoặc màn hình thông minh Google Nest. Sau đó, ứng dụng của bạn sẽ giao tiếp trực tiếp với người dùng các thiết bị thông minh hiện có qua mạng cục bộ bằng cách sử dụng các giao thức 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 đây 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 được viết bằng Node.js đến 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 Local Home SDK để viết một ứng dụng thực hiện cục bộ.
  • Cách gỡ lỗi ứng dụng thực hiện cục bộ đã 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 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 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ỉ áp dụ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ó tài khoản. 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 của bạn.

Mở trang Kiểm soát hoạt động cho 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 bật/tắt sau đang bật:

  • Web và Hoạt động ứ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ị
  • Giọng nói và Hoạt động âm thanh

Tạo một 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.

m

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.

36RsBUWBgb

Chọn thẻ trải nghiệm Nhà thông minh, sau đó bạn sẽ được chuyển hướng đế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 (CLI) của Firebase sẽ cho phép bạn phân phát các ứng dụng web của mình cục bộ và triển khai ứng dụng web đến dịch vụ lưu trữ Firebase.

Để cài đặt CLI, hãy chạy lệnh npm sau đây trên 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 mã:

firebase --version

Uỷ quyền giao diện dòng lệnh (CLI) của Firebase bằng Tài khoản Google của bạn bằng cách chạy:

firebase login

Bật API HomeGraph

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 phù hợp với Actions <project-id>. của bạn. Sau đó, trên màn hình Thư viện API cho HomeGraph API, nhấp vào Enable (Bật).

5SVCzM8IZLi_9DV8M0nEklv16NXkpvM0bIzQK2hSyKyvnFHBxPOz90rbr72ayxzmxd5aNROOqC_Cp4outbdlwJdObDs0DIE_8vYzw6dovoVrP9IZWlWsZxDS7UHOi1jiRbDMG8MqUA

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

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 đầ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 xuống cho lớp học lập trình này trên 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 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 của Cloud triển khai phương thức thực hiện trên đám mây cho Hành động nhà thông minh
  • local – Dự án ứng dụng thực hiện cục bộ Carbon với các trình xử lý ý định đã bị loại bỏ trong index.ts

Phương thức thực hiện trên đám mây được cung cấp bao gồm các chức năng 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 của nhà thông minh
  • reportstate – Gọi API HomeGraph khi trạng thái thiết bị thay đổi
  • updateDevice – Điểm cuối mà thiết bị ảo 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 Actions:

cd app-start
firebase use <project-id>

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

Khởi chạy một 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 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 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 rằng 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 động lại dự án, hãy chọn Ghi đè khi được hỏi 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 động lại dự án, hãy chọn No (Không) khi được hỏi bạn có muốn khởi chạy 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, có hai phương pháp có sẵn để tắt:

  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 tên 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ó một 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 đè lên tệp đó trong washer-start.

Trong thư mục washer-start:

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

Triển khai cho Firebase

Sau 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ả 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ố Cloud Functions for Firebase (Chức năng đám mây dành 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 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 của bạn, 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.

Giờ đã đến lúc kết nối dịch vụ đám mây 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 Bảng điều khiển Actions

Trong Tổng quan > Xây dựng hành động của bạn, chọn Add Action(s) (Thêm hành động). Nhập URL của hàm trên đám mây cung cấp phương thức thực hiện cho các ý định trong 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 trang Phát triển > Thẻ Lời gọi, thêm Tên hiển thị cho Hành động của bạn rồi nhấp vào 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 phần Phát triển > Liên kết tài khoản trong bảng điều hướng bên trái. Hãy 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 Lưu để lưu cấu hình liên kết tài khoản, sau đó nhấp vào Thử nghiệm để bật tính năng thử nghiệm 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ị ( soCeBB1CkSIEqsBmDc8Cth6EjgcXUnrOHeOpLNlvMiiXM73Rmh8iBK1ZFLFd47kycYqIMq3Fm49ryAGUt79BXVPDyEB1IU3W0fgiL49iqwszTAVR).

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. Điều này cho phép kiểm tra thông qua các nền tảng của 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 cần đăng nhập bằng chính tài khoản như trong bảng điều khiển.
  2. Chuyển đến Trợ lý Google > Cài đặt > Điều khiển nhà (trong 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 kiếm ứng dụng kiểm thử của bạn 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 với dịch vụ của bạn và gửi một yêu cầu SYNC, đề nghị 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 nhận rằng bạn có thể nhìn 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 sự thay đổi về 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.

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 cho 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ư minh hoạ 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 lên 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 Refresh (Làm mới) ae8d3b25777a5e30.png trên thanh công cụ. Thao tác này sẽ kích hoạt hoạt động Yêu cầu đồng bộ hoá để Trợ lý nhận dữ liệu phản hồi mới nhất của SYNC.

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 lựa chọn cấu hình cần thiết cho phương thức thực hiện cục bộ vào Hành động nhà thông minh của bạn. 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 dịch vụ Lưu trữ Firebase, nơi 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 > Thao tác rồi tìm phần Định cấu hình SDK cục bộ trên trang chủ. Nhập URL sau vào trường URL kiểm tra, 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 trong thiết bị. Nền tảng Local Home hỗ trợ một số giao thức để phát hiện thiết bị, trong đó có việc truyền tin mDNS, UPnP và UDP. Bạn sẽ dùng tính năng truyền tin 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 và điền các thuộc tính sau:

Trường

Nội dung mô tả

Giá trị đề xuất

Địa chỉ phát sóng

Địa chỉ truyền tin 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 cục bộ của mình trong TypeScript bằng cách sử dụng gói nhập Local Home SDK. 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 Local Home SDK biết rằng ứng dụng đã sẵn sàng.

Thêm trình xử lý IDENTIFY

Local Home SDK sẽ 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 trong 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 kèm theo dữ liệu quét kết quả khi Google phát hiện thấy một thiết bị phù hợ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ý sẽ trả về một thực thể IdentifyResponse chứa giá trị nhận dạng duy nhất của 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ộ thích 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 ý rằng trường verificationId phải khớp với một trong các giá trị otherDeviceIds trong phản hồi SYNC. Phản hồi này gắn cờ thiết bị là có thể thực hiện cục bộ trong Biểu đồ trang chủ của người dùng. Sau khi Google tìm thấy kết quả 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 tại địa phương.

Thêm trình xử lý EXECUTE

SDK Local Home sẽ kích hoạt trình xử lý EXECUTE khi một thiết bị hỗ trợ phương thức thực hiện cục bộ nhận được một 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, vì vậy, logic để xử lý ý định cục bộ cũng giống như cách bạn xử lý ý định trên đám mây.

Ứng dụng có thể dùng cổng TCP/UDP hoặc yêu cầu HTTP(S) để giao tiếp với các 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 định nghĩa trong index.ts là 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 các lệnh đó đế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/ và 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 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ộ dùng để phân phát ứng dụng cho mục đích thử nghiệm 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 lên tính năng Lưu trữ Firebase để bạn có thể truy cập vào 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

Giờ là lúc kiểm thử khả nă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 có một máy giặt thông minh v (được viết bằng Node.js) 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ị

Bạn cần định cấu hình thiết bị ảo để sử dụng chính tham số UDP mà bạn đã áp dụng cho cấu hình quét để khám phá thiết bị trong bảng điều khiển Actions. Ngoài ra, bạn cần cho thiết bị ảo biết mã thiết bị cục bộ cần báo cáo và mã dự án Hành động để 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.

Thông số

Giá trị đề xuất

Mã thiết bị

deviceid123

discoveryPortOut

3311

discoveryPacket

HelloLocalHomeSDK

projectId

Mã dự án Hành động của bạn

Khởi động thiết bị

Chuyển đến thư mục virtual-device/ và chạy tập lệnh thiết bị, truyề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 lệnh đến máy giặt thông minh ảo đúng cách 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ụ dành 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 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 một 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 để thiết bị nhận được 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 sẽ xuất hiện bên dưới tên của thiết bị Google Home.

567f97789a7d8846.pngS

Khởi chạy trình kiểm tra

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

6b67ded470a4c8be.png.

Kết quả này có nghĩa là ứng dụng thực hiện đơn hàng cục bộ của bạn đã 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 tới thiết bị Google Home thông qua lệnh thoại, chẳng hạn như:

"Ok Google, bật máy giặt cho tôi."

"Ok Google, bắt đầu máy giặt."

"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 trạng thái của máy giặt thông minh cục bộ thay đổi theo mỗi 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 một Hành động nhà thông minh.

Tìm hiểu thêm

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

  • Thay đổi cấu hình quét và làm cho nó hoạt động. Ví dụ: hãy thử dùng một cổng UDP hoặc gói khám phá khác.
  • Sửa đổi cơ sở mã của thiết bị thông minh ảo để chạy trên một thiết bị được nhúng (chẳng hạn như Raspberry 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.