Как использовать iBeacon и BLE в React Native?
В прошлой статье мы уже обсудили, чем полезны беакон-маячки и технология BLE для бизнеса. Сегодня перейдем к практике и рассмотрим, как именно можно использовать iBeacon и BLE в React Native, а именно с помощью библиотеки React Native BLE.
Как это реализовать технически?
Если вы решили, что хотите использовать данное решение в своем проекте, вам понадобятся
Beacon-маячок: выберите подходящий маячок с поддержкой BLE, который соответствуют вашим требованиям по дальности. Большое количество маячков вы можете найти на Aliexpress, мы использовали HOLY-IOT.
Смартфон или планшет с поддержкой BLE: Устройство для тестирования и использования вашего приложения, совместимое с технологией Bluetooth Low Energy. Для нашего решения подойдут iPhone c iOS 9.0 и выше, Android c 7 и выше.
Инструменты разработки для вашего приложения, например, VSCode, а также React Native и библиотека react-native-ble-plx.
Теперь можно приступать к реализации.
Сбор данных
Для сбора данных RSSI мы будем использовать библиотеку `react-native-ble-plx` . Используем методом startDeviceScan. Этот метод позволяет сканировать BLE устройства в радиусе действия и получать информацию о них, включая RSSI. Вот пример того, как можно реализовать сбор данных RSSI для определенных устройств:
import { BleManager } from "react-native-ble-plx";
const NAME = "HOLY-IOT";
const bleManager = new BleManager();
// Функция для начала сканирования BLE устройств
function startScanning() {
// Первый параметр - UUIDы сервисов (null, если хотите сканировать все устройства)
// Второй параметр - опции сканирования
// Третий параметр - колбэк, вызываемый при обнаружении устройства
bleManager.startDeviceScan(null, null, (error, scannedDevice) => {
if (error) {
console.warn(error);
return;
}
if (scannedDevice && scannedDevice.name === NAME) {
console.log(scannedDevice.name, scannedDevice.rssi); // находим необходимый нам девайс
// здесь в дальнейшем будем обрабатывать RSSI
}
});
}
// Остановка сканирования, если это необходимо
function stopScanning() {
bleManager.stopDeviceScan();
}
Также не забудьте запросить разрешения на доступ к местоположению, если вы работаете на Android, так как это необходимо для сканирования BLE устройств начиная с Android 6.0 (API уровня 23).
В этом примере сканирование всех доступных BLE устройств происходит каждый раз, когда обнаружено устройство c заданным UUID. В консоли будет отображаться имя устройства и его RSSI.
Обратите внимание, что для работы с Bluetooth на iOS и Android могут потребоваться разрешения и настройки конфиденциальности, включая запрос на доступ к местоположению и объяснение, зачем вашему приложению это разрешение, в файлах `Info.plist` (iOS) и `AndroidManifest.xml` (Android) соответственно.
Оценка расстояния на основе RSSI
Для расчета расстояние между BLE устройством и маячком на основе значения RSSI используем данную формулу:
где:
d — расстояние до устройства (маячка),
TX Power — мощность сигнала, измеренная на стандартном расстоянии (обычно 1 метр) от маячка
RSSI — мощность сигнала,
n — коэффициент затухания сигнала (environmental factor), отражающий потери сигнала в среде; типичные значения находятся в диапазоне от 2 до 4.
Эта формула позволяет оценить расстояние между двумя устройствами, используя логарифмическую зависимость изменения мощности сигнала от расстояния.
Значение коэффициента затухания сигнала n зависит от конкретных условий окружающей среды, в которой происходит передача сигнала.
Открытое пространство без препятствий: Значение n около 2. Это условие предполагает минимальное затухание сигнала, когда между устройствами нет значительных препятствий, и сигнал может распространяться прямолинейно.
Внутри помещений с препятствиями: Значение n может варьироваться от 2.5 до 3.5 или даже выше. В помещениях сигнал может отражаться от стен, потолков и других объектов, что увеличивает затухание. Более высокие значения n используются для учета этого дополнительного затухания.
Сложные условия с множеством препятствий: В помещении с высокой плотностью препятствий, таких как склады, производственные помещения или городские условия с множеством отражающих поверхностей, значение n может быть установлено в диапазоне от 4 до 5. Эти условия требуют более высокого коэффициента затухания для компенсации значительных потерь сигнала.
Важно понимать, что определение наиболее подходящего значения n часто требует эмпирического подхода. Это означает проведение тестов в целевой среде для измерения реального распределения сигнала и адаптации коэффициента затухания для достижения наилучшей точности в оценке расстояния.
Как это будет выглядеть на практике?
Мы уже получили значения RSSI в результате сканирования устройств, как было показано в предыдущем примере. Теперь добавим функцию для расчета расстояния:
function calculateDistance(rssi, measure = -69, multiplier = 2) {
return Math.pow(10, (measure - rssi) / (10 * multiplier));
}
bleManager.startDeviceScan(null, null, (error, scannedDevice) => {
if (error) {
console.warn(error);
return;
}
if (scannedDevice && scannedDevice.name === NAME) {
const distance = calculateDistance(scannedDevice.rssi);
}
});
Повышения точности измерений
Факторы, такие как физические препятствия, интерференция от других источников сигнала и различия в аппаратном обеспечении, могут искажать RSSI. Для повышения точности измерений применяются различные техники фильтрации.
Мы будем использовать простой метод скользящего среднего (Moving Average), который используется для сглаживания временных рядов данных и уменьшения случайных колебаний.
Для реализации этой техники мы будем хранить последние несколько измерений RSSI для устройства и вычислять среднее значение из них.
const rssiValues = {}; // объект для хранения массивов значений RSSI
function addRssiValueAndGetAverage(deviceId, newValue, maxSize = 3) {
if (!rssiValues[deviceId]) {
rssiValues[deviceId] = []; // Инициализируем массив, если это первое значение
}
const values = rssiValues[deviceId];
values.push(newValue); // Добавляем новое значение
// Удаляем самое старое значение, если превышен максимальный размер массива
if (values.length > maxSize) {
values.shift();
}
// Вычисляем среднее значение
const averageRssi = values.reduce((acc, value) => acc + value, 0) / values.length;
return averageRssi;
}
bleManager.startDeviceScan(null, null, (error, scannedDevice) => {
if (error) {
console.warn(error);
return;
}
if (scannedDevice && scannedDevice.name === NAME) {
const averageRssi = addRssiValueAndGetAverage(scannedDevice.id, scannedDevice.rssi);
console.log(`Среднее значение RSSI для устройства ${scannedDevice.name}: ${averageRssi}`);
// Здесь можно использовать среднее значение RSSI для оценки расстояния
}
});
Зачем мы все это делали?
Стоит отметить, что данный метод позволяет достичь приблизительной оценки расстояния до маячков. Несмотря на внедрение алгоритмов для повышения точности измерений, необходимо признать, что получаемые результаты остаются приблизительными. Также особенностью данной реализации является её работоспособность исключительно при активном состоянии приложения (foreground state), что накладывает определённые ограничения на сферы её применения.
Тем не менее, даже в текущем виде данная система может найти широкое применение в различных сценариях. Примеры включают в себя локализацию и навигацию внутри помещений, например, в торговых центрах, музеях, на складах, где важно предоставить пользователям или сотрудникам информацию о ближайших объектах и маршрутах движения.
В будущем мы планируем разработать улучшенную версию, которая будет способна функционировать не только при активном приложении, но и в фоновом режиме (background state). Это позволит расширить область применения технологии, делая её пригодной для задач мониторинга и трекинга в реальном времени без необходимости постоянного взаимодействия пользователя с приложением.
Развитие и улучшение системы трекинга с использованием BLE и RSSI открывает новые перспективы для создания эффективных и удобных решений в самых разных областях, от ритейла до фудтеха, предоставляя пользовательский опыт нового уровня.