Unify bluetooth, Android 12 permissions

This commit is contained in:
Milos Kozak 2021-12-13 01:01:16 +01:00
parent 0307796ecf
commit 201a04bfbf
29 changed files with 231 additions and 237 deletions

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.general.maintenance
import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@ -24,8 +24,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
@ -41,9 +39,11 @@ import info.nightscout.androidaps.utils.alertDialogs.WarningDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.storage.Storage
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
@ -81,17 +81,13 @@ class ImportExportPrefsImpl @Inject constructor(
override fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) {
fragment.context?.let { ctx ->
val permission = ContextCompat.checkSelfPermission(ctx,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
val permission = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
fragment.activity?.let {
androidPermission.askForPermission(it,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE))
androidPermission.askForPermission(it, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE))
}
} else {
onGranted.run()
}
} else onGranted.run()
}
}
@ -114,7 +110,7 @@ class ImportExportPrefsImpl @Inject constructor(
// based on https://medium.com/@pribble88/how-to-get-an-android-device-nickname-4b4700b3068c
val n1 = Settings.System.getString(context.contentResolver, "bluetooth_name")
val n2 = Settings.Secure.getString(context.contentResolver, "bluetooth_name")
val n3 = BluetoothAdapter.getDefaultAdapter()?.name
val n3 = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.name
val n4 = Settings.System.getString(context.contentResolver, "device_name")
val n5 = Settings.Secure.getString(context.contentResolver, "lock_screen_owner_info")
val n6 = Settings.Global.getString(context.contentResolver, "device_name")
@ -132,36 +128,38 @@ class ImportExportPrefsImpl @Inject constructor(
passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { password ->
then(password)
}, {
ToastUtils.warnToast(activity, rh.gs(canceledMsg))
})
ToastUtils.warnToast(activity, rh.gs(canceledMsg))
})
}
@Suppress("SameParameterValue")
private fun askForEncryptionPass(activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?,
@StringRes passwordWarning: Int?, then: ((password: String) -> Unit)) {
private fun askForEncryptionPass(
activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?,
@StringRes passwordWarning: Int?, then: ((password: String) -> Unit)
) {
passwordCheck.queryAnyPassword(activity, passwordName, R.string.key_master_password, passwordExplanation, passwordWarning, { password ->
then(password)
}, {
ToastUtils.warnToast(activity, rh.gs(canceledMsg))
})
ToastUtils.warnToast(activity, rh.gs(canceledMsg))
})
}
@Suppress("SameParameterValue")
private fun askForMasterPassIfNeeded(activity: FragmentActivity, @StringRes canceledMsg: Int, then: ((password: String) -> Unit)) {
askForMasterPass(activity, canceledMsg, then)
askForMasterPass(activity, canceledMsg, then)
}
private fun assureMasterPasswordSet(activity: FragmentActivity, @StringRes wrongPwdTitle: Int): Boolean {
if (!sp.contains(R.string.key_master_password) || (sp.getString(R.string.key_master_password, "") == "")) {
WarningDialog.showWarning(activity,
rh.gs(wrongPwdTitle),
rh.gs(R.string.master_password_missing, rh.gs(R.string.configbuilder_general), rh.gs(R.string.protection)),
R.string.nav_preferences, {
val intent = Intent(activity, PreferencesActivity::class.java).apply {
putExtra("id", R.xml.pref_general)
}
activity.startActivity(intent)
})
rh.gs(wrongPwdTitle),
rh.gs(R.string.master_password_missing, rh.gs(R.string.configbuilder_general), rh.gs(R.string.protection)),
R.string.nav_preferences, {
val intent = Intent(activity, PreferencesActivity::class.java).apply {
putExtra("id", R.xml.pref_general)
}
activity.startActivity(intent)
})
return false
}
return true
@ -170,29 +168,37 @@ class ImportExportPrefsImpl @Inject constructor(
private fun askToConfirmExport(activity: FragmentActivity, fileToExport: File, then: ((password: String) -> Unit)) {
if (!assureMasterPasswordSet(activity, R.string.nav_export)) return
TwoMessagesAlertDialog.showAlert(activity, rh.gs(R.string.nav_export),
TwoMessagesAlertDialog.showAlert(
activity, rh.gs(R.string.nav_export),
rh.gs(R.string.export_to) + " " + fileToExport.name + " ?",
rh.gs(R.string.password_preferences_encrypt_prompt), {
askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then)
}, null, R.drawable.ic_header_export)
askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then)
}, null, R.drawable.ic_header_export
)
}
private fun askToConfirmImport(activity: FragmentActivity, fileToImport: PrefsFile, then: ((password: String) -> Unit)) {
if (!assureMasterPasswordSet(activity, R.string.nav_import)) return
TwoMessagesAlertDialog.showAlert(activity, rh.gs(R.string.nav_import),
TwoMessagesAlertDialog.showAlert(
activity, rh.gs(R.string.nav_import),
rh.gs(R.string.import_from) + " " + fileToImport.name + " ?",
rh.gs(R.string.password_preferences_decrypt_prompt), {
askForMasterPass(activity, R.string.preferences_import_canceled, then)
}, null, R.drawable.ic_header_import)
askForMasterPass(activity, R.string.preferences_import_canceled, then)
}, null, R.drawable.ic_header_import
)
}
private fun promptForDecryptionPasswordIfNeeded(activity: FragmentActivity, prefs: Prefs, importOk: Boolean,
format: PrefsFormat, importFile: PrefsFile, then: ((prefs: Prefs, importOk: Boolean) -> Unit)) {
private fun promptForDecryptionPasswordIfNeeded(
activity: FragmentActivity, prefs: Prefs, importOk: Boolean,
format: PrefsFormat, importFile: PrefsFile, then: ((prefs: Prefs, importOk: Boolean) -> Unit)
) {
// current master password was not the one used for decryption, so we prompt for old password...
if (!importOk && (prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status == PrefsStatus.ERROR)) {
askForEncryptionPass(activity, R.string.preferences_import_canceled, R.string.old_master_password,
R.string.different_password_used, R.string.master_password_will_be_replaced) { password ->
askForEncryptionPass(
activity, R.string.preferences_import_canceled, R.string.old_master_password,
R.string.different_password_used, R.string.master_password_will_be_replaced
) { password ->
// ...and use it to load & decrypt file again
val prefsReloaded = format.loadPreferences(importFile.file, password)
@ -232,15 +238,19 @@ class ImportExportPrefsImpl @Inject constructor(
ToastUtils.errorToast(activity, e.message)
log.error(LTag.CORE, "Unhandled exception", e)
} catch (e: PrefFileNotFoundError) {
ToastUtils.Long.errorToast(activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.filenotfound)
+ ": " + e.message
+ "\n\n" + rh.gs(R.string.needstoragepermission))
ToastUtils.Long.errorToast(
activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.filenotfound)
+ ": " + e.message
+ "\n\n" + rh.gs(R.string.needstoragepermission)
)
log.error(LTag.CORE, "File system exception", e)
} catch (e: PrefIOError) {
ToastUtils.Long.errorToast(activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.needstoragepermission)
+ ": " + e.message)
ToastUtils.Long.errorToast(
activity, rh.gs(R.string.preferences_export_canceled)
+ "\n\n" + rh.gs(R.string.needstoragepermission)
+ ": " + e.message
)
log.error(LTag.CORE, "File system exception", e)
}
}
@ -269,7 +279,7 @@ class ImportExportPrefsImpl @Inject constructor(
askToConfirmImport(activity, importFile) { password ->
val format: PrefsFormat = encryptedPrefsFormat
val format: PrefsFormat = encryptedPrefsFormat
try {

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.queue
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
import android.os.PowerManager
import android.os.SystemClock
@ -9,18 +9,18 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueue
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.queue.events.EventQueueChanged
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
class QueueThread internal constructor(
private val queue: CommandQueue,
context: Context,
private val context: Context,
private val aapsLogger: AAPSLogger,
private val rxBus: RxBus,
private val activePlugin: ActivePlugin,
@ -63,8 +63,7 @@ class QueueThread internal constructor(
//toggle BT
pump.disconnect("watchdog")
SystemClock.sleep(1000)
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (bluetoothAdapter != null) {
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.let { bluetoothAdapter ->
bluetoothAdapter.disable()
SystemClock.sleep(1000)
bluetoothAdapter.enable()

View file

@ -74,7 +74,7 @@ class TriggerBTDevice(injector: HasAndroidInjector) : Trigger(injector) {
// Get the list of paired BT devices to use in dropdown menu
private fun devicesPaired(): ArrayList<CharSequence> {
val s = ArrayList<CharSequence>()
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter?.bondedDevices?.forEach { s.add(it.name) }
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.bondedDevices?.forEach { s.add(it.name) }
return s
}

View file

@ -7,6 +7,8 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application>
<activity android:name="info.nightscout.androidaps.activities.TDDStatsActivity" />
<activity

View file

@ -130,6 +130,7 @@ class BolusProgressDialog : DaggerDialogFragment() {
.toObservable(EventDismissBolusProgressIfRunning::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({
aapsLogger.debug(LTag.PUMP, "Running timestamp $timestamp. Close request timestamp ${it.bolusTimestamp}")
if (it.bolusTimestamp == null || it.bolusTimestamp == timestamp)
if (running) dismiss()
}, fabricPrivacy::logException)

View file

@ -6,6 +6,8 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Build
import android.os.SystemClock
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
@ -23,7 +25,9 @@ class BlePreCheck @Inject constructor(
) {
companion object {
private const val PERMISSION_REQUEST_COARSE_LOCATION = 30241 // arbitrary.
private const val PERMISSION_REQUEST_BLUETOOTH = 30242 // arbitrary.
}
fun prerequisitesCheck(activity: AppCompatActivity): Boolean {
@ -37,11 +41,20 @@ class BlePreCheck @Inject constructor(
// your code that requires permission
ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), PERMISSION_REQUEST_COARSE_LOCATION)
}
// change after SDK = 31+
if (Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31) {
//ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), PERMISSION_REQUEST_BLUETOOTH)
ActivityCompat.requestPermissions(activity, arrayOf("android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT"), PERMISSION_REQUEST_BLUETOOTH)
}
val bluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
val bluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
// 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) {
if (bluetoothAdapter?.isEnabled != true) {
bluetoothAdapter?.enable()
SystemClock.sleep(3000)
}
if (bluetoothAdapter?.isEnabled != true) {
OKDialog.show(activity, rh.gs(R.string.message), rh.gs(R.string.ble_not_enabled))
return false
} else {

View file

@ -3,6 +3,8 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<application>
<service
android:name="info.nightscout.androidaps.danar.services.DanaRExecutionService"

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.danar.services;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
@ -190,7 +191,7 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
protected void getBTSocketForSelectedPump() {
mDevName = sp.getString(R.string.key_danar_bt_name, "");
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothAdapter bluetoothAdapter = ((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
if (bluetoothAdapter != null) {
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();

View file

@ -3,9 +3,11 @@ package info.nightscout.androidaps.danars.activities
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import android.content.Context
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.os.Handler
@ -30,10 +32,12 @@ class BLEScanActivity : NoSplashAppCompatActivity() {
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBus
@Inject lateinit var blePreCheck: BlePreCheck
@Inject lateinit var context: Context
private var listAdapter: ListAdapter? = null
private val devices = ArrayList<BluetoothDeviceItem>()
private var bluetoothLeScanner: BluetoothLeScanner? = null
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private val bluetoothLeScanner: BluetoothLeScanner? get() = bluetoothAdapter?.bluetoothLeScanner
private lateinit var binding: DanarsBlescannerActivityBinding
@ -55,11 +59,8 @@ class BLEScanActivity : NoSplashAppCompatActivity() {
override fun onResume() {
super.onResume()
BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter ->
if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable()
bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
startScan()
}
if (bluetoothAdapter?.isEnabled != true) bluetoothAdapter?.enable()
startScan()
}
override fun onPause() {

View file

@ -21,8 +21,6 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.extensions.notify
import info.nightscout.androidaps.extensions.waitMillis
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
@ -31,6 +29,8 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import java.util.*
import java.util.concurrent.ScheduledFuture
@ -69,8 +69,7 @@ class BLEComm @Inject internal constructor(
private var scheduledDisconnection: ScheduledFuture<*>? = null
private var processedMessage: DanaRSPacket? = null
private val mSendQueue = ArrayList<ByteArray>()
private var bluetoothManager: BluetoothManager? = null
private var bluetoothAdapter: BluetoothAdapter? = null
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private var connectDeviceName: String? = null
private var bluetoothGatt: BluetoothGatt? = null
@ -92,14 +91,6 @@ class BLEComm @Inject internal constructor(
@Synchronized
fun connect(from: String, address: String?): Boolean {
aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing BLEComm.")
if (bluetoothManager == null) {
bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
if (bluetoothManager == null) {
aapsLogger.error("Unable to initialize BluetoothManager.")
return false
}
}
bluetoothAdapter = bluetoothManager?.adapter
if (bluetoothAdapter == null) {
aapsLogger.error("Unable to obtain a BluetoothAdapter.")
return false
@ -411,7 +402,8 @@ class BLEComm @Inject internal constructor(
if (bufferLength >= 6) {
for (idxStartByte in 0 until bufferLength - 2) {
if (readBuffer[idxStartByte] == PACKET_START_BYTE && readBuffer[idxStartByte + 1] == PACKET_START_BYTE ||
readBuffer[idxStartByte] == BLE5_PACKET_START_BYTE && readBuffer[idxStartByte + 1] == BLE5_PACKET_START_BYTE) {
readBuffer[idxStartByte] == BLE5_PACKET_START_BYTE && readBuffer[idxStartByte + 1] == BLE5_PACKET_START_BYTE
) {
if (idxStartByte > 0) {
// if buffer doesn't start with signature remove the leading trash
aapsLogger.debug(LTag.PUMPBTCOMM, "Shifting the input buffer by $idxStartByte bytes")
@ -429,7 +421,8 @@ class BLEComm @Inject internal constructor(
return
// Verify packed end [5A 5A]
if (readBuffer[length + 5] == PACKET_END_BYTE && readBuffer[length + 6] == PACKET_END_BYTE ||
readBuffer[length + 5] == BLE5_PACKET_END_BYTE && readBuffer[length + 6] == BLE5_PACKET_END_BYTE) {
readBuffer[length + 5] == BLE5_PACKET_END_BYTE && readBuffer[length + 6] == BLE5_PACKET_END_BYTE
) {
packetIsValid = true
} else {
aapsLogger.error(LTag.PUMPBTCOMM, "Error in input data. Resetting buffer.")

View file

@ -5,6 +5,10 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<application>
<activity android:name="info.nightscout.androidaps.diaconn.activities.DiaconnG8HistoryActivity" />
<activity android:name="info.nightscout.androidaps.diaconn.activities.DiaconnG8UserOptionsActivity" />

View file

@ -3,11 +3,13 @@ package info.nightscout.androidaps.diaconn.activities
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
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.content.pm.ActivityInfo
import android.os.Bundle
import android.os.Handler
@ -32,7 +34,9 @@ class DiaconnG8BLEScanActivity : NoSplashAppCompatActivity() {
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBus
@Inject lateinit var blePreCheck: BlePreCheck
@Inject lateinit var context: Context
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private var listAdapter: ListAdapter? = null
private val devices = ArrayList<BluetoothDeviceItem>()
private var bluetoothLeScanner: BluetoothLeScanner? = null
@ -58,7 +62,7 @@ class DiaconnG8BLEScanActivity : NoSplashAppCompatActivity() {
override fun onResume() {
super.onResume()
BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter ->
bluetoothAdapter?.let { bluetoothAdapter ->
if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable()
bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
startScan()

View file

@ -44,8 +44,7 @@ class BLECommonService @Inject internal constructor(
private var processedMessage: DiaconnG8Packet? = null
private var processedMessageByte: ByteArray? = null
private val mSendQueue = ArrayList<ByteArray>()
private var bluetoothManager: BluetoothManager? = null
private var bluetoothAdapter: BluetoothAdapter? = null
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private var connectDeviceName: String? = null
private var bluetoothGatt: BluetoothGatt? = null
@ -69,14 +68,6 @@ class BLECommonService @Inject internal constructor(
@Synchronized
fun connect(from: String, address: String?): Boolean {
aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing Bluetooth ")
if (bluetoothManager == null) {
bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
if (bluetoothManager == null) {
aapsLogger.error("Unable to initialize BluetoothManager.")
return false
}
}
bluetoothAdapter = bluetoothManager?.adapter
if (bluetoothAdapter == null) {
aapsLogger.error("Unable to obtain a BluetoothAdapter.")
return false

View file

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps.insight">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.VIBRATE" />
<application>
<activity

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.insight.activities;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@ -25,14 +26,20 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.insight.R;
import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck;
import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState;
import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator;
public class InsightPairingActivity extends NoSplashAppCompatActivity implements InsightConnectionService.StateCallback, View.OnClickListener, InsightConnectionService.ExceptionCallback {
@Inject BlePreCheck blePreCheck;
@Inject Context context;
private boolean scanning;
private LinearLayout deviceSearchSection;
private TextView pleaseWaitSection;
@ -71,6 +78,8 @@ public class InsightPairingActivity extends NoSplashAppCompatActivity implements
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insight_pairing);
blePreCheck.prerequisitesCheck(this);
deviceSearchSection = findViewById(R.id.device_search_section);
pleaseWaitSection = findViewById(R.id.please_wait_section);
codeCompareSection = findViewById(R.id.code_compare_section);
@ -160,7 +169,7 @@ public class InsightPairingActivity extends NoSplashAppCompatActivity implements
private void startBLScan() {
if (!scanning) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothAdapter bluetoothAdapter = ((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
if (bluetoothAdapter != null) {
if (!bluetoothAdapter.isEnabled()) bluetoothAdapter.enable();
IntentFilter intentFilter = new IntentFilter();
@ -176,7 +185,7 @@ public class InsightPairingActivity extends NoSplashAppCompatActivity implements
private void stopBLScan() {
if (scanning) {
unregisterReceiver(broadcastReceiver);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothAdapter bluetoothAdapter = ((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
if (bluetoothAdapter != null) {
bluetoothAdapter.cancelDiscovery();
}
@ -204,7 +213,7 @@ public class InsightPairingActivity extends NoSplashAppCompatActivity implements
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
BluetoothAdapter.getDefaultAdapter().startDiscovery();
((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().startDiscovery();
else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceAdapter.addDevice(bluetoothDevice);

View file

@ -2,7 +2,9 @@ package info.nightscout.androidaps.plugins.pump.insight.connection_service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
@ -106,7 +108,8 @@ public class InsightConnectionService extends DaggerService implements Connectio
private DelayedActionThread disconnectTimer;
private DelayedActionThread recoveryTimer;
private DelayedActionThread timeoutTimer;
private final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private final BluetoothAdapter bluetoothAdapter =
((BluetoothManager)getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
private BluetoothDevice bluetoothDevice;
private BluetoothSocket bluetoothSocket;
private ConnectionEstablisher connectionEstablisher;

View file

@ -97,7 +97,7 @@ class MedtronicFragment : DaggerFragment() {
binding.pumpStatusIcon.text = "{fa-bed}"
binding.history.setOnClickListener {
if (medtronicPumpPlugin.rileyLinkService.verifyConfiguration()) {
if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() == true) {
startActivity(Intent(context, MedtronicHistoryActivity::class.java))
} else {
displayNotConfiguredDialog()
@ -105,7 +105,7 @@ class MedtronicFragment : DaggerFragment() {
}
binding.refresh.setOnClickListener {
if (!medtronicPumpPlugin.rileyLinkService.verifyConfiguration()) {
if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() != true) {
displayNotConfiguredDialog()
} else {
binding.refresh.isEnabled = false
@ -119,7 +119,7 @@ class MedtronicFragment : DaggerFragment() {
}
binding.stats.setOnClickListener {
if (medtronicPumpPlugin.rileyLinkService.verifyConfiguration()) {
if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() == true) {
startActivity(Intent(context, RileyLinkStatusActivity::class.java))
} else {
displayNotConfiguredDialog()
@ -159,7 +159,7 @@ class MedtronicFragment : DaggerFragment() {
.observeOn(aapsSchedulers.main)
.subscribe({
aapsLogger.debug(LTag.PUMP, "EventMedtronicPumpConfigurationChanged triggered")
medtronicPumpPlugin.rileyLinkService.verifyConfiguration()
medtronicPumpPlugin.rileyLinkService?.verifyConfiguration()
updateGUI()
}, fabricPrivacy::logException)
disposable += rxBus
@ -191,7 +191,7 @@ class MedtronicFragment : DaggerFragment() {
@Synchronized
private fun setDeviceStatus() {
val resourceId = rileyLinkServiceData.rileyLinkServiceState.resourceId
val rileyLinkError = medtronicPumpPlugin.rileyLinkService.error
val rileyLinkError = medtronicPumpPlugin.rileyLinkService?.error
binding.rlStatus.text =
when {
rileyLinkServiceData.rileyLinkServiceState == RileyLinkServiceState.NotStarted -> rh.gs(resourceId)
@ -337,7 +337,7 @@ class MedtronicFragment : DaggerFragment() {
binding.reservoir.text = rh.gs(R.string.reservoirvalue, medtronicPumpStatus.reservoirRemainingUnits, medtronicPumpStatus.reservoirFullUnits)
warnColors.setColorInverse(binding.reservoir, medtronicPumpStatus.reservoirRemainingUnits, 50.0, 20.0)
medtronicPumpPlugin.rileyLinkService.verifyConfiguration()
medtronicPumpPlugin.rileyLinkService?.verifyConfiguration()
binding.errors.text = medtronicPumpStatus.errorInfo
val showRileyLinkBatteryLevel: Boolean = rileyLinkServiceData.showBatteryLevel

View file

@ -13,14 +13,13 @@ import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.common.events.EventRefreshButtonState
@ -33,6 +32,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask
import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR
import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
@ -56,6 +56,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.TimeChangeType
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import org.joda.time.LocalDateTime
import java.util.*
@ -89,7 +91,7 @@ class MedtronicPumpPlugin @Inject constructor(
aapsSchedulers: AapsSchedulers,
pumpSync: PumpSync,
pumpSyncStorage: info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage
) : info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract(PluginDescription() //
) : PumpPluginAbstract(PluginDescription() //
.mainType(PluginType.PUMP) //
.fragmentClass(MedtronicFragment::class.java.name) //
.pluginIcon(R.drawable.ic_veo_128)
@ -97,11 +99,11 @@ class MedtronicPumpPlugin @Inject constructor(
.shortName(R.string.medtronic_name_short) //
.preferencesId(R.xml.pref_medtronic)
.description(R.string.description_pump_medtronic), //
PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later
injector, rh, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage
), Pump, RileyLinkPumpDevice, info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator {
PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later
injector, rh, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage
), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator {
private lateinit var rileyLinkMedtronicService: RileyLinkMedtronicService
private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null
// variables for handling statuses and history
private var firstRun = true
@ -126,12 +128,12 @@ class MedtronicPumpPlugin @Inject constructor(
val mLocalBinder = service as RileyLinkMedtronicService.LocalBinder
rileyLinkMedtronicService = mLocalBinder.serviceInstance
isServiceSet = true
rileyLinkMedtronicService.verifyConfiguration()
rileyLinkMedtronicService?.verifyConfiguration()
Thread {
for (i in 0..19) {
SystemClock.sleep(5000)
aapsLogger.debug(LTag.PUMP, "Starting Medtronic-RileyLink service")
if (rileyLinkMedtronicService.setNotInPreInit()) {
if (rileyLinkMedtronicService?.setNotInPreInit() == true) {
break
}
}
@ -232,9 +234,7 @@ class MedtronicPumpPlugin @Inject constructor(
// Pump Plugin
private var isServiceSet: Boolean = false
override fun getRileyLinkService(): RileyLinkMedtronicService {
return rileyLinkMedtronicService
}
override fun getRileyLinkService(): RileyLinkMedtronicService? = rileyLinkMedtronicService
override fun getPumpInfo(): RileyLinkPumpInfo {
val frequency = rh.gs(if (medtronicPumpStatus.pumpFrequency == "medtronic_pump_frequency_us_ca") R.string.medtronic_pump_frequency_us_ca else R.string.medtronic_pump_frequency_worldwide)
@ -294,12 +294,12 @@ class MedtronicPumpPlugin @Inject constructor(
override fun isConnected(): Boolean {
if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnected")
return isServiceSet && rileyLinkMedtronicService.isInitialized
return isServiceSet && rileyLinkMedtronicService?.isInitialized == true
}
override fun isConnecting(): Boolean {
if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnecting")
return !isServiceSet || !rileyLinkMedtronicService.isInitialized
return !isServiceSet || rileyLinkMedtronicService?.isInitialized != true
}
override fun getPumpStatus(reason: String) {
@ -330,7 +330,7 @@ class MedtronicPumpPlugin @Inject constructor(
aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.")
return false
}
return !rileyLinkMedtronicService.deviceCommunicationManager.isDeviceReachable
return rileyLinkMedtronicService?.deviceCommunicationManager?.isDeviceReachable != true
}
private fun refreshAnyStatusThatNeedsToBeRefreshed() {
@ -369,13 +369,13 @@ class MedtronicPumpPlugin @Inject constructor(
}
MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> {
rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
refreshTypesNeededToReschedule.add(key)
resetTime = true
}
MedtronicStatusRefreshType.Configuration -> {
rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
resetTime = true
}
}
@ -406,7 +406,7 @@ class MedtronicPumpPlugin @Inject constructor(
private fun initializePump(): Boolean {
if (!isServiceSet) return false
aapsLogger.info(LTag.PUMP, logPrefix + "initializePump - start")
rileyLinkMedtronicService.deviceCommunicationManager.setDoWakeUpBeforeCommand(false)
rileyLinkMedtronicService?.deviceCommunicationManager?.setDoWakeUpBeforeCommand(false)
setRefreshButtonEnabled(false)
if (isRefresh) {
if (isPumpNotReachable) {
@ -420,7 +420,7 @@ class MedtronicPumpPlugin @Inject constructor(
// model (once)
if (!medtronicUtil.isModelSet) {
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.PumpModel)
} else {
if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) {
aapsLogger.warn(LTag.PUMP, logPrefix + "Configured pump is not the same as one detected.")
@ -434,19 +434,19 @@ class MedtronicPumpPlugin @Inject constructor(
readPumpHistory()
// remaining insulin (>50 = 4h; 50-20 = 1h; 15m)
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRemainingInsulin)
scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10)
// remaining power (1h)
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBatteryStatus)
scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20)
// configuration (once and then if history shows config changes)
rileyLinkMedtronicService.medtronicUIComm.executeCommand(getSettings(medtronicUtil.medtronicPumpModel))
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(getSettings(medtronicUtil.medtronicPumpModel))
// read profile (once, later its controlled by isThisProfileSet method)
basalProfiles
val errorCount = rileyLinkMedtronicService.medtronicUIComm.invalidResponsesCount
val errorCount = rileyLinkMedtronicService?.medtronicUIComm?.invalidResponsesCount ?: 0
if (errorCount >= 5) {
aapsLogger.error("Number of error counts was 5 or more. Starting tuning.")
setRefreshButtonEnabled(true)
@ -466,9 +466,9 @@ class MedtronicPumpPlugin @Inject constructor(
private val basalProfiles: Unit
get() {
val medtronicUITask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD)
if (medtronicUITask.responseType === MedtronicUIResponseType.Error) {
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD)
val medtronicUITask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBasalProfileSTD)
if (medtronicUITask?.responseType === MedtronicUIResponseType.Error) {
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBasalProfileSTD)
}
}
@ -558,10 +558,10 @@ class MedtronicPumpPlugin @Inject constructor(
return
}
medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus)
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRealTimeClock)
var clock = medtronicUtil.pumpTime
if (clock == null) { // retry
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRealTimeClock)
clock = medtronicUtil.pumpTime
}
if (clock == null) return
@ -569,7 +569,7 @@ class MedtronicPumpPlugin @Inject constructor(
if (timeDiff > 20) {
if (clock.localDeviceTime.year <= 2015 || timeDiff <= 24 * 60 * 60) {
aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Set time on pump.", timeDiff))
rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetRealTimeClock)
if (clock.timeDifference == 0) {
val notification = Notification(Notification.INSIGHT_DATE_TIME_UPDATED, rh.gs(R.string.pump_time_updated), Notification.INFO, 60)
rxBus.send(EventNewNotification(notification))
@ -619,9 +619,9 @@ class MedtronicPumpPlugin @Inject constructor(
bolusDeliveryType = BolusDeliveryType.Delivering
// LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery");
val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus,
val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetBolus,
arrayListOf(detailedBolusInfo.insulin))
val response = responseTask.result as Boolean?
val response = responseTask?.result as Boolean?
setRefreshButtonEnabled(true)
// LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response);
@ -639,8 +639,6 @@ class MedtronicPumpPlugin @Inject constructor(
}.start()
}
val now = System.currentTimeMillis()
detailedBolusInfo.timestamp = now
detailedBolusInfo.deliverAtTheLatest = now // not sure about that one
pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this)
@ -743,8 +741,8 @@ class MedtronicPumpPlugin @Inject constructor(
aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - TBR running - so canceling it.")
// CANCEL
val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR)
val response = responseTask2.result as Boolean?
val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.CancelTBR)
val response = responseTask2?.result as Boolean?
if (response == null || !response) {
aapsLogger.error(logPrefix + "setTempBasalAbsolute - Cancel TBR failed.")
finishAction("TBR")
@ -757,9 +755,9 @@ class MedtronicPumpPlugin @Inject constructor(
}
// now start new TBR
val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal,
val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetTemporaryBasal,
arrayListOf(absoluteRate, durationInMinutes))
val response = responseTask.result as Boolean?
val response = responseTask?.result as Boolean?
aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response)
return if (response == null || !response) {
finishAction("TBR")
@ -922,10 +920,10 @@ class MedtronicPumpPlugin @Inject constructor(
//aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate);
@Suppress("UNCHECKED_CAST")
val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData,
val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetHistoryData,
arrayListOf(/*lastPumpHistoryEntry*/ null, targetDate) as? ArrayList<Any>?)
if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task")
val historyResult = responseTask2.result as PumpHistoryResult?
val historyResult = responseTask2?.result as PumpHistoryResult?
if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString())
val latestEntry = historyResult!!.latestEntry
if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "Last entry: " + latestEntry)
@ -1018,8 +1016,8 @@ class MedtronicPumpPlugin @Inject constructor(
}
private fun readTBR(): TempBasalPair? {
val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal)
return if (responseTask.hasData()) {
val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.ReadTemporaryBasal)
return if (responseTask?.hasData() == true) {
val tbr = responseTask.result as TempBasalPair?
// we sometimes get rate returned even if TBR is no longer running
@ -1060,8 +1058,8 @@ class MedtronicPumpPlugin @Inject constructor(
return PumpEnactResult(injector).success(false).enacted(false)
.comment(R.string.medtronic_cmd_cant_read_tbr)
}
val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR)
val response = responseTask2.result as Boolean?
val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.CancelTBR)
val response = responseTask2?.result as Boolean?
finishAction("TBR")
return if (response == null || !response) {
aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR failed.")
@ -1145,9 +1143,9 @@ class MedtronicPumpPlugin @Inject constructor(
.enacted(false) //
.comment(rh.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid))
}
val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD,
val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetBasalProfileSTD,
arrayListOf(basalProfile))
val response = responseTask.result as Boolean?
val response = responseTask?.result as Boolean?
aapsLogger.info(LTag.PUMP, logPrefix + "Basal Profile was set: " + response)
return if (response == null || !response) {
PumpEnactResult(injector).success(false).enacted(false) //
@ -1203,7 +1201,7 @@ class MedtronicPumpPlugin @Inject constructor(
override fun executeCustomAction(customActionType: CustomActionType) {
when (customActionType as? MedtronicCustomActionType) {
MedtronicCustomActionType.WakeUpAndTune -> {
if (rileyLinkMedtronicService.verifyConfiguration()) {
if (rileyLinkMedtronicService?.verifyConfiguration() == true) {
serviceTaskExecutor.startTask(WakeAndTuneTask(injector))
} else {
runAlarm(context, rh.gs(R.string.medtronic_error_operation_not_possible_no_configuration), rh.gs(R.string.medtronic_warning), R.raw.boluserror)

View file

@ -148,7 +148,7 @@ class MedtronicUIPostprocessor @Inject constructor(
medtronicUtil.settings = settings
var checkValue: PumpSettingDTO
medtronicPumpPlugin.rileyLinkService.verifyConfiguration()
medtronicPumpPlugin.rileyLinkService?.verifyConfiguration()
// check profile
if (settings.containsKey("PCFG_BASAL_PROFILES_ENABLED") && settings.containsKey("PCFG_ACTIVE_BASAL_PROFILE")) {

View file

@ -58,7 +58,7 @@ class MedtronicPumpStatus @Inject constructor(private val rh: ResourceHelper,
if (medtronicDeviceTypeMap.isEmpty()) createMedtronicDeviceTypeMap()
lastConnection = sp.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L)
lastDataTime = lastConnection
var serial = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null)
val serial = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null)
if (serial != null) {
serialNumber = serial
}
@ -105,7 +105,7 @@ class MedtronicPumpStatus @Inject constructor(private val rh: ResourceHelper,
private var batteryTypeByDescMap: MutableMap<String, BatteryType?> = HashMap()
fun getBatteryTypeByDescription(batteryTypeStr: String?): BatteryType? {
if (batteryTypeByDescMap.size == 0) {
if (batteryTypeByDescMap.isEmpty()) {
for (value in BatteryType.values()) {
batteryTypeByDescMap[rh.gs(value.description)] = value
}

View file

@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

View file

@ -30,8 +30,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(
) : OmnipodDashBleManager {
private val busy = AtomicBoolean(false)
private val bluetoothAdapter: BluetoothAdapter?
get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private var connection: Connection? = null
private val ids = Ids(podState)

View file

@ -53,8 +53,7 @@ class Connection(
private val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets, this)
private var gattConnection: BluetoothGatt? = null
private val bluetoothManager: BluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
private val bluetoothManager: BluetoothManager? = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
@Volatile
var session: Session? = null
@ -67,8 +66,7 @@ class Connection(
podState.connectionAttempts++
podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING
val autoConnect = false
val gatt = gattConnection
?: podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE)
val gatt = gattConnection ?: podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE)
gattConnection = gatt
if (!gatt.connect()) {
throw FailedToConnectException("connect() returned false")
@ -150,7 +148,7 @@ class Connection(
}
fun connectionState(): ConnectionState {
val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT)
val connectionState = bluetoothManager?.getConnectionState(podDevice, BluetoothProfile.GATT)
aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState")
if (connectionState != BluetoothProfile.STATE_CONNECTED) {
return NotConnected

View file

@ -1,5 +1,17 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation
import android.os.Bundle
import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.PodActivationWizardActivity
import javax.inject.Inject
class DashPodActivationWizardActivity : PodActivationWizardActivity()
class DashPodActivationWizardActivity : PodActivationWizardActivity() {
@Inject lateinit var blePreCheck: BlePreCheck
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
blePreCheck.prerequisitesCheck(this)
}
}

View file

@ -4,9 +4,7 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.text.format.DateFormat
import com.google.gson.GsonBuilder
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.events.EventAppExit
@ -16,20 +14,21 @@ import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.extensions.toStringFull
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal
import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import org.json.JSONException
@ -74,8 +73,6 @@ abstract class PumpPluginAbstract protected constructor(
pumpDescription.fillFor(value)
}
protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
abstract fun initPumpStatusData()
override fun onStart() {
@ -85,9 +82,9 @@ abstract class PumpPluginAbstract protected constructor(
context.bindService(intent, serviceConnection!!, Context.BIND_AUTO_CREATE)
serviceRunning = true
disposable.add(rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ _ -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) }
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ _ -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) }
)
onStartCustomActions()
}
@ -113,17 +110,9 @@ abstract class PumpPluginAbstract protected constructor(
abstract val serviceClass: Class<*>?
abstract val pumpStatusData: PumpStatus
override fun isInitialized(): Boolean {
return pumpState.isInitialized()
}
override fun isSuspended(): Boolean {
return pumpState === PumpDriverState.Suspended
}
override fun isBusy(): Boolean {
return pumpState === PumpDriverState.Busy
}
override fun isInitialized(): Boolean = pumpState.isInitialized()
override fun isSuspended(): Boolean = pumpState == PumpDriverState.Suspended
override fun isBusy(): Boolean = pumpState == PumpDriverState.Busy
override fun isConnected(): Boolean {
if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "isConnected [PumpPluginAbstract].")
@ -335,10 +324,9 @@ abstract class PumpPluginAbstract protected constructor(
// bolus needed, ask pump to deliver it
deliverBolus(detailedBolusInfo)
} else {
detailedBolusInfo.timestamp = System.currentTimeMillis()
// no bolus required, carb only treatment
pumpSyncStorage.addCarbs(info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs(detailedBolusInfo, this))
pumpSyncStorage.addCarbs(PumpDbEntryCarbs(detailedBolusInfo, this))
val bolusingEvent = EventOverviewBolusProgress
bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB)
@ -357,25 +345,16 @@ abstract class PumpPluginAbstract protected constructor(
rxBus.send(EventCustomActionsChanged())
}
override fun manufacturer(): ManufacturerType {
return pumpType.manufacturer!!
}
override fun model(): PumpType {
return pumpType
}
override fun canHandleDST(): Boolean {
return false
}
override fun manufacturer(): ManufacturerType = pumpType.manufacturer!!
override fun model(): PumpType = pumpType
override fun canHandleDST(): Boolean = false
protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult
protected abstract fun triggerUIChange()
private fun getOperationNotSupportedWithCustomText(resourceId: Int): PumpEnactResult {
return PumpEnactResult(injector).success(false).enacted(false).comment(resourceId)
}
private fun getOperationNotSupportedWithCustomText(resourceId: Int): PumpEnactResult =
PumpEnactResult(injector).success(false).enacted(false).comment(resourceId)
init {
pumpDescription.fillFor(pumpType)

View file

@ -3,12 +3,15 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
<application>
<activity android:name="info.nightscout.androidaps.plugins.pump.common.dialog.RileyLinkBLEConfigActivity">
<intent-filter>

View file

@ -42,7 +42,8 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
private val gattDebugEnabled = true
private var manualDisconnect = false
val bluetoothAdapter: BluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
private val bluetoothGattCallback: BluetoothGattCallback
var rileyLinkDevice: BluetoothDevice? = null
private var bluetoothConnectionGatt: BluetoothGatt? = null
@ -128,7 +129,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Start scan for OrangeLink device.")
orangeLink.startScan()
} else {
rileyLinkDevice = bluetoothAdapter.getRemoteDevice(rileyLinkAddress)
rileyLinkDevice = bluetoothAdapter?.getRemoteDevice(rileyLinkAddress)
// if this succeeds, we get a connection state change callback?
if (rileyLinkDevice != null) connectGattInternal()
else aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device not found with address: $rileyLinkAddress")
@ -155,7 +156,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback)
// , BluetoothDevice.TRANSPORT_LE
if (bluetoothConnectionGatt == null)
aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter.address)
aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter?.address)
else {
if (gattDebugEnabled) aapsLogger.debug(LTag.PUMPBTCOMM, "Gatt Connected.")
val deviceName = bluetoothConnectionGatt?.device?.name
@ -361,7 +362,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (status == BluetoothGatt.GATT_SUCCESS) rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected, context)
else aapsLogger.debug(LTag.PUMPBTCOMM, "BT State connected, GATT status ${status} (${getGattStatusMessage(status)})")
else aapsLogger.debug(LTag.PUMPBTCOMM, "BT State connected, GATT status $status (${getGattStatusMessage(status)})")
} else if (newState == BluetoothProfile.STATE_CONNECTING || newState == BluetoothProfile.STATE_DISCONNECTING) {
aapsLogger.debug(LTag.PUMPBTCOMM, "We are in ${if (status == BluetoothProfile.STATE_CONNECTING) "Connecting" else "Disconnecting"} state.")
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {

View file

@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.device
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
@ -10,14 +9,14 @@ import android.bluetooth.le.ScanSettings
import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.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.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import java.util.*
import javax.inject.Inject
@ -37,10 +36,7 @@ class OrangeLinkImpl @Inject constructor(
if (characteristic.uuid.toString() == 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
)
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
@ -60,9 +56,8 @@ class OrangeLinkImpl @Inject constructor(
* We are checking if this is special Orange (with ORANGE_NOTIFICATION_SERVICE)
*/
fun checkIsOrange(uuidService: UUID) {
if (GattAttributes.isOrange(uuidService)) {
if (GattAttributes.isOrange(uuidService))
rileyLinkServiceData.isOrange = true
}
}
fun enableNotifications(): Boolean {
@ -98,15 +93,14 @@ class OrangeLinkImpl @Inject constructor(
fun startScan() {
try {
stopScan()
val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter
aapsLogger.debug(LTag.PUMPBTCOMM, "startScan")
handler.sendEmptyMessageDelayed(TIME_OUT_WHAT, TIME_OUT.toLong())
val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
val bluetoothLeScanner = rileyLinkBLE.bluetoothAdapter?.bluetoothLeScanner
// if (bluetoothLeScanner == null) {
// bluetoothAdapter.startLeScan(mLeScanCallback)
// return
// }
bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), scanCallback)
bluetoothLeScanner?.startScan(buildScanFilters(), buildScanSettings(), scanCallback)
} catch (e: Exception) {
e.printStackTrace()
aapsLogger.error(LTag.PUMPBTCOMM, "Start scan: ${e.message}", e)
@ -135,15 +129,6 @@ class OrangeLinkImpl @Inject constructor(
}
}
/*
private val mLeScanCallback = LeScanCallback { device, _, _ ->
if (rileyLinkServiceData.rileyLinkAddress.equals(device.address)) {
stopScan()
rileyLinkBLE.rileyLinkDevice = device
rileyLinkBLE.connectGattInternal()
}
}
*/
private val handler: Handler = object : Handler(HandlerThread(this::class.java.simpleName + "Handler").also { it.start() }.looper) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
@ -156,35 +141,17 @@ class OrangeLinkImpl @Inject constructor(
fun stopScan() {
handler.removeMessages(TIME_OUT_WHAT)
val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter
try {
val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
if (isBluetoothAvailable())
rileyLinkBLE.bluetoothAdapter?.bluetoothLeScanner?.stopScan(scanCallback)
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)
}
}
private fun isBluetoothAvailable(): Boolean {
val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter
return bluetoothAdapter.isEnabled && bluetoothAdapter.state == BluetoothAdapter.STATE_ON
}
private fun isBluetoothAvailable(): Boolean =
rileyLinkBLE.bluetoothAdapter?.isEnabled == true && rileyLinkBLE.bluetoothAdapter?.state == BluetoothAdapter.STATE_ON
companion object {

View file

@ -5,6 +5,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service;
*/
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -134,7 +135,7 @@ public class RileyLinkBroadcastReceiver extends DaggerBroadcastReceiver {
RileyLinkService rileyLinkService = getServiceInstance();
if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
if (((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().isEnabled()) {
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable);
} else {
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);