这是一个Android应用程序,用于监控手机电池电量并通过蓝牙控制ESP32继电器。 手机硬件测试环境: Android 14 (One Plus 8T) 艾尔赛AC供电ESP32单路继电器开发板(ESP32_Relay_AC X1_V1.1(303E32AC111))
- 实时监控手机电池电量
- 可设置高低电量阈值、当电量达到设定阈值时自动控制继电器
- 有防震荡,防止频繁切换继电器
- 启动时确保收到有效电量数据后才控制继电器,避免误触发
- 通过蓝牙与ESP32通信
- 记录操作历史
- 保存用户设置
- 使用 SQLite 数据库存储历史记录
- 使用 RecyclerView 显示历史记录列表
- 使用蓝牙LE通信
- 实现电池状态监听
- 使用 SharedPreferences 保存设置
- 安装应用
- 靠预设UUID配对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
- 克隆仓库
- 在Android Studio中打开项目,连接已开启开发调试的手机,Shift+10 编译并将APP安装到手机
- 将上面ESP32端代码通过 Arduino IDE编译并写入到ESP32继电器开发板
- 确保ESP32已经正确烧录代码
- 确保蓝牙已开启并已配对ESP32
- 建议将应用加入电池优化白名单
- 首次运行需要授予蓝牙权限
MIT License