diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ble/BlePreCheck.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ble/BlePreCheck.kt
new file mode 100644
index 0000000000..2d623902bb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ble/BlePreCheck.kt
@@ -0,0 +1,88 @@
+package info.nightscout.androidaps.plugins.pump.common.ble
+
+import android.Manifest
+import android.bluetooth.BluetoothAdapter
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.location.LocationManager
+import android.provider.Settings
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.utils.OKDialog
+import info.nightscout.androidaps.utils.OKDialog.showConfirmation
+import info.nightscout.androidaps.utils.resources.ResourceHelper
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class BlePreCheck @Inject constructor(
+ val resourceHelper: ResourceHelper
+) {
+
+ companion object {
+ private const val PERMISSION_REQUEST_COARSE_LOCATION = 30241 // arbitrary.
+ }
+
+ fun prerequisitesCheck(activity: AppCompatActivity): Boolean {
+ if (!activity.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+ OKDialog.show(activity, resourceHelper.gs(R.string.app_name), resourceHelper.gs(R.string.rileylink_scanner_ble_not_supported))
+ return false
+ } else {
+ // Use this check to determine whether BLE is supported on the device. Then
+ // you can selectively disable BLE-related features.
+ if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ // your code that requires permission
+ ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), PERMISSION_REQUEST_COARSE_LOCATION)
+ }
+
+ val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
+ // Ensures Bluetooth is available on the device and it is enabled. If not,
+ // displays a dialog requesting user permission to enable Bluetooth.
+ if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled) {
+ OKDialog.show(activity, resourceHelper.gs(R.string.app_name), resourceHelper.gs(R.string.rileylink_scanner_ble_not_enabled))
+ return false
+ } else {
+ // Will request that GPS be enabled for devices running Marshmallow or newer.
+ if (!isLocationEnabled(activity)) {
+ requestLocation(activity)
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ /**
+ * Determine if GPS is currently enabled.
+ *
+ *
+ * On Android 6 (Marshmallow), location needs to be enabled for Bluetooth discovery to work.
+ *
+ * @param context The current app context.
+ * @return true if location is enabled, false otherwise.
+ */
+ private fun isLocationEnabled(context: Context): Boolean {
+ val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
+ return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
+ locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
+ }
+
+ /**
+ * Prompt the user to enable GPS location if it isn't already on.
+ *
+ * @param activity The currently visible activity.
+ */
+ private fun requestLocation(activity: AppCompatActivity) {
+ if (isLocationEnabled(activity)) {
+ return
+ }
+
+ // Shamelessly borrowed from http://stackoverflow.com/a/10311877/868533
+ showConfirmation(activity, resourceHelper.gs(R.string.location_not_found_title), resourceHelper.gs(R.string.location_not_found_message), Runnable {
+ activity.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java
index e292808ded..7695344183 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java
@@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.pump.common.dialog;
-import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
@@ -10,7 +9,6 @@ import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
@@ -26,13 +24,12 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -43,10 +40,10 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
+import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes;
-import info.nightscout.androidaps.plugins.pump.common.utils.LocationHelper;
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
@@ -60,9 +57,7 @@ public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity {
@Inject SP sp;
@Inject RxBusWrapper rxBus;
@Inject ResourceHelper resourceHelper;
-
- private static final int PERMISSION_REQUEST_COARSE_LOCATION = 30241; // arbitrary.
- private static final int REQUEST_ENABLE_BT = 30242; // arbitrary
+ @Inject BlePreCheck blePrecheck;
private static String TAG = "RileyLinkBLEScanActivity";
@@ -156,36 +151,13 @@ public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity {
public void prepareForScanning() {
- // https://developer.android.com/training/permissions/requesting.html
- // http://developer.radiusnetworks.com/2015/09/29/is-your-beacon-app-ready-for-android-6.html
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- Toast.makeText(this, R.string.rileylink_scanner_ble_not_supported, Toast.LENGTH_SHORT).show();
- } else {
- // Use this check to determine whether BLE is supported on the device. Then
- // you can selectively disable BLE-related features.
- if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
- // your code that requires permission
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
- PERMISSION_REQUEST_COARSE_LOCATION);
- }
+ boolean checkOK = blePrecheck.prerequisitesCheck(this);
- // Ensures Bluetooth is available on the device and it is enabled. If not,
- // displays a dialog requesting user permission to enable Bluetooth.
- if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
- Toast.makeText(this, R.string.rileylink_scanner_ble_not_enabled, Toast.LENGTH_SHORT).show();
- } else {
-
- // Will request that GPS be enabled for devices running Marshmallow or newer.
- if (!LocationHelper.isLocationEnabled(this)) {
- LocationHelper.requestLocationForBluetooth(this);
- }
-
- mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
- settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
- filters = Arrays.asList(new ScanFilter.Builder().setServiceUuid(
- ParcelUuid.fromString(GattAttributes.SERVICE_RADIO)).build());
-
- }
+ if (checkOK) {
+ mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+ filters = Collections.singletonList(new ScanFilter.Builder().setServiceUuid(
+ ParcelUuid.fromString(GattAttributes.SERVICE_RADIO)).build());
}
// disable currently selected RL, so that we can discover it
@@ -193,19 +165,6 @@ public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity {
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_ENABLE_BT) {
- if (resultCode == RESULT_OK) {
- // User allowed Bluetooth to turn on
- } else if (resultCode == RESULT_CANCELED) {
- // Error, or user said "NO"
- finish();
- }
- }
- }
-
private ScanCallback mScanCallback2 = new ScanCallback() {
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java
deleted file mode 100644
index 065f0ec4d6..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package info.nightscout.androidaps.plugins.pump.common.utils;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.location.LocationManager;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.utils.OKDialog;
-
-/**
- * Helper for checking if location services are enabled on the device.
- */
-public class LocationHelper {
-
- /**
- * Determine if GPS is currently enabled.
- *
- * On Android 6 (Marshmallow), location needs to be enabled for Bluetooth discovery to work.
- *
- * @param context The current app context.
- * @return true if location is enabled, false otherwise.
- */
- public static boolean isLocationEnabled(Context context) {
- LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
-
- return (locationManager != null && //
- (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || //
- locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)));
-
- // return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
- }
-
-
- /**
- * Prompt the user to enable GPS location if it isn't already on.
- *
- * @param parent The currently visible activity.
- */
- public static void requestLocation(final Activity parent) {
- if (LocationHelper.isLocationEnabled(parent)) {
- return;
- }
-
- // Shamelessly borrowed from http://stackoverflow.com/a/10311877/868533
- OKDialog.showConfirmation(parent, MainApp.gs(R.string.location_not_found_title), MainApp.gs(R.string.location_not_found_message), () -> {
- parent.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
- });
- }
-
-
- /**
- * Prompt the user to enable GPS location on devices that need it for Bluetooth discovery.
- *
- * Android 6 (Marshmallow) needs GPS enabled for Bluetooth discovery to work.
- *
- * @param activity The currently visible activity.
- */
- public static void requestLocationForBluetooth(Activity activity) {
- // Location needs to be enabled for Bluetooth discovery on Marshmallow.
- LocationHelper.requestLocation(activity);
- }
-
- // public static Boolean locationPermission(ActivityWithMenu act) {
- // return ActivityCompat.checkSelfPermission(act, Manifest.permission.ACCESS_FINE_LOCATION) ==
- // PackageManager.PERMISSION_GRANTED;
- // }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java
index b9d4af7497..3e865cb0e4 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java
@@ -61,6 +61,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.T;
+import info.nightscout.androidaps.utils.ToastUtils;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
@@ -77,16 +78,16 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
private final TreatmentsPlugin treatmentsPlugin;
private final SP sp;
private final RxBusWrapper rxBus;
- private final CommandQueueProvider commandQueue;
private final DanaRPump danaRPump;
private final DetailedBolusInfoStorage detailedBolusInfoStorage;
+ private final FabricPrivacy fabricPrivacy;
- private static DanaRSService danaRSService;
+ private DanaRSService danaRSService;
- private static String mDeviceAddress = "";
- public static String mDeviceName = "";
+ private String mDeviceAddress = "";
+ public String mDeviceName = "";
- public static PumpDescription pumpDescription = new PumpDescription();
+ public PumpDescription pumpDescription = new PumpDescription();
// Bolus & history handling
public int bolusStartErrorCode; // from start message
@@ -112,7 +113,8 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
SP sp,
CommandQueueProvider commandQueue,
DanaRPump danaRPump,
- DetailedBolusInfoStorage detailedBolusInfoStorage
+ DetailedBolusInfoStorage detailedBolusInfoStorage,
+ FabricPrivacy fabricPrivacy
) {
super(new PluginDescription()
.mainType(PluginType.PUMP)
@@ -130,9 +132,9 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
this.profileFunction = profileFunction;
this.treatmentsPlugin = treatmentsPlugin;
this.sp = sp;
- this.commandQueue = commandQueue;
this.danaRPump = danaRPump;
this.detailedBolusInfoStorage = detailedBolusInfoStorage;
+ this.fabricPrivacy = fabricPrivacy;
pumpDescription.setPumpDescription(PumpType.DanaRS);
}
@@ -153,12 +155,12 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
- .subscribe(event -> context.unbindService(mConnection), exception -> FabricPrivacy.getInstance().logException(exception))
+ .subscribe(event -> context.unbindService(mConnection), fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange.class)
.observeOn(Schedulers.io())
- .subscribe(event -> loadAddress(), exception -> FabricPrivacy.getInstance().logException(exception))
+ .subscribe(event -> loadAddress(), fabricPrivacy::logException)
);
loadAddress(); // load device name
super.onStart();
@@ -195,7 +197,9 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
public void connect(String from) {
getAapsLogger().debug(LTag.PUMP, "RS connect from: " + from);
if (danaRSService != null && !mDeviceAddress.equals("") && !mDeviceName.equals("")) {
- danaRSService.connect(from, mDeviceAddress);
+ boolean success = danaRSService.connect(from, mDeviceAddress);
+ if (!success)
+ ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.rileylink_scanner_ble_not_supported));
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java
deleted file mode 100644
index 89f794259e..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java
+++ /dev/null
@@ -1,217 +0,0 @@
-package info.nightscout.androidaps.plugins.pump.danaRS.activities;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanResult;
-import android.content.pm.ActivityInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
-import info.nightscout.androidaps.plugins.bus.RxBus;
-import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange;
-import info.nightscout.androidaps.utils.SP;
-
-public class BLEScanActivity extends NoSplashAppCompatActivity {
- private ListAdapter mListAdapter = null;
- private ArrayList mDevices = new ArrayList<>();
-
- private BluetoothLeScanner mBluetoothLeScanner = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.danars_blescanner_activity);
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-
- mListAdapter = new ListAdapter();
-
- ListView listView = findViewById(R.id.danars_blescanner_listview);
- listView.setEmptyView(findViewById(R.id.danars_blescanner_nodevice));
- listView.setAdapter(mListAdapter);
-
- mListAdapter.notifyDataSetChanged();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBluetoothAdapter != null) {
- if (!mBluetoothAdapter.isEnabled()) mBluetoothAdapter.enable();
- mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
-
- if (mBluetoothLeScanner == null) {
- mBluetoothAdapter.enable();
- mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
- }
- startScan();
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- stopScan();
- }
-
- private void startScan() {
- if (mBluetoothLeScanner != null)
- mBluetoothLeScanner.startScan(mBleScanCallback);
- }
-
- private void stopScan() {
- if (mBluetoothLeScanner != null)
- mBluetoothLeScanner.stopScan(mBleScanCallback);
- }
-
- private void addBleDevice(BluetoothDevice device) {
- if (device == null || device.getName() == null || device.getName().equals("")) {
- return;
- }
- BluetoothDeviceItem item = new BluetoothDeviceItem(device);
- if (!isSNCheck(device.getName()) || mDevices.contains(item)) {
- return;
- }
-
- mDevices.add(item);
- new Handler().post(() -> mListAdapter.notifyDataSetChanged());
- }
-
- private ScanCallback mBleScanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- addBleDevice(result.getDevice());
- }
- };
-
- class ListAdapter extends BaseAdapter {
-
- @Override
- public int getCount() {
- return mDevices.size();
- }
-
- @Override
- public BluetoothDeviceItem getItem(int i) {
- return mDevices.get(i);
- }
-
- @Override
- public long getItemId(int i) {
- return 0;
- }
-
- @Override
- public View getView(int i, View convertView, ViewGroup parent) {
- View v = convertView;
- ViewHolder holder;
-
- if (v == null) {
- v = View.inflate(getApplicationContext(), R.layout.danars_blescanner_item, null);
- holder = new ViewHolder(v);
- v.setTag(holder);
- } else {
- holder = (ViewHolder) v.getTag();
- }
-
- BluetoothDeviceItem item = getItem(i);
- holder.setData(item);
- return v;
- }
-
- private class ViewHolder implements View.OnClickListener {
- private BluetoothDeviceItem item = null;
-
- private TextView mName;
- private TextView mAddress;
-
- ViewHolder(View v) {
- mName = v.findViewById(R.id.ble_name);
- mAddress = v.findViewById(R.id.ble_address);
-
- v.setOnClickListener(ViewHolder.this);
- }
-
- @Override
- public void onClick(View v) {
- SP.putString(R.string.key_danars_address, item.device.getAddress());
- SP.putString(R.string.key_danars_name, mName.getText().toString());
- item.device.createBond();
- RxBus.Companion.getINSTANCE().send(new EventDanaRSDeviceChange());
- finish();
- }
-
- public void setData(BluetoothDeviceItem data) {
- if (data != null) {
- try {
- String tTitle = data.device.getName();
- if (tTitle == null || tTitle.equals("")) {
- tTitle = "(unknown)";
- } else if (tTitle.length() > 10) {
- tTitle = tTitle.substring(0, 10);
- }
- mName.setText(tTitle);
-
- mAddress.setText(data.device.getAddress());
-
- item = data;
- } catch (Exception ignored) {
- }
- }
- }
- }
- }
-
- //
- private class BluetoothDeviceItem {
- private BluetoothDevice device;
-
- BluetoothDeviceItem(BluetoothDevice device) {
- super();
- this.device = device;
- }
-
- @Override
- public boolean equals(Object o) {
- if (device == null || !(o instanceof BluetoothDeviceItem)) {
- return false;
- }
- BluetoothDeviceItem checkItem = (BluetoothDeviceItem) o;
- if (checkItem.device == null) {
- return false;
- }
- return stringEquals(device.getAddress(), checkItem.device.getAddress());
- }
-
- boolean stringEquals(String arg1, String arg2) {
- try {
- return arg1.equals(arg2);
- } catch (Exception e) {
- return false;
- }
- }
- }
-
- public static boolean isSNCheck(String sn) {
- String regex = "^([a-zA-Z]{3})([0-9]{5})([a-zA-Z]{2})$";
- Pattern p = Pattern.compile(regex);
- Matcher m = p.matcher(sn);
-
- return m.matches();
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.kt
new file mode 100644
index 0000000000..d51dc5ab05
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.kt
@@ -0,0 +1,172 @@
+package info.nightscout.androidaps.plugins.pump.danaRS.activities
+
+import android.annotation.SuppressLint
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanResult
+import android.content.pm.ActivityInfo
+import android.os.Bundle
+import android.os.Handler
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import info.nightscout.androidaps.R
+import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
+import info.nightscout.androidaps.plugins.bus.RxBusWrapper
+import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck
+import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange
+import info.nightscout.androidaps.utils.sharedPreferences.SP
+import kotlinx.android.synthetic.main.danars_blescanner_activity.*
+import java.util.*
+import java.util.regex.Pattern
+import javax.inject.Inject
+
+class BLEScanActivity : NoSplashAppCompatActivity() {
+
+ @Inject lateinit var sp: SP
+ @Inject lateinit var rxBus: RxBusWrapper
+ @Inject lateinit var blePreCheck: BlePreCheck
+
+ private var listAdapter: ListAdapter? = null
+ private val devices = ArrayList()
+ private var bluetoothLeScanner: BluetoothLeScanner? = null
+
+ @SuppressLint("SourceLockedOrientationActivity")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.danars_blescanner_activity)
+ requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+
+ blePreCheck.prerequisitesCheck(this)
+
+ listAdapter = ListAdapter()
+ danars_blescanner_listview.emptyView = findViewById(R.id.danars_blescanner_nodevice)
+ danars_blescanner_listview.adapter = listAdapter
+ listAdapter?.notifyDataSetChanged()
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter ->
+ if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable()
+ bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
+ startScan()
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ stopScan()
+ }
+
+ private fun startScan() {
+ if (bluetoothLeScanner != null) bluetoothLeScanner!!.startScan(mBleScanCallback)
+ }
+
+ private fun stopScan() {
+ if (bluetoothLeScanner != null) bluetoothLeScanner!!.stopScan(mBleScanCallback)
+ }
+
+ private fun addBleDevice(device: BluetoothDevice?) {
+ if (device == null || device.name == null || device.name == "") {
+ return
+ }
+ val item = BluetoothDeviceItem(device)
+ if (!isSNCheck(device.name) || devices.contains(item)) {
+ return
+ }
+ devices.add(item)
+ Handler().post { listAdapter!!.notifyDataSetChanged() }
+ }
+
+ private val mBleScanCallback: ScanCallback = object : ScanCallback() {
+ override fun onScanResult(callbackType: Int, result: ScanResult) {
+ addBleDevice(result.device)
+ }
+ }
+
+ internal inner class ListAdapter : BaseAdapter() {
+ override fun getCount(): Int = devices.size
+ override fun getItem(i: Int): BluetoothDeviceItem = devices[i]
+ override fun getItemId(i: Int): Long = 0
+
+ override fun getView(i: Int, convertView: View?, parent: ViewGroup?): View {
+ var v = convertView
+ val holder: ViewHolder
+ if (v == null) {
+ v = View.inflate(applicationContext, R.layout.danars_blescanner_item, null)
+ holder = ViewHolder(v)
+ v.tag = holder
+ } else {
+ // reuse view if already exists
+ holder = v.tag as ViewHolder
+ }
+ val item = getItem(i)
+ holder.setData(item)
+ return v!!
+ }
+
+ private inner class ViewHolder internal constructor(v: View) : View.OnClickListener {
+ private lateinit var item: BluetoothDeviceItem
+ private val name: TextView = v.findViewById(R.id.ble_name)
+ private val address: TextView = v.findViewById(R.id.ble_address)
+
+ init {
+ v.setOnClickListener(this@ViewHolder)
+ }
+
+ override fun onClick(v: View) {
+ sp.putString(R.string.key_danars_address, item.device.address)
+ sp.putString(R.string.key_danars_name, name.text.toString())
+ item.device.createBond()
+ rxBus.send(EventDanaRSDeviceChange())
+ finish()
+ }
+
+ fun setData(data: BluetoothDeviceItem) {
+ var tTitle = data.device.name
+ if (tTitle == null || tTitle == "") {
+ tTitle = "(unknown)"
+ } else if (tTitle.length > 10) {
+ tTitle = tTitle.substring(0, 10)
+ }
+ name.text = tTitle
+ address.text = data.device.address
+ item = data
+ }
+
+ }
+ }
+
+ //
+ inner class BluetoothDeviceItem internal constructor(val device: BluetoothDevice) {
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is BluetoothDeviceItem) {
+ return false
+ }
+ return stringEquals(device.address, other.device.address)
+ }
+
+ private fun stringEquals(arg1: String, arg2: String): Boolean {
+ return try {
+ arg1 == arg2
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+ override fun hashCode(): Int = device.hashCode()
+ }
+
+ private fun isSNCheck(sn: String?): Boolean {
+ val regex = "^([a-zA-Z]{3})([0-9]{5})([a-zA-Z]{2})$"
+ val p = Pattern.compile(regex)
+ val m = p.matcher(sn)
+ return m.matches()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.kt
index ba73e1b368..03d31c10a2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.kt
@@ -1,11 +1,13 @@
package info.nightscout.androidaps.plugins.pump.danaRS.activities
+import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.os.Bundle
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.plugins.pump.danaRS.dialogs.PairingProgressDialog
class PairingHelperActivity : NoSplashAppCompatActivity() {
+ @SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PairingProgressDialog()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.kt
index b079d5c241..1260573c34 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.kt
@@ -37,6 +37,7 @@ class BLEComm @Inject internal constructor(
private val sp: SP,
private val danaRSMessageHashTable: DanaRSMessageHashTable,
private val danaRPump: DanaRPump,
+ private val danaRSPlugin: DanaRSPlugin,
private val bleEncryption: BleEncryption
) {
@@ -52,66 +53,51 @@ class BLEComm @Inject internal constructor(
private var scheduledDisconnection: ScheduledFuture<*>? = null
private var processedMessage: DanaRS_Packet? = null
private val mSendQueue = ArrayList()
- private var mBluetoothManager: BluetoothManager? = null
- private var mBluetoothAdapter: BluetoothAdapter? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
private var connectDeviceName: String? = null
- private var mBluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGatt: BluetoothGatt? = null
var isConnected = false
var isConnecting = false
private var uartRead: BluetoothGattCharacteristic? = null
private var uartWrite: BluetoothGattCharacteristic? = null
- init {
- initialize()
- }
-
- private fun initialize(): Boolean {
+ @Synchronized
+ fun connect(from: String, address: String?): Boolean {
aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing BLEComm.")
- if (mBluetoothManager == null) {
- mBluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
- if (mBluetoothManager == null) {
+ if (bluetoothManager == null) {
+ bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
aapsLogger.error("Unable to initialize BluetoothManager.")
return false
}
}
- mBluetoothAdapter = mBluetoothManager?.adapter
- if (mBluetoothAdapter == null) {
+ bluetoothAdapter = bluetoothManager?.adapter
+ if (bluetoothAdapter == null) {
aapsLogger.error("Unable to obtain a BluetoothAdapter.")
return false
}
- return true
- }
-
- fun connect(from: String, address: String?): Boolean {
- // test existing BT device
- val tBluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
- ?: return false
- tBluetoothManager.adapter ?: return false
if (address == null) {
aapsLogger.error("unspecified address.")
return false
}
- if (mBluetoothAdapter == null) {
- if (!initialize()) {
- return false
- }
- }
isConnecting = true
- val device = mBluetoothAdapter?.getRemoteDevice(address)
+ val device = bluetoothAdapter?.getRemoteDevice(address)
if (device == null) {
aapsLogger.error("Device not found. Unable to connect from: $from")
return false
}
aapsLogger.debug(LTag.PUMPBTCOMM, "Trying to create a new connection from: $from")
connectDeviceName = device.name
- mBluetoothGatt = device.connectGatt(context, false, mGattCallback)
+ bluetoothGatt = device.connectGatt(context, false, mGattCallback)
setCharacteristicNotification(uartReadBTGattChar, true)
return true
}
+ @Synchronized
fun stopConnecting() {
isConnecting = false
}
@@ -124,21 +110,21 @@ class BLEComm @Inject internal constructor(
scheduledDisconnection?.cancel(false)
scheduledDisconnection = null
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
- aapsLogger.error("disconnect not possible: (mBluetoothAdapter == null) " + (mBluetoothAdapter == null))
- aapsLogger.error("disconnect not possible: (mBluetoothGatt == null) " + (mBluetoothGatt == null))
+ if (bluetoothAdapter == null || bluetoothGatt == null) {
+ aapsLogger.error("disconnect not possible: (mBluetoothAdapter == null) " + (bluetoothAdapter == null))
+ aapsLogger.error("disconnect not possible: (mBluetoothGatt == null) " + (bluetoothGatt == null))
return
}
setCharacteristicNotification(uartReadBTGattChar, false)
- mBluetoothGatt?.disconnect()
+ bluetoothGatt?.disconnect()
isConnected = false
SystemClock.sleep(2000)
}
@Synchronized fun close() {
aapsLogger.debug(LTag.PUMPBTCOMM, "BluetoothAdapter close")
- mBluetoothGatt?.close()
- mBluetoothGatt = null
+ bluetoothGatt?.close()
+ bluetoothGatt = null
}
private val mGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
@@ -185,20 +171,20 @@ class BLEComm @Inject internal constructor(
@Synchronized
private fun setCharacteristicNotification(characteristic: BluetoothGattCharacteristic?, enabled: Boolean) {
aapsLogger.debug(LTag.PUMPBTCOMM, "setCharacteristicNotification")
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+ if (bluetoothAdapter == null || bluetoothGatt == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
isConnecting = false
isConnected = false
return
}
- mBluetoothGatt!!.setCharacteristicNotification(characteristic, enabled)
+ bluetoothGatt!!.setCharacteristicNotification(characteristic, enabled)
}
@Synchronized
private fun writeCharacteristicNoResponse(characteristic: BluetoothGattCharacteristic, data: ByteArray) {
Thread(Runnable {
SystemClock.sleep(WRITE_DELAY_MILLIS)
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+ if (bluetoothAdapter == null || bluetoothGatt == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
isConnecting = false
isConnected = false
@@ -207,7 +193,7 @@ class BLEComm @Inject internal constructor(
characteristic.value = data
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
aapsLogger.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data))
- mBluetoothGatt!!.writeCharacteristic(characteristic)
+ bluetoothGatt!!.writeCharacteristic(characteristic)
}).start()
}
@@ -220,15 +206,15 @@ class BLEComm @Inject internal constructor(
?: BluetoothGattCharacteristic(UUID.fromString(UART_WRITE_UUID), BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, 0).also { uartWrite = it }
private fun getSupportedGattServices(): List? {
- aapsLogger.debug(LTag.PUMPBTCOMM, "getSupportedGattServices")
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
- aapsLogger.error("BluetoothAdapter not initialized_ERROR")
- isConnecting = false
- isConnected = false
- return null
- }
- return mBluetoothGatt?.services
+ aapsLogger.debug(LTag.PUMPBTCOMM, "getSupportedGattServices")
+ if (bluetoothAdapter == null || bluetoothGatt == null) {
+ aapsLogger.error("BluetoothAdapter not initialized_ERROR")
+ isConnecting = false
+ isConnected = false
+ return null
}
+ return bluetoothGatt?.services
+ }
private fun findCharacteristic() {
val gattServices = getSupportedGattServices() ?: return
@@ -339,7 +325,7 @@ class BLEComm @Inject internal constructor(
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK.toByte() -> if (decryptedBuffer.size == 4 && decryptedBuffer[2] == 'O'.toByte() && decryptedBuffer[3] == 'K'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Grab pairing key from preferences if exists
- val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, "")
+ val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, "")
aapsLogger.debug(LTag.PUMPBTCOMM, "Using stored pairing key: $pairingKey")
if (pairingKey.isNotEmpty()) {
val encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey)
@@ -366,7 +352,7 @@ class BLEComm @Inject internal constructor(
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.connectionerror)))
- sp.remove(resourceHelper.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName)
+ sp.remove(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName)
val n = Notification(Notification.WRONGSERIALNUMBER, resourceHelper.gs(R.string.wrongpassword), Notification.URGENT)
rxBus.send(EventNewNotification(n))
}
@@ -396,7 +382,7 @@ class BLEComm @Inject internal constructor(
sendTimeInfo()
val pairingKey = byteArrayOf(decryptedBuffer[2], decryptedBuffer[3])
// store pairing key to preferences
- sp.putString(resourceHelper.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey))
+ sp.putString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey))
aapsLogger.debug(LTag.PUMPBTCOMM, "Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey))
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
index 84beb5871d..17f7b03a17 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
@@ -53,9 +53,6 @@ public class RileyLinkMedtronicService extends RileyLinkService {
public RileyLinkMedtronicService() {
super();
instance = this;
- aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly constructed");
- MedtronicUtil.setMedtronicService(this);
- pumpStatus = (MedtronicPumpStatus) medtronicPumpPlugin.getPumpStatusData();
}
@@ -68,6 +65,12 @@ public class RileyLinkMedtronicService extends RileyLinkService {
return instance.medtronicCommunicationManager;
}
+ @Override public void onCreate() {
+ super.onCreate();
+ aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly created");
+ MedtronicUtil.setMedtronicService(this);
+ pumpStatus = (MedtronicPumpStatus) medtronicPumpPlugin.getPumpStatusData();
+ }
@Override
public void onConfigurationChanged(Configuration newConfig) {