连接蓝牙,配网
This commit is contained in:
@@ -121,6 +121,7 @@ dependencies {
|
|||||||
implementation project(path: ':imagepickerl')
|
implementation project(path: ':imagepickerl')
|
||||||
//消息传递
|
//消息传递
|
||||||
implementation 'de.greenrobot:eventbus:3.0.0-beta1'
|
implementation 'de.greenrobot:eventbus:3.0.0-beta1'
|
||||||
|
implementation 'org.greenrobot:eventbus:3.3.1'
|
||||||
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
|
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
|
||||||
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
|
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
|
||||||
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
|
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
|
||||||
@@ -234,4 +235,3 @@ dependencies {
|
|||||||
implementation 'com.github.espressif:esp-idf-provisioning-android:lib-2.2.3'
|
implementation 'com.github.espressif:esp-idf-provisioning-android:lib-2.2.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,32 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
|||||||
initListener();
|
initListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化监听g
|
||||||
|
*/
|
||||||
|
private void initListener() {
|
||||||
|
setClick(viewBinding.includedTitle.imgBack);
|
||||||
|
setClick(viewBinding.tvScanAdd);
|
||||||
|
setClick(viewBinding.btnBleScan);
|
||||||
|
|
||||||
|
if(bleAdapter != null){
|
||||||
|
bleAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
|
||||||
|
WaterDeviceEntity device = mDeviceList.get(position);
|
||||||
|
String deviceName = TextUtils.isEmpty(device.getDeviceName()) ?
|
||||||
|
"未知设备" : device.getDeviceName();
|
||||||
|
// 停止扫描
|
||||||
|
stopBleScan();
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,100);
|
||||||
|
bundle.putSerializable("ble_device_entity",mDeviceList.get(position));
|
||||||
|
goTo(mContext, SelectWifiActivity.class,bundle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始 BLE 扫描
|
* 开始 BLE 扫描
|
||||||
*/
|
*/
|
||||||
@@ -192,7 +218,7 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
|||||||
ToastUtil.showShort(mContext, "扫描失败,错误码: " + errorCode);
|
ToastUtil.showShort(mContext, "扫描失败,错误码: " + errorCode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
scanner.startScan(null, settings, mScanCallback);
|
scanner.startScan(filters, settings, mScanCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,148 +232,7 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接蓝牙设备
|
|
||||||
*/
|
|
||||||
private void connectToDevice(String deviceAddress, String deviceName) {
|
|
||||||
if (waterDeviceManager != null) {
|
|
||||||
// 断开之前的连接
|
|
||||||
waterDeviceManager.disconnect().enqueue();
|
|
||||||
waterDeviceManager.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据地址获取 BluetoothDevice
|
|
||||||
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(deviceAddress);
|
|
||||||
if (device == null) {
|
|
||||||
ToastUtil.showShort(mContext, "设备无效");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
waterDeviceManager = new WaterDeviceManager(mContext);
|
|
||||||
|
|
||||||
// 设置数据回调
|
|
||||||
waterDeviceManager.setOnDataReceivedListener(bytes -> {
|
|
||||||
Log.e("TEST", "设备响应: " + Arrays.toString(bytes));
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
// TODO: 处理设备返回的数据,比如 WiFi 配置响应
|
|
||||||
handleDeviceResponse(bytes);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 连接设备
|
|
||||||
waterDeviceManager.connect(device)
|
|
||||||
.retry(3, 100) // 重试3次,间隔100ms
|
|
||||||
.done(bluetoothDevice -> {
|
|
||||||
Log.e("TEST", "连接成功: " + deviceName);
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
ToastUtil.showShort(mContext, "连接成功: " + deviceName);
|
|
||||||
// TODO: 连接成功后,发送 WiFi 配置
|
|
||||||
// sendWifiConfig("SSID", "PASSWORD");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.fail((bluetoothDevice, status) -> {
|
|
||||||
Log.e("TEST", "连接失败: " + status);
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
ToastUtil.showShort(mContext, "连接失败,请重试");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.enqueue();
|
|
||||||
|
|
||||||
waterDeviceManager.setConnectionObserver(new ConnectionObserver() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceConnecting(@NonNull BluetoothDevice device) {
|
|
||||||
Log.e("TEST", "onDeviceConnecting");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceConnected(@NonNull BluetoothDevice device) {
|
|
||||||
Log.e("TEST", "onDeviceConnected");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceFailedToConnect(@NonNull BluetoothDevice device, int reason) {
|
|
||||||
Log.e("TEST", "onDeviceFailedToConnect");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceReady(@NonNull BluetoothDevice device) {
|
|
||||||
Log.e("TEST", "onDeviceReady");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceDisconnecting(@NonNull BluetoothDevice device) {
|
|
||||||
Log.e("TEST", "onDeviceDisconnecting");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeviceDisconnected(
|
|
||||||
@NonNull BluetoothDevice device,
|
|
||||||
int reason) {
|
|
||||||
|
|
||||||
Log.e("TEST", "onDeviceDisconnected reason=" + reason);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送 WiFi 配置到设备
|
|
||||||
*/
|
|
||||||
public void sendWifiConfig(String ssid, String password) {
|
|
||||||
if (waterDeviceManager == null || !waterDeviceManager.isBlConnected()) {
|
|
||||||
Log.e("TEST", "设备未连接,无法发送WiFi配置");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 根据设备协议组装数据
|
|
||||||
// 示例:假设协议是 [header(1) + ssid_len(1) + ssid(n) + pwd_len(1) + pwd(m)]
|
|
||||||
byte[] ssidBytes = ssid.getBytes();
|
|
||||||
byte[] pwdBytes = password.getBytes();
|
|
||||||
|
|
||||||
byte[] data = new byte[2 + ssidBytes.length + 2 + pwdBytes.length];
|
|
||||||
int index = 0;
|
|
||||||
data[index++] = 0x01; // header
|
|
||||||
data[index++] = (byte) ssidBytes.length;
|
|
||||||
System.arraycopy(ssidBytes, 0, data, index, ssidBytes.length);
|
|
||||||
index += ssidBytes.length;
|
|
||||||
data[index++] = (byte) pwdBytes.length;
|
|
||||||
System.arraycopy(pwdBytes, 0, data, index, pwdBytes.length);
|
|
||||||
|
|
||||||
waterDeviceManager.send(data);
|
|
||||||
Log.e("TEST", "发送WiFi配置: SSID=" + ssid + ", PWD=" + password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理设备响应数据
|
|
||||||
*/
|
|
||||||
private void handleDeviceResponse(byte[] data) {
|
|
||||||
if (data == null || data.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 根据设备协议解析响应数据
|
|
||||||
// 示例:假设响应格式是 [type(1) + status(1) + ...]
|
|
||||||
Log.e("TEST", "处理设备响应: " + Arrays.toString(data));
|
|
||||||
|
|
||||||
if (data.length >= 2) {
|
|
||||||
byte type = data[0];
|
|
||||||
byte status = data[1];
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 0x01: // WiFi配置响应
|
|
||||||
if (status == 0x00) {
|
|
||||||
ToastUtil.showShort(mContext, "WiFi配置成功");
|
|
||||||
// TODO: 下一步操作
|
|
||||||
} else {
|
|
||||||
ToastUtil.showShort(mContext, "WiFi配置失败,错误码: " + status);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e("TEST", "未知响应类型: " + type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化蓝牙适配器
|
* 初始化蓝牙适配器
|
||||||
@@ -405,34 +290,6 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void initListener() {
|
|
||||||
setClick(viewBinding.includedTitle.imgBack);
|
|
||||||
setClick(viewBinding.tvScanAdd);
|
|
||||||
setClick(viewBinding.btnBleScan);
|
|
||||||
|
|
||||||
if(bleAdapter != null){
|
|
||||||
bleAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
|
|
||||||
WaterDeviceEntity device = mDeviceList.get(position);
|
|
||||||
String deviceName = TextUtils.isEmpty(device.getDeviceName()) ?
|
|
||||||
"未知设备" : device.getDeviceName();
|
|
||||||
String deviceAddress = device.getMacAddress();
|
|
||||||
|
|
||||||
ToastUtil.showShort(mContext, "正在连接: " + deviceName);
|
|
||||||
|
|
||||||
// 停止扫描
|
|
||||||
stopBleScan();
|
|
||||||
|
|
||||||
// 连接设备
|
|
||||||
connectToDevice(deviceAddress, deviceName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setClick(View view) {
|
private void setClick(View view) {
|
||||||
view.setOnClickListener(this::onClick);
|
view.setOnClickListener(this::onClick);
|
||||||
}
|
}
|
||||||
@@ -443,12 +300,6 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
|||||||
finish();
|
finish();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case R.id.img_device_item:
|
|
||||||
// Bundle bundle = new Bundle();
|
|
||||||
// bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,100);
|
|
||||||
// goTo(mContext, SelectWifiActivity.class,bundle);
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case R.id.tv_scan_add:
|
case R.id.tv_scan_add:
|
||||||
//检测有无相机权限
|
//检测有无相机权限
|
||||||
String readPermission = Manifest.permission.CAMERA;
|
String readPermission = Manifest.permission.CAMERA;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.net.wifi.ScanResult;
|
|||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
@@ -21,6 +22,8 @@ import com.ckkj.water.databinding.DeviceResetWifiBinding;
|
|||||||
import com.ckkj.water.device.mvp.DeviceContract;
|
import com.ckkj.water.device.mvp.DeviceContract;
|
||||||
import com.ckkj.water.device.mvp.DeviceImpl;
|
import com.ckkj.water.device.mvp.DeviceImpl;
|
||||||
import com.ckkj.water.device.mvp.DevicePresenter;
|
import com.ckkj.water.device.mvp.DevicePresenter;
|
||||||
|
import com.ckkj.water.espBle.EspProvisionManager;
|
||||||
|
import com.ckkj.water.espBle.ProvisionCallback;
|
||||||
import com.ckkj.water.index.entity.WaterDeviceEntity;
|
import com.ckkj.water.index.entity.WaterDeviceEntity;
|
||||||
import com.ckkj.water.network.BaseBean;
|
import com.ckkj.water.network.BaseBean;
|
||||||
import com.ckkj.water.permission.PermissionActivity;
|
import com.ckkj.water.permission.PermissionActivity;
|
||||||
@@ -34,6 +37,9 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置wifi
|
||||||
|
*/
|
||||||
public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, DevicePresenter>
|
public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, DevicePresenter>
|
||||||
implements DeviceContract.DeviceView {
|
implements DeviceContract.DeviceView {
|
||||||
|
|
||||||
@@ -45,6 +51,11 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
|
|||||||
|
|
||||||
private String mWifiName = "";
|
private String mWifiName = "";
|
||||||
|
|
||||||
|
private WaterDeviceEntity mBleDeviceEntity;
|
||||||
|
private EspProvisionManager espProvisionManager;
|
||||||
|
private boolean isBleConnecting = false;
|
||||||
|
private boolean isBleConnected = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DevicePresenter createPresenter() {
|
public DevicePresenter createPresenter() {
|
||||||
return new DevicePresenter(new DeviceImpl());
|
return new DevicePresenter(new DeviceImpl());
|
||||||
@@ -70,12 +81,22 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
|
|||||||
unregisterReceiver(wifiScanReceiver);
|
unregisterReceiver(wifiScanReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (WITCH_FROM_CODE == 100 && espProvisionManager != null) {
|
||||||
|
espProvisionManager.disconnect();
|
||||||
|
espProvisionManager.setCallback(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initData(Bundle savedInstanceState) {
|
public void initData(Bundle savedInstanceState) {
|
||||||
super.initData(savedInstanceState);
|
super.initData(savedInstanceState);
|
||||||
Bundle bundle = getIntent().getExtras();
|
Bundle bundle = getIntent().getExtras();
|
||||||
if(bundle != null){
|
if(bundle != null){
|
||||||
WITCH_FROM_CODE = bundle.getInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG);
|
WITCH_FROM_CODE = bundle.getInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG);
|
||||||
|
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmersionBar.with(this)
|
ImmersionBar.with(this)
|
||||||
@@ -90,6 +111,10 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
|
|||||||
|
|
||||||
initListener();
|
initListener();
|
||||||
initWifiList();
|
initWifiList();
|
||||||
|
if (WITCH_FROM_CODE == 100) {
|
||||||
|
initEspProvision();
|
||||||
|
connectBleDevice();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWifiList() {
|
private void initWifiList() {
|
||||||
@@ -142,7 +167,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(WITCH_FROM_CODE == 100){
|
if(WITCH_FROM_CODE == 100){
|
||||||
goTo(mContext,DeviceConnectActivity.class,null);
|
provisionWifi();
|
||||||
}else{
|
}else{
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra("wifi_name",mWifiName);
|
intent.putExtra("wifi_name",mWifiName);
|
||||||
@@ -154,6 +179,98 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置网络
|
||||||
|
*/
|
||||||
|
private void provisionWifi() {
|
||||||
|
if (espProvisionManager == null) {
|
||||||
|
ToastUtil.showShort(mContext, "设备连接未初始化");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isBleConnected) {
|
||||||
|
if (!isBleConnecting) {
|
||||||
|
connectBleDevice();
|
||||||
|
}
|
||||||
|
ToastUtil.showShort(mContext, "设备连接中,请稍后再试");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
espProvisionManager.provisionWifi(mWifiName, viewBinding.etInputPsd.getText().toString());
|
||||||
|
// goTo(mContext,DeviceConnectActivity.class,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initEspProvision() {
|
||||||
|
espProvisionManager = EspProvisionManager.init(mContext).setCallback(new ProvisionCallback() {
|
||||||
|
@Override
|
||||||
|
public void onConnecting() {
|
||||||
|
isBleConnecting = true;
|
||||||
|
isBleConnected = false;
|
||||||
|
Log.i("TEST","onConnecting");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnected() {
|
||||||
|
isBleConnecting = false;
|
||||||
|
isBleConnected = true;
|
||||||
|
Log.i("TEST","onConnected设备连接成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProvisioning(int progress) {
|
||||||
|
Log.i("TEST","WIFI连接进度 == " + progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String deviceName, String deviceType) {
|
||||||
|
Log.i("TEST","deviceName:" + deviceName + "连接成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(int errorCode, String message) {
|
||||||
|
isBleConnecting = false;
|
||||||
|
if (errorCode != 0) {
|
||||||
|
isBleConnected = espProvisionManager != null && espProvisionManager.isConnected();
|
||||||
|
}
|
||||||
|
Log.i("TEST","errorCode == " + errorCode + " message == " + message);
|
||||||
|
ToastUtil.showShort(mContext, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnected() {
|
||||||
|
isBleConnecting = false;
|
||||||
|
isBleConnected = false;
|
||||||
|
Log.i("TEST","onDisconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWifiListReceived(String[] wifiList) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWifiListFailed(String message) {
|
||||||
|
Log.i("TEST","onWifiListFailed-Msg==" + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProvisioningRejected() {
|
||||||
|
Log.i("TEST","onProvisioningRejected");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接设备
|
||||||
|
*/
|
||||||
|
private void connectBleDevice() {
|
||||||
|
if (WITCH_FROM_CODE != 100 || mBleDeviceEntity == null || espProvisionManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isBleConnected || isBleConnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
|
||||||
|
}
|
||||||
|
|
||||||
private void scanWifi() {
|
private void scanWifi() {
|
||||||
showLoadingDialog();
|
showLoadingDialog();
|
||||||
viewBinding.tvNext.setVisibility(View.GONE);
|
viewBinding.tvNext.setVisibility(View.GONE);
|
||||||
|
|||||||
517
app/src/main/java/com/ckkj/water/espBle/EspProvisionManager.java
Normal file
517
app/src/main/java/com/ckkj/water/espBle/EspProvisionManager.java
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
package com.ckkj.water.espBle;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.ckkj.water.AppConfig;
|
||||||
|
import com.espressif.provisioning.DeviceConnectionEvent;
|
||||||
|
import com.espressif.provisioning.ESPConstants;
|
||||||
|
import com.espressif.provisioning.ESPDevice;
|
||||||
|
import com.espressif.provisioning.WiFiAccessPoint;
|
||||||
|
import com.espressif.provisioning.listeners.ProvisionListener;
|
||||||
|
import com.espressif.provisioning.listeners.WiFiScanListener;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author fengxiaoyang
|
||||||
|
* @date 2026/6/4
|
||||||
|
* @description 鎿嶄綔钃濈墮绠$悊绫?
|
||||||
|
*/
|
||||||
|
public class EspProvisionManager {
|
||||||
|
private static volatile EspProvisionManager instance;
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final Handler mainHandler;
|
||||||
|
private final com.espressif.provisioning.ESPProvisionManager provisionManager;
|
||||||
|
|
||||||
|
private ESPDevice espDevice;
|
||||||
|
private ProvisionCallback callback;
|
||||||
|
private boolean connecting;
|
||||||
|
private boolean connected;
|
||||||
|
private boolean provisioning;
|
||||||
|
private boolean eventBusRegistered;
|
||||||
|
private boolean ignoreNextDisconnectEvent;
|
||||||
|
private String currentDeviceName;
|
||||||
|
private String currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
|
||||||
|
|
||||||
|
private final Runnable connectionTimeoutTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (connecting && !connected) {
|
||||||
|
connecting = false;
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_CONNECT_TIMEOUT, "蓝牙连接超时");
|
||||||
|
disconnectDeviceOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Runnable provisionTimeoutTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (provisioning) {
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_TIMEOUT, "配网超时");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private EspProvisionManager(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
this.mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
this.provisionManager = com.espressif.provisioning.ESPProvisionManager.getInstance(this.context);
|
||||||
|
ensureEventBusRegistered();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EspProvisionManager init(Context context) {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (EspProvisionManager.class) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new EspProvisionManager(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EspProvisionManager get() {
|
||||||
|
if (instance == null) {
|
||||||
|
throw new RuntimeException("Please call init()");
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EspProvisionManager setCallback(ProvisionCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ESPDevice getEspDevice() {
|
||||||
|
return espDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProvisioning() {
|
||||||
|
return provisioning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String deviceAddress, String deviceName) {
|
||||||
|
connect(deviceAddress, deviceName, AppConfig.BLUETOOTH_DEVICE_UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String deviceAddress, String deviceName, String serviceUuid) {
|
||||||
|
connect(deviceAddress, deviceName, serviceUuid, "", ProvisionConfig.DEFAULT_SECURITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String deviceAddress, String deviceName, String serviceUuid,
|
||||||
|
String proofOfPossession, int securityType) {
|
||||||
|
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
if (bluetoothAdapter == null || TextUtils.isEmpty(deviceAddress)) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备无效");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(deviceAddress);
|
||||||
|
connect(bluetoothDevice, deviceName, serviceUuid, proofOfPossession, securityType);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备地址无效");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(BluetoothDevice bluetoothDevice, String serviceUuid) {
|
||||||
|
connect(bluetoothDevice, null, serviceUuid, "", ProvisionConfig.DEFAULT_SECURITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(BluetoothDevice bluetoothDevice, String deviceName, String serviceUuid,
|
||||||
|
String proofOfPossession, int securityType) {
|
||||||
|
connect(bluetoothDevice, deviceName, serviceUuid, proofOfPossession, "", securityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(BluetoothDevice bluetoothDevice, String deviceName, String serviceUuid,
|
||||||
|
String proofOfPossession, String userName, int securityType) {
|
||||||
|
if (bluetoothDevice == null) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备无效");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String primaryServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
|
||||||
|
String displayName = !TextUtils.isEmpty(deviceName) ? deviceName : bluetoothDevice.getName();
|
||||||
|
currentDeviceName = displayName;
|
||||||
|
currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
|
||||||
|
|
||||||
|
ignoreNextDisconnectEvent = espDevice != null;
|
||||||
|
disconnectDeviceOnly();
|
||||||
|
ensureEventBusRegistered();
|
||||||
|
|
||||||
|
espDevice = provisionManager.createESPDevice(
|
||||||
|
ESPConstants.TransportType.TRANSPORT_BLE,
|
||||||
|
parseSecurityType(securityType)
|
||||||
|
);
|
||||||
|
espDevice.setBluetoothDevice(bluetoothDevice);
|
||||||
|
espDevice.setPrimaryServiceUuid(primaryServiceUuid);
|
||||||
|
espDevice.setDeviceName(displayName);
|
||||||
|
espDevice.setProofOfPossession(proofOfPossession == null ? "" : proofOfPossession);
|
||||||
|
espDevice.setUserName(userName == null ? "" : userName);
|
||||||
|
|
||||||
|
connecting = true;
|
||||||
|
connected = false;
|
||||||
|
provisioning = false;
|
||||||
|
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||||
|
mainHandler.postDelayed(connectionTimeoutTask, ProvisionConfig.CONNECTION_TIMEOUT);
|
||||||
|
notifyConnecting();
|
||||||
|
espDevice.connectBLEDevice(bluetoothDevice, primaryServiceUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scanDeviceWifiList() {
|
||||||
|
if (!checkConnected()) {
|
||||||
|
notifyWifiListFailed("设备未连接");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
espDevice.scanNetworks(new WiFiScanListener() {
|
||||||
|
@Override
|
||||||
|
public void onWifiListReceived(ArrayList<WiFiAccessPoint> wifiList) {
|
||||||
|
Set<String> wifiNames = new LinkedHashSet<>();
|
||||||
|
if (wifiList != null) {
|
||||||
|
for (WiFiAccessPoint accessPoint : wifiList) {
|
||||||
|
if (accessPoint != null && !TextUtils.isEmpty(accessPoint.getWifiName())) {
|
||||||
|
wifiNames.add(accessPoint.getWifiName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyWifiListReceived(wifiNames.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWiFiScanFailed(Exception e) {
|
||||||
|
notifyWifiListFailed(getErrorMessage(e, "获取设备 WiFi 列表失败"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void provision(String ssid, String password) {
|
||||||
|
provisionWifi(ssid, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void provisionWifi(String ssid, String password) {
|
||||||
|
if (!checkConnected()) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_NOT_CONNECTED, "设备未连接");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(ssid)) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_WIFI_CONFIG_FAILED, "WiFi 名称不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioning = true;
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
mainHandler.postDelayed(provisionTimeoutTask, ProvisionConfig.PROVISION_TIMEOUT);
|
||||||
|
notifyProvisioning(0);
|
||||||
|
|
||||||
|
espDevice.provision(ssid, password == null ? "" : password, new ProvisionListener() {
|
||||||
|
@Override
|
||||||
|
public void createSessionFailed(Exception e) {
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_SESSION_FAILED, getErrorMessage(e, "创建配网会话失败"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wifiConfigSent() {
|
||||||
|
notifyProvisioning(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wifiConfigFailed(Exception e) {
|
||||||
|
notifyProvisioningRejected();
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_WIFI_CONFIG_FAILED, getErrorMessage(e, "发送 WiFi 信息失败"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wifiConfigApplied() {
|
||||||
|
notifyProvisioning(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wifiConfigApplyFailed(Exception e) {
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_WIFI_APPLY_FAILED, getErrorMessage(e, "应用 WiFi 信息失败"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void provisioningFailedFromDevice(ESPConstants.ProvisionFailureReason failureReason) {
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_FAILED, getProvisionFailureMessage(failureReason));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deviceProvisioningSuccess() {
|
||||||
|
finishProvisionSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProvisioningFailed(Exception e) {
|
||||||
|
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_FAILED, getErrorMessage(e, "配网失败"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
boolean shouldNotify = connected || connecting || provisioning;
|
||||||
|
disconnectDeviceOnly();
|
||||||
|
resetState();
|
||||||
|
if (shouldNotify) {
|
||||||
|
notifyDisconnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
disconnect();
|
||||||
|
callback = null;
|
||||||
|
mainHandler.removeCallbacksAndMessages(null);
|
||||||
|
if (eventBusRegistered) {
|
||||||
|
EventBus.getDefault().unregister(this);
|
||||||
|
eventBusRegistered = false;
|
||||||
|
}
|
||||||
|
if (instance == this) {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onDeviceConnectionEvent(DeviceConnectionEvent event) {
|
||||||
|
if (event == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.getEventType()) {
|
||||||
|
case ESPConstants.EVENT_DEVICE_CONNECTED:
|
||||||
|
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||||
|
connecting = false;
|
||||||
|
connected = true;
|
||||||
|
notifyConnected();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESPConstants.EVENT_DEVICE_CONNECTION_FAILED:
|
||||||
|
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
boolean wasConnecting = connecting;
|
||||||
|
connecting = false;
|
||||||
|
connected = false;
|
||||||
|
provisioning = false;
|
||||||
|
if (wasConnecting) {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
|
||||||
|
} else {
|
||||||
|
notifyFailed(ProvisionConfig.ERROR_PROVISION_FAILED, "设备通信失败");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESPConstants.EVENT_DEVICE_DISCONNECTED:
|
||||||
|
if (ignoreNextDisconnectEvent) {
|
||||||
|
ignoreNextDisconnectEvent = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
boolean shouldNotify = connected || connecting || provisioning;
|
||||||
|
resetState();
|
||||||
|
if (shouldNotify) {
|
||||||
|
notifyDisconnected();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkConnected() {
|
||||||
|
return espDevice != null && connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureEventBusRegistered() {
|
||||||
|
if (!eventBusRegistered) {
|
||||||
|
EventBus.getDefault().register(this);
|
||||||
|
eventBusRegistered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disconnectDeviceOnly() {
|
||||||
|
if (espDevice != null) {
|
||||||
|
try {
|
||||||
|
espDevice.disconnectDevice();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetState() {
|
||||||
|
mainHandler.removeCallbacks(connectionTimeoutTask);
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
connecting = false;
|
||||||
|
connected = false;
|
||||||
|
provisioning = false;
|
||||||
|
ignoreNextDisconnectEvent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ESPConstants.SecurityType parseSecurityType(int securityType) {
|
||||||
|
if (securityType == ProvisionConfig.SECURITY_0) {
|
||||||
|
return ESPConstants.SecurityType.SECURITY_0;
|
||||||
|
} else if (securityType == ProvisionConfig.SECURITY_1) {
|
||||||
|
return ESPConstants.SecurityType.SECURITY_1;
|
||||||
|
} else {
|
||||||
|
return ESPConstants.SecurityType.SECURITY_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishProvisionSuccess() {
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
provisioning = false;
|
||||||
|
notifyProvisioning(100);
|
||||||
|
notifySuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishProvisionFailed(int errorCode, String message) {
|
||||||
|
mainHandler.removeCallbacks(provisionTimeoutTask);
|
||||||
|
provisioning = false;
|
||||||
|
notifyFailed(errorCode, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getProvisionFailureMessage(ESPConstants.ProvisionFailureReason failureReason) {
|
||||||
|
if (failureReason == ESPConstants.ProvisionFailureReason.AUTH_FAILED) {
|
||||||
|
return "WiFi 密码错误";
|
||||||
|
} else if (failureReason == ESPConstants.ProvisionFailureReason.NETWORK_NOT_FOUND) {
|
||||||
|
return "未找到指定 WiFi";
|
||||||
|
} else if (failureReason == ESPConstants.ProvisionFailureReason.DEVICE_DISCONNECTED) {
|
||||||
|
return "设备已断开连接";
|
||||||
|
} else {
|
||||||
|
return "设备配网失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getErrorMessage(Exception e, String defaultMessage) {
|
||||||
|
if (e != null && !TextUtils.isEmpty(e.getMessage())) {
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
|
return defaultMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runOnMainThread(Runnable runnable) {
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
runnable.run();
|
||||||
|
} else {
|
||||||
|
mainHandler.post(runnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyConnecting() {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onConnecting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyConnected() {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyProvisioning(final int progress) {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onProvisioning(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifySuccess() {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onSuccess(currentDeviceName, currentDeviceType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyFailed(final int errorCode, final String message) {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailed(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyDisconnected() {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onDisconnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyWifiListReceived(final String[] wifiList) {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onWifiListReceived(wifiList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyWifiListFailed(final String message) {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onWifiListFailed(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyProvisioningRejected() {
|
||||||
|
runOnMainThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onProvisioningRejected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.ckkj.water.espBle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author fengxiaoyang
|
||||||
|
* @date 2026/6/4
|
||||||
|
* @description 蓝牙设备配网回调接口
|
||||||
|
*/
|
||||||
|
public interface ProvisionCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正在连接设备
|
||||||
|
*/
|
||||||
|
void onConnecting();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备连接成功
|
||||||
|
*/
|
||||||
|
void onConnected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正在配网中
|
||||||
|
* @param progress 配网进度 (0-100)
|
||||||
|
*/
|
||||||
|
void onProvisioning(int progress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配网成功
|
||||||
|
* @param deviceName 设备名称
|
||||||
|
* @param deviceType 设备类型
|
||||||
|
*/
|
||||||
|
void onSuccess(String deviceName, String deviceType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配网失败
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 错误信息
|
||||||
|
*/
|
||||||
|
void onFailed(int errorCode, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备断开连接
|
||||||
|
*/
|
||||||
|
void onDisconnected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi列表获取成功
|
||||||
|
* @param wifiList WiFi列表
|
||||||
|
*/
|
||||||
|
void onWifiListReceived(String[] wifiList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取WiFi列表失败
|
||||||
|
* @param message 错误信息
|
||||||
|
*/
|
||||||
|
void onWifiListFailed(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配网被拒绝(设备端拒绝配网请求)
|
||||||
|
*/
|
||||||
|
void onProvisioningRejected();
|
||||||
|
}
|
||||||
125
app/src/main/java/com/ckkj/water/espBle/ProvisionConfig.java
Normal file
125
app/src/main/java/com/ckkj/water/espBle/ProvisionConfig.java
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package com.ckkj.water.espBle;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import com.espressif.provisioning.ESPConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author fengxiaoyang
|
||||||
|
* @date 2026/6/4
|
||||||
|
* @description 蓝牙配网配置管理类
|
||||||
|
*/
|
||||||
|
public class ProvisionConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESP BLE Service UUID
|
||||||
|
*/
|
||||||
|
public static final String SERVICE_UUID =
|
||||||
|
"0000ffff-0000-1000-8000-00805f9b34fb";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESP BLE Characteristic UUID for writes
|
||||||
|
*/
|
||||||
|
public static final String CHARACTERISTIC_UUID =
|
||||||
|
"0000ff01-0000-1000-8000-00805f9b34fb";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESP BLE Characteristic UUID for notifications
|
||||||
|
*/
|
||||||
|
public static final String NOTIFY_UUID =
|
||||||
|
"0000ff02-0000-1000-8000-00805f9b34fb";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备传输的协议类型
|
||||||
|
*/
|
||||||
|
public static final String TRANSPORT_BLE = "ble";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备前缀 (用于过滤设备)
|
||||||
|
*/
|
||||||
|
public static final String DEVICE_PREFIX = "PROV_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全类型 - SECURITY_0 (无安全)
|
||||||
|
*/
|
||||||
|
public static final int SECURITY_0 = ESPConstants.SecurityType.SECURITY_0.ordinal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全类型 - SECURITY_1 (推荐)
|
||||||
|
*/
|
||||||
|
public static final int SECURITY_1 = ESPConstants.SecurityType.SECURITY_1.ordinal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认安全类型
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_SECURITY = SECURITY_1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接超时时间 (毫秒)
|
||||||
|
*/
|
||||||
|
public static final int CONNECTION_TIMEOUT = 30000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配网超时时间 (毫秒)
|
||||||
|
*/
|
||||||
|
public static final int PROVISION_TIMEOUT = 120000;
|
||||||
|
|
||||||
|
public static final int ERROR_NOT_INITIALIZED = 1000;
|
||||||
|
|
||||||
|
public static final int ERROR_INVALID_DEVICE = 1001;
|
||||||
|
|
||||||
|
public static final int ERROR_CONNECT_TIMEOUT = 1002;
|
||||||
|
|
||||||
|
public static final int ERROR_CONNECT_FAILED = 1003;
|
||||||
|
|
||||||
|
public static final int ERROR_NOT_CONNECTED = 1004;
|
||||||
|
|
||||||
|
public static final int ERROR_SESSION_FAILED = 1005;
|
||||||
|
|
||||||
|
public static final int ERROR_WIFI_CONFIG_FAILED = 1006;
|
||||||
|
|
||||||
|
public static final int ERROR_WIFI_APPLY_FAILED = 1007;
|
||||||
|
|
||||||
|
public static final int ERROR_PROVISION_FAILED = 1008;
|
||||||
|
|
||||||
|
public static final int ERROR_PROVISION_TIMEOUT = 1009;
|
||||||
|
|
||||||
|
public static final int ERROR_WIFI_SCAN_FAILED = 1010;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配网版本 (可根据实际固件调整)
|
||||||
|
*/
|
||||||
|
public static final String VERSION = "v1.1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成蓝牙扫描过滤器
|
||||||
|
* @return 服务UUID数组
|
||||||
|
*/
|
||||||
|
public static String[] getScanServiceUuids() {
|
||||||
|
return new String[]{SERVICE_UUID};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成设备前缀过滤器 (用于过滤非ESP设备)
|
||||||
|
* @return 设备前缀
|
||||||
|
*/
|
||||||
|
public static String getDevicePrefix() {
|
||||||
|
return DEVICE_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前Android版本号
|
||||||
|
* @return Android版本号
|
||||||
|
*/
|
||||||
|
public static int getAndroidVersion() {
|
||||||
|
return Build.VERSION.SDK_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否为Android 10及以上版本
|
||||||
|
* @return true 表示支持
|
||||||
|
*/
|
||||||
|
public static boolean isAndroid10OrAbove() {
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -133,8 +133,7 @@ public class WaterDeviceManager extends BleManager {
|
|||||||
? notifyCharacteristic.getUuid()
|
? notifyCharacteristic.getUuid()
|
||||||
: "null"));
|
: "null"));
|
||||||
|
|
||||||
return writeCharacteristic != null
|
return writeCharacteristic != null;
|
||||||
&& notifyCharacteristic != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user