蓝牙连接不稳定修复
This commit is contained in:
@@ -36,6 +36,10 @@ public class EspProvisionManager {
|
||||
private final Context context;
|
||||
private final Handler mainHandler;
|
||||
private final com.espressif.provisioning.ESPProvisionManager provisionManager;
|
||||
private static final long CONNECT_COOLDOWN = 1200L;
|
||||
private static final long QUICK_DISCONNECT_WINDOW = 3000L;
|
||||
private static final long RETRY_DELAY = 1200L;
|
||||
private static final int MAX_CONNECT_RETRY = 2;
|
||||
|
||||
private ESPDevice espDevice;
|
||||
private ProvisionCallback callback;
|
||||
@@ -47,12 +51,28 @@ public class EspProvisionManager {
|
||||
private boolean expectDisconnected; // 标记是否预期断开(配网成功后)
|
||||
private String currentDeviceName;
|
||||
private String currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
|
||||
private BluetoothDevice pendingBluetoothDevice;
|
||||
private String pendingDeviceName;
|
||||
private String pendingServiceUuid;
|
||||
private String pendingProofOfPossession;
|
||||
private String pendingUserName;
|
||||
private int pendingSecurityType;
|
||||
private int connectRetryCount;
|
||||
private long lastDisconnectTime;
|
||||
private long connectStartTime;
|
||||
|
||||
private final Runnable connectionTimeoutTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (connecting && !connected) {
|
||||
connecting = false;
|
||||
disconnectDeviceOnly();
|
||||
lastDisconnectTime = System.currentTimeMillis();
|
||||
if (retryConnectIfAllowed()) {
|
||||
return;
|
||||
}
|
||||
resetState(true);
|
||||
clearPendingConnect();
|
||||
notifyFailed(ProvisionConfig.ERROR_CONNECT_TIMEOUT, "蓝牙连接超时");
|
||||
disconnectDeviceOnly();
|
||||
}
|
||||
@@ -68,6 +88,13 @@ public class EspProvisionManager {
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable connectRetryTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startPendingConnect(false);
|
||||
}
|
||||
};
|
||||
|
||||
private EspProvisionManager(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.mainHandler = new Handler(Looper.getMainLooper());
|
||||
@@ -150,32 +177,91 @@ public class EspProvisionManager {
|
||||
return;
|
||||
}
|
||||
|
||||
String primaryServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
|
||||
String displayName = !TextUtils.isEmpty(deviceName) ? deviceName : bluetoothDevice.getName();
|
||||
if (connecting && pendingBluetoothDevice != null
|
||||
&& TextUtils.equals(pendingBluetoothDevice.getAddress(), bluetoothDevice.getAddress())) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingBluetoothDevice = bluetoothDevice;
|
||||
pendingDeviceName = deviceName;
|
||||
pendingServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
|
||||
pendingProofOfPossession = proofOfPossession == null ? "" : proofOfPossession;
|
||||
pendingUserName = userName == null ? "" : userName;
|
||||
pendingSecurityType = securityType;
|
||||
connectRetryCount = 0;
|
||||
startPendingConnect(true);
|
||||
}
|
||||
|
||||
|
||||
private void startPendingConnect(boolean respectCooldown) {
|
||||
if (pendingBluetoothDevice == null) {
|
||||
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "钃濈墮璁惧鏃犳晥");
|
||||
return;
|
||||
}
|
||||
if (provisioning) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainHandler.removeCallbacks(connectRetryTask);
|
||||
long elapsedSinceDisconnect = System.currentTimeMillis() - lastDisconnectTime;
|
||||
if (respectCooldown && lastDisconnectTime > 0 && elapsedSinceDisconnect < CONNECT_COOLDOWN) {
|
||||
mainHandler.postDelayed(connectRetryTask, CONNECT_COOLDOWN - elapsedSinceDisconnect);
|
||||
return;
|
||||
}
|
||||
|
||||
String displayName = !TextUtils.isEmpty(pendingDeviceName)
|
||||
? pendingDeviceName : pendingBluetoothDevice.getName();
|
||||
currentDeviceName = displayName;
|
||||
currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
|
||||
|
||||
ignoreNextDisconnectEvent = espDevice != null;
|
||||
boolean hadActiveDevice = espDevice != null && (connecting || connected || provisioning);
|
||||
ignoreNextDisconnectEvent = hadActiveDevice;
|
||||
disconnectDeviceOnly();
|
||||
ensureEventBusRegistered();
|
||||
|
||||
espDevice = provisionManager.createESPDevice(
|
||||
ESPConstants.TransportType.TRANSPORT_BLE,
|
||||
parseSecurityType(securityType)
|
||||
parseSecurityType(pendingSecurityType)
|
||||
);
|
||||
espDevice.setBluetoothDevice(bluetoothDevice);
|
||||
espDevice.setPrimaryServiceUuid(primaryServiceUuid);
|
||||
espDevice.setBluetoothDevice(pendingBluetoothDevice);
|
||||
espDevice.setPrimaryServiceUuid(pendingServiceUuid);
|
||||
espDevice.setDeviceName(displayName);
|
||||
espDevice.setProofOfPossession(proofOfPossession == null ? "" : proofOfPossession);
|
||||
espDevice.setUserName(userName == null ? "" : userName);
|
||||
espDevice.setProofOfPossession(pendingProofOfPossession);
|
||||
espDevice.setUserName(pendingUserName);
|
||||
|
||||
connecting = true;
|
||||
connected = false;
|
||||
provisioning = false;
|
||||
connectStartTime = System.currentTimeMillis();
|
||||
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||
mainHandler.postDelayed(connectionTimeoutTask, ProvisionConfig.CONNECTION_TIMEOUT);
|
||||
notifyConnecting();
|
||||
espDevice.connectBLEDevice(bluetoothDevice, primaryServiceUuid);
|
||||
espDevice.connectBLEDevice(pendingBluetoothDevice, pendingServiceUuid);
|
||||
}
|
||||
|
||||
private boolean retryConnectIfAllowed() {
|
||||
if (pendingBluetoothDevice == null || provisioning || connected) {
|
||||
return false;
|
||||
}
|
||||
if (connectRetryCount >= MAX_CONNECT_RETRY) {
|
||||
return false;
|
||||
}
|
||||
connectRetryCount++;
|
||||
resetState(true);
|
||||
mainHandler.removeCallbacks(connectRetryTask);
|
||||
mainHandler.postDelayed(connectRetryTask, RETRY_DELAY * connectRetryCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void clearPendingConnect() {
|
||||
pendingBluetoothDevice = null;
|
||||
pendingDeviceName = null;
|
||||
pendingServiceUuid = null;
|
||||
pendingProofOfPossession = null;
|
||||
pendingUserName = null;
|
||||
pendingSecurityType = 0;
|
||||
connectRetryCount = 0;
|
||||
connectStartTime = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,8 +327,11 @@ public class EspProvisionManager {
|
||||
|
||||
public void disconnect() {
|
||||
boolean shouldNotify = connected || connecting || provisioning;
|
||||
mainHandler.removeCallbacks(connectRetryTask);
|
||||
disconnectDeviceOnly();
|
||||
resetState();
|
||||
lastDisconnectTime = System.currentTimeMillis();
|
||||
resetState(true);
|
||||
clearPendingConnect();
|
||||
if (shouldNotify) {
|
||||
notifyDisconnected();
|
||||
}
|
||||
@@ -258,8 +347,10 @@ public class EspProvisionManager {
|
||||
switch (event.getEventType()) {
|
||||
case ESPConstants.EVENT_DEVICE_CONNECTED:
|
||||
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||
mainHandler.removeCallbacks(connectRetryTask);
|
||||
connecting = false;
|
||||
connected = true;
|
||||
connectRetryCount = 0;
|
||||
notifyConnected();
|
||||
break;
|
||||
|
||||
@@ -270,7 +361,13 @@ public class EspProvisionManager {
|
||||
connecting = false;
|
||||
connected = false;
|
||||
provisioning = false;
|
||||
lastDisconnectTime = System.currentTimeMillis();
|
||||
if (wasConnecting && retryConnectIfAllowed()) {
|
||||
break;
|
||||
}
|
||||
if (wasConnecting) {
|
||||
resetState(true);
|
||||
clearPendingConnect();
|
||||
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
|
||||
} else {
|
||||
notifyFailed(ProvisionConfig.ERROR_PROVISION_FAILED, "设备通信失败");
|
||||
@@ -285,14 +382,27 @@ public class EspProvisionManager {
|
||||
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||
boolean shouldNotify = connected || connecting || provisioning;
|
||||
resetState();
|
||||
boolean expectedDisconnect = expectDisconnected;
|
||||
boolean wasConnecting2 = connecting;
|
||||
long connectDuration = System.currentTimeMillis() - connectStartTime;
|
||||
lastDisconnectTime = System.currentTimeMillis();
|
||||
resetState(true);
|
||||
if (wasConnecting2 && !expectedDisconnect
|
||||
&& connectDuration < QUICK_DISCONNECT_WINDOW
|
||||
&& retryConnectIfAllowed()) {
|
||||
break;
|
||||
}
|
||||
if (wasConnecting2 && !expectedDisconnect) {
|
||||
clearPendingConnect();
|
||||
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
|
||||
break;
|
||||
}
|
||||
if (shouldNotify) {
|
||||
// 如果是配网成功后的预期断开,不发送断开回调
|
||||
// 因为 onSuccess 已经通知过了
|
||||
if (!expectDisconnected) {
|
||||
if (!expectedDisconnect) {
|
||||
notifyDisconnected();
|
||||
}
|
||||
expectDisconnected = false; // 重置标志
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -321,14 +431,17 @@ public class EspProvisionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
private void resetState(boolean clearDevice) {
|
||||
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||
connecting = false;
|
||||
connected = false;
|
||||
provisioning = false;
|
||||
ignoreNextDisconnectEvent = false;
|
||||
// expectDisconnected 保持不变,用于断开回调判断
|
||||
expectDisconnected = false;
|
||||
if (clearDevice) {
|
||||
espDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
private ESPConstants.SecurityType parseSecurityType(int securityType) {
|
||||
|
||||
Reference in New Issue
Block a user