Просмотр исходного кода

添加设备状态页以及修复功能;修复准备配置行列号校验判断逻辑

Frankensteinly 1 год назад
Родитель
Сommit
f5e597f862

+ 19 - 0
app/src/main/java/com/grkj/iscs/BusinessManager.kt

@@ -110,6 +110,9 @@ object BusinessManager {
     // 是否是测试人员登录的
     // 是否是测试人员登录的
     var isTestMode = false
     var isTestMode = false
 
 
+    // 有问题的钥匙的列表 - rfid
+    var mExceptionKeyList = mutableListOf<String>()
+
     /**
     /**
      * 初始化消息总线
      * 初始化消息总线
      */
      */
@@ -695,6 +698,7 @@ object BusinessManager {
                         deviceList.removeIf { it.bleDevice.mac == bleDevice.mac }
                         deviceList.removeIf { it.bleDevice.mac == bleDevice.mac }
                         val bleBean = BleBean(it)
                         val bleBean = BleBean(it)
                         deviceList.add(bleBean)
                         deviceList.add(bleBean)
+                        removeExceptionKey(it.mac)
                         // 设置MTU
                         // 设置MTU
                         Executor.delayOnMain(200) {
                         Executor.delayOnMain(200) {
                             if (!checkProcess(bleDevice.mac)) {
                             if (!checkProcess(bleDevice.mac)) {
@@ -1116,6 +1120,8 @@ object BusinessManager {
                     Executor.delayOnMain(1000) {
                     Executor.delayOnMain(1000) {
                         getCurrentStatus(from, bleDevice, retryCount - 1)
                         getCurrentStatus(from, bleDevice, retryCount - 1)
                     }
                     }
+                } else {
+                    addExceptionKey(bleDevice.mac)
                 }
                 }
             }
             }
         }
         }
@@ -1511,4 +1517,17 @@ object BusinessManager {
             mEventBus.value = msgEvent
             mEventBus.value = msgEvent
         }
         }
     }
     }
+
+    fun addExceptionKey(key: String) {
+        LogUtil.w("addExceptionKey: $key")
+        if (mExceptionKeyList.contains(key)) {
+            return
+        }
+        mExceptionKeyList.add(key)
+    }
+
+    fun removeExceptionKey(key: String) {
+        LogUtil.i("removeExceptionKey: $key")
+        mExceptionKeyList.remove(key)
+    }
 }
 }

+ 5 - 0
app/src/main/java/com/grkj/iscs/extentions/ViewHolder.kt

@@ -6,4 +6,9 @@ import com.zhy.adapter.recyclerview.base.ViewHolder
 fun ViewHolder.setSelected(viewId: Int, isSelected: Boolean) {
 fun ViewHolder.setSelected(viewId: Int, isSelected: Boolean) {
     val view = getView<View>(viewId)
     val view = getView<View>(viewId)
     view.isSelected = isSelected
     view.isSelected = isSelected
+}
+
+fun ViewHolder.setVisibleWithHolder(viewId: Int, isVisible: Boolean) {
+    val view = getView<View>(viewId)
+    view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
 }
 }

+ 52 - 0
app/src/main/java/com/grkj/iscs/modbus/ModBusController.kt

@@ -440,6 +440,11 @@ object ModBusController {
         return dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getKeyList() }.find { it.mac == mac }
         return dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getKeyList() }.find { it.mac == mac }
     }
     }
 
 
+    fun getKeyByDock(dockAddr: Byte?, isLeft: Boolean): DockBean.KeyBean? {
+        dockAddr ?: return null
+        return dockList.find { it.addr == dockAddr }?.getKeyList()?.find { it.isLeft == isLeft }
+    }
+
     /**
     /**
      * 根据RFID找锁具
      * 根据RFID找锁具
      */
      */
@@ -447,6 +452,46 @@ object ModBusController {
         return dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getLockList() }.find { it.rfid == rfid }
         return dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getLockList() }.find { it.rfid == rfid }
     }
     }
 
 
+    fun isKeyExist(dockAddr: Byte?, isLeft: Boolean): Boolean {
+        dockAddr ?: return false
+        return dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
+            .find { it.addr == dockAddr }?.getKeyList()
+            ?.find { it.isLeft == isLeft && it.isExist } != null
+    }
+
+    /**
+     * 获取钥匙状态
+     *
+     * @return 0:不存在 1:存在 2:有RFID 3:有MAC 4:连接上 5:待机模式 6: 待机模式无异常
+     */
+    fun getKeyStatus(dockAddr: Byte?, isLeft: Boolean): Int {
+        dockAddr ?: return 0
+        val key = dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
+            .find { it.addr == dockAddr }?.getKeyList()
+            ?.find { it.isLeft == isLeft }
+        key ?: return 0
+        var status = 0
+        if (key.isExist) {
+            status = 1
+        }
+        if (key.rfid != null) {
+            status = 2
+        }
+        if (key.mac != null) {
+            status = 3
+        }
+        if (BleManager.getInstance().isConnected(BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice)) {
+            status = 4
+        }
+        if (key.isReady) {
+            status = 5
+        }
+        if (key.rfid != null && BusinessManager.mExceptionKeyList.none { it == key.rfid }) {
+            status = 6
+        }
+        return status
+    }
+
     /**
     /**
      * 更新钥匙的准备状态
      * 更新钥匙的准备状态
      */
      */
@@ -471,6 +516,13 @@ object ModBusController {
         }
         }
     }
     }
 
 
+    fun getDockByLockNfc(nfc: String): DockBean? {
+        return dockList.find {
+            (it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE)
+                    && it.getLockList().any { it.rfid == nfc }
+        }
+    }
+
     /**
     /**
      * 根据类型获取底座列表
      * 根据类型获取底座列表
      */
      */

+ 2 - 0
app/src/main/java/com/grkj/iscs/view/activity/HomeActivity.kt

@@ -20,6 +20,7 @@ import com.grkj.iscs.util.log.LogUtil
 import com.grkj.iscs.view.adapter.MenuAdapter
 import com.grkj.iscs.view.adapter.MenuAdapter
 import com.grkj.iscs.view.base.BaseFragment
 import com.grkj.iscs.view.base.BaseFragment
 import com.grkj.iscs.view.base.BaseMvpActivity
 import com.grkj.iscs.view.base.BaseMvpActivity
+import com.grkj.iscs.view.fragment.DeviceStatusFragment
 import com.grkj.iscs.view.fragment.DockTestFragment
 import com.grkj.iscs.view.fragment.DockTestFragment
 import com.grkj.iscs.view.fragment.ExceptionReportFragment
 import com.grkj.iscs.view.fragment.ExceptionReportFragment
 import com.grkj.iscs.view.fragment.JobManagementFragment
 import com.grkj.iscs.view.fragment.JobManagementFragment
@@ -62,6 +63,7 @@ class HomeActivity : BaseMvpActivity<IHomeView, HomePresenter, ActivityHomeBindi
                 mMenuList.add(Menu(getString(R.string.system_setting), R.mipmap.menu_icon_sys_setting, SystemSettingFragment()))
                 mMenuList.add(Menu(getString(R.string.system_setting), R.mipmap.menu_icon_sys_setting, SystemSettingFragment()))
             }
             }
         }
         }
+        mMenuList.add(Menu(getString(R.string.device_status), R.mipmap.menu_icon_device_status, DeviceStatusFragment()))
         mMenuList.add(Menu(getString(R.string.exception_report), R.mipmap.exception_handle, ExceptionReportFragment()))
         mMenuList.add(Menu(getString(R.string.exception_report), R.mipmap.exception_handle, ExceptionReportFragment()))
         mMenuList.add(Menu(getString(R.string.settings), R.mipmap.settings, SettingFragment()))
         mMenuList.add(Menu(getString(R.string.settings), R.mipmap.settings, SettingFragment()))
 
 

+ 105 - 0
app/src/main/java/com/grkj/iscs/view/fragment/DeviceStatusFragment.kt

@@ -0,0 +1,105 @@
+package com.grkj.iscs.view.fragment
+
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.grkj.iscs.R
+import com.grkj.iscs.databinding.FragmentDeviceStatusBinding
+import com.grkj.iscs.extentions.setSelected
+import com.grkj.iscs.extentions.setVisibleWithHolder
+import com.grkj.iscs.modbus.ModBusController
+import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_KEY
+import com.grkj.iscs.util.SPUtils
+import com.grkj.iscs.view.base.BaseMvpFragment
+import com.grkj.iscs.view.fragment.DockTestFragment.DockTestBean
+import com.grkj.iscs.view.iview.IDeviceStatusView
+import com.grkj.iscs.view.presenter.DeviceStatusPresenter
+import com.zhy.adapter.recyclerview.CommonAdapter
+import com.zhy.adapter.recyclerview.base.ViewHolder
+
+/**
+ * 设备状态页
+ */
+class DeviceStatusFragment : BaseMvpFragment<IDeviceStatusView, DeviceStatusPresenter, FragmentDeviceStatusBinding>() {
+
+    private var mKeyDockList = mutableListOf<DockTestBean>()
+    private var mRowList = mutableListOf<KeyDockStatusBO>()
+
+    override val viewBinding: FragmentDeviceStatusBinding
+        get() = FragmentDeviceStatusBinding.inflate(layoutInflater)
+
+    override fun initView() {
+        initData()
+
+        mBinding?.rvKey?.adapter = object :
+            CommonAdapter<KeyDockStatusBO>(requireActivity(), R.layout.item_rv_key_dock_status, mRowList) {
+            override fun convert(holder: ViewHolder, row: KeyDockStatusBO, 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.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)
+                holder.setSelected(R.id.rl_status_4, status4?.first == true)
+                holder.setText(R.id.tv_status_1, status1?.second)
+                holder.setText(R.id.tv_status_2, status2?.second)
+                holder.setText(R.id.tv_status_3, status3?.second)
+                holder.setText(R.id.tv_status_4, status4?.second)
+                holder.setVisible(R.id.tv_repair_1, status1?.first == false)
+                holder.setVisible(R.id.tv_repair_2, status2?.first == false)
+                holder.setVisible(R.id.tv_repair_3, status3?.first == false)
+                holder.setVisible(R.id.tv_repair_4, status4?.first == false)
+                holder.setOnClickListener(R.id.tv_repair_1) {
+                    presenter?.repairKey(row.dockList.find { it.column == "1" }?.address, true)
+                }
+                holder.setOnClickListener(R.id.tv_repair_2) {
+                    presenter?.repairKey(row.dockList.find { it.column == "1" }?.address, false)
+                }
+                holder.setOnClickListener(R.id.tv_repair_3) {
+                    presenter?.repairKey(row.dockList.find { it.column == "2" }?.address, true)
+                }
+                holder.setOnClickListener(R.id.tv_repair_4) {
+                    presenter?.repairKey(row.dockList.find { it.column == "2" }?.address, false)
+                }
+            }
+        }
+    }
+
+    private fun initData() {
+        val dockConfigJson = SPUtils.getDockConfig(requireActivity())
+        if (!dockConfigJson.isNullOrEmpty()) {
+            val tempList: MutableList<DockTestBean> =
+                Gson().fromJson(dockConfigJson, object : TypeToken<MutableList<DockTestBean>>() {}.type)
+            if (tempList.isNotEmpty()) {
+                mKeyDockList.addAll(tempList.filter { it.type == DOCK_TYPE_KEY })
+                mKeyDockList.forEach { dock ->
+                    mRowList.find { it.row == dock.row.toInt() }?.let {
+                        it.dockList.add(dock)
+                    } ?: let {
+                        mRowList.add(KeyDockStatusBO(dock.row.toInt(), mutableListOf(dock)))
+                    }
+                }
+            }
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+        mBinding?.rvKey?.adapter?.notifyDataSetChanged()
+    }
+
+    override fun initPresenter(): DeviceStatusPresenter {
+        return DeviceStatusPresenter()
+    }
+
+    data class KeyDockStatusBO(
+        val row: Int,
+        val dockList: MutableList<DockTestBean>
+    )
+}

+ 5 - 0
app/src/main/java/com/grkj/iscs/view/iview/IDeviceStatusView.kt

@@ -0,0 +1,5 @@
+package com.grkj.iscs.view.iview
+
+import com.grkj.iscs.view.base.IView
+
+interface IDeviceStatusView : IView {}

+ 90 - 0
app/src/main/java/com/grkj/iscs/view/presenter/DeviceStatusPresenter.kt

@@ -0,0 +1,90 @@
+package com.grkj.iscs.view.presenter
+
+import com.clj.fastble.BleManager
+import com.grkj.iscs.BusinessManager
+import com.grkj.iscs.BusinessManager.getCurrentStatus
+import com.grkj.iscs.R
+import com.grkj.iscs.extentions.removeLeadingZeros
+import com.grkj.iscs.extentions.toHexStrings
+import com.grkj.iscs.modbus.ModBusController
+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 com.grkj.iscs.view.base.BasePresenter
+import com.grkj.iscs.view.iview.IDeviceStatusView
+
+class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
+    fun getKeyStatus(dockAddr: Byte?, isLeft: Boolean): Pair<Boolean, String> {
+        val status = ModBusController.getKeyStatus(dockAddr, isLeft)
+        LogUtil.i("getKeyStatus Key status : $status")
+        val text = when (status) {
+            0 -> mContext!!.getString(R.string.key_does_not_exists)
+            1 -> mContext!!.getString(R.string.key_no_rfid)
+            2 -> mContext!!.getString(R.string.key_no_mac)
+            3 -> mContext!!.getString(R.string.key_no_connected)
+            4 -> mContext!!.getString(R.string.key_not_in_ready_mode)
+            5 -> mContext!!.getString(R.string.key_has_exception)
+            6 -> mContext!!.getString(R.string.key_is_available)
+            else -> mContext!!.getString(R.string.key_unknown)
+        }
+        return Pair(status == 6, text)
+    }
+
+    fun repairKey(dockAddr: Byte?, isLeft: Boolean) {
+        val status = ModBusController.getKeyStatus(dockAddr, isLeft)
+        LogUtil.i("repairKey Key status : $dockAddr - $isLeft - $status")
+        when (status) {
+            0 -> {
+                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 -> {
+                val mac = ModBusController.getKeyByDock(dockAddr, isLeft)?.mac
+                mac ?: return
+                BusinessManager.unregisterConnectListener(mac)
+                BusinessManager.getBleDeviceByMac(mac)?.bleDevice?.let {
+                    BleManager.getInstance().disconnect(it)
+                }
+                BusinessManager.registerConnectListener(mac) { isDone, bleBean ->
+                    if (isDone && bleBean != null) {
+                        Executor.delayOnMain(300) {
+                            getCurrentStatus(7, bleBean.bleDevice)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private fun readyRfid(dockAddr: Byte?, left: Boolean) {
+        dockAddr ?: return
+        ModBusController.readKeyRfid(dockAddr, if (left) 0 else 1) { isLeft, res ->
+            if (res.size < 11) {
+                LogUtil.e("Key rfid error")
+                return@readKeyRfid
+            }
+            val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
+            LogUtil.i("Key rfid : $rfid")
+            ModBusController.updateKeyRfid(dockAddr, left, rfid)
+            getKeyInfo(dockAddr, isLeft, rfid)
+        }
+    }
+
+    private fun getKeyInfo(dockAddr: Byte?, isLeft: Boolean, rfid: String?) {
+        dockAddr ?: return
+        rfid ?: return
+        NetApi.getKeyInfo(rfid) {
+            if (it != null && !it.macAddress.isNullOrEmpty()) {
+                LogUtil.i("Get key info success : ${it.macAddress}")
+                ModBusController.updateKeyMac(dockAddr, isLeft, it.macAddress)
+                ModBusController.updateKeyReadyStatus(it.macAddress, false, 5)
+            } else {
+                LogUtil.e("Get key info fail : $rfid")
+                ToastUtils.tip(R.string.get_key_info_fail)
+            }
+        }
+    }
+}

+ 5 - 1
app/src/main/java/com/grkj/iscs/view/presenter/SystemSettingPresenter.kt

@@ -62,6 +62,10 @@ class SystemSettingPresenter : BasePresenter<ISystemSettingView>() {
             ToastUtils.tip(R.string.please_input_address)
             ToastUtils.tip(R.string.please_input_address)
             return
             return
         }
         }
+        if (dockList.any { it.address == address.toInt(16).toByte() }) {
+            ToastUtils.tip(R.string.board_address_exists)
+            return
+        }
         if (row.isEmpty()) {
         if (row.isEmpty()) {
             ToastUtils.tip(R.string.please_input_row)
             ToastUtils.tip(R.string.please_input_row)
             return
             return
@@ -71,7 +75,7 @@ class SystemSettingPresenter : BasePresenter<ISystemSettingView>() {
                 ToastUtils.tip(R.string.please_input_column)
                 ToastUtils.tip(R.string.please_input_column)
                 return
                 return
             }
             }
-            if (column.toInt() != 1 || column.toInt() != 2) {
+            if (column.toInt() != 1 && column.toInt() != 2) {
                 ToastUtils.tip(R.string.column_must_be_1_or_2)
                 ToastUtils.tip(R.string.column_must_be_1_or_2)
                 return
                 return
             }
             }

+ 5 - 0
app/src/main/res/drawable/dock_key_selector.xml

@@ -0,0 +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_key" />
+    <item android:state_selected="true" android:drawable="@mipmap/dock_has_key" />
+</selector>

+ 5 - 0
app/src/main/res/drawable/dock_key_status_bg_selector.xml

@@ -0,0 +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="@drawable/common_btn_red_bg" />
+    <item android:state_selected="true" android:drawable="@drawable/common_btn_green_bg" />
+</selector>

+ 18 - 0
app/src/main/res/layout/fragment_device_status.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".view.fragment.DeviceStatusFragment">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/item_rv_technology_sop_bg_normal"
+        android:padding="@dimen/common_spacing">
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rv_key"
+            style="@style/CommonRecyclerView" />
+    </LinearLayout>
+</FrameLayout>

+ 1 - 1
app/src/main/res/layout/fragment_system_setting.xml

@@ -170,7 +170,7 @@
             android:layout_alignParentRight="true"
             android:layout_alignParentRight="true"
             android:layout_alignParentBottom="true"
             android:layout_alignParentBottom="true"
             android:text="@string/system_setting_tip"
             android:text="@string/system_setting_tip"
-            android:textSize="@dimen/common_text_size_small" />
+            android:textSize="7dp" />
 
 
         <com.grkj.iscs.view.widget.CommonBtn
         <com.grkj.iscs.view.widget.CommonBtn
             android:id="@+id/cb_save"
             android:id="@+id/cb_save"

+ 158 - 0
app/src/main/res/layout/item_rv_key_dock_status.xml

@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_margin="@dimen/common_spacing_small"
+    android:background="@color/white"
+    android:orientation="horizontal"
+    android:padding="@dimen/common_spacing_small">
+
+    <LinearLayout
+        android:id="@+id/ll_left"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <LinearLayout
+            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:background="@drawable/dock_key_selector" />
+
+            <RelativeLayout
+                android:id="@+id/rl_status_1"
+                android:layout_width="50dp"
+                android:layout_height="20dp"
+                android:layout_marginVertical="@dimen/common_spacing_small"
+                android:background="@drawable/dock_key_status_bg_selector"
+                android:gravity="center">
+
+                <TextView
+                    android:id="@+id/tv_status_1"
+                    style="@style/CommonTextView" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/tv_repair_1"
+                style="@style/CommonTextView"
+                android:background="@drawable/common_btn_red_bg"
+                android:text="@string/repair_key" />
+        </LinearLayout>
+
+        <LinearLayout
+            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_2"
+                android:layout_width="50dp"
+                android:layout_height="35dp"
+                android:background="@drawable/dock_key_selector" />
+
+            <RelativeLayout
+                android:id="@+id/rl_status_2"
+                android:layout_width="50dp"
+                android:layout_height="20dp"
+                android:layout_marginVertical="@dimen/common_spacing_small"
+                android:background="@drawable/dock_key_status_bg_selector"
+                android:gravity="center">
+
+                <TextView
+                    android:id="@+id/tv_status_2"
+                    style="@style/CommonTextView" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/tv_repair_2"
+                style="@style/CommonTextView"
+                android:background="@drawable/common_btn_red_bg"
+                android:text="@string/repair_key" />
+        </LinearLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_right"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <LinearLayout
+            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_3"
+                android:layout_width="50dp"
+                android:layout_height="35dp"
+                android:background="@drawable/dock_key_selector" />
+
+            <RelativeLayout
+                android:id="@+id/rl_status_3"
+                android:layout_width="50dp"
+                android:layout_height="20dp"
+                android:layout_marginVertical="@dimen/common_spacing_small"
+                android:background="@drawable/dock_key_status_bg_selector"
+                android:gravity="center">
+
+                <TextView
+                    android:id="@+id/tv_status_3"
+                    style="@style/CommonTextView" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/tv_repair_3"
+                style="@style/CommonTextView"
+                android:background="@drawable/common_btn_red_bg"
+                android:text="@string/repair_key" />
+        </LinearLayout>
+
+        <LinearLayout
+            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_4"
+                android:layout_width="50dp"
+                android:layout_height="35dp"
+                android:background="@drawable/dock_key_selector" />
+
+            <RelativeLayout
+                android:id="@+id/rl_status_4"
+                android:layout_width="50dp"
+                android:layout_height="20dp"
+                android:layout_marginVertical="@dimen/common_spacing_small"
+                android:background="@drawable/dock_key_status_bg_selector"
+                android:gravity="center">
+
+                <TextView
+                    android:id="@+id/tv_status_4"
+                    style="@style/CommonTextView" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/tv_repair_4"
+                style="@style/CommonTextView"
+                android:background="@drawable/common_btn_red_bg"
+                android:text="@string/repair_key" />
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>

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


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


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


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

@@ -282,10 +282,22 @@
     <string name="login_method_tip">● 您可以通过指纹或刷卡直接进行登录</string>
     <string name="login_method_tip">● 您可以通过指纹或刷卡直接进行登录</string>
     <string name="no_key_available_dialog_tip">暂无可用钥匙,确认继续执行作业票吗?</string>
     <string name="no_key_available_dialog_tip">暂无可用钥匙,确认继续执行作业票吗?</string>
     <string name="lock_take_report_fail">挂锁取出上报失败</string>
     <string name="lock_take_report_fail">挂锁取出上报失败</string>
+    <string name="board_address_exists">存在相同地址的主板</string>
     <string name="row">行</string>
     <string name="row">行</string>
     <string name="column">列</string>
     <string name="column">列</string>
     <string name="please_input_row">请输入行号</string>
     <string name="please_input_row">请输入行号</string>
     <string name="please_input_column">请输入钥匙列号</string>
     <string name="please_input_column">请输入钥匙列号</string>
     <string name="row_and_column_conflict">存在相同的行列号,请重新输入</string>
     <string name="row_and_column_conflict">存在相同的行列号,请重新输入</string>
     <string name="column_must_be_1_or_2">钥匙列号只能输入1或者2</string>
     <string name="column_must_be_1_or_2">钥匙列号只能输入1或者2</string>
+    <string name="device_status">设备状态</string>
+    <string name="key_does_not_exists">钥匙不存在</string>
+    <string name="key_no_rfid">钥匙RFID缺失</string>
+    <string name="key_no_mac">钥匙Mac缺失</string>
+    <string name="key_no_connected">钥匙未连接</string>
+    <string name="key_not_in_ready_mode">钥匙未处于待机模式</string>
+    <string name="key_has_exception">钥匙发生异常</string>
+    <string name="key_is_available">正常</string>
+    <string name="key_unknown">未知</string>
+    <string name="repair_key">修复</string>
+    <string name="no_key_to_repair">钥匙不存在,无法修复</string>
 </resources>
 </resources>