From 558f29b84406b0d4b9493503f0ca02b35bfed9cf Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 26 Mar 2021 19:42:17 +0100 Subject: When adding a new device, try to reuse existing connection to avoid useless reconnection --- app/src/main/java/com/javispedro/rempe/Device.java | 69 +++++++++---- .../com/javispedro/rempe/DeviceViewHolder.java | 8 +- .../java/com/javispedro/rempe/MainActivity.java | 108 +++++++++++++++------ app/src/main/res/values/strings.xml | 4 +- 4 files changed, 137 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/com/javispedro/rempe/Device.java b/app/src/main/java/com/javispedro/rempe/Device.java index fed7291..9258393 100644 --- a/app/src/main/java/com/javispedro/rempe/Device.java +++ b/app/src/main/java/com/javispedro/rempe/Device.java @@ -1,5 +1,6 @@ package com.javispedro.rempe; +import android.app.Activity; import android.content.Context; import android.util.Log; @@ -17,7 +18,8 @@ import java.util.EnumSet; public class Device { private final static String TAG = "Device"; - private final int mDeviceNumber; + public static final int INVALID_DEVICE = -1; + private int mDeviceNumber; private PccReleaseHandle mEnvPccHandle; private AntPlusEnvironmentPcc mEnvPcc; @@ -30,6 +32,7 @@ public class Device { private DeviceState mCurState; public interface DeviceObserver { + void onDeviceSearchFinished(RequestAccessResult result); void onDeviceInfoChanged(); void onDeviceStateChanged(); void onDeviceNewReading(); @@ -37,23 +40,56 @@ public class Device { } private DeviceObserver mObserver; - public Device(int deviceNumber) { + /** Creates empty Device object not attached to a specific device number. + * Only valid operation is searchForDevice. + */ + public Device() { + mDeviceNumber = INVALID_DEVICE; + mDeviceName = null; + mConnectResult = RequestAccessResult.SUCCESS; + mCurState = DeviceState.DEAD; + } + + /** Creates Device object with deviceNumber. Initial state will be unconnected. + * Can use connect() afterwards. */ + public Device(int deviceNumber, String initialDeviceName) { mDeviceNumber = deviceNumber; - mDeviceName = "dev-" + deviceNumber; + mDeviceName = initialDeviceName; mConnectResult = RequestAccessResult.SUCCESS; mCurState = DeviceState.DEAD; } + public void searchForDevice(Activity parentActivity) { + Log.d(TAG, "searchForNewDevice"); + if (isOpen()) { + Log.e(TAG, "Already open"); + return; + } + + // Clear old state + mConnectResult = RequestAccessResult.BAD_PARAMS; + mCurState = DeviceState.DEAD; + if (mObserver != null) { + mObserver.onDeviceStateChanged(); + } + + mEnvPccHandle = AntPlusEnvironmentPcc.requestAccess(parentActivity, parentActivity, mResultReceiver, mDeviceStateChangeReceiver); + } + public void connect(Context context) { Log.d(TAG, "connect (" + mDeviceNumber + ")"); - if (mEnvPccHandle != null) { - Log.w(TAG, "Already connected"); + if (isOpen()) { + Log.e(TAG, "Already open"); + return; } - mConnectResult = RequestAccessResult.SUCCESS; // Clear old connect result + + // Clear old connect result / state + mConnectResult = RequestAccessResult.SUCCESS; mCurState = DeviceState.SEARCHING; if (mObserver != null) { mObserver.onDeviceStateChanged(); } + mEnvPccHandle = AntPlusEnvironmentPcc.requestAccess(context, mDeviceNumber, 0, mResultReceiver, mDeviceStateChangeReceiver); } @@ -90,17 +126,15 @@ public class Device { } private void setEnvPcc(AntPlusEnvironmentPcc envPcc) { - if (mEnvPcc != null) { - mEnvPcc.subscribeTemperatureDataEvent(null); - mEnvPcc.subscribeRssiEvent(null); - mEnvPcc.releaseAccess(); - mEnvPcc = null; - } + assert mEnvPcc == null; mEnvPcc = envPcc; final String deviceName = mEnvPcc.getDeviceName(); final int deviceNumber = mEnvPcc.getAntDeviceNumber(); Log.d(TAG, "handleConnection deviceName=" + deviceName + " deviceNumber=" + deviceNumber); - if (deviceNumber != mDeviceNumber) { + if (mDeviceNumber == INVALID_DEVICE) { + mDeviceNumber = deviceNumber; // This is the initial search + } else if (deviceNumber != mDeviceNumber) { + // We tried to reconnect to a device and now it has a different number? Log.e(TAG, "device number mismatch"); } mDeviceName = deviceName; @@ -141,15 +175,14 @@ public class Device { Log.d(TAG, "onResultReceived resultCode=" + resultCode + " initialDeviceState=" + initialDeviceState); mConnectResult = resultCode; mCurState = initialDeviceState; - if (resultCode.equals(RequestAccessResult.SUCCESS)) { + if (resultCode == RequestAccessResult.SUCCESS) { setEnvPcc(result); } if (mObserver != null) { - mObserver.onDeviceStateChanged(); + mObserver.onDeviceSearchFinished(resultCode); } - - if (resultCode.equals(RequestAccessResult.SEARCH_TIMEOUT)) { - Log.d(TAG, "timeout"); + if (mObserver != null) { + mObserver.onDeviceStateChanged(); } } }; diff --git a/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java b/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java index 6306a2b..2e2a441 100644 --- a/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java +++ b/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java @@ -83,8 +83,12 @@ public class DeviceViewHolder extends RecyclerView.ViewHolder implements Device. } private String formatTemperature(BigDecimal temp) { - final String value = temp.setScale(1, BigDecimal.ROUND_HALF_EVEN).toPlainString(); - return mContext.getString(R.string.temperature_celsius, value); + return mContext.getString(R.string.temperature_celsius, temp); + } + + @Override + public void onDeviceSearchFinished(RequestAccessResult result) { + // Nothing to do here } @Override diff --git a/app/src/main/java/com/javispedro/rempe/MainActivity.java b/app/src/main/java/com/javispedro/rempe/MainActivity.java index e4e6d6f..48fa5fd 100644 --- a/app/src/main/java/com/javispedro/rempe/MainActivity.java +++ b/app/src/main/java/com/javispedro/rempe/MainActivity.java @@ -18,11 +18,7 @@ import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import com.dsi.ant.plugins.antplus.pcc.AntPlusEnvironmentPcc; -import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState; import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult; -import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc; -import com.dsi.ant.plugins.antplus.pccbase.PccReleaseHandle; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; @@ -41,7 +37,7 @@ public class MainActivity extends AppCompatActivity { private SwipeRefreshLayout mSrlList; private RecyclerView mList; - private PccReleaseHandle mPccSearchHandle; + private Device mSearchDevice; @Override protected void onCreate(Bundle savedInstanceState) { @@ -152,46 +148,67 @@ public class MainActivity extends AppCompatActivity { } }; - public void searchForNewDevice() { - Log.d(TAG, "searchForNewDevice"); - if (mPccSearchHandle != null) { - mPccSearchHandle.close(); - mPccSearchHandle = null; - } - mPccSearchHandle = AntPlusEnvironmentPcc.requestAccess(this, this, mResultReceiver, mDeviceStateChangeReceiver); - } - - private final AntPluginPcc.IPluginAccessResultReceiver mResultReceiver = new AntPluginPcc.IPluginAccessResultReceiver() { + private final Device.DeviceObserver mSearchDeviceObserver = new Device.DeviceObserver() { @Override - public void onResultReceived(AntPlusEnvironmentPcc result, RequestAccessResult resultCode, DeviceState initialDeviceState) { - Log.d(TAG, "onResultReceived resultCode=" + resultCode); - if (resultCode == RequestAccessResult.SUCCESS) { - int deviceNumber = result.getAntDeviceNumber(); - result.releaseAccess(); - runOnUiThread(() -> addDevice(result.getAntDeviceNumber())); - } else if (resultCode != RequestAccessResult.USER_CANCELLED) { + public void onDeviceSearchFinished(RequestAccessResult result) { + Log.d(TAG, "onDeviceSearchFinished result=" + result); + if (result == RequestAccessResult.SUCCESS) { + final Device device = mSearchDevice; + mSearchDevice.setObserver(null); + mSearchDevice = null; // Ownership of mSearchDevice passed to addDevice below + runOnUiThread(() -> addDevice(device)); + } else if (result != RequestAccessResult.USER_CANCELLED) { runOnUiThread(() -> { - final String resultText = Device.connectionRequestAccessResultToString(MainActivity.this, resultCode); + final String resultText = Device.connectionRequestAccessResultToString(MainActivity.this, result); Snackbar.make(findViewById(R.id.fabAddDevice), getString(R.string.add_device_failed, resultText), Snackbar.LENGTH_INDEFINITE).show(); }); } - mPccSearchHandle.close(); - mPccSearchHandle = null; + if (mSearchDevice != null) { + mSearchDevice.close(); + mSearchDevice = null; + } + } + + @Override + public void onDeviceInfoChanged() { + } - }; - private final AntPluginPcc.IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new AntPluginPcc.IDeviceStateChangeReceiver() { @Override - public void onDeviceStateChange(DeviceState newDeviceState) { - Log.d(TAG, "onDeviceStateChange newDeviceState=" + newDeviceState); + public void onDeviceStateChanged() { + + } + + @Override + public void onDeviceNewReading() { + + } + + @Override + public void onDeviceRssiChanged() { + } }; + public void searchForNewDevice() { + if (mSearchDevice != null) { + mSearchDevice.close(); + } + mSearchDevice = new Device(); + mSearchDevice.setObserver(mSearchDeviceObserver); + mSearchDevice.searchForDevice(this); + } + public void addDevice(int deviceNumber) { - Log.d(TAG, "addDevice " + deviceNumber); + Log.d(TAG, "addDevice deviceNumber=" + deviceNumber); + if (deviceNumber == Device.INVALID_DEVICE) { + Log.e(TAG, "trying to add invalid device number; ignoring"); + return; + } List list = Preferences.getDeviceNumbers(mPrefs); if (list.contains(deviceNumber)) { + Log.w(TAG, "device already on list!"); Snackbar.make(findViewById(R.id.fabAddDevice), getString(R.string.add_device_already), Snackbar.LENGTH_INDEFINITE).show(); return; @@ -200,6 +217,33 @@ public class MainActivity extends AppCompatActivity { Preferences.saveDeviceNumbers(mPrefs, list); } + public void addDevice(Device device) { + final int deviceNumber = device.getDeviceNumber(); + Log.d(TAG, "addDevice device.getDeviceNumber=" + deviceNumber); + if (deviceNumber == Device.INVALID_DEVICE) { + Log.e(TAG, "trying to add invalid device number; ignoring"); + return; + } + if (mDeviceNumbers.contains(deviceNumber)) { + Log.w(TAG, "device already on list!"); + Snackbar.make(findViewById(R.id.fabAddDevice), + getString(R.string.add_device_already), Snackbar.LENGTH_INDEFINITE).show(); + device.close(); + return; + } + + mDevices.add(device); + mDeviceNumbers.add(deviceNumber); + + if (mDeviceListAdapter != null) { + mDeviceListAdapter.notifyItemInserted(mDevices.size() - 1); + } + + // Since we have manipulated mDeviceNumbers directly, even if we change the Prefs now + // Prefs listener should end up doing nothing + Preferences.saveDeviceNumbers(mPrefs, mDeviceNumbers); + } + public void removeDeviceByPosition(int position) { Log.d(TAG, "removeDeviceByPosition position=" + position); List list = Preferences.getDeviceNumbers(mPrefs); @@ -212,6 +256,7 @@ public class MainActivity extends AppCompatActivity { Snackbar.make(mList, getString(R.string.remove_device_done), Snackbar.LENGTH_SHORT).show(); + // Prefs listener will take care of removing the device from mDevices Preferences.saveDeviceNumbers(mPrefs, list); } @@ -265,7 +310,8 @@ public class MainActivity extends AppCompatActivity { public void onInserted(int position, int count) { for (int i = 0; i < count; ++i) { final int deviceNumber = newDeviceNumbers.get(position + i); - Device device = new Device(deviceNumber); + final String deviceName = getString(R.string.device_unnamed, deviceNumber); + Device device = new Device(deviceNumber, deviceName); mDeviceNumbers.add(position + i, deviceNumber); mDevices.add(position + i, device); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c6832b0..c90f66a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,8 +10,10 @@ Device Status + dev#%d + - %1$s °C + %.1f °C Last 24h: -- cgit v1.2.3