Ver código fonte

refactor(硬件状态):
- 修改硬件状态的界面
- 新增锁仓锁定状态查询

周文健 5 meses atrás
pai
commit
9fb42df8a4

+ 100 - 1
app/src/main/java/com/grkj/iscs/BusinessManager.kt

@@ -283,10 +283,31 @@ object BusinessManager {
             tipStr += addressList
             ToastUtils.tip(tipStr)
         }
+        res.forEach { bytes ->
+            val dockBean = ModBusController.updateExtraLockStatus(bytes) ?: return@forEach
+            ModBusController.isInitReady = true
+            if (!CAN_RETURN) {
+                return@forEach
+            }
+            when (dockBean.type) {
+                DOCK_TYPE_LOCK -> {
+                    dockBean.getLockList().filter { it.idx > 7 }.forEach { lockBean ->
+                        ModBusController.updateLockStatus(
+                            dockBean.addr,
+                            lockBean.idx,
+                            lockBean.lockEnabled
+                        )
+                    }
+                }
+            }
+            Executor.delayOnMain(200) {
+                listeners.forEach { it.callBack(dockBean) }
+            }
+        }
     }
 
     /**
-     * 第1-8锁位卡扣状态
+     * 第1-8锁位卡扣状态和钥匙
      */
     private fun lockBuckleStatus(res: Any) {
         LogUtil.i("硬件状态:${(res as List<ByteArray>).map { it.toHexStrings() }}")
@@ -302,6 +323,84 @@ object BusinessManager {
             tipStr += addressList
             ToastUtils.tip(tipStr)
         }
+
+        res.forEach { bytes ->
+            val dockBean = ModBusController.updateLockStatus(bytes) ?: return@forEach
+            ModBusController.isInitReady = true
+            if (!CAN_RETURN) {
+                return@forEach
+            }
+            when (dockBean.type) {
+                DOCK_TYPE_KEY -> {
+                    dockBean.getKeyList().forEach { keyBean ->
+                        ModBusController.updateKeyLockStatus(
+                            dockBean.addr,
+                            keyBean.isLeft,
+                            keyBean.lockEnabled
+                        )
+                        //todo 更新锁仓状态
+                    }
+                }
+
+                DOCK_TYPE_LOCK -> {
+                    dockBean.getLockList().forEach { lockBean ->
+                        ModBusController.updateLockStatus(
+                            dockBean.addr,
+                            lockBean.idx,
+                            lockBean.lockEnabled
+                        )
+                    }
+                }
+
+                DOCK_TYPE_ELEC_LOCK_BOARD -> {
+                    // TODO 占位
+                }
+
+                DOCK_TYPE_PORTABLE -> {
+                    // TODO 便携式待完善
+                    dockBean.deviceList.forEach { deviceBean ->
+                        if (deviceBean.isExist) {
+                            when (deviceBean.type) {
+                                DEVICE_TYPE_KEY -> {
+                                    ModBusController.updateKeyLockStatus(
+                                        dockBean.addr,
+                                        true,
+                                        deviceBean.lockEnabled
+                                    )
+                                }
+
+                                DEVICE_TYPE_LOCK -> {
+                                    ModBusController.updateLockStatus(
+                                        dockBean.addr,
+                                        deviceBean.idx,
+                                        deviceBean.lockEnabled
+                                    )
+                                }
+
+                                DEVICE_TYPE_CARD -> {
+                                    ModBusController.readPortalCaseCardRfid(dockBean.addr) { res ->
+                                        if (res.size < 11) {
+                                            LogUtil.e("Portal Case card rfid error")
+                                            return@readPortalCaseCardRfid
+                                        }
+                                        val rfid = res.copyOfRange(3, 11).toHexStrings(false)
+                                            .removeLeadingZeros()
+                                        LogUtil.i("卡片RFID : $rfid")
+                                    }
+                                }
+
+                                DEVICE_TYPE_FINGERPRINT -> {
+
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            Executor.delayOnMain(200) {
+                listeners.forEach { it.callBack(dockBean) }
+            }
+        }
     }
 
     /**

+ 165 - 16
app/src/main/java/com/grkj/iscs/modbus/DockBean.kt

@@ -22,7 +22,9 @@ class DockBean(
     var type: Byte?,
     var deviceList: MutableList<DeviceBean>
 ) {
-
+    /**
+     * 转换状态
+     */
     fun parseStatus(byteArray: ByteArray): DockBean? {
         if (byteArray.isEmpty()) {
             return null
@@ -37,8 +39,28 @@ class DockBean(
                     val isRightCharging = (byteArray[3].toInt() shr 1) and 0x1 == 1
                     LogUtil.i("钥匙刷新状态 : $leftHasKey - $isLeftCharging - $rightHasKey - $isRightCharging")
                     if (getKeyList().isEmpty()) {
-                        deviceList.add(KeyBean(0, leftHasKey, true, isLeftCharging, null, null))
-                        deviceList.add(KeyBean(1, rightHasKey, false, isRightCharging, null, null))
+                        deviceList.add(
+                            KeyBean(
+                                0,
+                                leftHasKey,
+                                true,
+                                isLeftCharging,
+                                false,
+                                null,
+                                null
+                            )
+                        )
+                        deviceList.add(
+                            KeyBean(
+                                1,
+                                rightHasKey,
+                                false,
+                                isRightCharging,
+                                false,
+                                null,
+                                null
+                            )
+                        )
                         return null
                     }
 
@@ -89,7 +111,7 @@ class DockBean(
 
                     if (getLockList().isEmpty()) {
                         for (i in 0 until tempList.size) {
-                            deviceList.add(LockBean(i, tempList[i], null))
+                            deviceList.add(LockBean(i, tempList[i], false, null))
                         }
                     }
 
@@ -124,7 +146,7 @@ class DockBean(
                     }
                     if (getLockList().isEmpty()) {
                         for (i in 0 until tempList.size) {
-                            deviceList.add(LockBean(i, tempList[i], null))
+                            deviceList.add(LockBean(i, tempList[i], false, null))
                         }
                     }
 
@@ -132,7 +154,17 @@ class DockBean(
                     val isKeyCharging = (byteArray[3].toInt() shr 1) and 0x1 == 1
 
                     if (getKeyList().isEmpty()) {
-                        deviceList.add(KeyBean(4, isKeyExist, true, isKeyCharging, null, null))
+                        deviceList.add(
+                            KeyBean(
+                                4,
+                                isKeyExist,
+                                true,
+                                isKeyCharging,
+                                false,
+                                null,
+                                null
+                            )
+                        )
                     }
 
                     val isCardExist = (byteArray[3].toInt() shr 4) and 0x1 == 1
@@ -191,6 +223,118 @@ class DockBean(
         } ?: return null
     }
 
+    /**
+     * 转换锁仓状态
+     */
+    fun parseLockStatus(byteArray: ByteArray): DockBean? {
+        if (byteArray.isEmpty()) {
+            return null
+        }
+        type?.let {
+            // 因为都是一个寄存器返回的,所以一定能得到2个钥匙的状态或者10把锁具的状态
+            when (it) {
+                DOCK_TYPE_KEY -> {
+                    val leftKeyLockEnabled = (byteArray[4].toInt() shr 0) and 0x1 == 1
+                    val rightKeyLockEnabled = (byteArray[4].toInt() shr 4) and 0x1 == 1
+                    LogUtil.i("钥匙锁仓状态 : $leftKeyLockEnabled - $rightKeyLockEnabled")
+                    if (getKeyList().isEmpty()) {
+                        return null
+                    }
+                    val changeList = mutableListOf<DeviceBean>()
+                    getKeyList().forEach { keyBean ->
+                        if (keyBean.isLeft) {
+                            keyBean.lockEnabled = leftKeyLockEnabled
+                        } else {
+                            keyBean.lockEnabled = rightKeyLockEnabled
+                        }
+                    }
+
+                    return DockBean(addr, it, changeList)
+                }
+
+                DOCK_TYPE_LOCK -> {
+                    val tempList = mutableListOf<Boolean>()
+                    for (i in 0..7) {
+                        tempList.add((byteArray[4].toInt() shr i) and 0x1 == 1)
+                    }
+
+                    if (getLockList().isEmpty()) {
+                        return null
+                    }
+
+                    val changeList = mutableListOf<DeviceBean>()
+                    for (i in 0 until getLockList().size) {
+                        getLockList()[i].lockEnabled = tempList[i]
+                    }
+
+                    LogUtil.i("锁具刷新状态 : $changeList")
+                    return DockBean(addr, it, changeList)
+                }
+
+                DOCK_TYPE_ELEC_LOCK_BOARD -> {
+                    // TODO 临时占位
+                    return null
+                }
+
+                DOCK_TYPE_PORTABLE -> {
+                    // TODO 便携式底座更新
+                    val tempList = mutableListOf<Boolean>()
+                    for (i in 0..2) {
+                        tempList.add((byteArray[4].toInt() shr i) and 0x1 == 1)
+                    }
+                    val keyLockEnabled = (byteArray[4].toInt() shr 4) and 0x1 == 1
+
+                    val changeList = mutableListOf<DeviceBean>()
+                    // 锁具变化
+                    for (i in 0 until getLockList().size) {
+                        getLockList()[i].lockEnabled = tempList[i]
+                    }
+                    // 蓝牙钥匙变化
+                    if (getKeyList().isNotEmpty()) {
+                        getKeyList()[0].lockEnabled = keyLockEnabled
+                    }
+                    LogUtil.i("便携式刷新状态 : $changeList")
+                    return DockBean(addr, it, changeList)
+                }
+
+                else -> return null
+            }
+        } ?: return null
+    }
+
+    /**
+     * 获取额外的9,10锁仓数据
+     */
+    fun parseExtraLockStatus(byteArray: ByteArray): DockBean? {
+        if (byteArray.isEmpty()) {
+            return null
+        }
+        type?.let {
+            // 因为都是一个寄存器返回的,所以一定能得到2个钥匙的状态或者10把锁具的状态
+            when (it) {
+
+                DOCK_TYPE_LOCK -> {
+                    val tempList = mutableListOf<Boolean>()
+                    for (i in 0..1) {
+                        tempList.add((byteArray[4].toInt() shr i) and 0x1 == 1)
+                    }
+                    if (getLockList().isEmpty()) {
+                        return null
+                    }
+                    val changeList = mutableListOf<DeviceBean>()
+                    for (i in getLockList().size - 2 until getLockList().size) {
+                        getLockList()[i].lockEnabled = tempList[i]
+                    }
+
+                    LogUtil.i("锁具刷新状态 : $changeList")
+                    return DockBean(addr, it, changeList)
+                }
+
+                else -> return null
+            }
+        } ?: return null
+    }
+
     fun getKeyList(): MutableList<KeyBean> {
         return deviceList.filterIsInstance<KeyBean>().filter { it.type == DEVICE_TYPE_KEY }
             .toMutableList()
@@ -239,7 +383,8 @@ class DockBean(
     sealed class DeviceBean(
         var type: Int,
         var idx: Int,
-        var isExist: Boolean
+        var isExist: Boolean,
+        var lockEnabled: Boolean = false,
     ) {
         override fun toString(): String {
             return "DeviceBean(type=$type, idx=$idx, isExist=$isExist)"
@@ -255,16 +400,17 @@ class DockBean(
         isExist: Boolean,
         var isLeft: Boolean,
         var isCharging: Boolean,
+        lockEnabled: Boolean = false,
         var rfid: String?,
         var mac: String?,
         var isReady: Boolean = false    // 钥匙是否准备好(连接上且为待机模式)
-    ) : DeviceBean(DEVICE_TYPE_KEY, idx, isExist) {
+    ) : DeviceBean(DEVICE_TYPE_KEY, idx, isExist, lockEnabled) {
         override fun toString(): String {
             return "KeyBean(isLeft=$isLeft, isCharging=$isCharging, rfid=$rfid, mac=$mac, isReady=$isReady, idx=$idx, isExist=$isExist)"
         }
 
         fun clone(): KeyBean {
-            return KeyBean(idx, isExist, isLeft, isCharging, rfid, mac, isReady)
+            return KeyBean(idx, isExist, isLeft, isCharging, lockEnabled, rfid, mac, isReady)
         }
     }
 
@@ -276,14 +422,15 @@ class DockBean(
     class LockBean(
         idx: Int,
         isExist: Boolean,
-        var rfid: String?
-    ) : DeviceBean(DEVICE_TYPE_LOCK, idx, isExist) {
+        lockEnabled: Boolean = false,
+        var rfid: String?,
+    ) : DeviceBean(DEVICE_TYPE_LOCK, idx, isExist, lockEnabled) {
         override fun toString(): String {
             return "LockBean(rfid=$rfid, idx=$idx, isExist=$isExist)"
         }
 
         fun clone(): LockBean {
-            return LockBean(idx, isExist, rfid)
+            return LockBean(idx, isExist, lockEnabled, rfid)
         }
     }
 
@@ -292,14 +439,16 @@ class DockBean(
      */
     class CardBean(
         idx: Int,
-        isExist: Boolean
-    ) : DeviceBean(DEVICE_TYPE_CARD, idx, isExist)
+        isExist: Boolean,
+        lockEnabled: Boolean = false,
+    ) : DeviceBean(DEVICE_TYPE_CARD, idx, isExist, lockEnabled)
 
     /**
      * 指纹
      */
     class FingerPrintBean(
         idx: Int,
-        isExist: Boolean
-    ) : DeviceBean(DEVICE_TYPE_FINGERPRINT, idx, isExist)
+        isExist: Boolean,
+        lockEnabled: Boolean = false,
+    ) : DeviceBean(DEVICE_TYPE_FINGERPRINT, idx, isExist, lockEnabled)
 }

+ 57 - 2
app/src/main/java/com/grkj/iscs/modbus/ModBusController.kt

@@ -16,7 +16,6 @@ import com.grkj.iscs.util.Executor
 import com.grkj.iscs.util.NetApi
 import com.grkj.iscs.util.ToastUtils
 import com.grkj.iscs.util.log.LogUtil
-import java.util.concurrent.Executors
 import java.util.stream.Collectors
 
 
@@ -239,7 +238,7 @@ object ModBusController {
     }
 
     /**
-     * 新状态
+     * 获取最新状态
      */
     fun updateStatus(byteArray: ByteArray): DockBean? {
         if (byteArray.isEmpty()) {
@@ -249,6 +248,28 @@ object ModBusController {
         return dockB?.parseStatus(byteArray)
     }
 
+    /**
+     * 获取第1-8的锁仓数据和左右钥匙数据
+     */
+    fun updateLockStatus(byteArray: ByteArray): DockBean? {
+        if (byteArray.isEmpty()) {
+            return null
+        }
+        val dockB = dockList.find { it.addr == byteArray[0] }
+        return dockB?.parseLockStatus(byteArray)
+    }
+
+    /**
+     * 获取额外的9,10锁仓数据
+     */
+    fun updateExtraLockStatus(byteArray: ByteArray): DockBean? {
+        if (byteArray.isEmpty()) {
+            return null
+        }
+        val dockB = dockList.find { it.addr == byteArray[0] && it.type == DOCK_TYPE_KEY }
+        return dockB?.parseExtraLockStatus(byteArray)
+    }
+
     /**
      * 读取设备类型
      */
@@ -380,6 +401,14 @@ object ModBusController {
             ?.find { it.isLeft == isLeft }?.rfid = rfid
     }
 
+    /**
+     * 更新钥匙锁仓状态
+     */
+    fun updateKeyLockStatus(slaveAddress: Byte, isLeft: Boolean, lockEnabled: Boolean) {
+        dockList.find { it.addr == slaveAddress }?.getKeyList()
+            ?.find { it.isLeft == isLeft }?.lockEnabled = lockEnabled
+    }
+
     /**
      * 更新钥匙MAC
      */
@@ -404,6 +433,14 @@ object ModBusController {
             rfid
     }
 
+    /**
+     * 更新锁仓状态
+     */
+    fun updateLockStatus(slaveAddress: Byte, lockIdx: Int, lockEnabled: Boolean) {
+        dockList.find { it.addr == slaveAddress }?.getLockList()
+            ?.find { it.idx == lockIdx }?.lockEnabled = lockEnabled
+    }
+
     /**
      * 设备是否存在,加入deviceType防止有重复的但是不同类型的
      *
@@ -514,6 +551,24 @@ object ModBusController {
             ?.find { it.isLeft == isLeft && it.isExist } != null
     }
 
+    /**
+     * 获取钥匙锁仓的锁定状态
+     */
+    fun getKeyBuckleLockEnabled(dockAddr: Byte?, isLeft: Boolean): Boolean {
+        dockAddr ?: return false
+        return dockList.find { it.addr == dockAddr }?.getKeyList()
+            ?.find { it.isLeft == isLeft }?.lockEnabled == true
+    }
+
+    /**
+     * 获取挂锁锁仓的锁定状态
+     */
+    fun getLockBuckleLockEnabled(dockAddr: Byte?, lockIdx: Int): Boolean {
+        dockAddr ?: return false
+        return dockList.find { it.addr == dockAddr }?.getLockList()
+            ?.find { it.idx == lockIdx }?.lockEnabled == true
+    }
+
     fun isLockExist(dockAddr: Byte?, lockIdx: Int): Boolean {
         dockAddr ?: return false
         return dockList.find { it.addr == dockAddr }?.getLockList()

+ 10 - 3
app/src/main/java/com/grkj/iscs/model/UrlConsts.kt

@@ -1,11 +1,12 @@
 package com.grkj.iscs.model
 
 object UrlConsts {
-//    const val BASE_URL = "http://192.168.28.82:9190"  // 本地
+    //    const val BASE_URL = "http://192.168.28.82:9190"  // 本地
 //    const val BASE_URL = "http://192.168.28.97:9190"    // 车
 //    const val BASE_URL = "http://36.133.174.236:9190"    // 外
     const val BASE_URL = "http://192.168.0.10:9190"    // 外
-//    const val BASE_URL = "http://120.27.232.27:9190"    // 外
+
+    //    const val BASE_URL = "http://120.27.232.27:9190"    // 外
     const val WEB_SOCKET = "ws://192.168.1.127:9090/websocket/iot/127"
 
     const val AUTOCODE_TICKET_NUMBER = "JOB_TICKET_CODE"
@@ -233,7 +234,8 @@ object UrlConsts {
     /**
      * 删除用户特征(指纹、面部)
      */
-    const val REMOVE_USER_CHARACTERISTIC = "/system/user/characteristic/removeSysUserCharacteristicByRecordIds"
+    const val REMOVE_USER_CHARACTERISTIC =
+        "/system/user/characteristic/removeSysUserCharacteristicByRecordIds"
 
     /**
      * 新增异常记录
@@ -274,4 +276,9 @@ object UrlConsts {
      * 解锁取钥匙前检查
      */
     const val CHECK_BEFORE_UNLOCKING = "/iscs/hardware-api/checkBeforeToUnlock"
+
+    /**
+     * 批量更新硬件状态
+     */
+    const val UPDATE_HARDWARE_ES_STATUS = "/iscs/hardware-api/updateHardwareEsStatus"
 }

+ 28 - 0
app/src/main/java/com/grkj/iscs/model/vo/hardware/UpdateHardwareEsStatusReqVO.kt

@@ -0,0 +1,28 @@
+package com.grkj.iscs.model.vo.hardware
+
+/**
+ * 工卡异常数据
+ */
+data class JobCardExDTO(
+    val cardNfc: String,
+    val exRemark: String,
+    val exStatus: String
+)
+
+/**
+ * 钥匙异常数据
+ */
+data class KeyExDTO(
+    val keyNfc: String,
+    val exRemark: String,
+    val exStatus: String
+)
+
+/**
+ * 挂锁异常数据
+ */
+data class LockExDTO(
+    val lockNfc: String,
+    val exRemark: String,
+    val exStatus: String
+)

+ 25 - 0
app/src/main/java/com/grkj/iscs/util/NetApi.kt

@@ -10,6 +10,9 @@ import com.grkj.iscs.model.vo.characteristic.CharacteristicPageRespVO
 import com.grkj.iscs.model.vo.dept.DeptListRespVO
 import com.grkj.iscs.model.vo.dict.CommonDictRespVO
 import com.grkj.iscs.model.vo.finger.LoginCharacteristicRespVO
+import com.grkj.iscs.model.vo.hardware.JobCardExDTO
+import com.grkj.iscs.model.vo.hardware.KeyExDTO
+import com.grkj.iscs.model.vo.hardware.LockExDTO
 import com.grkj.iscs.model.vo.key.KeyInfoRespVO
 import com.grkj.iscs.model.vo.lock.LockInfoRespVO
 import com.grkj.iscs.model.vo.lock.LockTakeUpdateReqVO
@@ -1021,4 +1024,26 @@ object NetApi {
             }, isGet = true, isAuth = true
         )
     }
+
+    /**
+     * 批量更新硬件状态
+     */
+    fun updateHardwareEsStatus(jobCardExDTOList:List<JobCardExDTO>,keyExDTOList:List<KeyExDTO>,lockExDTOList:List<LockExDTO>, callBack: (Boolean) -> Unit){
+        NetHttpManager.getInstance().doRequestNet(
+            UrlConsts.UPDATE_HARDWARE_ES_STATUS,
+            false,
+            mapOf(
+                "jobCardExDTOList" to jobCardExDTOList,
+                "keyExDTOList" to keyExDTOList,
+                "lockExDTOList" to lockExDTOList
+            ),
+            { res, _, _ ->
+                res?.let {
+                    callBack.invoke(true)
+                } ?: run {
+                    callBack.invoke(false)
+                }
+            }, isGet = false, isAuth = true
+        )
+    }
 }

+ 114 - 16
app/src/main/java/com/grkj/iscs/view/fragment/DeviceStatusFragment.kt

@@ -1,6 +1,9 @@
 package com.grkj.iscs.view.fragment
 
 import android.content.Context
+import android.content.res.ColorStateList
+import android.view.View
+import androidx.core.content.ContextCompat
 import androidx.recyclerview.widget.RecyclerView
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentDeviceStatusBinding
@@ -21,7 +24,8 @@ import com.zhy.adapter.recyclerview.base.ViewHolder
 /**
  * 硬件状态页
  */
-class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPresenter, FragmentDeviceStatusBinding>() {
+class DeviceStatusFragment :
+    BaseMvpFragment<IDeviceStatusView, DeviceStatusPresenter, FragmentDeviceStatusBinding>() {
     private var mRowList = mutableListOf<DockStatusBO>()
 
     override val viewBinding: FragmentDeviceStatusBinding
@@ -31,8 +35,14 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         presenter?.initData(mRowList)
 
         val adapter = MultiItemTypeAdapter(requireContext(), mRowList)
-        adapter.addItemViewDelegate(KeyDockItemDelegate(presenter))
-        adapter.addItemViewDelegate(LockDockItemDelegate(presenter, requireContext()))
+        adapter.addItemViewDelegate(KeyDockItemDelegate(requireContext(), presenter))
+        adapter.addItemViewDelegate(
+            LockDockItemDelegate(
+                requireContext(),
+                presenter,
+                requireContext()
+            )
+        )
         adapter.addItemViewDelegate(EmptyItemDelegate())
         mBinding?.rvDock?.adapter = adapter
     }
@@ -51,7 +61,13 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         val dockList: MutableList<DockTestBean>
     )
 
-    class KeyDockItemDelegate(var presenter: DeviceStatusPresenter?): ItemViewDelegate<DockStatusBO> {
+    class KeyDockItemDelegate(var context: Context, var presenter: DeviceStatusPresenter?) :
+        ItemViewDelegate<DockStatusBO> {
+        private val statusCloseTintColor =
+            ContextCompat.getColor(context, R.color.common_status_red)
+        private val statusOpenTintColor =
+            ContextCompat.getColor(context, R.color.common_status_green)
+
         override fun getItemViewLayoutId(): Int {
             return R.layout.item_rv_key_dock_status
         }
@@ -59,14 +75,30 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         override fun convert(holder: ViewHolder?, row: DockStatusBO, position: Int) {
             holder?.setVisibleWithHolder(R.id.ll_left, row.dockList.any { it.column == "1" })
             holder?.setVisibleWithHolder(R.id.ll_right, row.dockList.any { it.column == "2" })
-            holder?.setSelected(R.id.iv_key_1, ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, true))
-            holder?.setSelected(R.id.iv_key_2, ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, false))
-            holder?.setSelected(R.id.iv_key_3, ModBusController.isKeyExist(row.dockList.find { it.column == "2" }?.address, true))
-            holder?.setSelected(R.id.iv_key_4, ModBusController.isKeyExist(row.dockList.find { it.column == "2" }?.address, false))
-            val status1 = presenter?.getKeyStatus(row.dockList.find { it.column == "1" }?.address, true)
-            val status2 = presenter?.getKeyStatus(row.dockList.find { it.column == "1" }?.address, false)
-            val status3 = presenter?.getKeyStatus(row.dockList.find { it.column == "2" }?.address, true)
-            val status4 = presenter?.getKeyStatus(row.dockList.find { it.column == "2" }?.address, false)
+            holder?.setSelected(
+                R.id.iv_key_1,
+                ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, true)
+            )
+            holder?.setSelected(
+                R.id.iv_key_2,
+                ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, false)
+            )
+            holder?.setSelected(
+                R.id.iv_key_3,
+                ModBusController.isKeyExist(row.dockList.find { it.column == "2" }?.address, true)
+            )
+            holder?.setSelected(
+                R.id.iv_key_4,
+                ModBusController.isKeyExist(row.dockList.find { it.column == "2" }?.address, false)
+            )
+            val status1 =
+                presenter?.getKeyStatus(row.dockList.find { it.column == "1" }?.address, true)
+            val status2 =
+                presenter?.getKeyStatus(row.dockList.find { it.column == "1" }?.address, false)
+            val status3 =
+                presenter?.getKeyStatus(row.dockList.find { it.column == "2" }?.address, true)
+            val status4 =
+                presenter?.getKeyStatus(row.dockList.find { it.column == "2" }?.address, false)
             holder?.setSelected(R.id.rl_status_1, status1?.first == true)
             holder?.setSelected(R.id.rl_status_2, status2?.first == true)
             holder?.setSelected(R.id.rl_status_3, status3?.first == true)
@@ -79,6 +111,38 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
             holder?.setVisibleWithHolder(R.id.tv_repair_2, status2?.first == false)
             holder?.setVisibleWithHolder(R.id.tv_repair_3, status3?.first == false)
             holder?.setVisibleWithHolder(R.id.tv_repair_4, status4?.first == false)
+            holder?.getView<View>(R.id.v_buckle_status_1)?.backgroundTintList =
+                if (presenter?.getKeyBuckleLockEnabled(
+                        row.dockList.find { it.column == "1" }?.address,
+                        true
+                    ) == true
+                ) ColorStateList.valueOf(statusCloseTintColor) else ColorStateList.valueOf(
+                    statusOpenTintColor
+                )
+            holder?.getView<View>(R.id.v_buckle_status_2)?.backgroundTintList =
+                if (presenter?.getKeyBuckleLockEnabled(
+                        row.dockList.find { it.column == "1" }?.address,
+                        true
+                    ) == true
+                ) ColorStateList.valueOf(statusCloseTintColor) else ColorStateList.valueOf(
+                    statusOpenTintColor
+                )
+            holder?.getView<View>(R.id.v_buckle_status_3)?.backgroundTintList =
+                if (presenter?.getKeyBuckleLockEnabled(
+                        row.dockList.find { it.column == "1" }?.address,
+                        true
+                    ) == true
+                ) ColorStateList.valueOf(statusCloseTintColor) else ColorStateList.valueOf(
+                    statusOpenTintColor
+                )
+            holder?.getView<View>(R.id.v_buckle_status_4)?.backgroundTintList =
+                if (presenter?.getKeyBuckleLockEnabled(
+                        row.dockList.find { it.column == "1" }?.address,
+                        true
+                    ) == true
+                ) ColorStateList.valueOf(statusCloseTintColor) else ColorStateList.valueOf(
+                    statusOpenTintColor
+                )
             holder?.setOnClickListener(R.id.tv_repair_1) {
                 presenter?.repairKey(row.dockList.find { it.column == "1" }?.address, true)
             }
@@ -98,7 +162,18 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         }
     }
 
-    class LockDockItemDelegate(var presenter: DeviceStatusPresenter?, var ctx: Context): ItemViewDelegate<DockStatusBO> {
+    class LockDockItemDelegate(
+        var context: Context,
+        var presenter: DeviceStatusPresenter?,
+        var ctx: Context
+    ) : ItemViewDelegate<DockStatusBO> {
+        private val statusCloseTintColor =
+            ContextCompat.getColor(context, R.color.common_status_red)
+        private val statusOpenTintColor =
+            ContextCompat.getColor(context, R.color.common_status_green)
+        private val statusNotLightTintColor =
+            ContextCompat.getColor(context, R.color.common_status_not_light)
+
         override fun getItemViewLayoutId(): Int {
             return R.layout.item_rv_lock_dock_status
         }
@@ -106,9 +181,32 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         override fun convert(holder: ViewHolder?, row: DockStatusBO, position: Int) {
             val rv = holder?.getView<RecyclerView>(R.id.rv_root)
             rv?.adapter = object :
-                CommonAdapter<Int>(ctx, R.layout.item_rv_lock_dock_child_status, row.dockList[0].deviceList) {
+                CommonAdapter<Int>(
+                    ctx,
+                    R.layout.item_rv_lock_dock_child_status,
+                    row.dockList[0].deviceList
+                ) {
                 override fun convert(holder: ViewHolder?, lockIdx: Int, position: Int) {
-                    holder?.setSelected(R.id.root, ModBusController.isLockExist(row.dockList[0].address, lockIdx))
+                    holder?.setSelected(
+                        R.id.root,
+                        ModBusController.isLockExist(row.dockList[0].address, lockIdx)
+                    )
+                    ColorStateList.valueOf(statusNotLightTintColor).let {
+                        holder?.getView<View>(R.id.v_buckle_status_close)?.backgroundTintList = it
+                        holder?.getView<View>(R.id.v_buckle_status_open)?.backgroundTintList = it
+                    }
+                    (presenter?.getLockBuckleLockEnabled(
+                        row.dockList[0].address,
+                        lockIdx
+                    ) == true).let {
+                        if (it) {
+                            holder?.getView<View>(R.id.v_buckle_status_close)?.backgroundTintList =
+                                ColorStateList.valueOf(statusCloseTintColor)
+                        } else {
+                            holder?.getView<View>(R.id.v_buckle_status_open)?.backgroundTintList =
+                                ColorStateList.valueOf(statusOpenTintColor)
+                        }
+                    }
                 }
             }
         }
@@ -118,7 +216,7 @@ class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPres
         }
     }
 
-    class EmptyItemDelegate: ItemViewDelegate<DockStatusBO> {
+    class EmptyItemDelegate : ItemViewDelegate<DockStatusBO> {
         override fun getItemViewLayoutId(): Int {
             return R.layout.item_rv_empty_dock_status
         }

+ 19 - 1
app/src/main/java/com/grkj/iscs/view/presenter/DeviceStatusPresenter.kt

@@ -26,7 +26,10 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
         val dockConfigJson = SPUtils.getDockConfig(mContext!!)
         if (!dockConfigJson.isNullOrEmpty()) {
             val tempList: MutableList<DockTestBean> =
-                Gson().fromJson(dockConfigJson, object : TypeToken<MutableList<DockTestBean>>() {}.type)
+                Gson().fromJson(
+                    dockConfigJson,
+                    object : TypeToken<MutableList<DockTestBean>>() {}.type
+                )
             if (tempList.isNotEmpty()) {
                 tempList.forEach { dock ->
                     try {
@@ -78,6 +81,7 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
                 ToastUtils.tip(R.string.no_key_to_repair)
                 return
             }
+
             1 -> readyRfid(dockAddr, isLeft)
             2 -> getKeyInfo(dockAddr, isLeft, ModBusController.getKeyByDock(dockAddr, isLeft)?.rfid)
             3, 4, 5 -> {
@@ -129,4 +133,18 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
             }
         }
     }
+
+    /**
+     * 获取钥匙的锁仓状态
+     */
+    fun getKeyBuckleLockEnabled(address: Byte?, isLeft: Boolean): Boolean {
+        return ModBusController.getKeyBuckleLockEnabled(address, isLeft)
+    }
+
+    /**
+     * 获取挂锁的锁仓状态
+     */
+    fun getLockBuckleLockEnabled(address: Byte, lockIdx: Int): Any {
+        return ModBusController.getLockBuckleLockEnabled(address, lockIdx)
+    }
 }

+ 8 - 0
app/src/main/res/drawable/common_status_circle.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <size
+        android:width="@dimen/common_status_circle_small"
+        android:height="@dimen/common_status_circle_small" />
+    <solid android:color="@color/common_status_red" />
+</shape>

+ 7 - 0
app/src/main/res/drawable/divider_dock_lock_status.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="line">
+    <size
+        android:width="@dimen/divider_line_width"
+        android:height="20dp" />
+</shape>

+ 21 - 0
app/src/main/res/drawable/dock_has_lock.xml

@@ -0,0 +1,21 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="76dp"
+    android:height="182dp"
+    android:viewportWidth="76"
+    android:viewportHeight="182">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,0L66,0A10,10 0,0 1,76 10L76,172A10,10 0,0 1,66 182L10,182A10,10 0,0 1,0 172L0,10A10,10 0,0 1,10 0z" />
+    <path
+        android:fillColor="#D9D9D9"
+        android:pathData=" M28,31
+        H48
+        A10,10 0 0 1 58,41
+        V141
+        A10,10 0 0 1 48,151
+        H28
+        A10,10 0 0 1 18,141
+        V41
+        A10,10 0 0 1 28,31
+        Z" />
+</vector>

+ 2 - 2
app/src/main/res/drawable/dock_lock_selector.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="false" android:drawable="@mipmap/dock_no_lock" />
-    <item android:state_selected="true" android:drawable="@mipmap/dock_has_lock" />
+    <item android:state_selected="false" android:drawable="@drawable/dock_no_lock" />
+    <item android:state_selected="true" android:drawable="@drawable/dock_has_lock" />
 </selector>

+ 9 - 0
app/src/main/res/drawable/dock_no_lock.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="76dp"
+    android:height="182dp"
+    android:viewportWidth="76"
+    android:viewportHeight="182">
+  <path
+      android:pathData="M10,0L66,0A10,10 0,0 1,76 10L76,172A10,10 0,0 1,66 182L10,182A10,10 0,0 1,0 172L0,10A10,10 0,0 1,10 0z"
+      android:fillColor="#000000"/>
+</vector>

+ 57 - 14
app/src/main/res/layout/item_rv_key_dock_status.xml

@@ -13,26 +13,27 @@
         android:id="@+id/ll_left"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:orientation="horizontal">
+        android:layout_weight="1">
 
-        <LinearLayout
+        <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:gravity="center"
             android:orientation="vertical">
 
             <ImageView
                 android:id="@+id/iv_key_1"
                 android:layout_width="50dp"
                 android:layout_height="35dp"
+                android:layout_centerHorizontal="true"
                 android:background="@drawable/dock_key_selector" />
 
             <RelativeLayout
                 android:id="@+id/rl_status_1"
                 android:layout_width="50dp"
                 android:layout_height="20dp"
+                android:layout_below="@+id/iv_key_1"
+                android:layout_centerHorizontal="true"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
                 android:gravity="center">
@@ -46,16 +47,25 @@
             <TextView
                 android:id="@+id/tv_repair_1"
                 style="@style/CommonTextView"
+                android:layout_below="@+id/rl_status_1"
+                android:layout_alignLeft="@+id/rl_status_1"
+                android:layout_alignRight="@+id/rl_status_1"
                 android:background="@drawable/common_btn_red_bg"
                 android:text="@string/repair_key" />
-        </LinearLayout>
 
-        <LinearLayout
+            <View
+                android:id="@+id/v_buckle_status_1"
+                android:layout_width="@dimen/common_status_circle_small"
+                android:layout_height="@dimen/common_status_circle_small"
+                android:layout_toRightOf="@+id/iv_key_1"
+                android:background="@drawable/common_status_circle" />
+        </RelativeLayout>
+
+        <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:gravity="center"
-            android:orientation="vertical">
+            android:gravity="center_horizontal">
 
             <ImageView
                 android:id="@+id/iv_key_2"
@@ -67,6 +77,7 @@
                 android:id="@+id/rl_status_2"
                 android:layout_width="50dp"
                 android:layout_height="20dp"
+                android:layout_below="@+id/iv_key_2"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
                 android:gravity="center">
@@ -80,9 +91,19 @@
             <TextView
                 android:id="@+id/tv_repair_2"
                 style="@style/CommonTextView"
+                android:layout_below="@+id/rl_status_2"
+                android:layout_alignLeft="@+id/rl_status_2"
+                android:layout_alignRight="@+id/rl_status_2"
                 android:background="@drawable/common_btn_red_bg"
                 android:text="@string/repair_key" />
-        </LinearLayout>
+
+            <View
+                android:id="@+id/v_buckle_status_2"
+                android:layout_width="@dimen/common_status_circle_small"
+                android:layout_height="@dimen/common_status_circle_small"
+                android:layout_toRightOf="@+id/iv_key_2"
+                android:background="@drawable/common_status_circle" />
+        </RelativeLayout>
     </LinearLayout>
 
     <LinearLayout
@@ -92,11 +113,11 @@
         android:layout_weight="1"
         android:orientation="horizontal">
 
-        <LinearLayout
+        <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:gravity="center"
+            android:gravity="center_horizontal"
             android:orientation="vertical">
 
             <ImageView
@@ -109,6 +130,7 @@
                 android:id="@+id/rl_status_3"
                 android:layout_width="50dp"
                 android:layout_height="20dp"
+                android:layout_below="@+id/iv_key_3"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
                 android:gravity="center">
@@ -122,11 +144,21 @@
             <TextView
                 android:id="@+id/tv_repair_3"
                 style="@style/CommonTextView"
+                android:layout_below="@+id/rl_status_3"
+                android:layout_alignLeft="@+id/rl_status_3"
+                android:layout_alignRight="@+id/rl_status_3"
                 android:background="@drawable/common_btn_red_bg"
                 android:text="@string/repair_key" />
-        </LinearLayout>
 
-        <LinearLayout
+            <View
+                android:id="@+id/v_buckle_status_3"
+                android:layout_width="@dimen/common_status_circle_small"
+                android:layout_height="@dimen/common_status_circle_small"
+                android:layout_toRightOf="@+id/iv_key_3"
+                android:background="@drawable/common_status_circle" />
+        </RelativeLayout>
+
+        <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
@@ -143,6 +175,7 @@
                 android:id="@+id/rl_status_4"
                 android:layout_width="50dp"
                 android:layout_height="20dp"
+                android:layout_below="@+id/iv_key_4"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
                 android:gravity="center">
@@ -156,8 +189,18 @@
             <TextView
                 android:id="@+id/tv_repair_4"
                 style="@style/CommonTextView"
+                android:layout_below="@+id/rl_status_4"
+                android:layout_alignLeft="@+id/rl_status_4"
+                android:layout_alignRight="@+id/rl_status_4"
                 android:background="@drawable/common_btn_red_bg"
                 android:text="@string/repair_key" />
-        </LinearLayout>
+
+            <View
+                android:id="@+id/v_buckle_status_4"
+                android:layout_width="@dimen/common_status_circle_small"
+                android:layout_height="@dimen/common_status_circle_small"
+                android:layout_toRightOf="@+id/iv_key_4"
+                android:background="@drawable/common_status_circle" />
+        </RelativeLayout>
     </LinearLayout>
 </LinearLayout>

+ 34 - 6
app/src/main/res/layout/item_rv_lock_dock_child_status.xml

@@ -1,8 +1,36 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/root"
-    android:layout_width="30dp"
-    android:layout_height="90dp"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:layout_marginHorizontal="@dimen/common_spacing_small"
-    android:background="@drawable/dock_lock_selector"
-    android:orientation="horizontal" />
+    android:orientation="horizontal">
+
+    <FrameLayout
+        android:id="@+id/root"
+        android:layout_width="30dp"
+        android:layout_height="90dp"
+        android:background="@drawable/dock_lock_selector" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="@dimen/divider_line_margin"
+        android:divider="@drawable/divider_dock_lock_status"
+        android:gravity="center"
+        android:orientation="vertical"
+        android:showDividers="middle">
+
+        <View
+            android:id="@+id/v_buckle_status_close"
+            android:layout_width="@dimen/common_status_circle_medium"
+            android:layout_height="@dimen/common_status_circle_medium"
+            android:background="@drawable/common_status_circle" />
+
+        <View
+            android:id="@+id/v_buckle_status_open"
+            android:layout_width="@dimen/common_status_circle_medium"
+            android:layout_height="@dimen/common_status_circle_medium"
+            android:background="@drawable/common_status_circle" />
+    </LinearLayout>
+</LinearLayout>
+

BIN
app/src/main/res/mipmap/dock_has_lock.png


BIN
app/src/main/res/mipmap/dock_no_lock.png


+ 4 - 0
app/src/main/res/values/colors.xml

@@ -16,6 +16,10 @@
     <color name="common_bg_white_80">#CCFFFFFF</color>
     <color name="common_bg_white_90">#E6FFFFFF</color>
 
+    <color name="common_status_red">#FFFF0000</color>
+    <color name="common_status_green">#FF008000</color>
+    <color name="common_status_not_light">#FFD9D9D9</color>
+
     <color name="common_bg_black_30">#4D000000</color>
 
     <color name="common_light_gray">#CCCCCC</color>

+ 3 - 1
app/src/main/res/values/dimens.xml

@@ -13,6 +13,8 @@
     <dimen name="common_spacing_smallest">2dp</dimen>
     <dimen name="common_icon_size">15dp</dimen>
     <dimen name="common_icon_size_small">12dp</dimen>
+    <dimen name="common_status_circle_small">5dp</dimen>
+    <dimen name="common_status_circle_medium">15dp</dimen>
 
     <dimen name="common_btn_width">150dp</dimen>
     <dimen name="common_btn_height">50dp</dimen>
@@ -28,7 +30,7 @@
     <dimen name="switch_radius">13dp</dimen>
     <dimen name="switch_thumb_stroke">2dp</dimen>
     <dimen name="switch_thumb_size">22dp</dimen>
-    
+
     <dimen name="home_navi_height">200dp</dimen>
     <dimen name="home_navi_width">133dp</dimen>