ESP32:Примеры/Android-приложение, коммуницирующее через BLE: управление выходными контактами и показ данных, считанных датчиком

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Android-приложение, коммуницирующее через BLE: управление выходными контактами и показ данных, считанных датчиком

В этом примере мы создадим Android-приложение, которое будет взаимодействовать с ESP32 при помощи Bluetooth Low Energy (BLE).

Обзор проекта

Давайте разберем главные функции этого проекта:

  • Android-приложение будет управлять устройством вывода данных, подключенным к ESP32, и показывать данные, считанные от датчика;
  • В этом проекте мы будем управлять светодиодом и считывать температуру с датчика DS18B20;
  • Цель этого проекта – создать простое Android-приложение и научиться новым способам использования BLE с ESP32. Сделав этот проект, вы можете заменить светодиод на другое устройство вывода данных, а DS18B20 – на какой-то другой датчик.

Итак, теперь давайте разберем, как работает этот проект.

ESP32 – это сервер, а ваш смартфон, на котором установлено Android-приложение – это клиент. Между ними будет установлено соединение типа «точка-точка».

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

В Android-приложении вам нужно лишь кликнуть на кнопку «CONNECT» – чтобы запустить поиск – а затем выбрать свою ESP32.

Примечание

Приложение для этого проекта было создано с помощью MIT App Inventor 2. Руководство по его созданию смотрите ниже.

Устанавливаем библиотеки

Перед загрузкой кода нам нужно установить в IDE Arduino две библиотеки – «OneWire» от Пола Стоффрегена и «Arduino Temperature Control» – чтобы считывать данные от датчика DS18B20.

Устанавливаем библиотеку «OneWire»

  1. Кликните тут, чтобы скачать ZIP-архив библиотеки. Он должен загрузиться в папку «Загрузки» на вашем ПК;
  2. Распакуйте этот архив. У вас должна получиться папка «OneWire-master»;
  3. Переименуйте ее на «OneWire»;
  4. Переместите папку «OneWire» в папку «libraries» (туда устанавливаются все библиотеки для IDE Arduino), которая находится в папке, куда установлена ваша IDE Arduino;
  5. Перезапустите IDE Arduino;

Устанавливаем библиотеку «Arduino Temperature Control»

  1. Кликните тут, чтобы скачать ZIP-архив библиотеки. Он должен загрузиться в папку «Загрузки» на вашем ПК;
  2. Распакуйте этот архив. У вас должна получиться папка «Arduino-Temperature-Control-Library-master»;
  3. Переименуйте ее на «DallasTemperature»;
  4. Переместите папку «DallasTemperature» в папку «libraries» (туда устанавливаются все библиотеки для IDE Arduino), которая находится в папке, куда установлена ваша IDE Arduino;
  5. Наконец, перезапустите IDE Arduino;

Как работает этот код

Давайте поближе рассмотрим этот код и разберемся, как работает BLE-сервер на базе ESP32.

Подключаем библиотеки

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

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <OneWire.h>
#include <DallasTemperature.h>

Задаем UUID

Теперь задаем UUID для сервиса, принимающей (RX) характеристики и отправляющей (TX) характеристики.

#define SERVICE_UUID "C6FBDD3C-7123-4C9E-86AB-005F1A7EDA01"
#define CHARACTERISTIC_UUID_RX "B88E098B-E464-4B54-B827-79EB2B150A9F"
#define CHARACTERISTIC_UUID_TX "D769FACF-A4DA-47BA-9253-65359EE480FB"
Важно

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

Температурный датчик и переменные

Задаем контакт для считывания данных с температурного датчика. В данном случае это GPIO27.

#define ONE_WIRE_BUS 27

Создаем объект для коммуникации с OneWire-устройством.

OneWire oneWire(ONE_WIRE_BUS);

Затем передаем объект «oneWire» объекту «sensors».

DallasTemperature sensors(&oneWire);

Строчка ниже создает указатель на BLE-характеристику.

BLECharacteristic *pCharacteristic;

Создаем булеву переменную для управления подключением/отключением устройства.

bool deviceConnected = false;

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

float temperature = 0;

Наконец, создаем константу «ledPin» для контакта GPIO26, к которому подключен светодиод.

const int ledPin = 26;

setup()

Теперь промотайте до блока setup(). Здесь мы инициализируем последовательную коммуникацию на скорости 115200 бод, переключаем контакт «ledPin» в режим «OUTPUT» и запускаем температурный датчик.

Serial.begin(115200);
pinMode(ledPin, OUTPUT);
sensors.begin();

BLE-устройство

Создаем новое BLE-устройство с названием, которое позволит легко идентифицировать ESP32-плату – например, «ESP32_Board».

BLEDevice::init("ESP32_Board");

BLE-сервер

Далее создаем BLE-сервер.

BLEServer *pServer = BLEDevice::createServer();

Затем задаем функции обратного вызова для сервера и характеристики – MyServerCallbacks() и MyCallbacks().

pServer->setCallbacks(new MyServerCallbacks()); 
pCharacteristic->setCallbacks(new MyCallbacks());

Функция MyServerCallbacks() при успешном подключении клиента вызовет функцию onConnect() и поменяет значение в булевой переменной «deviceConnected» на «true».

void onConnect(BLEServer* pServer) {
deviceConnected = true;
};

При отключении клиента она вызовет функцию onDisconnect() и поменяет значение в булевой переменной «deviceConnected» на «false».

void onDisconnect(BLEServer* pServer) {
 deviceConnected = false;
}

BLE-сервис

Вернемся в блок setup(). Создаем BLE-сервис с заданным ранее UUID.

BLEService *pService = pServer->createService(SERVICE_UUID);

BLE-характеристики

Также создаем две характеристики для этого сервиса:

pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);

Отправляющая (TX) характеристика ответственна за отправку данных клиенту. В нашем проекте она будет каждые 5 секунд уведомлять клиента о новых температурных данных.

Вторая характеристика – это принимающая (RX) характеристика, ответственная за получение новых данных от клиента. В нашем проекте она получает команды «ON» («вкл») и «OFF» («выкл») для управления устройством вывода данных (светодиодом). У этой характеристики активировано свойство для записи («PROPERTY_WRITE») и, кроме того, она служит параметром в функции обратного вызова onWrite().

void onWrite(BLECharacteristic *pCharacteristic) {
  std::string rxValue = pCharacteristic->getValue();
  if(rxValue.length() > 0) {
    Serial.print("Received value: ");  //  "Полученное значение: "
    for(int i = 0; i < rxValue.length(); i++) {
      Serial.print(rxValue[i]);
    }
    // включаем и выключаем светодиод согласно полученной команде:
    if(rxValue.find("ON") != -1) { 
      Serial.println(" - LED ON");  //  " - светодиод включен"
      digitalWrite(ledPin, HIGH);
    }
    else if(rxValue.find("OFF") != -1) {
      Serial.println(" - LED OFF");  //  " - светодиод выключен"
      digitalWrite(ledPin, LOW);
    }
  }
}

Получив новое значение, сервер вызовет функцию onWrite() и запишет это значение в характеристику сервиса. Оно будет храниться в переменной «rxValue». После этого, согласно полученному значению, сервер отправит команду «ON» или «OFF», тем самым либо включив, либо выключив светодиод.

if(rxValue.find("ON") != -1) { 
  Serial.println(" - LED ON");  //  " - светодиод включен"
  digitalWrite(ledPin, HIGH);
}
  else if(rxValue.find("OFF") != -1) {
  Serial.println(" - LED OFF");  //  " - светодиод выключен"
  digitalWrite(ledPin, LOW);
}

Запускаем BLE-сервис

Создав сервер, сервис и характеристики, запускаем BLE-сервис.

pService->start();

Также начинаем рассылку оповещений, чтобы клиент мог найти ESP32-сервер.

pServer->getAdvertising()->start();

loop()

При каждом проходе через loop() мы проверяем, подключилось ли BLE-устройство или нет. Если подключилось, то условие if() ниже равно «true» (т.е. правдиво). Следовательно, ESP32 примет новые данные от датчика и сохранит их в температурную переменную.

// Если устройство подключено... 
if(deviceConnected) {
  // ...измеряем температуру:
  sensors.requestTemperatures();
    
  // Температура в градусах Цельсия:
  temperature = sensors.getTempCByIndex(0);
  // Раскомментируйте строчку ниже,
  // если хотите получать температуру в градусах Фаренгейта
  // (но также закомментируйте строчку выше для градусов Цельсия): 
  //temperature = sensors.getTempFByIndex(0); // температура в  
                                              // градусах Фаренгейта 
    
  // конвертируем значение в массив символов:
  char txString[8];
  dtostrf(temperature, 1, 2, txString);
    
  // задаем новое значение для характеристики:
  pCharacteristic->setValue(txString);
  // отправляем значение Android-приложению:
  pCharacteristic->notify(); 
  Serial.print("Sent value: ");  // "Отправленное значение: "
  Serial.println(txString);
}

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

temperature = sensors.getTempCByIndex(0);

А затем расскомментируйте вот эту строчку:

//temperature = sensors.getTempFByIndex(0); // температура в  
                                            // градусах Фаренгейта

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

dtostrf(temperature, 1, 2, txString);

Затем задаем характеристике новое значение и уведомляем клиента.

// задаем новое значение для характеристики:
pCharacteristic->setValue(txString);
// отправляем значение Android-приложению:
pCharacteristic->notify();

Этот процесс будет повторяться каждые 5 секунд.

delay(5000);

Итак, если вкратце, то в этом коде выполняется следующее. Когда клиент подключается к ESP32-серверу, тот каждые 5 секунд отправляет ему новые температурные данные. Кроме того, когда клиент записывает в принимающую (RX) характеристику команду «ON» или «OFF», это включает или выключает светодиод.

Создание Android-приложения при помощи MIT App Inventor 2: как работает это приложение?

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

Ресурсы

  • Чтобы отредактировать это приложение, вам нужно загрузить его файл «.aia» и импортировать его в MIT App Inventor 2. Скачать этот файл можно отсюда;
  • Файл «.apk» для установки этого приложения в смартфон можно скачать по этой ссылке;
  • По этой ссылке можно скачать ZIP-архив со всеми ресурсами для этого проекта.

Введение в MIT App Inventor 2

Приложение для этого проекта было сделано при помощи редактора MIT App Inventor 2. Чтобы работать в нем, вам не нужно ничего загружать/устанавливать на свой ПК, потому что это облачный редактор. То есть мы будем создавать это приложение прямо в браузере (Chrome, Mozilla, Safari, Internet Explorer и т.д.). Нам понадобится лишь интернет-соединение.

Почему MIT App Inventor 2?

MIT App Inventor 2 – это простой, интуитивный и бесплатный сервис для создания Android-приложений. Благодаря ему вам не нужно быть экспертом в программировании или дизайне, чтобы создавать классные и полезные приложения.

Создание дизайна приложения в этом редакторе осуществляется просто – при помощи выбора и размещения различных элементов на «экране смартфона». Программирование – это лишь перетаскивание блоков кода. Вам достаточно всего пары часов практики, чтобы научиться создавать собственные приложения в MIT App Inventor 2.

Открываем MIT App Inventor 2

Чтобы получить доступ к редактору MIT App Inventor 2, перейдите по этой ссылке и кликните на оранжевую кнопку «Create apps!» (она находится справа вверху).

Для получения доступа к редактору приложений вам понадобится аккаунт в Google. Следуйте экранным подсказкам, чтобы залогиниться в MIT App Inventor 2. После этого перед вами откроется примерно такое окно:

Импортируем файл «.aia»

В самом верху редактора находится кнопка «Projects» – кликните по ней, а затем по пункту «Import project (.aia) from my computer...». Затем нажмите на «Выберите файл» и выберите скачанный ранее файл «.aia» для редактирования Android-приложения. Если еще не скачали, то сделать это можно по этой ссылке.

После импорта файла «.aia» должна открыться вот такая страница.

Это вкладка «Designer». Здесь можно добавлять кнопки, текст, изображения, ползунки и т.д. В общем, здесь можно менять внешний вид приложения. В этом меню есть несколько секций:

  • Palette. Содержит элементы для создания дизайна приложения – кнопки, ползунки, изображения, надписи и т.д.
  • Viewer. Это «экран смартфона», куда нужно будет перетягивать кнопки, ползунки и пр.
  • Components. Показывает элементы, добавленные в приложение, и их иерархию.
  • Media. Здесь показываются импортированные медиафайлы вроде изображений и звуков, которые можно добавить в приложение.
  • Properties. Здесь выбираются свойства для элементов – цвет, размер, ориентация и т.д.

Из чего состоит дизайн приложения

Элементы, добавляемые в дизайн приложения, должны быть размещены внутри блоков, которые добавляются в проект при помощи меню «Layout» (оно находится в секции «Palette»).

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

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

Текстовая надпись (Label)

Первый блок состоит из двух элементов Label.

Один из них содержит слово «VALUE» («Значение»). Такое общее слово выбрано не случайно – так вам будет проще вместо температуры показать какие-то другие данные. При желании этот текст можно отредактировать, чтобы он соответствовал тому, какие данные считываются в вашем проекте.

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

Чтобы добавить в блок новые надписи, вам нужно лишь перетянуть элемент Label (он выделен красным цветом на скриншоте выше) из меню Palette > User Interface в меню Viewer. Выбрав элемент Label, справа в меню Properties можно отредактировать то, как будет выглядеть этот текст.

Изображение (Image)

В следующем блоке находится изображение лампочки.

Чтобы добавить изображение в меню Viewer, просто перетяните в него элемент Image из меню Palette > User Interface. У нас в этом блоке находится два элемента Image, но показан будет только один из них – это можно задать в свойствах (Properties) элемента Image. Чтобы использовать в приложении какие-либо изображения, сначала их нужно загрузить в секцию Media.

Кнопка (Button)

Следующий блок содержит кнопку, предназначенную для отправки команд «ON» и «OFF» на ESP32 для управления устройством вывода данных (светодиодом).

Кнопка добавляется в приложение очень просто – перетягиванием элемента Button в меню Viewer. После этого вы можете отредактировать свойства кнопки в секции Properties. В данный момент у нас показана кнопка «ON». Чтобы показать кнопку «OFF», мы поменяем цвет и текст этой кнопки на вкладке Blocks. Если вы хотите добавить другие команды для управления ESP32, то для этого также понадобится добавить новые кнопки.

ListPicker

Последний блок содержит кнопку и элемент ListPicker. Этот элемент не видим в меню Viewer, но будет вызываться при нажатии на кнопку «CONNECT». Элемент ListPicker – это неотъемлемый компонент Bluetooth-приложений, т.к. выводит список найденных Bluetooth-устройств.

Невидимые элементы

Наконец, нам нужно добавить в приложение два невидимых элемента – Clock и BluetoothLE.

По умолчанию MIT App Inventor 2 не поддерживает BLE. Поэтому элемент BluetoothLE находится в секции «Расширения» (Palette > Extension). Поскольку в импортированном приложении есть элемент BluetoothLE, он будет автоматически добавлен в секцию расширений.

Как устроена логика приложения

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

В результате должно открыться вот такое окно:

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

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

Установка UUID

Блоки ниже задают UUID для сервиса, принимающей (RX) характеристики и отправляющей (TX) характеристики.

Эти UUID должны соответствовать UUID, которые заданы в коде IDE Arduino. Если вы хотите задать другие UUID, то их нужно будет поменять в обоих местах. Сгенерировать собственные UUID можно при помощи этого UUID-генератора.

Прослушивание и подключение к BLE-устройству

Набор блоков ниже ответственен за прослушивание, выбор и подключение к BLE-устройству.

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

Получение уведомлений

У температурной (принимающей) характеристики активировано свойство NOTIFY (уведомление) – вы будете при помощи уведомлений получать новые температурные данные каждые 5 секунд. Два блока ниже ответственны за показ получаемых температурных данных.

Первый блок начинается с того, что принимающая (RX) характеристика получает новые данные или, если клиент отключился, задает температурные данные на «...». Второй блок получает сообщение от ESP32, сохраняет его в переменную «stringValues» и показывает в надписи «valueLabel».

Примечание

Эти блоки будут работать при отправке и температурных, и любых других данных. То есть, если вы подключите к ESP32 вместо температурного датчика какое-то другое устройство, эти блоки кода редактировать не придется.

Отправка команд

Следующий блок отправляет команды «ON» и «OFF» на ESP32 для управления устройством вывода данных (светодиодом). Кроме того, он меняет текст и цвет кнопки, а также изображение лампочки.

Чтобы отправить команду на ESP32, мы записываем «ON» или «OFF» в отправляющую (TX) характеристику. К примеру, вот что происходит, когда вы кликаете на кнопку с надписью «ON»:

  • Становится видно изображение включенной лампочки;
  • Становится не видно изображение выключенной лампочки;
  • Меняется внешний вид кнопки – текст меняется на «OFF», а цвет кнопки меняется на серый;
  • Наконец, в отправляющую (TX) характеристику записывается значение «ON».

Если вы хотите, чтобы с помощью этого приложения можно было управлять не только светодиодом, но и другими устройствами, вам нужно добавить в дизайн приложения дополнительные кнопки. После этого вам нужно будет задать, какие сообщения будут записываться в отправляющую (TX) характеристику при нажатии на разные кнопки. Наконец, в код IDE Arduino нужно будет добавить то, что будет делать ESP32 при получении этих команд.

Тестируем приложение

Это приложение можно тестировать в режиме реального времени (внося изменения и сразу же видя результат). Для этого на смартфон нужно будет установить приложение MIT AI2 Companion. Зайдите в Google Play, поищите там «MIT AI2 Companion» и установите его.

Откройте приложение. Перед вами откроется примерно такой экран:

Чтобы протестировать приложение, зайдите в MIT App Inventor 2 и кликните на Connect > AI Companion.

Появится QR-код (как на картинке ниже).

В смартфоне нужно будет либо ввести кодовое слово (у меня это «hasveo»), а затем нажать на «connect with code», либо нажать на «scan QR code», а затем просканировать QR-код. В результате ваш смартфон покажет, как выглядит ваше приложение. Его внешний вид будет обновляться в реальном времени. То есть вы будете видеть результат при внесении каждого изменения.

Итого

Мы рассмотрели это BLE-приложение очень бегло, поэтому советуем поэкспериментировать и своими руками настроить его под собственные нужды. Лучший способ чему-то научиться – это начать это делать своими руками, и создание приложений в MIT App Inventor 2 – не исключение!

Дополнительные материалы о редакторе MIT App Inventor 2 смотрите на его официально сайте.

Подготавливаем Android-приложение

Теперь давайте перейдем к Android-приложению. Как уже говорилось выше, оно создано с помощью MIT App Inventor 2. Файлы «.apk» и «.aia» можно скачать отсюда:

или вы можете его скомпилировать сами(вверху MIT App Inventor кликните по Build и в выпадающем меню выберете удобный вариант) и затем скопировать для установки на свой телефон.

Теперь давайте установим это приложение в смартфон.

Скопируйте ссылку ниже в смартфон, а затем кликните на нее. Это ссылка на загрузку файла «.apk».

Также можно просто переместить загруженный файл «.apk» в свой смартфон. В смартфоне откройте загруженный файл и разрешите устанавливать приложения из этого источника. Далее следуйте инструкциям мастера установки, чтобы установить приложение. Установка должна занять несколько секунд. Если все прошло как надо, на домашнем экране смартфона должна появиться иконка установленного приложения. Или вы можете просто поискать приложение «ESP32 BLE».

Демонстрация

Теперь все должно быть готово. Давайте протестируем проект. Включите в смартфоне Bluetooth, откройте установленное Android-приложение и нажмите в нем на кнопку «CONNECT», чтобы запустить поиск близлежащих устройств. Выберите устройство «ESP32_Board». Через несколько секунд смартфон должен к нему подключиться.

[Картинка]

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

[Картинка]

Нажмите на кнопку «ON», чтобы включить светодиод. Изображение лампочки должно поменяться – она должна «загореться». Теперь нажмите на кнопку «OFF», чтобы выключить светодиод. Если все настроено правильно, система должна работать идеально и мгновенно отвечать на команды.

[Картинка]

Итого

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

Необходимое оборудование

Схема

Подключите температурный датчик DS18B20 к ESP32 как показано на схеме ниже (контакт для передачи данных должен быть подключен к GPIO27), а светодиод – к GPIO26.

Примечание

На этой схеме изображена 36-контактная версия платы ESP32 DEVKIT DOIT V1. Если у вас какая-то другая плата, обязательно сверьтесь с ее распиновкой.

Код

/*********
  Руи Сантос
  Более подробно о проекте на: http://randomnerdtutorials.com  
*********/

// Подключаем необходимые библиотеки:
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// НЕ МЕНЯЙТЕ ЭТИ UUID.
// Если поменяете, вам также нужно будет поменять их
// в Android-приложении, используемом для этого проекта:
#define SERVICE_UUID            "C6FBDD3C-7123-4C9E-86AB-005F1A7EDA01"
#define CHARACTERISTIC_UUID_RX  "B88E098B-E464-4B54-B827-79EB2B150A9F"
#define CHARACTERISTIC_UUID_TX  "D769FACF-A4DA-47BA-9253-65359EE480FB"

// Контакт для передачи данных DS18B20 подключаем к GPIO27 на ESP32: 
#define ONE_WIRE_BUS 27
// Создаем объект «oneWire» для коммуникации с OneWire-устройствами:
OneWire oneWire(ONE_WIRE_BUS);
// Передаем объект «oneWire» объекту температурного датчика DS18B20:
DallasTemperature sensors(&oneWire);

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

// переменная для температурных данных
// и константа для контакта, к которому подключен светодиод:
float temperature = 0;
const int ledPin = 26;

// функции обратного вызова, которые будут запускаться
// при подключении и отключении BLE-клиента от BLE-сервера:
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

// функция обратного вызова, которая будет запускаться
// при получении нового значения от Android-приложения:
class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    std::string rxValue = pCharacteristic->getValue();
    if(rxValue.length() > 0) {
      Serial.print("Received value: ");  //  "Полученное значение: "
      for(int i = 0; i < rxValue.length(); i++) {
        Serial.print(rxValue[i]);
      }
      // включаем и выключаем светодиод согласно полученной команде:
      if(rxValue.find("ON") != -1) { 
        Serial.println(" - LED ON");  //  " - светодиод включен"
        digitalWrite(ledPin, HIGH);
      }
      else if(rxValue.find("OFF") != -1) {
        Serial.println(" - LED OFF");  //  " - светодиод выключен"
        digitalWrite(ledPin, LOW);
      }
    }
  }
};

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  sensors.begin();
  
  // создаем BLE-устройство:
  BLEDevice::init("ESP32_Board");

  // создаем BLE-сервер:
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Создаем BLE-сервис:
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Создаем BLE-характеристику:
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY);
                      
  pCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                               CHARACTERISTIC_UUID_RX,
                               BLECharacteristic::PROPERTY_WRITE);

  pCharacteristic->setCallbacks(new MyCallbacks());

  // Запускаем сервис:
  pService->start();

  // Начинаем рассылку оповещений:
  pServer->getAdvertising()->start();
  Serial.println("Waiting to connect...");
             //  "Ждем подключения..."
}

void loop() {
  // Если устройство подключено... 
  if(deviceConnected) {
    // ...измеряем температуру:
    sensors.requestTemperatures();
    
    // Температура в градусах Цельсия:
    temperature = sensors.getTempCByIndex(0);
    // Раскомментируйте строчку ниже,
    // если хотите получать температуру в градусах Фаренгейта
    // (но также закомментируйте строчку выше для градусов Цельсия): 
    //temperature = sensors.getTempFByIndex(0); // температура в  
                                                // градусах Фаренгейта 
    
    // конвертируем значение в массив символов:
    char txString[8];
    dtostrf(temperature, 1, 2, txString);
    
    // задаем новое значение для характеристики:
    pCharacteristic->setValue(txString);
    // отправляем значение Android-приложению:
    pCharacteristic->notify(); 
    Serial.print("Sent value: ");  // "Отправленное значение: "
    Serial.println(txString);
  }
  delay(5000);
}

См.также

Внешние ссылки