- refactored OrangeLink code, created separate handler class and simplified code a little.

This commit is contained in:
Andy Rozman 2021-10-14 21:45:33 +01:00
parent 9e59390d75
commit 57c5401243
8 changed files with 232 additions and 160 deletions

View file

@ -109,7 +109,7 @@ android {
defaultConfig {
multiDexEnabled true
versionCode 1500
version "2.8.2.5-dev_mdt1"
version "2.8.2.5-dev_mdt2"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -9,6 +9,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.S
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.SetPreamble
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioResponse
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.device.OrangeLinkImpl
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusGeneralFragment
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusHistoryFragment
@ -30,6 +31,7 @@ abstract class RileyLinkModule {
@ContributesAndroidInjector abstract fun sendAndListenProvider(): SendAndListen
@ContributesAndroidInjector abstract fun setPreambleProvider(): SetPreamble
@ContributesAndroidInjector abstract fun radioPacketProvider(): RadioPacket
@ContributesAndroidInjector abstract fun orangeLinkDeviceProvider(): OrangeLinkImpl
@ContributesAndroidInjector abstract fun contributesRileyLinkStatusGeneral(): RileyLinkStatusGeneralFragment
@ContributesAndroidInjector abstract fun contributesRileyLinkStatusHistoryFragment(): RileyLinkStatusHistoryFragment

View file

@ -8,19 +8,11 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
@ -34,6 +26,7 @@ import info.nightscout.androidaps.logging.LTag;
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.hw.rileylink.ble.device.OrangeLinkImpl;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperation;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.CharacteristicReadOperation;
@ -57,6 +50,7 @@ public class RileyLinkBLE {
@Inject RileyLinkServiceData rileyLinkServiceData;
@Inject RileyLinkUtil rileyLinkUtil;
@Inject SP sp;
@Inject OrangeLinkImpl orangeLink;
private final Context context;
private final boolean gattDebugEnabled = true;
@ -75,6 +69,8 @@ public class RileyLinkBLE {
this.context = context;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
orangeLink.rileyLinkBLE = this;
bluetoothGattCallback = new BluetoothGattCallback() {
@Override
@ -93,16 +89,7 @@ public class RileyLinkBLE {
radioResponseCountNotified.run();
}
if (characteristic.getUuid().toString().equals(GattAttributes.UUID_NOTIF_CHARACTER.toString())) {
final byte[] data = characteristic.getValue();
int first = 0xff & data[0];
aapsLogger.info(LTag.PUMPBTCOMM,
"onCharacteristicChanged " + ByteUtil.shortHexString(characteristic.getValue()) + "=====" + first);
String fv = data[3] + "." + data[4];
String hv = data[5] + "." + data[6];
rileyLinkServiceData.versionOrangeFV = fv;
rileyLinkServiceData.versionOrangeHV = hv;
}
orangeLink.onCharacteristicChanged(gatt, characteristic);
}
@ -253,9 +240,8 @@ public class RileyLinkBLE {
if (gattDebugEnabled) {
debugService(service, 0);
}
if (GattAttributes.isOrange(uuidService)) {
rileyLinkServiceData.isOrange = true;
}
orangeLink.checkIsOrange(uuidService);
}
if (gattDebugEnabled) {
@ -300,6 +286,7 @@ public class RileyLinkBLE {
if (isAnyRileyLinkServiceFound(serviceI)) {
return true;
}
orangeLink.checkIsOrange(serviceI.getUuid());
}
}
@ -383,53 +370,43 @@ public class RileyLinkBLE {
aapsLogger.error(LTag.PUMPBTCOMM, "Error setting response count notification");
return false;
}
if(rileyLinkServiceData.isOrange){
enableNotificationsOrange();
if (rileyLinkServiceData.isOrange) {
return orangeLink.enableNotifications();
}
return true;
}
public boolean enableNotificationsOrange() {
aapsLogger.error(LTag.PUMPBTCOMM, "enableNotificationsORG");
BLECommOperationResult result = setNotification_blocking(GattAttributes.UUID_NOTIF_SERVICE, //
GattAttributes.UUID_NOTIF_CHARACTER);
if (result.resultCode != BLECommOperationResult.RESULT_SUCCESS) {
aapsLogger.error(LTag.PUMPBTCOMM, "Error setting response count notification");
return false;
}
return true;
}
String macAddress;
public void findRileyLink(String RileyLinkAddress) {
aapsLogger.debug(LTag.PUMPBTCOMM, "RileyLink address: " + RileyLinkAddress);
// Must verify that this is a valid MAC, or crash.
macAddress = RileyLinkAddress;
//macAddress = RileyLinkAddress;
boolean useScanning = sp.getBoolean(RileyLinkConst.Prefs.OrangeUseScanning, false);
if (useScanning) {
startScan();
orangeLink.startScan();
} else {
rileyLinkDevice = bluetoothAdapter.getRemoteDevice(RileyLinkAddress);
// if this succeeds, we get a connection state change callback?
if (rileyLinkDevice != null) {
connectGatt();
connectGattInternal();
} else {
aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device not found with address: " + RileyLinkAddress);
}
}
}
public void connectGattCheckOrange() {
public void connectGatt() {
boolean useScanning = sp.getBoolean(RileyLinkConst.Prefs.OrangeUseScanning, false);
if (useScanning) {
startScan();
orangeLink.startScan();
} else {
connectGatt();
connectGattInternal();
}
}
// This function must be run on UI thread.
public void connectGatt() {
public void connectGattInternal() {
if (this.rileyLinkDevice == null) {
aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device is null, can't do connectGatt.");
return;
@ -478,7 +455,7 @@ public class RileyLinkBLE {
}
private BLECommOperationResult setNotification_blocking(UUID serviceUUID, UUID charaUUID) {
public BLECommOperationResult setNotification_blocking(UUID serviceUUID, UUID charaUUID) {
BLECommOperationResult rval = new BLECommOperationResult();
if (bluetoothConnectionGatt != null) {
@ -643,116 +620,11 @@ public class RileyLinkBLE {
return statusMessage;
}
private List<ScanFilter> buildScanFilters() {
ArrayList scanFilterList = new ArrayList<>();
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder();
scanFilterBuilder.setDeviceAddress(macAddress);
scanFilterList.add(scanFilterBuilder.build());
return scanFilterList;
public void setRileyLinkDevice(BluetoothDevice device) {
this.rileyLinkDevice = device;
}
private ScanSettings buildScanSettings() {
ScanSettings.Builder scanSettingBuilder = new ScanSettings.Builder();
scanSettingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
scanSettingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
scanSettingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
return scanSettingBuilder.build();
}
public void startScan() {
try {
stopScan();
aapsLogger.debug(LTag.PUMPBTCOMM, "startScan");
handler.sendEmptyMessageDelayed(TIME_OUT_WHAT, TIME_OUT);
BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bluetoothLeScanner == null) {
bluetoothAdapter.startLeScan(mLeScanCallback);
return;
}
bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), scanCallback);
} catch (Exception e) {
e.printStackTrace();
aapsLogger.error(LTag.PUMPBTCOMM, e.getMessage());
}
}
ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
String name = result.getDevice().getName();
String address = result.getDevice().getAddress();
if (macAddress.equals(address)) {
stopScan();
rileyLinkDevice = result.getDevice();
connectGatt();
}
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
stopScan();
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, final int rssi,
final byte[] scanRecord) {
if (macAddress.equals(device.getAddress())) {
stopScan();
rileyLinkDevice = device;
connectGatt();
}
}
};
public static final int TIME_OUT = 90 * 1000;
public static final int TIME_OUT_WHAT = 0x12;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case TIME_OUT_WHAT:
stopScan();
break;
}
}
};
public void stopScan() {
handler.removeMessages(TIME_OUT_WHAT);
if (bluetoothAdapter == null) {
return;
}
try {
BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bluetoothLeScanner == null) {
if (isBluetoothAvailable()) {
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
return;
}
if (isBluetoothAvailable()) {
bluetoothLeScanner.stopScan(scanCallback);
}
} catch (Exception e) {
e.printStackTrace();
aapsLogger.error(LTag.PUMPBTCOMM, e.getMessage());
}
}
public boolean isBluetoothAvailable() {
return (bluetoothAdapter != null &&
bluetoothAdapter.isEnabled() &&
bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON);
public BluetoothAdapter getBluetoothAdapter() {
return bluetoothAdapter;
}
}

View file

@ -16,7 +16,7 @@ public class GattAttributes {
public static String SERVICE_GAP = PREFIX + "1800" + SUFFIX;
public static String CHARA_GAP_NAME = PREFIX + "2a00" + SUFFIX; // RileyLink RFSpy
public static String CHARA_GAP_NUM = PREFIX + "2a01" + SUFFIX; // 0000
public static String CHARA_GAP_UNK = PREFIX + "2a01" + SUFFIX; // a
//public static String CHARA_GAP_UNK = PREFIX + "2a01" + SUFFIX; // a
public static String SERVICE_BATTERY = PREFIX + "180f" + SUFFIX; // Battery
public static String CHARA_BATTERY_UNK = PREFIX + "2a19" + SUFFIX;
@ -29,9 +29,13 @@ public class GattAttributes {
public static String CHARA_RADIO_CUSTOM_NAME = "d93b2af0-1e28-11e4-8c21-0800200c9a66";
public static String CHARA_RADIO_VERSION = "30d99dc9-7c91-4295-a051-0a104d238cf2";
public static String CHARA_RADIO_LED_MODE = "c6d84241-f1a7-4f9c-a25f-fce16732f14e";
//Orange Radio Service
public static UUID UUID_NOTIF_SERVICE = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
public static UUID UUID_NOTIF_CHARACTER = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
public static String SERVICE_RADIO_ORANGE = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
public static String CHARA_NOTIFICATION_ORANGE = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
//public static UUID UUID_NOTIF_SERVICE = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
//public static UUID UUID_NOTIF_CHARACTER = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
private static final Map<String, String> attributes;
private static final Map<String, String> attributesRileyLinkSpecific;
@ -63,6 +67,9 @@ public class GattAttributes {
attributesRileyLinkSpecific.put(CHARA_RADIO_TIMER_TICK, "Timer Tick");
attributesRileyLinkSpecific.put(CHARA_RADIO_VERSION, "Version"); // firmwareVersion
attributesRileyLinkSpecific.put(CHARA_RADIO_LED_MODE, "Led Mode");
attributesRileyLinkSpecific.put(SERVICE_RADIO_ORANGE, "Orange Radio Interface");
attributesRileyLinkSpecific.put(CHARA_NOTIFICATION_ORANGE, "Orange Notification");
}
@ -86,8 +93,10 @@ public class GattAttributes {
public static boolean isRileyLink(UUID uuid) {
return attributesRileyLinkSpecific.containsKey(uuid.toString());
}
public static boolean isOrange(UUID uuid) {
return UUID_NOTIF_SERVICE.equals(uuid.toString());
return SERVICE_RADIO_ORANGE.equals(uuid.toString());
}
}

View file

@ -0,0 +1,187 @@
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.device
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothAdapter.LeScanCallback
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.os.Handler
import android.os.Message
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.lang.Exception
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class OrangeLinkImpl @Inject constructor(
var aapsLogger: AAPSLogger,
var rileyLinkServiceData: RileyLinkServiceData,
var rileyLinkUtil: RileyLinkUtil,
var sp: SP) {
lateinit var rileyLinkBLE: RileyLinkBLE
fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
if (characteristic.uuid.toString().equals(GattAttributes.CHARA_NOTIFICATION_ORANGE)) {
val data = characteristic.value
val first = 0xff and data[0].toInt()
aapsLogger.info(LTag.PUMPBTCOMM,
"OrangeLinkImpl: onCharacteristicChanged " + ByteUtil.shortHexString(characteristic.value) + "=====" + first)
val fv = data[3].toString() + "." + data[4]
val hv = data[5].toString() + "." + data[6]
rileyLinkServiceData.versionOrangeFirmware = fv
rileyLinkServiceData.versionOrangeHardware = hv
aapsLogger.info(LTag.PUMPBTCOMM, "OrangeLink: Firmware: ${fv}, Hardware: ${hv}")
}
}
fun checkIsOrange(uuidService: UUID) {
if (GattAttributes.isOrange(uuidService)) {
rileyLinkServiceData.isOrange = true
}
}
fun enableNotifications(): Boolean {
aapsLogger.info(LTag.PUMPBTCOMM, "OrangeLinkImpl::enableNotifications")
val result: BLECommOperationResult = rileyLinkBLE.setNotification_blocking(
UUID.fromString(GattAttributes.SERVICE_RADIO_ORANGE), //
UUID.fromString(GattAttributes.CHARA_NOTIFICATION_ORANGE)
)
if (result.resultCode != BLECommOperationResult.RESULT_SUCCESS) {
aapsLogger.error(LTag.PUMPBTCOMM, "Error setting response count notification")
return false
}
return true
}
private fun buildScanFilters(): List<ScanFilter> {
val scanFilterList: MutableList<ScanFilter> = mutableListOf() //ArrayList<*> = ArrayList<Any>()
val scanFilterBuilder = ScanFilter.Builder()
scanFilterBuilder.setDeviceAddress(rileyLinkServiceData.rileyLinkAddress)
scanFilterList.add(scanFilterBuilder.build())
return scanFilterList
}
private fun buildScanSettings(): ScanSettings? {
val scanSettingBuilder = ScanSettings.Builder()
scanSettingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
scanSettingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
scanSettingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
return scanSettingBuilder.build()
}
fun startScan() {
try {
stopScan()
val bluetoothAdapter = rileyLinkBLE.getBluetoothAdapter()
aapsLogger.debug(LTag.PUMPBTCOMM, "startScan")
handler.sendEmptyMessageDelayed(TIME_OUT_WHAT, TIME_OUT.toLong())
val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner()
// if (bluetoothLeScanner == null) {
// bluetoothAdapter.startLeScan(mLeScanCallback)
// return
// }
bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), scanCallback)
} catch (e: Exception) {
e.printStackTrace()
aapsLogger.error(LTag.PUMPBTCOMM, "Start scan: ${e.message}", e)
}
}
var scanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
super.onScanResult(callbackType, result)
//val name = result.device.name
val address = result.device.address
if (rileyLinkServiceData.rileyLinkAddress.equals(address)) {
stopScan()
rileyLinkBLE.rileyLinkDevice = result.device
rileyLinkBLE.connectGattInternal()
}
}
override fun onBatchScanResults(results: List<ScanResult>) {
super.onBatchScanResults(results)
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
stopScan()
}
}
private val mLeScanCallback = LeScanCallback { device, _, _ ->
if (rileyLinkServiceData.rileyLinkAddress.equals(device.address)) {
stopScan()
rileyLinkBLE.rileyLinkDevice = device
rileyLinkBLE.connectGattInternal()
}
}
val TIME_OUT = 90 * 1000
val TIME_OUT_WHAT = 0x12
var handler: Handler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.what) {
TIME_OUT_WHAT -> stopScan()
}
}
}
fun stopScan() {
handler.removeMessages(TIME_OUT_WHAT)
val bluetoothAdapter = rileyLinkBLE.getBluetoothAdapter() ?: return
try {
val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner()
if (isBluetoothAvailable()) {
bluetoothLeScanner.stopScan(scanCallback)
}
return
// if (bluetoothLeScanner == null) {
// if (isBluetoothAvailable()) {
// bluetoothAdapter.stopLeScan(mLeScanCallback)
// }
// return
// }
// if (isBluetoothAvailable()) {
// bluetoothLeScanner.stopScan(scanCallback)
// }
} catch (e: Exception) {
aapsLogger.error(LTag.PUMPBTCOMM, "Stop scan: ${e.message}", e)
}
}
fun isBluetoothAvailable(): Boolean {
val bluetoothAdapter = rileyLinkBLE.getBluetoothAdapter()
return bluetoothAdapter != null &&
bluetoothAdapter.isEnabled() &&
bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON
}
}

View file

@ -109,7 +109,7 @@ public class RileyLinkStatusGeneralFragment extends DaggerFragment implements Re
if(rileyLinkServiceData.isOrange){
this.firmwareVersion.setText("FV:"+Optional.ofNullable(rileyLinkServiceData.versionOrangeFV).orElse(PLACEHOLDER)+"\nHV:"+Optional.ofNullable(rileyLinkServiceData.versionOrangeHV).orElse(PLACEHOLDER));
this.firmwareVersion.setText("FV:"+Optional.ofNullable(rileyLinkServiceData.versionOrangeFirmware).orElse(PLACEHOLDER)+"\nHV:"+Optional.ofNullable(rileyLinkServiceData.versionOrangeHardware).orElse(PLACEHOLDER));
}else{
this.firmwareVersion.setText(resourceHelper.gs(R.string.rileylink_firmware_version_value,
Optional.ofNullable(rileyLinkServiceData.versionBLE113).orElse(PLACEHOLDER), Optional.ofNullable(rileyLinkServiceData.versionCC110).orElse(PLACEHOLDER)));

View file

@ -48,9 +48,11 @@ public class RileyLinkServiceData {
public String versionBLE113;
// radio version
public String versionCC110;
// orangeLink
public boolean isOrange;
public String versionOrangeFV;
public String versionOrangeHV;
public String versionOrangeFirmware;
public String versionOrangeHardware;
public RileyLinkTargetDevice targetDevice;

View file

@ -38,7 +38,7 @@ public class DiscoverGattServicesTask extends ServiceTask {
RileyLinkPumpDevice pumpDevice = (RileyLinkPumpDevice) activePlugin.getActivePump();
if (needToConnect) {
pumpDevice.getRileyLinkService().getRileyLinkBLE().connectGattCheckOrange();
pumpDevice.getRileyLinkService().getRileyLinkBLE().connectGatt();
}
pumpDevice.getRileyLinkService().getRileyLinkBLE().discoverServices();