Cảm biến cho web

Sử dụng Generic Sensor API (API Cảm biến chung) để có quyền truy cập vào các cảm biến trên thiết bị như gia tốc kế, con quay hồi chuyển và từ kế.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Hiện nay, dữ liệu cảm biến được dùng trong nhiều ứng dụng dành riêng cho nền tảng để hỗ trợ các trường hợp sử dụng như chơi trò chơi sống động, theo dõi hoạt động thể dục và thực tế tăng cường hoặc thực tế ảo. Thật tuyệt vời khi làm cầu nối giữa các ứng dụng web và ứng dụng dành riêng cho nền tảng? Nhập Generic Sensor API (API Cảm biến chung) cho web!

API cảm biến chung là gì?

API Cảm biến chung là một tập hợp các giao diện hiển thị thiết bị cảm biến lên nền tảng web. API này bao gồm giao diện Sensor cơ sở và một tập hợp các lớp cảm biến cụ thể được tạo ở trên cùng. Việc sở hữu giao diện cơ sở giúp đơn giản hoá quá trình triển khai và quy cách cho các lớp cảm biến cụ thể. Ví dụ: hãy xem lớp Gyroscope. Siêu nhỏ! Chức năng cốt lõi do giao diện cơ sở chỉ định, và Gyroscope chỉ mở rộng chức năng này với 3 thuộc tính biểu thị vận tốc góc.

Một số lớp cảm biến giao tiếp với cảm biến phần cứng thực tế, chẳng hạn như lớp gia tốc kế hoặc con quay hồi chuyển. Chúng được gọi là cảm biến cấp thấp. Các cảm biến khác, còn gọi là cảm biến nhiệt hợp, hợp nhất dữ liệu từ một số cảm biến cấp thấp để hiển thị thông tin mà tập lệnh cần tính toán. Ví dụ: cảm biến AbsoluteOrientation cung cấp một ma trận xoay 4x4 có thể sử dụng được dựa trên dữ liệu thu được từ gia tốc kế, con quay hồi chuyển và từ kế.

Bạn có thể cho rằng nền tảng web này đã cung cấp dữ liệu cảm biến và bạn hoàn toàn đúng! Ví dụ: các sự kiện DeviceMotionDeviceOrientation sẽ hiển thị dữ liệu cảm biến chuyển động. Vậy tại sao chúng ta cần một API mới?

So với các giao diện hiện có, API cảm biến chung mang lại nhiều ưu điểm như sau:

  • API cảm biến chung là một khung cảm biến có thể dễ dàng mở rộng bằng các lớp cảm biến mới và mỗi lớp trong số này sẽ giữ giao diện chung. Mã ứng dụng được viết cho một loại cảm biến có thể được sử dụng lại cho một loại cảm biến khác với rất ít lần sửa đổi!
  • Bạn có thể định cấu hình cảm biến. Ví dụ: bạn có thể đặt tần suất lấy mẫu phù hợp với nhu cầu của ứng dụng.
  • Bạn có thể phát hiện xem có cảm biến trên nền tảng hay không.
  • Kết quả đọc cảm biến có dấu thời gian chính xác cao, giúp đồng bộ hoá tốt hơn với các hoạt động khác trong ứng dụng.
  • Mô hình dữ liệu cảm biến và hệ thống toạ độ được xác định rõ ràng, cho phép các nhà cung cấp trình duyệt triển khai các giải pháp có khả năng tương tác.
  • Các giao diện dựa trên Cảm biến chung không được liên kết với DOM (nghĩa là các giao diện này không phải là đối tượng navigator hoặc window) và điều này mở ra cơ hội trong tương lai để sử dụng API trong các trình chạy dịch vụ hoặc triển khai API trong thời gian chạy JavaScript không có giao diện người dùng, chẳng hạn như thiết bị được nhúng.
  • khía cạnh Bảo mật và quyền riêng tư là ưu tiên hàng đầu đối với API Cảm biến chung và mang lại khả năng bảo mật tốt hơn nhiều so với các API cảm biến cũ. API này tích hợp với API Quyền.
  • Tính năng đồng bộ hoá với toạ độ màn hình tự động hiện có cho Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensorMagnetometer.

Các API cảm biến chung hiện có

Tại thời điểm viết bài này, bạn có thể thử nghiệm một số cảm biến.

Cảm biến chuyển động:

  • Accelerometer
  • Gyroscope
  • LinearAccelerationSensor
  • AbsoluteOrientationSensor
  • RelativeOrientationSensor
  • GravitySensor

Cảm biến môi trường:

  • AmbientLightSensor (Đằng sau cờ #enable-generic-sensor-extra-classes trong Chromium.)
  • Magnetometer (Đằng sau cờ #enable-generic-sensor-extra-classes trong Chromium.)

Phát hiện tính năng

Việc phát hiện tính năng của API phần cứng là rất khó khăn, vì bạn cần xác định xem trình duyệt có hỗ trợ giao diện được đề cập hay không thiết bị có cảm biến tương ứng hay không. Việc kiểm tra xem trình duyệt có hỗ trợ một giao diện hay không một cách đơn giản. (Thay thế Accelerometer bằng bất kỳ giao diện nào khác đã đề cập ở trên.)

if ('Accelerometer' in window) {
  // The `Accelerometer` interface is supported by the browser.
  // Does the device have an accelerometer, though?
}

Để có kết quả phát hiện tính năng thực sự có ý nghĩa, bạn cũng cần cố gắng kết nối với cảm biến. Ví dụ này minh hoạ cách thực hiện việc đó.

let accelerometer = null;
try {
  accelerometer = new Accelerometer({ frequency: 10 });
  accelerometer.onerror = (event) => {
    // Handle runtime errors.
    if (event.error.name === 'NotAllowedError') {
      console.log('Permission to access sensor was denied.');
    } else if (event.error.name === 'NotReadableError') {
      console.log('Cannot connect to the sensor.');
    }
  };
  accelerometer.onreading = (e) => {
    console.log(e);
  };
  accelerometer.start();
} catch (error) {
  // Handle construction errors.
  if (error.name === 'SecurityError') {
    console.log('Sensor construction was blocked by the Permissions Policy.');
  } else if (error.name === 'ReferenceError') {
    console.log('Sensor is not supported by the User Agent.');
  } else {
    throw error;
  }
}

Vải polyfill

Đối với các trình duyệt không hỗ trợ API Cảm biến chung, bạn có thể sử dụng polyfill. Tính năng polyfill chỉ cho phép bạn tải các phương thức triển khai cảm biến có liên quan.

// Import the objects you need.
import { Gyroscope, AbsoluteOrientationSensor } from './src/motion-sensors.js';

// And they're ready for use!
const gyroscope = new Gyroscope({ frequency: 15 });
const orientation = new AbsoluteOrientationSensor({ frequency: 60 });

Những cảm biến này là gì? Làm cách nào để sử dụng quảng cáo khi mở ứng dụng?

Cảm biến là một lĩnh vực mà bạn có thể cần giới thiệu ngắn gọn. Nếu đã quen thuộc với cảm biến, bạn có thể chuyển đến phần thực hành lập trình. Nếu không, hãy xem xét chi tiết từng cảm biến được hỗ trợ.

Cảm biến gia tốc kế và cảm biến gia tốc tuyến tính

Đo lường cảm biến gia tốc kế

Cảm biến Accelerometer đo lường gia tốc của một thiết bị lưu trữ cảm biến trên 3 trục (X, Y và Z). Cảm biến này là cảm biến quán tính, nghĩa là khi thiết bị đang rơi tự do tuyến tính, tổng gia tốc đo được sẽ là 0 m/s2 và khi một thiết bị nằm phẳng trên mặt bàn, gia tốc hướng lên (trục Z) sẽ bằng trọng lực của Trái đất, tức là g ≈ +9, 8 m/s khi đẩy bàn lên trên là2 Nếu bạn đẩy thiết bị sang phải, gia tốc trên trục X sẽ là dương hoặc âm nếu thiết bị được tăng tốc từ phải sang trái.

Bạn có thể dùng gia tốc kế cho những việc như: đếm bước, cảm biến chuyển động hoặc hướng thiết bị đơn giản. Thông thường, các phép đo gia tốc kế được kết hợp với dữ liệu từ các nguồn khác để tạo ra các cảm biến hợp nhất, chẳng hạn như cảm biến hướng.

LinearAccelerationSensor đo lường gia tốc áp dụng cho thiết bị lưu trữ cảm biến, không bao gồm phần đóng góp của trọng lực. Khi một thiết bị ở trạng thái nghỉ, chẳng hạn như nằm trên mặt bàn, cảm biến sẽ đo gia tốc ≈ 0 m/s2 trên 3 trục.

Cảm biến trọng lực

Người dùng hiện có thể tự lấy kết quả đọc gần với kết quả đọc của cảm biến trọng lực bằng cách tự kiểm tra kết quả đọc AccelerometerLinearAccelerometer. Tuy nhiên, việc này có thể rườm rà và phụ thuộc vào độ chính xác của các giá trị do các cảm biến đó cung cấp. Các nền tảng như Android có thể cung cấp chỉ số trọng lực như một phần của hệ điều hành, điều này có thể rẻ hơn về mặt tính toán, cung cấp giá trị chính xác hơn tuỳ thuộc vào phần cứng của người dùng và dễ sử dụng hơn về mặt công thái học của API. GravitySensor trả về hiệu ứng gia tốc dọc theo trục X, Y và Z của thiết bị do trọng lực.

Con quay hồi chuyển

Đo lường cảm biến con quay hồi chuyển

Cảm biến Gyroscope đo vận tốc góc tính bằng radian mỗi giây xung quanh trục X, Y và Z cục bộ của thiết bị. Hầu hết thiết bị tiêu dùng đều có con quay hồi chuyển cơ học (MEMS). Đây là cảm biến quán tính đo tốc độ xoay dựa trên lực Coriolis quán tính. Con quay hồi chuyển MEMS dễ bị trôi do độ nhạy hấp dẫn của cảm biến làm biến dạng hệ thống cơ học bên trong của cảm biến. Con quay hồi chuyển dao động ở tần số tương đối cao, ví dụ: 10 giây kHz có thể tiêu thụ nhiều năng lượng hơn so với các cảm biến khác.

Cảm biến hướng

Đo lường cảm biến hướng tuyệt đối

AbsoluteOrientationSensor là cảm biến nhiệt hạch đo độ xoay của một thiết bị trong hệ thống toạ độ của Trái đất, trong khi RelativeOrientationSensor cung cấp dữ liệu biểu thị độ quay của một thiết bị lưu trữ cảm biến chuyển động so với hệ toạ độ tham chiếu tĩnh.

Tất cả các khung JavaScript 3D hiện đại đều hỗ trợ quaternionsma trận xoay để thể hiện chế độ xoay; tuy nhiên, nếu bạn sử dụng trực tiếp WebGL, OrientationSensor sẽ thuận tiện có cả thuộc tính quaternion và một populateMatrix() phương thức. Dưới đây là một số đoạn mã:

three.js

let torusGeometry = new THREE.TorusGeometry(7, 1.6, 4, 3, 6.3);
let material = new THREE.MeshBasicMaterial({ color: 0x0071c5 });
let torus = new THREE.Mesh(torusGeometry, material);
scene.add(torus);

// Update mesh rotation using quaternion.
const sensorAbs = new AbsoluteOrientationSensor();
sensorAbs.onreading = () => torus.quaternion.fromArray(sensorAbs.quaternion);
sensorAbs.start();

// Update mesh rotation using rotation matrix.
const sensorRel = new RelativeOrientationSensor();
let rotationMatrix = new Float32Array(16);
sensor_rel.onreading = () => {
  sensorRel.populateMatrix(rotationMatrix);
  torus.matrix.fromArray(rotationMatrix);
};
sensorRel.start();

BABYLON

const mesh = new BABYLON.Mesh.CreateCylinder('mesh', 0.9, 0.3, 0.6, 9, 1, scene);
const sensorRel = new RelativeOrientationSensor({ frequency: 30 });
sensorRel.onreading = () => mesh.rotationQuaternion.FromArray(sensorRel.quaternion);
sensorRel.start();

WebGL

// Initialize sensor and update model matrix when new reading is available.
let modMatrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const sensorAbs = new AbsoluteOrientationSensor({ frequency: 60 });
sensorAbs.onreading = () => sensorAbs.populateMatrix(modMatrix);
sensorAbs.start();

// Somewhere in rendering code, update vertex shader attribute for the model
gl.uniformMatrix4fv(modMatrixAttr, false, modMatrix);

Cảm biến hướng hỗ trợ nhiều trường hợp sử dụng, chẳng hạn như chơi trò chơi sống động, thực tế tăng cường và thực tế ảo.

Để biết thêm thông tin về cảm biến chuyển động, trường hợp sử dụng nâng cao và các yêu cầu, hãy xem tài liệu giải thích về cảm biến chuyển động.

Đồng bộ hoá với toạ độ màn hình

Theo mặc định, kết quả đọc cảm biến không gian được phân giải trong một hệ toạ độ cục bộ được liên kết với thiết bị và không tính đến hướng màn hình.

Hệ toạ độ thiết bị
Hệ toạ độ thiết bị

Tuy nhiên, nhiều trường hợp sử dụng như trò chơi hoặc thực tế tăng cường và thực tế ảo yêu cầu phân giải kết quả đọc cảm biến trong một hệ toạ độ được liên kết với hướng màn hình.

Hệ toạ độ màn hình
Hệ toạ độ màn hình

Trước đây, bạn phải triển khai tính năng ánh xạ lại kết quả đọc cảm biến thành toạ độ màn hình trong JavaScript. Phương pháp này không hiệu quả và cũng làm tăng đáng kể độ phức tạp của mã ứng dụng web; ứng dụng web phải theo dõi các thay đổi về hướng màn hình và biến đổi toạ độ để đọc cảm biến. Đây không phải là một việc đơn giản đối với các góc Euler hoặc quaternion.

Generic Sensor API (API Cảm biến chung) cung cấp một giải pháp đơn giản và đáng tin cậy hơn nhiều! Bạn có thể định cấu hình hệ toạ độ cục bộ cho tất cả các lớp cảm biến không gian đã xác định: Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensorMagnetometer. Bằng cách truyền tuỳ chọn referenceFrame đến hàm khởi tạo đối tượng cảm biến, người dùng xác định liệu các kết quả đọc trả về sẽ được phân giải trong toạ độ thiết bị hay màn hình.

// Sensor readings are resolved in the Device coordinate system by default.
// Alternatively, could be RelativeOrientationSensor({referenceFrame: "device"}).
const sensorRelDevice = new RelativeOrientationSensor();

// Sensor readings are resolved in the Screen coordinate system. No manual remapping is required!
const sensorRelScreen = new RelativeOrientationSensor({ referenceFrame: 'screen' });

Hãy lập trình!

API Cảm biến chung rất đơn giản và dễ sử dụng! Giao diện Cảm biến có các phương thức start()stop() để kiểm soát trạng thái cảm biến và một số trình xử lý sự kiện để nhận thông báo về việc kích hoạt cảm biến, lỗi và các kết quả đọc mới có. Các lớp cảm biến cụ thể thường thêm thuộc tính đọc cụ thể vào lớp cơ sở.

Môi trường phát triển

Trong quá trình phát triển, bạn có thể sử dụng cảm biến thông qua localhost. Nếu bạn đang phát triển cho các thiết bị di động, hãy thiết lập tính năng chuyển tiếp cổng cho máy chủ cục bộ và thế là bạn đã sẵn sàng!

Khi mã của bạn đã sẵn sàng, hãy triển khai mã trên máy chủ hỗ trợ HTTPS. GitHub Pages được phân phát qua HTTPS nên đây là một nơi tuyệt vời để chia sẻ các bản minh hoạ của bạn.

Xoay mô hình 3D

Trong ví dụ đơn giản này, chúng ta sử dụng dữ liệu từ cảm biến hướng tuyệt đối để sửa đổi bội số xoay của mô hình 3D. model là một thực thể lớp Object3D 3.js có thuộc tính quaternion. Đoạn mã sau đây từ bản minh hoạ điện thoại hướng minh hoạ cách sử dụng cảm biến hướng tuyệt đối để xoay mô hình 3D.

function initSensor() {
  sensor = new AbsoluteOrientationSensor({ frequency: 60 });
  sensor.onreading = () => model.quaternion.fromArray(sensor.quaternion);
  sensor.onerror = (event) => {
    if (event.error.name == 'NotReadableError') {
      console.log('Sensor is not available.');
    }
  };
  sensor.start();
}

Hướng của thiết bị sẽ được phản ánh trong chế độ xoay model 3D trong cảnh WebGL.

Cảm biến cập nhật hướng của mô hình 3D
Cảm biến cập nhật hướng của mô hình 3D

Máy bấm lỗ

Đoạn mã sau đây được trích xuất từ bản minh hoạ máy đo lỗ, minh hoạ cách sử dụng cảm biến gia tốc tuyến tính để tính vận tốc tối đa của một thiết bị với giả định ban đầu thiết bị nằm yên.

this.maxSpeed = 0;
this.vx = 0;
this.ax = 0;
this.t = 0;

/* … */

this.accel.onreading = () => {
  let dt = (this.accel.timestamp - this.t) * 0.001; // In seconds.
  this.vx += ((this.accel.x + this.ax) / 2) * dt;

  let speed = Math.abs(this.vx);

  if (this.maxSpeed < speed) {
    this.maxSpeed = speed;
  }

  this.t = this.accel.timestamp;
  this.ax = this.accel.x;
};

Vận tốc hiện tại được tính bằng giá trị gần đúng của tích phân của hàm gia tốc.

Ứng dụng web minh hoạ để đo tốc độ đấm
Đo tốc độ bấm lỗ

Gỡ lỗi và ghi đè cảm biến bằng Công cụ của Chrome cho nhà phát triển

Trong một số trường hợp, bạn không cần thiết bị thực để sử dụng với Generic Sensor API (API Cảm biến chung). Công cụ của Chrome cho nhà phát triển có khả năng hỗ trợ tuyệt vời cho việc mô phỏng hướng thiết bị.

Công cụ của Chrome cho nhà phát triển dùng để ghi đè dữ liệu về hướng tuỳ chỉnh của điện thoại ảo
Mô phỏng hướng thiết bị bằng Công cụ của Chrome cho nhà phát triển

Quyền riêng tư và bảo mật

Kết quả đọc cảm biến là dữ liệu nhạy cảm và có thể bị nhiều cuộc tấn công từ các trang web độc hại thực hiện. Việc triển khai API cảm biến chung sẽ thực thi một số giới hạn để giảm thiểu rủi ro có thể xảy ra về bảo mật và quyền riêng tư. Các nhà phát triển có ý định sử dụng API này phải tính đến các giới hạn này. Vì vậy, hãy liệt kê ngắn gọn những giới hạn này.

Chỉ giao thức HTTPS

Vì API cảm biến chung là một tính năng mạnh mẽ nên trình duyệt chỉ cho phép API này trên ngữ cảnh bảo mật. Trên thực tế, điều đó có nghĩa là để sử dụng API Cảm biến chung, bạn cần truy cập vào trang của mình thông qua HTTPS. Trong quá trình phát triển, bạn có thể làm như vậy thông qua http://localhost, nhưng để phát hành chính thức, bạn cần có HTTPS trên máy chủ của mình. Hãy xem bộ sưu tập An toàn và bảo mật để biết các phương pháp và nguyên tắc hay nhất.

Tích hợp chính sách về quyền

Việc tích hợp Chính sách quyền trong API Cảm biến chung kiểm soát quyền truy cập vào dữ liệu cảm biến cho một khung.

Theo mặc định, bạn chỉ có thể tạo các đối tượng Sensor trong một khung chính hoặc các khung phụ có cùng nguồn gốc, từ đó ngăn các iframe nhiều nguồn gốc đọc dữ liệu cảm biến khi chưa được phép. Bạn có thể sửa đổi hành vi mặc định này bằng cách bật hoặc tắt một cách rõ ràng các tính năng do chính sách kiểm soát tương ứng.

Đoạn mã dưới đây minh hoạ việc cấp quyền truy cập dữ liệu gia tốc kế vào một iframe nhiều nguồn gốc, nghĩa là hiện có thể tạo các đối tượng Accelerometer hoặc LinearAccelerationSensor tại đó.

<iframe src="https://third-party.com" allow="accelerometer" />

Quá trình phân phối chỉ số cảm biến có thể bị tạm ngưng

Chỉ có một trang web hiển thị mới có thể truy cập vào kết quả đọc cảm biến, tức là khi người dùng thực sự đang tương tác với trang web đó. Hơn nữa, dữ liệu cảm biến sẽ không được cung cấp cho khung mẹ nếu tiêu điểm của người dùng thay đổi sang khung phụ trên nhiều nguồn gốc. Điều này ngăn khung mẹ suy luận hoạt động đầu vào của người dùng.

Tiếp theo là gì?

Chúng tôi sẽ triển khai một tập hợp các lớp cảm biến đã chỉ định trong tương lai gần, chẳng hạn như Cảm biến ánh sáng xung quanh hoặc Cảm biến độ gần; tuy nhiên, nhờ khả năng mở rộng tuyệt vời của khung Cảm biến chung, chúng ta có thể dự đoán sự xuất hiện của nhiều lớp mới đại diện cho nhiều loại cảm biến.

Một khía cạnh quan trọng khác cần thực hiện trong tương lai là cải thiện chính API cảm biến chung. Thông số kỹ thuật của Cảm biến chung hiện là Đề xuất đề xuất, nghĩa là vẫn còn thời gian để khắc phục và mang đến chức năng mới mà nhà phát triển cần.

Bạn có thể trợ giúp!

Thông số kỹ thuật của cảm biến đã đạt đến độ tuổi Đề xuất ứng viên. Do đó, chúng tôi rất trân trọng ý kiến phản hồi của các nhà phát triển web và trình duyệt. Hãy cho chúng tôi biết những tính năng bạn nên thêm hoặc có điều gì bạn muốn sửa đổi trong API hiện tại.

Vui lòng gửi vấn đề về quy cách cũng như bugs để triển khai Chrome.

Tài nguyên

Xác nhận

Bài viết này đã được Joe MedleyKayce Basques đánh giá. Hình ảnh chính của Misko qua Wikimedia Commons.