Підводні камені використання Cocoa Touch BLE
Будь-який розробник, який працював з iOS BLE, знає, що насправді не все так чудово, як описує документація. Сьогодні я хотів би розповісти про кілька основних моментів, які можуть виявитись каверзними під час роботи з BLE. Поділюся з вами корисною інформацією, аби зробити вашу подорож до світу Cocoa BLE менш болючою та більш продуктивною.
Скорочення (у порядку їх появи в тексті):
BLE — Bluetooth Low Energy — технологія Bluetooth з низьким енергоспоживанням
PCB — Printed circuit board — друкована плата
API — Application Programming Interface — програмний інтерфейс застосунку
Основні підходи
Найперше, що вам треба знати, — це відповідь на питання: «Де саме щось іде не так — на вашому боці чи на підключеному пристрої?».
Щоб відповісти на це питання, я рекомендую застосовувати кілька підходів:
- сніффер (аналізатор трафіку);
- сторонні програми для тестування API;
- ведення логу;
- версія прошивки пристрою, з яким ви працюєте, без шифрування чи будь-якого іншого захисту.
Тож давайте обговоримо кожен підхід детальніше.
Сніффер
Це інструмент, що дозволяє вам перехоплювати пакети даних та аналізувати їх напряму за допомогою спеціального застосунку. Він може бути корисним, щоб розрізняти різні аспекти BLE-комунікації — запити, відповіді, необроблені помилки, несподівані повідомлення і таке інше.
Щоб встановити такий інструмент, вам потрібно лише кілька речей: спеціальна PCB-плата та відповідний застосунок. Я використовував Wireshark та тестову плату Nordic Semiconductors. Разом вони забезпечують потужний набір інструментів для сніффингу. Інструменти-сніффери можуть бути використані в двох режимах — реклами та з’єднання.
Корисні посилання:
- Інформація про інструменти для сніффингу та те, як вони працюють.
- Сніффер nRF-Sniffer-UG.
- Wireshark.
- XQuartz (потрібен для деяких версій Wireshark).
Сторонні програми для тестування API
Один з найшвидших способів перевірки вашого пристрою — це використання сторонніх рішень. З їх допомогою ви легко можете сканувати, надсилати/отримувати або навіть симулювати деякі функції свого пристрою. Чудові приклади: LightBlue, BlueGecko.
Ведення логу
Більшість BLE-пристроїв комунікують зі смартфоном. Тому розуміти, що відбувається власне на телефоні, може бути надзвичайно важливим і корисним. Один з найкращих способів для перевірки того, що відбувається у телефоні, — використання можливостей власне операційної системи телефона, реєструючи всі події в лог. Щоб активувати ведення лога для Bluetooth в iOS, потрібно встановити спеціальний профіль на пристрій. Більше інформації про це можна знайти тут.
Після активації iTunes зможе синхронізувати логи з комп’ютером для їх подальшого аналізу.
Прошивка
Щоб захистити свій продукт, виробники часто використовують зашифрований протокол зв’язку між програмою та пристроєм. Такий підхід забезпечує більш високий рівень безпеки для користувача, однак він набагато складніший в розробці. Щоб спростити цей процес, завжди використовуйте незашифровану версію прошивки під час розробки та включайте додатковий рівень безпеки лише при виведенні на ринок. Це, звичайно, дещо впливає на час розробки прошивки, але водночас зменшує зусилля, необхідні з вашого боку для розробки застосунку.
На цьому етапі я припускаю, що середовище розробки повністю працює, і все, що вам треба, це просто засукати рукава та почати програмувати :)
Про що подбати
Щоб гарантувати вашому користувачеві найкращий user experience, ви повинні повністю контролювати середовище Bluetooth всередині вашої програми та, відповідно, у всіх його аспектах. Загалом ви повинні подбати про такі моменти:
- доступність Bluetooth-пристрою (спостереження за статусом пристрою);
- тайм-аут для відповіді від підключеного пристрою;
- обробка багаторядкових відповідей (за необхідності);
- робота в фоновому режимі (за необхідності);
- з’єднання з кількома пристроями одночасно (за необхідності).
Я не буду описувати всі аспекти кожного з наведених вище моментів. Замість цього я поділюся з вами кількома порадами та власними спостереженнями.
Спостереження за статусом пристрою
На наше щастя, iOS вміє працювати з кількома пристроями одночасно. Тож при роботі з кількома об’єктами, що працюють з Bluetooth-пристроями, ніяких проблем не виникає. Звичайно ж, ми скористаємося цією можливістю. Один з можливих підходів — це підготувати простий сканер стану Bluetooth, що дозволить вам отримувати сповіщення при зміні статусу. Цей підхід простий, ефективний і може бути використаний таким чином:
import Foundation import CoreBluetooth final class BLEStatusObserver: NSObject { public struct Notifications { public static let BLEStatusObserverDidDetectBLEStatusChange = "BLEStatusObserverDidDetectBLEStatusChangeNotification" struct Keys { static let availability = "availability"static let message = "message" } } static let observer = BLEStatusObserver() var isBleDeviceActive:Bool { return currentState == .poweredOn } private var centralManager:CBCentralManager? private var currentState:CBManagerState = .unknown // MARK: - LifeCycle override init() { super.init() centralManager = CBCentralManager(delegate: self, queue: nil) } } extension BLEStatusObserver:CBCentralManagerDelegate { // MARK: - CBCentralManagerDelegate func centralManagerDidUpdateState(_ central: CBCentralManager) { var notificationMessage:String? = nilswitch central.state { case .unauthorized: notificationMessage = NdynamicLocalizableString"bleService.message.StatusUnathorized") case .unsupported: notificationMessage = NdynamicocalizableString("bleService.message.Unsupported") case .poweredOff: notificationMessage = NdynamicocalizableString("bleService.message.PowerOff") case .poweredOn: notificationMessage = NdynamicocalizableString("bleService.message.PowerOn") default: break } currentState = central.state NotificationCenter.default.post(name: NSNotification.Name(rawValue: BLEStatusObserver.Notifications.BLEStatusObserverDidDetectBLEStatusChange), object: nil, userInfo: [ Notifications.Keys.availability : central.state == .poweredOn, Notifications.Keys.message : notificationMessage ?? "" ]) } }
Тайм-аут
Тайм-аут для запитів від BLE не обробляється CoreBluetooth за замовчуванням, тому вам доведеться реалізувати цей механізм самостійно. Ось де ви зможете втілити весь свій творчий потенціал в рамках проектних вимог. Єдине, що вам насправді треба знати, — тайм-аут насправді необхідний (навіть коли все здавалося б працює бездоганно).
Ще один корисний момент — це знання про швидкість передачі пакетів даних та відповідні взаємозалежності. Хтось, напевне, вже підготував тести на справжніх пристроях. Також у вас, можливо, з’явиться бажання перевірити офіційну документацію Bluetooth. Припускаю, швидкість передачі пакетів може залежати від кількох факторів:
- Модель передавача на ваших BLE-пристроях.
- Реалізація прошивки (Різні функції можуть потребувати на виконання різного часу. На одному з проектів ми маємо запит, виконання якого потребує до 4 секунд).
- Відстань до пристрою.
- Розмір пакету даних.
- Потужність передавача.
Беручи це до уваги, пропоную починати з
Багаторядкові відповіді
Деякі прошивки можуть для конкретних запитів повертати відповідь довжиною у кілька рядків (через обмеження розміру пакету, особливості реалізації або з іншої причини). У такому разі я хотів би запропонувати узгоджувати конкретний протокол зв’язку та структуру кожного запиту/відповіді. Наприклад, це може бути таким чином:
- Кожний запит має бути розміром n байт, з random байтом для невикористаного простору.
- Кожна відповідь має починатись/закінчуватись певним символом або кількома символами.
Цей підхід надзвичайно простий та, повірте мені, дуже ефективний. Якщо ви його запровадите, ви можете навіть почати краще спати вночі :)
Ще один момент — переконайтесь, що ви виконуєте лише один запит одночасно. Для цього у пригоді може стати NSOperationQueue. Я не поринатиму в особливості реалізації, проте хочу наголосити, що, аби належним чином обробляти усі моменти, слід створити щось на кшталт AsyncOperation (наприклад, як отут).
Робота у фоновому режимі
А ось це надзвичайно цікаво. Серйозно — дуже і дуже цікаво. Слід прочитати усю наявну документацію, а потом прочитати її ще раз. Чимало моментів можуть виявитись дещо підступними. Я не описуватиму всі складнощі тут, бо вважаю, що це питання для окремої статті, наприклад, такої.
Все, що вам слід знати про роботу у фоновому режимі для Cocoa Touch — це те, що все дійсно працює, але не завжди так, як ви очікуєте. Якщо ви стикнулися з труднощами, є лише одна порада — читати документацію ще раз.
Висновки
Використавши наведені підходи при роботі з BLE в CocoaTouch, ви з легкістю збережете свій час та підвищите ефективність своєї роботи. Звісно, багато моментів тут не розкриті на повну, проте наведені ресурси та посилання допоможуть знайти правильний шлях для коректного вирішення будь-яких поставлених задач. І на останок скажу, що по-хорошому заздрю тому, хто буде вперше починати працювати з BLE в Cocoa, тому побажаю терпіння і натхнення :)
Корисні посилання:
- Apple Developer — Core Bluetooth Programming Guide, Documentation
- WWDC 2012 Videos — Core Bluetooth 101
- WWDC 2012 Videos — Advanced Core Bluetooth
- WWDC 2013 Videos — Core Bluetooth
- Tutorials
- Gists
- Sniffer tool