Czujniki internetu

Używaj interfejsu Generic Sensor API, aby uzyskać dostęp do czujników na urządzeniu, takich jak akcelerometry, żyroskopy i magnetometry.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Obecnie dane z czujników są wykorzystywane w wielu aplikacjach działających na konkretnych platformach, na przykład wciągające gry, śledzenie aktywności fizycznej oraz rzeczywistość rozszerzoną lub wirtualną. Czy nie byłoby wspaniale przejść przez most między aplikacjami zależnymi od platformy a aplikacjami internetowymi? Wpisz wartość Ogólny Sensor API do użytku w internecie.

Czym jest interfejs Generative Sensor API?

Generic Sensor API to zestaw interfejsów, które udostępniają urządzenia czujnikowe platformie internetowej. Interfejs API składa się z elementów Interfejs Sensor i zestaw konkretnych i klasy czujników. Dzięki interfejsowi podstawowemu upraszcza się proces implementacji i specyfikacji konkretnych klas czujników. Spójrz na przykład na Gyroscope. Jest bardzo malutki! główna funkcjonalność jest określana przez interfejs podstawowy, a Gyroscope rozszerza ją o trzy atrybutów reprezentujących prędkość kątową.

Niektóre klasy czujników łączą się z rzeczywistymi czujnikami sprzętowymi, takimi jak akcelerometr lub lekcji żyroskopu. Są to tak zwane czujniki niskiego poziomu. Inne czujniki, zwane czujnikami fuzji, łączą dane z kilku czujników niskiego poziomu, aby udostępniać informacje, które skrypt musiałby inaczej obliczyć. Na przykład parametr Czujnik AbsoluteOrientation zapewnia gotową do użycia macierz obrotu w układzie 4:4, opartą na danych uzyskanych akcelerometr, żyroskop i magnetometr.

Możesz myśleć, że platforma internetowa już udostępnia dane z czujników. I masz absolutną rację! Na przykład zdarzenia DeviceMotionDeviceOrientation udostępniają dane z czujnika ruchu. Dlaczego więc potrzebujemy nowego interfejsu API?

W porównaniu z dotychczasowymi interfejsami interfejs Generic Sensor API zapewnia wiele korzyści:

  • Interfejs General Sensor API to platforma czujników, którą można łatwo rozszerzyć za pomocą nowych klas czujników i każda z nich zachowa ogólny interfejs. Kod klienta napisany dla jednego typu czujnika można wykorzystać do innego z niewielkimi modyfikacjami.
  • Możesz skonfigurować czujnik. Możesz na przykład ustawić częstotliwość próbkowania odpowiednią do potrzeb aplikacji.
  • Możesz sprawdzić, czy na platformie jest dostępny czujnik.
  • Odczyty czujników mają znaczniki czasu o wysokiej dokładności, co umożliwia lepszą synchronizację z innymi działaniami w aplikacji.
  • Modele danych czujników i układy współrzędnych są jasno zdefiniowane, dzięki czemu dostawcy przeglądarek mogą wdrażania rozwiązań interoperacyjnych.
  • Interfejsy oparte na czujnikach ogólnych nie są powiązane z DOM (co oznacza, że nie są navigator ani obiektów window), co otwiera możliwości korzystania z interfejsu API w usłudze w przyszłości. lub implementować w środowiskach wykonawczych JavaScript bez interfejsu graficznego, takich jak urządzenia.
  • Aspekty bezpieczeństwa i prywatności mają najwyższy priorytet. API i zapewniają znacznie lepsze zabezpieczenia w porównaniu ze starszymi interfejsami API czujników. Istnieje integracja z interfejsem Permissions API.
  • Automatyczna synchronizacja z koordynatami ekranu jest dostępna w przypadku usług Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensorMagnetometer.

Dostępne ogólne interfejsy API czujników

W momencie pisania tego artykułu dostępnych jest kilka czujników, z którymi możesz eksperymentować.

Czujniki ruchu:

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

Czujniki środowiskowe:

  • AmbientLightSensor (za flagą #enable-generic-sensor-extra-classes w Chromium).
  • Magnetometer (za flagą #enable-generic-sensor-extra-classes w Chromium).

Wykrywanie cech

Wykrywanie funkcji interfejsów API sprzętowych jest trudne, ponieważ trzeba wykryć, czy przeglądarka obsługuje dany interfejs, oraz czy urządzenie ma odpowiedni czujnik. Konto rozliczeniowe czy przeglądarka obsługuje odpowiedni interfejs. (Zastąp Accelerometer dowolnym z tych elementów innych interfejsów wymienionych powyżej).

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

Aby uzyskać wiarygodny wynik wykrywania funkcji, musisz też spróbować połączyć się z czujnikiem. Ten przykład pokazuje, jak to zrobić.

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

Watolina

W przypadku przeglądarek, które nie obsługują interfejsu Generic Sensor API, dostępna jest funkcja polyfill. Dzięki polyfillowi możesz wczytywać tylko implementacje odpowiednich czujników.

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

Co to za wszystkie te czujniki? Jak mogę ich używać?

Czujniki to zagadnienie, o którym warto wspomnieć. Jeśli znasz się na czujnikach, możesz przejść od razu do sekcji poświęconej programowaniu praktycznemu. Przyjrzyjmy się teraz każdemu z nich z czujnika.

Akcelerometr i czujnik przyspieszenia liniowego

Dane z czujnika akcelerometru

Czujnik Accelerometer mierzy przyspieszenie urządzenia, na którym jest zainstalowany, na trzech osiach (X, Y i Z). Ten czujnik jest czujnika bezwładnego, co oznacza, że gdy urządzenie znajduje się w liniowym swobodnym spadaniu, całkowita liczba przyspieszenie wyniesie 0 m/s2, a gdy urządzenie leży płasko na stole, przyspieszenie w kierunku do góry (oś Z) będzie równa grawitacji Ziemi, tj. g ≈ +9,8 m/s2 Wskazuje on siłę, na jaką stół pcha urządzenie w górę. Jeśli umieścisz urządzenie w do prawej, przyspieszenie na osi X będzie dodatnie lub ujemne, jeśli przyspieszenie w prawo, w lewo.

Akcelerometr może służyć np. do liczenia kroków, wykrywania ruchu lub prostych urządzeń. orientacji ekranu. Pomiary z akcelerometru są często łączone z danymi z innych źródeł, czujniki Fusion, takie jak czujniki orientacji.

LinearAccelerationSensor zmierzyć przyspieszenie zastosowane do urządzenia, na którym znajduje się czujnik, z wyłączeniem wpływu grawitacji. Gdy urządzenie jest nieruchome, np. leży na stole, czujnik mierzy przyspieszenie ≈ 0 m/s2 na trzech osiach.

Czujnik grawitacji

Użytkownicy mogą już ręcznie uzyskiwać odczyty zbliżone do odczytów z czujnika grawitacyjnego, ręcznie sprawdzając odczyty AccelerometerLinearAccelerometer, ale może to być uciążliwe i zależy od dokładności wartości dostarczanych przez te czujniki. Takie platformy jak Android udostępniają odczyty grawitacji w ramach systemu operacyjnego, co powinno być tańsze pod względem pozwala na generowanie dokładniejszych wartości w zależności od sprzętu użytkownika i łatwiejsze korzystanie pod kątem ergonomii interfejsów API. GravitySensor zwraca efekt. przyspieszenia wzdłuż osi X, Y i Z urządzenia z powodu grawitacji.

Żyroskop

Pomiarów czujnika żyroskopu

Czujnik Gyroscope mierzy prędkość kątowa w radianach na sekundę wokół lokalnej osi X, Y i Z urządzenia. Większość konsumentów urządzenia są wyposażone w mechanizm (MEMS) żyroskopy, które są czujnikami bezwładnymi mierzącymi prędkość obrotu na podstawie siły wewnętrznej Coriolisa. Żyroskopy MEMS są podatne na dryf spowodowany przez czułość na przyciąganie ziemskie, która deformuje wewnętrzny system mechaniczny czujnika. żyroskopy oscylują z relatywnie wysokimi częstotliwościami, np. 10 s kHz oraz dlatego może zużywać więcej energii w porównaniu z innymi czujnikami.

Czujniki orientacji

Bezwzględne pomiary czujnika orientacji

AbsoluteOrientationSensor to czujnik fuzji, który mierzy obrót urządzenia w odniesieniu do układu współrzędnych Ziemi, podczas gdy RelativeOrientationSensor dostarcza dane przedstawiające obrót urządzenia z czujnikami ruchu w odniesieniu do miejsca nieruchomego wsadowy układ współrzędnych.

Wszystkie nowoczesne platformy JavaScript 3D obsługują kwaternionymacierze obrotu do reprezentowania obrotu. Jeśli jednak używasz bezpośrednio WebGL, obiekt OrientationSensor ma zarówno właściwość quaternion, jak i metodę populateMatrix(). Oto kilka fragmentów kodu:

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

Czujniki orientacji umożliwiają różne zastosowania, takie jak wciągające gry, rzeczywistość rozszerzona i wirtualna.

Więcej informacji o czujnikach ruchu, zaawansowanych zastosowaniach i wymaganiach znajdziesz w artykule Opis czujników ruchu.

Synchronizacja z koordynatami ekranu

Domyślnie odczyty czujników przestrzennych są przetwarzane w lokalnym układzie współrzędnych powiązanym z urządzeniem i nie uwzględniającym orientacji ekranu.

Układ współrzędnych urządzenia
Układ współrzędnych urządzenia

Jednak w wielu przypadkach użycia, takich jak gry czy rzeczywistość rozszerzona i wirtualna, odczyty z czujników muszą być w układzie współrzędnych, który jest powiązany z orientacją ekranu.

Układ współrzędnych ekranu
System współrzędnych ekranu

Wcześniej mapowanie odczytów z czujników do współrzędnych ekranu trzeba było wdrażać w JavaScripcie. Takie podejście jest nieefektywne i znacznie zwiększa złożoność kodu aplikacji internetowej. Aplikacja internetowa musi obserwować zmiany orientacji ekranu i przekształcać współrzędne odczytów czujnika, co nie jest proste w przypadku kątów Eulera ani kwaternionów.

Interfejs Generic Sensor API to znacznie prostsze i bardziej niezawodne rozwiązanie. Lokalny system współrzędnych można skonfigurować dla wszystkich zdefiniowanych klas czujników przestrzennych: Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensorMagnetometer. Przekazując opcję referenceFrame do konstruktora obiektów czujnika, użytkownik określa, czy zwrócone odczyty zostaną rozwiązane w device lub Współrzędne ekranu.

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

Kodujmy!

Interfejs Generative Sensor API jest bardzo prosty i łatwy w użyciu. Interfejs czujnika start() i Metody stop() do kontrolowania stanu czujnika oraz kilku moduły obsługi zdarzeń do otrzymywania powiadomień o aktywowaniu czujników, błędach i nowo dostępnych odczyty. Klasy konkretnych czujników zwykle dodają do klasy podstawowej określone atrybuty odczytu.

Środowisko programistyczne

Podczas programowania będzie można używać czujników w programie localhost. Jeśli tworzysz aplikację na urządzenia mobilne, skonfiguruj przekierowanie portów na serwerze lokalnym.

Gdy kod będzie gotowy, wdróż go na serwerze, który obsługuje HTTPS. Strony GitHub są wyświetlane przez HTTPS, dzięki czemu warto je udostępniać w Twoich wersjach demonstracyjnych.

Obracanie modelu 3D

W tym prostym przykładzie używamy danych z czujnika orientacji bezwzględnej, aby zmodyfikować obrót kwartion modelu 3D. Obiekt model jest instancją klasy Object3D z biblioteki three.js, która ma właściwość quaternion. ten fragment kodu z telefon w orientacji poziomej ilustruje sposób użycia czujnika orientacji bezwzględnej do obracania modelu 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();
}

Orientacja urządzenia będzie odzwierciedlona w obrocie 3D model w scenie WebGL.

Sensor updates 3D model's orientation
Czujnik aktualizuje orientację modelu 3D

Punchmeter

Następujący fragment kodu jest wyodrębniony z pliku prezentacja Punchmeter, przedstawia sposób użycia czujnika przyspieszenia liniowego do obliczania maksymalnej prędkości przy założeniu, że początkowo leży nieruchomo.

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

Bieżąca prędkość jest obliczana jako przybliżenie całki funkcji przyspieszenia.

Wersja demonstracyjna aplikacji internetowej do pomiaru szybkości przebijania
Pomiar szybkości uderzenia pięścią

Debugowanie i zastępowanie czujników w Narzędziach deweloperskich w Chrome

W niektórych przypadkach do korzystania z interfejsu General Sensor API nie potrzebujesz fizycznego urządzenia. Narzędzia deweloperskie w Chrome zapewniają świetne wsparcie w symulowaniu orientacji urządzenia.

Narzędzia deweloperskie w Chrome używane do zastępowania niestandardowych danych orientacji w wirtualnym telefonie
Symulowanie orientacji urządzenia za pomocą Narzędzi deweloperskich w Chrome

Prywatność i bezpieczeństwo

Odczyty z czujników to dane wrażliwe, które mogą być celem różnych ataków ze złośliwych stron internetowych. Implementacje interfejsów API czujników ogólnych narzucają kilka ograniczeń, aby ograniczyć możliwe zagrożenia dla bezpieczeństwa i prywatności. Deweloperzy, którzy chcą korzystać z interfejsu API, muszą wziąć pod uwagę te ograniczenia. Oto ich krótki opis.

Tylko HTTPS

Interfejs Generic Sensor API jest potężną funkcją, dlatego przeglądarka zezwala na jego użycie tylko w bezpiecznych kontekstach. W oznacza to, że aby korzystać z interfejsu Generative Sensor API, musisz uzyskiwać dostęp do strony przez HTTPS. W trakcie programowania możesz to zrobić przez http://localhost, ale w wersji produkcyjnej niezbędny jest protokół HTTPS na Twoim serwerze. Sprawdzone metody znajdziesz w kolekcji Bezpieczeństwo i ochrona. i wytycznych.

Integracja z zasadami dotyczącymi uprawnień

Integracja z zasadami dotyczącymi uprawnień w sekcji Ogólna Interfejs Sensor API kontroluje dostęp do danych z czujników klatki.

Domyślnie obiekty Sensor mogą być tworzone tylko w ramach głównego elementu iframe lub podelementów iframe tego samego pochodzenia, co uniemożliwia nieautoryzowane odczytywanie danych z czujników przez iframe z innego pochodzenia. To domyślne zachowanie można zmienić, wyraźnie włączając lub wyłączając odpowiednie funkcje kontrolowane przez zasady.

Poniżej znajduje się fragment kodu, który pokazuje, jak przyznać dostęp do danych akcelerometru do ramki iframe w innej domenie. Oznacza to, że teraz można tworzyć w niej obiekty Accelerometer lub LinearAccelerationSensor.

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

Dostarczanie odczytów z czujników może zostać zawieszone.

Wyniki pomiarów czujników są dostępne tylko dla widocznej strony internetowej, czyli wtedy, gdy użytkownik faktycznie z nią współpracuje. Ponadto dane z czujnika nie będą przekazywane do ramki nadrzędnej, jeśli użytkownik i zaznacz zmiany na ramce podrzędnej z innej domeny. Zapobiega to wywnioskowaniu danych wejściowych użytkownika przez ramkę nadrzędną.

Co dalej?

W najbliższej przyszłości zostanie zaimplementowany zestaw już określonych klas czujników, takich jak czujnik jasności otoczenia czy czujnik zbliżeniowy. Jednak dzięki dużej możliwości rozszerzalności Generic Sensor framework możemy spodziewać się pojawienia jeszcze większej liczby nowych klas reprezentujących różne typy czujników.

Kolejnym ważnym obszarem do dalszego rozwijania jest ulepszenie samego interfejsu Generic Sensor API. Specyfikacja Generic Sensor jest obecnie w fazie rekomendacji, co oznacza, że wciąż jest czas na wprowadzenie poprawek i nowych funkcji potrzebnych deweloperom.

Możesz pomóc.

Specyfikacja czujnika Rekomendacja kandydatów dojrzałości cyfrowej, dlatego opinie programistów internetu i przeglądarek są dla nas bardzo ważne. Daj nam znać, jakie funkcje warto dodać lub co można zmienić w obecnym interfejsie API.

Zgłaszaj problemy ze specyfikacją oraz błędy związane z implementacją w Chrome.

Zasoby

Podziękowania

Ten artykuł został zrecenzowany przez Joe Medley i Kayce Basques Baner powitalny autorstwa Misko z Wikimedia Commons.