|
|
@@ -0,0 +1,220 @@
|
|
|
+package com.grkj.iscs.view.viewmodel
|
|
|
+
|
|
|
+import androidx.lifecycle.LiveData
|
|
|
+import androidx.lifecycle.MutableLiveData
|
|
|
+import androidx.lifecycle.liveData
|
|
|
+import com.google.gson.Gson
|
|
|
+import com.google.gson.reflect.TypeToken
|
|
|
+import com.grkj.iscs.BusinessManager
|
|
|
+import com.grkj.iscs.MyApplication
|
|
|
+import com.grkj.iscs.ble.BleConnectionManager
|
|
|
+import com.grkj.iscs.modbus.DockBean
|
|
|
+import com.grkj.iscs.modbus.ModBusController
|
|
|
+import com.grkj.iscs.model.DeviceConst
|
|
|
+import com.grkj.iscs.model.bo.DockStatusBO
|
|
|
+import com.grkj.iscs.model.bo.LoginUserBO
|
|
|
+import com.grkj.iscs.util.NetApi
|
|
|
+import com.grkj.iscs.util.SPUtils
|
|
|
+import com.grkj.iscs.util.log.LogUtil
|
|
|
+import com.grkj.iscs.view.base.BaseViewModel
|
|
|
+import com.grkj.iscs.view.fragment.DockTestFragment
|
|
|
+import com.sik.sikcore.thread.ThreadUtils
|
|
|
+import kotlinx.coroutines.Dispatchers
|
|
|
+import kotlinx.coroutines.delay
|
|
|
+import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
+import kotlin.collections.iterator
|
|
|
+import kotlin.coroutines.resume
|
|
|
+
|
|
|
+class DeviceInputKeyAndLockViewModel : BaseViewModel() {
|
|
|
+ var loginUser: LoginUserBO? = null
|
|
|
+ val isLoadComplete: MutableLiveData<Boolean> = MutableLiveData(false)
|
|
|
+ var isStartCheckKey: Boolean = false
|
|
|
+ var isDestroy: Boolean = false
|
|
|
+ private val newHardwareKeyBean: MutableMap<Byte, MutableList<DockBean.KeyBean>> = mutableMapOf()
|
|
|
+
|
|
|
+ fun initData(rowList: MutableList<DockStatusBO>) {
|
|
|
+ val dockConfigJson = SPUtils.getDockConfig(MyApplication.Companion.instance?.applicationContext!!)
|
|
|
+ if (!dockConfigJson.isNullOrEmpty()) {
|
|
|
+ val tempList: MutableList<DockTestFragment.DockTestBean> = Gson().fromJson(
|
|
|
+ dockConfigJson, object : TypeToken<MutableList<DockTestFragment.DockTestBean>>() {}.type
|
|
|
+ )
|
|
|
+ if (tempList.isNotEmpty()) {
|
|
|
+ tempList.forEach { dock ->
|
|
|
+ try {
|
|
|
+ if (dock.type == DeviceConst.DOCK_TYPE_LOCK) {
|
|
|
+ dock.deviceList = mutableListOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
|
|
|
+ }
|
|
|
+ rowList.find { it.row == dock.row.toInt() }?.let {
|
|
|
+ it.dockList.add(dock)
|
|
|
+ } ?: let {
|
|
|
+ rowList.add(DockStatusBO(dock.row.toInt(), mutableListOf(dock)))
|
|
|
+ }
|
|
|
+ } catch (e: Exception) {
|
|
|
+ LogUtil.e("Device status data error : ${e.message}")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 添加空行
|
|
|
+ val maxRow = rowList.maxBy { it.row }.row
|
|
|
+ for (i in 1..maxRow) {
|
|
|
+ if (rowList.find { it.row == i } == null) {
|
|
|
+ rowList.add(DockStatusBO(i, mutableListOf()))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rowList.sortBy { it.row }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun registerInitListener(): LiveData<Boolean> {
|
|
|
+ return liveData(Dispatchers.IO) {
|
|
|
+ isStartCheckKey = false
|
|
|
+ newHardwareKeyBean.clear()
|
|
|
+ isLoadComplete.postValue(false)
|
|
|
+ val allDeviceCloseCmdSend =
|
|
|
+ BleConnectionManager.scanOnlineKeyLockMacAndSwitchModeToClose()
|
|
|
+ LogUtil.i("设备录入-是否所有关闭命令发送成功:${allDeviceCloseCmdSend}")
|
|
|
+ BusinessManager.registerInitListener {
|
|
|
+ if (isStartCheckKey) {
|
|
|
+ return@registerInitListener
|
|
|
+ }
|
|
|
+ isStartCheckKey = true
|
|
|
+ val dockList = ModBusController.dockList
|
|
|
+
|
|
|
+ newHardwareKeyBean.putAll(dockList.filter { it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
|
|
|
+ .associate {
|
|
|
+ it.addr to it.deviceList.filterIsInstance<DockBean.KeyBean>()
|
|
|
+ .filter { it.newHardware && it.isExist }
|
|
|
+ .toMutableList()
|
|
|
+ })
|
|
|
+ LogUtil.d("设备录入-新设备:${newHardwareKeyBean}")
|
|
|
+ ThreadUtils.runOnIO {
|
|
|
+ for ((addr, keyBeans) in newHardwareKeyBean) {
|
|
|
+ for (keyBean in keyBeans) {
|
|
|
+ if (isDestroy) {
|
|
|
+ return@runOnIO
|
|
|
+ }
|
|
|
+ openChargeAndScanMac(addr, keyBean)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ isLoadComplete.postValue(true)
|
|
|
+ emit(true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 打开充电并扫描蓝牙
|
|
|
+ */
|
|
|
+ suspend fun openChargeAndScanMac(addr: Byte, keyBean: DockBean.KeyBean): Boolean {
|
|
|
+ return suspendCancellableCoroutine<Boolean> { cont ->
|
|
|
+ LogUtil.i("设备录入-关闭充电:${addr},${keyBean.idx}")
|
|
|
+ ModBusController.controlKeyCharge(false, keyBean.isLeft, addr) {
|
|
|
+ ThreadUtils.runOnIO {
|
|
|
+ delay(3000)
|
|
|
+ LogUtil.i("设备录入-打开充电:${addr},${keyBean.idx}")
|
|
|
+ ModBusController.controlKeyLockAndCharge(true, keyBean.isLeft, addr) {
|
|
|
+ ThreadUtils.runOnIO {
|
|
|
+ delay(3000)
|
|
|
+ LogUtil.i("设备录入-开始扫描在线蓝牙Mac")
|
|
|
+ BleConnectionManager.scanOnlineKeyLockMac { bleDevices ->
|
|
|
+ LogUtil.i(
|
|
|
+ "设备录入-在线的蓝牙设备:${keyBean.rfid},${
|
|
|
+ bleDevices?.joinToString(
|
|
|
+ ","
|
|
|
+ ) { it.mac }
|
|
|
+ }"
|
|
|
+ )
|
|
|
+ if (bleDevices?.isEmpty() == true) {
|
|
|
+ ThreadUtils.runOnIO {
|
|
|
+ if (isDestroy) {
|
|
|
+ return@runOnIO
|
|
|
+ }
|
|
|
+ openChargeAndScanMac(addr, keyBean)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LogUtil.i(
|
|
|
+ "设备录入-没有使用过的mac:${keyBean.rfid},${
|
|
|
+ bleDevices?.find {
|
|
|
+ it.mac !in newHardwareKeyBean.map { it.value }
|
|
|
+ .flatten()
|
|
|
+ .map { it.mac }
|
|
|
+ }?.mac
|
|
|
+ }"
|
|
|
+ )
|
|
|
+ keyBean.mac = bleDevices?.find {
|
|
|
+ it.mac !in newHardwareKeyBean.map { it.value }.flatten()
|
|
|
+ .map { it.mac }
|
|
|
+ }?.mac
|
|
|
+ cont.resume(true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun unregisterInitListener() {
|
|
|
+ BusinessManager.unRegisterInitListener()
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备录入挂起任务
|
|
|
+ */
|
|
|
+ private suspend fun deviceInputKeySuspend(keyNfc: String, keyMacAddress: String): Boolean {
|
|
|
+ return suspendCancellableCoroutine<Boolean> { cont ->
|
|
|
+ NetApi.deviceInputKey(keyNfc, keyMacAddress) {
|
|
|
+ cont.resume(it)
|
|
|
+ cont.cancel()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备录入挂起任务
|
|
|
+ */
|
|
|
+ private suspend fun deviceInputLockSuspend(cardNo: String): Boolean {
|
|
|
+ return suspendCancellableCoroutine<Boolean> { cont ->
|
|
|
+ NetApi.deviceInputLock(cardNo) {
|
|
|
+ cont.resume(it)
|
|
|
+ cont.cancel()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备录入(钥匙和挂锁)
|
|
|
+ * //todo 录入待完成
|
|
|
+ */
|
|
|
+ fun deviceInputData(dockData: MutableList<DockStatusBO>): LiveData<Triple<Boolean, Int, Int>> {
|
|
|
+ return liveData(Dispatchers.IO) {
|
|
|
+ val dockList = dockData.map { it.dockList }.flatten()
|
|
|
+ val deviceList =
|
|
|
+ ModBusController.dockList.filter { it.addr in dockList.map { it.address } }
|
|
|
+ .map { it.deviceList }.flatten()
|
|
|
+ val lockDevice = deviceList.filter { it.type == DeviceConst.DEVICE_TYPE_LOCK }
|
|
|
+ .filterIsInstance<DockBean.LockBean>().filter { it.newHardware == true }
|
|
|
+ val keyDevice = deviceList.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
|
|
|
+ .filterIsInstance<DockBean.KeyBean>().filter { it.newHardware == true }
|
|
|
+ lockDevice.filter { it.rfid?.isNotEmpty() == true }.map { it.rfid }.forEach { rfid ->
|
|
|
+ deviceInputLockSuspend(rfid.toString())
|
|
|
+ }
|
|
|
+ keyDevice.filter { it.rfid?.isNotEmpty() == true && it.mac?.isNotEmpty() == true }
|
|
|
+ .forEach { keyDevice ->
|
|
|
+ val isBind =
|
|
|
+ deviceInputKeySuspend(keyDevice.rfid.toString(), keyDevice.mac.toString())
|
|
|
+ if (isBind) {
|
|
|
+ keyDevice.newHardware = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ emit(
|
|
|
+ Triple(
|
|
|
+ true,
|
|
|
+ keyDevice.count { it.rfid?.isNotEmpty() == true && it.mac?.isNotEmpty() == true },
|
|
|
+ lockDevice.count { it.rfid?.isNotEmpty() == true })
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|