Skip to content

sceic/Android-ESP32-Battery-Charge-Controller

Repository files navigation

电池控制器

这是一个Android应用程序,用于监控手机电池电量并通过蓝牙控制ESP32继电器。 手机硬件测试环境: Android 14 (One Plus 8T) 艾尔赛AC供电ESP32单路继电器开发板(ESP32_Relay_AC X1_V1.1(303E32AC111))

功能特点

  • 实时监控手机电池电量
  • 可设置高低电量阈值、当电量达到设定阈值时自动控制继电器
  • 有防震荡,防止频繁切换继电器
  • 启动时确保收到有效电量数据后才控制继电器,避免误触发
  • 通过蓝牙与ESP32通信
  • 记录操作历史
  • 保存用户设置

技术特点

  • 使用 SQLite 数据库存储历史记录
  • 使用 RecyclerView 显示历史记录列表
  • 使用蓝牙LE通信
  • 实现电池状态监听
  • 使用 SharedPreferences 保存设置

使用说明

  1. 安装应用
  2. 靠预设UUID配对ESP32蓝牙模块
  3. 设置所需的高低电量阈值
  4. 应用会在前、后台自动监控电量并控制继电器

ESP32端代码

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

const int RELAY_PIN = 16;  // 使用IO16引脚

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define THRESHOLD_CHAR_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a9"
#define RELAY_STATE_UUID    "beb5483e-36e1-4688-b7f5-ea07361b26aa"

BLEServer* pServer = NULL;
BLECharacteristic* pBatteryCharacteristic = NULL;
BLECharacteristic* pThresholdCharacteristic = NULL;
BLECharacteristic* pRelayStateCharacteristic = NULL;

bool deviceConnected = false;
int highThreshold = 80;
int lowThreshold = 20;
int lastBatteryLevel = 0;
bool batteryLevelValid = false; // 是否已接收到有效电量

bool currentRelayState = false;
unsigned long lastRelayChangeTime = 0;
const unsigned long MIN_SWITCH_INTERVAL = 5000; // 最小切换间隔(毫秒)

// 继电器状态控制
void updateRelayState() {
  if (!batteryLevelValid) {
    Serial.println("尚未接收到有效电量数据,跳过继电器状态更新");
    return;
  }

  bool desiredRelayState = currentRelayState;

  if (lastBatteryLevel >= highThreshold) {
    desiredRelayState = false;
  } else if (lastBatteryLevel <= lowThreshold) {
    desiredRelayState = true;
  } else {
    return; // 电量在阈值中间区域,不切换
  }

  unsigned long now = millis();
  if (desiredRelayState != currentRelayState && 
      (now - lastRelayChangeTime >= MIN_SWITCH_INTERVAL)) {

    digitalWrite(RELAY_PIN, desiredRelayState ? HIGH : LOW);
    currentRelayState = desiredRelayState;
    lastRelayChangeTime = now;

    Serial.print("继电器状态已更新: ");
    Serial.println(currentRelayState ? "闭合(充电)" : "断开(停止充电)");

    // 通知 APP 状态
    if (deviceConnected && pRelayStateCharacteristic != NULL) {
      String stateStr = currentRelayState ? "1" : "0";
      pRelayStateCharacteristic->setValue(stateStr.c_str());
      pRelayStateCharacteristic->notify();
      Serial.print("发送继电器状态: ");
      Serial.println(stateStr);
    }
  } else if (desiredRelayState != currentRelayState) {
    Serial.println("继电器状态需要切换,但尚未达到最小切换间隔,跳过。");
  }
}

// BLE 连接状态回调
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("设备已连接");
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("设备已断开");
    BLEDevice::startAdvertising();
  }
};

// 电量特征回调
class BatteryCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String value = pCharacteristic->getValue().c_str();
    if (value.length() > 0) {
      int batteryLevel = value.toInt();
      lastBatteryLevel = batteryLevel;
      batteryLevelValid = true;

      Serial.print("收到电量值: ");
      Serial.println(batteryLevel);
      updateRelayState();
    }
  }
};

// 阈值特征回调
class ThresholdCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String value = pCharacteristic->getValue().c_str();
    if (value.length() > 0) {
      int commaIndex = value.indexOf(',');
      if (commaIndex != -1) {
        highThreshold = value.substring(0, commaIndex).toInt();
        lowThreshold = value.substring(commaIndex + 1).toInt();
        Serial.print("更新阈值 - 高: ");
        Serial.print(highThreshold);
        Serial.print("%, 低: ");
        Serial.println(lowThreshold);
        updateRelayState();
      }
    }
  }
};

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // 默认不充电

  BLEDevice::init("ESP32_Battery_Controller");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

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

  pBatteryCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_WRITE |
    BLECharacteristic::PROPERTY_NOTIFY
  );
  pBatteryCharacteristic->setCallbacks(new BatteryCallbacks());
  pBatteryCharacteristic->addDescriptor(new BLE2902());

  pThresholdCharacteristic = pService->createCharacteristic(
    THRESHOLD_CHAR_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_WRITE
  );
  pThresholdCharacteristic->setCallbacks(new ThresholdCallbacks());

  pRelayStateCharacteristic = pService->createCharacteristic(
    RELAY_STATE_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_NOTIFY
  );
  pRelayStateCharacteristic->addDescriptor(new BLE2902());

  pService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  Serial.println("ESP32电池控制器已启动,等待连接...");
}

void loop() {
  delay(2000);
}

开发环境要求

  • Android Studio Meerkat 2024.3.1 Path1
  • ESP32开发板
  • Arduino IDE 2.3.2

安装说明

  1. 克隆仓库
  2. 在Android Studio中打开项目,连接已开启开发调试的手机,Shift+10 编译并将APP安装到手机
  3. 将上面ESP32端代码通过 Arduino IDE编译并写入到ESP32继电器开发板

注意事项

  • 确保ESP32已经正确烧录代码
  • 确保蓝牙已开启并已配对ESP32
  • 建议将应用加入电池优化白名单
  • 首次运行需要授予蓝牙权限

许可证

MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published