Added MedtrumService

This commit is contained in:
jbr7rr 2023-02-21 10:59:31 +01:00
parent b635ad26d8
commit baa4376f68
12 changed files with 503 additions and 200 deletions

View file

@ -54,7 +54,7 @@ import info.nightscout.plugins.sync.xdrip.XdripPlugin
import info.nightscout.pump.combo.ComboPlugin import info.nightscout.pump.combo.ComboPlugin
import info.nightscout.pump.combov2.ComboV2Plugin import info.nightscout.pump.combov2.ComboV2Plugin
import info.nightscout.pump.diaconn.DiaconnG8Plugin 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.pump.virtual.VirtualPumpPlugin
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventPreferenceChange
@ -123,7 +123,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
@Inject lateinit var wearPlugin: WearPlugin @Inject lateinit var wearPlugin: WearPlugin
@Inject lateinit var maintenancePlugin: MaintenancePlugin @Inject lateinit var maintenancePlugin: MaintenancePlugin
@Inject lateinit var eopatchPumpPlugin: EopatchPumpPlugin @Inject lateinit var eopatchPumpPlugin: EopatchPumpPlugin
@Inject lateinit var medtrumPumpPlugin: MedtrumPumpPlugin @Inject lateinit var MedtrumPlugin: MedtrumPlugin
@Inject lateinit var passwordCheck: PasswordCheck @Inject lateinit var passwordCheck: PasswordCheck
@Inject lateinit var nsSettingStatus: NSSettingsStatus @Inject lateinit var nsSettingStatus: NSSettingsStatus
@ -214,7 +214,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(diaconnG8Plugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(diaconnG8Plugin, rootKey, config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(eopatchPumpPlugin, 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) addPreferencesFromResource(R.xml.pref_pump, rootKey, config.PUMPDRIVERS)
addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey) addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey)
addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey) addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey)

View file

@ -31,9 +31,9 @@ import info.nightscout.pump.common.di.PumpCommonModule
import info.nightscout.pump.dana.di.DanaHistoryModule import info.nightscout.pump.dana.di.DanaHistoryModule
import info.nightscout.pump.dana.di.DanaModule import info.nightscout.pump.dana.di.DanaModule
import info.nightscout.pump.danars.di.DanaRSModule 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.diaconn.di.DiaconnG8Module
import info.nightscout.pump.virtual.di.VirtualPumpModule import info.nightscout.pump.virtual.di.VirtualPumpModule
import info.nightscout.pump.medtrum.di.MedtrumPumpModule
import info.nightscout.rx.di.RxModule import info.nightscout.rx.di.RxModule
import info.nightscout.shared.di.SharedModule import info.nightscout.shared.di.SharedModule
import info.nightscout.shared.impl.di.SharedImplModule import info.nightscout.shared.impl.di.SharedImplModule
@ -88,7 +88,7 @@ import javax.inject.Singleton
OmnipodErosModule::class, OmnipodErosModule::class,
PumpCommonModule::class, PumpCommonModule::class,
RileyLinkModule::class, RileyLinkModule::class,
MedtrumPumpModule::class, MedtrumModule::class,
VirtualPumpModule::class VirtualPumpModule::class
] ]
) )

View file

@ -46,7 +46,7 @@ import info.nightscout.plugins.sync.tidepool.TidepoolPlugin
import info.nightscout.plugins.sync.xdrip.XdripPlugin import info.nightscout.plugins.sync.xdrip.XdripPlugin
import info.nightscout.pump.combo.ComboPlugin import info.nightscout.pump.combo.ComboPlugin
import info.nightscout.pump.combov2.ComboV2Plugin 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.diaconn.DiaconnG8Plugin
import info.nightscout.pump.virtual.VirtualPumpPlugin import info.nightscout.pump.virtual.VirtualPumpPlugin
import info.nightscout.sensitivity.SensitivityAAPSPlugin import info.nightscout.sensitivity.SensitivityAAPSPlugin
@ -214,7 +214,7 @@ abstract class PluginsListModule {
@PumpDriver @PumpDriver
@IntoMap @IntoMap
@IntKey(160) @IntKey(160)
abstract fun bindMedtrumPumpPlugin(plugin: MedtrumPumpPlugin): PluginBase abstract fun bindMedtrumPlugin(plugin: MedtrumPlugin): PluginBase
@Binds @Binds
@AllConfigs @AllConfigs

View file

@ -1,3 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<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> </manifest>

View file

@ -1,6 +1,12 @@
package info.nightscout.pump.medtrum 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 dagger.android.HasAndroidInjector
import info.nightscout.core.ui.toast.ToastUtils
import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.interfaces.plugin.PluginDescription import info.nightscout.interfaces.plugin.PluginDescription
import info.nightscout.interfaces.plugin.PluginType 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.ui.UiInteraction
import info.nightscout.interfaces.utils.TimeChangeType import info.nightscout.interfaces.utils.TimeChangeType
import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment
import info.nightscout.pump.medtrum.services.MedtrumService
import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventAppExit
import info.nightscout.rx.events.EventAppInitialized import info.nightscout.rx.events.EventAppInitialized
import info.nightscout.rx.events.EventOverviewBolusProgress import info.nightscout.rx.events.EventOverviewBolusProgress
import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventPreferenceChange
import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil import info.nightscout.shared.utils.DateUtil
import info.nightscout.shared.utils.T import info.nightscout.shared.utils.T
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.functions.Consumer import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.subjects.BehaviorSubject import io.reactivex.rxjava3.subjects.BehaviorSubject
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class MedtrumPumpPlugin @Inject constructor( class MedtrumPlugin @Inject constructor(
injector: HasAndroidInjector, injector: HasAndroidInjector,
aapsLogger: AAPSLogger, aapsLogger: AAPSLogger,
rh: ResourceHelper, rh: ResourceHelper,
commandQueue: CommandQueue, commandQueue: CommandQueue,
private val sp: SP,
private val aapsSchedulers: AapsSchedulers, private val aapsSchedulers: AapsSchedulers,
private val rxBus: RxBus, private val rxBus: RxBus,
private val context: Context,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val pumpSync: PumpSync, private val pumpSync: PumpSync,
@ -55,7 +66,7 @@ class MedtrumPumpPlugin @Inject constructor(
private val profileFunction: ProfileFunction private val profileFunction: ProfileFunction
) : PumpPluginBase( ) : PumpPluginBase(
PluginDescription() PluginDescription()
.mainType(PluginType.PUMP) // TODO Prefs etc .mainType(PluginType.PUMP)
.fragmentClass(MedtrumPumpFragment::class.java.name) .fragmentClass(MedtrumPumpFragment::class.java.name)
.pluginIcon(info.nightscout.core.ui.R.drawable.ic_eopatch2_128) // TODO .pluginIcon(info.nightscout.core.ui.R.drawable.ic_eopatch2_128) // TODO
.pluginName(R.string.medtrum) .pluginName(R.string.medtrum)
@ -64,16 +75,51 @@ class MedtrumPumpPlugin @Inject constructor(
.description(R.string.medtrum_pump_description), injector, aapsLogger, rh, commandQueue .description(R.string.medtrum_pump_description), injector, aapsLogger, rh, commandQueue
), Pump { ), Pump {
private val disposable = CompositeDisposable()
private var medtrumService: MedtrumService? = null
private var mPumpType: PumpType = PumpType.MEDTRUM_NANO private var mPumpType: PumpType = PumpType.MEDTRUM_NANO
private val mPumpDescription = PumpDescription(mPumpType) private val mPumpDescription = PumpDescription(mPumpType)
private var mDeviceSN: Long = 0
override fun onStart() { override fun onStart() {
super.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() { override fun onStop() {
aapsLogger.debug(LTag.PUMP, "MedtrumPlugin onStop()")
context.unbindService(mConnection)
disposable.clear()
super.onStop() 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 { override fun isInitialized(): Boolean {
@ -88,33 +134,35 @@ class MedtrumPumpPlugin @Inject constructor(
return false return false
} }
override fun isConnected(): Boolean { override fun isConnected(): Boolean = medtrumService?.isConnected ?: false
return false override fun isConnecting(): Boolean = medtrumService?.isConnecting ?: false
} override fun isHandshakeInProgress(): Boolean = false
override fun isConnecting(): Boolean {
return false
}
override fun isHandshakeInProgress(): Boolean {
return false
}
override fun finishHandshaking() { override fun finishHandshaking() {
} }
override fun connect(reason: String) { override fun connect(reason: String) {
aapsLogger.debug(LTag.PUMP, "Medtrum connect - reason:$reason") 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) { 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() { override fun stopConnecting() {
medtrumService?.stopConnecting()
} }
override fun getPumpStatus(reason: String) { override fun getPumpStatus(reason: String) {
// TODO
} }
override fun setNewBasalProfile(profile: Profile): PumpEnactResult { override fun setNewBasalProfile(profile: Profile): PumpEnactResult {

View file

@ -14,15 +14,15 @@ class ManufacturerData(private val manufacturerDataBytes: ByteArray) {
fun setData(inputData: ByteArray) { fun setData(inputData: ByteArray) {
var index = 0 var index = 0
val deviceIDBytes: ByteArray = manufacturerDataBytes.copyOfRange(index, index + 4) val deviceIDBytes: ByteArray = inputData.copyOfRange(index, index + 4)
deviceID = deviceIDBytes.toLong() deviceID = deviceIDBytes.toLong()
index += 4 index += 4
deviceType = (manufacturerDataBytes[index] and 0xff.toByte()).toInt() deviceType = (inputData[index] and 0xff.toByte()).toInt()
index += 1 index += 1
version = (manufacturerDataBytes[index] and 0xff.toByte()).toInt() version = (inputData[index] and 0xff.toByte()).toInt()
} }
fun getDeviceID(): Long{ fun getDeviceSN(): Long{
return deviceID return deviceID
} }

View file

@ -1,13 +1,12 @@
package info.nightscout.pump.medtrum.di package info.nightscout.pump.medtrum.di
import dagger.Binds
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment import info.nightscout.pump.medtrum.ui.MedtrumPumpFragment
@Module @Module
@Suppress("unused") @Suppress("unused")
abstract class MedtrumPumpModule { abstract class MedtrumActivitiesModule {
@ContributesAndroidInjector abstract fun contributesMedtrumPumpFragment(): MedtrumPumpFragment @ContributesAndroidInjector abstract fun contributesMedtrumPumpFragment(): MedtrumPumpFragment

View file

@ -0,0 +1,9 @@
package info.nightscout.pump.medtrum.di
import dagger.Module
@Module(includes = [
MedtrumActivitiesModule::class,
MedtrumServicesModule::class
])
open class MedtrumModule

View file

@ -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
}

View file

@ -79,7 +79,7 @@ class BLEComm @Inject internal constructor(
var isConnecting = false var isConnecting = false
private var uartWrite: BluetoothGattCharacteristic? = null 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) */ /** Connect flow: 1. Start scanning for our device (SN entered in settings) */
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
@ -98,7 +98,6 @@ class BLEComm @Inject internal constructor(
.build() .build()
val filters = mutableListOf<ScanFilter>() val filters = mutableListOf<ScanFilter>()
if (deviceID == 0.toLong()) deviceID = rh.gs(info.nightscout.pump.medtrum.R.string.key_snInput).toLong(radix = 16)
isConnected = false isConnected = false
// TODO: Maybe replace this by (or add) a isScanning parameter? // TODO: Maybe replace this by (or add) a isScanning parameter?
@ -119,17 +118,43 @@ class BLEComm @Inject internal constructor(
mBluetoothAdapter?.bluetoothLeScanner?.stopScan(mScanCallback) 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() */ /** Connect flow: 2. When device is found this is called by onScanResult() */
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
@Synchronized @Synchronized
fun connect(device: BluetoothDevice) { fun connectGatt(device: BluetoothDevice) {
mBluetoothGatt = mBluetoothGatt =
device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE) device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
} }
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
@Synchronized @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?.disconnect()
mBluetoothGatt = null mBluetoothGatt = null
} }
@ -156,11 +181,12 @@ class BLEComm @Inject internal constructor(
result.scanRecord?.getManufacturerSpecificData(MANUFACTURER_ID) result.scanRecord?.getManufacturerSpecificData(MANUFACTURER_ID)
?.let { ManufacturerData(it) } ?.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() stopScan()
connect(result.device) connectGatt(result.device)
} }
} }
@ -230,6 +256,7 @@ class BLEComm @Inject internal constructor(
checkDescriptor(descriptor) checkDescriptor(descriptor)
} }
} }
}
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
@Synchronized @Synchronized
@ -244,6 +271,7 @@ class BLEComm @Inject internal constructor(
mBluetoothGatt?.readDescriptor(descriptor) mBluetoothGatt?.readDescriptor(descriptor)
} }
@Suppress("DEPRECATION")
private fun checkDescriptor(descriptor: BluetoothGattDescriptor) { private fun checkDescriptor(descriptor: BluetoothGattDescriptor) {
aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor") aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor")
val service = getGattService() val service = getGattService()
@ -308,8 +336,6 @@ class BLEComm @Inject internal constructor(
isConnecting = false isConnecting = false
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)) rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED))
aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected
disconnect()
startScan()
} }
} }
@ -322,15 +348,12 @@ class BLEComm @Inject internal constructor(
private fun authorize() { private fun authorize() {
aapsLogger.debug(LTag.PUMPBTCOMM, "Start auth!") aapsLogger.debug(LTag.PUMPBTCOMM, "Start auth!")
val role = 2 // Fixed to 2 for pump val role = 2 // Fixed to 2 for pump
val key = mCrypt.keyGen(deviceID) val key = mCrypt.keyGen(mDeviceSN)
val commandData = byteArrayOf(COMMAND_AUTH_REQ) + byteArrayOf(role.toByte()) + 0.toByteArray(4) + key.toByteArray(4) val commandData = byteArrayOf(COMMAND_AUTH_REQ) + byteArrayOf(role.toByte()) + 0.toByteArray(4) + key.toByteArray(4)
sendMessage(commandData) sendMessage(commandData)
} }
@Suppress("DEPRECATION") fun sendMessage(message: ByteArray) {
@SuppressLint("MissingPermission")
@Synchronized
private fun sendMessage(message: ByteArray) {
// TODO: Handle packages which consist of multiple, Create a queue of packages // TODO: Handle packages which consist of multiple, Create a queue of packages
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message)) aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
val writePacket = WriteCommandPackets(message) val writePacket = WriteCommandPackets(message)
@ -396,4 +419,3 @@ class BLEComm @Inject internal constructor(
} }
} }
} }
}

View file

@ -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
}
}

View file

@ -13,7 +13,7 @@ import info.nightscout.interfaces.iob.IobCobCalculator
import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.pump.medtrum.databinding.MedtrumPumpFragmentBinding import info.nightscout.pump.medtrum.databinding.MedtrumPumpFragmentBinding
import info.nightscout.pump.medtrum.events.EventMedtrumPumpUpdateGui 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.AapsSchedulers
import info.nightscout.rx.bus.RxBus import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventExtendedBolusChange import info.nightscout.rx.events.EventExtendedBolusChange
@ -31,7 +31,7 @@ class MedtrumPumpFragment : DaggerFragment() {
@Inject lateinit var rh: ResourceHelper @Inject lateinit var rh: ResourceHelper
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var medtrumPumpPlugin: MedtrumPumpPlugin @Inject lateinit var MedtrumPlugin: MedtrumPlugin
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@ -90,7 +90,7 @@ class MedtrumPumpFragment : DaggerFragment() {
private fun updateGui() { private fun updateGui() {
if (_binding == null) return if (_binding == null) return
val profile = profileFunction.getProfile() ?: 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.tempbasal.text = iobCobCalculator.getTempBasal(dateUtil.now())?.toStringFull(profile, dateUtil)
?: "" ?: ""
binding.extendedbolus.text = iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(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.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.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()
} }
} }