Cảm biến cho web

Sử dụng Generic Sensor API để 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

Ngày 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ư trải nghiệm chơi trò chơi sống động, theo dõi hoạt động thể dục và thực tế ảo hoặc thực tế tăng cường. Bắt đầu cầu nối sẽ hay đấy khoảng cách giữa các ứng dụng web và ứng dụng dành riêng cho nền tảng? Nhập General Sensor API (API Cảm biến chung), dành cho web!

Generic Sensor API (API Cảm biến chung) là gì?

General Sensor API (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 vào nền tảng web. API này bao gồm cơ sở Giao diện Sensor và một nhóm cụ thể các lớp cảm biến được xây dựng dựa trên đó. Việc có giao diện cơ sở giúp đơn giản hoá việc triển khai và quy cách cho các lớp cảm biến bê tông. Ví dụ: hãy xem Lớp Gyroscope. Nó siêu nhỏ! Chiến lược phát hành đĩa đơn chức năng cốt lõi được xác định bởi giao diện cơ sở, còn Gyroscope chỉ mở rộng nó bằng 3 các 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ác cảm biến phần cứng thực tế, chẳng hạn như 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 kết hợp, hợp nhất dữ liệu từ một số cấp độ thấp để hiển thị thông tin mà một tập lệnh cần phải tính toán. Ví dụ: Cảm biến AbsoluteOrientation cung cấp ma trận xoay bốn x bốn sẵn sàng sử dụng 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 đã cung cấp dữ liệu cảm biến và điều đó hoàn toàn đúng! Cho thực thể của DeviceMotionDeviceOrientation các sự kiện làm lộ 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ó, Generic Sensor API cung cấp nhiều ưu điểm lớn:

  • 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 này sẽ giữ giao diện chung. Mã ứng dụng khách được viết cho một loại cảm biến có thể được tái sử dụng cho một video khác với rất ít thao tác 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ể biết được liệu có cảm biến trên nền tảng này hay không.
  • Kết quả đo của cảm biến có dấu thời gian có độ chính xác cao, cho phép đồng bộ hoá tốt hơn với trong ứng dụng của bạn.
  • 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 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.
  • Giao diện dựa trên Cảm biến chung không bị ràng buộc với DOM (có nghĩa là các giao diện này không phải là navigator cũng như đối tượng window) và điều này mở ra cơ hội trong tương lai để sử dụng API trong dịch vụ hoặc triển khai mã đó trong thời gian chạy JavaScript không có giao diện người dùng, chẳng hạn như được nhúng thiết bị.
  • Các khía cạnh Bảo mật và quyền riêng tư là ưu tiên hàng đầu của Cảm biến chung và cung cấp khả năng bảo mật tốt hơn nhiều so với các API cảm biến cũ. Có tích hợp với API Quyền.
  • Tính năng đồng bộ hoá tự động với toạ độ màn hình đang có sẵn 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, 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 (Phía sau cờ #enable-generic-sensor-extra-classes trong Chromium).
  • Magnetometer (Phía 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 phức tạp vì bạn cần phải phát hiện cả hai liệu trình duyệt hỗ trợ giao diện liên quan thiết bị có cảm biến tương ứng hay không. Tài khoản thanh toán việc trình duyệt có hỗ trợ một giao diện hay không. (Thay thế Accelerometer bằng bất kỳ các giao diện khác được đề cập ở trên.)

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

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

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;
  }
}

Ống polyfill

Đối với các trình duyệt không hỗ trợ Generic Sensor API, Bạn có thể sử dụng polyfill. Polyfill cho phép bạn chỉ tải các cảm biến có liên quan thực tế.

// 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 });

Tất cả những cảm biến này là gì? Làm cách nào để sử dụng các tính năng này?

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

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

Thông tin đo lường của cảm biến gia tốc kế

Cảm biến Accelerometer đo lường gia tốc của thiết bị lưu trữ cảm biến trên ba trục (X, Y và Z). Cảm biến này là một cảm biến quán tính, nghĩa là khi thiết bị ở dạng rơi tự do tuyến tính, tổng giá trị đo được gia tốc sẽ là 0 m/s2 và khi một thiết bị nằm phẳng trên bàn thì gia tốc theo hướng đi lên (trục Z) sẽ bằng trọng lực của Trái đất, tức là g ≈ +9,8 m/s2 nó đang đo lực của bàn đẩy thiết bị lên. Nếu bạn đẩy thiết bị đến 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ừ từ phải sang trái.

Gia tốc kế có thể dùng cho những tính năng như: đếm số bước, cảm biến chuyển động hoặc thiết bị đơn giản hướng. 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ảm biến hợp nhất, chẳng hạn như cảm biến hướng.

Chiến lược phát hành đĩa đơn 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 giá trị đóng góp trọng lực. Khi một thiết bị ở trạng thái nghỉ, chẳng hạn như nằm trên bàn, cảm biến sẽ đo Gia tốc ≈ 0 m/s2 trên ba trục.

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

Người dùng có thể lấy được giá trị thủ công gần bằng giá trị đo của cảm biến trọng lực bằng cách kiểm tra kết quả AccelerometerLinearAccelerometer theo cách thủ công, nhưng 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 các chỉ số trọng lực như một phần của hệ điều hành, vốn sẽ rẻ hơn vì tính toán, cung cấp các 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 trong các điều khoản của API công thái học. Chiến lược phát hành đĩa đơn 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

Phép đo cảm biến con quay hồi chuyển

Cảm biến Gyroscope đo lường vận tốc góc (tính bằng radian/giây) xung quanh trục X, Y và Z cục bộ của thiết bị. Hầu hết người tiêu dùng thiết bị có cơ khí (MEMS) con quay hồi chuyển, là cảm biến quán tính đo tốc độ quay dựa trên lực hướng Coriolis. Con quay hồi chuyển MEMS bị lỗi độ trôi do độ nhạy trọng trường của cảm biến khiến cảm biến biến dạng hệ thống cơ học bên trong. Con quay hồi chuyển dao động ở tần số cao tương đối, ví dụ: 10 giây kHz và do đó, 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

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

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

Tất cả các khung JavaScript 3D hiện đại đều hỗ trợ bộ phân tíchma trận xoay để biểu thị thao tác xoay; tuy nhiên, nếu bạn sử dụng WebGL trực tiếp, OrientationSensor sẽ thuận tiện có cả hai Tài sản 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, tăng cường và ảo thực tế.

Để biết thêm thông tin về cảm biến chuyển động, các trường hợp sử dụng nâng cao và yêu cầu, hãy xem 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, chỉ số của cảm biến không gian sẽ được phân giải trong hệ toạ độ cục bộ được liên kết với thiết bị và không đưa hướng màn hình vào tài khoản.

Hệ toạ độ của thiết bị
Hệ thống toạ độ của 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 đòi hỏi việc đọc cảm biến phải được được phân giải trong hệ toạ độ được liên kết với hướng màn hình.

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

Trước đây, việc ánh xạ lại kết quả đọc cảm biến cho toạ độ màn hình phải được triển khai 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ôi trường web mã xử lý ứng dụng; ứng dụng web phải theo dõi các thay đổi về hướng màn hình và thực hiện toạ độ biến đổi để đọc cảm biến, đây không phải là một việc đơn giản đối với góc Euler hoặc quaternion.

Generic Sensor API cung cấp một giải pháp đơn giản và đáng tin cậy hơn nhiều! Hệ toạ độ cục bộ là có thể định cấu hình cho tất cả các lớp cảm biến không gian đã xác định: Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensorMagnetometer. Khi 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 giá trị đọc trả về có được phân giải trong thiết bị hoặc toạ độ của 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 cùng lập trình!

Generic Sensor API rất đơn giản và dễ sử dụng! Giao diện Cảm biến 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 báo cáo mới có sẵn bài đọc. Các lớp cảm biến bê tông thường thêm các thuộc tính đọc cụ thể vào chân đế .

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

Trong quá trình phát triển, bạn có thể sử dụng các cảm biến thông qua localhost. Nếu bạn đang phát triển cho thiết bị di động, thiết lập chuyển tiếp cổng cho máy chủ cục bộ của bạn và bạn đã sẵn sàng để sử dụ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. Trang GitHub được phân phối qua HTTPS, khiến đây trở thành một nơi tuyệt vời để chia sẻ các bản minh hoạ của mình.

Xoay mô hình 3D

Trong ví dụ đơn giản này, chúng ta sử dụng dữ liệu từ một cảm biến hướng tuyệt đối để sửa đổi hướng xoay tứ phân vị của mô hình 3D. model là một tệp Three.js Thực thể lớp Object3Dquaternion. Chiến lược phát hành đĩa đơn đoạn mã sau đây từ hướng điện thoại bản 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 3D model 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 được trích xuất từ bản minh hoạ về máy đếm lỗ, minh hoạ cách dùng cảm biến gia tốc tuyến tính để tính vận tốc cực đại của một theo 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 gần đúng với tích phân của hàm gia tốc.

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

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 để chơi với Generic Sensor API (API Cảm biến chung). Dịch vụ Công cụ của Chrome cho nhà phát triển hỗ trợ nhiệt tình cho 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 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ả đo lường của cảm biến là dữ liệu nhạy cảm và có thể bị các trang web độc hại tấn công. Việc triển khai API cảm biến chung sẽ thực thi một số hạn chế nhằm giảm thiểu khả năng bảo mật và quyền riêng tư. Những giới hạn này phải được xem xét bởi các nhà phát triển có ý định sử dụng API. Vì vậy, hãy liệt kê ngắn gọn chúng.

Chỉ HTTPS

Vì Generic Sensor API là một tính năng mạnh mẽ, nên trình duyệt chỉ cho phép API này trong bối cảnh bảo mật. Trong điều đó có nghĩa là để sử dụng Generic Sensor API, bạn sẽ 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ể thực hiện việc này qua http://localhost nhưng đối với phiên bản sản xuất, bạn sẽ cần có HTTPS trên máy chủ của bạn. Xem bộ sưu tập An toàn và bảo mật để biết các phương pháp hay nhất và nguyên tắc của chúng tôi.

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

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

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

Đoạn mã dưới đây minh hoạ việc cấp quyền truy cập vào dữ liệu gia tốc kế vào iframe trên 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 kết quả đọc cảm biến có thể bị tạm ngưng

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

Tiếp theo là gì?

Có một tập hợp các lớp cảm biến được chỉ định để triển khai 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 hơn nữa đại diện cho nhiều loại cảm biến.

Một lĩnh vực quan trọng khác cần thực hiện trong tương lai là cải thiện chính Generic Sensor API (API Cảm biến chung), Thông số kỹ thuật của cảm biến hiện là Đề xuất cho ứng viên, nên vẫn còn thời gian để sửa lỗi và cung cấp 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 Đề xuất ứng cử viên Do đó, phản hồi từ các nhà phát triển web và trình duyệt được đánh giá cao. Hãy để chúng tôi những tính năng nào nên thêm vào hoặc nếu có điều gì bạn muốn sửa đổi trong API hiện tại.

Bạn cũng có thể gửi các vấn đề về quy cách lỗi triển khai Chrome.

Tài nguyên

Xác nhận

Bài viết này do Joe Medley xem xét và Kayce Basques. Hình ảnh chính của Misko qua Wikimedia Commons.