BLE対応のコード
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Wire.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_BMP280.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// DS18B20 Configuration
#define ONE_WIRE_BUS 32
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Sensor Configuration
Adafruit_AHTX0 aht;
Adafruit_BMP280 bmp;
// BLE Configuration
BLEServer* pServer;
BLEService* pService;
BLECharacteristic* pTemperatureCharacteristic;
BLECharacteristic* pHumidityCharacteristic;
BLECharacteristic* pPressureCharacteristic;
BLECharacteristic* pWaterTemperatureCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
// Timing Variables
unsigned long currentTime;
static unsigned long lastMeasureTime = 0;
// BLE Server Callbacks
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
}
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
Wire.begin(22, 21);
// Initialize AHT Sensor
if (!aht.begin()) {
Serial.println("Could not find AHT? Check wiring");
while (1) delay(10);
}
Serial.println("AHT10 or AHT20 found");
// Initialize BMP280 Sensor
if (!bmp.begin(0x77)) {
Serial.println("Could not find BMP280 sensor!");
while (1) delay(10);
}
Serial.println("BMP280 found");
// Initialize DS18B20 Sensor
sensors.begin();
// Initialize BLE
BLEDevice::init("AQUA-FAN-BLE");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
pService = pServer->createService("19B10000-E8F2-537E-4F6C-D104768A1214");
// Create BLE Characteristics
pTemperatureCharacteristic = pService->createCharacteristic(
"19B10001-E8F2-537E-4F6C-D104768A1214",
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
pTemperatureCharacteristic->addDescriptor(new BLE2902());
pHumidityCharacteristic = pService->createCharacteristic(
"19B10002-E8F2-537E-4F6C-D104768A1214",
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
pHumidityCharacteristic->addDescriptor(new BLE2902());
pPressureCharacteristic = pService->createCharacteristic(
"19B10003-E8F2-537E-4F6C-D104768A1214",
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
pPressureCharacteristic->addDescriptor(new BLE2902());
pWaterTemperatureCharacteristic = pService->createCharacteristic(
"19B10004-E8F2-537E-4F6C-D104768A1214",
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
pWaterTemperatureCharacteristic->addDescriptor(new BLE2902());
pService->start();
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(pService->getUUID());
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // Functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("BLE Server started. Waiting for connections...");
}
void loop() {
currentTime = millis();
// Measure and send sensor data every 1000ms
if (currentTime > lastMeasureTime + 1000) {
measureAndSendSensorData();
lastMeasureTime = currentTime;
}
// Handle BLE connection state
if (!deviceConnected && oldDeviceConnected) {
delay(500); // Give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // Restart advertising
Serial.println("Start advertising");
oldDeviceConnected = deviceConnected;
}
if (deviceConnected && !oldDeviceConnected) {
oldDeviceConnected = deviceConnected;
}
}
void measureAndSendSensorData() {
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);
float pressure = bmp.readPressure() / 100.0F; // hPaに変換
sensors.requestTemperatures();
float water_temperature = sensors.getTempCByIndex(0);
// Send data via BLE
if (deviceConnected) {
pTemperatureCharacteristic->setValue(temp.temperature);
pTemperatureCharacteristic->notify();
pHumidityCharacteristic->setValue(humidity.relative_humidity);
pHumidityCharacteristic->notify();
pPressureCharacteristic->setValue(pressure);
pPressureCharacteristic->notify();
pWaterTemperatureCharacteristic->setValue(water_temperature);
pWaterTemperatureCharacteristic->notify();
}
// Print data to Serial
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
Serial.print("Pressure: ");
Serial.print(pressure);
Serial.println(" hPa");
Serial.print("Water Temperature: ");
Serial.print(water_temperature);
Serial.println(" degrees C");
}
…
コードの説明
-
BLE初期化:
BLEDevice::init("AQUA-FAN-BLE");でBLEデバイスを初期化します。BLEServerとBLEServiceを作成し、センサーデータを公開するためのBLECharacteristicを定義します。
-
センサーデータの取得:
- AHT10/AHT20、BMP280、DS18B20から温度、湿度、気圧、水温を取得します。
-
BLE経由でデータを送信:
- センサーデータをBLE Characteristicsに設定し、
notify()を呼び出してクライアントに通知します。
- センサーデータをBLE Characteristicsに設定し、
-
接続状態の管理:
- デバイスが接続または切断された場合に、BLE広告を再開します。
必要なライブラリ
- , , , : ESP32のBLEライブラリ。
- : AHT10/AHT20センサーのライブラリ。
- : BMP280センサーのライブラリ。
- , : DS18B20センサーのライブラリ。
Flutter側のBLEクライアント
Flutter側では、flutter_blue_plusを使用してBLEデバイスに接続し、Characteristicsからデータを読み取ることができます。以下は、Flutter側のコード例です。
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: BleClientScreen(),
);
}
}
class BleClientScreen extends StatefulWidget {
_BleClientScreenState createState() => _BleClientScreenState();
}
class _BleClientScreenState extends State<BleClientScreen> {
FlutterBluePlus flutterBlue = FlutterBluePlus.instance;
BluetoothDevice? connectedDevice;
List<BluetoothService> services = [];
String temperature = "N/A";
String humidity = "N/A";
String pressure = "N/A";
String waterTemperature = "N/A";
void initState() {
super.initState();
startScan();
}
void startScan() {
flutterBlue.startScan(timeout: Duration(seconds: 4));
flutterBlue.scanResults.listen((results) {
for (ScanResult result in results) {
if (result.device.name == "AQUA-FAN-BLE") {
stopScan();
connectToDevice(result.device);
break;
}
}
});
}
void stopScan() {
flutterBlue.stopScan();
}
void connectToDevice(BluetoothDevice device) async {
await device.connect();
connectedDevice = device;
discoverServices(device);
}
void discoverServices(BluetoothDevice device) async {
List<BluetoothService> services = await device.discoverServices();
for (BluetoothService service in services) {
for (BluetoothCharacteristic characteristic in service.characteristics) {
if (characteristic.uuid.toString() == "19b10001-e8f2-537e-4f6c-d104768a1214") {
characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
setState(() {
temperature = String.fromCharCodes(value);
});
});
}
if (characteristic.uuid.toString() == "19b10002-e8f2-537e-4f6c-d104768a1214") {
characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
setState(() {
humidity = String.fromCharCodes(value);
});
});
}
if (characteristic.uuid.toString() == "19b10003-e8f2-537e-4f6c-d104768a1214") {
characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
setState(() {
pressure = String.fromCharCodes(value);
});
});
}
if (characteristic.uuid.toString() == "19b10004-e8f2-537e-4f6c-d104768a1214") {
characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
setState(() {
waterTemperature = String.f
