Sensor APIs

Sensor APIs - это набор интерфейсов, построенных по общему дизайну, которые последовательно предоставляют доступ к датчикам устройств на веб-платформе.

Концепции и использование Sensor APIs

Несмотря на то, что спецификация Generic Sensor API определяет интерфейс Sensor, вам, как веб-разработчику, не придётся его использовать. Вместо него, для получения данных с конкретных датчиков, вы будете использовать один из его подклассов. Например, интерфейс Accelerometer возвращает ускорение перемещения устройства по всем трём осям на момент его считывания.

Данные с датчиков могут точно соответствовать данным с физических датчиков устройства, либо не соответствовать им. Например, интерфейс датчика Gyroscope точно соответствует интерфейсу физического датчика. В качестве альтернативы, интерфейс AbsoluteOrientationSensor предоставляет информацию, которая алгоритмически объединяет данные с двух и более датчиков устройста. Два эти типа датчиков называются низкоуровневыми и высокоуровневыми соответственно. Второй тип так же называют объединяющим датчиком (либо, виртуальным или, синтетическим).

Возможность использования

Интерфейсы датчиков - это только прокси для датчиков устройства. Как следствие, задача определения возможности использования датчиков гораздо сложнее, чем для других API. Наличие API датчика не значит, что этот API подключен к реальному аппаратному датчику, работает ли он, подключен или, даже, предоставил ли пользователь к нему доступ. Обеспечение постоянного доступа ко всей этой информации приводит к снижению производительности и разряду батареи.

Таким образом, определение возможности использования API датчиков должно включать определение наличия самого этого API и стратегии оборонительного программирования (см. ниже).

Пример ниже показывает три метода определения API датчика. Кроме того, вы можете обернуть создание экземпляра объекта в блок try...catch. Обратите внимание, что определение через интерфейс Navigator не единственный возможный путь.

js
if (typeof Gyroscope === "function") {
  // бег по кругу...
}

if ("ProximitySensor" in window) {
  // берегись!
}

if (window.AmbientLightSensor) {
  // погрузись во тьму...
}

Оборонительное программирование

Как указано в разделе Возможность использования, проверить наличие конкретного API датчика недостаточно. Наличие фактического датчика также должно быть подтверждено. Как раз здесь и необходимо оборонительное программирование. Оно включает три стратегии.

  • Проверка на наличие ошибок при создании экземпляра объекта датчика.
  • Прослушивание ошибок, возникающих во время его использования.
  • Корректная обработка ошибок для улучшения, а не ухудшения пользовательского опыта.

Приведенный ниже пример кода иллюстрирует эти принципы. Блок try...catch ловит ошибки, возникающие при создании объекта датчика. Этот объект слушает события error, чтобы поймать ошибки, возникающие во время использования датчика. Единственный раз, когда что-либо показывается пользователю, это когда необходимо запросить разрешения и когда датчик не поддерживается устройством.

Примечание: Если функциональная политика блокирует использование функции, то это происходит потому, что ваш код не соответствует политикам, установленным на вашем сервере. Это не то, что когда-либо будет показано пользователю. Статья о HTTP заголовке Feature-Policy содержит инструкцию по реализации.

js
let accelerometer = null;
try {
  accelerometer = new Accelerometer({ referenceFrame: "device" });
  accelerometer.addEventListener("error", (event) => {
    // Обработчик ошибок времени исполнения.
    if (event.error.name === "NotAllowedError") {
      // Переход к коду для запроса разрешения.
    } else if (event.error.name === "NotReadableError") {
      console.log("Не могу подключиться к датчику.");
    }
  });
  accelerometer.addEventListener("reading", () => reloadOnShake(accelerometer));
  accelerometer.start();
} catch (error) {
  // Обработчик ошибок создания объекта.
  if (error.name === "SecurityError") {
    // Смотри заметку о функциональных политиках.
    console.log(
      "Создание экземпляра объекта датчика было задлокировано по функциональным политикам.",
    );
  } else if (error.name === "ReferenceError") {
    console.log("Датчик не поддерживается в User agent.");
  } else {
    throw error;
  }
}

Разрешения и Функциональные Политики

Показания датчиков могут сниматься только в том случае, если пользователь дает разрешение на определенный тип датчика. Сделать это можно используя Permissions API. Короткий пример, показанный ниже, запрашивает у пользователя разрешение перед попыткой использовать датчик.

js
navigator.permissions.query({ name: "accelerometer" }).then((result) => {
  if (result.state === "denied") {
    console.log("Использование датчика не разрешено.");
    return;
  }
  // Используйте датчик.
});

Альтернативный подход заключается в попытке использовать датчик и прослушивании SecurityError.

js
const sensor = new AbsoluteOrientationSensor();
sensor.start();
sensor.addEventListener("error", (error) => {
  if (event.error.name === "SecurityError")
    console.log("Нет разрешения использовать AbsoluteOrientationSensor.");
});

В следующей таблице для каждого типа датчика описано имя, требуемое для Permissions API, атрибут allow элемента <iframe> и директива Feature-Policy.

Датчик Разрешение/Имя Feature Policy
AbsoluteOrientationSensor 'accelerometer', 'gyroscope', и 'magnetometer'
Accelerometer 'accelerometer'
AmbientLightSensor 'ambient-light-sensor'
GravitySensor 'accelerometer'
Gyroscope 'gyroscope'
LinearAccelerationSensor 'accelerometer'
Magnetometer 'magnetometer'
RelativeOrientationSensor 'accelerometer', и 'gyroscope'

Показания

Показания датчиков принимаются через событие reading, которое унаследовано для всех типов датчиков. Частота получения данных зависит от вас и указывается как параметр объекта, переданного в конструктор класса. Этот параметр определяет количество опросов датчика в секунду. Можно использовать целое или десятичное число, последнее для частот менее секунды. Фактическая частота считывания зависит от аппаратного обеспечения устройства и, следовательно, может быть меньше запрошенной.

Пример ниже иллюстрирует это используя Magnetometer.

js
let magSensor = new Magnetometer({ frequency: 60 });

magSensor.addEventListener("reading", (e) => {
  console.log("Магнитное поле вдоль оси X " + magSensor.x);
  console.log("Магнитное поле вдоль оси Y " + magSensor.y);
  console.log("Магнитное поле вдоль оси Z " + magSensor.z);
});
magSensor.addEventListener("error", (event) => {
  console.log(event.error.name, event.error.message);
});
magSensor.start();

Интерфейсы

AbsoluteOrientationSensorSecure context

Описывает физическую ориентацию устройства относительно системы координат Земли.

AccelerometerSecure context

Показывает ускорение, приложенное к устройству по всем трём осям.

AmbientLightSensorSecure context

Возвращает текущий уровень освещенности или освещенность окружающего освещения вокруг устройства.

GravitySensorSecure context

Показывает силу тяжести, приложенную к устройству по всем трём осям.

GyroscopeSecure context

Показывает угловую скорость устройства по всем трём осям.

LinearAccelerationSensorSecure context

Показывает ускорение, приложенное к устройству по всем трём осям, но без силы тяжести.

MagnetometerSecure context

Предоставляет информацию о магнитном поле, обнаруженном основным магнитометром устройства.

OrientationSensorSecure context

Базовый класс для AbsoluteOrientationSensor. Этот класс не может быть использован сам по себе, вместо этого он предоставляет свойства и методы, к которым обращаются наследуемые от него интерфейсы.

RelativeOrientationSensorSecure context

Описывает физическую ориентацию устройства без учета системы координат Земли.

SensorSecure context

Базовый класс для всех других интерфесов датчиков. Этот класс не может быть использован сам по себе. Вместо этого он предоставляет свойства, обработчики событий и методы, к которым обращаются интерфейсы, которые наследуются от него.

SensorErrorEventSecure context

Предоставляет информацию об ошибках, вызванных Sensor или связанным интерфейсом.

Спецификации

Specification
Generic Sensor API
Accelerometer
Orientation Sensor
Ambient Light Sensor
Gyroscope
Magnetometer

Совместимость с браузерами

api.Sensor

BCD tables only load in the browser

api.Accelerometer

BCD tables only load in the browser

api.OrientationSensor

BCD tables only load in the browser

api.Gyroscope

BCD tables only load in the browser

api.Magnetometer

BCD tables only load in the browser

api.AmbientLightSensor

BCD tables only load in the browser