kt, share some MDT code
This commit is contained in:
parent
7b0bc81c47
commit
b872b82cd9
9 changed files with 326 additions and 399 deletions
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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;
|
||||
// }
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<BluetoothDeviceItem> 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();
|
||||
}
|
||||
}
|
|
@ -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<BluetoothDeviceItem>()
|
||||
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()
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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<ByteArray>()
|
||||
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<BluetoothGattService>? {
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue