Added MedtrumService
This commit is contained in:
parent
b635ad26d8
commit
baa4376f68
|
@ -54,7 +54,7 @@ import info.nightscout.plugins.sync.xdrip.XdripPlugin
|
|||
import info.nightscout.pump.combo.ComboPlugin
|
||||
import info.nightscout.pump.combov2.ComboV2Plugin
|
||||
import info.nightscout.pump.diaconn.DiaconnG8Plugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPumpPlugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPlugin
|
||||
import info.nightscout.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventPreferenceChange
|
||||
|
@ -123,7 +123,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
@Inject lateinit var wearPlugin: WearPlugin
|
||||
@Inject lateinit var maintenancePlugin: MaintenancePlugin
|
||||
@Inject lateinit var eopatchPumpPlugin: EopatchPumpPlugin
|
||||
@Inject lateinit var medtrumPumpPlugin: MedtrumPumpPlugin
|
||||
@Inject lateinit var MedtrumPlugin: MedtrumPlugin
|
||||
|
||||
@Inject lateinit var passwordCheck: PasswordCheck
|
||||
@Inject lateinit var nsSettingStatus: NSSettingsStatus
|
||||
|
@ -214,7 +214,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(diaconnG8Plugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(eopatchPumpPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(medtrumPumpPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(MedtrumPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResource(R.xml.pref_pump, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey)
|
||||
|
|
|
@ -31,9 +31,9 @@ import info.nightscout.pump.common.di.PumpCommonModule
|
|||
import info.nightscout.pump.dana.di.DanaHistoryModule
|
||||
import info.nightscout.pump.dana.di.DanaModule
|
||||
import info.nightscout.pump.danars.di.DanaRSModule
|
||||
import info.nightscout.pump.medtrum.di.MedtrumModule
|
||||
import info.nightscout.pump.diaconn.di.DiaconnG8Module
|
||||
import info.nightscout.pump.virtual.di.VirtualPumpModule
|
||||
import info.nightscout.pump.medtrum.di.MedtrumPumpModule
|
||||
import info.nightscout.rx.di.RxModule
|
||||
import info.nightscout.shared.di.SharedModule
|
||||
import info.nightscout.shared.impl.di.SharedImplModule
|
||||
|
@ -88,7 +88,7 @@ import javax.inject.Singleton
|
|||
OmnipodErosModule::class,
|
||||
PumpCommonModule::class,
|
||||
RileyLinkModule::class,
|
||||
MedtrumPumpModule::class,
|
||||
MedtrumModule::class,
|
||||
VirtualPumpModule::class
|
||||
]
|
||||
)
|
||||
|
|
|
@ -46,7 +46,7 @@ import info.nightscout.plugins.sync.tidepool.TidepoolPlugin
|
|||
import info.nightscout.plugins.sync.xdrip.XdripPlugin
|
||||
import info.nightscout.pump.combo.ComboPlugin
|
||||
import info.nightscout.pump.combov2.ComboV2Plugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPumpPlugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPlugin
|
||||
import info.nightscout.pump.diaconn.DiaconnG8Plugin
|
||||
import info.nightscout.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.sensitivity.SensitivityAAPSPlugin
|
||||
|
@ -214,7 +214,7 @@ abstract class PluginsListModule {
|
|||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(160)
|
||||
abstract fun bindMedtrumPumpPlugin(plugin: MedtrumPumpPlugin): PluginBase
|
||||
abstract fun bindMedtrumPlugin(plugin: MedtrumPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
<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>
|
||||
<service
|
||||
android:name=".services.MedtrumService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,6 +1,12 @@
|
|||
package info.nightscout.pump.medtrum
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.core.ui.toast.ToastUtils
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.interfaces.plugin.PluginDescription
|
||||
import info.nightscout.interfaces.plugin.PluginType
|
||||
|
@ -21,33 +27,38 @@ import info.nightscout.interfaces.queue.CustomCommand
|
|||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.interfaces.utils.TimeChangeType
|
||||
import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment
|
||||
import info.nightscout.pump.medtrum.services.MedtrumService
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventAppExit
|
||||
import info.nightscout.rx.events.EventAppInitialized
|
||||
import info.nightscout.rx.events.EventOverviewBolusProgress
|
||||
import info.nightscout.rx.events.EventPreferenceChange
|
||||
import info.nightscout.rx.logging.AAPSLogger
|
||||
import info.nightscout.rx.logging.LTag
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.shared.utils.DateUtil
|
||||
import info.nightscout.shared.utils.T
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@Singleton
|
||||
class MedtrumPumpPlugin @Inject constructor(
|
||||
class MedtrumPlugin @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
rh: ResourceHelper,
|
||||
commandQueue: CommandQueue,
|
||||
private val sp: SP,
|
||||
private val aapsSchedulers: AapsSchedulers,
|
||||
private val rxBus: RxBus,
|
||||
private val context: Context,
|
||||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val dateUtil: DateUtil,
|
||||
private val pumpSync: PumpSync,
|
||||
|
@ -55,7 +66,7 @@ class MedtrumPumpPlugin @Inject constructor(
|
|||
private val profileFunction: ProfileFunction
|
||||
) : PumpPluginBase(
|
||||
PluginDescription()
|
||||
.mainType(PluginType.PUMP) // TODO Prefs etc
|
||||
.mainType(PluginType.PUMP)
|
||||
.fragmentClass(MedtrumPumpFragment::class.java.name)
|
||||
.pluginIcon(info.nightscout.core.ui.R.drawable.ic_eopatch2_128) // TODO
|
||||
.pluginName(R.string.medtrum)
|
||||
|
@ -64,16 +75,51 @@ class MedtrumPumpPlugin @Inject constructor(
|
|||
.description(R.string.medtrum_pump_description), injector, aapsLogger, rh, commandQueue
|
||||
), Pump {
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private var medtrumService: MedtrumService? = null
|
||||
private var mPumpType: PumpType = PumpType.MEDTRUM_NANO
|
||||
private val mPumpDescription = PumpDescription(mPumpType)
|
||||
private var mDeviceSN: Long = 0
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
aapsLogger.debug(LTag.PUMP, "MedtrumPlugin onStart()")
|
||||
val intent = Intent(context, MedtrumService::class.java)
|
||||
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAppExit::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ context.unbindService(mConnection) }, fabricPrivacy::logException)
|
||||
changePump()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
aapsLogger.debug(LTag.PUMP, "MedtrumPlugin onStop()")
|
||||
context.unbindService(mConnection)
|
||||
disposable.clear()
|
||||
super.onStop()
|
||||
aapsLogger.debug(LTag.PUMP, "MedtrumPumpPlugin onStop()")
|
||||
}
|
||||
|
||||
private val mConnection: ServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceDisconnected(name: ComponentName) {
|
||||
aapsLogger.debug(LTag.PUMP, "Service is disconnected")
|
||||
medtrumService = null
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
aapsLogger.debug(LTag.PUMP, "Service is connected")
|
||||
val mLocalBinder = service as MedtrumService.LocalBinder
|
||||
medtrumService = mLocalBinder.serviceInstance
|
||||
}
|
||||
}
|
||||
|
||||
fun changePump() { // TODO: Call this on inputfield change?
|
||||
try {
|
||||
mDeviceSN = sp.getString(info.nightscout.pump.medtrum.R.string.key_snInput, " ").toLong(radix = 16)
|
||||
commandQueue.readStatus(rh.gs(info.nightscout.core.ui.R.string.device_changed), null)
|
||||
} catch (e: NumberFormatException) {
|
||||
aapsLogger.debug(LTag.PUMP, "changePump: invalid input!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun isInitialized(): Boolean {
|
||||
|
@ -88,33 +134,35 @@ class MedtrumPumpPlugin @Inject constructor(
|
|||
return false
|
||||
}
|
||||
|
||||
override fun isConnected(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isConnecting(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isHandshakeInProgress(): Boolean {
|
||||
return false
|
||||
}
|
||||
override fun isConnected(): Boolean = medtrumService?.isConnected ?: false
|
||||
override fun isConnecting(): Boolean = medtrumService?.isConnecting ?: false
|
||||
override fun isHandshakeInProgress(): Boolean = false
|
||||
|
||||
override fun finishHandshaking() {
|
||||
}
|
||||
|
||||
override fun connect(reason: String) {
|
||||
aapsLogger.debug(LTag.PUMP, "Medtrum connect - reason:$reason")
|
||||
aapsLogger.debug(LTag.PUMP, "Medtrum connect - service::$medtrumService")
|
||||
aapsLogger.debug(LTag.PUMP, "Medtrum connect - mDeviceSN:$mDeviceSN")
|
||||
if (medtrumService != null && mDeviceSN != 0.toLong()) {
|
||||
aapsLogger.debug(LTag.PUMP, "Medtrum connect - Attempt connection!")
|
||||
val success = medtrumService?.connect(reason, mDeviceSN) ?: false
|
||||
if (!success) ToastUtils.errorToast(context, info.nightscout.core.ui.R.string.ble_not_supported_or_not_paired)
|
||||
}
|
||||
}
|
||||
|
||||
override fun disconnect(reason: String) {
|
||||
aapsLogger.debug(LTag.PUMP, "Medtrum disconnect - reason:$reason")
|
||||
aapsLogger.debug(LTag.PUMP, "RS disconnect from: $reason")
|
||||
medtrumService?.disconnect(reason)
|
||||
}
|
||||
|
||||
override fun stopConnecting() {
|
||||
medtrumService?.stopConnecting()
|
||||
}
|
||||
|
||||
override fun getPumpStatus(reason: String) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
|
||||
|
@ -177,7 +225,7 @@ class MedtrumPumpPlugin @Inject constructor(
|
|||
}
|
||||
|
||||
override fun model(): PumpType {
|
||||
return mPumpType
|
||||
return mPumpType
|
||||
}
|
||||
|
||||
override fun serialNumber(): String {
|
|
@ -14,15 +14,15 @@ class ManufacturerData(private val manufacturerDataBytes: ByteArray) {
|
|||
|
||||
fun setData(inputData: ByteArray) {
|
||||
var index = 0
|
||||
val deviceIDBytes: ByteArray = manufacturerDataBytes.copyOfRange(index, index + 4)
|
||||
val deviceIDBytes: ByteArray = inputData.copyOfRange(index, index + 4)
|
||||
deviceID = deviceIDBytes.toLong()
|
||||
index += 4
|
||||
deviceType = (manufacturerDataBytes[index] and 0xff.toByte()).toInt()
|
||||
deviceType = (inputData[index] and 0xff.toByte()).toInt()
|
||||
index += 1
|
||||
version = (manufacturerDataBytes[index] and 0xff.toByte()).toInt()
|
||||
version = (inputData[index] and 0xff.toByte()).toInt()
|
||||
}
|
||||
|
||||
fun getDeviceID(): Long{
|
||||
fun getDeviceSN(): Long{
|
||||
return deviceID
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package info.nightscout.pump.medtrum.di
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class MedtrumPumpModule {
|
||||
abstract class MedtrumActivitiesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesMedtrumPumpFragment(): MedtrumPumpFragment
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package info.nightscout.pump.medtrum.di
|
||||
|
||||
import dagger.Module
|
||||
|
||||
@Module(includes = [
|
||||
MedtrumActivitiesModule::class,
|
||||
MedtrumServicesModule::class
|
||||
])
|
||||
open class MedtrumModule
|
|
@ -0,0 +1,11 @@
|
|||
package info.nightscout.pump.medtrum.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.pump.medtrum.services.MedtrumService
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class MedtrumServicesModule {
|
||||
@ContributesAndroidInjector abstract fun contributesDanaRSService(): MedtrumService
|
||||
}
|
|
@ -79,7 +79,7 @@ class BLEComm @Inject internal constructor(
|
|||
var isConnecting = false
|
||||
private var uartWrite: BluetoothGattCharacteristic? = null
|
||||
|
||||
private var deviceID: Long = 0
|
||||
private var mDeviceSN: Long = 0
|
||||
|
||||
/** Connect flow: 1. Start scanning for our device (SN entered in settings) */
|
||||
@SuppressLint("MissingPermission")
|
||||
|
@ -98,7 +98,6 @@ class BLEComm @Inject internal constructor(
|
|||
.build()
|
||||
val filters = mutableListOf<ScanFilter>()
|
||||
|
||||
if (deviceID == 0.toLong()) deviceID = rh.gs(info.nightscout.pump.medtrum.R.string.key_snInput).toLong(radix = 16)
|
||||
|
||||
isConnected = false
|
||||
// TODO: Maybe replace this by (or add) a isScanning parameter?
|
||||
|
@ -119,17 +118,43 @@ class BLEComm @Inject internal constructor(
|
|||
mBluetoothAdapter?.bluetoothLeScanner?.stopScan(mScanCallback)
|
||||
}
|
||||
|
||||
fun connect(from: String, deviceSN: Long): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
||||
ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ToastUtils.errorToast(context, context.getString(info.nightscout.core.ui.R.string.need_connect_permission))
|
||||
aapsLogger.error(LTag.PUMPBTCOMM, "missing permission: $from")
|
||||
return false
|
||||
}
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing BLEComm.")
|
||||
if (mBluetoothAdapter == null) {
|
||||
aapsLogger.error("Unable to obtain a BluetoothAdapter.")
|
||||
return false
|
||||
}
|
||||
mDeviceSN = deviceSN
|
||||
isConnecting = true
|
||||
startScan()
|
||||
return true
|
||||
}
|
||||
|
||||
/** Connect flow: 2. When device is found this is called by onScanResult() */
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
fun connect(device: BluetoothDevice) {
|
||||
fun connectGatt(device: BluetoothDevice) {
|
||||
mBluetoothGatt =
|
||||
device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
fun disconnect() {
|
||||
fun disconnect(from: String) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
||||
ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
aapsLogger.error(LTag.PUMPBTCOMM, "missing permission: $from")
|
||||
return
|
||||
}
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "disconnect from: $from")
|
||||
mBluetoothGatt?.disconnect()
|
||||
mBluetoothGatt = null
|
||||
}
|
||||
|
@ -156,11 +181,12 @@ class BLEComm @Inject internal constructor(
|
|||
result.scanRecord?.getManufacturerSpecificData(MANUFACTURER_ID)
|
||||
?.let { ManufacturerData(it) }
|
||||
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Found DeviceID: " + manufacturerData?.getDeviceID())
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Found deviceSN: " + manufacturerData?.getDeviceSN())
|
||||
|
||||
if (manufacturerData?.getDeviceID() == deviceID) {
|
||||
if (manufacturerData?.getDeviceSN() == mDeviceSN) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Found our device! deviceSN: " + manufacturerData.getDeviceSN())
|
||||
stopScan()
|
||||
connect(result.device)
|
||||
connectGatt(result.device)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,170 +256,166 @@ class BLEComm @Inject internal constructor(
|
|||
checkDescriptor(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun readDescriptor(descriptor: BluetoothGattDescriptor?) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "readDescriptor")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || descriptor == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
mBluetoothGatt?.readDescriptor(descriptor)
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun readDescriptor(descriptor: BluetoothGattDescriptor?) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "readDescriptor")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || descriptor == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
mBluetoothGatt?.readDescriptor(descriptor)
|
||||
}
|
||||
|
||||
private fun checkDescriptor(descriptor: BluetoothGattDescriptor) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor")
|
||||
val service = getGattService()
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
if (descriptor.value.toInt() > 0) {
|
||||
var notificationEnabled = true
|
||||
val characteristics = service.characteristics
|
||||
for (j in 0 until characteristics.size) {
|
||||
val configDescriptor =
|
||||
characteristics[j].getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG_UUID))
|
||||
if (configDescriptor.value == null || configDescriptor.value.toInt() <= 0) {
|
||||
notificationEnabled = false
|
||||
}
|
||||
}
|
||||
if (notificationEnabled) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Notifications enabled!")
|
||||
authorize()
|
||||
@Suppress("DEPRECATION")
|
||||
private fun checkDescriptor(descriptor: BluetoothGattDescriptor) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor")
|
||||
val service = getGattService()
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
if (descriptor.value.toInt() > 0) {
|
||||
var notificationEnabled = true
|
||||
val characteristics = service.characteristics
|
||||
for (j in 0 until characteristics.size) {
|
||||
val configDescriptor =
|
||||
characteristics[j].getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG_UUID))
|
||||
if (configDescriptor.value == null || configDescriptor.value.toInt() <= 0) {
|
||||
notificationEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun setCharacteristicNotification(characteristic: BluetoothGattCharacteristic?, enabled: Boolean) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "setCharacteristicNotification")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
mBluetoothGatt?.setCharacteristicNotification(characteristic, enabled)
|
||||
characteristic?.getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG_UUID))?.let {
|
||||
if (characteristic.properties and 0x10 > 0) {
|
||||
it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
mBluetoothGatt?.writeDescriptor(it)
|
||||
} else if (characteristic.properties and 0x20 > 0) {
|
||||
it.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
||||
mBluetoothGatt?.writeDescriptor(it)
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Connect flow: 3. When we are connected discover services*/
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun onConnectionStateChangeSynchronized(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "onConnectionStateChange newState: " + newState + " status: " + status)
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
gatt.discoverServices()
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
close()
|
||||
isConnected = false
|
||||
isConnecting = false
|
||||
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED))
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected
|
||||
disconnect()
|
||||
startScan()
|
||||
}
|
||||
}
|
||||
|
||||
private fun readDataParsing(receivedData: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<readDataParsing>>> " + Arrays.toString(receivedData))
|
||||
// TODO
|
||||
/** Connect flow: 6. Authorized */ // TODO place this at the correct place
|
||||
}
|
||||
|
||||
private fun authorize() {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Start auth!")
|
||||
val role = 2 // Fixed to 2 for pump
|
||||
val key = mCrypt.keyGen(deviceID)
|
||||
val commandData = byteArrayOf(COMMAND_AUTH_REQ) + byteArrayOf(role.toByte()) + 0.toByteArray(4) + key.toByteArray(4)
|
||||
sendMessage(commandData)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun sendMessage(message: ByteArray) {
|
||||
// TODO: Handle packages which consist of multiple, Create a queue of packages
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
|
||||
val writePacket = WriteCommandPackets(message)
|
||||
val value: ByteArray? = writePacket.getNextPacket()
|
||||
|
||||
// TODO: queue
|
||||
writeCharacteristic(uartWriteBTGattChar, value)
|
||||
}
|
||||
|
||||
private fun getGattService(): BluetoothGattService? {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattService")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return null
|
||||
}
|
||||
return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID))
|
||||
}
|
||||
|
||||
private fun getGattCharacteristic(uuid: UUID): BluetoothGattCharacteristic? {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattCharacteristic $uuid")
|
||||
val service = getGattService()
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return null
|
||||
}
|
||||
return service.getCharacteristic(uuid)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun writeCharacteristic(characteristic: BluetoothGattCharacteristic, data: ByteArray?) {
|
||||
Thread(Runnable {
|
||||
SystemClock.sleep(WRITE_DELAY_MILLIS)
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return@Runnable
|
||||
}
|
||||
characteristic.value = data
|
||||
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
aapsLogger.debug("writeCharacteristic:" + Arrays.toString(data))
|
||||
mBluetoothGatt?.writeCharacteristic(characteristic)
|
||||
}).start()
|
||||
SystemClock.sleep(WRITE_DELAY_MILLIS)
|
||||
}
|
||||
|
||||
private val uartWriteBTGattChar: BluetoothGattCharacteristic
|
||||
get() = uartWrite
|
||||
?: BluetoothGattCharacteristic(UUID.fromString(WRITE_UUID), BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT, 0).also { uartWrite = it }
|
||||
|
||||
/** Connect flow: 4. When services are discovered find characteristics and set notifications*/
|
||||
private fun findCharacteristic() {
|
||||
val gattService = getGattService() ?: return
|
||||
val gattCharacteristics = gattService.characteristics
|
||||
for (gattCharacteristic in gattCharacteristics) {
|
||||
setCharacteristicNotification(gattCharacteristic, true)
|
||||
if (notificationEnabled) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Notifications enabled!")
|
||||
authorize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun setCharacteristicNotification(characteristic: BluetoothGattCharacteristic?, enabled: Boolean) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "setCharacteristicNotification")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return
|
||||
}
|
||||
mBluetoothGatt?.setCharacteristicNotification(characteristic, enabled)
|
||||
characteristic?.getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG_UUID))?.let {
|
||||
if (characteristic.properties and 0x10 > 0) {
|
||||
it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
mBluetoothGatt?.writeDescriptor(it)
|
||||
} else if (characteristic.properties and 0x20 > 0) {
|
||||
it.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
||||
mBluetoothGatt?.writeDescriptor(it)
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Connect flow: 3. When we are connected discover services*/
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun onConnectionStateChangeSynchronized(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "onConnectionStateChange newState: " + newState + " status: " + status)
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
gatt.discoverServices()
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
close()
|
||||
isConnected = false
|
||||
isConnecting = false
|
||||
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED))
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected
|
||||
}
|
||||
}
|
||||
|
||||
private fun readDataParsing(receivedData: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<readDataParsing>>> " + Arrays.toString(receivedData))
|
||||
// TODO
|
||||
/** Connect flow: 6. Authorized */ // TODO place this at the correct place
|
||||
}
|
||||
|
||||
private fun authorize() {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Start auth!")
|
||||
val role = 2 // Fixed to 2 for pump
|
||||
val key = mCrypt.keyGen(mDeviceSN)
|
||||
val commandData = byteArrayOf(COMMAND_AUTH_REQ) + byteArrayOf(role.toByte()) + 0.toByteArray(4) + key.toByteArray(4)
|
||||
sendMessage(commandData)
|
||||
}
|
||||
|
||||
fun sendMessage(message: ByteArray) {
|
||||
// TODO: Handle packages which consist of multiple, Create a queue of packages
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
|
||||
val writePacket = WriteCommandPackets(message)
|
||||
val value: ByteArray? = writePacket.getNextPacket()
|
||||
|
||||
// TODO: queue
|
||||
writeCharacteristic(uartWriteBTGattChar, value)
|
||||
}
|
||||
|
||||
private fun getGattService(): BluetoothGattService? {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattService")
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return null
|
||||
}
|
||||
return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID))
|
||||
}
|
||||
|
||||
private fun getGattCharacteristic(uuid: UUID): BluetoothGattCharacteristic? {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattCharacteristic $uuid")
|
||||
val service = getGattService()
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return null
|
||||
}
|
||||
return service.getCharacteristic(uuid)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
private fun writeCharacteristic(characteristic: BluetoothGattCharacteristic, data: ByteArray?) {
|
||||
Thread(Runnable {
|
||||
SystemClock.sleep(WRITE_DELAY_MILLIS)
|
||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
||||
isConnecting = false
|
||||
isConnected = false
|
||||
return@Runnable
|
||||
}
|
||||
characteristic.value = data
|
||||
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
aapsLogger.debug("writeCharacteristic:" + Arrays.toString(data))
|
||||
mBluetoothGatt?.writeCharacteristic(characteristic)
|
||||
}).start()
|
||||
SystemClock.sleep(WRITE_DELAY_MILLIS)
|
||||
}
|
||||
|
||||
private val uartWriteBTGattChar: BluetoothGattCharacteristic
|
||||
get() = uartWrite
|
||||
?: BluetoothGattCharacteristic(UUID.fromString(WRITE_UUID), BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT, 0).also { uartWrite = it }
|
||||
|
||||
/** Connect flow: 4. When services are discovered find characteristics and set notifications*/
|
||||
private fun findCharacteristic() {
|
||||
val gattService = getGattService() ?: return
|
||||
val gattCharacteristics = gattService.characteristics
|
||||
for (gattCharacteristic in gattCharacteristics) {
|
||||
setCharacteristicNotification(gattCharacteristic, true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
package info.nightscout.pump.medtrum.services
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.os.SystemClock
|
||||
import dagger.android.DaggerService
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.constraints.Constraints
|
||||
import info.nightscout.interfaces.notifications.Notification
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.profile.Profile
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.interfaces.pump.BolusProgressData
|
||||
import info.nightscout.interfaces.pump.PumpEnactResult
|
||||
import info.nightscout.interfaces.pump.PumpSync
|
||||
import info.nightscout.interfaces.queue.Callback
|
||||
import info.nightscout.interfaces.queue.Command
|
||||
import info.nightscout.interfaces.queue.CommandQueue
|
||||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.pump.medtrum.MedtrumPlugin
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventAppExit
|
||||
import info.nightscout.rx.events.EventInitializationChanged
|
||||
import info.nightscout.rx.events.EventOverviewBolusProgress
|
||||
import info.nightscout.rx.events.EventProfileSwitchChanged
|
||||
import info.nightscout.rx.events.EventPumpStatusChanged
|
||||
import info.nightscout.rx.logging.AAPSLogger
|
||||
import info.nightscout.rx.logging.LTag
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.shared.utils.DateUtil
|
||||
import info.nightscout.shared.utils.T
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
class MedtrumService : DaggerService() {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var commandQueue: CommandQueue
|
||||
@Inject lateinit var context: Context
|
||||
@Inject lateinit var medtrumPlugin: MedtrumPlugin
|
||||
@Inject lateinit var activePlugin: ActivePlugin
|
||||
@Inject lateinit var constraintChecker: Constraints
|
||||
@Inject lateinit var uiInteraction: UiInteraction
|
||||
@Inject lateinit var bleComm: BLEComm
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var pumpSync: PumpSync
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private val mBinder: IBinder = LocalBinder()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
disposable += rxBus
|
||||
.toObservable(EventAppExit::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ stopSelf() }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
disposable.clear()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
val isConnected: Boolean
|
||||
get() = bleComm.isConnected
|
||||
|
||||
val isConnecting: Boolean
|
||||
get() = bleComm.isConnecting
|
||||
|
||||
fun connect(from: String, deviceSN: Long): Boolean {
|
||||
// TODO Check we might want to replace this with start scan?
|
||||
return bleComm.connect(from, deviceSN)
|
||||
}
|
||||
|
||||
fun stopConnecting() {
|
||||
bleComm.stopConnecting()
|
||||
}
|
||||
|
||||
fun disconnect(from: String) {
|
||||
bleComm.disconnect(from)
|
||||
}
|
||||
|
||||
fun sendMessage(message: ByteArray) { // TODO Check what we use here?
|
||||
// TODO
|
||||
bleComm.sendMessage(message)
|
||||
}
|
||||
|
||||
fun readPumpStatus() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fun loadEvents(): PumpEnactResult {
|
||||
if (!medtrumPlugin.isInitialized()) {
|
||||
val result = PumpEnactResult(injector).success(false)
|
||||
result.comment = "pump not initialized"
|
||||
return result
|
||||
}
|
||||
// TODO need this? Check
|
||||
val result = PumpEnactResult(injector)
|
||||
return result
|
||||
}
|
||||
|
||||
fun setUserSettings(): PumpEnactResult {
|
||||
// TODO need this? Check
|
||||
val result = PumpEnactResult(injector)
|
||||
return result
|
||||
}
|
||||
|
||||
fun bolus(insulin: Double, carbs: Int, carbTime: Long, t: EventOverviewBolusProgress.Treatment): Boolean {
|
||||
if (!isConnected) return false
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun bolusStop() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fun tempBasal(percent: Int, durationInHours: Int): Boolean {
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun highTempBasal(percent: Int): Boolean {
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun tempBasalShortDuration(percent: Int, durationInMinutes: Int): Boolean {
|
||||
if (durationInMinutes != 15 && durationInMinutes != 30) {
|
||||
aapsLogger.error(LTag.PUMPCOMM, "Wrong duration param")
|
||||
return false
|
||||
}
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun tempBasalStop(): Boolean {
|
||||
if (!isConnected) return false
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun extendedBolus(insulin: Double, durationInHalfHours: Int): Boolean {
|
||||
if (!isConnected) return false
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun extendedBolusStop(): Boolean {
|
||||
if (!isConnected) return false
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun updateBasalsInPump(profile: Profile): Boolean {
|
||||
if (!isConnected) return false
|
||||
// TODO
|
||||
return false
|
||||
}
|
||||
|
||||
fun loadHistory(type: Byte): PumpEnactResult {
|
||||
val result = PumpEnactResult(injector)
|
||||
if (!isConnected) return result
|
||||
// TODO
|
||||
return result
|
||||
}
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
val serviceInstance: MedtrumService
|
||||
get() = this@MedtrumService
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder {
|
||||
return mBinder
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
return Service.START_STICKY
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import info.nightscout.interfaces.iob.IobCobCalculator
|
|||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.pump.medtrum.databinding.MedtrumPumpFragmentBinding
|
||||
import info.nightscout.pump.medtrum.events.EventMedtrumPumpUpdateGui
|
||||
import info.nightscout.pump.medtrum.MedtrumPumpPlugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPlugin
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventExtendedBolusChange
|
||||
|
@ -31,7 +31,7 @@ class MedtrumPumpFragment : DaggerFragment() {
|
|||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var medtrumPumpPlugin: MedtrumPumpPlugin
|
||||
@Inject lateinit var MedtrumPlugin: MedtrumPlugin
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var iobCobCalculator: IobCobCalculator
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
|
@ -90,7 +90,7 @@ class MedtrumPumpFragment : DaggerFragment() {
|
|||
private fun updateGui() {
|
||||
if (_binding == null) return
|
||||
val profile = profileFunction.getProfile() ?: return
|
||||
binding.baseBasalRate.text = rh.gs(info.nightscout.core.ui.R.string.pump_base_basal_rate, medtrumPumpPlugin.baseBasalRate)
|
||||
binding.baseBasalRate.text = rh.gs(info.nightscout.core.ui.R.string.pump_base_basal_rate, MedtrumPlugin.baseBasalRate)
|
||||
binding.tempbasal.text = iobCobCalculator.getTempBasal(dateUtil.now())?.toStringFull(profile, dateUtil)
|
||||
?: ""
|
||||
binding.extendedbolus.text = iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil)
|
||||
|
@ -98,6 +98,6 @@ class MedtrumPumpFragment : DaggerFragment() {
|
|||
binding.battery.text = rh.gs(info.nightscout.core.ui.R.string.format_percent, 0) // TODO
|
||||
binding.reservoir.text = rh.gs(info.nightscout.interfaces.R.string.format_insulin_units, 0.0) // TODO
|
||||
|
||||
binding.serialNumber.text = medtrumPumpPlugin.serialNumber()
|
||||
binding.serialNumber.text = MedtrumPlugin.serialNumber()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue