Sensoren für das Web

Mit der Generic Sensor API können Sie auf On-Device-Sensoren wie Beschleunigungsmesser, Gyroskope und Magnetometer zugreifen.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Heutzutage werden Sensordaten in vielen plattformspezifischen Anwendungen verwendet, um Anwendungsfälle wie immersives Gaming, Fitness-Tracking sowie Augmented oder Virtual Reality zu ermöglichen. Wäre es nicht toll, die Lücke zwischen plattformspezifischen und Webanwendungen zu schließen? Die Generic Sensor API für das Web

Die Generic Sensor API ist eine Reihe von Schnittstellen, über die Sensorgeräte der Webplattform zur Verfügung gestellt werden. Die API besteht aus der Basisschnittstelle Sensor und einer Reihe von konkreten Sensorklassen, die darauf aufbauen. Eine Basisschnittstelle vereinfacht den Implementierungs- und Spezifikationsprozess für die konkreten Sensorklassen. Sehen wir uns beispielsweise die Klasse Gyroscope an. Es ist super klein! Die Hauptfunktionen werden durch die Basisoberfläche angegeben und Gyroscope erweitert sie lediglich um drei Attribute, die die Winkelgeschwindigkeit darstellen.

Einige Sensorklassen sind mit tatsächlichen Hardwaresensoren verbunden, z. B. die Beschleunigungsmesser- oder Gyroskopklassen. Diese Sensoren werden auch als Low-Level-Sensoren bezeichnet. Andere Sensoren, sogenannte Fusionssensoren, kombinieren Daten aus mehreren Low-Level-Sensoren, um Informationen bereitzustellen, die sonst von einem Script berechnet werden müssten. Der AbsoluteOrientation-Sensor bietet beispielsweise eine gebrauchsfertige 4 × 4-Rotationsmatrix, die auf den Daten des Beschleunigungsmessers, des Gyroskops und des Magnetometers basiert.

Sie denken vielleicht, dass die Webplattform bereits Sensordaten bereitstellt. Das ist richtig. So werden beispielsweise bei den Ereignissen DeviceMotion und DeviceOrientation Daten von Bewegungssensoren freigegeben. Warum brauchen wir also eine neue API?

Im Vergleich zu den vorhandenen Schnittstellen bietet die Generic Sensor API eine Vielzahl von Vorteilen:

  • Die Generic Sensor API ist ein Sensor-Framework, das einfach mit neuen Sensorklassen erweitert werden kann. Jede dieser Klassen behält die generische Schnittstelle bei. Der für einen Sensortyp geschriebene Clientcode kann mit nur wenigen Änderungen für einen anderen Sensortyp wiederverwendet werden.
  • Sie können den Sensor konfigurieren. Sie können beispielsweise die Abtastrate so festlegen, dass sie den Anforderungen Ihrer Anwendung entspricht.
  • Sie können prüfen, ob ein Sensor auf der Plattform verfügbar ist.
  • Sensormesswerte haben hochpräzise Zeitstempel, was eine bessere Synchronisierung mit anderen Aktivitäten in Ihrer Anwendung ermöglicht.
  • Sensordatenmodelle und Koordinatensysteme sind klar definiert, sodass Browseranbieter interoperable Lösungen implementieren können.
  • Die generischen sensorbasierten Schnittstellen sind nicht an das DOM gebunden, d. h., sie sind weder navigator- noch window-Objekte. Dies eröffnet in Zukunft Möglichkeiten, die API in Service Workern zu verwenden oder in headless JavaScript-Laufzeiten wie eingebetteten Geräten zu implementieren.
  • Sicherheit und Datenschutz haben bei der Generic Sensor API höchste Priorität und bieten im Vergleich zu älteren Sensor-APIs eine viel höhere Sicherheit. Es gibt eine Integration mit der Permissions API.
  • Die automatische Synchronisierung mit Bildschirmkoordinaten ist für Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor und Magnetometer verfügbar.

Verfügbare generische Sensor-APIs

Zum Zeitpunkt der Erstellung dieses Artikels gibt es mehrere Sensoren, mit denen Sie experimentieren können.

Bewegungssensoren:

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

Umgebungssensoren:

  • AmbientLightSensor (In Chromium hinter dem Flag #enable-generic-sensor-extra-classes)
  • Magnetometer (In Chromium hinter dem Flag #enable-generic-sensor-extra-classes)

Funktionserkennung

Die Erkennung von Merkmalen von Hardware-APIs ist kompliziert, da sowohl festgestellt werden muss, ob der Browser die betreffende Schnittstelle unterstützt, als auch, ob das Gerät über den entsprechenden Sensor verfügt. Es ist ganz einfach zu prüfen, ob der Browser eine Schnittstelle unterstützt. Ersetzen Sie Accelerometer durch eine der anderen oben erwähnten Schnittstellen.

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

Für ein aussagekräftiges Ergebnis der Feature-Erkennung müssen Sie auch versuchen, eine Verbindung zum Sensor herzustellen. In diesem Beispiel wird gezeigt, wie das geht.

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

Polyfill

Für Browser, die die Generic Sensor API nicht unterstützen, ist eine Polyfill verfügbar. Mit dem Polyfill kannst du nur die Implementierungen der relevanten Sensoren laden.

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

Was sind all diese Sensoren? Wie kann ich sie verwenden?

Sensoren ist ein Bereich, der möglicherweise einer kurzen Einführung bedarf. Wenn Sie mit Sensoren vertraut sind, können Sie direkt zum Abschnitt mit praktischen Programmieraufgaben springen. Sehen wir uns die einzelnen unterstützten Sensoren genauer an.

Beschleunigungsmesser und linearer Beschleunigungssensor

Messungen des Beschleunigungssensors

Der Accelerometer-Sensor misst die Beschleunigung eines Geräts, in dem sich der Sensor befindet, auf drei Achsen (X, Y und Z). Dieser Sensor ist ein inertialer Sensor. Wenn sich das Gerät also im linearen kostenlosen Fall befindet, beträgt die gemessene Gesamtbeschleunigung 0 m/s2. Wenn das Gerät flach auf einem Tisch liegt, entspricht die Beschleunigung in Aufwärtsrichtung (Z-Achse) der Schwerkraft der Erde, also g ≈ +9,8 m/s2, da die Kraft des Tisches gemessen wird, die das Gerät nach oben drückt. Wenn Sie das Gerät nach rechts schieben, ist die Beschleunigung auf der X-Achse positiv. Ist die Beschleunigung von rechts nach links, ist sie negativ.

Beschleunigungsmesser können beispielsweise für die Schrittzählung, die Bewegungserkennung oder die einfache Geräteausrichtung verwendet werden. Häufig werden Beschleunigungsmessermessungen mit Daten aus anderen Quellen kombiniert, um Fusionssensoren wie Orientierungssensoren zu erstellen.

LinearAccelerationSensor misst die Beschleunigung, die auf das Gerät angewendet wird, das den Sensor hostet, unter Ausschluss der Schwerkraft. Wenn sich ein Gerät in Ruhe befindet, also beispielsweise flach auf dem Tisch liegt, misst der Sensor eine Beschleunigung von ≈ 0 m/s2 auf drei Achsen.

Schwerkraftsensor

Nutzer können bereits manuell Messwerte ermitteln, die denen eines Schwerkraftsensors nahe kommen, indem sie die Messwerte Accelerometer und LinearAccelerometer manuell prüfen. Dies kann jedoch umständlich sein und von der Genauigkeit der von diesen Sensoren gelieferten Werte abhängen. Plattformen wie Android können Gravitationsmessungen als Teil des Betriebssystems bereitstellen. Dies sollte in Bezug auf die Berechnung günstiger sein, je nach Hardware des Nutzers genauere Werte liefern und in Bezug auf die API-Ergonomie einfacher zu verwenden sein. GravitySensor gibt die Beschleunigung entlang der X-, Y- und Z-Achse des Geräts aufgrund der Schwerkraft zurück.

Gyroskop

Messungen des Gyroskopsensors

Der Gyroscope-Sensor misst die Winkelgeschwindigkeit in Radianten pro Sekunde um die lokale X-, Y- und Z-Achse des Geräts. Die meisten Verbrauchergeräte haben mechanische (MEMS)-Gyroskope, also Trägheitssensoren, die die Drehrate anhand der Trägheits-Corioliskraft messen. MEMS-Gyroskope neigen zu Abweichungen, die durch die Gravitationsempfindlichkeit des Sensors verursacht werden, wodurch das interne mechanische System des Sensors verformt wird. Gyroskope schwingen mit relativ hohen Frequenzen, z.B. 10 kHz und verbrauchen daher im Vergleich zu anderen Sensoren möglicherweise mehr Strom.

Ausrichtungssensoren

Messungen des Sensors für die absolute Ausrichtung

Der AbsoluteOrientationSensor ist ein Fusionssensor, der die Drehung eines Geräts in Bezug auf das Erdkoordinatensystem misst. Der RelativeOrientationSensor liefert Daten zur Drehung eines Geräts mit Bewegungssensoren in Bezug auf ein stationäres Referenzkoordinatensystem.

Alle modernen 3D-JavaScript-Frameworks unterstützen Quaternionen und Rotationsmatrizen zur Darstellung der Rotation. Wenn Sie WebGL direkt verwenden, hat OrientationSensor jedoch praktisch sowohl ein Attribut quaternion als auch eine populateMatrix()-Methode. Hier einige Beispiele:

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

Ausrichtungssensoren ermöglichen verschiedene Anwendungsfälle wie immersives Gaming, Augmented Reality und Virtual Reality.

Weitere Informationen zu Bewegungssensoren, erweiterten Anwendungsfällen und Anforderungen finden Sie in der Erläuterung zu Bewegungssensoren.

Synchronisierung mit Bildschirmkoordinaten

Die Messwerte der Raumsensoren werden standardmäßig in einem lokalen Koordinatensystem aufgelöst, das an das Gerät gebunden ist und die Bildschirmausrichtung nicht berücksichtigt.

Gerätekoordinatensystem
Geräte-Koordinatensystem

Für viele Anwendungsfälle wie Spiele oder Augmented und Virtual Reality müssen die Sensorwerte jedoch in einem Koordinatensystem aufgelöst werden, das stattdessen an die Bildschirmausrichtung gebunden ist.

Bildschirmkoordinatensystem
Bildschirmkoordinatensystem

Bisher musste die Neuzuordnung von Sensorwerten zu Bildschirmkoordinaten in JavaScript implementiert werden. Dieser Ansatz ist ineffizient und erhöht auch die Komplexität des Webanwendungscodes erheblich. Die Webanwendung muss die Bildschirmausrichtung überwachen und Koordinatentransformationen für Sensordaten ausführen, was bei Eulerwinkeln oder Quaternionen nicht trivial ist.

Die Generic Sensor API bietet eine viel einfachere und zuverlässigere Lösung. Das lokale Koordinatensystem kann für alle definierten räumlichen Sensorklassen konfiguriert werden: Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor und Magnetometer. Durch Weitergabe der Option referenceFrame an den Konstruktor des Sensorobjekts definiert der Nutzer, ob die zurückgegebenen Messwerte in Geräte- oder Bildschirmkoordinaten aufgelöst werden.

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

Los gehts!

Die Generic Sensor API ist sehr einfach und nutzerfreundlich. Die Sensor-Benutzeroberfläche bietet die Methoden start() und stop() zum Steuern des Sensorstatus sowie mehrere Ereignis-Handler, um Benachrichtigungen über die Sensoraktivierung, Fehler und neu verfügbare Messwerte zu erhalten. Die konkreten Sensorklassen fügen der Basisklasse in der Regel ihre spezifischen Leseattribute hinzu.

Entwicklungsumgebung

Während der Entwicklung können Sie Sensoren über localhost verwenden. Wenn Sie für Mobilgeräte entwickeln, richten Sie die Portweiterleitung für Ihren lokalen Server ein.

Wenn Ihr Code fertig ist, stellen Sie ihn auf einem Server bereit, der HTTPS unterstützt. GitHub Pages werden über HTTPS ausgeliefert und sind daher eine gute Möglichkeit, Ihre Demos zu teilen.

3D-Modellrotation

In diesem einfachen Beispiel verwenden wir die Daten eines Sensors für die absolute Ausrichtung, um die Rotationsquaternion eines 3D-Modells zu ändern. model ist eine Instanz der Three.js-Klasse Object3D mit der Property quaternion. Im folgenden Code-Snippet aus der Demo orientation phone wird veranschaulicht, wie mit dem Sensor für die absolute Ausrichtung ein 3D‑Modell gedreht werden kann.

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

Die Ausrichtung des Geräts wird in der WebGL-Szene durch eine 3D-model-Drehung widergespiegelt.

Sensor aktualisiert die Ausrichtung des 3D‑Modells
Der Sensor aktualisiert die Ausrichtung eines 3D-Modells.

Punchmeter

Das folgende Code-Snippet stammt aus der Demo für den Schlagmesser. Es zeigt, wie mit dem linearen Beschleunigungssensor die maximale Geschwindigkeit eines Geräts berechnet werden kann, vorausgesetzt, es liegt anfangs still.

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

Die aktuelle Geschwindigkeit wird als Näherung für das Integral der Beschleunigungsfunktion berechnet.

Demo-Webanwendung zur Messung der Schlaggeschwindigkeit
Messung der Stempelgeschwindigkeit

Debugging und Sensorüberschreibung mit Chrome-Entwicklertools

In einigen Fällen benötigen Sie kein physisches Gerät, um die Generic Sensor API zu testen. Die Chrome-Entwicklertools bieten eine hervorragende Unterstützung für die Geräteorientierungssimulation.

Chrome DevTools wurden verwendet, um die benutzerdefinierten Ausrichtungsdaten eines virtuellen Smartphones zu überschreiben
Geräteausrichtung mit Chrome-Entwicklertools simulieren

Datenschutz und Sicherheit

Sensordaten sind sensible Daten, die von schädlichen Webseiten angegriffen werden können. Bei der Implementierung von Generic Sensor APIs werden einige Einschränkungen erzwungen, um die möglichen Sicherheits- und Datenschutzrisiken zu minimieren. Diese Einschränkungen müssen von Entwicklern, die die API verwenden, berücksichtigt werden. Daher sind sie im Folgenden kurz aufgeführt.

Nur HTTPS

Da die Generic Sensor API eine leistungsstarke Funktion ist, erlaubt der Browser sie nur in sicheren Kontexten. In der Praxis bedeutet das, dass Sie für die Verwendung der Generic Sensor API über HTTPS auf Ihre Seite zugreifen müssen. Während der Entwicklung ist das über http://localhost möglich. Für die Produktion ist jedoch HTTPS auf Ihrem Server erforderlich. Best Practices und Richtlinien finden Sie in der Sammlung Sicherheit und Schutz.

Integration der Richtlinie für Berechtigungen

Durch das Einbinden der Berechtigungsrichtlinie in die Generic Sensor API wird der Zugriff auf Sensordaten für einen Frame gesteuert.

Standardmäßig können Sensor-Objekte nur innerhalb eines Hauptframes oder von Subframes mit demselben Ursprung erstellt werden. So wird verhindert, dass iframes mit unterschiedlichen Ursprüngen Sensordaten unberechtigt lesen. Dieses Standardverhalten kann geändert werden, indem die entsprechenden richtliniengesteuerten Funktionen explizit aktiviert oder deaktiviert werden.

Im folgenden Snippet wird veranschaulicht, wie einem iframe mit unterschiedlicher Herkunft Zugriff auf Beschleunigungssensordaten gewährt wird. Das bedeutet, dass dort jetzt Accelerometer- oder LinearAccelerationSensor-Objekte erstellt werden können.

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

Die Übermittlung von Sensordaten kann ausgesetzt werden

Auf Sensordaten kann nur über eine sichtbare Webseite zugegriffen werden, d.h., wenn der Nutzer tatsächlich mit der Seite interagiert. Außerdem werden dem übergeordneten Frame keine Sensordaten zur Verfügung gestellt, wenn der Nutzerfokus auf einen plattformübergreifenden Unterframe wechselt. So wird verhindert, dass der übergeordnete Frame Nutzereingaben ableitet.

Nächste Schritte

Es gibt bereits eine Reihe von Sensorklassen, die in naher Zukunft implementiert werden sollen, z. B. Umgebungslichtsensor oder Näherungssensor. Dank der großen Erweiterungsfähigkeit des Generic Sensor Framework können wir jedoch davon ausgehen, dass noch mehr neue Klassen für verschiedene Sensortypen hinzukommen.

Ein weiterer wichtiger Bereich für zukünftige Arbeit ist die Verbesserung der Generic Sensor API selbst. Die Spezifikation für den generischen Sensor ist derzeit eine Empfehlung, was bedeutet, dass noch Zeit für Fehlerkorrekturen und neue Funktionen bleibt, die Entwickler benötigen.

Du kannst helfen!

Die Sensorspezifikationen haben den Reifegrad der Kandidatenempfehlungen erreicht, weshalb das Feedback von Web- und Browserentwicklern sehr gut ankommt. Lass uns wissen, welche Funktionen du dir wünschen würdest oder ob du etwas an der aktuellen API ändern möchtest.

Sie können Probleme mit Spezifikationen sowie Programmfehler für die Chrome-Implementierung melden.

Ressourcen

Danksagungen

Dieser Artikel wurde von Joe Medley und Kayce Basques geprüft.