BLE対応のESP32センサー取得アプリ


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");
}


コードの説明

  1. BLE初期化:

    • BLEDevice::init("AQUA-FAN-BLE"); でBLEデバイスを初期化します。
    • BLEServerBLEServiceを作成し、センサーデータを公開するためのBLECharacteristicを定義します。
  2. センサーデータの取得:

    • AHT10/AHT20、BMP280、DS18B20から温度、湿度、気圧、水温を取得します。
  3. BLE経由でデータを送信:

    • センサーデータをBLE Characteristicsに設定し、notify()を呼び出してクライアントに通知します。
  4. 接続状態の管理:

    • デバイスが接続または切断された場合に、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
タイトルとURLをコピーしました