Để hỗ trợ việc thực hiện tại địa phương, bạn cần tạo một ứng dụng để xử lý các ý định nhà thông minh sau:
IDENTIFY
: Hỗ trợ việc phát hiện các thiết bị thông minh có thể điều khiển tại chỗ. Trình xử lý ý định trích xuất dữ liệu mà thiết bị thông minh của bạn trả về trong quá trình khám phá và gửi dữ liệu này trong một phản hồi cho Google.EXECUTE
: Hỗ trợ thực thi các lệnh.QUERY
: Hỗ trợ truy vấn trạng thái thiết bị.REACHABLE_DEVICES
: (Không bắt buộc) Hỗ trợ việc tìm thấy các thiết bị đầu cuối có thể điều khiển tại chỗ nằm sau một thiết bị trung tâm (hoặc cầu nối).
Ứng dụng này chạy trên các thiết bị Google Home hoặc Google Nest của người dùng và kết nối thiết bị thông minh của bạn với Trợ lý. Bạn có thể tạo ứng dụng bằng TypeScript (nên dùng) hoặc JavaScript.
Bạn nên dùng TypeScript vì có thể tận dụng các liên kết để đảm bảo một cách tĩnh rằng dữ liệu mà ứng dụng của bạn trả về khớp với các loại mà nền tảng mong đợi.
Để biết thêm thông tin về API này, hãy xem Tài liệu tham khảo về Local Home SDK API.
Các đoạn mã sau đây cho thấy cách bạn có thể khởi tạo ứng dụng thực hiện đơn hàng tại địa phương và đính kèm các trình xử lý.
import App = smarthome.App; const localHomeApp: App = new App("1.0.0"); localHomeApp .onIdentify(identifyHandler) .onExecute(executeHandler) .listen() .then(() => { console.log("Ready"); });
import App = smarthome.App; const localHomeApp: App = new App("1.0.0"); localHomeApp .onIdentify(identifyHandler) .onReachableDevices(reachableDevicesHandler) .onExecute(executeHandler) .listen() .then(() => { console.log("Ready"); });
Tạo dự án
Để triển khai ứng dụng thực hiện đơn hàng tại địa phương, bạn cần tạo một gói JavaScript cho mã và tất cả các phần phụ thuộc của mã.
Sử dụng trình khởi tạo dự án của ứng dụng thực hiện đơn hàng tại địa phương để khởi động cấu trúc dự án phù hợp bằng cấu hình trình đóng gói mà bạn muốn.
Mẫu dự án
Để chọn cấu hình trình đóng gói, hãy chạy lệnh npm init
như trong các ví dụ sau:
TypeScript không có cấu hình trình kết hợp:
npm init @google/local-home-app project-directory/ --bundler none
Cấu trúc dự án:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Thay thế project-directory bằng một thư mục mới sẽ chứa dự án ứng dụng hoàn tất đơn hàng tại địa phương.
TypeScript có cấu hình trình đóng gói webpack:
npm init @google/local-home-app project-directory/ --bundler webpack
Cấu trúc dự án:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── webpack.config.web.js ├── webpack.config.node.js └── serve.js
Thay thế project-directory bằng một thư mục mới sẽ chứa dự án ứng dụng hoàn tất đơn hàng tại địa phương.
TypeScript có cấu hình trình kết hợp Rollup:
npm init @google/local-home-app project-directory/ --bundler rollup
Cấu trúc dự án:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── rollup.config.js └── serve.js
Thay thế project-directory bằng một thư mục mới sẽ chứa dự án ứng dụng hoàn tất đơn hàng tại địa phương.
TypeScript có cấu hình trình đóng gói Parcel:
npm init @google/local-home-app project-directory/ --bundler parcel
Cấu trúc dự án:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
Thay thế project-directory bằng một thư mục mới sẽ chứa dự án ứng dụng hoàn tất đơn hàng tại địa phương.
Thực hiện các thao tác phổ biến ở cấp dự án
Dự án được tạo hỗ trợ các tập lệnh npm sau đây:
cd project-directory/ npm run build
Tập lệnh này biên dịch nguồn TypeScript và gói ứng dụng của bạn cùng với các phần phụ thuộc cho môi trường thời gian chạy Chrome trong thư mục con dist/web
và môi trường thời gian chạy Node.js trong thư mục con dist/node
.
cd project-directory/ npm run lint npm run compile npm test
Tập lệnh này xác minh cú pháp của mã TypeScript, biên dịch mã đó mà không tạo ra bất kỳ đầu ra nào trong thư mục con dist/
và chạy các kiểm thử tự động từ test.ts
.
cd project-directory/ npm run start
Trong quá trình phát triển, tập lệnh này sẽ phân phát các gói ứng dụng cho môi trường thời gian chạy Chrome và Node.js cục bộ.
Triển khai trình xử lý IDENTIFY
Trình xử lý IDENTIFY
sẽ được kích hoạt khi thiết bị Google Home hoặc Google Nest khởi động lại và phát hiện thấy các thiết bị cục bộ chưa được xác minh (bao gồm cả các thiết bị đầu cuối được kết nối với một trung tâm). Nền tảng Local Home sẽ quét các thiết bị tại nhà bằng thông tin cấu hình quét mà bạn đã chỉ định trước đó và gọi trình xử lý IDENTIFY
của bạn bằng kết quả quét.
IdentifyRequest
từ nền tảng Local Home chứa dữ liệu quét của một thực thể LocalIdentifiedDevice
. Chỉ một phiên bản device
được điền sẵn, dựa trên cấu hình quét đã phát hiện thiết bị.
Nếu kết quả quét khớp với thiết bị của bạn, trình xử lý IDENTIFY
sẽ trả về một đối tượng IdentifyResponsePayload
, bao gồm một đối tượng device
có siêu dữ liệu nhà thông minh (chẳng hạn như các loại, đặc điểm và trạng thái báo cáo).
Google thiết lập mối liên kết thiết bị nếu verificationId
trong phản hồi IDENTIFY
khớp với một trong các giá trị otherDeviceIds
do phản hồi SYNC
trả về.
Ví dụ:
Các đoạn mã sau đây cho biết cách bạn có thể tạo trình xử lý IDENTIFY
cho các chế độ tích hợp thiết bị độc lập và trung tâm tương ứng.
const identifyHandler = (request: IntentFlow.IdentifyRequest): IntentFlow.IdentifyResponse => { // Obtain scan data from protocol defined in your scan config const device = request.inputs[0].payload.device; if (device.udpScanData === undefined) { throw Error("Missing discovery response"); } const scanData = device.udpScanData.data; // Decode scan data to obtain metadata about local device const verificationId = "local-device-id"; // Return a response const response: IntentFlow.IdentifyResponse = { intent: Intents.IDENTIFY, requestId: request.requestId, payload: { device: { id: device.id || "", verificationId, // Must match otherDeviceIds in SYNC response }, }, }; return response; };
const identifyHandler = (request: IntentFlow.IdentifyRequest): IntentFlow.IdentifyResponse => { // Obtain scan data from protocol defined in your scan config const device = request.inputs[0].payload.device; if (device.udpScanData === undefined) { throw Error("Missing discovery response"); } const scanData = device.udpScanData.data; // Decode scan data to obtain metadata about local device const proxyDeviceId = "local-hub-id"; // Return a response const response: IntentFlow.IdentifyResponse = { intent: Intents.IDENTIFY, requestId: request.requestId, payload: { device: { id: proxyDeviceId, isProxy: true, // Device can control other local devices isLocalOnly: true, // Device not present in `SYNC` response }, }, }; return response; };
Xác định các thiết bị phía sau một trung tâm
Nếu Google xác định được một thiết bị trung tâm, thì Google sẽ coi thiết bị trung tâm đó là ống dẫn đến các thiết bị cuối được kết nối với thiết bị trung tâm và cố gắng xác minh các thiết bị cuối đó.
Để cho phép Google xác nhận rằng có một thiết bị trung tâm, hãy làm theo các hướng dẫn sau cho trình xử lý IDENTIFY
của bạn:
- Nếu phản hồi
SYNC
của bạn báo cáo mã nhận dạng của các thiết bị đầu cuối cục bộ được kết nối với trung tâm, hãy đặtisProxy
thànhtrue
trongIdentifyResponsePayload
. - Nếu phản hồi
SYNC
không báo cáo thiết bị trung tâm của bạn, hãy đặtisLocalOnly
thànhtrue
trongIdentifyResponsePayload
. - Trường
device.id
chứa mã nhận dạng thiết bị cục bộ cho chính thiết bị trung tâm.
Triển khai trình xử lý REACHABLE_DEVICES (chỉ tích hợp với trung tâm)
Google gửi ý định REACHABLE_DEVICES
để xác nhận những thiết bị đầu cuối nào có thể được kiểm soát cục bộ. Ý định này được kích hoạt mỗi khi Google chạy một quy trình quét phát hiện (khoảng một lần mỗi phút), miễn là phát hiện thấy trung tâm đang trực tuyến.
Bạn triển khai trình xử lý REACHABLE_DEVICES
tương tự như trình xử lý IDENTIFY
, ngoại trừ việc trình xử lý của bạn cần thu thập thêm các mã nhận dạng thiết bị mà thiết bị proxy cục bộ (tức là trung tâm) có thể truy cập. Trường device.verificationId
chứa mã nhận dạng thiết bị cục bộ cho một thiết bị đầu cuối được kết nối với trung tâm.
ReachableDevicesRequest
của nền tảng Local Home chứa một phiên bản của LocalIdentifiedDevice
.
Thông qua phiên bản này, bạn có thể lấy mã nhận dạng thiết bị proxy cũng như dữ liệu từ kết quả quét.
Trình xử lý REACHABLE_DEVICES
của bạn phải trả về một đối tượng ReachableDevicesPayload
bao gồm một đối tượng devices
chứa một mảng các giá trị verificationId
đại diện cho các thiết bị đầu cuối mà trung tâm điều khiển. Các giá trị verificationId
phải khớp với một trong các otherDeviceIds
trong phản hồi SYNC
.
Đoạn mã sau đây cho biết cách bạn có thể tạo trình xử lý REACHABLE_DEVICES
.
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest): IntentFlow.ReachableDevicesResponse => { // Reference to the local proxy device const proxyDeviceId = request.inputs[0].payload.device.id; // Gather additional device ids reachable by local proxy device // ... const reachableDevices = [ // Each verificationId must match one of the otherDeviceIds // in the SYNC response { verificationId: "local-device-id-1" }, { verificationId: "local-device-id-2" }, ]; // Return a response const response: IntentFlow.ReachableDevicesResponse = { intent: Intents.REACHABLE_DEVICES, requestId: request.requestId, payload: { devices: reachableDevices, }, }; return response; };
Triển khai trình xử lý EXECUTE
Trình xử lý EXECUTE
trong ứng dụng sẽ xử lý các lệnh của người dùng và sử dụng Local Home SDK để truy cập vào các thiết bị thông minh thông qua một giao thức hiện có.
Nền tảng Local Home truyền cùng một tải trọng đầu vào đến hàm trình xử lý EXECUTE
như đối với ý định EXECUTE
đến dịch vụ thực hiện trên đám mây. Tương tự, trình xử lý EXECUTE
sẽ trả về dữ liệu đầu ra ở cùng định dạng như khi xử lý ý định EXECUTE
.
Để đơn giản hoá quá trình tạo phản hồi, bạn có thể sử dụng lớp Execute.Response.Builder
mà Local Home SDK cung cấp.
Ứng dụng của bạn không có quyền truy cập trực tiếp vào địa chỉ IP của thiết bị. Thay vào đó, hãy dùng giao diện CommandRequest
để tạo các lệnh dựa trên một trong các giao thức sau: UDP, TCP hoặc HTTP. Sau đó, hãy gọi hàm deviceManager.send()
để gửi các lệnh.
Khi nhắm đến các lệnh cho thiết bị, hãy sử dụng mã nhận dạng thiết bị (và các tham số từ trường customData
, nếu có) trong phản hồi SYNC
để giao tiếp với thiết bị.
Ví dụ:
Đoạn mã sau đây cho biết cách bạn có thể tạo trình xử lý EXECUTE
.
const executeHandler = (request: IntentFlow.ExecuteRequest): Promise<IntentFlow.ExecuteResponse> => { // Extract command(s) and device target(s) from request const command = request.inputs[0].payload.commands[0]; const execution = command.execution[0]; const response = new Execute.Response.Builder() .setRequestId(request.requestId); const result = command.devices.map((device) => { // Target id of the device provided in the SYNC response const deviceId = device.id; // Metadata for the device provided in the SYNC response // Use customData to provide additional required execution parameters const customData: any = device.customData; // Convert execution command into payload for local device let devicePayload: string; // ... // Construct a local device command over TCP const deviceCommand = new DataFlow.TcpRequestData(); deviceCommand.requestId = request.requestId; deviceCommand.deviceId = deviceId; deviceCommand.data = devicePayload; deviceCommand.port = customData.port; deviceCommand.operation = Constants.TcpOperation.WRITE; // Send command to the local device return localHomeApp.getDeviceManager() .send(deviceCommand) .then((result) => { response.setSuccessState(result.deviceId, state); }) .catch((err: IntentFlow.HandlerError) => { err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST; response.setErrorState(device.id, err.errorCode); }); }); // Respond once all commands complete return Promise.all(result) .then(() => response.build()); };
Triển khai trình xử lý QUERY
Trình xử lý QUERY
trong ứng dụng sẽ xử lý các yêu cầu của người dùng và sử dụng Local Home SDK để báo cáo trạng thái của các thiết bị thông minh.
Nền tảng Local Home truyền cùng một tải trọng yêu cầu đến hàm trình xử lý "QUERY" như đối với ý định QUERY
đến dịch vụ thực hiện trên đám mây. Tương tự, trình xử lý QUERY
của bạn sẽ trả về dữ liệu ở cùng định dạng như khi xử lý ý định QUERY
.
Gửi lệnh đến các thiết bị sau một trung tâm
Để điều khiển các thiết bị đầu cuối phía sau một thiết bị trung tâm, bạn có thể cần cung cấp thêm thông tin trong tải trọng lệnh dành riêng cho giao thức được gửi đến thiết bị trung tâm để thiết bị trung tâm xác định thiết bị mà lệnh đó nhắm đến. Trong một số trường hợp, bạn có thể suy luận trực tiếp từ giá trị device.id
, nhưng khi không phải như vậy, bạn nên thêm dữ liệu bổ sung này vào trường customData
.
Nếu bạn tạo ứng dụng bằng TypeScript, hãy nhớ biên dịch ứng dụng sang JavaScript. Bạn có thể sử dụng hệ thống mô-đun mà bạn chọn để viết mã. Đảm bảo trình duyệt Chrome hỗ trợ mục tiêu của bạn.