Русский
Русский
English
Статистика
Реклама

Ble

Security Week 39 две уязвимости в протоколе Bluetooth

21.09.2020 18:14:10 | Автор: admin


За последние две недели стало известно сразу о двух уязвимостях в стандарте беспроводной связи Bluetooth. Сначала 9 сентября организация Bluetooth SIG распространила предупреждение о семействе атак BLURtooth. В теории уязвимость в спецификациях Bluetooth 4.2 и 5.0 позволяет организовать MitM-атаку. На практике для этого требуется совпадение множества условий, например подключение (с ограниченными правами) к целевому устройству.

Уязвимость обнаружена на стыке двух вариантов соединения Bluetooth традиционного Basic Rate / Enhanced Data Rate и энергоэффективного Bluetooth Low Energy. Чтобы не авторизоваться дважды по разным протоколам, в устройствах, поддерживающих и BR/EDR, и BLE, генерируются общие ключи длительного срока действия. Спецификация позволяет перезаписывать ключи, если требуется более надежный режим передачи данных. Но в результате с устройством можно установить связь либо вовсе без должной авторизации, либо защита соединения легко взламывается.

Вторую уязвимость, получившую название BLESA, обнаружили в спецификации Bluetooth Low Energy. Она позволяет подключаться к другим устройствам без авторизации, имитируя процедуру восстановления соединения после разрыва связи.

На практике это выглядит так: к смартфону подключено устройство (например, фитнес-трекер), затем соединение с ним обрывают и подключают к смартфону устройство атакующего. Дополнительная авторизация не требуется, а перехватить идентификатор легитимного устройства легко, так как эти данные передаются открытым текстом. Простота повторного подключения устройства обернулась прорехой в безопасности.


Источники
BLURTooth:
сообщение CERT Университета Карнеги Меллона;
бюллетень Bluetooth SIG;
новость на сайте Bleeping Computer;
новость на Хабре.

BLESA:
новость;
исследовательская работа;
новость на Хабре с PoC-видео.

Информация об этих атаках раскрыта совершенно по-разному. О BLESA опубликована научная работа с подробным описанием процесса атаки. Про BLURtooth лишь два коротких сообщения без деталей. Возможно, это связано с тем, что для BLESA уже выпустили патч (как минимум для устройств Apple), а также готовятся заплатки для Android и универсального стека Bluez.

BLURtooth пока что проблема без решения. Хотя есть у этих атак и общее: невысокая вероятность использования на практике из-за необходимости находиться рядом с жертвой и сомнительных (как минимум неисследованных) перспектив с точки зрения кражи данных.

Обе уязвимости в будущем могут стать этапом более серьезной атаки на IoT-устройства, тем более что обновить стек Bluetooth получится далеко не везде.

Что еще произошло
Специалисты Лаборатории Касперского опубликовали отчет о развитии угроз во II квартале 2020 года. Из интересного: рост числа вредоносных атак игровой тематики, в частности фишинг и распространение вредоносного ПО, связанного с платформой Steam.

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

Другое исследование Лаборатории Касперского посвящено уязвимости нулевого дня в Internet Explorer 11. В паре с другой дырой, не столь опасной самой по себе, баг в браузере обеспечивал полный контроль над целевой системой.

Печальный, но предсказуемый случай: в Германии атака трояна-шифровальщика на инфраструктуру больницы привела к смерти пациента.

В среду 16 сентября разработчики обновили CMS Drupal, в том числе исправили критическую XSS-уязвимость.

Интересный случай произошел с WordPress-плагином Discount Rules for WooCommerce. Две серьезных уязвимости пропатчили лишь с третьей попытки.



Издание Bleeping Computer сообщает о фишинговой атаке, которая маскируется под тренинг по информационной безопасности.

Компания Google вводит запрет на ПО типа stalkerware в Google Play. Точнее, нельзя наблюдать за пользователем скрытно: если такие функции есть, пользователя надо предупредить, что за его перемещениями и действиями будут наблюдать.

Эксплойт для уязвимости Zerologon в Windows появился в публичном доступе. Патч для этой дыры выпустили еще в августе этого года.
Подробнее..

Мини плата для разработки и отладки ПО на BLE, Zigbee Thread

23.07.2020 04:04:23 | Автор: admin
Приветствую читателей Habr! В этой статье хочу поделится с сообществом своей новой разработкой, речь пойдет о небольшой Development Board на чипе nRF52840. Плата была спроектированна под недорогие модули E73-2G4M08S1C. Идея ее создания родилась в одном уютном телеграмм чатике довольно спонтанно. Была необходимость в недорогом и простом в сборке девайсе.




За основу была взята схема nRF52840 Dongle, совместимость с pca10059 позволяло довольно просто начать разработку в СДК, не было необходимоти переназначать интерфейсы, переферию. Все электронные компоненты которые необходимо напаять имеют размер >= 0805, поэтому плата паяется довольно просто.



Устройство может работать как запитанным от USB, так и от батарейки CR2032 или от источника напряжением 3.3в. Для переключения питания необходимо переставить перемычку U4 в нужное положение 5V или 3V3. Для питания и програмирования через USB на плате сделаны посадочные места под 2 типа USB разьемов, MICRO USB 2.0 TYPE B и USB 2.0 Type A.

Так же на плате установлена дополнительная перемычка BAT для батарейного отсека, это позволяет полностью отключать батарейку от устройства.


На девайсе установлены два разьема, с одной стороны 14P разьем, и с другой стороны 10P разьеме, так же с нижней стороны устройсва сделаны пады под оставшиеся пины.

C помошью данной платы удобно собирать прототипы будующих девайсов и тестировать ПО. Мне данный модуль пригодился для прототипирования устройств для сетей Mysensors. Так же данную плату очень легко превратить в Arduino NINA 33 BLE. В Arduino есть неплохая библтиотека Arduino BLE на основе Mbed OS.

Гитхаб проекта Mini Development Board

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



Изначально дополнительная плата и проект диммера в целом разрабатывался VKE(Maxim) под сеть Zigbee но уперся в непреодолимые препятствия внутри ZigBee Open Source Stack, привет ребятам из dsr-corporation.



Насколько мне известно сейчас данный проект диммера пересобран под протокол Thread и там все просто прекрасно.

Гитхаб проекта модуля расширения(dimmer)
Гитхаб проекта диммера на Zigbee
Гитхаб проекта диммера на Thread

Так же буквально на днях стал доступен проект датчика температуры, влажности и давления BME 280 на Thread, результаты по стабильности работы в сети Thread и энергопотреблению впечатляют.


Гитхаб проекта BME280 сенсора на Thread





Фото платы Mini Development Board собранной разными людьми







Небольшой видосик теста oled дисплея на Mini Development Board



На этом наверное и закончу! Всех интересующихся DIY железками и разработкой ПО для nRF5 (и не только) на протоколах BLE, Zigbee, Thread, Mysensors приглашаю в наши уютные телеграмм чаты:
Telegram@DIY Devices
Telegram@MySensors

Всем Добра!!!
Подробнее..

Прием всего Bluetooth разом на SDR с CUDA? Легко

31.07.2020 16:11:33 | Автор: admin

В последнее время коллеги по "цеху" независимо друг от друга стали спрашивать меня: как получить c одного SDR-приемника одновременно все каналы Bluetooth? Полоса ведь позволяет, есть SDR с выходной полосой 80 МГц и более. Можно, конечно, сделать это на ПЛИС, но время такой разработки будет довольно большим. Мне давно было известно, что сделать такое на GPU довольно просто, но чтобы так!


Стандарт Bluetooth определяет физический уровень в двух версиях: Classic и Low Energy. Спецификация есть здесь. Документ ужасно большой, читать его целиком опасно для мозга. К счастью, большие компании, производящие измерительную технику, имеют средства для создания наглядных документов по теме. Tektronix и National Instruments, например. У меня совершенно нет шансов в конкуренции с ними по качеству представления материала. Интересующихся прошу изучать по ссылкам.


Все, что мне нужно знать о физическом уровне для создания многоканального фильтра, это шаг сетки частот и скорость модуляции. Они сведены в таблицу в одном из указанных документов:


image


Таким образом, нам нужно нарезать полосу 80 МГц на 79 фильтров с шагом настройки 1 МГц и, одновременно с этим, на 40 фильтров с шагом настройки 2 МГц. Частоты следования отсчетов с выходов фильтров должны быть 1 МГц и 2 МГц, соответственно.


Таким образом, нам необходимо две гребенки фильтров.


Для начала выберем параметры этих фильтров исходя из полос сигналов Bluetooth Classic и Bluetooth Low Energy. Нам нужны их импульсные характеристики, чтобы рассчитать нагрузку на вычислительное устройство фильтра. Здесь сразу стоит оговориться, что длины импульсных характеристик мы выбрали исходя из требований "быстрого" алгоритма фильтрации. Суть от этого не меняется. И число коэффициентов импульсной характеристики не должно быть слишком большим, чтобы фильтр был реализуем на вменяемой вычислительной аппаратуре.


Для фильтров с шагом 1 МГц выберем полосу пропускания ФНЧ (половина полосы пропускания полосового фильтра) 500 кГц, длину импульсной характеристики подгоним к 480 отводам. Для фильтров с шагом 2 МГц эти параметры выберем 1 МГц и 240 отводов, соответственно. Тип окна выбираем Кайзера. Рассчитаем импульсные характеристики в filterDesigner и выгрузим их в формате С-header:


Скриншоты из filterDesigner

image
image
image
image


Можно решать задачу лобовым способом: строить соответствующий по числу фильтров массив DDC (Digital Down Converter). Такой подход хорош для ПЛИС, где возможна экономия за счет уменьшения разрядности вычислителей первых ступеней. Также ПЛИС это наиболее энергетически-эффективный способ реализации. Но трудозатраты при этом способе наиболее высоки.


При выполнении гребенки фильтров на популярных нынче GPU появляется возможность реализации более хитрого алгоритма: полифазной гребенки фильтров на основе БПФ, который на CUDA доступен из библиотеки. В заграничной литературе алгоритм называется Polyphase or WOLA (Weight, Overlap and Add) FFT Filterbank. Лень к рисованию не дает мне возможности выполнить наглядное объяснение самостоятельно. В Сети есть много материалов по теме, особенно наглядный график выполнен здесь на странице 11 (огромное спасибо уважаемым авторам), вот он:


image


Я попробую пояснить схему обработки своими словами. Слабонервных прошу не читать.

Я попробую пояснить схему обработки своими словами в рамках моих методических возможностей. БПФ есть свертка входного сигнала со всем спектром комплексных ортогональных гармоник, укладывающихся на интервале импульсной характеристики. Импульсная характеристика фильтра, на которую умножается сигнал перед входом БПФ, модулируется этим спектров гармоник. Другими словами, огибающая импульсных характеристик результирующих фильтров гребенки выносится за скобки. Далее, спектр гармоник прореживается в некоторое число раз, ввиду расширения полосы пропускания фильтра относительно фильтра в прямоугольным окном. На рисунке мы видим прореживание на четыре. Другими словами, после расширения полосы окном Кайзера (с одновременным увеличением затухания в полосе задержания), нам уже нужны не все фильтры а только четвертая их часть. Остальные избыточны, их частотные характеристики перекрываются. Из четырех точек БПФ, идущих подряд, выбираем только нулевую, вычисление которой есть суммирование четырех
входных точек, взятых через время, равное четверти длительности исходного БПФ.


Железо выберем то, которое есть под рукой. Это плата ввода компании "Инструментальные Системы" FMC126P. О ней я уже писал в одной предыдущей статье. В разъем FMC платы вставлен субмодуль той же компании с трансивером AD9371 с полосой 100 МГц. Весь поток с трансивера может быть непрерывно передан в компьютер для обработки.


Выберем видео-карту с GPU GTX 1050. (Соврал, это она нас выбрала: это все что было под рукой, была выдрана из вычислителя для расчета антенн, но тем удивительней было увидеть рабочую гребенку). Перейдем к программной части.


К сожалению, из-за лицензий мы не можем опубликовать полный код. Можем показать только ядра GPU. Впрочем, остальной код и не особо интересен.


Вот ядро, которое выполняет перемножение сигнала на окно и сложение, и обертка для его вызова:


__global__ void cuComplexMultiplyWindowKernel(const cuComplex *data, const float *window, size_t windowSize, cuComplex *result) {    __shared__ cuComplex multiplicationResult[480];    multiplicationResult[threadIdx.x] = cuComplexMultiplyFloat(data[threadIdx.x + windowSize / 4 * blockIdx.x], window[threadIdx.x]);    __syncthreads();    cuComplex sum;    sum.x = sum.y = 0;    if (threadIdx.x < windowSize / 4) {        for(int i = 0; i < 4; i++) {            sum = cuComplexAdd(sum, multiplicationResult[threadIdx.x + i * windowSize / 4]);        }        result[threadIdx.x + windowSize / 4 * blockIdx.x] = sum;    }}cudaError_t cuComplexMultiplyWindow(const cuComplex *data, const float *window, size_t windowSize, cuComplex *result, size_t dataSize, cudaStream_t stream) {    size_t windowStep = windowSize / 4;    cuComplexMultiplyWindowKernel<<<dataSize / windowStep - 3, windowSize, 1024, stream>>>(data, window, windowSize, result);    return cudaGetLastError();}

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


Гребенки были проверены на выходном спектре каналов в реальном времени. На вход AD9371 подавался сигнал генератора сигналов 2450 МГц, селективность фильтров соответствовала расчетной.


image


В планах: адаптация софта на плату XRTX и реализация поиска пакетов, если это кому-нибудь окажется нужно или будет свободное время.


Всю работу по софту выполнил gaudima, слава ему!

Подробнее..

Как я делаю цифровую минигитару

06.09.2020 16:13:36 | Автор: admin
image

В этой статье я постараюсь в общих чертах описать путь создания девайса от идеи до реализации юзабельного прототипа.

Меня зовут Дмитрий Дударев. Я занимаюсь разработкой электроники и очень люблю создавать различные портативные девайсы. Еще я люблю музыку. Полгода назад я взял у друга акустическую гитару чтобы попытаться научиться на ней играть по урокам из ютуба и табулатурам. Было тяжело. То ли я неправильно что-то делал, то ли плохо старался, то ли в обществе моих предков мелкая моторика вредила размножению. В любом случае, ничего кроме звуков дребезжащих струн у меня не выходило. Мое негодование усиливала постоянная расстройка струн. Да и окружающим тысячный раз слушать мою кривую Nothing else matters удовольствия не доставляло.

Но в этих муках про главное правило электронщика я не забыл. Если что-то существует, значит туда можно вставить микроконтроллер. Или, хотя бы, сделать портативную электронную модификацию.


Идея


В голове начала вырисовываться структура цифровой гитары.

Первым делом я составил список требований к девайсу:

  1. Устройство должно имитировать гитару с 6-ю струнами и 12-ю ладами на грифе
  2. Должно быть компактным, в идеале складным, чтобы можно было брать его с собой куда угодно
  3. Должно подключаться ко всем популярным осям Android, IOS, Windows, Linux, MacOS и определяться там как MIDI устройство без каких-либо драйверов
  4. Работа от аккумулятора
  5. Подключение должно производиться без проводов (но раз уж там будет USB разъем для зарядки, то и по проводу пусть тоже подключается)
  6. Возможность сразу начать играть, без необходимости в долгих тренировках по адаптации кистевых связок
  7. На каждой струне и каждом элементе грифа должно быть по светодиоду, чтобы можно было запустить табулатуру мелодии, и гитара сама показывала куда нужно прикладывать руки
  8. Возможность использования основных техник игры на гитаре: hummer on, pull off, slide, vibrato
  9. Задержка передачи midi команд не более 10мс
  10. Все должно собираться из подручных материалов без сложных техпроцессов и дорогой электроники

Разумеется, для мобильных платформ потребуется написать приложение, в котором можно будет выбрать табулатуру для обучения светодиодами, выбрать инструмент (акустика, классика, электрогитара с различными пресетами фильтров, и т.д.), и воспроизводить звуки.

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

Аналоги


Итак, первым делом, вооружившись мыслью о том, что в наше время почти невозможно придумать что-то новое и кто-то уже это делал, иду гуглить. Действительно, оказалось, что первая цифровая гитара была создана еще в 1981 году, но из-за ограниченной функциональности широкого применения не нашла.



Современные компактные midi гитары тоже существуют, но рассчитаны на более профессиональную целевую аудиторию, дорогие и, самое главное, без режима жми на лампочки. Есть даже экзотические варианты с айпадом вместо струн или напоминающее моллюска.



Значит, можно приступать.

Proof of concept


Начать решил с проверкой концепции. Минимальный прототип на скорую руку.
Для начала нужно определиться с элементной базой.

Контроллер

В своих проектах я чаще всего использую STM32. Они мощные, дешевые, доступные. Выбрал STM32F042. В нем есть USB (причем, со специальным внутренним генератором на 48МГц чтобы не вешать внешний кварц), 32-битное ядро, и вся необходимая периферия. И все это при стоимости меньше бакса.

Беспроводное подключение решил оставить на следующую итерацию.

Струны на дэке

В качестве струн решил напечатать пластиковые язычки, закрепить их на потенциометрах с пружинками и измерять углы отклонения.

Замоделил в солиде и напечатал для оценки эргономики.





Получилось довольно приятно на ощупь. Должно работать.

Сенсоры на грифе

На гитаре предполагаются 6 струн и 12 ладов. Суммарно это 72 сенсора на грифе и еще 6 на дэке. Можно было бы использовать на каждый элемент по тактовой кнопке, но, во-первых, они щелкают, во-вторых, не получится реализовать техники вроде slide или vibrato. Хотелось бы еще и усилие нажатия определять.

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



В продаже их найти в нужном количестве оказалось очень сложно, да и стоят немало. Пришлось заказать на али.

АЦП

Для считывания состояния каждого датчика нужен ацп. В STM-ке их всего несколько штук, так что для опроса 78 датчиков понадобится что-то еще. Можно было бы использовать внешние многоканальные ацп микросхемы, но они слишком дорогие. Поэтому я решил поставить 5 дешевых 16-канальных аналоговых мультиплексора CD74HC4067 и подключить к каждому по одному каналу ацп STM-ки.

Плата

Пока едут тензорезисторы, начинаю разводку платы. Выводы датчиков длинные, так что пришлось располагать их внахлест.







Прежде чем заказывать печать платы, решил дождаться тензорезисторов. И, как оказалось, не зря.

Из 80-ти датчиков рабочими оказались только несколько, и то с разными параметрами.



От изображения на сайте продавца они отличаются заметно в худшую сторону.

И чего я ожидал, покупая электронику на али?..

И тут меня осенило.

Можно ведь применить другой метод детектирования измерение емкости как в датчиках прикосновения. Это гораздо дешевле и доступнее. А если правильно спроектировать механику, то можно и усилие определять.

Что ж. Удаляю все что было сделано.



Начинаю сначала


В новой версии минималистичного proof of concept-а в качестве сенсорных элементов я выбрал напиленные из 4мм медного прутка цилиндрики, припаянные к плате.

Теперь нужно придумать как измерять 78 емкостей.

Опрос сенсоров

Немного погуглив, выяснил, что существует множество микросхем контроллеров сенсорных клавиатур. Среди них удалось найти дешевый 12-канальный измеритель емкости общего назначения. Он измеряет емкость в масштабах единиц пикофарад, чего должно быть достаточно для схемы измерения усилия, которую я планирую реализовать в следующих модификациях.
Дополнительно на всякий случай повесил на каждый элемент грифа по посадочному месту для кнопки или чего-то подобного. И сделал вырезы в плате, чтобы можно было не только прикоснуться к цилиндрику, но и прожать его внутрь. Можно будет поэкспериментировать с разными техниками игры.

Микросхема подключается по I2C интерфейсу и имеет 2 конфигурационных пина, задающих адрес. Соответственно, на одну шину можно повесить максимум 4 микросхемы. А мне нужно 12. Не проблема, распределяю их на три группы и подключаю к шине STM-ки через мультиплексор.

Платы





На этот раз плату удалось заказать и даже дождаться ее изготовления.

После запайки комплектухи, медных цилиндриков и потенциометров понял, что конструкция с пластиковыми струнами получается слишком сложной. Поэтому решил пока что повесить на дэку такие же сенсорные цилиндрики, но подлиннее. Чтобы не переделывать всю плату, сделал небольшую платку-накладку и подключил ее ко второй I2C шине STM-ки.



Железяка готова. Следующая задача заставить ее играть.

Софт


План следующий:

  1. Скачать виртуальный синтезатор, который может работать с MIDI устройствами и издавать гитарные звуки.
  2. Написать прошивку, которая будет опрашивать сенсоры и передавать результаты в комп через USB custom HID интерфейс около 100 раз в секунду.
  3. Написать программу на питоне, которая будет принимать эти данные, эмулировать виртуальное MIDI устройство, генерировать MIDI пакеты и отправлять их на виртуальный синтезатор.

Разбираться как сразу прикинуться MIDI устройством решил чуть позже.

Чем воспроизводить звук?

Виртуальных синтезаторов под винду с поддержкой MIDI оказалось довольно много. Я попробовал Ableton live, RealGuitar, FL studio, Kontakt. Остановился на RealGuitar из-за простоты и заточенности именно под гитару. Он даже умеет имитировать несовершенства человеческой игры скольжение пальцев по струнам, рандомизированные параметры извлечения нот.



Подключение к виртуальному синтезатору

Для питона удалось найти библиотеку mido, которая может эмулировать виртуальный midi порт, который через внешний эмулятор midi кабеля loopmidi можно подключить ко входу виртуального синтезатора.



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



Для того, чтобы удары по струнам гитары вызывали проигрывание правильных нот, нужно замапить все 72 сенсора на грифе на соответствующую ноту.

Оказалось, что из 72 элементов на 12-ти ладах всего 37 уникальных нот. Они расположены по определенной структуре, так что удалось вместо построения большой таблицы вывести простое уравнение, которое по номеру сенсора выдает номер соответствующей ноты.



Тест

Похоже, все готово для первого теста. Пилить прутки и паять все 12 ладов мне было лень, поэтому ограничился 8-ю. Момент истины:


ITS ALIVE! Жизнеспособность концепта подтверждена. Счастью не было предела! Но нельзя расслабляться.

Следующий этап добавление светодиодов, акселерометра, вибромотора, аккумулятора, беспроводной связи, корпуса и возможности работы без драйверов или программ эмуляции midi на всех популярных платформах.

Светодиоды

Для подключения 84 светодиодов я выбрал самый простой пусть daisy chain из 14-ти 8-битных сдвиговых регистров. Их удобно подключить к SPI MOSI выводу STM-ки и слать по DMA массив данных без участия ядра.

Акселерометр

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

Беспровод

Для беспроводной передачи данных решил поставить ESP32. Оно поддерживает различные протоколы Bluetooth и WI-FI, будет с чем поэкспериментировать (на тот момент я еще не знал, что в моем случае существует только один правильный способ подключения).

Корпус

Корпус должен быть складным, поэтому электронику дэки и грифа нужно разнести на две платы и соединять их шлейфом.

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

Начинаю работу


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



Я обратился к другу, который профессионально занимается пром дизайном. Мы придумали конструкцию узла сгибания гитары, после чего он спроектировал и напечатал прототип корпуса.



Вроде, все продумано, можно начинать разводку платы.











MIDI устройство

В новой версии, в первую очередь я хотел, чтобы при подключении по USB, гитара определялась как MIDI устройство без всяких лишних программ.

Оказалось, сделать это не так сложно, все спецификации есть на официальном сайте usb.org. Но все алгоритмы, которые выполнялись на стороне питонского приложения, пришлось переписывать на C в контроллер.

Я был удивлен, что оно сразу заработало на всех устройствах. Windows 10, MacOS, Debian 9, Android (через USB переходник). Достаточно просто воткнуть провод и в системе появляется MIDI устройство с названием Sensy и распознается всеми синтезаторами. С айфоном пока протестировать не удалось т.к. нет переходника. Но должно работать так же.



Беспроводной интерфейс

Следующая задача организовать работу без проводов.

Погуглить сразу я поленился, поэтому потратил несколько дней на тестирование различных беспроводных интерфейсов. BLE я отмёл сразу, т.к. в моей голове Low energy прочно ассоциировалось с низкой частотой передачи пакетов. Пробовал WI-FI в режиме клиента, WI-FI в режиме точки доступа, Bluetooth в режиме SPP и т.д. Везде была одна и та же проблема огромная задержка (больше 100мс на глаз) и неравномерность прихода пакетов во времени. Это делало игру невозможной.

Я уже собирался сдаться и сделать отдельный донгл, который бы втыкался в USB мобильника или компа и принимал данные с гитары по кастомному радио.

Но тут я случайно наткнулся на спецификации новых версий протокола BLE и увидел, что минимальный connection interval там 7.5мс, что отлично вписывается в мои требования.

Более того, оказалось, что существует протокол BLE MIDI, который поддерживается всеми новыми операционками и работает без всяких драйверов прямо как по USB MIDI.

Единственной проблемой оказалось то, что такой низкий connection interval и вообще BLE MIDI поддерживаются только относительно новыми платформами. Подробности еще предстоит выяснить, но тесты с доступными мне девайсами прошли успешно.

На некоторых новых айфонах даже имеется предустановленный виртуальный синтезатор Garage Band, способный издавать качественные гитарные звуки (если нет, можно скачать в App Store бесплатно).

Прошивка

Написав весь минимальный необходимый функционал, я уперся ровно в размер флэша STM-ки. Свободными осталось всего 168 байт. Очевидно, кремниевые боги мне благоволили, значит иду в правильном направлении.



Можно было бы углубиться в оптимизацию кода и значительно сократить объем занимаемой памяти, но проще будет в следующей версии использовать контроллер потолще, который стоит на 5 центов дороже и не тратить время. Тем более, мало ли какие еще фичи захочется добавить.
Но минимального функционала недостаточно, нужно еще поработать с техниками игры. В первую очередь, хочу реализовать slide. Это когда начинаешь играть ноту с определенным зажатым ладом и проскальзываешь рукой по грифу, перескакивая с лада на лад.

С USB я уже поразвлекался, поэтому можно весь код, связанный с ним, закомментить и освободить память. Тестировать можно и по беспроводу:


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



Какие минусы у этой конструкции?

  1. На сенсорах нигде не измеряется усилие нажатия. Это влечет за собой три проблемы:
    • Постоянно происходят случайные задевания соседних струн как на дэке, так и на грифе. Это делает игру очень сложной.
    • Все играемые ноты извлекаются с одинаковой громкостью. Большинство подопытных этого не замечают, но хотелось бы более приближенной к настоящей гитаре игры
    • Невозможность использовать техники hammer on, pull off и vibrato
  2. Светодиоды одноцветные. Это ограничивает наглядность при игре по табулатурам. Хочется иметь возможность разными цветами указывать на различные приемы игры.
  3. Форма корпуса не подходит для левшей. С точки зрения софта я уже реализовал инверсию струн по акселерометру. Но механический лепесток, необходимый для удержания гитары рукой во время игры, поворачивается только в сторону, удобную правшам.
  4. Отсутствие упора для ноги. Сейчас, при игре сидя, нижняя струна почти касается ноги, а это неудобно.
  5. Сустав сгибания гитары требует осмысления и доработки. Возможно, он недостаточно надежен и стабилен.

Время переходить к разработке следующей версии.


Переезжаю на контроллер серии STM32F07. На нем уже 128КБ флэша этого хватит на любой функционал. И даже на пасхалки останется.

Использовать ESP32 в финальной версии гитары было бы слишком жирно, поэтому я пошел искать что-то более православное. Выбор нал на NRF52 по критериям доступности, наличию документации и адекватности сайта.

Конечно, будут реализованы и три главных нововведения:

  • светодиоды теперь RGB,
  • на каждом сенсоре грифа будет измерение усилия (тактовые кнопки больше не нужны),
  • струны на дэке станут подвижными.

На данный момент плата дэки выглядит так (футпринт ESP на всякий случай оставил):


Проект называется Sensy и сейчас находится в активной разработке. Уже есть полная уверенность в том, что весь задуманный функционал будет реализован, поэтому было принято решение о дальнейшем развитии.

Мы находимся в Питере, сейчас команда состоит из двух человек: я занимаюсь технической частью, мой партнер маркетингом, финансами, юридическими вопросами.

Если среди читателей есть джедаи в области проектирования корпусов или мобильной разработки, желающие присоединиться к проекту пожалуйста, пишите мне куда и когда угодно.

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

Очень надеюсь на обратную связь от Хабрасообщества с комментариями и предложениями!

Забавный эпизод из процесса разработки
Сижу отлаживаю NRF52, пытаюсь вывести данные через UART. Ничего не выходит. Проверял код, пайку, даже перепаивал чип, ничего не помогает.

И тут случайно нестандартным способом перезагружаю плату в терминал приходит буква N в ascii. Это соответствует числу 0x4E, которое я не отправлял. Перезагружаю еще раз приходит буква O. Странно. Может быть проблема с кварцевым резонатором и сбился baud rate? Меняю частоту в терминале, перезагружаю плату опять приходит N. С каждой новой перезагрузкой приходит по новой букве, которые в итоге составляют повторяющуюся по кругу фразу NON GENUINE DEVICE FOUND.

Что эта NRF-ка себе позволяет? Прошивку я обнулял. Как она после перезагрузки вообще помнит, что отправлялось в предыдущий раз? Это было похоже на какой-то спиритический сеанс. Может, я и есть тот самый NON GENUINE DEVICE?

Залез в гугл, выяснил, что производители ftdi микросхем, которые стоят в USB-UART донглах, придумали способ бороться с китайскими подделками. Виндовый драйвер проверяет оригинальность микросхемы и на лету подменяет приходящие данные на эту фразу в случае, если она поддельная. Очевидно, мой донгл оказался подделкой и переход на другой решил эту проблему.

Снова спасибо китайцам.

Спасибо за внимание!
Подробнее..

Фитнес-трекер для скейта

08.02.2021 02:17:53 | Автор: admin
Прототипы на микроконтроллерах nRF52 (в WLCSP корпусе, чем я только думал?), NXP QN9080 и STM32WB55. Ничего не бывает с первого раза, эти ревизии работали лишь частично.Прототипы на микроконтроллерах nRF52 (в WLCSP корпусе, чем я только думал?), NXP QN9080 и STM32WB55. Ничего не бывает с первого раза, эти ревизии работали лишь частично.

Основная идея

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

Целью нашего девайса будет определение качества и количества сделанных трюков. Потом эти данные можно собрать в статистику и инфографику и отобразить в мобильном приложении, где можно будет отслеживать свой прогресс и делиться им с друзьями. Устройство должно крепиться на сам скейтборд. Так проще определять, что с ним происходит.

Грубо говоря, большинство трюков это некое изменение пространственного положения доски с ходом времени и по определённому сценарию. Для отслеживания движений можно использовать MEMS-датчики и компас. Для скейт-трюков это необходимое, но не достаточное условие, но чисто теоретически, самые базовые элементы типа ollie и kickflip с их помощью можно определять.

Что-то подобное уже существует?

Мне удалось нагуглить только два похожих проекта, но статус обоих превращает эту часть статьи в небольшой некролог.

RideBlock (c) IGGRideBlock (c) IGG

1) RideBlock. Проект скейтборд-трекера с мобильным приложением. Использует IMU (9DoF) для сбора данных. Был запущен в инкубаторе в Лос-Анджелесе 4-5 лет назад, в 2017 году не собрал нужную сумму на Indiegogo, с тех пор признаков жизни не подаёт.

Syrmo (c) DigitalTrendsSyrmo (c) DigitalTrends

2) Syrmo. Аналогичный проект из Долины, с более удачным местом установки на подвеске. Размещение сбоку под осью уберегает устройство от возможных ударов и не препятствует выполнению ряда трюков. Для измерения высоты прыжков использует высокоточный барометр, для остального - 6DoF IMU. Последние новости о проекте датируются 2015 годом.

Провалились ли эти проекты? Я считаю, что да.

Почему? Трудно сказать, ведь никто из их создателей не делился публично тем, что же пошло не так.

Можно предположить, что:

  • Целевая аудитория (скейтеры) не захотели тратить деньги на устройство к скейту, когда на эту же сумму можно купить новую доску или кеды, ведь у скейтеров это дорогой расходный материал, который нужен всегда

  • Возникли какие-то непреодолимые трудности в реализации идеи. Вдруг в принципе невозможно при текущем развитии технологий добиться желаемого результата в точности определения трюков или в качестве полученных данных?

  • Не хватило капитала на реализацию идеи: денежного либо человеческого

  • Оба проекта были мошенничеством в том или ином виде и служили лишь целью быстрого получения денег

Лично я настроен оптимистично и не имею никакого давления со стороны (инвесторы, зарплаты сотрудников), так как проект некоммерческий и делается в свободное время, быть может это позволит ему остаться на плаву?

Скейт-трюки

Дальше по тексту на глаза могут попасться названия трюков, которые могут быть не знакомы тем из читателей, кто не катается или не играл в THPS или Skate 3. Под спойлером небольшой раздел с илюстрацией трюков.

Скейтборд-ликбез

Хотя катание на скейте и несёт в себе креативный и развлекательный аспекты, некая система всё же присутствует. Известные трюки имеют устоявшиеся названия, вот самые базовые из них (в исполнении вашего покорного слуги):

Kickflip
Доска в прыжке совершает полный оборот вокруг продольной оси с помощью носка ноги, как будто её пинают. Отсюда и слово kick в названииДоска в прыжке совершает полный оборот вокруг продольной оси с помощью носка ноги, как будто её пинают. Отсюда и слово kick в названии
Heelflip
Доска в прыжке делает полный оборот вокруг продольной оси с помощью пятки, в сторону противоположную kickflip-у, отсюда и heel в названииДоска в прыжке делает полный оборот вокруг продольной оси с помощью пятки, в сторону противоположную kickflip-у, отсюда и heel в названии
Pop shove-it
Доска вращается в воздухе по горизонтальной оси на 180 с помощью задней ногиДоска вращается в воздухе по горизонтальной оси на 180 с помощью задней ноги

Беря во внимание основную идею, можем сформулировать базовые требования к устройству.

Требования к железу

  • Компактность. На скейтборде не так много места, куда можно было бы закрепить устройство так, чтобы оно не пострадало

  • Питание от батареи. Батарея должна быть перезаряжаемая и компактная, но достаточной ёмкости, чтобы протянуть минимум одну типичную скейт-сессию (у меня это 2-3 часа)

  • Необходимые датчики: акселерометр, гироскоп, магнитометр и др.

  • Наличие беспроводной связи. Так как устройство призвано генерировать много данных, нужен удобный способ эти данные получить

  • Минимальный пользовательский интерфейс помимо беспроводного. Например, парочка светодиодов и кнопка. Нам не нужен черный ящик

  • (Желательно) Водонепроницаемость, вибро- и ударостойкость. Трюки получаются не всегда с первой попытки и доска может упасть, сильно и много раз удариться о землю. На асфальте так же могут быть лужи, грязь и влага, которые могут навредить электронике устройства

  • (Желательно) Отделяемый блок батареи, чтобы не заряжать доску

Требования к прошивке

Сформулируем некий минимум того, что мы хотим от прошивки устройства:

  • Опрос датчиков и сбор данных. Собираем и обрабатываем данные с гироскопа, акселерометра, и т.д.

  • Обеспечение работы BLE, формирование пакетов данных

  • Отслеживание состояния и уровня заряда батареи. Общаемся с контроллером заряда, оцениваем когда батарея заряжена и сколько осталось заряда

  • Обеспечение низкого энергопотребления. Что не нужно в данный момент выключаем, что нужно, но не часто регулируем частоту срабатываний

  • Индикация и взаимодействие с пользователем. Реагируем на кнопку, сообщаем о текущем состоянии и нештатных ситуациях

Подбираем компоненты

В этом разделе рассмотрим самые ключевые компоненты, не беря во внимание мелочь типа пассивных компонентов, кнопок или разъемов.

Микроконтроллер

Сердцем устройства должен стать шустрый, но малоопотребляющий микроконтроллер. Из-за требований к компактности, хочется, чтобы этот чип был системой на кристалле со встроенным радио.

Выбирал между:

  1. Nordic Semi nRF52x зарекомендовавшие себя на рынке системы на кристалле с Cortex-M4F и отличной поддержкой BLE/Bluetooth 5. Преимущества этих чипов известны: очень продуманная и простая в использовании периферия, возможность назначать её на любые выводы, что освобождает руки при разводке платы. Проверенная временем экосистема драйверов, документации и примеров. В том числе и на языке Rust.

  2. ST STM32WBx5 относительная новинка на рынке беспроводных SoC.

STM32WB55 в QFN-48 корпусеSTM32WB55 в QFN-48 корпусе

Отличительные особенности:
1) Два ядра: Cortex-M4F как основное и Cortex-M0+ как ядро для радио-стека
2) Периферия унаследована от STM32L4, можно переиспользовать код и опыт
3) Высокочастотный кварц можно подключать без нагрузочных конденсаторов, они встроены в чип
4) Есть поддержка USB, у Nordic она только в самом продвинутом nRF52840 и супер-новом двухъядерном (2 x Cortex-M33) nRF5340

Изначально выбрал Nordic, но как только в широкой продаже появился STM32WB, решил попробовать его. В отличие от нордика, под STM32 чип не было экосистемы драйверов и библиотек и пришлось написать свои1,2 и получить тонну опыта. Собственно, ради нового опыта я этот чип и выбрал, хотя и nRF52 всем устраивает.

Помимо этих двух чипов, довелось попробовать в работе чип NXP QN908x. Это довольно интересный чип с уникальными фишками типа встроенного сопроцессора (FSP) для sensor fusion и машинного обучения, USB, встроенных конденсаторов для кварцев, подключения внешней FLASH-памяти по (Q)SPI. Было дело, что я даже развёл и спаял плату под этот чип. Но столкнулся с сырой документацией и примерами, странными багами с отладочной платой и, видимо, отсутствие опыта с чипами NXP дало о себе знать.

Решил ставить STM32WB55. Сперва в исполнении с 1 МБ FLASH и 512 КБ RAM. Затем можно будет оптимизировать размер памяти.

Инерциальные датчики (IMU)

Здесь я решил пойти простым путем и взять что-то компактное и дающее нужные данные из коробки.

Изначально выбор пал на Bosch Sensortec BNO055. Это SiP из акселерометра, гироскопа и магнитометра, а также Cortex-M0+ микроконтроллера. Чип идёт с проприетарной прошивкой, которая обеспечивает опрос датчиков и sensor fusion, что позволяет сильно разгрузить основной микроконтроллер. При этом размеры корпуса 5.2 x 3.8 мм. В ходе работы над драйвером обнаружился ряд несовершенств прошивки этого чипа (например, медленная скорость обновления данных либо кривые углы Эйлера после fusion-а).

Чип BNO08x на типичной breakout-платеЧип BNO08x на типичной breakout-плате

Затем вышел более новый Hillcrest/CEVA BNO08x на базе того же железа, что и BNO055, но с более совершенной прошивкой и я решил использовать уже его. Разница между BNO080 и BNO085 лишь в версии прошивки, идущей в чипе.

Отдельно стоит упомянуть InvenSense/TDK ICM-20948, преемника очень популярного MPU9250 (который ныне NRND). Чип с хорошими характеристиками и тоже имеет встроенный sensor fusion (Motion Engine), но документация на него очень непрозрачная либо под NDA, что для хобби-проекта неприемлемо.

Поэтому ставим BNO08x, даже если это может быть немного оверкилл.

Контроллер питания, заряда батареи

Девайс будет работать от батареи. При этом хотелось бы, чтобы устройство:

  1. Заряжало литиевую батарею

  2. Мгновенно переключалось между источниками питания: от шнура при зарядке и от батареи, когда шнур отключен (power path selection)

  3. Отслеживало, сколько в батарее осталось заряда (gas gauge)

  4. Включало-выключало элементы схемы по команде главного контроллера

  5. Обладало режимами вкл/выкл

  6. Имело один или несколько преобразователей напряжения для питания остальных частей

Все желаемые функции так или иначе можно сделать из дискретных компонентов: микросхем заряда, gas gauge чипов, регуляторов напряжения, watchdog-чипов с кнопкой, транзисторов. Но из-за требований к компактности, идеальным вариантом было бы получить все перечисленные возможности, добавив лишь одну микросхему. И такие варианты есть, они входят в категорию микросхем под названием PMIC.

Что предлагает рынок?

Перечислим то, что удалось найти под наши требования. В скобках число реализуемых конкретным чипом желаемых возможностей.

  1. AMS AS3701 PP, 1 DC/DC, 2 LDO, WLCSP-20, charger, GPIO и кнопка (5/6)

  2. Maxim MAX20353 PP, 3 DC/DC, 2 LDO, корпус WLP-56, charger, gas gauge, GPIO, кнопка (6/6)

  3. Dialog DA9070 PP, 1 DC/DC, 3 LDO, WLCSP-42, charger, gas gauge (ADC), watchdog и кнопка (6/6)

  4. TI TPS6572x PP, 1 DC/DC, 1 LDO, WQFN-32, DSBGA-25, charger, GPIO и кнопка (4/6)

  5. Qorvo (Active Semi) ACT81460 PP, 4 DC/DC, 3 LDO, 1 HVB, WLCSP-49, charger, 4 GPIO, кнопка (5/6)

  6. Microchip MCP73871 PP, QFN-20, charger. Просто маленький зарядник + power path контроллер (2/6)

  7. X-Powers AXP173 PP, 2 DC/DC, 4 LDO, QFN-32, charger, кнопка, gas gauge (6/6)

AXP173, QFN-32AXP173, QFN-32

Из массы имеющихся вариантов, я сделал довольно странный, но по-итогу вполне логичный выбор это китайский чип X-Powers AXP173. Это оказался единственный чип, который включает всё что нужно и при этом представлен в QFN-корпусе. Наличие такого корпуса важно по причине требований к ударостойкости самого устройства, корпусы типа BGA/WLCSP известны низкой стойкостью к ударам и подверженностью возникновения трещин в шариках.

И это только если не задумываться о том, что WLCSP-корпуса с шагом 0.4/0.5мм сильно повышают требования к печатной плате, а также требуют инспекции во время производства (например, просвет рентгеном).

После гугл-перевода китайского даташита, оказалось вполне понятно как с AXP173 работать по I2C шине, был написан драйвер (Rust). Микросхему легко достать и в Китае она стоит мало, проблем с ней не возникало. Кстати, чипы этой фирмы используются почти во всех устройствах на базе решений Allwinner (планшеты, одноплатник Banana Pi и т.п.).

Хоть чип и предлагает несколько DC/DC, для экономии пространства на плате я ограничился использованием лишь трёх LDO: два на главный микроконтроллер и один на IMU.

Все LDO и DC/DC преобразователи позволяют регулировать их выходное напряжение через соответствующие регистры. Чип имеет несколько встроенных АЦП для измерения напряжения батареи, протекающего в/из батареи тока, интегратор тока (coulomb counter), который помогает отслеживать уровень заряда. Чип так же можно использовать с кнопкой, и настраивать реакцию на короткое и длинное нажатие. Например, выключать или включать устройство по длинному нажатию. На каждое нажатие кнопки чип выдаёт прерывание и указывает в одном из регистров, какое было нажатие. Выдаются прерывания и по началу/окончанию зарядки, подключению/отключению зарядного устройства и много чему ещё.

Ставим AXP173.

Батарея

За батареями можно ходить на Aliexpress, я заказывал максимально приближенный к размерам будущей платы литиевый элемент 301430 на 120 mAh.

Фото батареи
Батарея 3мм х 14 мм х 30мм на 120 мАчБатарея 3мм х 14 мм х 30мм на 120 мАч

Радио

Следуя рекомендациям для STM32WB55 мы берём чип-фильтр гармоник ST MLPF-WB55-01E3:

2.4GHz фильтр MLPF-WB55-01E32.4GHz фильтр MLPF-WB55-01E3

Простоты ради я решил так же использовать маленькую и проверенную чип-антенну Johanson 2450AT18B100:

Чип-антенна на 2.4GHz 2450AT18B100Чип-антенна на 2.4GHz 2450AT18B100

SoC имеет встроенный балун, поэтому он нам не нужен.

Светодиоды

В текущей ревизии устройства два светодиода:

  1. Светодиод-чип желтого цвета American Bright BL-HKC37A-AV-TRB размера 0402 для индикации процесса зарядки. Он подключается напрямую к PMIC AXP173 и управляется ею же

  2. Маленький чип RGB-светодиода 1x1mm Foshan NationStar FC-B1010RGBT-HG. Подключается к микроконтроллеру и используется для отладки и индикации процесса работы

Пожалуй, самый миниатюрный RGB-светодиод 1х1мм, FC-B1010RGBT-HG. Фото от LCSCПожалуй, самый миниатюрный RGB-светодиод 1х1мм, FC-B1010RGBT-HG. Фото от LCSC

Схемотехника

Теперь мы можем сформировать целостную картину основных блоков устройства:

Система-на-кристалле STM32WB5x отвечает за BLE связь и управляет по двум разным IC шинам контроллером питания (PMIC) и инерциальными датчиками (IMU). Светодиоды и кнопка образуют минимальный интерфейс для взаимодействия с устройством, а USB порт позволяет заряжать батарею и, например, обновлять прошивку, загружать лог данныхСистема-на-кристалле STM32WB5x отвечает за BLE связь и управляет по двум разным IC шинам контроллером питания (PMIC) и инерциальными датчиками (IMU). Светодиоды и кнопка образуют минимальный интерфейс для взаимодействия с устройством, а USB порт позволяет заряжать батарею и, например, обновлять прошивку, загружать лог данных

Пройдёмся по основным блокам схемы, рассмотрев интересные на мой взгляд детали. На момент написания статьи была актуальна ревизия C (третья).

Схема рисовалась в онлайн-EDA Upverter (by Altium), ссылка на дизайн.

USB-порт, питание, батарея

Схема подсистемы питанияСхема подсистемы питания

На схеме видно, что MicroUSB-порт (J3) и батарея (J2) подключены к PMIC AXP173 (U3).

Выходы регуляторов напряжения LDO1 и LDO2 через сдвоенный диод Шоттки питают основной микроконтроллер. Диоды нужны, чтобы оба LDO не перетягивали друг на друга одеяло и регулировали только свой выход.

Почему вообще два LDO на один чип? Чтобы обеспечить достаточный ток, так как LDO1 очень маломощный и рекомендуется производителем только для питания домена RTC. При этом LDO1 включен вообще всегда, а LDO2 включается программно, но почти сразу же.

LDO3 питает IMU и по-умолчанию выключен. Его будем включать только когда нужны данные с датчиков.

Кнопка не требует подтягивающего резистора, потому что подтяжка встроена в чип. Остальные компоненты подключены по даташиту и общим рекомендациям.

IMU

Схема подключения инерциальных датчиков (IMU)Схема подключения инерциальных датчиков (IMU)

BNO08x (U2) питается от VCC_IMU и сидит на I2C шине (IMU_SCL, IMU_SDA). Также стоит внешний кварц на 32.768 Гц (Y3) с нагрузочными конденсаторами (C17, C18) на 22 пФ.

В основном всё подключено по даташиту, но стоит резистор-перемычка R26 для тестирования работы чипа с внешним кварцем и без. На случай, если внешний кварц по каким-то причинам не заведётся, можно будет выбрать режим без него. Спойлер: кварц завёлся без проблем. DNP означает, что этот резистор не должен быть запаян по-умолчанию.

От IMU микроконтроллер через I2C шину получает данные, а кроме этого есть линия запроса на прерывание IMU_INT. По отдельным линиям микроконтроллер также управляет сбросом чипа и режимом входа в загрузчик, если вдруг когда-нибудь можно будет обновлять прошивку чипа IMU (такая возможность есть, но она под NDA).

BNO08x поддерживает подключение дополнительных сенсоров типа барометра или датчика освещённости по собственной шине I2C, на которой он будет выступать ведущим. Эти сенсоры нам не нужны, поэтому просто подтягиваем линии внешнего I2C согласно даташиту.

Отдельно на схеме стоят также подтяжки (R21, R22) для I2C шины, на которой висит IMU. Эти подтяжки подключены к питанию IMU и неактивны (не потребляют ток) когда IMU обесточен путём отключения LDO3 PMIC, который питает VCC_IMU. Отключая подтяжки вместе с чипом, мы экономим некоторую часть общего бюджета энергопотребления.

Почему для обмена данными с IMU выбрана шина I2C вместо гораздо более быстрой SPI? Всё просто: сэкономил ножки микроконтроллера. Две (SCL, SDA) против четырёх (MOSI, MISO, nCS, CLK). Микроконтроллер, чип IMU и подтяжки на 4.7 кОм позволяют шине I2C разгоняться до 400 кГц без особых проблем.

Теперь перейдём к мозгу устройства.

Микроконтроллер, радио, DC/DC (SMPS), внешние подтяжки I2C

Мозг устройстваМозг устройства

Обвязка микроконтроллера STM32WB55 (U1) согласно даташиту. Благодаря встроенным нагрузочным конденсаторам, кварцевый резонатор на 32 МГц Y2 подключается напрямую к чипу. В то время как низкочастотный кварц Y1 на 32.768 Гц подключается с нагрузочными конденсаторами на 12 пФ.

В плане подключения 2.4 GHz антенны для BLE всё тривиально, никаких диаграмм Смита пока не потребовалось. Антенна ANT1 подключена через фильтр FL1. Выход SoC RF1, фильтр и антенна рассчитаны на импеданс 50 Ом, поэтому согласующая цепь не применяется, достаточно соединить всё напрямую.

L1, L2, C1 внешние элементы для встроенного DC/DC преобразователя SMPS. Его использование позволяет снизить энергопотребление SoC при работающем радио и получить более чистое питание, уменьшив шум.

Подтяжки для шины I2C (R2, R3), к которой подключен PMIC, не подключаются сразу к линии питания. Вместо этого они подключены к выходу SoC I2C_PULLUPS. Подтяжки включаются только при подаче на этот выход высокого лог. уровня и выключаются при переводе выхода в High-Z (высокоимпедансное, третье) состояние. Таким образом подтягивающие резисторы не потребляют энергию когда не нужны.

После того как схема более-менее готова, можно переходить к разводке платы. Как правило, два этих процесса взаимосвязаны и влияют друг на друга. Плата разводится по схеме, а схема изменяется под возможности разводки платы.

Разводка платы

Так выглядит трассировка одного из сигналов в UpverterТак выглядит трассировка одного из сигналов в Upverter

Разводка платы точно так же выполнялась в EDA Upverter. В основном я использовал готовые футпринты компонентов из встроенной в Upverter библиотеки на базе Octopart, но для парочки деталей приходилось редактировать футпринт либо рисовать свой.

Процесс

Обычно я развожу платы по примерно такому плану:

  1. Рисуем желаемую форму и задаём габариты платы

  2. Задаём нужные слои, у нас их точно будет 4: верхний, земля, питание, нижний. Такой четырёхслойный стек является рекомендуемым1,2 для плат с RF, при этом слой земли должен быть следующим после слоя, на котором будет разведена RF часть. Кроме этого, работать с 4 слоями удобнее, особенно когда это касается подключения питания компонентов. Когда два внутренних слоя выделены для питания и земли, для запитывания чипов часто достаточно просто поставить переходное отверстие на соответствующий слой

  3. Задаём автоматические правила проверки (DRC) согласно возможностям выбранного производителя плат (у меня это PCBWay): 5/5 mil (0.127 мм) проводник/зазор, 10 mil (0.254 мм) ширина отверстия, 4 mil внешнее кольцо переходного отверстия. При этом это минимально допустимые правила. Для большей надёжности я ставлю по-умолчанию минимальные размер дорожки и зазор в 6 mil (0.1524 мм)

  4. Расставляем монтажные отверстия для крепления платы в корпусе. Лучше сделать это в самом начале, чем потом, когда места под них уже не останется

  5. Расставляем те компоненты, которые точно должны быть с краю платы: разъёмы и антенну

  6. Ставим на плату все микросхемы (U1 U3) и их обвязку и двигаем-вращаем их, пока:

    1. Не станет как можно меньше пересечений воздушных линий (ratsnest) между компонентами. Это уменьшает число переходов на другие слои и в целом даёт идею об оптимальности взаимного расположения

    2. Длина воздушных линий не станет минимальной (это уменьшает длину печатных проводников и помогает сэкономить площадь платы)

  7. Расставляем/двигаем обвязочные компоненты по ходу разводки

  8. Соединяем все цепи проводниками, заливаем полигон на слое земли. Сеть питания можно разводить на выделенном слое, желательно для линий питания использовать топологию звезда

  9. Cтараемся держать все SMD компоненты на одном слое платы. Это позволит удешевить автоматический монтаж, потому что pick-and-place автомат сможет расставить все компоненты за один подход

Результат

Разводку удалось уместить в 35 х 15 мм, что вполне удовлетворяет нашим требованиям к компактности.

Скриншот платы (без полигонов, вид сверху)

Для наглядности, разметил топологию основных блоков после разводки:

Как обычно, тратим минимум несколько дней на сверку с даташитом/референсами и поиск ошибок, после чего можно переходить к генерированию файлов для отправки на производство.

Заказ производства

В этот раз получается не совсем своими руками я решил заказать производство плат вместе с монтажом компонентов. Чтобы сэкономить время и нервы, а заодно и попробовать что-то новое.

Для производства плат и поверхностного монтажа я выбрал сервис PCBWay по рекомендации знакомых.

Подготовка

Для производства устройств нужен следующий набор файлов:

  • Gerber-файлы, содержащие рисунок платы + drill файл с координатами отверстий

  • BOM, т.е. список компонентов с точным артикулом (part number) детали, количеством

  • XYRS-файл (centroid), содержащий координаты центра и ориентацию всех монтируемых компонентов

В Upverter есть специальный раздел для экспорта этих файлов, заходим туда и скачиваем. Все файлы, кроме BOM, не требуют никакой обработки и готовы к отправке. А вот BOM нужно будет подогнать под стандартный формат (.xlsx), предлагаемый PCBWay.

Пример BOM в формате PCBWay

В каждой строке количество деталей идёт в расчёте на одно устройство. При закупке компонентов это количество сотрудники PCBWay умножат на число собираемых устройств.

Заказываем платы

Заходим на сайт PCBWay и переходим в раздел Quote & Order. Там вводим основные параметры платы:

  • Режим Всё Включено (Turnkey): платы, трафареты, закупка, монтаж, всё делают они

  • Размер: 35 х 15 мм

  • Сторона монтажа SMD-компонентов: только верх

  • Количество плат: 5 (это минимум плат в заказе, сам монтаж можно сделать и на меньшем количестве)

  • Число слоёв: 4

  • Цвет паяльной маски: чёрный

  • Финиш поверхностей: HASL со свинцом (хороший вариант когда не надо самому паять)

Остальные параметры я оставил по-умолчанию.

Загружаем герберы, указываем, какой файл отвечает за какой слой, загружаем сверловку и XYRS, загружаем BOM. Отправляем и ждём ответа.

Через некоторое время в личном кабинете статус заказа меняется на In Audit и если всё хорошо, то заказ переходит в Audit Passed и начинается производство плат. Одновременно с этим на почту пишет сотрудник компании и уточняет наличие позиций в BOM, примерное время ожидания доставки компонента. Таблица дополняется столбцом стоимости каждой позиции умноженной на число устройств, а так же итоговой стоимостью компонентов. На этом этапе можно заменить отсутствующие на складе детали на аналоги, чтобы сократить время ожидания. Так же можно попросить специалиста подобрать компонент запросами типа поставьте самый дешевый светодиод 0402 желтого цвета или самый доступный кварц в этом корпусе с точностью 50 ppm.

По моему опыту, проходит несколько рабочих дней от отправки файлов до первого email с уточнениями по BOM.

Производство

Хорошим признаком того, что всё идёт хорошо является тишина. Если производитель больше ничего не пишет, значит процесс идёт и проблем не возникло. Сам процесс можно отслеживать поэтапно в личном кабинете:

Каждый шаг производства плат показан либо зелёным, когда он завершен, либо серым, если он в процессе или к нему ещё не приступили. Такая же картина наблюдается и при монтаже компонентовКаждый шаг производства плат показан либо зелёным, когда он завершен, либо серым, если он в процессе или к нему ещё не приступили. Такая же картина наблюдается и при монтаже компонентов

Когда производитель смонтировал самую первую плату (я так понял, что они делают это поштучно, а не панелями), наступает час Икс, когда на почту приходит письмо с фотографиями готовой платы и просьбой внимательно посмотреть и указать на недочёты:

Предварительная плата выглядела вполне себе ничего:

Точно лучше, чем если бы я паял вручнуюТочно лучше, чем если бы я паял вручную

Фото платы в более высоком разрешении: клик.

У производителя возник вопрос по поводу полярности футпринта RGB-светодиода, ведь у них не было схемы, чтобы сверить, только герберы:

Фото светодиода с предположением о полярности

Сравнив со схемой я подтвердил, что всё верно и дал зелёный свет. Возможно, что данный вопрос бы не возник, если бы я удосужился разместить на шелкографии ключ компонента либо оставил полярность где-то в заметках, которые можно приложить к файлам.

Доставка

Доставляют по заранее указанному при заказе адресу выбранной службой. Можно изменить адрес доставки в любое время. Например, если успел переехать на другой адрес пока шло производство (у меня так было). Если цена доставки при этом становится выше, то просят доплатить.

До адреса в России фирмой EMS посылка шла где-то неделю.

Фото посылки я не делал, но сделал фото того, что оказалось внутри:

Одно из пяти готовых устройств я уже подключил для тестов. К устройствам также приложили подарок: 5 таких же плат, но без компонентовОдно из пяти готовых устройств я уже подключил для тестов. К устройствам также приложили подарок: 5 таких же плат, но без компонентов

Экономика и цены

Удовольствие не из дешёвых, но затраты компенсируются огромной экономией времени и нервов. Вот, что получилось у меня (курс доллара на 2021 год):

  • Платы: 5 штук за $97 (7,200 ) в сумме

  • Монтаж: 5 устройств за $186 (13,800 ) в сумме. При стоимости монтажа в $30 (2,238 ), львиная доля стоимости это компоненты:

    • SoC: $11.5 x 5 = $55.75 (4,160 ) за 5 штук

    • IMU: $11.9 x 5 = $59.85 (4,466 ) за 5 штук

    • USB разъем molex: $1.2 x 5 = $6.3 (470 )

    • Цены остальных компонентов меркнут по сравнению с первой тройкой

  • Доставка EMS: $28 (2,000 )

Очевидно, что есть куда удешевлять. Вот некоторые идеи и low-hanging fruit по снижению стоимости:

  • Взять менее тонкий техпроцесс плат, наприме 6/6 mil вместо 5/5 mil, взять стандартный цвет маски (зелёный)

  • Снижение оверкиллов в дизайне: использовать младшие модели SoC с меньшим объемом памяти и периферией. Взять более дешевый IMU BNO080 вместо BNO085

  • Использовать USB разъем подешевле

Прошивка и софт

Hello, world!Hello, world!

Что-ж, вот железо лежит на столе, подключенное к программатору и ждёт, когда в него вдохнут жизнь.

Приступив к программной части, я сформулировал следующий план действий:

  1. Язык прошивки будет Rust. Исключительно на нём я пишу последние годы и уже порядком подзабыл Си, да и возвращаться к нему после раста совсем не хочется

  2. Надо собрать в кучу или дописать драйверы для периферии, BLE-стека, IMU и PMIC

  3. Помигать светодиодом

  4. Написать простую прошивку, которая будет включать IMU и слать рассчитанные им кватернионы текущего положения устройства через последовательный порт

  5. Написать программу для визуализации кватернионов положения

  6. Написать прошивку посложнее, которая будет слать все данные с IMU через BLE

  7. Написать программу на ПК для опроса по BLE и адаптировать визуализацию, добавив графики

Сбор данных

Хотелось как можно скорее прицепить девайс к доске хоть на скотч и приступить к сбору данных. Для этого сперва надо сориентировать оси IMU относительно скейтборда и выбрать, где расположить устройство:

Ориентация осей относительно скейтборда и желаемое положение устройства под доскойОриентация осей относительно скейтборда и желаемое положение устройства под доской

Как только минимально рабочий софт был готов, я примотал устройство к нужному месту на подвеске доски и отправился в скейт-парк.

Мне удалось добиться стабильной передачи данных по BLE с частотой 15 Гц через характеристику с оповещением (Notify), несущую пакет данных из 20 байт. Если пытаться выставить частоту обновления выше, то перестаёт выдаваться прерывание от радио-сопроцессора. Особо глубоко пока не копал, но предполагаю, что боттлнеком является процедура обновления характеристики где-то в BLE стеке, работающем на сопроцессоре. Есть идея, например, в одно обновление характеристики упаковывать несколько пакетов, два или три за раз. Это нужно только на этапе сбора данных. В дальнейшем, все основные расчёты планируется вести на самом устройстве, поэтому канал BLE будет существенно разгружен.

Больше всего боялся, что устройство сразу же вырубится после первого же прыжка из-за тряски или удара, но обошлось:

Делаю Ollie, данные регистрируются с частотой где-то 15 ГцДелаю Ollie, данные регистрируются с частотой где-то 15 Гц

На графике акселерометра (слева снизу) видно, когда доска отрывается от земли и когда она приземляется. Значительно возрастает ускорение по вертикальной оси Z (зелёная). Используя эти данные и время, можно придумать алгоритм расчета высоты прыжка. На графике справа показаны данные с гироскопа. Т.к. при ollie значительных вращений вокруг осей не происходит, график гироскопа здесь выглядит скучновато.

Heelflip. Из-за вращения доски график гироскопа выглядит интереснее. Из-за низкого FPS визуализации, кажется, что доска не сделала полный оборот вдоль оси Y, но на видео он был, а также на гироскопе видно, что вращение точно было.Heelflip. Из-за вращения доски график гироскопа выглядит интереснее. Из-за низкого FPS визуализации, кажется, что доска не сделала полный оборот вдоль оси Y, но на видео он был, а также на гироскопе видно, что вращение точно было.Ещё пример
Постоянное вращение показано на графике гироскопа как ровная линия выше нуля, при этом на акселерометре по оси X видно значительное ускорение (но со знаком минус)Постоянное вращение показано на графике гироскопа как ровная линия выше нуля, при этом на акселерометре по оси X видно значительное ускорение (но со знаком минус)

Для определения трюков с вращениями очень полезны данные с гироскопа. Прекрасно видно, вокруг каких осей, как быстро и на сколько градусов вращается доска.

Например, kickflip это +360 вдоль оси Y, а heelflip это -360. Меняем знаки местами если стойка скейтера меняется с regular на goofy. А pop shove-it будет выглядеть как вращение на 180 вдоль оси Z.

Заключение

За кадром этого поста остались детали разработки прошивки, поскольку она пока далека от завершения и может ещё много раз измениться кардинально. Более подробно я могу рассказать про код прошивки и ПО для ПК в следующем посте. Сейчас же ссылки на весь код можно найти в разделе ссылок в конце поста.

Полдела сделано и идея проверку проходит, осталось самое сложное довести проект до конца. Вот некоторые планы на будущее (так сказать, roadmap):

  • Корпус! Пожалуй, это самая сложная часть проекта и источник прокрастинации для меня. Но корпус придётся делать, не приматывать же устройство скотчем каждый раз

  • Собрать ещё больше примеров данных с более высокой частотой, дабы иметь представление о тех вещах, которых не видно при 15 Гц дискретизации

  • Обратиться к литературе по алгоритмам определения высоты по акселерометру, машинному обучению и классификации по данным с IMU, например: 1, 2, 3, 4

  • Выполнять расчёты на самом устройстве, по BLE передавать лишь результаты

  • Оптимизация энергопотребления устройства

  • Мобильное приложение

  • Подумать над влаго- и ударо- защитой устройства. Это скорее относится к корпусу, но и с точки зрения электроники тоже можно попытаться на что-то повлиять. На ум приходит conformal coating платы, убрать, где возможно кварцевые, резонаторы, водонепроницаемый разъем для зарядки

Спасибо за внимание, с нетерпением жду ваших вопросов и комментариев!

Ссылки

  1. Репозиторий с кодом прошивки, программ и документация

  2. Схема и разводка платы на Upverter

Подробнее..

Как я делаю цифровую минигитару. Часть 2

08.03.2021 14:16:44 | Автор: admin

Прошло 4 месяца с написания предыдущей статьи, за это время произошло довольно много нового как по технической части, так и по позиционированию девайса.

Напомню какие требования к девайсу я поставил, когда начинал разработку:

  • Устройство должно имитировать гитару с 6-ю струнами и 12-ю ладами на грифе

  • Должно быть компактным, в идеале складным, чтобы можно было брать его с собой куда угодно

  • Должно подключаться ко всем популярным осям Android, IOS, Windows, Linux, MacOS и определяться там как MIDI устройство без каких-либо драйверов

  • Работа от аккумулятора

  • Подключение должно производиться без проводов по Bluetooth Low Energy (но раз уж там будет USB разъем для зарядки, то и по проводу пусть тоже подключается)

  • Возможность сразу начать играть, без необходимости в долгих тренировках по адаптации кистевых связок

  • На каждой струне и каждом элементе грифа должно быть по светодиоду, чтобы можно было запустить табулатуру мелодии, и гитара сама показывала куда нужно прикладывать руки

  • Возможность использования основных техник игры на гитаре: hummer on, pull off, slide, vibrato

  • Задержка передачи midi команд не более 10мс

  • Все должно собираться из подручных материалов без сложных техпроцессов и дорогой электроники

Реализовать мне все это удалось, и даже больше. Был дополнительно интегрирован акселерометр для управления параметрами фильтрации звука наклоном гитары и вибромотор (правда, я до сих пор не придумал зачем).

На момент написания предыдущей статьи выглядело оно так:

Было принято решение пытаться делать стартап и выходить на кикстартер.

И так, что было дальше?

Следующим шагом стал стандартный этап поиска pre-seed раунда инвестирования. Деньги нужны были на доработку и изготовление нового прототипа, проведения пиар кампании и оплату юридических манипуляций (для участия на кикстартере необходимо юр. лицо в США со всеми вытекающими организационными тратами). Эту задачу нам с моим партнером, отвечающим за бизнес процессы, удалось решить за 2 месяца.

Позиционирование

Для подтверждения полезности продукта и его функционала мы решили провести встречи со всеми Питерскими и Московскими музыкантами, с которыми смогли связаться, и заодно поснимать видеороликов для соц сетей.

Профессиональные гитаристы отнеслись к девайсу ожидаемо скептически. И я их полностью понимаю, это не замена настоящей полноценной гитаре. Это девайс для применений, в которых важны портативность, универсальность, простота, возможность играть в наушниках и т.д. Сидишь, например, в самолете, вокруг шум, суета, плачущие дети, кислородные маски выпадают. Спать невозможно. И тут внезапно наступает вдохновение, достаешь девайс, надеваешь наушники и записываешь новый трек.

Широкой публикой гитара была оценена очень позитивно не смотря на пока что ограниченный функционал и большие конструктивные неудобства. Девайс оказался настолько интересным, что даже популярный в рунете блогер Ваганыч снял на него обзор.

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

Конкуренты

Есть на этом рынке и конкуренты. Мы купили по экземпляру каждого для оценки.

1. Artiphon - панель, чувствительная к нажатию, по форме напоминает гитару, но позиционируется скорее как настольная клавиатура.

Интересная, но дорогая штука. В целом, работает неплохо, можно извлекать разнообразные звуки. Имеет встроенные динамики, но лучше их не включать. Подключается только по USB.

2. Jammy - гитарный форм-фактор, состоит из разъединяющихся элементов с реальными струнами. Датчики независимо отслеживают удары по струнам на деке и прикосновение струны к ладу на грифе. Знакомым гитаристам не удалось сыграть на ней что-то внятное - ноты то не извлекались, то извлекались по нескольку раз. Возможно, требуется длительное привыкание. На реальных роликах в интернете также не удалось найти полноценной гитарной игры, в основном это игра медленным перебором по отдельным струнам.

3. Jamtik - игрушка с 7-ю ладами на батарейках. Сыграть на ней не удалось даже В траве сидел кузнечик.

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

Теперь самое интересное новый прототип.

На основе испытаний старого прототипа, конкурентов и личных предпочтений, я решил расширить функционал девайса и добавить несколько пунктов к требованиям:

  • Конечно, RGB подсветка

  • Подвижные струны на деке с детектированием как касания, так и величины отклонения при извлечении ноты. Это позволит избавиться от проблемы задевания пальцами соседних струн и расширит возможности игры за счет поддержки velocity (разные параметры нарастания звука и громкости ноты) и глушения струн прикосновениями как в настоящей гитаре

  • Детектирование силы нажатия на сенсоры грифа для реализации стандартных гитарных техник игры

  • Встроенный синтезатор со встроенной библиотекой инструментов и разъем Jack 3.5мм для подключения наушников или внешних колонок. Встроенные динамики делать не стал добиться хорошего звучания было бы слишком сложно и дорого

  • Мобильное приложение со встроенным качественным синтезатором и функционалом обучения

  • Пады с подсветкой для записи лупов

  • Упоры на деке и удобного удержания сидя и стоя, крепления для ремешка

Корпус

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

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

Электроника

Электронику пришлось разделить на 4 платы:

  • Гриф

Адресные RGB светодиоды подключены последовательно к одной ноге STM-ки. Пришлось повозиться с двойной буферизацией и выводом данных через DMA 100 раз в секунду. Зато, теперь оно работает очень быстро и можно запускать цветные визуальные анимации на поверхности грифа.

  • Плата с падами и подпружиненными контактами для соединения с грифом в разложенном состоянии гитары

  • Основная плата со струнами, мозгами, силовой частью, радио частью, синтезатором и датчиками

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

  • Плата с разъемами USB type-C, Jack 3.5мм и тремя индикаторными светодиодами

Мобильное приложение

После выкладывания предыдущей статьи, мне написал мобильный разработчик Юрий Дубовой с предложением помочь в разработке приложения под iOS.

Мы сформировали протокол общения гитары с приложением и разбили его на несколько интерфейсов:

  • Midi команды, разумеется, по умолчанию передаются по стандартному BLE-Midi интерфейсу. Таким образом, к приложению при желании можно будет подключить и другие midi устройства, например, клавиатуру

  • Опционально поддерживается прием midi команд и по проводному USB-Midi интерфейсу. Это будет полезно для старых телефонов без поддержки BLE, а также в случае необходимости сокращения задержки до минимума (порядка 5мс)

  • Отдельный кастомный BLE сервис для передачи уникальных команд, связанных с управлением светодиодами, режимами работы девайса, синхронизацией состояния и т.д.

  • Стандартный BLE battery service для передачи уровня заряда аккумулятора. Он поддерживается на уровне операционной системы и, в случае в виндой, даже отображается соответствующая иконка в панели устройств

Приложение разбито на несколько экранов, соответствующих разным режимам работы:

Свободная игра

В этом режиме пользователь выбирает один из инструментов (акустика, электрогитара, пианино, укулеле, барабаны, и т.д.) и просто играет как ему хочется. Есть возможность загружать свои инструменты в виде саундфонтов в формате .sf2.

Игра по табулатурам

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

Обучение

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

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

Теперь играть на ней можно тремя разными способами:

  1. Подключение через BLE MIDI протокол к телефону или компу, где девайс распознается как миди устройство, и игра через внешние виртуальные синтезаторы (Ableton, FL studio, Garage Band и т.д. или наше приложение)

  2. То же самое, но с подключением через USB MIDI (работает со всеми хостами, которые я проверял Android, IOS, Windows, MacOS, Debian)

  3. Игра внутренним синтезатором, с подключением наушников или внешней колонки напрямую в гитару. В этом случае звук будет не самым Hi-Fi, но вполне приемлемым для игры для себя

Интересно, что можно играть всеми тремя способами одновременно, может кому-то пригодится.

Завершение

После завершения изготовления корпуса и тестирования нового прототипа я планирую написать следующую статью, в которой будет больше технических подробностей. Если среди читателей Хабра есть люди, желающие поучаствовать в создании контента, поделиться предложениями или помочь с продвижением пожалуйста, пишите мне. А также будем рады помощи с изготовлением корпуса и разработкой мобильного приложения.

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

Спасибо за внимание! Буду рад обратной связи в комментариях.

Подробнее..

BLE шлюз из Xiaomi Gateway DGNWG05LM без BLE

26.03.2021 20:17:43 | Автор: admin

(eu version lumi.gateway.mieu01)

В этом посте я расскажу как можно собирать данные BLE и передавать через MQTT в системы умного дома, например в HomeAssistant.

Как все начиналось?

Эта история началась в прошлом году: у меня появился несколько таких шлюзов. В то время было несколько статей по получению root доступа, интеграции miio в HA и по прошивке чистого openwrt на шлюз. Толчком к развитию стал сезон распродаж в разных магазинах, где стоимость шлюза стремилась к нулю, и многие энтузиасты получили интересную железку.

Первым большим делом для меня было заставить работать zigbee2mqtt с чипом и прошивкой находящимся в шлюзе. И пока я допиливал интеграцию в zigbee-herdsman, ребята в чатике @xiaomi_gw_hack занимались добавлением поддержки в openwrt периферии, которая была в шлюзе (светодиоды RGB, динамик, датчик света, wi-fi модуль).

Отдельное спасибо @lenz1986, @Alx2000y, @belokobylskiy!

Было обнаружено, что в wifi модуле rtl8723bs европейской версии шлюза есть встроенный bluetooth с поддержкой BLE.

Но в стоковой системе на шлюзе нет никаких следов bluetooth. И лишних uart, по которому можно было бы с ним работать тоже. @lenz1986 провел раскопки

Несколько плат очень помогли разобраться в внутреннем мире шлюзаНесколько плат очень помогли разобраться в внутреннем мире шлюзаВот как плата выглядит без процессора )Вот как плата выглядит без процессора )

Он вызвонил контакты, и обнаружил что на плате разведены все 4 UART от процессора. Один из которых вел на uart от bluetooth части модуля wifi rtl8723bs. Потом он добавил поддержку этого uart в DTB, где описываются вся периферия устройства для openwrt и нашел подходящие драйвера. За что @lenz1986 огромное спасибо!

модуля

Внимание! Все действия я описываю и делаю на базе openwrt прошивки для шлюза. Установить ее можно по воздуху просто подключившись по uart к шлюзу. (спасибо @divanikus)

Подробнее описано на https://openlumi.github.io/

Bluetooth инициализируется через rtk_hciattach при запуске шлюза. После загрузки мы получаем такую картину hciconfig

Я знаю 2 пути, как можно включить bluetooth адаптер.

  • Руками hciconfig hci0 up

  • изменив параметр AutoEnableконфиге /etc/bluetooth/main.confна true

Я выбираю второй. Интерфейс запущен. Для проверки можно запустить скан hcitool lescan

Работа с BLE

Мои знания по BLE были на нуле, и чтобы было проще разобраться я искал что-то готовое по типу zigbee2mqtt. Перепробовал несколько решений на Node.Js, в том числе пакеты для node-red. Остановился на проекте EspruinoHub. (хоть и код там не супер современен и технологичен, но зато работает)

После запуска с отсылкой данных в локальный mqtt сервер, в CLI и web интерфейсе уже показались распарсенные данные с части датчиков LYWSDCGQ (круглые гигротермографы) .

Раньше я их слушал на esp32 через esphome. Небольшое сравнение получаемых данных с одного термометра.Раньше я их слушал на esp32 через esphome. Небольшое сравнение получаемых данных с одного термометра.

Это меня порадовало, но у меня было еще несколько устройств, данные от которых я увидел почти в raw виде. И я решил использовать эту программу и немного улучшить ее.

пример cli интерфейса с статусом доступных устройствпример cli интерфейса с статусом доступных устройств

Многие устройства Xiaomi с bluetooth шлет BLE Advertising Packet, в большинстве случаев в нем содержится полезная нагрузка в виде измерений, которые производит устройство. Часто данные отправляются открыто, но используется шифрование с ключом.

Например для браслета MiBand данные выглядят вот так. Если есть данные о пульсе то они добавляются в конец

В устройствах xiaomi, часто используется BLE сервис fe95. В интернете есть небольшая документация по нему .На github есть множество проектов которые умеют парсить эти данные. На основе этих данных и существующей реализации espruino я немного улучшил парсинг открытых данных, но потом я нашел более красивое решение из hannseman/homebridge-mi-hygrothermograph. Мне особенно понравилась стандартизация разных событий и расшифровка исходя из данных заголовка.

Этот парсер закрыл вопрос с большинством устройств Xiaomi, отправляющих данные в fe95. Можно еще попробовать добавить некоторые типы событий (движение, дым, нажатие на кнопку), но у меня нет таких устройств под рукой.

Я добавил в EspruinoHub данный парсер, и реализовал возможность указать настройки для разных устройств. Это необходимо для устройств, которые шифруют с помощью bindKey свои пакеты. Получить bindKey можно из miHome.

MQTT Discovery - Home Assistant

Данных стало больше, но хотелось чтобы они автоматически появлялись в HomeAssistant. EspruinoHub отправляет данные которые и слышит в эфире, и не имеет на данный момент привязки к конкретным устройствам. Поэтому в момент появления данных, если они из списка поддерживаемых отправляется config устройства в топик homeassistant в mqtt и устройства появляются в системе умного дома

Добавленные и протестированные устройства.

В результате изучения разных решений и raw сообщений от устройств удалось добавить или улучшить интеграцию следующих устройств в пассивном режиме (только слушаем эфир не подключаемся к устройствам и не тратим батарейку).

LYWSDCGQ - работал "из коробки". Добавил только mqtt discovery в HA

показания перепоказания пере

LYWSD02 - температура, влажность и батарейка


Самый бюджетный датчик температуры и влажности с экраном LYWSD03MMC - температура, влажность и батарейка (нужен bindKey). Существует 2 альтернативные прошивки, они очень крутые и продвинутые. Особенно от Виктора pvvx. Рекомендую использовать именно ее. Помимо лучшего потребления она шлет данные в одном пакете, а не в трёх и имеет множество настроек.


MI SCALE - 181d v1 По крупицам из разных источников допилена реализация в которой показываются данные о - стабилизации веса (весы моргают) - убрали вес (встали с весов) - дата и время измерения. 181b v2 Работает, но не тестировал лично. Возможно нужно что-то допилить


Mi band 3 fee0 Шаги и Пульс в режиме тренировки. Чтобы браслет отправлял данные необходимо включить обнаружение в MiFit.

Как оказалось шлюз очень хорошо и далеко слышит, а эта функция включена у многих людей. Работает это и для других моделей и даже на некоторых часах например Amazfit GTS


HHCCJCY01 MiFlora, Huahuacaocao - temperature, moisture, illuminance, conductivity, battery_level

Другие устройства тоже можно попробовать подключить. Если они шлют в кодированном виде, то в mqtt об этом будет ошибка с просьбой указать bindKey в конфиг.

YEERC - я обнаружил что прошивка для esp32 tasmota сообщает, что поддерживает данный пульт. Он идет в комплекте с многими люстрами YEELIGHT, но к сожалению у меня не получилось нигде найти как получить 32 символьный bindKey для него. Сообщения нажатий я вижу, но не могу расшифровать. (Значение event закодировано и зависит от counter который увеличивается с каждым нажатием) Возможно кто-то из читателей подскажет как добыть данный ключик. Пульт можно привязать к нескольким люстрам в разное время и они будут вместе расшифровывать и отрабатывать нажатия. Скорей всего ключ там не изменяется со временем или привязкой.

Как установить EspruinoHub на шлюз Xiaomi с OpenWrt ?

Можно установить и на другие устройства с помощью git / npm, инструкция на странице проекта EspruinoHub

Установка

Мои последние наработки собраны в пакет и ставятся с помощью opkg

Необходимо подключить фид по инструкции https://openlumi.github.io/openwrt-packages/

Дальше установить собранный пакет.

opkg updateopkg install node-espruinohub

Конфигурирование

По-умолчанию он будет пытаться подключиться к локальному mqtt без авторизации. Если вы хотите подключить к внешнему брокеру mqtt, то нужно изменить конфиг в /etc/espurinohub/config.json

Внимание! у некоторых настроек в начале стоят слеши чтобы они не применялись. (конфиг в этом проекте частично сделан как пример и я не стал ничего менять)

Пример конфига можно посмотреть тут. Если вы знаете мак адреса своих устройств то рекомендую их прописать и установить"only_known_devices": true, чтобы не отправлялись данные с чужих устройств из эфира.

Для работы с HomeAssistant достаточно отправлять данные в json формате, а остальное можно выключить. По умолчанию будет отправлять в топики с группировкой по типу данных.

"mqtt_format_json": true,"homeassistant": true,"mqtt_cache_state": true

Планы

Отслеживание носимых устройств по rssi между комнатами. Для этого в конфиг я добавил возможность указать минимальный rssi в разрезе устройства и таймаут присутствия.

данные с устройств летят достаточно часто если они в зоне прямой видимости.данные с устройств летят достаточно часто если они в зоне прямой видимости.

Активные подключения: хочу попробовать управлять некоторыми устройствами по BLE, но для одновременного подключения и сканирования Bluetooth модуль и ПО могут работать нестабильно. Поэтому я пока только изучаю этот вопрос.

Альтернативные opensource проекты работающие с BLE на шлюзе

  • devbis/ble2mqtt - своя реализация на python через bleak, умеет подключаться к чайникам, но сильно грузит процессор.

  • Beetle-II/lumi - тот же парсер из hannseman/homebridge-mi-hygrothermograph, но без возможности задать индивидуальный ключ bindKey для устройства. Нет raw данных и управление через mqtt. + Умеет работать не только с BLE.

Заключение

Спасибо, что дочитали до конца!

Если у Вас есть вопросы, то можете задавать их в комментариях.

Подробнее..

Становление термостата Lytko 101 что из этого вышло

04.11.2020 16:22:09 | Автор: admin
Ровно год назад на суд общественности был представлен разработанный нами термостат: умный термостат Lytko 101.

Статья, посвященная ему, в то время получила широкий оклик среди аудитории, интересующийся домашней автоматизацией и просто неравнодушных; и в данном материале мы хотим актуализировать информацию о нашем продукте, рассказать как он эволюционировал за это время и какой был пройден путь нами. Но обо всём по порядку. Надеемся, вам будет интересно, начнем!

image



Схемотехника


Термостат по прежнему представляет собой сендвич из трех компонентов: нижняя силовая плата, умная верхняя плата и тач-монитор (старый знакомый Nextion 2.4). В будущем мы хотим заменить монитор: ведем работы по созданию аналогичного дисплейного модуля, но с емкостным тачскрином. Данная модернизация не повлияет на конечную стоимость: не увеличит ее, но, к сожалению, и затраты на производство также сокращены не будут. Выиграют пользователи перспективный дисплей более отзывчив по сравнению с резистивным Nextion.
Также мы разработали без экранную версию термостата. Отличие лишь в итоговой стоимости и возможности скрытой установки в подрозетник.

Всё это позволяет установить наш термостат вместо большинства термостатов сторонних производителей, которые используют аналоговый датчик представленного номинала (об этом ниже).

Силовая часть без изменений, всё на своих местах:
БП AC-DC 5В 700мА, реле TE Connectivity (RT314005) 16А
image

image

А вот мозг термостата, как аппаратная, так и его программная часть, подверглась куда более основательному пересмотру.

image

1 минорное изменение: отказались от встроенного датчика температуры ds18b20, место под него осталось, при необходимости установка diy не должна составить труда;
2 разъем для подключения монитора Nextion.
3 разъем для будущего монитора (на изображении не установлен) приверженцы DIY смогут им воспользоваться в полной мере;
4 посадочное место для радио-модуля сс2530 (е18);
5 разъем для подключения провода программирования (на изображении ниже).
С его помощью владелец может поменять ПО на любое другое, совместимое с платформой. Ранние версии предусматривали лишь место под пайку, сейчас же перепрошивать устройство не составит труда.



Watchdog (аппаратный) для обеспечения максимальной надежности перезапустит устройство, если что-то пошло нет так. Прежнюю перемычку джампер для его активации сменил аналоговый ключ управления и кнопка.

В целях оптимизации места модуль ESP8266 был перенесен на нижнюю сторону платы. Радио-модуль nRF24L был заменен на модуль cc2530 (e18), что в будущем позволит использовать термостат в сетях ZigBee.

Ранее примененный механизм для соединения верхнего и нижнего яруса в единое целое (изображение 1), к сожалению, показал себя не с лучшей стороны отмечен его неприемлемо низкий ресурс на эти самые соединения рассоединения. Мы заменили его на более надежный (изображение 2).


Изображение 1


Изображение 2

Программная составляющая


В прошивку с поддержкой MQTT мы добавили экспериментальную функцию в виде нативной поддержки протокола Apple HomeKit. В дальнейшем мы планируем получить сертификат MFI и сделать полноценную поддержку Apple HomeKit.

Опытная прошивка HomeKit делает интеграцию термостата в экосистему умного дома под управлением Apple прозрачной и простой. Настраивать и управлять устройством вы сможете, используя как его сенсорный экран или web-интерфейс, так и родное Apple приложение Дом.

В фирменной версии MQTT общение с остальным миром умных вещей ведётся по MQTT протоколу через MQTT-брокера, что открывает возможности для интеграции практически с любыми системами, представленными на рынке (MajorDoMo!, Home Assistant и т.п.). В целом характеризуется более гибкими настройками, позволяет настраивать сценарии.

Переключиться между этими двумя версиями пользователь может в любой момент с помощью web-интерфейса.

Опишем все возможности обстоятельнее


Была переработана механика взаимодействия и дизайн интерфейса для встроенного в термостат тачскрин монитора. В основу лег опыт эксплуатации пользователей, их запросы. В том числе очень помогли комментарии под статьей (еще раз спасибо!) и предложения по улучшению интерфейса в нашей группе Телеграмм. Web-сайту тоже досталось.

Так выглядела главная страница в старой версии


Теперь она выглядит так:



Сделаем обзор всех настроек термостата.

Старый интерфейс




Новый интерфейс

Вы можете:
  1. Выставить гистерезис и настроить корректировку температуры сенсора (сдвиг в большую или меньшую сторону +- 5.0 градусов с шагом 0.5);
  2. Изменить тип сенсора (цифровой ds18b20 или аналоговый доступного номинала);
  3. Включить или выключить защиту от детей (блокировка дисплея);
  4. Обновить прошивку термостата Over-the-air (по воздуху);
  5. В разделе Отладочная информация выводятся данные для разработчиков: количество свободной оперативной памяти, прошедшее с момента включения время и текущий режим работы контроллера термостата;
  6. При необходимости задать иную конфигурацию устройства произвести сброс настроек.


Кроме того, Вы можете настроить пороговые значения температуры: минимально и максимально допустимые значения. На данный момент диапазон регулируется от 7 до 75 градусов, но в дальнейшем мы увеличим верхний порог до 90 градусов. Это позволит использовать термостат для управления котлом отопления. Эти значения задаются только в момент первоначальной конфигурации. В случае необходимости их изменения понадобится сбросить устройство и заново настроить параметры.



Мы постоянно расширяем список поддерживаемых аналоговых датчиков температуры, и на данный момент он выглядит так:
  1. 3.3 кОм,
  2. 5 кОм,
  3. 6.8 кОм,
  4. 10 кОм,
  5. 12 кОм,
  6. 14.8 кОм,
  7. 15 кОм,
  8. 20 кОм,
  9. 33 кОм,
  10. 47 кОм.

Само собой, поддержка цифрового датчика ds18b20 сохранилась (он выбран по умолчанию).





Web-страница позволяет произвести все вышеперечисленные настройки. Кроме того:
  • подключиться к MQTT-брокеру;
  • посмотреть описание топиков для управления устройством;
  • обновить устройство с Сервера, либо загрузить файл прошивки вручную;
  • сменить режим работы с MQTT на HomeKit и обратно;
  • переподключить устройство к другой сети Wi-Fi.




Подготовка к работе


Данные для подключения к точке доступа ESP закодированы в qr-code, демонстрируемом на экране при первом включении (на версии с экраном). Просто отсканируйте его своим смартфоном и согласитесь с предложением подключится к AP термостата. В версии без экрана понадобится подключиться к точке доступа Lytko-xxxx вручную.



После подключения к сети и первоначальной конфигурации на Вашем смартфоне устройство готово к работе. Всё.

Обратная связь


Помимо предложений по улучшению интерфейса термостата, нам также поступают идеи для расширения функционала устройства: что если установить тот же самый термостат для управления бойлером? По просьбе одного из участников нашей группы в Телеграм мы добавили в прошивку поддержку бойлера, увеличив верхний порог температуры, до которого контроллер позволяет нагревать подключенное устройство.

При первом запуске понадобится выставить максимальную температуру до необходимого уровня в момент первоначальной конфигурации.

Коллега подключил термостат к бойлеру ГВС и написал об этом статью.

Достижения


Наш термостат теперь в телевизоре, точнее, в объективе. На YouTube-канале Электроника в объективе вышло видео о нашем продукте. Команда Lytko благодарна автору за обстоятельный обзор устройства и емкое демонстрирование функционала. Мы учли высказанную автором критику и работаем над исправлением всех недочетов.

В обзоре представлено две модели: обычный теплый пол* и сухой контакт.
*хотя термостат этой версии также может использоваться вместе с бойлером, а некоторые из наших пользователей смогли сконфигурировать его для управления клапанами на радиаторах. Пока что только через проводной сенсор, но мы разрабатываем и варианты получения температуры извне: с помощью BLE-датчика, ZigBee-датчика или внешнего датчика MQTT.
P.S. мы не останавливаемся на достигнутом и подготовили новую версию устройства с ESP32 на борту. Испытания скоро начнутся.



Подробнее..

Перевод Bluetooth Low Energy подробный гайд для начинающих

10.12.2020 12:12:32 | Автор: admin

Создание кастомного сервиса и тем более клиента Bluetooth Low Energy прогулка по граблям с завязанными глазами. По крайне мере так было для меня 4 года назад, когда я только начинал работать с BLE-устройствами. Сейчас почти каждый мой проект предусматривает использование этого протокола, поэтому в свое время пришлось в нем долго и мучительно разбираться.

Разложить все по полкам помогла книга Мохаммада Афане "Intro to Bluetooth Low Energy" и серия постов на Novel Bits. Лично для меня эта книга стала настоящим открытием. Изначально я делал ее перевод на русский для своих коллег, не имеющим опыт работы с BLE. С согласия автора (огромное ему спасибо) решил опубликовать свою работу здесь. Надеюсь, перевод окажется полезным.

Это первая часть перевода (всего их будет 5), которая рассказывает, что такое BLE, ее возможности и отличия от Bluetooth Classic и описывает архитектуру протокола.

Об авторе

Мохаммад Афане занимается разработкой встроенного программного обеспечения и прошивок с 2006 года. Он работал и консультировал множество крупных компаний, включая такие как Allegion (Schlage locks), Motorola, Technicolor, Audiovox, и Denon & Marantz Group. На протяжении всей своей карьеры он работал над множеством проектов Интернета Вещей, включая: беспроводные электронные дверные замки, спутниковые приемники, беспроводные дверные замки и т.д.

В июле 2015 года он принял решение прекратить работу на полную ставку для того, чтобы основать собственную компанию Novel Bits, LLC, где он делится своими знаниями и опытом на своем web-сайте, локальных тренингах и в электронных книгах, посвященных разработке приложений с поддержкой Bluetooth Low Energy.

Вы можете связаться с Мохаммадом по его электронной почте: mohammad@novelbits.io или через профиль на LinkedIn.

Базовые понятия Bluetooth Low Energy

1. Что такое Bluetooth Low Energy?

Bluetooth был задуман как технология связи ближнего диапазона, призванная заменить провода в таких устройствах, как компьютерные мыши, клавиатуры или персональные компьютеры. Если у вас есть современный автомобиль или смартфон, то скорее всего вы использовали Bluetooth хотя бы раз в своей жизни. Он повсюду: в громкоговорителях и колонках, беспроводных наушниках, автомобилях, носимых устройствах и даже в шлёпанцах!

Первая официальная версия стандарта была выпущена компанией Ericsson в 1994 году. Разработчики назвали свое изобретение в честь короля Дании Харальда Гормссона по прозвищу Синезубый, объединившего в 10 веке враждовавшие датские племена в единое королевство.

В настоящее время существует два типа устройств с поддержкой Bluetooth:

  • Bluetooth Classic (BR/EDR), используется в беспроводных громкоговорителях, автомобильных информационно-развлекательных системах и наушниках;

  • Bluetooth Low Energy (BLE), т.е. Bluetooth с низким энергопотреблением, который появился в версии стандарта Bluetooth 4.0. Он чаще всего применяется в приложениях, чувствительных к энергопотреблению (например в устройствах с батарейным питанием) или в устройствах, передающих небольшие объемы данных с большими перерывами между передачами (например, разнообразные сенсоры параметров окружающей среды или управляющие устройства, такие как беспроводные выключатели).

Эти два типа устройств несовместимы друг с другом, даже если они выпущены под одним брендом или спецификацией. Устройства с поддержкой Bluetooth Classic не могут напрямую связываться с устройствами, использующими BLE. Это причина, по которой некоторые устройства, такие как смартфоны, выполняются с поддержкой обоих типов соединения (так называемые Dual mode Bluetooth devices), что позволяет им обмениваться информацией с обоими типами устройств.

Рис.1: Типы Bluetooth-устройствРис.1: Типы Bluetooth-устройств

Несколько важных замечаний о BLE:

  • Официальная спецификация Bluetooth сочетает оба типа Bluetooth (Classic и BLE), что иногда затрудняет поиск документации, специфичной для BLE;

  • BLE был введен в версии 4.0 спецификации стандарта Bluetooth, выпущенной в 2010 году;

  • BLE иногда называют Bluetooth Smart, BTLE или Bluetooth 4.0, что является ошибкой, так как эта версия в действительности включает оба типа Bluetooth;

  • Bluetooth Classic и BLE работают в одном и том же частотном диапазоне 2.4 ГГц, ISM-диапазон.

Поскольку во многих устройствах Интернета Вещей (IoT) используются небольшие устройства и датчики, BLE стал наиболее часто используемым протоколом связи (в сравнении с Bluetooth Classic) в приложениях Интернета Вещей. В декабре 2016 года группа компаний Bluetooth Special Interest Group (SIG), регулирующая развитие стандарта, выпустила Bluetooth версии 5.0 (для простоты маркетинга была убрана точка из названия, так что официально он называется Bluetooth 5). Большинство улучшений и новых функций, представленных в этой версии, были ориентированы на BLE, а не на Bluetooth Classic.

Вы также могли слышать о другом термине, связанном с Bluetooth Bluetooth Mesh. Bluetooth Mesh был выпущен в июле 2017 года и основан на BLE. Для работы ему требуется полный стек BLE (ПО, которое действует как интерфейс для другого программного или аппаратного обеспечения), но он не является частью основной спецификации Bluetooth. Мы рассмотрим более подробно эту технологию в отдельной главе.

Подводя итог, посмотрим на диаграмму, показывающую прогресс BLE за прошедшие годы с начала его появления:

Рис.2: История BLEРис.2: История BLE

Технические факты о BLE

Некоторые из наиболее важных технических фактов о BLE включают в себя:

  • Используемый частотный диапазон 2.400 - 2.4835 ГГц.

  • Весь частотный диапазон поделен на 40 каналов по 2 МГц каждый.

  • Максимальная скорость передачи данных по радиоканалу (начиная с Bluetooth версии 5) 2Мбит/с.

  • Дальность передачи сильно зависит от физического окружения, а также используемого режима передачи. Например, в режиме большой дальности передачи дальность связи будет выше, а скорость передачи ниже, чем в высокоскоростном режиме. Типичная дальность передачи: 10-30 метров.

  • Потребление электроэнергии также может изменяться в широких пределах. Оно зависит от реализации устройства, различных параметров протокола и используемого чипсета. Типичное потребление BLE-трансивера во время передачи данных как правило не превышает 15 мА.

  • Обеспечение безопасности не обязательно при обмене данными через BLE и зависит от устройства и реализации приложения разработчиком. Другими словами, существует несколько возможных для реализации уровней обеспечения безопасности.

  • Для всех операций, связанных с шифрованием, BLE использует алгоритм AES-CCM с длиной ключа 128 бит.

  • BLE предназначен для передачи данных по каналу с низкой пропускной способностью. Использование BLE для приложений с большим объемом часто передаваемых данных существенно увеличивает потребление электроэнергии и сводит на нет основное преимущество BLE. То есть минимизация использования радиосвязи, насколько это возможно, позволяет достичь минимального уровня потребления энергии.

  • Версии Bluetooth (в части BLE) являются обратно совместимыми. Тем не менее возможности связи будут ограничены функциями более старой версии. Например, устройство с поддержкой Bluetooth 5 LE может установить связь с устройством с поддержкой Bluetooth 4.1 LE, но возможности, появившиеся в версии 4.2 и более новых, будут недоступны. В то же время они смогут использовать возможности подключения, рассылки и приема широковещательных пакетов, обнаруживать сервисы и характеристики, а также читать и записывать их независимо от поддерживаемой ими версии стандарта, так как эти возможности доступны во всех версиях Bluetooth.

Сравнение Bluetooth Classic и BLE

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

Некоторые из упомянутых различий представлены в этой таблице:

Таблица 1. Сравнение Bluetooth Classic и BLE

Bluetooth Classic

BLE

Используется для потоковых приложений, таких как трансляция аудио и передача файлов

Используется в сенсорах, управлении устройствами и приложениях, не требующих передачи больших объемов данных

Не оптимизирован для низкого энергопотребления, но поддерживает большую скорость передачи (максимум 3 МБит/с, в то время как BLE 5 имеет максимум 2 МБит/с)

Предназначен для применения в малопотребляющих устройствах с большими интервалами между передачей данных

Использует 79 радиоканалов

Использует 40 радиоканалов

Обнаружение происходит на 32 каналах

Обнаружение происходит на 3 каналах, что приводит к более быстрому обнаружению и установке соединения по сравнению с Bluetooth Classic

С момента официального выпуска в 2010 году BLE прошел череду ревизий и изменений. Наиболее важное изменение произошло в декабре 2016 года с внедрением Bluetooth 5, который привнес множество важных улучшений в спецификацию стандарта, большинство из которых касалось BLE. Эти улучшения позволили удвоить скорость передачи, в 4 раза увеличить дальность передачи и в 8 раз увеличить размер широковещательного пакета.

Возможности и ограничения BLE

Каждая технология имеет свои ограничения, и BLE не является исключением. Как мы упомянули ранее, BLE наилучшим образом подходит для приложений с небольшим радиусом передачи и редко передаваемыми небольшими объемами данных.

4.1. Ограничения BLE

Пропускная способность

Пропускная способность BLE ограничена физической пропускной способностью радиоканала, т.е. скоростью, с которой данные передаются по радиоканалу. Пропускная способность зависит от используемой версии Bluetooth. Для Bluetooth 4.2 и более ранних, доступна только пропускная способность в 1 Мбит/с. В Bluetooth 5 и более поздних версиях пропускная способность зависит от выбранного режима PHY (Physical Layer, рассматривается в разделе физического уровня). Она может составлять 1 Мбит/с как в более ранних версиях или 2 Мбит/с при использовании высокоскоростной передачи. При использовании функции дальней связи пропускная способность ограничена значениями 500 или 125 Мбит/с. Мы обсудим это более подробно в главе, посвященной Bluetooth 5.

Скорость передачи с точки зрения конечного пользователя всегда будет ниже скорости передачи по радиоканалу в силу следующих факторов:

  • Промежутки между пакетами данных: спецификация Bluetooth определяет зазор в 150 микросекунд между передаваемыми пакетами как требование для соблюдения спецификации. В этот промежуток времени невозможна передача данных между устройствами.

  • Служебная информация внутри пакета: каждый пакет содержит помимо полезной нагрузки заголовок и служебные данные, обрабатываемые на уровнях ниже уровня приложения. Они учитываются при передаче данных, но не используются вашим приложением.

  • Требование на передачу служебной информации периферийным устройством: спецификация требует обязательного ответа ведомого устройства на каждый пакет, переданный ведущим. В случае, когда необходимая для передачи информация отсутствует, передается пустой пакет.

  • Переотправка пакетов данных: в случае потери пакета или перекрестных помех от находящихся поблизости устройств, потерянные или поврежденные данные отправляются заново.

Дальность передачи

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

  • На передачу в ISM-диапазоне 2.4 ГГц сильно влияют окружающие нас препятствия, такие как металлические предметы, бетонные стены, вода и человеческие тела.

  • Диаграмма направленности и коэффициент усиления антенны.

  • Корпус устройства, в котором находится антенна, также ухудшает характеристики антенны.

  • Ориентация устройства в пространстве, от которого зависит ориентация антенны, например в смартфонах.

Потребность в шлюзе для интернет-соединения

Для передачи данных с устройства, поддерживающего только BLE-соединение, необходимо другое устройство с поддержкой как BLE, так и IP-соединения. Именно оно будет получать данные и отправлять их в интернет.

4.2 Преимущества BLE

Даже с учетом представленных выше ограничений BLE имеет некоторые существенные преимущества перед другими аналогичными технологиями передачи данных для IoT.

Вот некоторые из них:

  • Меньшее энергопотребление;

По сравнению с другими низкопотребляющими технологиями передачи данных, BLE потребляет гораздо меньше электроэнергии. Это достигается благодаря глубокой оптимизации протокола, выключению передатчика при первой возможности и пересылке малых объемов данных на низкой скорости.

  • Бесплатный доступ к официальным спецификациям;

Чтобы получить доступ к спецификациям большинства других протоколов вы должны стать членом официальной группы или консорциума по этому стандарту. Стать членом можно за внушительную сумму (от 7500 до 35000 долларов в год). В случае с BLE, спецификации для основных версий (4.0, 4.1, 4.2, 5) доступны для загрузки с сайта Bluetooth абсолютно бесплатно.

  • Низкая цена модулей и чипсетов по сравнению с другими технологиями;

  • Наконец, не менее важный фактор наличие в большинстве смартфонов на рынке. Возможно, это наибольшее преимущество BLE перед такими технологиями как ZigBee, Z-Wave и Thread.

4.3 Наиболее подходящие области применения BLE

Исходя из ограничений и преимуществ, указанных выше, существуют варианты использования, где BLE раскрывается наиболее полно:

  • Малый объем передаваемых данных;

BLE подходит для случаев, когда устройство передает небольшие объемы данных, например, данные датчиков или команды исполнительных устройств.

  • Настройка устройств;

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

Например, некоторые устройства с поддержкой WiFi добавляют BLE как вспомогательный протокол вместо использования таких технологий как WiFi Direct. Это технология, которая позволяет двум устройствам с поддержкой WiFi соединяться напрямую, минуя роутер. Вы можете узнать подробнее о ней на Википедии или здесь.

  • Использование смартфона в качестве интерфейса;

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

  • Персональные и носимые устройства;

Для случаев, когда устройство является носимым и находится вне зоны покрытия беспроводных сетей (таких как WiFi или сотовая связь), BLE может оказаться единственным доступным способом подключения.

  • Устройства без возможности установления соединения.

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

Все вышеперечисленные сценарии только выигрывают от использования BLE. С другой стороны, есть условия, при которых, как правило, использование BLE невозможно или не дает ощутимых преимуществ, такие как:

  • Потоковая передача видео;

  • Трансляция высококачественного звука (прим.: стала возможна в BLE 5.2);

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

Архитектура BLE

Рисунок ниже иллюстрирует различные уровни, присущие архитектуре BLE. Три главных блока в этой архитектуре приложение, хост и контроллер.

Рис.3: Архитектура BLEРис.3: Архитектура BLE

В этой книге мы сфокусируемся на верхних уровнях архитектуры, кратко ознакомившись с нижними уровнями в этой главе. Подробное описание верхних уровней GAP (Generic Access Profile), GATT (Generic Attribute Profile) и Security Manager вынесем в отдельные главы.

Прикладной уровень

Прикладной уровень зависит от варианта использования девайса/приложения и относится к реализации на основе общего профиля доступа (GAP) и общего профиля атрибутов (GATT) он отвечает за то, как ваше приложение обрабатывает данные, полученные от других устройств и отправленные на них, а также управляющую логику.

Эта часть является кодом, который вы написали для своего приложения и, как правило, не является частью BLE-стека для платформы, под которую вы разрабатываете. Эта часть не рассматривается в книге, поскольку она зависит от специфики вашего приложения и способа использования.

Хост-уровень

Хост включает следующие уровни:

  • Общий профиль доступа (GAP, Generic Access Profile);

  • Общий профиль атрибутов (GATT, Generic Attribute Profile);

  • Протокол атрибутов (ATT, Attribute Protocol);

  • Менеджер безопасности (SM, Security Manager);

  • Протокол управления и адаптации логических связей (L2CAP, Logical Link Control and Adaptation Protocol);

  • Интерфейс хост-контроллера (HCI, Host Controller Interface), зона ответственности хоста.

Контроллер

Контроллер включает следующие уровни:

  • Физический уровень (PHY, Physical Layer);

  • Слой связи (Link Layer);

  • Режим прямого тестирования (DTM, Direct Test Mode);

  • Интерфейс хост-контроллера (HCI, Host Controller Interface), зона ответственности контроллера.

Уровни архитектуры BLE

Физический уровень (PHY)

PHY относится к части оборудования, ответственного за прием, передачу, модуляцию и демодуляцию сигнала. BLE работает в ISM-диапазоне (2.4 ГГЦ), который разделен на 40 каналов по 2 Мгц, как показано на рисунке ниже:

Рис.4: Частотный спектр и радиоканалы в BLEРис.4: Частотный спектр и радиоканалы в BLE

Три выделенных канала носят название Первичных Широковещательных Каналов, в то время, как оставшиеся 37 используются в роли Вторичных Широковещательных и для передачи данных во время соединения. Мы подробно рассмотрим принципы их использования в разделе Адвертайзинг и сканирование, но для начала кратко ознакомимся с ними в этой главе.

Адвертайзинг заключается в рассылке широковещательных пакетов по трем Первичным Каналам Адвертайзинга (или части из них). Это дает возможность обнаружить широковещающее устройство и прочитать его данные сканирующим устройствам. После этого сканирующее устройство может инициировать соединение, если широковещающее разрешает подключение. Также сканирующее устройство может послать запрос на сканирование, и, если широковещающее устройство поддерживает эту функцию, то оно пошлет ответ на сканирование. Запросы на сканирование и ответы на него позволяют передавать дополнительные данные без подключения к устройству.

Вот некоторые другие важные технические детали, касающиеся физического уровня передачи BLE:

  • Он использует скачкообразную перестройку несущей частоты (FHSS, Frequency Hopping Spread Spectrum), что позволяет двум взаимодействующим устройствам переключаться на случайные предварительно согласованные частоты для обмена данными. Это значительно повышает надежность и позволяет устройствам избегать перегруженных каналов.

  • Мощность передачи может быть:

Не более: 100 мВт (+20 дБм) для версии 5 и более новых, 10 мВт (+10 дБм) для версии 4.2 и более старых;

Не менее: 0.01 мВт (-20 дБм).

  • В старых версиях Bluetooth (4.0, 4.1 и 4.2) была доступна только одна скорость передачи 1 Мбит/с. Физический уровень радио (PHY) в этом случае называется 1M PHY и является обязательным во всех версиях, включая Bluetooth 5. В Bluetooth 5 были также введены два новых дополнительных PHY:

    • 2 Мбит/с PHY, используемый для удвоения скорости передачи по сравнению с более ранними версиями Bluetooth.

    • Зашифрованный PHY, используемый для связи на дальних расстояниях.

Мы рассмотрим эти два новых PHY и концепцию кодирования в главе, посвященной Bluetooth 5.

Канальный уровень

Канальный уровень отвечает за взаимодействие с физическим уровнем радио и предоставление другим уровням абстракции для взаимодействия с радио (через промежуточный уровень интерфейса хост-контроллера, который мы вскоре обсудим). Он отвечает за управление состоянием радио и соблюдение требований к временным задержкам, необходимых для удовлетворения спецификации BLE. Также он отвечает за управление аппаратно-ускоренными операциями, такими как вычисление контрольных сумм, генерацию случайных чисел и шифрование.

Существует три основных состояния, в которых может находиться устройство с BLE:

  • Широковещательное состояние (Advertising);

  • Состояние сканирования (Scanning);

  • Подключенное состояние.

Когда устройство посылает широковещательные пакеты, оно позволяет сканирующим устройствам обнаружить себя и подключиться. Если широковещающее устройство допускает подключения, сканирующее устройство нашло его и послало запрос на подключение, оба они переходят в подключенное состояние.

Канальный уровень управляет различными состояниями радио, показанными на рисунке:

Рис.5: Состояния канального уровняРис.5: Состояния канального уровня
  • Standby: состояние по умолчанию, когда радио не передает и не принимает никаких данных.

  • Advertising: состояние, в котором устройство посылает широковещательные пакеты для обнаружения и чтения другими устройствами.

  • Scanning: состояние, в котором устройство ищет устройства, посылающие широковещательные пакеты.

  • Initiating: состояние, в котором начинается процесс установки соединения с устройством, находящимся в состоянии advertising.

  • Connected: Состояние, в котором одно устройство установило соединение с другим и регулярно обменивается с ним информацией. В подключенном состоянии устройство, которое находилось в состоянии scanning и инициировало соединение, называется ведущим. Устройство, которое рассылало широковещательные пакеты, называется ведомым.

Мы рассмотрим эти состояния более подробно в последующих главах.

Bluetooth адрес:

Bluetooth-устройства идентифицируются посредством 48-битного адреса, похожего на MAC-адрес. Существуют два основных типа адресов: публичный и случайный.

Публичный адрес:

Это фиксированный адрес, запрограммированный на фабрике. Он не может быть изменен и должен быть зарегистрирован в IEEE (также, как и MAC-адреса устройств с поддержкой WiFi или Ethernet).

Случайный адрес:

Так как у производителей есть возможность выбирать, какой тип адреса использовать (публичный или случайный), случайные адреса встречаются более часто, так как они не требуют регистрации в Институте инженеров электротехники и электроники. Случайный адрес программируется на устройстве или генерируется в ходе выполнения программы. Он может относиться к одному из следующих подтипов:

  • Статический адрес

    • Используется в качестве замены публичного адреса;

    • Может быть заново сгенерирован при загрузке кода или оставаться постоянным в течение всего срока службы;

    • Не может изменяться при включении или выключении.

  • Частный адрес включает в себя следующие подтипы:

    Неразрешимый частный адрес:

    • Случайный, генерируется на определенный промежуток времени;

    • Широко не используется.

    Разрешимый частный адрес:

    • Используется для обеспечения безопасности;

    • Генерируется с использованием ключа (IRK, Identity Resolving Key) и случайного числа;

    • Периодически меняется (даже во время соединения);

    • Используется для защиты от отслеживания злоумышленниками;

    • Доверенные устройства (связанные, описанные в главе, посвященной безопасности) могут расшифровать адрес, используя предварительно сохраненный ключ.

Режим прямого тестирования

Режим прямого тестирования (DTM, Direct Test Mode) используется исключительно для проведения испытаний радиочасти во время производства или сертификационных испытаний. Он не относится напрямую к теме нашей книги, поэтому мы оставим его без подробного рассмотрения.

Уровень интерфейса хост-контроллера (HCI)

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

В случае, когда хост и контроллер находятся на разных микросхемах, связь между ними может быть реализована посредством трех официально поддерживаемых физических интерфейсов: UART, USB или SDIO (Secure Digital Input Output). В случае, когда хост и контроллер находятся на одной и той же микросхеме, интерфейс хост-контроллера будет логическим интерфейсом.

Задача интерфейса хост-контроллера состоит в передаче команд от хоста контроллеру и передаче информации и событий от контроллера к хосту. На рисунке ниже приведен пример обмена командами и событиями между уровнями хоста и контроллера.

Рис.6: Пример пакетов интерфейса хост-контроллераРис.6: Пример пакетов интерфейса хост-контроллера

Примеры сообщений включают в себя: пакеты команд, настройку контроллера, запрос действий, управление параметрами соединения, пакеты событий, завершение команд и события состояния.

Уровень протокола управления и адаптации логического канала (L2CAP)

Протокол L2CAP предоставляет услуги по работе с данными, как ориентированные на соединения, так и без ориентации на них, протоколам более высокого уровня с возможностями мультиплексирования и обеспечения операций по сегментации и обратной сборке. Он заимствован из стандарта Bluetooth Classic и в случае BLE выполняет следующие задачи:

  • Принимает несколько протоколов с верхних уровней и помещает их в стандартные пакеты BLE, которые передаются на нижние уровни под ним.

  • Управляет фрагментацией и рекомбинацией пакетов. Он берет большие пакеты с верхних уровней и разбивает их на порции, которые соответствуют максимальному размеру полезной нагрузки BLE, поддерживаемому для передачи. На стороне получателя он принимает несколько пакетов и объединяет их в один пакет, который может быть обработан верхними уровнями.

В случае BLE уровень L2CAP управляет двумя основными протоколами: протоколом атрибутов (ATT, рассмотрен в главе, посвященной GATT) и протоколу управления безопасностью (SMP, рассмотрен в главе, посвященной безопасности).

Слои верхнего уровня

Протокол атрибутов (АТТ), общий профиль атрибутов (GATT), менеджер безопасности (SM) и общий профиль доступа (GAP) будут подробно рассмотрены в следующих главах.


На этом заканчивается первая глава книги. Большое спасибо дочитавшим. Следующая часть будет посвящена классам устройств и адвертайзингу методу, с помощью которого устройства сообщают о своем присутствии окружающему миру.

Подробнее..

Перевод Bluetooth Low Energy подробный гайд для начинающих. Часть 2

17.12.2020 16:16:33 | Автор: admin

Это вторая часть перевода книги Мохаммада Афане Intro to Bluetooth Low Energy. В представленных главах мы поговорим о типах устройств и об адвертайзинге, методе, с помощью которого периферийные устройства сообщают о своем присутствии.Первая часть здесь.

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

2. Периферийные и центральные устройства BLE

Существуют несколько важных определений, с которыми вы будете постоянно сталкиваться при изучении BLE. Два наиболее важных касаются ролей устройства: BLE central и BLE peripheral.

Рассмотрим их более детально.

2.1 Периферийные устройства

Периферийное устройство устройство, которое объявляет о своем присутствии путем адвертайзинга, т.е.рассылки широковещательных пакетов, и принимает запросы на соединение от центральных устройств.

Другой связанный термин BLE-передатчик, устройство, которое также рассылает широковещательные пакеты, но имеет одно отличие от периферийного устройства:оно не разрешает другим устройствам устанавливать с ним соединение. С другой стороны, устройство-наблюдатель только обнаруживает устройства, производящие процедуру адвертайзинга, но не имеет возможности инициировать соединение с ними.

Типичный пример устройства, реализующего роль передатчика маячок (beacon). Маячки это устройства, которые передают информацию без возможности установить с ними соединение. Они очень популярны в двух сферах: розничная торговля и определение местоположения внутри помещений.

Например, некоторая сеть магазинов использует мобильное приложение, которое может обнаруживать маячки на территории магазина. Если покупатель, имеющий на своем смартфоне это же приложение, приблизится к маячку, то в приложении отобразится специальная скидка на группу товаров, связанную с маячком.

Отличить маячок от периферийного устройства можно по типу широковещательных пакетов, которые он передает. Существуют различные типы пакетов: некоторые указывают на возможность установить соединение, а другие просто указывают на наличие маячка в этом месте. Когда центральное BLE-устройство обнаруживает широковещательные пакеты другого устройства с BLE (будь оно маячком или периферийным), оно знает, может ли оно начинать процедуру установки соединения или нет в зависимости от типа принятых широковещательных пакетов.

Как только периферийное устройство подключается к центральному, оно принимает на себя роль ведомого. Центральное устройство в таком случае называется ведущим. Это роли, определенные на канальном уровне, тогда как роли периферийного и центрального устройства определены на уровне GAP.

2.2 Центральные устройства

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

Наблюдатель устройство, схожее по функционалу с центральным, но не имеющее возможности устанавливать соединение с другим устройством.

2.3 Сравнение типов устройств

Рассмотрим возможности и ограничения четырех типов устройств: передатчик, наблюдатель, периферийное и центральное устройство.

Передатчик

Периферийное устройство

Наблюдатель

Центральное устройство

Не требует наличия приемника

Требует наличия как приемника, так и передатчика

Не требует наличия передатчика

Требует наличия как приемника, так и передатчика

Не поддерживает двунаправленный обмен данными

Поддерживает двунаправленный обмен данными

Не поддерживает двунаправленный обмен данными

Поддерживает двунаправленный обмен данными

Упрощенная схема, уменьшенный размер программного стека BLE

Требует полного программного стека BLE

Упрощенная схема, уменьшенный размер программного стека BLE

Требует полного программного стека BLE

Табл. 1: Сравнение типов устройств

2.4 Энергопотребление и требования к вычислительной мощности

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

Центральное устройство BLE также может иметь батарейное питание, но обычно имеет перезаряжаемый аккумулятор большой емкости. Как правило, роль центрального устройства на себя берет смартфон, компьютер или планшет.

Центральное устройство может быть подключено к нескольким периферийным одновременно. Характерный пример смартфон, подключенный к умным часам, термостату умного дома и фитнес-трекеру одновременно.

2.5 Многоролевые устройства BLE

В некоторых случаях поддержка BLE-устройством центральной и периферийной роли одновременно приносит заметную пользу. Например, устройство может контролировать несколько датчиков (периферийных устройств) и в то же время иметь возможность передавать данные с этих датчиков на смартфон, обеспечивая доступ к ним из интерфейса мобильного приложения.

Рис. 1: Смартфон в качестве многоролевого устройстваРис. 1: Смартфон в качестве многоролевого устройства

2.6 Роль смартфонов в BLE

Одним из наиболее значимых преимуществ BLE перед другими похожими малопотребляющими технологиями, такими как ZigBee, Z-Wave, Thread и др.,) является его наличие в большинстве смартфонов, представленных на рынке. Практически все смартфоны уже имели на борту Bluetooth Classic с самых ранних дней, и большинство производителей чипсетов Bluetooth теперь внедряют в свои чипы поддержку и BLE, и Bluetooth Classic. В результате в настоящее время подавляющее большинство смартфонов поддерживает BLE.

Для смартфона возможность взаимодействовать с устройствами BLE дает пару существенных преимуществ:

  • Смартфоны предоставляют пользователям привычный интерфейс. Использование мобильного приложения для взаимодействия с BLE-устройством зачастую оказывается удобнее непосредственного взаимодействия с этим устройством.

  • Смартфоны, как правило, постоянно подключены к Интернету. Это означает, что данные, полученные с BLE-устройства, могут быть переданы в облако и сохранены для последующего анализа и обработки.

Сложности, связанные с BLE на смартфонах

В настоящий момент существуют две основные мобильные операционные системы: Android и iOS. Android представил встроенную поддержку BLE API в версии Android 4.3 (выпущена в июле 2012 года), в то время как iOS сделал то же самое немного раньше в октябре 2011 года.

Важно отметить, что многое зависит от возможностей аппаратного обеспечения операционной системы. В случае с iOS, поддержку BLE имеют все устройства, начиная с iPhone 4s. Ситуация с Android гораздо сложнее. Эта операционная система работает на устройствах разных производителей с разной аппаратной конфигурацией, поэтому нет простого способа определить, какие устройства первыми начали поддерживать BLE. Эта проблема фрагментации Android представляет большую проблему при разработке приложений, использующих BLE, которые должны работать одинаково на всех существующих Android-устройствах.

3. Рассылка и сканирование пакетов адвертайзинга

3.1 Общий профиль доступа (GAP)

Общий профиль доступа предоставляет фреймворк, который определяет способы взаимодействия BLE-устройств друг с другом. Он включает в себя следующие аспекты:

  • Режимы и роли устройств;

  • Обнаружение устройств: рассылка пакетов адвертайзинга, сканирование, параметры рассылки и сканирования, содержимое пакетов;

  • Установка соединения: инициация, подтверждение, параметры соединения;

  • Обеспечение безопасности

Реализация этого фреймворка является обязательной согласно официальной спецификации, и это то, что позволяет устройствам BLE обмениваться данными и взаимодействовать друг с другом.

Мы кратко осветили состояния сканирования и рассылки пакетов адвертайзинга BLE-устройств и упомянули, что периферийное устройство всегда запускается в состоянии рассылки пакетов адвертайзинга, даже если оно предназначено для работы в подключенном состоянии большую часть времени. Чтобы два устройства могли обнаружить друг друга, одно из них должно рассылать пакеты адвертайзинга, а другое сканировать первичные широковещательные каналы (радиоканалы 37, 38, 39) в поисках пакетов адвертайзинга, отправленных периферийным устройством.

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

3.2 Рассылка пакетов адвертайзинга

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

В BLE существуют 40 радиоканалов, разнесенных на 2 МГц (от центра до центра), как показано на рисунке ниже. Три канала называются каналами первичного адвертайзинга, в то время как оставшиеся 37 каналов используются для вторичного адвертайзинга, а также для передачи пакетов данных во время соединения.

Рис. 8: Радиоканалы в BLEРис. 8: Радиоканалы в BLE

Замечание: Так как устройство посылает пакеты адвертайзинга на одном из этих каналов и, как правило, постоянно переключается между ними, они (каналы) разнесены далеко по спектру друг от друга для того, чтобы избежать перекрестных помех между устройствами, вещающими на разных каналах. Также, расположение этих каналов на спектре выбрано таким, чтобы избежать помех от наиболее часто используемых Wi-Fi каналов.

Процесс адвертайзинга всегда начинается с посылки широковещательного пакета по трем первичным каналам адвертайзинга или части из них. Это позволяет центральным устройствам найти периферийные и прочитать и пакеты адвертайзинга. Затем центральное устройство может запустить процесс подключения, если периферийное устройство поддерживает такую возможность.

Также центральное устройство может послать запрос на сканирование и, если периферийное поддерживает такую возможность, оно пошлет пакет, содержащий ответ на сканирование. Запросы на сканирование и ответы позволяют периферийному устройству отправить дополнительные данные, которые не поместились в основной пакет адвертайзинга без установки соединения.

Примечание: длина первичного пакета адвертайзинга ограничена 31 байтами. Длина вторичного пакета адвертайзинга может составлять до 254 байт.

Как мы упоминали ранее, некоторые устройства (маячки) всегда остаются в состоянии адвертайзинга и не принимают запросы на подключение, в то время как другие (периферийные устройства) позволяют переход в подключенное состояние, если центральное устройство инициирует соединение.

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

Рис. 9: Устройства, имеющие и не имеющие возможность подключенияРис. 9: Устройства, имеющие и не имеющие возможность подключения

3.3 Состояние сканирования

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

Устройство, которое прослушивает каналы адвертайзинга в поисках пакетов адвертайзинга а затем посылает запросы сканирования, находится в режиме активного сканирования, а устройство, которое только принимает пакеты адвертайзинга, и не посылает запросов на сканирование, соответственно находится в режиме пассивного сканирования.

Рис. 10: Пассивное и активное сканированиеРис. 10: Пассивное и активное сканирование

3.4 События адвертайзинга

Событие адвертайзинга состоит из нескольких пакетов, отправленных по всем или нескольким из трех каналов первичного адвертайзинга (37, 38 и 39). Существует семь типов событий адвертайзинга (их можно рассматривать как различные типы пакетов):

  • Подключаемое и сканируемое ненаправленное событие.

Этот тип позволяет другим устройствам принимать пакеты, посылать запросы сканирования отправителю и устанавливать с ним соединение.

  • Подключаемое ненаправленное событие.

Позволяет другим устройствам принимать пакеты и устанавливать соединение с их отправителем.

  • Подключаемое направленное событие.

Позволяет определенному устройству принимать пакеты и устанавливать соединение с отправителем

  • Неподключаемое и несканируемое ненаправленное событие.

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

  • Неподключаемое и несканируемое направленное событие.

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

  • Сканируемое ненаправленное событие.

Дает возможность другим устройствам посылать запросы сканирования отправителю для получения дополнительного пакета данных.

  • Сканируемое направленное событие.

Позволяет определенному устройству посылать запросы сканирования отправителю пакета адвертайзинга для получения дополнительного пакета данных.

3.5 Параметры адвертайзинга

Под параметрами адвертайзинга понимают:

  • Интервал адвертайзинга.

Наиболее важный параметр из относящихся к адвертайзингу это интервал адвертайзинга. Значение этого параметра может дискретно изменяться в пределах от 20 миллисекунд до 10.24 секунд, с шагом в 625 микросекунд. Интервал адвертайзинга оказывает большое влияние на продолжительность работы от батареи, поэтому выбору его значения следует уделить самое пристальное внимание. Рекомендуется выбирать наибольший интервал адвертайзинга, позволяющий соблюсти баланс между скоростью обнаружения и энергопотреблением.

  • Данные адвертайзинга и ответа на сканирование.

Давайте посмотрим на формат пакета адвертайзинга и составляющие его поля. Стоит отметить, что пакет ответа на сканирование использует такой же формат.

Рис. 11: Формат пакета адвертайзинга (из спецификации стандарта Bluetooth 5)Рис. 11: Формат пакета адвертайзинга (из спецификации стандарта Bluetooth 5)

Данные адвертайзинга используют формат, аналогичный формату TLV (Type-Length-Value, Тип-Длина-Значение), используемому для передачи данных. Отличие состоит в том, что в пакетах адвертайзинга длина данных следует перед их типом. Данные адвертайзинга входят в состав протокольных данных (PDU, Protocol Data Unit) BLE-пакета и включает в себя:

  • Длину: длину данных, которые следуют за самим значением длины, включая тип данных и непосредственно данные.

  • Тип данных адвертайзинга: тип данных адвертайзинга, содержащихся в этой структуре TLV.

  • Данные адвертайзинга: непосредственно данные.

Типы данных адвертайзинга определены в дополнении спецификации Bluetooth (не в основном документе).

Ниже приведены одни из наиболее часто встречающихся типов данных:

  • Local Name: имя устройства, считываемое при его обнаружении другими устройствами, производящими процедуру сканирования.

  • Tx Power Level: Мощность передачи, измеряемая в дБм.

  • Flags: множество однобитных логических флагов (переменные, которые могут принимать одно из двух значений, истина [1] или ложь [0], включающее в себя:

    • Limited Discoverable Mode (ограниченный режим обнаружения);

    • General Discoverable Mode (общий режим обнаружения);

    • BR/EDR Not Supported (возможность поддержки классического протокола Bluetooth);

    • Возможность одновременной поддержки классического и Low Energy Bluetooth на одном устройстве со стороны контроллера;

    • Возможность одновременной поддержки классического и Low Energy Bluetooth на одном устройстве со стороны хоста.

Примечание: понятия BR (Basic Rate, базовая пропускная способность) и EDR (Enhanced Data Rate, расширенная пропускная способность) относятся к Bluetooth Classic.

  • Service Solicitation: список из одного или нескольких UUID, показывающий, какие сервисы поддерживаются и представлены GATT-сервером устройства. Это помогает центральному устройству узнать о поддерживаемых периферийным устройством сервисах до установления соединения.

  • Appearance: вид, определяет тип устройства в соответствии со спецификацией стандарта. Включает в себя такие виды как телефон, измеритель сердечного ритма, брелок для ключей и множество других.

Если вы не можете найти вид, к которому можно было бы отнести ваше устройство, вы всегда можете оставить ему значение по умолчанию Неопределенный.

3.6. Параметры сканирования

Существует три основных параметра сканирования:

  • Scan Type (тип сканирования): пассивное или активное.

  • Scan Window (окно сканирования): определяет, длительность сканирования.

  • Scan Interval (интервал сканирования): определяет частоту повторения сканирования.

Центральное устройство прослушивает один из первичных каналов адвертайзинга в течении всего окна сканирования с периодом, равным интервалу сканирования, причем каждое последующее сканирование проходит на новом канале.

Рис. 12: Параметры сканированияРис. 12: Параметры сканирования

__________________________________

А что дальше?

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

Подробнее..

Перевод Bluetooth Low Energy подробный гайд для начинающих. Соединения и сервисы

01.02.2021 08:17:17 | Автор: admin

Это третья часть перевода книги Мохаммада Афане Intro to Bluetooth Low Energy. Сегодня мы подробнее рассмотрим процесс подключения устройств и поговорим о сервисах.

Предыдущие части:
Про архитектуру BLE
Про типы устройств, адвертайзинг и сканирование

Благодаря сервисам происходит обмен как стандартными данными (уровень заряда батареи через Battery Service, текущее время устройства через Current Time Service и т.д.), так и кастомными, при помощи сервисов, созданных разработчиком устройства для удовлетворения специфических нужд. Например, для Atmotube Pro мы сделали два сервиса, в которые сгруппировали несколько характеристик для синхронизации истории, передачи данных о концентрации пыли и летучих органических соединений.

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

4. Соединения

Для того, чтобы два BLE устройства установили соединение, необходимо выполнить следующие шаги:

  • Периферийное устройство должно начать процесс адвертайзинга и не останавливать его до момента установки соединения.

  • Центральное устройство должно сканировать радиоэфир в поисках пакетов адвертайзинга.

  • Если центральное устройство прослушивает канал адвертайзинга в момент, когда периферийное устройство посылает по нему данные, то оно обнаруживает периферийное устройство.

  • Затем центральное устройство посылает пакет CONNECT_IND (также известный как запрос на соединение).

  • Периферийное устройство всегда прослушивает текущий канал адвертайзинга после отправки пакета. Это позволяет ему получить запрос на соединение от центрального устройства, что запускает процесс установки соединения между двумя устройствами.

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

4.1 События подключения

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

  • События подключения происходят периодически до тех пор, пока соединение не будет закрыто или потеряно.

  • Событие подключения состоит как минимум из одного пакета посланного ведущим устройством.

  • Ведомое устройство всегда посылает отвечает отправкой пакета, если оно получает пакет от ведущего.

  • Если ведущий не получает ответный пакет от ведомого, он закрывает подключение - он возобновит посылку пакетов во время следующего события подключения.

  • Подключение может быть закрыто как ведущим, так и ведомым.

  • События подключения разнесены во времени на период интервала соединения.

Рис. 13: Интервал соединения и события соединенияРис. 13: Интервал соединения и события соединения

4.2 Параметры соединения

Параметры, определяющие соединение:

  • Интервал соединения

    Интервал соединения может принимать любое из значений между 7.5 мс и 4.0 секундами с шагом в 1.25 мс. Он задается центральным устройством в пакете запроса соединения. Центральное устройство может принять во внимание Предпочитаемые Параметры Соединения Периферийного Устройства (PPCP). Центральное устройство вправе принять их, модифицировать или отклонить.

  • Задержка ведомого (Slave Latency)

    Параметр задержки ведомого позволяет периферийному устройству оставлять без ответа определенное количество событий соединения и не слушать центральное устройство во время этих событий без инвалидации соединения. Это позволяет периферийному устройству переходить в режим энергосбережения на более длительный срок. Задержка ведомого отображает количество событий соединения, которое периферийное устройство может пропустить.

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

  • Таймаут наблюдения (Supervision Timeout)

    Таймаут наблюдения используется для определения потери соединения. Он определяется как максимальное время между двумя полученными пакетами данных, прежде чем соединение считается потерянным. Его значение может задаваться в диапазоне между 100 мс и 32 секундами с шагом 10 мс. Другое условие выглядит следующим образом:

    Таймаут наблюдения > (1 + задержка ведомого) * интервал соединения * 2

    Существует исключение, для которого таймаут наблюдения не применяется - в момент, когда соединение создано, но еще не установлено. В этом случае ведущее устройство примет решение о потере соединения, если не получит пакета от ведомого в течении 6 интервалов соединения.

  • Расширение длины данных (DLE)

    Это опция, которая позволяет пакетам данных содержать большее количество полезной нагрузки (до 251 байта, в случае, когда эта настройка выключена, полезная нагрузка составляет 27 байт). Эта возможность введена в версии 4.2 спецификации Bluetooth.

  • Максимальная единица передачи (MTU)

    Понятие максимальной единицы передачи используется в компьютерных сетях и определяет максимальный размер данных, которые можно передать по определенному протоколу. Максимальная единица передачи атрибута (в спецификации определена как ATT_MTU) это наибольший размер полезной нагрузки атрибута, который можно передать между клиентом и сервером.

    Эффективный размер ATT_MTU определяется наименьшим значением максимальных ATT_MTU поддерживаемых ведущим и ведомым. Например, если ведущее устройство поддерживает ATT_MTU 100 байт и ведомое устройство сообщает, что оно поддерживает ATT_MTU 150 байт, то ведущий решает, что для этого соединения будет использоваться ATT_MTU 100 байт.

    Примечание: Для достижения максимальной пропускной способности убедитесь, что включено расширение длины передаваемых данных (в случае, если вы используете Bluetooth 4.2 или новее). Это поможет снизить количество избыточно передаваемых служебных данных, таких как заголовки пакетов, за счет уменьшения числа пакетов.

4.3 Переключение между каналами

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

Последовательность каналов, используемая для каждого события соединения определяется картой каналов и шагом прыжка (hop increment). Шаг прыжка, также как и карта каналов, включен в пакет запроса соединения. Комбинация карты каналов и шага прыжка определяет, какой канал будет использован для каждого интервала соединения.

Рис. 14: Карта каналов и шаг прыжкаРис. 14: Карта каналов и шаг прыжка

Существует два алгоритма выбора каналов в BLE. Рассмотрение подробностей их работы лежит вне поля зрения этой книги. Для того, чтобы узнать больше об этих алгоритмах и принципах их работы, обратитесь к спецификации Bluetooth (version 5.0 | Vol 6, Part B, Section 4.5.8.2).

4.4 Белый список и фильтрация устройств

BLE поддерживает фильтрацию устройств для процедур, связанных с состояниями адвертайзинга, сканирования и стадией инициации (при установлении соединения).

Белый список это список адресов и типов адресов определенных устройств. Он используется для определения того, в каких устройствах заинтересовано конкретное устройство. Запись для анонимного типа адреса устройства позволяет сопоставить все широковещательные пакеты, отправленные без адреса.

Фильтрация устройств происходит на канальном уровне контроллера (нижний уровень протокола Bluetooth), что позволяет сохранить время и не производить лишнюю работу на уровне хоста (на верхних уровнях протокола). Однако именно хост отвечает на конфигурацию белого списка.

Ниже приведен список различных правил фильтрации для каждого из состояний:

  • Правило фильтрации для состоянии адвертайзинга (периферийное устройство)

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

    • Обрабатываются запросы сканирования и запросы на подключение только от устройств из белого списка.

    • Обрабатываются запросы от всех устройств (фильтрация не используется).

    • Обрабатываются запросы сканирования только от устройств из белого списка, обрабатываются запросы на подключение от всех устройств.

    • Обрабатываются запросы на подключение только от устройств из белого списка, обрабатываются запросы сканирования от всех устройств.

  • Правило фильтрации для состояния сканирования (центральное устройство)

    Это правило фильтрации определяет, как сканирующее устройство будет обрабатывать пакеты адвертайзинга. Может быть сконфигурировано следующим образом:

    • Обрабатываются пакеты адвертайзинга от всех устройств (белый список не используется).

    • Обрабатываются пакеты адвертайзинга только от устройств, включенных в белый список.

  • Правило фильтрации для состояния инициации (центральное устройство)

    Это правило определяет, как устройство, инициирующее соединение, будет обрабатывать пакеты адвертайзинга. Может быть сконфигурировано следующим образом:

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

    • Обрабатывать пакеты адвертайзинга и инициировать соединение только с устройствами, определенными хостом.

    Обратите внимание, что это не опция для обработки пакетов и подключения к подключаемому периферийному устройству, которого нет в белом списке.

5. Сервисы и характеристики

Прежде чем начать рассказ о сервисах и характеристиках, мы должны рассмотреть два очень важных понятия: Общий профиль атрибутов (GATT) и Протокол атрибутов (ATT).

Для того, чтобы понять, что из себя представляет общий профиль атрибутов, необходимо сперва разобраться, что из себя представляет его нижний слой - протокол атрибутов. GATT вступает в игру только после того, как будет установлено соединение между двумя устройствами.

Примечание автора

если вы считаете GAP, GATT и ATT набором слишком похожих акронимов не проклинайте меня Я просто рассказчик! Тем не менее важно разделять их!

5.1 Протокол атрибутов (ATT)

АТТ определяет, в каком виде сервер представит свои данные клиенту и как эти данные будут структурированы. Существует две роли, связанные с АТТ:

  • Сервер:

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

    Например, беспроводной термометр будет вести себя как сервер, когда он будет предоставлять температуру окружающей среды, единицу измерений, свой уровень заряда и, возможно, временные интервалы, с которыми термометр производит измерения и сохраняет их результаты. Он также может уведомлять клиент (объясним позже) об изменениях температуры для того, чтобы клиент не опрашивал его непрерывно в ожидании готовых к отправке данных.

  • Клиент:

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

    Данные, предоставляемые сервером, сгруппированы в атрибуты. Атрибут это общий термин для любых типов данных, предоставляемых сервером, он определяет структуру этих данных. Например, сервисы и характеристики (будут описаны позднее) являются атрибутами. Ниже состав атрибута:

  • Тип атрибута (универсальный уникальный идентификатор, UUID)

    Это 16-битное (в случае стандартных атрибутов Bluetooth SIG) или 128-битное число (в случае атрибутов, определенных разработчиком устройства, vendor-specific UUID).

    Например, UUID для одобренного консорциумом атрибута значения температуры 0x2A1C. Одобренные консорциумом типы атрибутов имеют один общий (за исключением 16 бит) специальный 128-битный UUID:

    0000XXXX-0000-1000-8000-00805F9B34FB

    16-битный UUID будет подставлен вместо символов ХХХХ в базовом UUID.

    Собственный UUID может быть любым 128-битным числом, не совпадающим ни с одним из одобренных Bluetooth-SIG базовых UUID. Например, разработчик может создать свой собственный UUID для показаний температуры, такой как:

    F5A1287E-227D-4C9E-AD2C-11D0FD6ED640

    Одно из преимуществ использования стандартных UUID состоит в уменьшении размера пакета, так как UUID может быть передан в виде 16-битного числа, вместо передачи полного 128-битного числа.

  • Дескриптор атрибута

    Это 16-битное число, которое сервер присваивает каждому из своих атрибутов. Это число используется клиентом как ссылка на конкретный атрибут, и сервер гарантирует, что эта ссылка будет уникальной для атрибута, которому она присвоена, в течении всего времени существования соединения между устройствами. Дескриптор может иметь любое значение в диапазоне 0x0001-0xFFFF, значение 0х0000 зарезервировано.

  • Права атрибута

    Права определяют, может ли атрибут быть прочитан или записан, может ли он посылать уведомления или индикации, и какие уровни доступа требуются для каждой из этих операций. Эти права не определяются протоколом атрибутов (АТТ) и не могут быть прочитаны через него, они определяются на верхнем уровне (GATT или уровне приложения).

Рис. 15: Состав атрибута (источник: спецификация Bluetooth 5)Рис. 15: Состав атрибута (источник: спецификация Bluetooth 5)

5.2 Общий профиль атрибутов (GATT)

Теперь, когда мы рассмотрели концепцию атрибутов, познакомимся с другими тремя важными понятиями в BLE, с которыми вам придется постоянно сталкиваться.

  • Сервисы

  • Характеристики

  • Профили

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

GATT определяет формат сервисов и их характеристик, а также процедуры, используемые для взаимодействия с этими атрибутами, такие как обнаружение сервисов, чтение и запись характеристик, уведомления и индикации.

GATT выполняет ту же роль, что и протокол атрибутов (АТТ). Роли устанавливаются не для устройств, они определяются во время транзакций (такие как запрос ответ, индикация подтверждение, уведомление). Таким образом, устройство может действовать как сервер, предоставляющий данные клиентам, и в то же время быть в роли клиента, получая данные, подготовленные другими серверами одновременно.

5.3 Сервисы и характеристики

5.3.1 Сервисы

Сервисы это группа из одного или большего числа атрибутов, некоторые из которых являются характеристиками. Он предназначен для группировки связанных атрибутов, удовлетворяющих специфической функциональности сервера. Например, одобренный SIG сервис батареи содержит одну характеристику под названием уровень заряда.

Сервисы также содержат другие атрибуты, которые помогают структурировать данные сервиса, такие как объявления сервера, объявления характеристик и другие.

Вот что из себя представляют сервисы:

Рис. 16: Профили, сервисы и характеристики (источник: спецификация Bluetooth)Рис. 16: Профили, сервисы и характеристики (источник: спецификация Bluetooth)

На рисунке мы видим различные атрибуты, составляющие сервис:

  • Один или несколько включенных сервисов

  • Одна или несколько характеристик

    • Свойства характеристики

    • Ее значение

    • Дескрипторы характеристики

Включение сервисов позволяет сервису ссылаться на другие сервисы как на включенные в него. Существует два типа сервисов:

  • Первичный сервис: предоставляет основную функцию устройства или одну из них.

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

5.3.2 Характеристики

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

  • Свойства: представлены набором бит, определяющих то, каким образом значение характеристики может использоваться. Пример свойств: чтение, запись, запись без ответа, уведомление, индикация.

  • Дескрипторы: используются для хранения информации, связанной со значением характеристики. Примеры использования: расширенные свойства, пользовательское описание, поля, используемые для подписки на уведомления и индикации, поля, описывающие представление характеристики, такие как формат или единица измерения.

Понимание этих концепций важно, однако вы, как разработчик приложения, будете в основном взаимодействовать с API, предоставленным операционной системой или SDK чипсета, которые абстрагируют вас от многих этих понятий.

Например, вы можете иметь API для включения уведомлений для некоторых характеристик, который вы просто вызываете и вам нет необходимости знать, что результатом этого вызова будет запись значения 0x0001 в дескриптор конфигурации характеристик клиента (CCCD) на сервере.

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

Например, технически возможно создать сервис под названием сервис влажности, который будет включать в себя характеристику влажности и характеристику температуры. Но гораздо более логичным решением будет создать два отдельных сервиса для каждой несвязанной функции (отображение текущей температуры и отображение текущей влажности).

Стоит отметить, что Bluetooth SIG приняла довольно-таки большое количество сервисов и характеристик, которые удовлетворяют большей части распространенных сценариев использования. Для этих одобренных сервисов существуют спецификации, помогающие разработчикам реализовать их вместе с обеспечением соответствия и взаимодействия с каждым сервисом.

Если устройство заявляет о совместимости с сервисом, оно должно полностью соответствовать спецификации сервиса, опубликованной Bluetooth SIG. Это важно, если вы хотите разработать устройство, которое будет гарантированно подключаться к устройствам, изготовленными другим производителем. Сервисы Bluetooth, принятые SIG, делают соединение предварительно согласованным между устройствами различных производителей.

Вы можете найти список одобренных сервисов здесь, и их спецификации здесь. Одобренные характеристики находятся по этому адресу.

5.4 Профили

Профили по своему определению гораздо шире сервисов. Они занимаются определением поведения как клиента, так и сервиса, когда дело касается сервисов, характеристик и даже соединений и требований безопасности. Сервисы и их спецификации, с другой стороны, касаются реализации этих сервисов и характеристик только на стороне сервера.

Также как и в случае с сервисами, существуют одобренные SIG профили с опубликованными спецификациями к ним. В спецификации профиля вы можете найти следующее:

  • Определение ролей и взаимоотношений между GATT сервера и клиента.

  • Требуемые сервисы.

  • Требования сервисов.

  • Как используются требуемые сервисы и характеристики.

  • Детали требований к процессу установления соединения, включая параметры адвертайзинга и соединения.

  • Соображения безопасности.

Ниже в качестве примера приведена диаграмма, взятая из спецификации на профиль кровяного давления. Она показывает отношения между ролями (сервер и клиент), сервисами и характеристиками внутри профиля.

Рис. 17: Профиль кровяного давления (Источник: Спецификация профиля кровяного давления)Рис. 17: Профиль кровяного давления (Источник: Спецификация профиля кровяного давления)

Роли представлены в виде желтых прямоугольников, сервисы в виде оранжевых прямоугольников. Вы можете найти список профилей, одобренных SIG, здесь.

5.5 Пример GATT

Давайте посмотрим на пример использования GATT. В этом примере мы будем использовать файл GATT.xml, используемый в Silicon Labs Bluetooth Low Energy development framework (BGLib).

Рис. 18: Файл GATT.xml из примера приложения от фирмы Silicon LabsРис. 18: Файл GATT.xml из примера приложения от фирмы Silicon Labs

В этом XML-файле вы можете заметить следующее:

  • Определены два сервиса:

    • Сервис общего профиля доступа (GAP) с UUID: 0x1800 (одобрен SIG).

    • Сервис замены кабеля с UUID: 0bd51666-e7cb-469b-8e4d-2742f1ba77cc (Собственный сервис, определенный разработчиком приложения или производителем чипсета. Обычно так называют реализацию UART средствами Bluetooth. Например, у Nordic Semi эту роль выполняет Nordic UART Service, а у Dialog Semiconductor - Dialog Debug Service).

  • Сервис общего профиля доступа обязателен по спецификации и включает следующие обязательные характеристики:

    • Имя с UUID 0x2A00 и значением: Bluegiga CR Demo.

    • Окружение с UUID 0x2A01 и значением 0x4142.

    Описание значений окружения приведены здесь.

    Примечание: обычно создание и включение этого сервиса является задачей вендора чипсета и, обычно, разработчику предоставляется API для простой установки значений имени и окружения.

  • Сервис замены кабеля имеет одну характеристику под названием данные.

    • Характеристика данных имеет UUID: e7add780-b042-4876-aae1-112855353cc1

    • Включены свойства, разрешающие запись в характеристику и индикацию.

5.6 Операции с атрибутами

Существует шесть различных типов операций, которые могут производиться над атрибутами:

  • Команды: посылаются клиентом серверу и не требуют ответов.

  • Запросы: посылаются клиентом серверу и требуют ответов. Существуют два типа запросов:

    • Запросы на поиск информации

    • Запросы на чтение

  • Ответы: посылаются сервером клиенту в ответ на запрос.

  • Уведомления: Посылаются сервером клиенту с целью оповестить об изменении значения характеристики. Для получения уведомлений клиент должен включить их для интересующих характеристик. Помните, что уведомления не требуют подтверждения о получении от клиента.

  • Индикации: посылаются сервером клиенту. Во многом похожи на уведомления, но требуют подтверждения успешного приема клиентом.

    Примечание: настройки уведомлений и индикаций представлены в атрибуте дескриптора конфигурации характеристик клиента (CCCD). Запись 1 в этот атрибут включит уведомления, запись 2 включит индикации. Запись 0 отключит как уведомления, так и индикации.

  • Подтверждения: посылаются клиентом серверу. Это пакеты, посылаемые с целью уведомить сервер об успешном приеме индикации клиентом.

5.6.1 Управление потоком и последовательность операций с атрибутами

Запросы последовательны по своей природе и требуют ответа от сервера перед отправкой нового запроса. Индикации имеют такое же требование: новая индикация не может быть отправлена до тех пор, пока не получено подтверждение о приеме предыдущей индикации.

Запросы и индикации являются взаимоисключающими с точки зрения требований к последовательности. То есть индикация может быть отправлена сервером до того как он ответит на запрос, который получил ранее.

Команды и уведомления отличаются, и не требуют управления потоком сообщений - они могут быть посланы в любое время. По этой причине, а также потому что сервер или клиент могут быть не в состоянии обработать эти пакеты, они считаются ненадежными. Запросы и индикации должны использоваться в случаях, когда надежность стоит во главе угла.

5.6.2 Чтение атрибутов

Чтение это запрос по своей природе, так как оно требует ответа. Существует несколько типов запросов на чтение, но наиболее важны следующие два:

  • Запрос на чтение: простой запрос, ссылающийся на атрибут, который будет прочитан его дескриптором.

  • Запрос на чтение части данных: похож на запрос на чтение, но содержит смещение, указывающее, с какого участка чтение должно начаться, возвращая часть значения. Этот тип чтения используется для чтения только части значения характеристики.

5.6.3 Запись атрибутов

Запись может быть командой или запросом. Ниже представлены наиболее популярные типы записи:

  • Запрос на запись: как следует из названия, требует ответа от сервера, подтверждающего успешное получение данных.

  • Команда на запись: не требует ответа от сервера.

  • Упорядоченная запись (атомарное поведение операции): классифицируется как запрос и требует подтверждения от сервера. Они используются в случаях, когда требуется записать большое количество данных, не умещающееся в одно сообщение. Вместо того, чтобы записывать части сообщения и давать возможность кому-то прочитать некорректное неполное значение, применяются два типа запросов на запись, для того, чтобы иметь уверенность в безопасном выполнении операции:

    • Один или несколько запросов на подготовку к записи: каждый включает в себя смещение, с которым посылаемое значение должно быть записано в значение атрибута. Посылаемые значения также часто называют подготовленными значениями, и они хранятся в буфере на стороне сервера, еще не записанные в атрибут. Эта операция требует ответа со стороны сервера.

    • Один запрос на запись: используется для запроса сервера о выполнении или отмены записи принятых значений в атрибут. Требует ответа от сервера для того, чтобы клиент был уверен в том, что атрибут содержит целое и верное значение, посланное серверу.

5.6.4 Запрос на обмен MTU

Сервер и клиент согласуют общее значение MTU, использующееся для передачи данных в обоих направлениях. Запрос инициируется клиентом и может быть послан только один раз во время жизни соединения (согласно спецификации Bluetooth, version 5.0, Vol 3, Part F, Section 3.4.2.1).

Сервер отвечает особым пакетом, содержащим поддерживаемый им размер ATT_MTU. Итоговое значение будет выбрано равным меньшему из переданных между сервером и клиентом ATT_MTU.

Важно помнить, что различные версии BLE имеют разные поддерживаемые максимальные значения ATT_MTU.

5.7 Создание своего GATT

5.7.1 Общие рекомендации

Несмотря на то, что GATT это удивительно гибкий фреймворк, существуют несколько общих рекомендаций, которым нужно следовать при создании сервисов и характеристик для них:

  • Убедитесь, что внедрены обязательные сервисы и их характеристики:

    • Сервис общего профиля доступа (GAP)

    • Заданы характеристики имени и окружения.

  • Используйте одобренные Bluetooth SIG профили, сервисы и характеристики там, где это возможно. Это дает следующие преимущества:

    • Вы уменьшаете размер передаваемых пакетов, содержащих UUID сервисов и характеристик (включая пакеты адвертайзинга) ускоряете процедуру обнаружения и другие процедуры за счет использования 16-битных UUID вместо 128-битных.

    • Производители модулей и чипсетов обычно предоставляют примеры реализации этих сервисов в своих примерах и SDK - уменьшая нужное вам время на разработку.

    • Большее число сторонних устройств и приложений сможет взаимодействовать с вашим, тем самым расширяя число возможных пользовательских сценариев.

  • Группируйте характеристики, отвечающие за смежный функционал, в один сервис.

  • Избегайте создания сервисов, имеющий слишком большое количество характеристик. Хорошее разделение сервисов ускоряет процесс обнаружения характеристик и ведет к дружественному к пользователю модульному дизайну GATT.

В следующей главе мы рассмотрим практический пример, показывающий как разработать GATT для системы домашней автоматизации.

6. Урок создания GATT

Разработка GATT для вашего BLE устройства может быть очень сложной задачей. Для того, чтобы упростить ее, давайте пройдем полный урок создания GATT для простой системы домашней автоматизации.

Система домашней автоматизации это абстрактное нечто, но она поможет вам лучше понять шаги создания GATT для реального приложения, а не для какой-то обобщенной системы. Ниже показана схема с элементами системы умного дома и связями между ними.

Рис. 19: Пример проекта системы умного дома с BLEРис. 19: Пример проекта системы умного дома с BLE

Система состоит из множества устройств. Некоторые из них куплены в магазине, и мы не можем как-то изменить их прошивку, остальные подлежат модификации в соответствии с нашими нуждами.

6.1 Общее описание системы

Давайте опишем основные пользовательские сценарии для системы:

  1. Владелец дома может использовать пульт дистанционного управления для включения и выключения светильника.

  2. Владелец дома может наблюдать за изменениями показаний температуры и влажности на сенсоре окружающей среды.

  3. Владелец дома получает уведомления об уровне заряда батареи всех элементов системы.

6.2 Элементы системы

Теперь давайте рассмотрим составляющие нашей системы.

  1. Шлюз

    Шлюз будет выполнять роль центрального BLE устройства во время обмена данными со всеми устройствами кроме смартфона, где он будет выполнять роль периферийного устройства. Мы можем контролировать это устройство и спроектируем GATT для него.

    Команды для управления светильником будут поступать с пульта управления на шлюз, и с него на сам светильник.

  2. Пульт управления
    Пульт управления это устройство, которое выполняет только периферийную роль, для него мы также спроектируем GATT.

  3. Сенсор окружающей среды
    Это стандартное устройство, GATT которого мы не можем изменить, так что область нашего интереса будет ограничена чтением показаний с него (данные о текущей температуре и влажности).

  4. Светильник

    Это еще одно стандартное устройство, которое мы не можем каким-либо образом изменить.

  5. Смартфон

    Очередное стандартное устройство, мы будем использовать его для контроля системы.

6.3 Разработка GATT

Теперь мы пройдем пошагово весь процесс создания GATT, удовлетворяющего нашим требованиям.

6.3.1 Шаг 1: Документирование различных пользовательских сценариев

Несмотря на то, что GATT обычно больше сфокусирован на периферийной роли (так как обычно в роли сервера, предоставляющего данные, выступает периферийное устройство), центральное устройство также может выполнять роль сервера в особых случаях. Также, так как мы разрабатываем устройство, выполняющее обе роли (центральную и периферийную), это поможет нам понять, что должно произойти с каждой стороны, так как это повлияет на некоторые аспекты разработки системы и GATT.

6.3.1.1 Шлюз

Шлюз выполняет роль как центрального, так и периферийного устройства. Каждая из этих ролей используется для обеспечения связи с различными устройствами, входящими в состав системы. Основная задача шлюза как центрального устройства - считывать показания с множества периферийных устройств. Затем он, действуя в роли периферийного устройства, предоставляет собранные и обработанные данные другому центральному устройству (смартфону), который может передать эти данные на облачный сервер.

Рассмотрим пользовательские сценарии с точки зрения шлюза, для центральной и периферийной роли.

Периферийная роль

  • Пульт управления уведомляет шлюз, когда кнопки на нем нажимаются, для включения и выключения светильника.

  • Данные должны передаваться на облачный сервер через шлюз. Они представлены центральному устройству (например смартфону, имеющему доступ в интернет) в виде GATT-сервера в периферийной роли. Ниже перечень этих данных:

    • Показания температуры датчика окружающей среды

    • Показания влажности датчика окружающей среды

    • Статус светильника (включен или выключен)

    • Уровни заряда батареи пульта, светильника и датчика окружающей среды.

Центральная роль

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

6.3.1.2 Пульт управления

Пульт управления выполняет одну функцию: управляет светильником. Он выполняет исключительно периферийную роль и должен предоставлять следующую информацию:

  • При нажатии кнопки ВКЛ: уведомить шлюз о том, что была нажата эта кнопка.

  • При нажатии кнопки ВКЛ: также уведомить шлюз о нажатии этой кнопки.

  • Уровень заряда батареи: шлюз должен иметь возможность читать данные о заряде батареи пульта и получать уведомления о его изменении.

6.3.2 Шаг 2: Настройка сервисов, характеристик и прав доступа

На этом шаге мы сгруппируем характеристики в группы (сервисы), объединяющие характеристики со схожим функционалом и зададим разрешения для каждой из них.

6.3.2.1 Шлюз

У нас есть один GATT-сервер для шлюза в периферийной роли. Посмотрев еще раз на данные, которые нам нужно передавать, мы можем назначить им характеристики и сгруппировать их в следующие сервисы:

  • Сервис датчика окружающей среды:

    • Характеристика показаний температуры датчика окружающей среды: Температура

      Права: Чтение, уведомление.

  • Характеристика показаний влажности датчика окружающей среды: Влажность

    Права: Чтение, уведомление.

  • Характеристика остаточного заряда аккумулятора: Уровень заряда

    Права: Чтение, уведомление.

  • Сервис светильника:

    • Текущее состояние светильника Статус

      Права: Чтение, уведомление.

  • Характеристика остаточного заряда аккумулятора: Уровень заряда

    Права: Чтение, уведомление.

  • Сервис пульта дистанционного управления:

    • Характеристика остаточного заряда аккумулятора: Уровень заряда

      Права: Чтение, уведомление.

Помимо этих сервисов необходимо реализовать обязательный (согласно спецификации Bluetooth) сервис:

  • GAP сервис:

    • Характеристика имя: имя устройства.

      Права: чтение.

    • Характеристика местоположения: описание места, где размещено устройство.

      Права: чтение.

6.3.2.2 Пульт управления

У нас есть один GATT-сервер для пульта управления. Мы можем назначить ему следующие сервисы и характеристики:

  • GAP сервис (обязательный):

    • Характеристика имя: имя устройства.

      Права: чтение.

    • Характеристика местоположения: описание места, где размещено устройство.

      Права: чтение.

  • Сервис аккумулятора:

    • Характеристика остаточного заряда аккумулятора: Уровень заряда

      Права: Чтение, уведомление.

  • Сервис кнопок:

    • Характеристика кнопки ВКЛ

      Права: уведомление.

    • Характеристика кнопки ВКЛ

      Права: уведомление.

6.3.3. Шаг 3: Использование стандартных сервисов и характеристик

6.3.3.1. Шлюз

Сервисы датчика окружающей среды, светильника и пульта являются нашими собственными, так как не существует ни одного стандартного сервиса, который мы бы могли использовать для них. Однако у нас есть три устройства с аккумуляторами, заряд которых нам необходимо отображать и мы можем использовать стандартную характеристику уровня заряда. Мы будем использовать ее для каждого устройства в его сервисе в GATT шлюза. Также мы будем использовать обязательный GAP сервис.

6.3.3.2. Пульт управления

Для пульта управления мы можем использовать стандартный сервис уровня заряда батареи и обязательный GAP сервис.

6.3.4. Шаг 4: Присвоение UUID нашим сервисам и характеристикам

Для каждого нестандартного сервиса и характеристики мы можем использовать онлайн-инструмент для генерации UUID, например этот.

Распространенной практикой является выбор базового UUID для сервиса и увеличение значения третьего и четвертого старшего байта UUID для каждой последующей характеристики.

Для примера, возьмем следующий UUID для какого-либо сервиса:

00000001-1000-2000-3000-111122223333

И затем заменим выделенные байты на

0000000[N]-1000-2000-3000-111122223333, где N>1 - порядковый номер характеристики.

Единственное условие, которое накладывает ограничение на выбор UUID для наших сервисов и характеристик это условие несовпадения нашего UUID с базовым UUID Bluetooth SIG: XXXXXXXX-0000-1000-8000-00805F9B34FB.

Следование вышепредставленной методике выбора UUID немного упрощает понимание связей между сервисами и их характеристиками.

На таблицах ниже представлены наши сервисы, характеристики и их UUID для шлюза и пульта управления.

Таблица 3: GATT шлюзаТаблица 3: GATT шлюзаТаблица 4: GATT пульта управленияТаблица 4: GATT пульта управления

6.3.5. Шаг 5: Реализация сервисов и характеристик с использованием API SDK производителя платформы

Каждая платформа, встраиваемая или мобильная, имеет собственный интерфейс прикладного программирования (API, application programming interface) для реализации сервисов и характеристик. Задача читателя самостоятельно реализовать их для выбранного им устройства или приложения.

Подробнее..

Подключаем новый Xiaomi Gateway 3 к Home Assistant без паяльника и смс

18.09.2020 10:20:14 | Автор: admin

Новый хаб от Xiaomi с поддержкой технологий Zigbee 3, Bluetooth Mesh, HomeKit и его подключение к достаточно популярной системе умного дома Home Assistant, интересует?



Введение


Устройства умного дома можно встретить на разных беспроводных протоколах.


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


Wi-Fi


Чаще всего новички выбирают устройства на технологии Wi-Fi. Ведь Wi-Fi роутер сегодня есть у всех. Умным устройством можно пользоваться сразу после покупки. Но тут есть нюанс: в количестве устройств слабость Wi-Fi. Роутеры от провайдеров в большинстве своём тот ещё хлам, способный справиться с 1-2 десятками устройств. И пять новых умных лампочек могут быть проблемой для всей сети.


Здесь выходом будет хороший двухдиапазонный роутер. Весь умный дом можно повесить на диапазон 2.4 ГГц, а мультимедиа-устройства (смартфоны, ноутбуки, телевизоры, колонки) на 5 ГГц.


Bluetooth


Устройства на Bluetooth новички выбирают так же охотно, ведь сегодня смартфоны есть почти у всех. Проблема в том, что дальность Bluetooth весьма ограничена. Уже из соседней комнаты вы не сможете посмотреть температуру на датчике или включить чайник или лампочку.


В таких случаях производители рекомендуют покупать BLE Gateway. Это устройство, которое будет посредником между Bluetooth и серверами производителя. Здесь уже далеко не все пользователи соглашаются на дополнительные траты и лишнюю железку в доме.


Некоторые производители встраивают возможности BLE Gateway в камеры и лампы, закрывая проблему лишних затрат и лишнего устройства в доме.


Zigbee


От этой технологии новички отказываются чаще всего из-за необходимости приобретать дополнительное устройство-посредник, ведь ничего работающего с Zigbee в их доме скорее всего нет. Некоторые производители встраивают поддержку этой технологии в умные колонки и, на мой взгляд, это очень интересный ход.


Дополнительную проблему составляет, что каждый такой Gateway поддерживает только дочерние устройства своего производителя. Купив устройства Philips Hue, IKEA, Sonoff, Xiaomi и Tuya, вы, скорее всего, должны будете докупить пять Gateway соответственно.


Эта технология заслуживает внимания по следующим причинам:


  • Беспроводные датчики довольно маленькие и в последнее время не такие и дорогие: 500 рублей за простейший датчик или кнопку это реальность, Xiaomi и AliExpress сделали своё дело.
  • Беспроводные датчики могут продержаться на одной батарее несколько лет, без шуток лет!
  • В количестве Zigbee устройств их сила: технология поддерживает Mesh, проводные устройства, скорее всего, будут ретрансляторами сигнала между Gateway и удалёнными датчиками, заодно снимая нагрузку с самого Gateway.
  • Технология поддерживает прямое управление в обход Gateway, можно связать кнопку и лампочку. В случае выхода Gateway из строя управление светом продолжит работать. Правда далеко не все кнопки это умеют.

Xiaomi


Фирма Xiaomi сделала многое для продвижения технологии Zigbee в альтернативных системах умного дома. Их старенький Xiaomi Gateway 2 (DGNWG02LM, lumi.gateway.v3) имел на борту "режим разработчика", который открывал локальный протокол доступа к управлению Zigbee устройствами этого шлюза. Интеграции этого протокола есть в множестве open source систем.


В евро-версии этого шлюза Xiaomi Gateway EU (DGNWG05LM, lumi.gateway.mieu01), а также в обновлённой версии Xiaomi Gateway 3 (ZNDMWG03LM, lumi.gateway.mgl03) этого протокола нет.


Обновлённая версия шлюза получила новый чип на Zigbee 3 (EFR32MG1B), а также поддержку технологии Bluetooth Mesh и HomeKit. В HomeKit поддерживаются не все устройства, будьте внимательны.


Xiaomi Gateway 3


В отличие от всех остальных шлюзов, обновлённая версия имеет уникальную особенность: на ней программно можно открыть Telnet-доступ. Доступ открывается только при наличии Mi Home токена, так что всё вполне секьюрно.


В этом шлюзе стоит чип серии EFR32 от фирмы Silicon Labs. Те в свою очередь поставляют вместе с чипом набор SDK. В составе SDK есть MQTT-транспорт, обеспечивающий доступ к Zigbee проколу из любого ПО, установленного как на шлюзе, так и за его пределами.


По умолчанию MQTT-брокер не доступен извне, но у нас ведь теперь есть Telnet!


В брокере есть два корневых топика: это "сырые" данные Zigbee и обработанные данные от Xiaomi. Я решил взять за основу обработанные данные. Там атрибуты устройств хоть и описаны псевдокодами, но в них всё же проще разобраться человеку, ничего не понимающему в Zigbee.


В итоге получился такой вот компонент для Home Assistant XiaomiGateway3.


Он автоматически включает Telnet и публичный MQTT, используя токен Mi Home.


Сейчас токен нужно получать нехитрым образом (инструкция в readme). Но в будущем я планирую добавить получение токена с серверов Xiaomi, используя аккаунт Mi Home. Ведь недавно в сети появилась рабочая реализация авторизации в их облаке.


Сейчас компонент получает список устройств и последние значения их атрибутов с Хаба. Но в дальнейшем я планирую добавить получение списка устройств из облака. Там есть пользовательские названия всех устройств.


BLE Gateway


С этим пришлось повозиться. Работа с Bluetooth-устройствами не отражается в MQTT. Зато все данные отражаются в консоли. Поэтому компонент подключается к хабу через Telnet отдельным потоком, перезапускает утилиту работы с Bluetooth и читает её вывод в реальном времени. Это самый стабильный способ, что я нашёл. В syslog данные от этой утилиты попадают с перебоями. Моих знаний Linux не хватает, чтоб понять, почему так происходит.


Первым делом компонент научился поддерживать стандартный набор Bluetooth-устройств Xiaomi: датчики температуры, анализаторы почвы и освещенности, фумигатор.


А пару дней назад в нём появилась поддержка умных Bluetooth-замков. На сегодняшний день это единственный из известных мне способов подключить BLE-умный замок Xiaomi в альтернативную систему умного дома.


Чайника у меня нет, но присылайте логи добавлю и его. Правда чайники Xiaomi не поддерживают функцию удалённого включения, это большой минус.


BLE-устройства и их атрибуты отображаются по мере поступления данных. Когда появится поддержка облака полный список BLE устройств с их моделями, именами и последними посланными данными можно будет получить оттуда. Такая информация на хабе не хранится.


Поддержка Bluetooth Mesh ламп пока в разработке. Работа с ними сильно отличается от BLE-устройств.


Планы


Грандиозные.


Нужно отладить работу хаба со всем списком официально поддерживаемых Zigbee-устройств. Добавить возможность настройки "тонких" параметров:


  • настройки хаба: например, мощность (и её можно сильно увеличить!),
  • изменение настроек дочерних устройств: режим логических кнопок на выключателях, чувствительность датчика вибрации и многое другое.

Нужно добавить поддержку облака для получения токена хаба и полного списка Zigbee и Bluetooth-устройств.


Нужно добавить поддержку Bluetooth Mesh ламп.


И самое главное добавить поддержку устройств других производителей. Да, это возможно. Мне удалось подключить все сторонние устройства, что у меня были, и управлять ими. Такие устройства не отображаются в Mi Home и HomeKit. Но управлять ими можно с помощью "сырых" Zigbee-команд.


Для понимания полного масштаба проблемы такой поддержки загляните в исходники замечательного проекта zigbee2mqtt: devices, fromZigbee, toZigbee.


Почти каждое устройство требует свой собственный обработчик. В случае с Xiaomi Gateway 3 и официально поддерживаемыми устройствами роль такого обработчика выполняет софт хаба.


Другие мои разработки можно найти на GitHub. Среди русскоговорящей аудитории наиболее популярный проект YandexStation. Глобально очень хорошо себя зарекомендовал SonoffLAN. Но, думаю, XiaomiGateway3 его легко обгонит. За развитием этого и других моих проектов можно следить на моём канале Telegram.

Подробнее..

Плюсы интеграции Xiaomi Gateway 3 в Home Assistant

30.12.2020 14:14:51 | Автор: admin

Первая версия компонента XiaomiGateway3 для Home Assistant вышла 4 месяца назад, и с тех пор много всего изменилось. В прошлой статье я писал про создание компонента. А в этой статье расскажу, почему это решение так заинтересовало сотни пользователей.

Прошивка шлюза

Эта модель шлюза действительно получилась очень удачной. Иначе как можно объяснить, что компания Xiaomi уже два раза успела обновить прошивку шлюза на своих заводах. Это единственная модель шлюза, у которой прошивка теперь обновляется настолько оперативно на производстве.

В сентябре вышла первая версия компонента. В октябре, после долгих задержек, покупателям начали приходить шлюзы уже с новой прошивкой. В ней Telnet был закрыт паролем. В ноябре прошивка на заводах снова обновилась, и Telnet в ней совсем пропал. Определить проблемный шлюз можно по дате производства на коробке 2020.10 и выше.

В миг шлюз превратился из простого Plug and Play устройства в устройство, которое нужно обязательно вскрыть и прошить для интеграции в альтернативные системы умного дома.

Но шлюз хорош не только своим современным Zigbee-чипом и наличием чипа Bluetooth. Выбранный компанией-производителем SoC от Realtek позволяет в любой момент записать на шлюз любую прошивку, подключив всего три провода UART.

Если вы не любите паять, можно воспользоваться специальной прищепкой с контактами. Есть даже удачные примеры прошивки с бельевой прищепкой. Главное помнить, что обрыв контактов во время прошивки или UART на 5 В вместо 3.3 В вполне могут спалить микросхемы шлюза.

В развитии этого хаба участвует довольно много крутых людей. @serrj-sv собрал скрипт под Windows, который может прошить шлюз в полуавтоматическом режиме. А @zvldz собрал альтернативную версию прошивки, которая на 99% соответствует оригинальной. В ней поправлено недоразумение с закрытым Telnet и ещё пара мелочей. По особенностям прошивки и другим вопросам можно писать в этот чат Telegram.

Все полезные ссылки можно найти в вики проекта.

Поддержка Mi Home

Многие гики не любят облака и стараются с ними не связываться. Идеология облаков нарушает и главный девиз Home Assistant: конфиденциальность прежде всего (privacy first).

С другой стороны, если при данном подходе сохраняется полноценное локальное управление (local control, вторая часть девиза Home Assistant), то ничего страшного в облаках нет.

Экосистемы производителей добавляют устройствам больше свободы и возможностей управления, включая внешний доступ из коробки и прямое подключение к популярным голосовым ассистентам вроде Яндекс.Алисы и Google Assistant.

Также с этим подходом новые пользователи могут плавно осваивать Open Source системы умного дома: если что-то не получается, можно легко продолжить пользоваться устройством в экосистеме производителя.

Да, где-то на китайском сервере будет хранится информация, включен ли у вас в туалете свет. Так ли много на вас компромата у лампочки? Особенно если сравнивать с данными в вашем браузере или смартфоне. А полный доступ к прошивке шлюза позволяет пытливому уму легко отследить, какая именно информация отправляется на родину.

Поддержка Zigbee устройств Xiaomi

Компонент поддерживает:

  • все популярные устройства: выключатели, кнопки, розетки, реле, лампочки, датчики движения, температуры, открытия, протечки, вибрации, газа, дыма, шторы и замки;

  • редкие устройства вроде термостата Aqara Thermostat S2 (KTWKQ03ES) такой термостат пока не поддерживается даже в zigbee2mqtt;

  • самые свежие устройства вроде новых: реле Aqara Relay T1 и высокоточный датчик присутствия Aqara Hight Precision Motion Sensor (RTCGQ13LM).

Альтернатива: разнообразные DIY и коммерческие Zigbee-стики и DIY-хабы. Вот довольно большое русскоязычное сообщество в Telegram, где могут ответить на ваши вопросы по поводу Zigbee.

Поддержка BLE-датчиков Xiaomi

Компонент поддерживает:

  • все популярные датчики: разнообразные датчики температуры с экраном, датчик ухода за растениями, фумигатор, ночник и умный кубик Рубика;

  • редкие устройства вроде сейфа Xiaomi Safe Box (BGX-5/X1-3001) да, есть и такое устройство;

  • самые свежие датчики вроде новых датчиков двери, протечки и движения на технологии BLE;

  • различные дверные замки экосистемы Xiaomi.

Компонент не поддерживает не BLE устройства вроде чайника и самоката Xiaomi.

Альтернатива: шлюз на основе ESP32 или встроенный Bluetooth на сервере умного дома. Обычно этими способами поддерживаются только популярные датчики температуры альтернативной поддержки дверных замков я не встречал.

Поддержка Bluetooth Mesh-ламп

Компонент поддерживает новые Mesh-лампы экосистемы Xiaomi под брендами MiJia и Yeelight. И один китайский пользователь уже второй месяц пытается добавить поддержку Mesh-выключателей. А я никак не найду время рассмотреть его pull request.

Новые лампы очень выгодно отличаются ценой и функциями от аналогов на технологиях Wi-Fi и Zigbee, поэтому к ним стоит присмотреться. Об одной из таких ламп я рассказываю в своей статье про адаптивное освещение.

Альтернатива: на ум приходит только новый хаб Yeelight и подключение его к Home Assistant через протокол HomeKit. Open Source проекты с поддержкой Mesh-ламп я не встречал.

Поддержка Zigbee Home Automation

Пользователи не любят хабы крупных компаний из-за того, что они поддерживают только устройства своего производителя. Так вот Xiaomi Gateway 3 лишен этого недостатка.

Я добавил в него режим, в котором Home Assistant напрямую подключается к Zigbee-чипу хаба через интеграцию Zigbee Home Automation.

Конечно, у подхода есть минусы:

  • Zigbee-чип перестаёт работать с Mi Home и начинает работать только с Home Assistant;

  • по количеству поддерживаемых устройств ZHA сильно уступает проекту zigbee2mqtt.

Но есть и плюсы:

  • в Китае не узнают, включен ли у вас в туалете свет;

  • в любой момент можно вернуть хаб в обычный режим работы c Mi Home без последствий для родной прошивки хаба;

  • BLE-датчики и Mesh-лампы продолжают работать в этом режиме;

  • команда Home Assistant активно развивает проект ZHA в рамках своей основной работы.

Альтернатива: шлюз Sonoff ZBBridge, прошитый Tasmota.

Поддержка сторонних устройств в Mi Home

В некоторых случаях для поддержки сторонних Zigbee-устройств режим ZHA включать не обязательно.

Изучая проблему, почему лампы IKEA E27 из российских магазинов не подключаются к хабам Xiaomi, я пришел к выводу, что в хабах зашита поддержка лишь семи моделей ламп, хотя проект zigbee2mqtt поддерживает более 30 моделей ИКЕА.

Дело осталось за малым вместо настоящей модели лампы подсунуть хабу ту, которую он поддерживает. Реализовать код, организующий подмену модели устройства в момент добавления устройства в хаб, оказалось несложно. Как оказалось, этот способ отлично подошёл для диммеров и реле других фирм.

И самое интересное в данном способе то, что устройства работают и управляются в Mi Home без участия Home Assistant. И могут участвовать в автоматизациях.

Конечно, не стоит рассчитывать, что таким образом заработают любые устройства. Например, у меня не получилось заставить работать лампочки и датчик Philips Hue, а также кнопку Sonoff. А умные розетки, добавленные таким образом, не показывают энергопотребление.

Интеграция с облаком

Компонент поддерживает опциональную интеграцию с облаком. При этом компонентом можно пользоваться и без интеграции с облаком, просто добавив шлюз по IP-адресу и токену Mi Home.

Но если вы авторизуетесь в облаке Xiaomi, все данные о шлюзе загрузятся автоматически. Кроме адреса и токена шлюза из облака загрузятся все имена ваших Zigbee, BLE и Mesh-устройств. Вам не придётся снова заполнять их в Home Assistant, выясняя, что за устройство скрывается за именем 0x00158D0007396A5D.

Получение токенов любых Xiaomi устройств

Помимо получения данных о шлюзе и его устройствах - облачная интеграция позволяет получить Mi Home токены от любых Wi-Fi устройств в вашем аккаунте. Если ваш аккаунт использует одновременно разные сервера (например, европейский и китайский), это тоже поддерживается.

Функция получения токенов работает даже если у вас нет шлюза Xiaomi Gateway 3.

Расширенные настройки устройств

Один из самых популярных Zigbee-датчиков в экосистеме Xiaomi это датчик движения. Ранее я пользовался вторым шлюзом Xiaomi и писал автоматизации для этого датчика в Node-RED.

Довольно давно я придумал автоматизацию прогрессивного таймера для датчика движения с опцией быстрого возвращения. Первое движение человека перед датчиком запускало небольшой таймер, а следующие движения - запускали уже увеличенный таймер. Таким образом при постоянном нахождении в комнате свет мог гореть дольше, а при кратковременном пробегании мимо датчика - свет выключался быстро. Хорошо работает в помещении вроде кухни.

Также при обнаружении движения сразу после выключения света - свет включался с увеличенным таймером. Полезно, когда свет выключается не вовремя и злой человек машет рукой датчику.

Логика работы показана на картинке

Мониторинг работы устройств

Радиосвязь всегда менее надёжнее провода. Сигнал от датчика может по разным причинам не дойти в центр. Zigbee и Bluetooth работают на той же частоте, что Wi-Fi и микроволновки.

Для обнаружения возможных проблем в компоненте есть опциональная статистика по каждому Zigbee и BLE устройству.

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

Хотя многие привыкли судить о стабильности в сети именно по качеству сигнала, на мой взгляд именно количество пропущенных сообщений является наиболее показательной величиной.

Именно этот показатель помог мне выпустить две заплатки и уменьшить количество пропусков срабатывания у популярного датчика движения Aqara Motion Sensor. Одна заплатка попала в компонент Home Assistant, а вторая в проект zigbee2mqtt.

Перспективы развития

За четыре месяца компонент оброс огромным количеством функционала и успел получить более 400 звёзд на GitHub. Но мысли по дальнейшему развитию и не думают кончаться.

Ещё остаётся добавить корректную работу с Bluetooth-устройствами при использовании нескольких хабов на одном сервере Home Assistant. Дело в том, что BLE датчики и Mesh-лампы не привязаны к какому-либо одному хабу. Все хабы могут получать данные с окружающих сенсоров и управлять окружающими лампами. Кстати огромный плюс в сравнении с технологией Zigbee.

Так же в планах добавить настройку параметров дочерних устройств - режим interlock в реле Aqara (переключатель пропал в последних версиях приложения Mi Home), чувствительность и задержки между срабатываниями нового датчика присутствия Aqara и многие другие.

Отдельным направление развития остаётся поддержка конвертеров проекта zigbee2mqtt. Если его удастся довести до релиза, пользователь сможет выбрать, как именно подключать имеющиеся у него устройства:

  • оригинальное ПО Xiaomi - готово

  • интеграция Zigbee Home Automation - готово

  • конвертеры zigbee2mqtt - есть рабочий прототип

И что немаловажно - переключаться между режимами можно в любой момент без последствий для оригинальной прошивки хаба.

На моём GitHub можно найти ссылки на другие компоненты и статьи. А за их развитием можно следить на моём канале в Telegram.

Подробнее..

Перевод Android Bluetooth Low Energy (BLE) готовим правильно, часть 1

07.01.2021 20:09:56 | Автор: admin

В последний год я разрабатывал Bluetooth Low Energy (BLE) приложения под iOS и это оказалось довольно простым. Далее было портирование их на Android насколько это могло быть сложным?

Могу точно сказать это было сложней, чем представлял, мне пришлось приложить немало усилий для стабильной работы под Android. Я изучил много статей в свободном доступе, некоторые оказались ошибочными, многие были очень полезными и помогли в деле. В этой серии статей я хочу описать свои выводы, чтобы вы не тратили уйму времени на поиски как я.

Особенности работы BLE под Android

  • Google документация по BLE очень общая, в некоторых случаях нет важной информации или она устарела, примеры приложений не показывают, как правильно использовать BLE. Я обнаружил лишь несколько источников, как правильно сделать BLE.Презентация Stuart Kentдает замечательный материал для старта. Для некоторых продвинутых тем есть хорошая статьяNordic.

  • Android BLE API это низкоуровневые операции, в реальных приложениях нужно использовать несколько слоев абстракции (как например сделано из коробки в iOS-CoreBluetooth). Обычно нужно самостоятельно сделать: очередь команд, bonding, обслуживание соединений, обработка ошибок и багов, мультипоточный доступ . Самые известные библиотеки:SweetBlue,RxAndroidBleиNordic. На мой взгляд самая легкая для изучения - Nordic,см. детали тут.

  • Производители делают изменения в Android BLE стекеили полностью заменяют на свою реализацию. И надо учитывать разницу поведения для разных устройств в приложении. То что прекрасно работает на одном телефоне, может не работать на других! В целом не все так плохо, например реализация Samsung сделана лучше собственной реализации от Google!

  • В Android есть несколько известных (и неизвестных) баговкоторые должны быть обработаны, особенно в версиях 4,5 и 6. Более поздние версии работают намного лучше, но тоже имеют определенные проблемы, такие как случайные сбои соединения с ошибкой 133. Подробнее об этом ниже.

Не претендую на то, что я решил все проблемы, но мне удалось выйти на приемлемый уровень. Начнем со сканирования.

Сканирование устройств

Перед подключением к устройству вам нужно его просканировать. Это делается при помощи классаBluetoothLeScanner:

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();if (scanner != null) {    scanner.startScan(filters, scanSettings, scanCallback);    Log.d(TAG, "scan started");}  else {    Log.e(TAG, "could not get scanner object");}

Сканер пытается найти устройства в соответствии снастройками filtersиscanSettings, при обнаружении устройства вызываетсяscanCallback:

private final ScanCallback scanCallback = new ScanCallback() {    @Override    public void onScanResult(int callbackType, ScanResult result) {        BluetoothDevice device = result.getDevice();        // ...do whatever you want with this found device    }    @Override    public void onBatchScanResults(List<ScanResult> results) {        // Ignore for now    }    @Override    public void onScanFailed(int errorCode) {        // Ignore for now    }};

В результате сканирования мы получаем экземплярScanResult, в котором есть объектBluetoothDevice, его используют для подключения к устройству. Но прежде чем начать подключаться, поговорим о сканировании подробнее,ScanResultсодержит несколько полезных сведений об устройстве:

  • Advertisement data- массив байтов с информацией об устройстве, для большинства устройств это имя и UUID сервисов, можно задать вfiltersимя устройства и UUID сервисов для поиска конкретных устройств.

  • RSSI уровень- уровень сигнала (насколько близко устройство).

  • дополнительные данные, см. документацию поScanResultздесь.

Помним про жизненный циклActivity,onScanResultможет вызываться многократно для одних и тех же устройств, при пересозданииActivityсканирование может запускаться повторно, вызываю лавину вызововonScanResult.

Настраиваем фильтр для сканирования

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

Сканирование устройств по UUID сервиса

Используется если вам необходимо найти устройства определенной категории, например мониторы артериального давления со стандартным сервисным UUID: 1810. При сканировании устройство может содержать вAdvertisement dataUUID сервис, который характеризует это устройство. На самом деле эти данные ненадежные, фактически сервисы могут не поддерживаться, или подделыватьсяAdvertisement dataданные, в общем тут есть творческий момент.

Прим. переводчика: одно из моих устройств со специфичной прошивкой, вообще не содержало список UUID сервисов вAdvertisement data, хотя все остальные прошивки этого устройства работали ожидаемо.

Пример сканирования службы с артериальным давлением:

UUID BLP_SERVICE_UUID = UUID.fromString("00001810-0000-1000-8000-00805f9b34fb");UUID[] serviceUUIDs = new UUID[]{BLP_SERVICE_UUID};List<ScanFilter> filters = null;if(serviceUUIDs != null) {    filters = new ArrayList<>();    for (UUID serviceUUID : serviceUUIDs) {        ScanFilter filter = new ScanFilter.Builder()                .setServiceUuid(new ParcelUuid(serviceUUID))                .build();        filters.add(filter);    }}scanner.startScan(filters, scanSettings, scanCallback);

Обратите внимание на короткий UUID (например1810), он называется16-bit UUIDи является частью длинного128-bit UUID(в данном случае00001810-000000-1000-8000-000-00805f9b34fb). Короткий UUID это BASE_PART длинного UUID, см. спецификациюздесь.

Сканирование устройств по имени

Поиск устройств использует точное совпадение имени устройства, обычно это применяется в двух случаях:

  • поиск конкретного устройства

  • поиск конкретной модели устройства, например, мой нагрудный напульсник Polar H7 определяется как Polar H7 391BBB014, первая часть - Polar H7 общая для всех таких устройств этой модели, а последняя часть 391BBB014 - уникальный серийный номер. Это очень распространенная практика. Если вы хотите найти все устройства Polar H7, то фильтр по имени вам не поможет, придется искать подстроку у всех отсканированных устройств вScanResult. Пример с поискомточнопо имени:

String[] names = new String[]{"Polar H7 391BB014"};List<ScanFilter> filters = null;if(names != null) {    filters = new ArrayList<>();    for (String name : names) {        ScanFilter filter = new ScanFilter.Builder()                .setDeviceName(name)                .build();        filters.add(filter);    }}scanner.startScan(filters, scanSettings, scanCallback);

Сканирование устройств по MAC-адресам.

Обычно применяется дляпереподключенияк уже известным устройствам. Обычно мы не знаем MAC-адрес девайса, если не сканировали его раньше, иногда адрес печатается на коробке или на корпусе самого устройства, особенно это касается медицинских приборов. Существует другой способ повторного подключения, но в некоторых случаях придется еще раз сканировать устройство, например при очистке кеша Bluetooth.

String[] peripheralAddresses = new String[]{"01:0A:5C:7D:D0:1A"};// Build filters listList<ScanFilter> filters = null;if (peripheralAddresses != null) {    filters = new ArrayList<>();    for (String address : peripheralAddresses) {        ScanFilter filter = new ScanFilter.Builder()                .setDeviceAddress(address)                .build();        filters.add(filter);    }}scanner.startScan(filters, scanSettings, scanByServiceUUIDCallback);

Вероятно вы уже поняли, что можно комбинировать в фильтре UUID, имя и MAC-адрес устройства. Выглядит неплохо, но на практике я не применял такое. Хотя может быть вам это пригодится.

Настройка ScanSettings

ScanSettings объясняют Android как сканировать устройства. Там есть ряд настроек, которые можно задать, ниже полный пример:

ScanSettings scanSettings = new ScanSettings.Builder()        .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)        .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)        .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)        .setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)        .setReportDelay(0L)        .build();

ScanMode

Безусловно, это самый важный параметр. Определяет метод и время сканирования в Bluetooth стеке. Такая операция требует много энергии и необходим контроль над этим процессом, чтобы не разрядить батарею телефона быстро. Есть 4 режима работы, в соответствии с руководствомNordics и официальной документацией:

  1. SCAN_MODE_LOW_POWER. В этом режиме Android сканирует 0.5с, потом делает паузу на 4.5с. Поиск может занять относительно длительное время, зависит от того насколько часто устройство посылает пакет advertisement данных.

  2. SCAN_MODE_BALANCED. Время сканирования: 2с, время паузы: 3с, компромиссный режим работы.

  3. SCAN_MODE_LOW_LATENCY. В этом случае, Android сканирует непрерывно, что очевидно требует больше энергозатрат, при этом получаются лучшие результаты сканирования. Режим подходит если вы хотите найти свое устройство как можно быстрее. Не стоит использовать для длительного сканирования.

  4. SCAN_MODE_OPPORTUNISTIC. Результаты будут получены, если сканирование выполняется другими приложениями! Строго говоря, это вообще не гарантирует, что обнаружится ваше устройство. Стек Android использует этот режим в случае долгого сканирования, для понижения качества результатов (см. ниже Непрерывное сканирование).

Callback Type

Эта настройка контролирует как будет вызываться callback соScanResultв соответствии с заданными фильтрами, есть 3 варианта:

  1. CALLBACK_TYPE_ALL_MATCHES. Callback будет вызывать каждый раз, при получении advertisement пакета от устройств. На практике - каждые 200-500мс будет срабатывать сallback, в зависимости от частоты отправки advertisement пакетов устройствами.

  2. CALLBACK_TYPE_FIRST_MATCH. Callback сработает один раз для устройства, даже если оно далее будет снова посылать advertisement пакеты.

  3. CALLBACK_TYPE_MATCH_LOST. Callback будет вызван, если получен первый advertisement пакет от устройства и дальнейшие advertisement пакеты не обнаружены. Немного странное поведение.

В практике обычно используются настройкаCALLBACK_TYPE_ALL_MATCHESилиCALLBACK_TYPE_FIRST_MATCH. Правильный тип зависит от конкретного случая. Если не знаете - используйтеCALLBACK_TYPE_ALL_MATCHES, это дает больше контроля при получении callback, если вы останавливаете сканирование после получения нужных результатов - фактически этоCALLBACK_TYPE_FIRST_MATCH.

Match mode

Настройка того, как Android определяет совпадения.

  1. MATCH_MODE_AGGRESSIVE. Агрессивность обуславливается поиском минимального количества advertisement пакетов и устройств даже со слабым сигналом.

  2. MATCH_MODE_STICKY. В противоположность, этот режим требует большего количества advertisement пакетов и хорошего уровня сигнала от устройств.

Я не тестировал эти настройки подробно, но я в основном используюMATCH_MODE_AGGRESSIVE, это помогает быстрее найти устройства.

Number of matches

Параметр определяет сколько advertisement данных необходимо для совпадения.

  1. MATCH_NUM_ONE_ADVERTISEMENT. Одного пакета достаточно.

  2. MATCH_NUM_FEW_ADVERTISEMENT. Несколько пакетов нужно для соответствия.

  3. MATCH_NUM_MAX_ADVERTISEMENT. Максимальное количество advertisement данных, которые устройство может обработать за один временной кадр.

Нет большой необходимости в таком низкоуровневом контроле. Все что вам надо - быстро найти свое устройство, обычно используются первые 2 варианта.

Report delay

Задержка для вызова сallback в миллисекундах. Если она больше нуля, Android будет собирать результаты в течение этого времени и вышлет их сразу все в обработчикеonBatchScanResults. Важно понимать чтоonScanResultне будет вызываться. Обычно применяется, когда есть несколько устройств одного типа и мы хотим дать пользователю выбрать одно из них. Единственная проблема здесь - предоставить информацию пользователю для выбора, это должен быть не только MAC-адрес (например имя устройства).

Важно: естьизвестный багдля Samsung S6 / Samsung S6 Edge, когда все результаты сканирования имеют один и тот же RSSI (уровень сигнала) при задержке больше нуля.

Кеширование Android Bluetooth стека

В результате процесса сканирования вы получаете список BLE устройств и при этом данные устройств кешируются в Bluetooth стеке. Там хранится основная информация: имя, MAC-адрес, тип адреса (публичный, случайный), тип устройства (Classic, Dual, BLE) и т.д. Android нужны эти данные, чтобы подключится к устройству быстрее. Он кеширует все устройства, которые видит при сканировании. Для каждого из них записывается небольшой файл с данными. Когда вы пытаетесь подключиться к устройству, стек Android ищет соответствующий файл, чтобы прочитать данные для подключения. Важный момент - одного MAC-адреса недостаточно для успешного подключения к устройству!

Очистка кеша

Bluetooth кеш, как и любой другой, не существует вечно, есть 3 ситуации, когда он очищается:

  1. Выключение и включение системного переключателя Bluetooth

  2. Перезагрузка телефона

  3. Очистка данных приложения (в ручном режиме в настройках телефона)

Это достаточно неудобный момент для разработчиков, потому что телефон часто перезагружается, пользователь может включать-выключать самолетный режим. Есть еще различия между производителями телефонов, например на некоторых телефонах Samsung, кеш не очищался при выключении Bluetooth.

Это значит, что нельзя полагаться на данные об устройстве из BT кеша. Есть небольшой трюк, он поможет узнать закешировано ли устройство или нет:

// Get device object for a mac addressBluetoothDevice device = bluetoothAdapter.getRemoteDevice(peripheralAddress)// Check if the peripheral is cached or notint deviceType = device.getType();if(deviceType == BluetoothDevice.DEVICE_TYPE_UNKNOWN) {    // The peripheral is not cached} else {    // The peripheral is cached}

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

Непрерывное сканирование?

Вообще хорошая практика избегать непрерывного сканирования потому что, это очень энергоемкая операция, а пользователи любят, когда батарея их смартфона работает долго. Если вам действительно нужно постоянное сканирование, например при поиске BLE-маячков, выберите настройки сканирования с низким потреблением и ограничивайте время сканирования, например когда приложение находится только на переднем плане (foreground), либо сканируйте с перерывами.

Плохая новость в том, что Google в последнее время ограничивает (неофициально) непрерывное сканирование:

Непрерывное сканирование в фоне

Google значительно усложнил сканирование на переднем плане. Для фонового режима вы столкнетесь с еще большими трудностями! Новые версии Android имеют лимиты на работу служб в фоновом режиме, обычно после 10 минут работы, фоновый сервис прекращает свою работу принудительно. Посмотрите возможные решения этой проблемы:

Проверка разрешений (permissions)

Есть еще несколько важных моментов, прежде чем мы закончим статью. Для начала сканирования нужны системные разрешения (permissions):

<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Убедитесь, что все разрешения одобрены, или запросите их у пользователя. РазрешениеACCESS_COARSE_LOCATIONGoogle считает опасным и для него требуется обязательное согласие пользователя.

private boolean hasPermissions() {    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {        if (getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {            requestPermissions(new String[] { Manifest.permission.ACCESS_COARSE_LOCATION }, ACCESS_COARSE_LOCATION_REQUEST);            return false;        }    }    return true;}

Прим. переводчика, в моем проекте для корректной работы с BLE потребовалось еще 2 разрешения:ACCESS_FINE_LOCATION(для API<23) иACCESS_BACKGROUND_LOCATIONобсуждение на Stackoverflow.

В итоге полный список разрешений включая версию Android10:

<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

После получения всех нужный разрешений, нужно проверить включен Bluetooth, если нет - используйтеIntentдля запуска запроса на включение:

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (!bluetoothAdapter.isEnabled()) {    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}

Заключение

Мы научились запускать сканирование BLE устройств с учетом жизненного цикла Activity (Fragment / Service), использовать фильтры и различные настройки сканирования, также узнали все нужные разрешения (permissions) для удачного запуска сканирования и особенности работы Android-Bluetooth кеша. В следующей статье мы погрузимся глубже в процесс подключения и отключения к устройствам.

Спасибо!

Подробнее..

Перевод Android Bluetooth Energy (BLE) готовим правильно, часть 3 (readwrite)

22.01.2021 20:15:37 | Автор: admin

Содержание

Часть #1 (scanning)

Часть #2 (connecting/disconnecting)

Часть #3 (read/write), вы здесь

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

Чтение и запись характеристик

Многие разработчики, которые начинают работать с BLE на Android, сталкиваются с проблемами чтения/записи BLE характеристик. НаStackoverflowполно людей, предлагающих просто использовать задержки Большинство таких советов неверные.

Есть две основные причины проблем:

  • Операции чтения/записи асинхронные. Это значит, что вызов метода вернется немедленно, но результат вызова вы получите немного позже в соответствующих колбеках. НапримерonCharacteristicRead()илиonCharacteristicWrite().

  • Одновременно может быть запущена только одна операция. Нужно дождаться выполнения текущей операции, и затем, запускать следующую. В исходном кодеBluetoothGattесть блокирующая переменная, которая при запуске операции устанавливается и при вызове колбека сбрасывается. Google забыла про это упомянуть в документации (Прим. переводчика: речь идет оmDeviceBusyиmDeviceBusyLockздесь).

Первая причина, на самом деле, не является проблемой, такова природа BLE. Асинхронное программирование это распространенная штука, используется, например, при сетевых вызовах. Однако вторая причина раздражает и требует специального подхода.

Ниже кусок кодаBluetoothGatt.javaс блокировкой переменнойmDeviceBusy, перед чтением характеристики:

public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {    if ((characteristic.getProperties()             & BluetoothGattCharacteristic.PROPERTY_READ) == 0) {        return false;    }    if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());    if (mService == null || mClientIf == 0) return false;    BluetoothGattService service = characteristic.getService();    if (service == null) return false;    BluetoothDevice device = service.getDevice();    if (device == null) return false;    synchronized (mDeviceBusy) {        if (mDeviceBusy) return false;        mDeviceBusy = true;    }    try {        mService.readCharacteristic(mClientIf, device.getAddress(),                characteristic.getInstanceId(), AUTHENTICATION_NONE);    } catch (RemoteException e) {        Log.e(TAG, "", e);        mDeviceBusy = false;        return false;    }    return true;}

Когда приходит результат чтения/записи, переменнаяmDeviceBusyсбрасывается в false снова:

public void onCharacteristicRead(String address,                                 int status,                                 int handle,                                 byte[] value) {    if (VDBG) {        Log.d(TAG, "onCharacteristicRead() - Device=" + address                + " handle=" + handle + " Status=" + status);    }    if (!address.equals(mDevice.getAddress())) {        return;    }    synchronized (mDeviceBusy) {        mDeviceBusy = false;    }....

Используем очередь

Выполнять чтение/запись по одной операции за раз неудобно, но любое сложное приложение должно это учитывать. Решение этой проблемы - использованиеочереди команд. Все BLE библиотеки, которые я ранее упоминал, так или иначе реализуют очередь. Это одна из лучших практик! Идея простая каждая команда сначала добавляется в очередь. Затем команда забирается из очереди на исполнение, после результата, команда помечается как завершенная и, удаляется из очереди. Запускать команды можно в любое время, но они выполняются точно в том порядке, в котором поступают в очередь. Это очень упрощает разработку под BLE. В iOS аналогично работает фреймворкCoreBluetooth(Прим. переводчика: который намного удобнее, чем реализация Bluetooth стека в Android).

Очередь создается для каждого объектаBluetoothGatt. К счастью, Android сможет обрабатывать очереди от нескольких объектовBluetoothGatt, вам не нужно об этом беспокоиться (Прим. переводчика: у меня это не сработало, я использовал глобальную очередь команд для всех устройств). Есть много способов создать очередь, мы будем использовать простую очередьQueueсRunnableдля каждой команды и переменнойcommandQueueBusyдля отслеживания работы команды:

private Queue<Runnable> commandQueue;private boolean commandQueueBusy;

Мы добавляем новый экземплярRunnableв очередь при выполнении команды. Ниже пример чтения характеристики (readCharacteristic):

public boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {    if(bluetoothGatt == null) {        Log.e(TAG, "ERROR: Gatt is 'null', ignoring read request");        return false;    }    // Check if characteristic is valid    if(characteristic == null) {        Log.e(TAG, "ERROR: Characteristic is 'null', ignoring read request");        return false;    }    // Check if this characteristic actually has READ property    if((characteristic.getProperties() & PROPERTY_READ) == 0 ) {        Log.e(TAG, "ERROR: Characteristic cannot be read");        return false;    }    // Enqueue the read command now that all checks have been passed    boolean result = commandQueue.add(new Runnable() {        @Override        public void run() {            if(!bluetoothGatt.readCharacteristic(characteristic)) {                Log.e(TAG, String.format("ERROR: readCharacteristic failed for characteristic: %s", characteristic.getUuid()));                completedCommand();            } else {                Log.d(TAG, String.format("reading characteristic <%s>", characteristic.getUuid()));                nrTries++;            }        }    });    if(result) {        nextCommand();    } else {        Log.e(TAG, "ERROR: Could not enqueue read characteristic command");    }    return result;}

В этом методе, сначала проверяем все ли готово для выполнения (наличие и тип характеристики) и логгируем ошибки, если они есть. ВнутриRunnable, фактически вызывается методreadCharacteristic(), который выдает команду на устройство. Мы также отслеживаем сколько было попыток, чтобы сделать повтор в случае ошибки (Прим. переводчика: это лучшая тактика, чтобы добиться стабильной работы с устройством). Если чтение характеристики возвращаетfalse, мы логгируем ошибку, завершаем команду, чтобы можно было запустить следующую. Наконец вызываетсяnextCommand(), чтобы запустить следующую команду из очереди:

private void nextCommand() {    // If there is still a command being executed then bail out    if(commandQueueBusy) {        return;    }    // Check if we still have a valid gatt object    if (bluetoothGatt == null) {        Log.e(TAG, String.format("ERROR: GATT is 'null' for peripheral '%s', clearing command queue", getAddress()));        commandQueue.clear();        commandQueueBusy = false;        return;    }    // Execute the next command in the queue    if (commandQueue.size() > 0) {        final Runnable bluetoothCommand = commandQueue.peek();        commandQueueBusy = true;        nrTries = 0;        bleHandler.post(new Runnable() {            @Override            public void run() {                    try {                        bluetoothCommand.run();                    } catch (Exception ex) {                        Log.e(TAG, String.format("ERROR: Command exception for device '%s'", getName()), ex);                    }            }        });    }}

Обратите внимание, мы используем методpeek()для получения объектаRunnableиз очереди, чтобы можно было повторить запуск позже. Этот метод не удаляет объект из очереди.

Результат чтения будет отправлен в ваш колбек:

@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,                                 final BluetoothGattCharacteristic characteristic,                                 int status) {    // Perform some checks on the status field    if (status != GATT_SUCCESS) {        Log.e(TAG, String.format(Locale.ENGLISH,"ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));        completedCommand();        return;    }    // Characteristic has been read so processes it       ...    // We done, complete the command    completedCommand();}

Мы завершаем командуcompletedCommand()после обработки нового значения. Это помогает избежать одновременный вызов другой команды и состояния гонки.

Теперь мы готовы завершить команду, убираемRunnableиз очереди через вызовpoll()и запускаем следующую из очереди:

private void completedCommand() {    commandQueueBusy = false;    isRetrying = false;    commandQueue.poll();    nextCommand();}

В некоторых случаях (ошибка, неожиданное значение), вам нужно будет повторить команду. Сделать это просто, так как объектRunnableостается в очереди до вызоваcompletedCommand(). Чтобы не уйти в бесконечное повторение проверяем лимит на повторы:

private void retryCommand() {    commandQueueBusy = false;    Runnable currentCommand = commandQueue.peek();    if(currentCommand != null) {        if (nrTries >= MAX_TRIES) {            // Max retries reached, give up on this one and proceed            Log.v(TAG, "Max number of tries reached");            commandQueue.poll();        } else {            isRetrying = true;        }    }    nextCommand();}

Запись характеристик

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

  • WRITE_TYPE_DEFAULT(вы получите ответ от устройства, например, код завершения);

  • WRITE_TYPE_NO_RESPONSE(никакого ответа от устройства не будет).

Использовать тот или иной тип зависит от вашего устройства и характеристики (иногда она поддерживает оба типа записи, иногда только один конкретный тип).

В Android каждая характеристика имеет дефолтный тип записи, который определяется при ее создании. Ниже фрагмент кода из исходников Android, где определяется тип:

...if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) {    mWriteType = WRITE_TYPE_NO_RESPONSE;} else {    mWriteType = WRITE_TYPE_DEFAULT;}...

Как вы видите, это работает нормально, если характеристика поддерживает только один их двух типов записи. Если характеристика поддерживает оба типа, то значение по умолчанию будетWRITE_TYPE_NO_RESPONSE. Имейте это ввиду!

Перед записью можно проверить характеристику, поддерживает ли она нужный тип записи:

// Check if this characteristic actually supports this writeTypeint writeProperty;switch (writeType) {    case WRITE_TYPE_DEFAULT: writeProperty = PROPERTY_WRITE; break;    case WRITE_TYPE_NO_RESPONSE : writeProperty = PROPERTY_WRITE_NO_RESPONSE; break;    case WRITE_TYPE_SIGNED : writeProperty = PROPERTY_SIGNED_WRITE; break;    default: writeProperty = 0; break;}if((characteristic.getProperties() & writeProperty) == 0 ) {    Log.e(TAG, String.format(Locale.ENGLISH,"ERROR: Characteristic <%s> does not support writeType '%s'", characteristic.getUuid(), writeTypeToString(writeType)));    return false;}

Я рекомендую всегда явно указывать тип записи и не полагаться на дефолтные настройки выбранные Android!

Итак, запись массива байтовbytesToWriteв характеристику выглядит так:

characteristic.setValue(bytesToWrite);characteristic.setWriteType(writeType);if (!bluetoothGatt.writeCharacteristic(characteristic)) {    Log.e(TAG, String.format("ERROR: writeCharacteristic failed for characteristic: %s", characteristic.getUuid()));    completedCommand();} else {    Log.d(TAG, String.format("writing <%s> to characteristic <%s>", bytes2String(bytesToWrite), characteristic.getUuid()));    nrTries++;}

Включение/выключение уведомлений

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

Для включения уведомлений нужно сделать две вещи в Android:

  1. вызватьsetCharacteristicNotification. Bluetooth стек будет ожидать уведомления для этой характеристики.

  2. записать1или2какunsigned int16в дескриптор конфигурации характеристик (Client Characteristic Configuration, сокращенно - ССС). Дескриптор CCC имеет короткий UUID2902.

Почему1или2? Потому что под капотом Bluetooth стека есть Уведомление и Индикация. Полученное Уведомление не подтверждаются стеком Bluetooth, а Индикация наоборот подтверждается стеком. При использовании Индикации, устройство будет точно знать, что данные получены и может их, например, удалить из локального хранилища. С точки зрения Android приложения нет разницы: в обоих случаях вы просто получите массив байтов и Bluetooth стек уведомит устройство об этом, если вы используете Индикацию. Итак,1включает уведомления,2 индикацию. Чтобы выключить их, записываем0. Вы должны самостоятельно определить, что записать в дескриптор CCC.

В iOS методsetNotify()делает всю работу за вас. Ниже пример, как сделать тоже самое на Android, там сначала идут проверки входных параметров, определяется что записать в дескриптор и, наконец команда отправляется в очередь:

private final String CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";public boolean setNotify(BluetoothGattCharacteristic characteristic,                         final boolean enable) {    // Check if characteristic is valid    if(characteristic == null) {        Log.e(TAG, "ERROR: Characteristic is 'null', ignoring setNotify request");        return false;    }    // Get the CCC Descriptor for the characteristic    final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CCC_DESCRIPTOR_UUID));    if(descriptor == null) {        Log.e(TAG, String.format("ERROR: Could not get CCC descriptor for characteristic %s", characteristic.getUuid()));        return false;    }    // Check if characteristic has NOTIFY or INDICATE properties and set the correct byte value to be written    byte[] value;    int properties = characteristic.getProperties();    if ((properties & PROPERTY_NOTIFY) > 0) {        value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;    } else if ((properties & PROPERTY_INDICATE) > 0) {        value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;    } else {        Log.e(TAG, String.format("ERROR: Characteristic %s does not have notify or indicate property", characteristic.getUuid()));        return false;    }    final byte[] finalValue = enable ? value : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;    // Queue Runnable to turn on/off the notification now that all checks have been passed    boolean result = commandQueue.add(new Runnable() {        @Override        public void run() {            // First set notification for Gatt object  if(!bluetoothGatt.setCharacteristicNotification(descriptor.getCharacteristic(), enable)) {                Log.e(TAG, String.format("ERROR: setCharacteristicNotification failed for descriptor: %s", descriptor.getUuid()));            }            // Then write to descriptor            descriptor.setValue(finalValue);            boolean result;            result = bluetoothGatt.writeDescriptor(descriptor);            if(!result) {                Log.e(TAG, String.format("ERROR: writeDescriptor failed for descriptor: %s", descriptor.getUuid()));                completedCommand();            } else {                nrTries++;            }        }    });    if(result) {        nextCommand();    } else {        Log.e(TAG, "ERROR: Could not enqueue write command");    }    return result;}

Результат записи в CCC дескриптор обрабатывается в колбекеonDescriptorWrite. Здесь вы должны отличить запись в CCC от записей в другие дескрипторы. Во время обработки колбека, мы также должны хранить, какие в данный момент характеристики уведомляются.

@Overridepublic void onDescriptorWrite(BluetoothGatt gatt,                                 final BluetoothGattDescriptor descriptor,                                 final int status) {    // Do some checks first    final BluetoothGattCharacteristic parentCharacteristic = descriptor.getCharacteristic();    if(status!= GATT_SUCCESS) {        Log.e(TAG, String.format("ERROR: Write descriptor failed value <%s>, device: %s, characteristic: %s", bytes2String(currentWriteBytes), getAddress(), parentCharacteristic.getUuid()));    }    // Check if this was the Client Configuration Descriptor  if(descriptor.getUuid().equals(UUID.fromString(CCC_DESCRIPTOR_UUID))) {        if(status==GATT_SUCCESS) {            // Check if we were turning notify on or off            byte[] value = descriptor.getValue();            if (value != null) {                if (value[0] != 0) {                    // Notify set to on, add it to the set of notifying characteristics          notifyingCharacteristics.add(parentCharacteristic.getUuid());                    }                } else {                    // Notify was turned off, so remove it from the set of notifying characteristics               notifyingCharacteristics.remove(parentCharacteristic.getUuid());                }            }        }        // This was a setNotify operation        ....    } else {        // This was a normal descriptor write....        ...        });    }    completedCommand();}

Чтобы узнать из какой характеристики пришло уведомление используйте методisNotifying():

public boolean isNotifying(BluetoothGattCharacteristic characteristic) {    return notifyingCharacteristics.contains(characteristic.getUuid());}

Лимиты на установку уведомлений

К сожалению, нельзя включить столько уведомлений, сколько хочешь. Начиная с Android-5 лимит равен 15. В более старых версиях он был равен 7 или даже 4. Большинство смартфонов поддерживают 15 уведомлений. Не забывайте отключать их, если они вам больше не нужны, чтобы не исчерпать лимит.

Проблемы с потоками

Итак, мы научились читать/писать характеристики, включать/выключать уведомления, а значит готовы использовать это в реальном проекте. Я думаю, что устройства BLE можно разделить на две категории:

  • Простые устройства. Например, термометр, который использует официальный Bluetooth Health Thermometer сервис. Такие устройства легко использовать, вы просто включаете уведомления и данные начинают поступать. Здесь мы используем только операции чтения характеристики, запись не нужна;

  • Сложные устройства. Это может быть любое устройство, но обычно все они используют свой внутренний протокол обмена данными. Часто эти протоколы не спроектированы под BLE, а просто транслируют внутренний последовательный протокол в BLE, где одна характеристика используется для отправки данных, а другая для приема. Сложность в том, что вам требуется знать большое количество команд для работы с устройством: авторизация, обновление пользовательских параметров, параметров самого устройства, получение сохраненных данных и т.д.

Простые устройства обычно не создают проблем с потоками, для сложных следует работать внимательно. Чтение, запись и уведомления в этом случае будут чередоваться и могут мешать друг другу, особенно если у вас устройство с высокой частотой передачи данных (30Hz или около).

Типичная проблема с потоками выглядит так:

  • приходит уведомление

  • вы отправляете событие в свою собственную очередь для обработки

  • запускается обработку полученных данных

  • в это время приходит новое уведомление и перезаписывает предыдущее значение вBluetoothGattCharacteristic

  • если ваша обработка данных медленная, вы потенциально теряете значение из первого уведомления.

Причины такого поведения:

  • как только сообщение доставлено, Android будет отправлять следующее(если оно есть). Посколько обработка данных отправляется в другой поток, текущий освобождается и Android продолжит доставку уведомлений;

  • Androidпереиспользует BluetoothGattCharacteristic объекты внутри. Они создаются в время обнаружения сервисов (services discovering) и после этогопереспользуютсямногократно. Таким образом, когда приходит уведомления Android сохраняет значение в объектBluetoothGattCharacteristic. Если характеристика в этот момент обрабатывается в другом потоке мы получим гонку состояний (race condition) и результат будет непредсказуемым.

Очевидно, чтонужно всегда работать с копией массива байтов. Получили данные, сразу же делаем копию и работаем с ней.

Ниже пример, который использует такую тактику:

@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,                                     final BluetoothGattCharacteristic characteristic) {    // Copy the byte array so we have a threadsafe copy    final byte[] value = new byte[characteristic.getValue().length];    System.arraycopy(        characteristic.getValue(),         0, value, 0,         characteristic.getValue().length);    // Characteristic has new value so pass it on for processing    bleHandler.post(new Runnable() {        @Override        public void run() {                     myProcessor.onCharacteristicUpdate(BluetoothPeripheral.this, value, characteristic);        }    });}

Другие рекомендации по работе с потоками

Есть несколько дополнительных рекомендаций по работе с BLE на Android. Поскольку стек BLE в основном асинхронный, у нас есть мульти-поточная обработка задач.

Android использует потоки:

  • При сканировании (результаты приходят вmainпоток);

  • Вызове колбековBluetoothGattCallback(выполняются в потокахBinder);

Обработка результатов сканирования на main потоке не будет проблемой. Но с потоками Binder все немного сложнее. При вызове колбека на потоке Binder, Android не будет отправлять новые данные пока не закончится обработка текущих, то есть поток Binder блокируется пока ваш код не завершится. Следует избегать тяжелых операций в колбеках, никакихsleep()или что-то подобное. Кроме того, никаких новых вызовов в объектеBluetoothGatt, пока вы находитесь в потоке Binder, хотя большинство методов асинхронные.

Я рекомендую следующее:

  • Всегда выполняйте вызовыBluetoothGattCallbackв отдельном потоке, возможно даже из потока пользовательского интерфейса (Прим. переводчика: работать на main потоке - плохая идея, если у вас есть активный обмен с устройством, обязательно будут залипания UI, не делайте так);

  • Освобождайте потокиBinderкак можно быстрее иникогдане блокируйте их;

Самый простой способ выполнить рекомендации выше создать выделенныйHandlerи использовать его для обработки данных и выдачи новых команд. Обратите внимание, я уже использовалHandlerна примере кода для колбекаonCharacteristicUpdate.

Объявление объекта:

Handler bleHandler = new Handler();

Если хотите запуститьHandlerнаmainпотоке:

Handler bleHandler = new Handler(Looper.getMainLooper());

Прокрутите назад и взгляните на наш методnextCommand(), каждыйRunnableвыполняется в нашем собственномHandler, следовательно, мы гарантируем, что все команды выполняются вне потокаBinder.

Следующая статья: сопряжение (bonding)

В этой статье мы разобрались с чтением и записью характеристик, включением и выключением уведомлений/нотификаций. В следующей статье, мы детально изучим процесс спряжения с устройством (bonding).

Не терпится поработать с BLE? Попробуйтемою библиотеку Blessed for Android. Она использует все подходы из этой серии статей и упрощает работу с BLE в вашем приложении.

Подробнее..

Перевод Android Bluetooth Low Energy (BLE) готовим правильно, часть 4 (bonding)

28.01.2021 18:09:16 | Автор: admin

Содержание

Часть #1 (scanning)

Часть #2 (connecting/disconnecting)

Часть #3 (read/write)

Часть #4 (bonding), вы здесь

Впредыдущей статьемы разобрались с операциями чтения/записи, включения/выключения нотификаций и организации очереди команд. В этой статье мы поговорим осопряжении устройств(Прим. переводчика далее я буду использовать термин bonding).

Bonding

Некоторые устройства для правильной работы требуют bonding. Технически это обозначает, что генерируются ключи шифрования, обмениваются и хранятся, для безопасного обмена данными. При запуске процедуры bonding, Android может запросить у пользователя согласие, пин-код или кодовую фразу. При следующих подключениях, Android уже знает, что устройство сопряжено и обмен ключами шифрования происходит скрытно без участия пользователя. Использование bonding делает подключение к устройству более безопасным, так как соединение зашифровано.

Тема bonding плохо описана в документации Google, полностью непонятно, как приложение должно работать с bonding. Первое на что вы обратите внимание это методcreateBond(). Что интересно, в iOS такого метода нет вообще и фреймворкCoreBluetoothделает все за вас! Тогда зачем вызыватьcreateBond()? Кажется немного странным, вам заранее надо знать, какие устройства требуют bonding, а какие нет. Протокол Bluetooth был спроектирован так, что обычно устройства явно говорят им требуется или нет bonding. Я копнул немного глубже и поэкспериментировал. Чтобы разобраться с этим, ушло некоторое время, но в конце концов, все оказалось просто.

Принципы работы с bonding:

  • Пусть Android сам работает с bonding.Android сделает bonding за вас, когда устройство скажет, что нужен bonding, или во время операции чтения/записи зашифрованной характеристики. В большинстве случаев не надо вызыватьcreateBond()самостоятельно (Прим. переводчика: мне пришлось это делать самостоятельно, из-за особенностей прошивки устройства. Кроме того, Samsung работает по-другому, чем другие вендоры);

  • Нельзя запускать другие операции, в процессе работы bonding.Если вы будете запускать обнаружение сервисов или читать/писать характеристики, это приведет к ошибками и сбросу соединения. Просто дождитесь пока Android выполнит bonding;

  • Продолжайте очередь операций после завершения bonding.Как только операция bonding завершилась, продолжайте выполнение операций из очереди;

  • Если вы знаете, что делаете, и это необходимовы можете вызватьcreateBond()для запуска bonding с устройством самостоятельно. Но это должно быть исключением.

Что вызывает bonding?

Есть три причины, по которым запускается процесс bonding:

  1. При соединении с устройством, оно сигнализирует, что требуется bonding, до любых других операций;

  2. Характеристика может быть зашифрована для чтения или записи.При попытке прочитать или записать такую характеристику, запустится bonding. Если он пройдет удачно чтение/запись также выполнится, в случае ошибки bonding чтение/запись выполнится с ошибкойINSUFFICIENT_AUTHENTICATION. Такая же ошибка есть в iOS.

  3. Вызапускаете процесс bonding самостоятельночерез вызовcreateBond(). Если этого требует ваше устройство, оно вероятно не будет совместимо с iOS, так как там нет аналогичного метода. Но формально в протоколе Bluetooth такое возможно.

Давайте обсудим каждый случай.

Bonding во время подключения

Если устройство требует bonding сразу после подключения, то при вызове колбекаonConnectionStateChangeсостояние bonding будетBOND_BONDING. Это означает что идет процесс bonding ивы не должны ничего делать в этот момент, например вызыватьdiscoverServices(), до тех пор пока процесс bonding не закончится! Иначе возможны неожиданные дисконнекты или ошибки обнаружения сервисов. Поэтому следует специально обрабатывать эту ситуацию вonConnectionStateChanged:

// Take action depending on the bond stateif(bondstate == BOND_NONE || bondstate == BOND_BONDED) {    // Connected to device, now proceed to discover it's services    ... } else if (bondstate == BOND_BONDING) {    // Bonding process has already started let it complete    Log.i(TAG, "waiting for bonding to complete");}

Чтобы следить, как идет процесс bonding, необходимо зарегистрировать колбекBroadcastReceiverдля интентаACTION_BOND_STATE_CHANGEDдо вызоваconnectGatt. Этот колбек будет вызываться несколько раз в процессе bonding.

context.registerReceiver(bondStateReceiver,                         new IntentFilter(ACTION_BOND_STATE_CHANGED));private final BroadcastReceiver bondStateReceiver = new BroadcastReceiver() {    @Override    public void onReceive(Context context, Intent intent) {        final String action = intent.getAction();        final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);        // Ignore updates for other devices        if (bluetoothGatt == null || !device.getAddress().equals(bluetoothGatt.getDevice().getAddress()))            return;        // Check if action is valid        if(action == null) return;        // Take action depending on new bond state        if (action.equals(ACTION_BOND_STATE_CHANGED)) {            final int bondState = intent.getIntExtra(EXTRA_BOND_STATE, ERROR);            final int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);            switch (bondState) {                case BOND_BONDING:                    // Bonding started                    ...                    break;                case BOND_BONDED:                    // Bonding succeeded                    ...                    break;                case BOND_NONE:                    // Oh oh                    ...                    break;            }        }    }};

После завершения bonding, мы запускаем обнаружение сервисов (service discovery), если они еще не обнаружены, это можно проверить:

case BOND_BONDED:    // Bonding succeeded    Log.d(TAG, "bonded");    // Check if there are services    if(bluetoothGatt.getServices().isEmpty()) {        // No services discovered yet        bleHandler.post(new Runnable() {            @Override            public void run() {                Log.d(TAG, String.format("discovering services of '%s'", getName()));                boolean result = bluetoothGatt.discoverServices();                if (!result) {                    Log.e(TAG, "discoverServices failed to start");                }            }        });    }

Вот и все, что касается особенностей bonding при подключении.

Bonding при чтении/записи зашифрованных характеристик

Если bonding стартует при чтении/записи зашифрованной характеристики, то самая первая операция чтения/записи окончится с ошибкойGATT_INSUFFICIENT_AUTHENTICATION. На версиях Android-6, 7 вы получите эту ошибку вonCharacteristicRead/onCharacteristicWrite, при этом процесс bonding уже будет запущен внутри Android. С версии Android-8 ошибки не будет и Android самостоятельно повторит операцию после завершения bonding. Получается на Android-6, 7 надо повторить операцию чтения/записи самостоятельно. Итак, вам надо поймать ошибку и сделать повтор операции после bonding.

При получении такой ошибки, не продолжайте запуск операций:

public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status) {    // Perform some checks on the status field    if (status != GATT_SUCCESS) {        if (status == GATT_INSUFFICIENT_AUTHENTICATION ) {            // Characteristic encrypted and needs bonding,            // So retry operation after bonding completes            // This only happens on Android 5/6/7            Log.w(TAG, "read needs bonding, bonding in progress");            return;        } else {            Log.e(TAG, String.format(Locale.ENGLISH,"ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));            completedCommand();            return;        }    }...

После bonding проверяем, есть ли операция в процессе выполнения и повторяем ее:

case BOND_BONDED:    // Bonding succeeded    Log.d(TAG, "bonded");    // Check if there are services    ...    // If bonding was triggered by a read/write, we must retry it    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {        if (commandQueueBusy && !manuallyBonding) {            bleHandler.postDelayed(new Runnable() {                @Override                public void run() {                    Log.d(TAG, "retrying command after bonding");                    retryCommand();                }            }, 50);        }    }

Запуск bonding самостоятельно

Как я говорил выше, лучше не вызыватьcreateBondсамостоятельно, хотя сделать это, конечно можно. Спросите себя, это действительно необходимо? На iOS нет эквивалента методаcreateBond(), если этот метод единственный способ сделать bonding для вашего устройства, то скорее всего оно несовместимо с iOS. Это прямо указывается в документации iOS. Я перепробовал несколько десятков BLE устройств, и только в единственном случае я вызывалcreateBond()самостоятельно из-за исключительных обстоятельств.

При вызовеcreateBondсамостоятельно, также нельзя ничего делать, пока bonding не завершится и требуется регистрировать колбекBroadcastReceiverдля отслеживания процесса. Если устройство уже сопряжено (bonding завершился), тоcreateBond()вызовет ошибку, надо проверить состояние bonding перед вызовом.

Еще одна причина запускатьcreateBond()самостоятельно упростить повторное подключение. ОбъектBluetoothDeviceможно получить при помощи MAC-адреса, если устройство закешировано или сопряжено (bonding). Таким образом вам не придется снова сканировать устройство Может пригодиться! (Прим. переводчика: я как раз работал с таким вариантом подключения, его требовалось сделать полностью детерминированным, разбитым на подфазы, для точного понимания что происходит).

Удаление bonding

Как пользователь Android, я могу увидеть список сопряженных устройств в Bluetooth настройках. Там можно удалить устройство, bonding также будет удален.

Требуется некоторое время на удаление устройства.

Достаточно странно, что нет официального способа удалить bonding устройства программно. Это можно сделать, используя скрытый методremoveBond(), доступный через механизм рефлексии в Java:

try {    Method method = device.getClass().getMethod("removeBond", (Class[]) null);    result = (boolean) method.invoke(device, (Object[]) null);    if (result) {        Log.i(TAG, "Successfully removed bond");    }    return result;} catch (Exception e) {    Log.e(TAG, "ERROR: could not remove bond");    e.printStackTrace();    return false;}

Потеря bonding

Большинство BLE устройств поддерживают bonding только с одним смартфоном. Типичный сценарий, когда мы теряем bonding такой:

  • Смартфон А делает bonding с устройством Х

  • Смартфон B делает bonding с устройством Х

  • Смартфон А переподключается к устройству Х, и теперь bonding потерян.

При реконнекте смартфон А получит состояние bondingBOND_NONEв колбекеBroadcastReceiver. Сравнивайте предыдущее состояние bonding, чтобы понять была потеря или нет:

case BOND_NONE:    if(previousBondState == BOND_BONDING) {       // Bonding failed       ...    } else {       // Bond lost       ...    }    disconnect();    break;

Если случилась потеря bonding, отключаемся от устройства, иначе будут происходить странные вещи и соединение с устройством не будет нормально работать. Когда вы делаете реконнект, Android снова запускает процедуру bonding. Тоже самое происходит и при обрыве связи.

Существует мелкий баг, о котором следует знать. При потере bonding, кажется нужнаодна секундадля того, чтобы Bluetooth стек обновил свое внутреннее состояние. Если сделать реконнект сразу после потери bonding, Android может сказать, что устройство все еще сопряжено, но на самом деле это будет не так. Сделайте задержку в одну секунду перед переподключением.

Pairing попап

Прим. переводчика: не нашел толковой замены слова pairing, спаривание - звучит неблагозвучно здесь.

Когда Android запускает процесс bonding, может появится всплывающее окно. Я говорю может, потому что некоторые вендоры используют свою логику показа этого попапа (Прим. переводчика: на моем Samsung-S9, после обновления до Android-10, это попап стал появляться всегда, при коннекте любого нового устройства, до этого обновления, такого не было). На смартфонах Google (или других вендоров, где код Android в этой части не изменялся), всплывающий попап появляется только при определенный условиях.

Pairing попап появляется на переднем фоне если:

  • Устройство недавно было в режиме обнаружения;

  • Устройство было обнаружено недавно;

  • Устройство недавно было выбрано в сборщике устройств;

  • Экран настроек Bluetooth виден.

Значение недавно означаетв течение последних 60 секунд. Условия выглядят непонятными, поэтому лучше посмотреть наисходный код. Если все эти условия не выполняются, то вместо попапа появится уведомление, которое большинство пользователей не замечает. Но если они заметят и нажмут на него, всплывающее окно сбивает с толку своей опцией доступа к контактам. Ужасный UI по-моему! Некоторые производители (справедливо) решили исправить такое поведение! На устройствах Samsung всплывающее окно-подтверждение (для подключений в режиме JustWorks) вообще не отображается, а всплывающие окна всегда появляются на переднем плане. При этом всплывающее окно открывается только при вводе PIN-кода или кодовой фразы. Никаких доступов к контактам и всегда передний план. Так намного лучше!

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

public void startPairingPopupHack() {    String manufacturer = Build.MANUFACTURER;    if(!manufacturer.equals("samsung")) {        bluetoothAdapter.startDiscovery();        callBackHandler.postDelayed(new Runnable() {            @Override            public void run() {                Log.d(TAG, "popup hack completed");                bluetoothAdapter.cancelDiscovery();            }        }, 1000);    }}

Важный момент здесь вы не должны запускать никакие BLE операции пока попап на экране. Подождите ответа от пользователя.

Если учтете все эти моменты, bonding будет работать как часики!

Подведение итогов

На этом мы завершаем цикл статей о BLE в Android (Прим. переводчика: я готовлю отдельную статью-заключение, где опишу свои подходы к работе с BLE устройствами на Android, небольшие ньюансы и решения для стабильной продолжительной работы с устройствами). Надеюсь эта информация будет полезной вам и сделает работу с BLE комфортнее. Чем больше знаешь про BLE, тем лучше работает ваше приложение. Успехов!

Не терпится поработать с BLE? Попробуйтемою библиотеку Blessed for Android. Она использует все подходы из этой серии статей и упрощает работу с BLE в вашем приложении.

Подробнее..

Flipper Zero вымученная сертификация, открытие исходников и новые приколдесы

23.03.2021 18:09:53 | Автор: admin


Flipper Zero проект карманного мультитула для хакеров в формфакторе тамагочи, который мы разрабатываем. Предыдущие посты [1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]

Мы изо всех сил готовимся к старту массового производства, но на пути возникают шероховатости. Нам посчастливилось, что наше производство приходится на один из самых крупных кризисов в поставке электронных компонентов за последние пару десятков лет. Вы можете наблюдать это, например, по ситуации с видеокартами. Также нам пришлось переделать Sub-1 GHz тракт, чтобы он соответствовал требованиям регулятора, и антенна не отваливалась от ударов. В посте я расскажу, что мы делаем сейчас, как движется разработка, как выглядит подготовка к доставке, и покажу пару новых классных фич.

Трудности с сертификацией Sub-1 GHz


Как мы писали ранее, для того чтобы официально ввозить устройства в Евросоюз, США, Японию, Австралию, нам нужно получить сертификат соответствия радиочастотным нормам в этих странах. Наш первый дизайн тракта Sub-1 GHz не проходил сертификацию из-за паразитных гармоник, превышающих допустимый уровень. В итоге нам пришлось сильно переделать дизайн всего тракта. Это отняло много времени, потому что необходимо было добиться одинаково хорошего качества передачи на всех 3 поддерживаемых диапазонах: 315, 433, 868 MHz.

image
Гармоники в диапазоне 315 MHz

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

image
Вариант дизайна антенны из нескольких частей

Мы проводили тесты надежности, в которых устройство роняют, трясут и по-всякому пытаются сломать. В результате тестов выяснилось, что вибрация разрушает точку пайки антенны, и со временем, при активной тряске и падениях, антенна может отвалиться. Пришлось переделать крепление антенны: теперь она закреплена в двух точках и дополнительно усилена демпфирующим материалом в корпусе, чтобы устранить неприятный металический дребезг.

image
Клейкая подложка для фиксации антенны убирает вибрации

flipperzero new design sub1ghz antenna
Старая антенна Sub-1 GHz могла оторваться при вибрациях и падениях. В новом дизайне 2 точки крепления

Уникальное имя


imageТак выглядит паспорт дельфина, в котором теперь указано его имя

Каждый микроконтроллер STM32WB55 внутри Flipper Zero имеет уникальный серийный номер в шестнадцатиричном формате. Но это скучно и мы решили дать каждому Флипперу уникальное читаемое имя. Для этого мы взяли нейронную сеть, натренированную на именах покемонов, и сгенерировали словарь из 1 миллиона имен. Для большей уникальности имена разбавлены 1337-спиком.

Иногда нейронная сеть генерировала очень провокацинные имена. Пришлось долго настраивать фильтры, чтобы убрать имена похожие на ругательства. Но весь миллион именем просмотреть нереально, поэтому есть риск, что вам достанется Флиппер с именем вроде Loh4mo.

image
Странные имена, сгенерированные нейронной сетью, обученной на именах покемонов

Уникальный путь к порту в macOS


Это имя передается в дескрипторе USB как серийный номер в формате flip_NAME. В macOS этот серийный номер дописывается к имени последовательного порта и получается: /dev/tty.usbmodemflip_Oleg

Flipper Zero unique USB port name in macOS

Разработка интерфейса


Прошивка это самая масштабная часть работы в проекте Флиппера. Над ней трудятся сразу несколько команд: программисты, UI/UX-проектировщики, дизайнеры. Дизайн интерфейса осложняется тем, что у Флиппера маленький экранчик (всего 128х64 px) и только 5 функциональных кнопок, не считая кнопки Back. Это порождает необычный процесс проектирования интерфейсов. Мы выработали такой порядок:

  1. Сперва интерфейс проектируется в виде майндмапов в Miro. В этом месте происходит обсуждение, проработка разных концепций, споры и т.д.
  2. Утвержденный интерфейс разбивается на конкретные экраны и отрисовывается в виде картинок 128x64 в фотошопе в формате BMP.
  3. Дальше ассеты (наборы графики) конвертируются из BMP в XBM и передаются программистам вместе и инструкциями как нужно реализовывать интерактивные элементы, вроде клавиатуры и диалоговых окон. В процессе реализации интерфейса часто возникают ситуации, когда существующая библиотека для графики не позволяет реализовать что-то, тогда приходится решать, переделывать ли интерфейс, или дорабатывать графическую библиотеку.

image
Структура приложения RFID в Miro

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

image
Пример логики перехода между экранами и уведомлений

Блокировка экрана и новый UI главного экрана


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

  • Вверх меню блокировки.
  • Вправо взаимодействие с дельфином.
    Можно посмотреть профиль, поиграть и покормить пацана.
  • Вниз быстрый доступ к инвентарю
    Ключи из всех приложений сохраняются в архив, по которому можно быстро перемещаться, чтобы сразу иметь доступ ко всем ключам из разных приложений: iButton, RFID/NFC, Infrared и т.д.

Демонстрация функции блокировки экрана и новые окна главного экрана

Приложение qFlipper


image
Приложение qFlipper для обновления прошивки, радиостека, загрузчика и трансляции экрана Флиппера на компьютер

Мы разрабатываем свою утилиту для прошивки Флиппера на Qt и C++. Она будет нативно работать на всех десктопных платформах. Еще эта утилита умеет захватывать фреймбуфер экрана Флиппера и транслировать его на экране компьютера. Это позволяет делать качественные скринкасты вместо того, чтобы снимать Флиппер камерой. Это удобно для записи инструкций и обучающих материалов.


Через qFlipper можно транслировать экран Флиппера в реальном времени на компьютер

Обновление прошивки из браузера


image
Обновить прошивку Flipper Zero можно через браузер без сторонних программ. Поддерживается Chrome, Opera, Microsoft Edge

Оказывается, есть такая штука, как WebUSB позволяет прямо из браузера общаться с USB-устройством. У нас получилось успешно обновить прошивку Флиппера через специальную страницу Web DFU-Util Пока поддерживается только в Chrome, Opera, Microsoft Edge.

Это безумно круто, потому что позволяет пользователю прошить свой Флиппер, вообще не скачивая никакие файлы из интернета! В итоге релизы альтернативных прошивок будут выглядеть так:

  1. Чувак форкает репозиторий с прошивкой Флиппера сразу вместе с файлами для WebUSB
  2. Делает свою сборку от Васяна и одной кнопкой создает страницу на GitHub Pages, куда выкладывает бинарник своей прошивки
  3. Любой желающий может зайти на его сайт и в один клик прошить свой Флиппер его прошивкой

Начинаем открывать исходники


Схема Flipper Zero теперь публична

Мы постепенно начинаем выкладывать исходники проекта. Сейчас уже опубликована принципиальная схема всего Flipper Zero в виде каждой отдельной платы. Мы просим вас изучить схему и написать обо всех замечаниях в комментариях.

Исходники схемы: docs.flipperzero.one/ru/development/hardware/schematic


Мы также опубликовали чертежи и обновили 3D-модели корпуса и референсного модуля Флиппера.

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

Эти модели уже очень близки к финальным, хоть и могут незначительно измениться перед процессом литья.

Мы продолжим открывать исходники проекта, и к моменту отправки основной волны устройств опубликуем все оставшиеся части проекта.

Упаковка и логистика


Готовим упаковку. Мы выбрали самый простой, дешевый и экологичный картон с черно-белой печатью. От упаковки требуется быть максимально компактной и при этом уберечь устройство внутри от падений, ударов и сжатий.

Внутри коробки находится вставка из упругой пенки, куда укладывается сам Флиппер. Под ним будет находиться Type-C кабель.

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

image
Тестовые образцы коробки. Финальная версия будет аккуратной, а изображение может отличаться

Если вы хотите принять участие в дизайне коробки, вот исходники cdn.flipperzero.one/Flipper_zero_Box_Template.zip Свои варианты можете выкладывать в комментариях.

image
Исходники дизайна коробки для желающих предложить свой вариант оформления

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

Мы будем отправлять Флиппер в транспортном режиме, когда питание процессора оставлено только на RTC, то есть сохраняется состояние внутренних часов. Чтобы включить устройство, нужно будет зажать кнопку Back.

Заполнение адресов и оплата доставки


imageНа сегодняшний день 92% бэкеров заполнили адрес доставки в пледж-менеджере. Около 3 тысяч бэкеров до сих пор не закончили опрос. Если вы до сих пор не заполнили свои данные, пожалуйста, сделайте это. Нам важно точно рассчитывать количество черных и белых корпусов для производства, а также регионы, в которые поедут посылки.

BackerKit работает точно так же как Кикстартер: в форме вы просто указываете карту, а списание произойдёт массово и позднее. В пледж-менеджере можно добавить в заказ дополнительных Флипперов, чехол и прочие аксессуары. Даже если вы завершили заполнение формы, любые поля в ней можно изменить, пока мы не заблокируем заказы, о чём предупредим заранее.

Подробнее описывали процесс в англоязычном посте.

image
8% бекеров не закончили ввод адреса и карты для оплаты доставки в пледж-менеджере

В середине апреля мы начнем списывать деньги с ваших карт за доставку и аксессуары. До этого момента вы можете свободно изменять адрес доставки, выбранные цвета, набор аксессуаров в заказе. Поменять можно даже страну доставки. За несколько дней до блокировки заказов и списания денег мы пришлем письмо, чтобы не застать вас врасплох. И всё же, не зевайте.

Отладочный модуль ST-Link V3


image
Модуль отладчика для Flipper Zero на базе ST-Link V3

Для всех желающих разрабатывать модули под Флиппер мы опубликовали исходники референсного модуля отладочной платы на базе STLink V3. Доступны полные исходники проекта в Altium, наша библиотека компонентов и чертежи механики.

Наша разработчица Сахаайа, которая занимается трассировкой плат, записала небольшой видеоурок о том, как выглядит работа в Altium.


Алло, мы ищем таланты!


imageМы постоянно ищем инженеров и менеджеров в нашу дружную команду. Весь список вакансий можно посмотреть здесь career.habr.com/companies/flipper-devices




C Разработчик (Embedded) / Middle


Прошивка очень масштабная часть, состоящая из операционной системы на базе FreeRTOS и большого числа отдельных приложений, поэтому мы постоянно набираем новых разработчиков для ее реализации. Нам нужен человек, который уверенно умеет в C и хорошо знаком с эмбеддом. Полное описание вакансии career.habr.com/vacancies/1000068496

QA-инженеры / Тестировщики ПО (Embedded)


Тестирование объемная часть, которая невероятно важна на всех этапах создания Flipper Zero. Сейчас наши разработчики активно выкатывают новые версии софта и железа, поэтому в нашу команду нужен Middle и Juior QA-инженеры. Полное описание вакансий:
career.habr.com/vacancies/1000071996
career.habr.com/vacancies/1000071987

Project Manager


Наш проект состоит из большого количества систем, каждой из которых занимается один или несколько людей. Мы ищем человека, который поможет успевать со всеми задачами, синхронизировать команды и держать планирование под контроллем. Полное описание вакансии career.habr.com/vacancies/1000063748



Наши соц.сети




Все характеристики Flipper Zero на официальном сайте.
Наш англоязычный блог.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru