From b924519dd245e2171f006ed68c0f934cffe7aeb9 Mon Sep 17 00:00:00 2001 From: Graham Jones Date: Sun, 16 Aug 2020 22:28:12 +0100 Subject: [PATCH] Added some automatic reconnection code for BLE data source. Still not as reliable as I would like though. --- .../org/openseizuredetector/SdDataSource.java | 2 +- .../openseizuredetector/SdDataSourceBLE.java | 64 +++++++++++++------ .../uk/org/openseizuredetector/SdServer.java | 42 +++++++----- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java index 7ea3569..e8501e8 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java @@ -53,7 +53,7 @@ interface SdDataReceiver { * network data source. */ public abstract class SdDataSource { - private Handler mHandler = new Handler(); + protected Handler mHandler = new Handler(); private Timer mStatusTimer; private Timer mSettingsTimer; private Timer mFaultCheckTimer; diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceBLE.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceBLE.java index 6213f2a..9ae0f57 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceBLE.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceBLE.java @@ -126,34 +126,41 @@ public class SdDataSourceBLE extends SdDataSource { } private void bleConnect() { - // Now we have selected a BLE Device, open the bluetooth adapter and connect to it. + mSdData.watchConnected = false; + mSdData.watchAppRunning = false; + mBluetoothGatt = null; + mConnectionState = STATE_DISCONNECTED; if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { - Log.e(TAG, "Unable to initialize BluetoothManager."); + Log.e(TAG, "bleConnect(): Unable to initialize BluetoothManager."); + return; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { - Log.e(TAG, "Unable to obtain a BluetoothAdapter."); + Log.e(TAG, "bleConnect(): Unable to obtain a BluetoothAdapter."); + return; } if (mBluetoothAdapter == null || mBleDeviceAddr == null) { - Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); + Log.w(TAG, "bleConnect(): BluetoothAdapter not initialized or unspecified address."); + return; } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mBleDeviceAddr); if (device == null) { - Log.w(TAG, "Device not found. Unable to connect."); + Log.w(TAG, "bleConnect(): Device not found. Unable to connect."); + return; + } else { + // We want to directly connect to the device, so we are setting the autoConnect + // parameter to false. + mBluetoothGatt = device.connectGatt(mContext, true, mGattCallback); + Log.d(TAG, "bleConnect(): Trying to create a new connection."); + mBluetoothDeviceAddress = mBleDeviceAddr; + mConnectionState = STATE_CONNECTING; } - // We want to directly connect to the device, so we are setting the autoConnect - // parameter to false. - mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback); - Log.d(TAG, "Trying to create a new connection."); - mBluetoothDeviceAddress = mBleDeviceAddr; - mConnectionState = STATE_CONNECTING; - } private void bleDisconnect() { @@ -167,6 +174,9 @@ public class SdDataSourceBLE extends SdDataSource { } mBluetoothGatt.close(); mBluetoothGatt = null; + mSdData.watchAppRunning = false; + mSdData.watchConnected = false; + mConnectionState = STATE_DISCONNECTED; } @@ -190,21 +200,27 @@ public class SdDataSourceBLE extends SdDataSource { if (newState == BluetoothProfile.STATE_CONNECTED) { mConnectionState = STATE_CONNECTED; mSdData.watchConnected = true; - Log.i(TAG, "Connected to GATT server."); + Log.i(TAG, "onConnectionStateChange(): Connected to GATT server."); // Attempts to discover services after successful connection. - Log.i(TAG, "Attempting to start service discovery:"); + Log.i(TAG, "onConnectionStateChange(): Attempting to start service discovery:"); mBluetoothGatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mConnectionState = STATE_DISCONNECTED; mSdData.watchConnected = false; - Log.i(TAG, "Disconnected from GATT server - retrying..."); - bleDisconnect(); // Tidy up connections - bleConnect(); + Log.i(TAG, "onConnectionStateChange(): Disconnected from GATT server - reconnecting after delay..."); + //bleDisconnect(); // Tidy up connections + // Wait 2 seconds to give the server chance to shutdown, then re-start it + mHandler.postDelayed(new Runnable() { + public void run() { + bleConnect(); + } + }, 2000); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { + boolean foundOsdService = false; if (status == BluetoothGatt.GATT_SUCCESS) { Log.v(TAG, "Services discovered"); List serviceList = mBluetoothGatt.getServices(); @@ -226,6 +242,7 @@ public class SdDataSourceBLE extends SdDataSource { } } else if (uuidStr.equals(SERV_OSD)) { Log.v(TAG, "OpenSeizureDetector Service Discovered"); + foundOsdService = true; for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { String charUuidStr = gattCharacteristic.getUuid().toString(); if (charUuidStr.equals(CHAR_OSD_ACC_DATA)) { @@ -239,7 +256,18 @@ public class SdDataSourceBLE extends SdDataSource { } } } - mGatt = gatt; + if (foundOsdService) { + mGatt = gatt; + } else { + Log.v(TAG, "device is not offering the OSD Gatt Service - re-trying connection"); + bleDisconnect(); + // Wait 1 second to give the server chance to shutdown, then re-start it + mHandler.postDelayed(new Runnable() { + public void run() { + bleConnect(); + } + }, 1000); + } } else { Log.w(TAG, "onServicesDiscovered received: " + status); } diff --git a/app/src/main/java/uk/org/openseizuredetector/SdServer.java b/app/src/main/java/uk/org/openseizuredetector/SdServer.java index 03a2f16..c6f13dd 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdServer.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdServer.java @@ -677,10 +677,24 @@ public class SdServer extends Service implements SdDataReceiver { mSdData.alarmPhrase = "FAULT"; mSdData.alarmStanding = false; if (webServer != null) webServer.setSdData(mSdData); - if (mAudibleFaultWarning) { + // We only take action to warn the user and re-start the data source to attempt to fix it + // ourselves if we have been in a fault condition for a while - signified by the mFaultTimerCompleted + // flag. + if (mFaultTimerCompleted) { faultWarningBeep(); + //mSdDataSource.stop(); + //mHandler.postDelayed(new Runnable() { + // public void run() { + // mSdDataSource.start(); + // } + //}, 190); + } else { + startFaultTimer(); + Log.v(TAG, "onSdDataFault() - starting Fault Timer"); + mUtil.writeToSysLogFile("onSdDataFault() - starting Fault Timer"); } - showNotification(-1); + + showNotification(-1); } /* from http://stackoverflow.com/questions/12154940/how-to-make-a-beep-in-android */ @@ -703,26 +717,20 @@ public class SdServer extends Service implements SdDataReceiver { * beep, provided mAudibleAlarm is set */ public void faultWarningBeep() { - if (mFaultTimerCompleted) { - if (mCancelAudible) { + if (mCancelAudible) { Log.v(TAG, "faultWarningBeep() - CancelAudible Active - silent beep..."); } else { - if (mAudibleFaultWarning) { - if (mMp3Alarm) { - Log.v(TAG, "Not making MP3 fault beep - handled by notification"); - } else { - beep(10); - } - Log.v(TAG, "faultWarningBeep()"); - mUtil.writeToSysLogFile("SdServer.faultWarningBeep() - beeping"); + if (mAudibleFaultWarning) { + if (mMp3Alarm) { + Log.v(TAG, "Not making MP3 fault beep - handled by notification"); } else { - Log.v(TAG, "faultWarningBeep() - silent..."); + beep(10); } + Log.v(TAG, "faultWarningBeep()"); + mUtil.writeToSysLogFile("SdServer.faultWarningBeep() - beeping"); + } else { + Log.v(TAG, "faultWarningBeep() - silent..."); } - } else { - startFaultTimer(); - Log.v(TAG, "faultWarningBeep() - starting Fault Timer"); - mUtil.writeToSysLogFile("faultWarningBeep() - starting Fault Timer"); } }