BLEComm: Added callbacks to enable handling of notifications in calling class
This commit is contained in:
parent
f31f6c1649
commit
ed100a4eb0
3 changed files with 103 additions and 34 deletions
|
@ -0,0 +1,19 @@
|
|||
package info.nightscout.pump.medtrum.comm
|
||||
|
||||
class ReadDataPacket(data: ByteArray) {
|
||||
|
||||
private var totalData = data.copyOfRange(0, data.size - 1) // Strip crc
|
||||
private var dataSize: Byte = data[0]
|
||||
|
||||
fun addData(newData: ByteArray) {
|
||||
totalData += newData.copyOfRange(4, newData.size - 1) // Strip header and crc
|
||||
}
|
||||
|
||||
fun allDataReceived(): Boolean {
|
||||
return (totalData.size >= dataSize)
|
||||
}
|
||||
|
||||
fun getData(): ByteArray {
|
||||
return totalData
|
||||
}
|
||||
}
|
|
@ -32,9 +32,9 @@ import info.nightscout.interfaces.pump.PumpSync
|
|||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import info.nightscout.pump.medtrum.extension.toInt
|
||||
import info.nightscout.pump.medtrum.encryption.Crypt
|
||||
import info.nightscout.pump.medtrum.comm.WriteCommandPackets
|
||||
import info.nightscout.pump.medtrum.comm.ManufacturerData
|
||||
import info.nightscout.pump.medtrum.comm.ReadDataPacket
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventDismissNotification
|
||||
import info.nightscout.rx.events.EventPumpStatusChanged
|
||||
|
@ -48,6 +48,14 @@ import java.util.Arrays
|
|||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
interface BLECommCallback {
|
||||
|
||||
open fun onBLEConnected() {}
|
||||
open fun onNotification(notification: ByteArray) {}
|
||||
open fun onIndication(indication: ByteArray) {}
|
||||
open fun onSendMessageError(reason: String)
|
||||
}
|
||||
|
||||
@Singleton
|
||||
class BLEComm @Inject internal constructor(
|
||||
private val injector: HasAndroidInjector,
|
||||
|
@ -74,23 +82,28 @@ class BLEComm @Inject internal constructor(
|
|||
private const val NEEDS_ENABLE = 0x30
|
||||
|
||||
private const val MANUFACTURER_ID = 18305
|
||||
private const val COMMAND_AUTH_REQ: Byte = 5
|
||||
}
|
||||
|
||||
private val handler =
|
||||
Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
||||
private val mBluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
|
||||
private var mBluetoothGatt: BluetoothGatt? = null
|
||||
private val mCrypt = Crypt()
|
||||
|
||||
var isConnected = false
|
||||
var isConnecting = false
|
||||
private var uartWrite: BluetoothGattCharacteristic? = null
|
||||
private var uartRead: BluetoothGattCharacteristic? = null
|
||||
|
||||
private var mDeviceSN: Long = 0
|
||||
|
||||
// Read and write buffers
|
||||
private var mWritePackets = WriteCommandPackets()
|
||||
private var mReadPacket: ReadDataPacket? = null
|
||||
|
||||
private var mDeviceSN: Long = 0
|
||||
private var mCallback: BLECommCallback? = null
|
||||
|
||||
fun setCallback(callback: BLECommCallback?) {
|
||||
this.mCallback = callback
|
||||
}
|
||||
|
||||
/** Connect flow: 1. Start scanning for our device (SN entered in settings) */
|
||||
@SuppressLint("MissingPermission")
|
||||
|
@ -225,14 +238,26 @@ class BLEComm @Inject internal constructor(
|
|||
|
||||
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "onCharacteristicChanged")
|
||||
// TODO: Make split between Notif and Indication
|
||||
// Notif contains pump status and alarms
|
||||
readDataParsing(characteristic.value)
|
||||
|
||||
val value = characteristic.getValue()
|
||||
if (characteristic.getUuid() == UUID.fromString(READ_UUID)) {
|
||||
mCallback?.onNotification(value)
|
||||
} else if (characteristic.getUuid() == UUID.fromString(WRITE_UUID)) {
|
||||
if (mReadPacket == null) {
|
||||
mReadPacket = ReadDataPacket(value)
|
||||
} else {
|
||||
mReadPacket?.addData(value)
|
||||
}
|
||||
if (mReadPacket?.allDataReceived() == true) {
|
||||
mReadPacket = null
|
||||
mReadPacket?.getData()?.let { mCallback?.onIndication(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "onCharacteristicWrite status = " + status)
|
||||
|
||||
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// Check if we need to finish our command!
|
||||
synchronized(mWritePackets) {
|
||||
|
@ -242,7 +267,7 @@ class BLEComm @Inject internal constructor(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: What to do here?
|
||||
mCallback?.onSendMessageError("onCharacteristicWrite failure")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +328,10 @@ class BLEComm @Inject internal constructor(
|
|||
}
|
||||
if (notificationEnabled) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Notifications enabled!")
|
||||
authorize()
|
||||
/** Connect flow: 6. Connected */
|
||||
mCallback?.onBLEConnected()
|
||||
isConnected = true
|
||||
isConnecting = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -351,23 +379,6 @@ class BLEComm @Inject internal constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun readDataParsing(receivedData: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< readDataParsing " + Arrays.toString(receivedData))
|
||||
// TODO Implement
|
||||
// TODO place this at the correct place
|
||||
/** Connect flow: 6. Authorized */
|
||||
isConnected = true
|
||||
isConnecting = false
|
||||
}
|
||||
|
||||
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) {
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
|
||||
if (!mWritePackets.allPacketsConsumed()) {
|
||||
|
@ -381,6 +392,7 @@ class BLEComm @Inject internal constructor(
|
|||
writeCharacteristic(uartWriteBTGattChar, value)
|
||||
} else {
|
||||
aapsLogger.error(LTag.PUMPBTCOMM, "sendMessage error in writePacket!")
|
||||
mCallback?.onSendMessageError("error in writePacket!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ 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.pump.medtrum.encryption.Crypt
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventAppExit
|
||||
|
@ -40,12 +42,13 @@ 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.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
class MedtrumService : DaggerService() {
|
||||
class MedtrumService : DaggerService(), BLECommCallback {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
|
@ -65,11 +68,19 @@ class MedtrumService : DaggerService() {
|
|||
@Inject lateinit var pumpSync: PumpSync
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
companion object {
|
||||
private const val COMMAND_AUTH_REQ: Byte = 5
|
||||
}
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private val mBinder: IBinder = LocalBinder()
|
||||
private val mCrypt = Crypt()
|
||||
|
||||
private var mDeviceSN: Long = 0
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
bleComm.setCallback(this)
|
||||
disposable += rxBus
|
||||
.toObservable(EventAppExit::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
|
@ -89,22 +100,20 @@ class MedtrumService : DaggerService() {
|
|||
|
||||
fun connect(from: String, deviceSN: Long): Boolean {
|
||||
// TODO Check we might want to replace this with start scan?
|
||||
mDeviceSN = deviceSN
|
||||
return bleComm.connect(from, deviceSN)
|
||||
}
|
||||
|
||||
fun stopConnecting() {
|
||||
// TODO proper way for this might need send commands etc
|
||||
bleComm.stopConnecting()
|
||||
}
|
||||
|
||||
fun disconnect(from: String) {
|
||||
// TODO proper way for this might need send commands etc
|
||||
bleComm.disconnect(from)
|
||||
}
|
||||
|
||||
fun sendMessage(message: ByteArray) { // TODO Check what we use here?
|
||||
// TODO
|
||||
bleComm.sendMessage(message)
|
||||
}
|
||||
|
||||
fun readPumpStatus() {
|
||||
// TODO
|
||||
}
|
||||
|
@ -179,6 +188,35 @@ class MedtrumService : DaggerService() {
|
|||
return false
|
||||
}
|
||||
|
||||
private fun authorize() {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "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)
|
||||
bleComm.sendMessage(commandData)
|
||||
}
|
||||
|
||||
/** BLECommCallbacks */
|
||||
override fun onBLEConnected() {
|
||||
// TODO Replace by FSM Entry?
|
||||
authorize()
|
||||
}
|
||||
|
||||
override fun onNotification(notification: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "<<<<< onNotification" + notification.contentToString())
|
||||
// TODO
|
||||
}
|
||||
|
||||
override fun onIndication(indication: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "<<<<< onIndication" + indication.contentToString())
|
||||
// TODO
|
||||
}
|
||||
|
||||
override fun onSendMessageError(reason: String) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "<<<<< error during send message " + reason)
|
||||
// TODO
|
||||
}
|
||||
|
||||
/** Service stuff */
|
||||
inner class LocalBinder : Binder() {
|
||||
val serviceInstance: MedtrumService
|
||||
|
|
Loading…
Reference in a new issue