Mit der Generic Sensor API können Sie auf On-Device-Sensoren wie Beschleunigungsmesser, Gyroskope und Magnetometer zugreifen.
Heutzutage werden Sensordaten in vielen plattformspezifischen Anwendungen verwendet, um Anwendungsfälle wie immersives Gaming, Fitness-Tracking und Augmented Reality 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
Was ist die Generic Sensor API?
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 die Implementierung und Spezifikation der 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 werden 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 sich leicht mit neuen Sensorklassen erweitern lässt. 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
- nochwindow
-Objekte. Dies eröffnet in Zukunft Möglichkeiten, die API in Serviceworkern zu verwenden oder in headless JavaScript-Laufzeiten wie eingebetteten Geräten zu implementieren. - Sicherheit und Datenschutz haben für die Generic Sensor API oberste Priorität und bieten im Vergleich zu älteren Sensor APIs eine deutlich bessere Sicherheit. Es gibt eine Integration mit der Permissions API.
- Die automatische Synchronisierung mit Bildschirmkoordinaten ist für
Accelerometer
,Gyroscope
,LinearAccelerationSensor
,AbsoluteOrientationSensor
,RelativeOrientationSensor
undMagnetometer
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 Funktionserkennung von Hardware-APIs ist schwierig, da Sie sowohl feststellen müssen, ob der Browser die entsprechende Schnittstelle unterstützt, als auch, ob das Gerät den entsprechenden Sensor hat. Es ist ganz einfach zu prüfen, ob der Browser eine Schnittstelle unterstützt. Ersetzen Sie Accelerometer
durch eine der oben genannten 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 der Polyfill-Funktion können Sie 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 das für 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
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.
Der LinearAccelerationSensor
misst die Beschleunigung, die auf das Gerät mit dem Sensor ausgeübt wird, ohne den Beitrag 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 ableiten, die denen eines Gravitationssensors nahekommen, indem sie die Accelerometer
- und LinearAccelerometer
-Messwerte manuell prüfen. Das kann jedoch mühsam sein und von der Genauigkeit der von diesen Sensoren bereitgestellten 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 Auswirkungen der Beschleunigung entlang der X-, Y- und Z-Achse des Geräts aufgrund der Schwerkraft zurück.
Gyroskop
Der Sensor Gyroscope
misst die Winkelgeschwindigkeit in Radian 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
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 von Drehungen. Wenn Sie jedoch WebGL direkt verwenden, hat OrientationSensor
sowohl eine quaternion
-Eigenschaft als auch eine populateMatrix()
-Methode.
Hier einige Beispiele:
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();
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();
// 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);
Orientierungssensoren ermöglichen verschiedene Anwendungsfälle, z. B. immersive Spiele, Augmented Reality und virtuelle Realität.
Weitere Informationen zu Bewegungssensoren, erweiterten Anwendungsfällen und Anforderungen finden Sie im Dokument Erläuterung zu Bewegungssensoren.
Synchronisierung mit Bildschirmkoordinaten
Standardmäßig werden die Messwerte der räumlichen Sensoren in einem lokalen Koordinatensystem aufgelöst, das an das Gerät gebunden ist und die Bildschirmausrichtung nicht berücksichtigt.
Bei vielen Anwendungsfällen wie Spielen oder Augmented Reality und Virtual Reality müssen Sensordaten jedoch in einem Koordinatensystem aufgelöst werden, das an die Bildschirmausrichtung gebunden ist.
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 Übergabe 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 eignen sich daher hervorragend, um Ihre Demos zu teilen.
3D-Modell drehen
In diesem einfachen Beispiel verwenden wir die Daten eines absoluten Orientierungssensors, 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.
Locher
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.
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.
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 möchten, berücksichtigt werden. Hier eine kurze Auflistung:
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 Sicher und geschützt.
Integration der Richtlinie für Berechtigungen
Die Integration der Berechtigungsrichtlinie in der Generic Sensor API steuert den Zugriff auf Sensordaten für einen Frame.
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 Zustellung 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. der Umgebungslichtsensor oder der 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 Arbeiten 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 Empfohlene Kandidatur erreicht. Daher wird das Feedback von Web- und Browserentwicklern sehr geschätzt. 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 der Spezifikation sowie Fehler für die Chrome-Implementierung melden.
Ressourcen
- Demoprojekte: https://intel.github.io/generic-sensor-demos/
- Spezifikation der Generic Sensor API: https://w3c.github.io/sensors/
- Probleme mit der Spezifikation: https://github.com/w3c/sensors/issues
- Mailingliste der W3C-Arbeitsgruppe: public-device-apis@w3.org
- Chrome-Funktionsstatus: https://www.chromestatus.com/feature/5698781827825664
- Implementierungsfehler: http://crbug.com?q=component:Blink>Sensor
Danksagungen
Dieser Artikel wurde von Joe Medley und Kayce Basques geprüft.