Pull to refresh
0
Techmas
Производство результативных решений в Mobile.

Пример работы с технологией iBeacon с помощью Swift

Reading time 4 min
Views 13K
Учитывая возрастающий интерес к использованию Bluetooth маячков в различных областях начиная от чипирования животных, навигации в музейной экспозиции и заканчивая наиболее востребованной функцией уведомлений по акциям в магазинах, мы в Techmas подготовили введение для их внедрения на практике. Возможно, кому-нибудь из разработчиков, кто только планирует создавать свои приложения и еще не знает с чего начать, инструкция ниже поможет разобраться с основными понятиями и возможностями технологии. Несмотря на то, что уже существует набор SDK для работы с маячками, мы используем только Swift и библиотеки CoreLocation и CoreBluetooth.






Начнем с теории по самой технологии. В конце 2014 года Bluetooth Special Interest Group (SIG) выпустила спецификацию Bluetooth v4.2 (Bluetooth Low Energy, BLE).

Следуя описанию, мы имеем сигнал размером в 31 байт в виде пакета Scan Response Data. Этот пакет делится на так называемые AD структуры, которые представляют собой последовательности байтов различных предопределенных размеров. Принимая во внимание, что 16 байт из этого пакета должно уходить на 128 битный UUID устройства, большое количество данных с одного маячка получить нельзя.

Стандарт iBeacon был представлен компанией Apple в 2013 году. В нем сигнал BLE содержит MAC адрес и две AD структуры. Тогда как первая AD структура содержит общую информацию, вторая имеет непосредственное отношение к iBeacon. Рассмотрим ее подробнее.

Первый байт содержит информацию о длине структуры в 26 байт (0x1A), следом один байт на тип, который указывает принадлежность к производителю. Далее идет идентификатор компании Apple (0xFF). Следующие два байта на индикаторы маячка, которые всегда равны 0x02 и 0x15 (по одному байту на каждый). Как мы писали выше, на UUID устройства уходит 16 байт. Итого для полей Major и Minor остается всего по 2 байта. Последнее поле TX Power может быть использовано для калибровки маячка (1 байт).

Общая схема пакета:



Изучив основные понятия, вернемся к SDK от Apple для работы с маячками и напишем простое приложение для вывода информации о ближайшем маячке.

Мы использовали маячки, купленные здесь. Они представляют собой небольшую коробочку размером 46мм*36мм*18мм:


Код примера можно взять в Github.

Итак, начнем с подключения необходимых библиотек:

import UIKit
import CoreLocation
import CoreBluetooth


Далее определим переменные, о назначении которых подробнее скажем позже.
var locationManager = CLLocationManager()
var region = CLBeaconRegion()


Для простоты, мы в основном будем использовать метод viewDidLoad(). В нем определим:
override func viewDidLoad() {
     super.viewDidLoad()
     locationManager.delegate = self
}


Объект region определяет область поиска маячков и позволяет ее ограничить по параметрам маячков: uuid, значением полей major и minor.

let region = CLBeaconRegion(proximityUUID: NSUUID(UUIDString: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), identifier: "ru.techmas.techbeacon") 


Далее мы имеем объект locationManager, который обращается к самому устройству для выполнения поиска маячков и отслеживает события их обнаружения. Для этого необходимо назначить наш контроллер делегатом locationManager:

class ViewController: UIViewController, CLLocationManagerDelegate {


Кроме того, начиная с iOS 8 приложение должно запрашивать авторизацию для использования функций геолокации. Мы можем использовать методы locationManager.requestWhenInUseAuthorization() и locationManager.requestAlwaysAuthorization(). Они отличаются тем, что первый допускает использование геолокации только при активном окне приложения, тогда как второй предоставляет доступ в любое время.

С помощью конструктора добавляем строку в info.plist, который содержится в директории «Supporting Files»:



Чтобы предупреждение не возникало каждый раз, используем метод authorizationStatus() класса CLLocationManager:

if (CLLocationManager.authorizationStatus() != CLAuthorizationStatus.AuthorizedWhenInUse) {
     locationManager.requestWhenInUseAuthorization()
} 


Теперь мы готовы к поиску маячков!

Добавляем вызов метода поиска:
locationManager.startRangingBeaconsInRegion(region)


Для отображения информации о найденных маячках определим новый метод:
func locationManager(manager: CLLocationManager!, didRangeBeacons beacons: [AnyObject]!, inRegion region: CLBeaconRegion!) {
}


Внутри метода делегата мы имеем доступ к маячкам, которые нашел наш locationManager. Для вывода информации о них в консоль достаточно добавить строку:
println(beacons)


Попробуем вывести информацию о ближайшем маячке на экран.

Определим ближайший маячок:
let knownBeacons = beacons.filter{ $0.proximity != CLProximity.Unknown }
if (knownBeacons.count > 0) {
            let closestBeacon = knownBeacons[0] as! CLBeacon
}


Объект closestBeacon имеет поля, о которых мы упоминали выше:
  • major
  • minor
  • proximity
  • rssi
  • accuracy


Остановимся на поле proximity, которое имеет тип enum. Чтобы получить информацию в виде строки нам нужно:
var proximityString = String()
switch proximity
{
case .Near:
    proximityString = "Близко"
case .Immediate:
    proximityString = "Недалеко"
case .Far:
    proximityString = "Далеко"
case .Unknown:
    proximityString = "Unknown"
}


Полученные данные выведем на экран. Код будет выглядеть так:
func locationManager(manager: CLLocationManager!, didRangeBeacons beacons: [AnyObject]!, inRegion region: CLBeaconRegion!) {
        println(beacons)
        
        let knownBeacons = beacons.filter{ $0.proximity != CLProximity.Unknown }
        
        if (knownBeacons.count > 0) {
            let closestBeacon = knownBeacons[0] as! CLBeacon

            major_label.text = String(stringInterpolationSegment: closestBeacon.major)
            minor_label.text = String(stringInterpolationSegment: closestBeacon.minor)
            
            let proximity = closestBeacon.proximity
            
            var proximityString = String()
            
            switch proximity
            {
            case .Near:
                proximityString = "Близко"
            case .Immediate:
                proximityString = "Недалеко"
            case .Far:
                proximityString = "Далеко"
            case .Unknown:
                proximityString = "Unknown"
            }

            proximity_label.text = proximityString
            rssi_label.text = String(closestBeacon.rssi)
            accuracy_label.text = String(stringInterpolationSegment: closestBeacon.accuracy)
        }
        
} 


Наше приложение будет иметь вид:


Надеемся, что наше описание поможет разработчикам быстрее разобраться в технологии iBeacon и начать создавать новые приложения. В следующих статьях мы расскажем как подготовить структуру навигации внутри помещений с помощью набора маячков, использовать уведомления при попадании в зону сигнала и многое другое.
Tags:
Hubs:
+14
Comments 2
Comments Comments 2

Articles

Information

Website
techmas.ru
Registered
Founded
Employees
11–30 employees
Location
Россия