You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
8.2 KiB
237 lines
8.2 KiB
package com.whitefish.ring
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.app.AlertDialog
|
|
import android.bluetooth.BluetoothManager
|
|
import android.bluetooth.BluetoothProfile
|
|
import android.content.Context
|
|
import androidx.lifecycle.MutableLiveData
|
|
import com.whitefish.app.bt.BleDevice
|
|
import com.whitefish.ring.bt.OnBleConnectionListener
|
|
import com.whitefish.ring.bt.OnBleScanCallback
|
|
import com.whitefish.ring.bean.ui.Device
|
|
import com.whitefish.ring.device.IDeviceManager
|
|
import io.github.aakira.napier.Napier
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import lib.linktop.nexring.api.BATTERY_STATE_CHARGING
|
|
import lib.linktop.nexring.api.LOAD_DATA_EMPTY
|
|
import lib.linktop.nexring.api.LOAD_DATA_STATE_COMPLETED
|
|
import lib.linktop.nexring.api.LOAD_DATA_STATE_PROCESSING
|
|
import lib.linktop.nexring.api.LOAD_DATA_STATE_START
|
|
import lib.linktop.nexring.api.NexRingManager
|
|
import lib.linktop.nexring.api.OnSleepDataLoadListener
|
|
import lib.linktop.nexring.api.SleepData
|
|
|
|
|
|
class DeviceManager() : IDeviceManager(), OnBleConnectionListener, OnSleepDataLoadListener {
|
|
companion object{
|
|
const val STATE_DEVICE_CHARGING = 1
|
|
const val STATE_DEVICE_DISCHARGING = 0
|
|
const val STATE_DEVICE_DISCONNECTED = -3
|
|
const val STATE_DEVICE_CONNECTING = -2
|
|
const val STATE_DEVICE_CONNECTED = -1
|
|
}
|
|
private val app = Application.INSTANTS!!
|
|
private var isRegisterBattery = false
|
|
val batteryLevel = MutableLiveData(STATE_DEVICE_DISCONNECTED to 0)
|
|
private val sycProgress = MutableLiveData(0)
|
|
var isSyncingData: Boolean = false
|
|
private lateinit var context: Context
|
|
|
|
private val scope = CoroutineScope(Dispatchers.IO)
|
|
// var homeViewModel: demo.linktop.nexring.ui.HomeViewModel? = null
|
|
// var workoutDetailViewModel: demo.linktop.nexring.ui.workout.WorkoutDetailViewModel? = null
|
|
|
|
|
|
fun init(context: Context){
|
|
registerCb()
|
|
this.context = context
|
|
}
|
|
override fun onBleState(state: Int) {
|
|
bleStateListeners().forEach {
|
|
it.invoke(state)
|
|
}
|
|
when (state) {
|
|
BluetoothProfile.STATE_DISCONNECTED -> {
|
|
isRegisterBattery = false
|
|
batteryLevel.postValue(STATE_DEVICE_DISCONNECTED to 0)
|
|
}
|
|
|
|
BluetoothProfile.STATE_CONNECTED -> {
|
|
batteryLevel.postValue(STATE_DEVICE_CONNECTED to 0)
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onBleReady() {
|
|
bleReadyStateFlow.value = true
|
|
postDelay {
|
|
NexRingManager.get()
|
|
.deviceApi()
|
|
.getBatteryInfo {
|
|
if (it.state == BATTERY_STATE_CHARGING) {
|
|
batteryLevel.postValue(STATE_DEVICE_CHARGING to 0)
|
|
} else {
|
|
batteryLevel.postValue(STATE_DEVICE_DISCHARGING to it.level)
|
|
}
|
|
if (!isRegisterBattery) {
|
|
isRegisterBattery = true
|
|
postDelay {
|
|
NexRingManager.get()
|
|
.sleepApi()
|
|
.syncDataFromDev()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onSyncDataFromDevice(state: Int, progress: Int) {
|
|
Napier.i(
|
|
"onSyncDataFromDevice state: $state, progress: $progress"
|
|
)
|
|
when (state) {
|
|
LOAD_DATA_EMPTY -> {
|
|
Napier.e("Empty data")
|
|
//TODO Callback when no data is received from the device.
|
|
}
|
|
|
|
LOAD_DATA_STATE_START -> {
|
|
isSyncingData = true
|
|
sycProgress.postValue(progress)
|
|
}
|
|
|
|
LOAD_DATA_STATE_PROCESSING -> sycProgress.postValue(progress)
|
|
LOAD_DATA_STATE_COMPLETED -> {
|
|
sycProgress.postValue(progress)
|
|
isSyncingData = false
|
|
//todo sync data complete
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onSyncDataError(errorCode: Int) {
|
|
context.cmdErrorTip(errorCode)
|
|
}
|
|
|
|
override fun onOutputNewSleepData(sleepData: ArrayList<SleepData>?) {
|
|
sleepData.also {
|
|
if (it.isNullOrEmpty()) {
|
|
Napier.i(
|
|
"onOutputNewSleepData NULL"
|
|
)
|
|
} else {
|
|
Napier.i(
|
|
"onOutputNewSleepData size ${it.size}"
|
|
)
|
|
it.forEachIndexed { index, data ->
|
|
Napier.i(
|
|
"onOutputNewSleepData $index sleep from ${data.startTs} to ${data.endTs}"
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun registerCb() {
|
|
app.bleManager.addOnBleConnectionListener(this)
|
|
NexRingManager.get().sleepApi().setOnSleepDataLoadListener(this)
|
|
}
|
|
|
|
fun unregisterCb() {
|
|
NexRingManager.get().sleepApi().setOnSleepDataLoadListener(null)
|
|
app.bleManager.removeOnBleConnectionListener(this)
|
|
}
|
|
|
|
|
|
override fun connect(address: String) {
|
|
with(app.bleManager) {
|
|
when (bleState.value) {
|
|
BluetoothProfile.STATE_DISCONNECTED -> {
|
|
batteryLevel.postValue(STATE_DEVICE_CONNECTING to 0)
|
|
if (!connect(address)) {
|
|
startScan(
|
|
20 * 1000L,
|
|
object : OnBleScanCallback {
|
|
override fun onScanning(result: BleDevice) {
|
|
if (result.device.address == address) {
|
|
connect(result.device)
|
|
}
|
|
}
|
|
|
|
override fun onScanFinished() {
|
|
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
BluetoothProfile.STATE_CONNECTED -> {
|
|
onBleState(bleState.value)
|
|
onBleReady()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun bind(onBound: () -> Unit) {
|
|
NexRingManager.get()
|
|
.deviceApi()
|
|
.getBindState {
|
|
if (it) {
|
|
//todo bind dialog
|
|
AlertDialog.Builder(context)
|
|
.setCancelable(false)
|
|
.setTitle(R.string.dialog_title_restricted_mode)
|
|
.setMessage(R.string.dialog_msg_restricted_mode)
|
|
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
|
|
|
}.setPositiveButton(android.R.string.ok) { _, _ ->
|
|
onResetDeviceWhenBind.invoke()
|
|
NexRingManager.get()
|
|
.deviceApi()
|
|
.factoryReset()
|
|
}.create().show()
|
|
} else {
|
|
NexRingManager.get()
|
|
.deviceApi()
|
|
.bind {
|
|
onBound.invoke()
|
|
//todo bind result
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun getCurrentMac(): String? {
|
|
return app.bleManager.connectedDevice?.address
|
|
}
|
|
|
|
override fun startScan() {
|
|
val bluetoothAdapter =
|
|
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
|
|
if (bluetoothAdapter.isEnabled) {
|
|
if (!app.bleManager.isScanning) {
|
|
app.bleManager.startScan(20 * 1000L,
|
|
object : OnBleScanCallback {
|
|
@SuppressLint("MissingPermission")
|
|
override fun onScanning(result: BleDevice) {
|
|
Napier.i("scanned device:${result}")
|
|
val newDevices = arrayListOf<Device>().apply {
|
|
addAll(_deviceList.value)
|
|
add(Device(result.device.name,result.device.address))
|
|
}
|
|
_deviceList.value = newDevices
|
|
}
|
|
|
|
override fun onScanFinished() {
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun stopScan() {
|
|
}
|
|
}
|
|
|