Реализация UWB Find My (точный поиск предметов) в мобильном приложении
AirTag работает именно так: iPhone с U1-чипом направляет пользователя стрелкой прямо на потерянный предмет с точностью до 10 сантиметров. Это Precision Finding через UWB, и Apple открыла этот API для сторонних акцессуаров через Find My Network Accessory Program. Аналогичный опыт можно реализовать в собственном приложении — для трекеров инструментов, медицинских устройств, промышленного оборудования.
Два сценария: Find My сеть vs автономный UWB
Принципиально разные подходы:
Find My Network — трекер регистрируется в Apple Find My сети. Любой iPhone рядом анонимно отправляет местоположение трекера на серверы Apple. Пользователь видит трекер на карте в приложении Locator. Proximity Precision Finding через UWB при нахождении рядом. Требует: MFi Find My Network Accessory Program (платная, через Apple), специфичный Bluetooth-чип с Apple H2 или совместимым.
Автономный UWB-поиск — только когда телефон и трекер рядом. Без глобального трекинга через чужие устройства. Требует: UWB-чип в трекере (Qorvo DW3000, NXP SR150), поддержка NearbyInteraction на iPhone (U1-чип). Этот сценарий доступен без MFi-программы.
Для большинства B2B-задач (поиск инструментов на стройке, трекинг медоборудования в больнице) подходит автономный UWB.
iOS: Precision Finding через NearbyInteraction
import NearbyInteraction
import CoreBluetooth
class ItemFinderSession: NSObject {
private var niSession: NISession?
private var currentDistance: Float = 0
private var currentDirection: SIMD3<Float>?
func startFinding(accessoryToken: Data, bluetoothId: UUID) {
niSession = NISession()
niSession?.delegate = self
niSession?.delegateQueue = .main
let config = NINearbyAccessoryConfiguration(
accessoryData: accessoryToken,
bluetoothPeerIdentifier: bluetoothId
)
niSession?.run(config)
}
}
extension ItemFinderSession: NISessionDelegate {
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) {
guard let obj = nearbyObjects.first else { return }
if let distance = obj.distance {
currentDistance = distance
// Обновляем UI: расстояние до предмета
updateDistanceDisplay(meters: distance)
}
if let direction = obj.direction {
currentDirection = direction
// direction — единичный вектор в ARKit coordinate space
// direction.x: влево-вправо, direction.y: вверх-вниз, direction.z: вперёд-назад
updateDirectionalArrow(direction: direction)
}
}
func session(_ session: NISession, didUpdateAlgorithmConvergence convergence: NIAlgorithmConvergence, for object: NINearbyObject?) {
// convergence.status: .converged / .notConverged([reasons])
// При notConverged — просить пользователя повести телефоном
handleConvergence(convergence.status)
}
}
convergence.status — критично для UX. UWB-алгоритм требует нескольких секунд движения телефона для определения направления. Если пользователь стоит неподвижно, direction не будет определён. При .notConverged(.insufficientMovement) показываем анимацию "подвигайте телефоном".
Стрелка-направление: ARKit vs UIKit
ARKit подход (как AirTag): стрелка рендерится в AR-пространстве, привязана к реальному миру. Использует ARWorldTrackingConfiguration + NINearbyObject.direction для вычисления положения предмета в AR-сцене. Самый иммерсивный UX.
UIKit подход: обычная стрелка на экране, поворачивается по компасу с учётом направления от NearbyInteraction. Проще в реализации, работает в любом окружении без AR-инициализации.
// UIKit стрелка через CMMotionManager + NearbyInteraction direction
func updateArrow(direction: SIMD3<Float>) {
// Конвертируем UWB-вектор в угол на экране
let angle = atan2(direction.x, -direction.z) // угол в горизонтальной плоскости
let deviceHeading = motionManager.deviceMotion?.attitude.yaw ?? 0
let arrowAngle = angle - Float(deviceHeading)
arrowImageView.transform = CGAffineTransform(rotationAngle: CGFloat(arrowAngle))
}
Расстояние → интенсивность вибрации: UIImpactFeedbackGenerator(style: .heavy) при < 0.3 м, .medium при 0.3–1 м. Тактильная обратная связь — стандарт для поиска предметов.
Трекер на базе DW3000
Для автономного UWB-трекера без MFi: Qorvo DWM3001C development module — готовый UWB-трансивер с BLE для начального handshake. Прошивка реализует UWB Initiator role, обменивается токеном по BLE, отвечает на TWR-запросы от телефона.
На Android: androidx.core.uwb:uwb + собственный трекер с поддержкой FiRa Consortium спецификации. Те же принципы, другой API:
val rangingParams = UwbRangingParameters(
uwbConfigType = UwbRangingParameters.CONFIG_UNICAST_DS_TWR,
complexChannel = controllerScope.uwbComplexChannel,
peerDevices = listOf(UwbDevice.createForAddress(trackerUwbAddress)),
updateRateType = UwbRangingParameters.RANGING_UPDATE_RATE_FREQUENT,
sessionKeyInfo = sharedSessionKey
)
Сроки
Мобильное приложение с UWB Precision Finding (при наличии UWB-трекера): 1–3 недели. Разработка прошивки трекера на DW3000 + мобильное приложение: 1–3 месяца. Стоимость определяется требованиями к аппаратной части и числу поддерживаемых устройств.







