package com.jsbogang.womp.ble; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.util.Log; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.inuker.bluetooth.library.Code; import com.inuker.bluetooth.library.Constants; import com.inuker.bluetooth.library.search.SearchResult; import com.inuker.bluetooth.library.search.response.SearchResponse; import com.veepoo.protocol.VPOperateManager; import com.veepoo.protocol.listener.base.IABleConnectStatusListener; import com.veepoo.protocol.listener.base.IBleWriteResponse; import com.veepoo.protocol.listener.data.ICustomSettingDataListener; import com.veepoo.protocol.listener.data.IDeviceFuctionDataListener; import com.veepoo.protocol.listener.data.IPersonInfoDataListener; import com.veepoo.protocol.listener.data.IPwdDataListener; import com.veepoo.protocol.listener.data.ISocialMsgDataListener; import com.veepoo.protocol.model.datas.DeviceFunctionPackage1; import com.veepoo.protocol.model.datas.DeviceFunctionPackage2; import com.veepoo.protocol.model.datas.DeviceFunctionPackage3; import com.veepoo.protocol.model.datas.DeviceFunctionPackage4; import com.veepoo.protocol.model.datas.DeviceFunctionPackage5; import com.veepoo.protocol.model.datas.FunctionDeviceSupportData; import com.veepoo.protocol.model.datas.FunctionSocailMsgData; import com.veepoo.protocol.model.datas.PersonInfoData; import com.veepoo.protocol.model.datas.PwdData; import com.veepoo.protocol.model.enums.EOprateStauts; import com.veepoo.protocol.model.enums.ESex; import com.veepoo.protocol.model.settings.CustomSettingData; public final class VeepooBleManager { public static final String ACTION_SCAN = "com.jsbogang.womp.ACTION_SCAN"; public static final String ACTION_CONN = "com.jsbogang.womp.ACTION_CONN"; public static final String EXTRA_MAC = "mac"; public static final String EXTRA_NAME = "name"; public static final String EXTRA_RSSI = "rssi"; public static final String EXTRA_CONNECTED = "connected"; public static final String EXTRA_READY = "ready"; public static final String EXTRA_MSG = "msg"; private static final String TAG = "VeepooBle"; private static final VeepooBleManager INSTANCE = new VeepooBleManager(); private Context app; private final Handler handler = new Handler(Looper.getMainLooper()); private volatile boolean connected; private volatile boolean ready; private volatile boolean connecting; private volatile boolean scanning; private String connectingMac = ""; private String connectingName = ""; private String connectingPwd = "0000"; private boolean allowReconnect = true; private VeepooBleManager() {} public static VeepooBleManager get() { return INSTANCE; } public synchronized void init(Context context) { if (app != null || context == null) { return; } app = context.getApplicationContext(); VPOperateManager.getInstance().init(app); VPOperateManager.getInstance().setAutoConnectBTBySdk(false); VPOperateManager.getInstance().setDeviceShowConfirm(false); if (DevicePrefs.isBound(app)) { handler.postDelayed(this::connectBound, 1500); } } public boolean isConnected() { return connected; } public boolean isReady() { return ready; } public boolean isScanning() { return scanning; } public void startScan() { if (scanning) { return; } scanning = true; VPOperateManager.getInstance().startScanDevice(12, new SearchResponse() { @Override public void onSearchStarted() { } @Override public void onDeviceFounded(SearchResult device) { if (device == null || device.getAddress() == null) { return; } Intent i = new Intent(ACTION_SCAN); i.putExtra(EXTRA_MAC, device.getAddress()); i.putExtra(EXTRA_NAME, device.getName() == null ? "" : device.getName()); i.putExtra(EXTRA_RSSI, device.rssi); LocalBroadcastManager.getInstance(app).sendBroadcast(i); } @Override public void onSearchStopped() { scanning = false; } @Override public void onSearchCanceled() { scanning = false; } }); } public void stopScan() { try { VPOperateManager.getInstance().stopScanDevice(); } catch (Exception ignored) { } scanning = false; } public void connect(String mac, String name, String password) { if (mac == null || mac.isEmpty()) { return; } connecting = true; ready = false; connectingMac = mac; connectingName = name == null ? "" : name; connectingPwd = (password == null || password.isEmpty()) ? "0000" : password; stopScan(); VPOperateManager.getInstance().registerConnectStatusListener(mac, statusListener); VPOperateManager.getInstance().connectDevice(mac, connectingName, (code, profile, isoadModel) -> { if (code == Code.REQUEST_SUCCESS) { connected = true; broadcastConn("已连接,正在校验密码…"); } else { connecting = false; connected = false; ready = false; broadcastConn("连接失败"); scheduleReconnect(); } }, state -> { if (state == Code.REQUEST_SUCCESS) { confirmPwd(); } else { connecting = false; ready = false; broadcastConn("通知开启失败"); scheduleReconnect(); } }); } public void connectBound() { if (app == null || !DevicePrefs.isBound(app) || connecting || ready) { return; } connect(DevicePrefs.getMac(app), DevicePrefs.getName(app), DevicePrefs.getPassword(app)); } public void disconnect() { allowReconnect = false; connecting = false; ready = false; try { VPOperateManager.getInstance().disconnectWatch(code -> {}); } catch (Exception ignored) { } connected = false; broadcastConn("已断开"); handler.postDelayed(() -> allowReconnect = true, 2000); } public void unbind() { allowReconnect = false; disconnect(); DevicePrefs.unbind(app); handler.postDelayed(() -> allowReconnect = true, 2000); } private void confirmPwd() { IBleWriteResponse wr = code -> {}; VPOperateManager.getInstance().confirmDevicePwd(wr, new IPwdDataListener() { @Override public void onPwdDataChange(PwdData pwdData) { Log.i(TAG, "pwd: " + pwdData); } @Override public void onConnectionConfirmTimeout() { connecting = false; broadcastConn("连接确认超时"); } }, new IDeviceFuctionDataListener() { @Override public void onFunctionSupportDataChange(FunctionDeviceSupportData functionSupport) { int days = 3; try { days = functionSupport.getWathcDay(); } catch (Exception ignored) { } if (days <= 0) { days = 3; } DevicePrefs.bind(app, connectingMac, connectingName, connectingPwd, days); } @Override public void onDeviceFunctionPackage1Report(DeviceFunctionPackage1 functionPackage1) { } @Override public void onDeviceFunctionPackage2Report(DeviceFunctionPackage2 functionPackage2) { } @Override public void onDeviceFunctionPackage3Report(DeviceFunctionPackage3 functionPackage3) { } @Override public void onDeviceFunctionPackage4Report(DeviceFunctionPackage4 functionPackage4) { } @Override public void onDeviceFunctionPackage5Report(DeviceFunctionPackage5 functionPackage5) { } }, new ISocialMsgDataListener() { @Override public void onSocialMsgSupportDataChange(FunctionSocailMsgData socailMsgData) { } @Override public void onSocialMsgSupportDataChange2(FunctionSocailMsgData socailMsgData) { } }, new ICustomSettingDataListener() { @Override public void OnSettingDataChange(CustomSettingData customSettingData) { connecting = false; ready = true; connected = true; DevicePrefs.bind(app, connectingMac, connectingName, connectingPwd, DevicePrefs.getWatchDay(app)); syncPerson(); AlarmPrefs.writeToWatch(app); broadcastConn("已就绪,正在首次同步,之后每5分钟自动拉取"); com.jsbogang.womp.health.HealthSyncer.get().syncAll(); } }, connectingPwd, true); } private void syncPerson() { try { VPOperateManager.getInstance().syncPersonInfo(code -> {}, new IPersonInfoDataListener() { @Override public void OnPersoninfoDataChange(EOprateStauts eOprateStauts) { } }, new PersonInfoData(ESex.MAN, 170, 65, 30, 8000)); } catch (Exception ignored) { } } private final IABleConnectStatusListener statusListener = new IABleConnectStatusListener() { @Override public void onConnectStatusChanged(String mac, int status) { if (status == Constants.STATUS_CONNECTED) { connected = true; } else if (status == Constants.STATUS_DISCONNECTED) { connected = false; ready = false; connecting = false; broadcastConn("已断开"); scheduleReconnect(); } } }; private void scheduleReconnect() { if (!allowReconnect || app == null || !DevicePrefs.isBound(app)) { return; } handler.removeCallbacks(reconnectTask); handler.postDelayed(reconnectTask, 8000); } private final Runnable reconnectTask = this::connectBound; private void broadcastConn(String msg) { Intent i = new Intent(ACTION_CONN); i.putExtra(EXTRA_CONNECTED, connected); i.putExtra(EXTRA_READY, ready); i.putExtra(EXTRA_MAC, DevicePrefs.getMac(app)); i.putExtra(EXTRA_NAME, DevicePrefs.getName(app)); i.putExtra(EXTRA_MSG, msg == null ? "" : msg); LocalBroadcastManager.getInstance(app).sendBroadcast(i); } }