Przeglądaj źródła

refactor(更新)
- 设备初始化第一次重启之后蓝牙失效的问题处理

周文健 4 miesięcy temu
rodzic
commit
2c6aa7aafa
24 zmienionych plików z 311 dodań i 131 usunięć
  1. 34 4
      app/src/main/java/com/grkj/iscs/ISCSApplication.kt
  2. 5 0
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitCardRegistrationFragment.kt
  3. 27 22
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitDeviceRegistrationKeyAndLockFragment.kt
  4. 5 0
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitPointRfidRegistrationFragment.kt
  5. 10 2
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitWelcomeFragment.kt
  6. 33 49
      app/src/main/java/com/grkj/iscs/features/init/viewmodel/InitDeviceRegistrationKeyAndLockViewModel.kt
  7. 16 2
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/CreateJobFragment.kt
  8. 5 5
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/UserManageViewModel.kt
  9. 3 0
      app/src/main/res/values-en/strings.xml
  10. 4 4
      app/src/main/res/values-land/dimens.xml
  11. 3 0
      app/src/main/res/values-zh/strings.xml
  12. 3 0
      app/src/main/res/values/strings.xml
  13. 5 0
      data/src/main/java/com/grkj/data/data/EventConstants.kt
  14. 1 1
      gradle/libs.versions.toml
  15. 3 4
      ui-base/src/main/java/com/grkj/ui_base/business/BleBusinessManager.kt
  16. 8 3
      ui-base/src/main/java/com/grkj/ui_base/dialog/LoadingDialog.kt
  17. 45 28
      ui-base/src/main/java/com/grkj/ui_base/utils/ble/BleConnectionManager.kt
  18. 24 1
      ui-base/src/main/java/com/grkj/ui_base/utils/ble/BleUtil.kt
  19. 24 0
      ui-base/src/main/java/com/grkj/ui_base/utils/event/RestartAppEvent.kt
  20. 5 3
      ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusController.kt
  21. 42 3
      ui-base/src/main/java/com/grkj/ui_base/utils/modbus/PortManager.kt
  22. 2 0
      ui-base/src/main/res/values-en/strings.xml
  23. 2 0
      ui-base/src/main/res/values-zh/strings.xml
  24. 2 0
      ui-base/src/main/res/values/strings.xml

+ 34 - 4
app/src/main/java/com/grkj/iscs/ISCSApplication.kt

@@ -1,10 +1,15 @@
 package com.grkj.iscs
 
+import android.app.AlarmManager
 import android.app.Application
+import android.app.PendingIntent
+import android.bluetooth.BluetoothDevice
 import android.content.Context
+import android.content.Intent
 import ch.qos.logback.classic.Level
 import com.grkj.data.data.EventConstants
 import com.grkj.data.di.RepositoryManager
+import com.grkj.iscs.features.splash.activity.SplashActivity
 import com.grkj.shared.model.EventBean
 import com.grkj.ui_base.business.ModbusBusinessManager
 import com.grkj.ui_base.config.ISCSConfig
@@ -20,6 +25,8 @@ import com.scwang.smart.refresh.layout.api.RefreshLayout
 import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator
 import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator
 import com.sik.sikcore.SIKCore
+import com.sik.sikcore.bluetooth.BLEScanner
+import com.sik.sikcore.bluetooth.IBluetoothScanCallback
 import com.sik.sikcore.log.LogUtils
 import com.sik.sikcore.thread.ThreadUtils
 import dagger.hilt.android.HiltAndroidApp
@@ -54,7 +61,7 @@ class ISCSApplication : Application() {
         if (ISCSConfig.DEBUG) {
             LogUtils.setGlobalLogLevel(Level.DEBUG)
         }
-        if (ISCSConfig.isInit){
+        if (ISCSConfig.isInit) {
             BleUtil.instance?.initBle(this)
         }
         AutoSizeConfig.getInstance().isCustomFragment = true
@@ -71,14 +78,37 @@ class ISCSApplication : Application() {
                 ThreadUtils.runOnIO {
                     ModBusController.interruptReadTrashBinStatus(false)
                     ModBusController.start()
-                    if (!ISCSConfig.isInit) {
-                        delay(10_000)
-                    }
                     logger.info("Application 连接完成,开始初始化")
                     ModBusController.initDevicesStatus()
                 }
             }
+
+            EventConstants.EVENT_RESTART_APP -> {
+                scheduleRestart(this)
+            }
+        }
+    }
+
+    /**
+     * 计划重启
+     */
+    private fun scheduleRestart(context: Context) {
+        val restartIntent = Intent(context, SplashActivity::class.java).apply {
+            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
         }
+        val pi = PendingIntent.getActivity(
+            context,
+            0,
+            restartIntent,
+            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
+        val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+        am.setExact(
+            AlarmManager.RTC,
+            System.currentTimeMillis() + 2000,
+            pi
+        )
+        Runtime.getRuntime().exit(0)
     }
 
     override fun onTerminate() {

+ 5 - 0
app/src/main/java/com/grkj/iscs/features/init/fragment/InitCardRegistrationFragment.kt

@@ -14,6 +14,7 @@ import com.grkj.shared.model.EventBean
 import com.grkj.shared.utils.KeyboardUtils
 import com.grkj.ui_base.base.BaseFragment
 import com.grkj.ui_base.utils.event.CardSwipeEvent
+import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
 
@@ -70,6 +71,10 @@ class InitCardRegistrationFragment : BaseFragment<FragmentInitCardRegistrationBi
         when (event.code) {
             EventConstants.EVENT_CARD_SWIPE -> {
                 val cardSwipeEvent = (event.data as CardSwipeEvent)
+                if (cardRfidData.contains(cardSwipeEvent.cardNo)){
+                    PopTip.tip(R.string.card_already_registration)
+                    return
+                }
                 cardRfidData.add(cardSwipeEvent.cardNo)
                 binding.cardRv.adapter?.notifyDataSetChanged()
                 KeyboardUtils.hideKeyboard(requireActivity())

+ 27 - 22
app/src/main/java/com/grkj/iscs/features/init/fragment/InitDeviceRegistrationKeyAndLockFragment.kt

@@ -46,7 +46,7 @@ class InitDeviceRegistrationKeyAndLockFragment :
             logger.debug("设备录入-初始化检测任务分发完成")
         }
         binding.reRecognize.setDebouncedClickListener {
-            ISCSConfig.canInitDevice = true
+            viewModel.isInDeviceInit = false
         }
         binding.previousBtn.setDebouncedClickListener {
             navController.popBackStack()
@@ -86,30 +86,35 @@ class InitDeviceRegistrationKeyAndLockFragment :
                     R.string.init_device_registration_key_and_lock_complete_step_hint
                 )
             binding.reRecognize.isVisible = it
-            val dockData =
-                ModBusController.dockList.filter { it.type == DeviceConst.DOCK_TYPE_LOCK || it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
-            val keyDock = dockData.filter { it.type == DeviceConst.DOCK_TYPE_KEY }.map {
-                DockData.KeyDock().apply {
-                    keyData.addAll(it.deviceList.filterIsInstance<DockBean.KeyBean>())
+            if (it){
+                val dockData =
+                    ModBusController.dockList.filter { it.type == DeviceConst.DOCK_TYPE_LOCK || it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
+                val keyDock = dockData.filter { it.type == DeviceConst.DOCK_TYPE_KEY }.map {
+                    DockData.KeyDock().apply {
+                        keyData.addAll(it.deviceList.filterIsInstance<DockBean.KeyBean>())
+                    }
                 }
-            }
-            val keyDatas = keyDock.map { it.keyData }.flatten()
-            val newKeyDock = DockData.KeyDock()
-            newKeyDock.keyData.addAll(keyDatas)
-            val newKeyDockList = newKeyDock.keyData.chunked(4).map { subList ->
-                KeyDock().apply { keyData.addAll(subList) }
-            }
-            val lockDock = dockData.filter { it.type == DeviceConst.DOCK_TYPE_LOCK }.map {
-                DockData.LockDock().apply {
-                    lockData.addAll(it.deviceList.filterIsInstance<DockBean.LockBean>())
+                val keyDatas = keyDock.map { it.keyData }.flatten()
+                val newKeyDock = DockData.KeyDock()
+                newKeyDock.keyData.addAll(keyDatas)
+                val newKeyDockList = newKeyDock.keyData.chunked(4).map { subList ->
+                    KeyDock().apply { keyData.addAll(subList) }
                 }
-            }
-            val portableDock = dockData.filter { it.type == DeviceConst.DOCK_TYPE_PORTABLE }.map {
-                DockData.PortableDock().apply {
-                    deviceData.addAll(it.deviceList.toList())
+                val lockDock = dockData.filter { it.type == DeviceConst.DOCK_TYPE_LOCK }.map {
+                    DockData.LockDock().apply {
+                        lockData.addAll(it.deviceList.filterIsInstance<DockBean.LockBean>())
+                    }
                 }
+                val portableDock =
+                    dockData.filter { it.type == DeviceConst.DOCK_TYPE_PORTABLE }.map {
+                        DockData.PortableDock().apply {
+                            deviceData.addAll(it.deviceList.toList())
+                        }
+                    }
+                binding.reRecognize.isVisible =
+                    (newKeyDockList + portableDock + lockDock).isNotEmpty()
+                binding.dockRv.models = newKeyDockList + portableDock + lockDock
             }
-            binding.dockRv.models = newKeyDockList + portableDock + lockDock
         }
     }
 
@@ -181,7 +186,7 @@ class InitDeviceRegistrationKeyAndLockFragment :
         when (event.code) {
             EventConstants.EVENT_START_MODBUS_COMPLETE -> {
                 ThreadUtils.runOnMainDelayed(1000) {
-                    ISCSConfig.canInitDevice = true
+                    viewModel.isInDeviceInit = false
                 }
             }
         }

+ 5 - 0
app/src/main/java/com/grkj/iscs/features/init/fragment/InitPointRfidRegistrationFragment.kt

@@ -18,6 +18,7 @@ import com.grkj.shared.utils.KeyboardUtils
 import com.grkj.ui_base.base.BaseFragment
 import com.grkj.ui_base.config.ISCSConfig
 import com.grkj.ui_base.utils.event.CardSwipeEvent
+import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.extension.saveMMKVData
 import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
@@ -84,6 +85,10 @@ class InitPointRfidRegistrationFragment : BaseFragment<FragmentInitPointRfidRegi
         when (event.code) {
             EventConstants.EVENT_CARD_SWIPE -> {
                 val cardSwipeEvent = (event.data as CardSwipeEvent)
+                if (pointRfidData.contains(cardSwipeEvent.cardNo)){
+                    PopTip.tip(R.string.rfid_already_registration)
+                    return
+                }
                 pointRfidData.add(cardSwipeEvent.cardNo)
                 binding.pointRfidRv.adapter?.notifyDataSetChanged()
                 KeyboardUtils.hideKeyboard(requireActivity())

+ 10 - 2
app/src/main/java/com/grkj/iscs/features/init/fragment/InitWelcomeFragment.kt

@@ -1,11 +1,14 @@
 package com.grkj.iscs.features.init.fragment
 
 import androidx.fragment.app.viewModels
+import com.grkj.data.data.MMKVConstants
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentInitWelcomeBinding
 import com.grkj.iscs.features.init.viewmodel.InitDeviceRegistrationKeyAndLockViewModel
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.CommonUtils
 import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.extension.getMMKVData
 import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
 
@@ -30,8 +33,13 @@ class InitWelcomeFragment : BaseFragment<FragmentInitWelcomeBinding>() {
                 PopTip.tip("清除成功")
             }
         }
-        binding.startBtn.setDebouncedClickListener {
-            navController.navigate(R.id.action_initWelcomeFragment_to_initSetAdminAccountFragment)
+        if (MMKVConstants.KEY_PORT_CONFIG.getMMKVData("").isEmpty()) {
+            binding.startBtn.text = CommonUtils.getStr(R.string.detect_port)
+        } else {
+            binding.startBtn.text = CommonUtils.getStr(R.string.start)
+            binding.startBtn.setDebouncedClickListener {
+                navController.navigate(R.id.action_initWelcomeFragment_to_initSetAdminAccountFragment)
+            }
         }
     }
 }

+ 33 - 49
app/src/main/java/com/grkj/iscs/features/init/viewmodel/InitDeviceRegistrationKeyAndLockViewModel.kt

@@ -1,5 +1,6 @@
 package com.grkj.iscs.features.init.viewmodel
 
+import android.bluetooth.BluetoothDevice
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.liveData
@@ -13,12 +14,16 @@ import com.grkj.ui_base.utils.ble.BleConnectionManager
 import com.grkj.ui_base.utils.modbus.DeviceConst
 import com.grkj.ui_base.utils.modbus.DockBean
 import com.grkj.ui_base.utils.modbus.ModBusController
+import com.sik.sikcore.bluetooth.BLEScanner
+import com.sik.sikcore.bluetooth.BluetoothManager
+import com.sik.sikcore.bluetooth.IBluetoothScanCallback
 import com.sik.sikcore.thread.ThreadUtils
 import com.tencent.mmkv.MMKV
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withContext
 import java.util.concurrent.atomic.AtomicInteger
 import javax.inject.Inject
 import kotlin.coroutines.resume
@@ -30,6 +35,7 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
     var isDestroy: Boolean = false
     var newHardwareKeySize: Int = 0
     var newHardwareLockSize: Int = 0
+    var isInDeviceInit: Boolean = false
     private val newHardwareKeyBean: MutableMap<Byte, MutableList<DockBean.KeyBean>> = mutableMapOf()
     private val alreadyUsedMac: MutableList<String> = mutableListOf()
 
@@ -58,30 +64,21 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
             newHardwareKeyBean.clear()
             alreadyUsedMac.clear()
             isLoadComplete.postValue(false)
-            ModbusBusinessManager.registerInitListener {
-                if (!ISCSConfig.canInitDevice) {
-                    return@registerInitListener
-                }
-                ISCSConfig.canInitDevice = false
-                val dockList = ModBusController.dockList
-                if (dockList.size < DockBean.dockConfig.size) {
-                    ISCSConfig.canInitDevice = true
-                    return@registerInitListener
-                }
-                ThreadUtils.runOnIO {
-                    val allDevice = ModBusController.dockList.map { it.deviceList }.flatten()
-                        .filter { it is DockBean.KeyBean || it is DockBean.LockBean }
-                        .filter { it.isExist }
-                    var currentCheckDevices = AtomicInteger(0)
-                    allDevice.forEach { device ->
-                        checkNewHardware(device) {
-                            currentCheckDevices.addAndGet(1)
-                            if (currentCheckDevices.get() == allDevice.size) {
-                                checkNewHardwareKey(dockList)
-                            }
-                        }
+            ModBusController.controlAllKeyBuckleOpen{
+                ModbusBusinessManager.registerInitListener {
+                    if (!ISCSConfig.canInitDevice || isInDeviceInit) {
+                        return@registerInitListener
+                    }
+                    isInDeviceInit = true
+                    val dockList = ModBusController.dockList
+                    if (dockList.size < DockBean.dockConfig.size) {
+                        isInDeviceInit = true
+                        return@registerInitListener
+                    }
+                    ThreadUtils.runOnIO {
+                        checkNewHardwareKey(dockList)
+                        emit(true)
                     }
-                    emit(true)
                 }
             }
         }
@@ -144,32 +141,19 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
                         ThreadUtils.runOnIO {
                             delay(3000)
                             logger.info("设备录入-开始扫描在线蓝牙Mac")
-                            BleConnectionManager.scanOnlineKeyLockMac(alreadyUsedMac) { bleDevice ->
-                                logger.info(
-                                    "设备录入-在线的蓝牙设备:${keyBean.rfid},${
-                                        bleDevice?.mac
-                                    }"
-                                )
-                                if (isDestroy) {
+                            withContext(Dispatchers.Main){
+                                BleConnectionManager.scanOnlineKeyLockMac(alreadyUsedMac) { mac ->
                                     logger.info(
-                                        "设备录入-界面已销毁"
+                                        "设备录入-在线的蓝牙设备:${keyBean.rfid},${mac}"
                                     )
-                                    cont.cancel()
-                                    return@scanOnlineKeyLockMac
-                                }
-                                if (bleDevice == null) {
-                                    logger.info(
-                                        "设备录入-设备空:${keyBean.rfid}"
-                                    )
-                                    ThreadUtils.runOnIO {
-                                        if (retryCount > 0) {
-                                            openChargeAndScanMac(addr, keyBean, retryCount - 1)
-                                        } else {
-                                            cont.resume(false)
-                                        }
+                                    if (isDestroy) {
+                                        logger.info(
+                                            "设备录入-界面已销毁"
+                                        )
+                                        cont.cancel()
+                                        return@scanOnlineKeyLockMac
                                     }
-                                } else {
-                                    if (bleDevice.mac == null) {
+                                    if (mac == null) {
                                         logger.info(
                                             "设备录入-设备mac空:${keyBean.rfid}"
                                         )
@@ -184,11 +168,11 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
                                     }
                                     logger.info(
                                         "设备录入-没有使用过的mac:${keyBean.rfid},${
-                                            bleDevice.mac
+                                            mac
                                         }"
                                     )
-                                    keyBean.mac = bleDevice.mac
-                                    alreadyUsedMac.add(bleDevice.mac)
+                                    keyBean.mac = mac
+                                    alreadyUsedMac.add(mac)
                                     if (cont.isActive) {
                                         cont.resume(true)
                                     }

+ 16 - 2
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/CreateJobFragment.kt

@@ -87,7 +87,14 @@ class CreateJobFragment : BaseFormFragment<FragmentCreateJobBinding>() {
                     dialogType = TipDialog.DialogType.INFO,
                     countDownTime = 10,
                     onConfirmClick = {
-                        createJob(null)
+                        ThreadUtils.runOnIO {
+                            val sopId = if (binding.saveSop.isChecked) {
+                                saveSop()
+                            } else {
+                                null
+                            }
+                            createJob(sopId)
+                        }
                     })
             }
         }
@@ -102,7 +109,14 @@ class CreateJobFragment : BaseFormFragment<FragmentCreateJobBinding>() {
                     dialogType = TipDialog.DialogType.INFO,
                     countDownTime = 10,
                     onConfirmClick = {
-                        createJob(null, true)
+                        ThreadUtils.runOnIO {
+                            val sopId = if (binding.saveSop.isChecked) {
+                                saveSop()
+                            } else {
+                                null
+                            }
+                            createJob(sopId, true)
+                        }
                     })
             }
         }

+ 5 - 5
app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/UserManageViewModel.kt

@@ -117,11 +117,11 @@ class UserManageViewModel @Inject constructor(
                 )
             }
             roleRepository.addUserRoleData(updateUserDataVo.userId, updateUserDataVo.roleId)
-            hardwareRepository.addCard(
-                updateUserDataVo.userId,
-                updateUserDataVo.cardCode,
-                updateUserDataVo.nickname
-            )
+//            hardwareRepository.addCard(
+//                updateUserDataVo.userId,
+//                updateUserDataVo.cardCode,
+//                updateUserDataVo.nickname
+//            )
             emit(true)
         }
     }

+ 3 - 0
app/src/main/res/values-en/strings.xml

@@ -332,5 +332,8 @@
     <string name="invalid_card">Invalid card</string>
     <string name="invalid_user">Invalid User</string>
     <string name="currently_unable_to_lock_together">Currently unable to colock or uncolock</string>
+    <string name="detect_port">Scanning Device......</string>
+    <string name="card_already_registration">Card already registration</string>
+    <string name="rfid_already_registration">RFID already registration</string>
 
 </resources>

+ 4 - 4
app/src/main/res/values-land/dimens.xml

@@ -47,10 +47,10 @@
     <dimen name="common_spacing_1_5x">15dp</dimen>
     <dimen name="init_margin_space">120dp</dimen>
     <dimen name="init_set_admin_account_et_height">51dp</dimen>
-    <dimen name="init_key_iv_width">50dp</dimen>
-    <dimen name="init_key_iv_height">35dp</dimen>
-    <dimen name="init_lock_iv_width">30dp</dimen>
-    <dimen name="init_lock_iv_height">70dp</dimen>
+    <dimen name="init_key_iv_width">85dp</dimen>
+    <dimen name="init_key_iv_height">60dp</dimen>
+    <dimen name="init_lock_iv_width">51dp</dimen>
+    <dimen name="init_lock_iv_height">119dp</dimen>
     <dimen name="login_method_item_layout_width">341dp</dimen>
     <dimen name="login_method_item_layout_height">384dp</dimen>
     <dimen name="login_method_item_iv_size">205dp</dimen>

+ 3 - 0
app/src/main/res/values-zh/strings.xml

@@ -332,5 +332,8 @@
     <string name="invalid_card">卡片无效</string>
     <string name="invalid_user">用户不存在</string>
     <string name="currently_unable_to_lock_together">当前阶段无法共锁</string>
+    <string name="detect_port">正在扫描设备......</string>
+    <string name="card_already_registration">卡片已录入</string>
+    <string name="rfid_already_registration">RFID标签已录入</string>
 
 </resources>

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -335,5 +335,8 @@
     <string name="invalid_card">卡片无效</string>
     <string name="invalid_user">用户不存在</string>
     <string name="currently_unable_to_lock_together">当前阶段无法共锁</string>
+    <string name="detect_port">正在扫描设备......</string>
+    <string name="card_already_registration">卡片已录入</string>
+    <string name="rfid_already_registration">RFID标签已录入</string>
 
 </resources>

+ 5 - 0
data/src/main/java/com/grkj/data/data/EventConstants.kt

@@ -51,6 +51,11 @@ object EventConstants {
      */
     const val EVENT_START_MODBUS_COMPLETE = 100_000_009
 
+    /**
+     * 重启app
+     */
+    const val EVENT_RESTART_APP = 100_000_010
+
     //---------------------------作业票------------------------
     const val EVENT_GET_TICKET_STATUS: Int = 100_001_001
 

+ 1 - 1
gradle/libs.versions.toml

@@ -11,7 +11,7 @@ material = "1.10.0"
 activity = "1.8.0"
 constraintlayout = "2.1.4"
 jetbrainsKotlinJvm = "2.0.21"
-sikextension = "1.1.46"
+sikextension = "1.1.50"
 sikcamera = "1.0.11"
 sikcronjob = "1.0.3"
 sikfontmanager = "1.0.2"

+ 3 - 4
ui-base/src/main/java/com/grkj/ui_base/business/BleBusinessManager.kt

@@ -99,7 +99,7 @@ object BleBusinessManager {
                     ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
                         logger.info("钥匙: ${bleBean.bleDevice.mac} 开始充电")
                     }
-                } else {
+                } else if (power > 90) {
                     ModBusController.controlKeyCharge(false, bleBean.bleDevice.mac) {
                         logger.info("钥匙: ${bleBean.bleDevice.mac} 关闭充电")
                     }
@@ -521,6 +521,7 @@ object BleBusinessManager {
             logger.info("作业票信息:${workTicketGet}")
             if (workTicketGet == null) {
                 PopTip.tip(R.string.ticket_data_error)
+                switchReadyMode(bleDevice)
                 return@handleTicketStatus
             }
 
@@ -601,9 +602,7 @@ object BleBusinessManager {
                             SIKCore.getApplication().serialNo()
                         ) { isSuccess, msg, code ->
                             logger.info("钥匙归还:${isSuccess},${msg},${code}")
-                            if (!isSuccess && msg != SIKCore.getApplication().getString(
-                                    R.string.ticket_lost
-                                )
+                            if (!isSuccess && code != 500
                             ) {
                                 SPUtils.saveUpdateKeyReturn(
                                     SIKCore.getApplication(),

+ 8 - 3
ui-base/src/main/java/com/grkj/ui_base/dialog/LoadingDialog.kt

@@ -38,9 +38,14 @@ class LoadingDialog : OnBindView<CustomDialog>(R.layout.common_dialog_loading_pr
         fun show(msg: String? = null) {
             ThreadUtils.runOnMain {
                 loadingDialog?.dismiss()
-                loadingDialog = CustomDialog.show(LoadingDialog().apply {
-                    setMessage(msg)
-                }, CustomDialog.ALIGN.CENTER)
+                loadingDialog = CustomDialog.build().apply {
+                    setCustomView(LoadingDialog().apply {
+                        setMessage(msg)
+                    })
+                    setAlign(CustomDialog.ALIGN.CENTER)
+                    setEnterAnimDuration(0)
+                    setExitAnimDuration(0)
+                }.show()
             }
         }
 

+ 45 - 28
ui-base/src/main/java/com/grkj/ui_base/utils/ble/BleConnectionManager.kt

@@ -1,5 +1,6 @@
 package com.grkj.ui_base.utils.ble
 
+import android.bluetooth.BluetoothDevice
 import android.bluetooth.BluetoothGatt
 import com.clj.fastble.BleManager
 import com.clj.fastble.data.BleDevice
@@ -11,7 +12,10 @@ import com.grkj.ui_base.utils.event.LoadingEvent
 import com.grkj.shared.utils.extension.startsWith
 import com.grkj.shared.utils.extension.toHexStrings
 import com.grkj.ui_base.utils.modbus.ModBusController
+import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.activity.ActivityTracker
+import com.sik.sikcore.bluetooth.BLEScanner
+import com.sik.sikcore.bluetooth.IBluetoothScanCallback
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.delay
@@ -697,39 +701,52 @@ object BleConnectionManager {
     /**
      * 扫描在线的蓝牙
      */
-    fun scanOnlineKeyLockMac(existsMac: List<String>, callback: (BleDevice?) -> Unit) {
-        BleUtil.instance?.scan(object : CustomBleScanCallback() {
-            override fun onPrompt(promptStr: String?) {
-                // 蓝牙未启动重试
-                logger.info("设备录入-参数:${promptStr}")
-                BleManager.getInstance().enableBluetooth()
-                ThreadUtils.runOnMainDelayed(5000) {
-                    scanOnlineKeyLockMac(existsMac, callback)
-                }
+    fun scanOnlineKeyLockMac(existsMac: List<String>, callback: (String?) -> Unit) {
+        BLEScanner.stopScan()
+        BLEScanner.startScan(object : IBluetoothScanCallback {
+            override fun onDeviceFound(device: BluetoothDevice) {
+                logger.info("发现设备:${device.address}")
+                callback(device.address)
             }
 
-            override fun onScanStarted(success: Boolean) {
-                logger.info("设备录入-onScanStarted:${success}")
-                if (!success) {
-                    ThreadUtils.runOnMainDelayed(300) {
-                        scanOnlineKeyLockMac(existsMac, callback)
-                    }
-                }
-            }
+            override fun onScanFinished() {
 
-            override fun onScanning(bleDevice: BleDevice?) {
-                val mac = bleDevice?.mac ?: return
-                logger.info("设备录入-onScanning:$mac")
-                if (mac !in existsMac) {
-                    BleManager.getInstance().cancelScan()
-                }
             }
 
-            override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
-                logger.info("设备录入-扫描完成:${scanResultList?.joinToString(",") { it.mac }}")
-                callback(scanResultList?.find { it.mac !in existsMac })
-            }
-        })
+        }, knownDevices = existsMac, stopFirst = true, nameFilter = BleConst.BLE_LOCAL_NAME)
+//        BleUtil.instance?.scan(object : CustomBleScanCallback() {
+//            override fun onPrompt(promptStr: String?) {
+//                // 蓝牙未启动重试
+//                logger.info("设备录入-参数:${promptStr}")
+//                PopTip.tip(R.string.please_reopen_ble)
+//                BleManager.getInstance().enableBluetooth()
+//                ThreadUtils.runOnMainDelayed(5000) {
+//                    scanOnlineKeyLockMac(existsMac, callback)
+//                }
+//            }
+//
+//            override fun onScanStarted(success: Boolean) {
+//                logger.info("设备录入-onScanStarted:${success}")
+//                if (!success) {
+//                    ThreadUtils.runOnMainDelayed(300) {
+//                        scanOnlineKeyLockMac(existsMac, callback)
+//                    }
+//                }
+//            }
+//
+//            override fun onScanning(bleDevice: BleDevice?) {
+//                val mac = bleDevice?.mac ?: return
+//                logger.info("设备录入-onScanning:$mac")
+//                if (mac !in existsMac) {
+//                    BleManager.getInstance().cancelScan()
+//                }
+//            }
+//
+//            override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
+//                logger.info("设备录入-扫描完成:${scanResultList?.joinToString(",") { it.mac }}")
+//                callback(scanResultList?.find { it.mac !in existsMac }?.mac)
+//            }
+//        })
     }
 
 

+ 24 - 1
ui-base/src/main/java/com/grkj/ui_base/utils/ble/BleUtil.kt

@@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory
  */
 class BleUtil private constructor() {
     private val logger: Logger = LoggerFactory.getLogger(BleUtil::class.java)
+    private var inScan: Boolean = false
 
     companion object {
         var instance: BleUtil? = null
@@ -56,7 +57,29 @@ class BleUtil private constructor() {
     fun scan(bleScanCallback: CustomBleScanCallback) {
         if (BleManager.getInstance().isSupportBle) {
             if (BleManager.getInstance().isBlueEnable) {
-                BleManager.getInstance().scan(bleScanCallback)
+                if (inScan) {
+                    BleManager.getInstance().cancelScan()
+                }
+                BleManager.getInstance().scan(object : CustomBleScanCallback(){
+                    override fun onPrompt(promptStr: String?) {
+                        bleScanCallback.onPrompt(promptStr)
+                    }
+
+                    override fun onScanFinished(p0: List<BleDevice?>?) {
+                        inScan = false
+                        bleScanCallback.onScanFinished(p0)
+                    }
+
+                    override fun onScanStarted(p0: Boolean) {
+                        inScan = true
+                        bleScanCallback.onScanStarted(p0)
+                    }
+
+                    override fun onScanning(p0: BleDevice?) {
+                        bleScanCallback.onScanning(p0)
+                    }
+
+                })
             } else {
                 bleScanCallback.onPrompt("请打开您的蓝牙后重试")
             }

+ 24 - 0
ui-base/src/main/java/com/grkj/ui_base/utils/event/RestartAppEvent.kt

@@ -0,0 +1,24 @@
+package com.grkj.ui_base.utils.event
+
+import com.grkj.shared.model.EventBean
+import com.grkj.data.data.EventConstants
+
+/**
+ * 重启App事件
+ */
+class RestartAppEvent() {
+
+    companion object {
+        /**
+         * 发送重启app事件
+         */
+        @JvmStatic
+        fun sendRestartAppEvent() {
+            val restartAppEvent = RestartAppEvent()
+            val restartAppEventBean = EventBean<RestartAppEvent>(
+                EventConstants.EVENT_RESTART_APP, restartAppEvent
+            )
+            EventHelper.sendEvent(restartAppEventBean)
+        }
+    }
+}

+ 5 - 3
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusController.kt

@@ -194,7 +194,7 @@ object ModBusController {
                             updateLockNewHardware(
                                 dockBean.addr,
                                 idx,
-                                it?.lockNfc?.isEmpty() == true
+                                it == null || it.lockNfc?.isEmpty() == true
                             )
                         }
                     }
@@ -230,7 +230,7 @@ object ModBusController {
                                 updateKeyNewHardware(
                                     dockBean.addr,
                                     key.idx,
-                                    keyInfo?.keyNfc?.isEmpty() == true || keyInfo?.macAddress?.isEmpty() == true
+                                    keyInfo == null || keyInfo.keyNfc?.isEmpty() == true || keyInfo.macAddress?.isEmpty() == true
                                 )
                                 if (keyInfo != null && !keyInfo.macAddress.isNullOrEmpty()) {
                                     // 更新mac
@@ -275,6 +275,7 @@ object ModBusController {
                 }
             }
         if (!ISCSConfig.isInit) {
+            ISCSConfig.canInitDevice = true
             ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
         }
     }
@@ -732,12 +733,13 @@ object ModBusController {
     /**
      * 打开所有钥匙锁仓并关闭充电
      */
-    fun controlAllKeyBuckleOpen() {
+    fun controlAllKeyBuckleOpen(complete:()-> Unit = {}) {
         dockList.filter { it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
             .forEach { dock ->
                 dock.type?.let { dockType ->
                     ModBusCMDHelper.generateAllKeyBuckleOpenCmd(dockType).let { cmd ->
                         modBusManager?.sendTo(dock.addr, cmd) { res ->
+                            complete()
                         }
                     }
                 }

+ 42 - 3
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/PortManager.kt

@@ -1,10 +1,17 @@
 package com.grkj.ui_base.utils.modbus
 
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
 import androidx.annotation.WorkerThread
 import com.epton.sdk.SerialPort
 import com.grkj.data.data.MMKVConstants
 import com.grkj.shared.utils.extension.toHexStrings
+import com.grkj.ui_base.R
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.event.RestartAppEvent
 import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.SIKCore
 import com.sik.sikcore.extension.getMMKVData
 import com.sik.sikcore.extension.saveMMKVData
 import com.sik.sikcore.extension.toJson
@@ -18,6 +25,7 @@ import java.io.OutputStream
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
 import java.util.concurrent.TimeoutException
+import kotlin.system.exitProcess
 
 /**
  * 串口通信管理器
@@ -147,10 +155,37 @@ class PortManager private constructor(
             perAddrTimeoutMs: Long = 700        // 地址检测超时 700 ms
         ): String? {
             isDetectMode = true
-            // 1. 列出所有串口
+            // —— 1. 找出系统/蓝牙保留的 ttyS 口 ——
+            val reserved = mutableSetOf<String>()
+            runCatching {
+                val cmdline = File("/proc/cmdline").readText()
+                Regex("console=(ttyS\\d+)").find(cmdline)?.groupValues?.get(1)
+                    ?.let { reserved += it }
+            }
+            // b) Bluetooth HCI(假如你在 bt_vendor.conf 指定了)
+            runCatching {
+                File("/etc/bluetooth/bt_vendor.conf").readLines()
+                    .mapNotNull { line ->
+                        val clean = line.substringBefore('#')     // 去掉注释
+                        val parts = clean.split('=', limit = 2)
+                        if (parts.size == 2 && parts[0].trim().equals("UartPort", true)) {
+                            parts[1].trim().removeSurrounding("\"")
+                        } else null
+                    }
+                    .forEach { path ->
+                        if (path.startsWith("/dev/")) reserved += path.removePrefix("/dev/")
+                    }
+            }
+
+            // c) 手动补充其他保留口
+            reserved += listOf("ttyS0"/*蓝牙*/, "ttyS1" /* ADB-over-UART */, "ttyS2" /* Modem */)
+
+            logger.info("忽略的串口: $reserved")
             val devs = File("/dev").listFiles { _, name ->
-                name.startsWith("ttyS")
+                name.startsWith("ttyS") && name !in reserved
             }?.map { it.absolutePath } ?: return null
+
+            logger.info("将要检测的串口: $devs")
             logger.info("共发现 ${devs.size} 个串口,开始依次串行检测")
 
             // 2. 用线程池来做 open()/checkSlave() 的超时调度
@@ -352,14 +387,18 @@ class PortManager private constructor(
             if (newPort != null) {
                 // 3. 扫描到就保存,下次直接用
                 MMKVConstants.KEY_PORT_CONFIG.saveMMKVData(newPort)
+                PopTip.tip(CommonUtils.getStr(R.string.scan_complete_app_restarting))
+                RestartAppEvent.sendRestartAppEvent()
                 logger.info("扫描到新主控板串口: $newPort")
-                return open(newPort, baud)
+                return null
             } else {
                 PopTip.tip("未找到从机,请检查硬件连接")
                 return null
             }
         }
 
+
     }
 
+
 }

+ 2 - 0
ui-base/src/main/res/values-en/strings.xml

@@ -364,4 +364,6 @@
     <string name="ticket_data_error">Ticket data error</string>
     <string name="job_already_finished">job already finished</string>
     <string name="not_save_tip">Data not save,Do you want to lost save and leave?</string>
+    <string name="please_reopen_ble">Please reopen ble</string>
+    <string name="scan_complete_app_restarting">scan complete app restarting</string>
 </resources>

+ 2 - 0
ui-base/src/main/res/values-zh/strings.xml

@@ -364,4 +364,6 @@
     <string name="ticket_data_error">工作票数据损坏</string>
     <string name="job_already_finished">该作业已被结束</string>
     <string name="not_save_tip">数据还没有保存,您确定要放弃保存,离开当前页面吗?</string>
+    <string name="please_reopen_ble">请重新打开蓝牙</string>
+    <string name="scan_complete_app_restarting">扫描完成,APP将自动重启</string>
 </resources>

+ 2 - 0
ui-base/src/main/res/values/strings.xml

@@ -364,4 +364,6 @@
     <string name="ticket_data_error">工作票数据损坏</string>
     <string name="job_already_finished">该作业已被结束</string>
     <string name="not_save_tip">数据还没有保存,您确定要放弃保存,离开当前页面吗?</string>
+    <string name="please_reopen_ble">请重新打开蓝牙</string>
+    <string name="scan_complete_app_restarting">扫描完成,APP将自动重启</string>
 </resources>