Sensor APIs
===========

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

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

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

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

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

Интерфейсы датчиков - это только прокси для датчиков устройства. Как следствие, задача определения возможности использования датчиков гораздо сложнее, чем для других 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`, чтобы поймать ошибки, возникающие во время использования датчика. Единственный раз, когда что-либо показывается пользователю, это когда необходимо запросить разрешения (en-US) и когда датчик не поддерживается устройством.

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


```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 (en-US). Короткий пример, показанный ниже, запрашивает у пользователя разрешение перед попыткой использовать датчик.


```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>` (en-US) и директива `Feature-Policy` (en-US).

| Датчик | Разрешение/Имя 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` (en-US).


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

Интерфейсы
----------

`AbsoluteOrientationSensor` (en-US)Secure context

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

`Accelerometer` (en-US)Secure context

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

`AmbientLightSensor` (en-US)Secure context

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

`GravitySensor` (en-US)Secure context

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

`Gyroscope`Secure context

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

`LinearAccelerationSensor` (en-US)Secure context

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

`Magnetometer` (en-US)Secure context

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

`OrientationSensor` (en-US)Secure context

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

`RelativeOrientationSensor` (en-US)Secure context

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

`Sensor`Secure context

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

`SensorErrorEvent` (en-US)Secure context

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

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

| Specification |
| --- |
| Generic Sensor API # the-sensor-interface |

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

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.