From c7376f8d1091b70597ba4430a281496b585b386e Mon Sep 17 00:00:00 2001
From: weimingfei <fei_gaming@sina.com>
Date: 星期四, 23 十月 2025 21:58:26 +0800
Subject: [PATCH] 钥匙柜

---
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java                           |   48 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java                                  |    4 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java                          |   13 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java                           |    5 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridOneResultEvent.java                  |   30 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDB.java                             |   70 +
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java              |  294 ++++
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/SendPortCode.java                            |   27 
 keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml                                          |    4 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/AlcoholTestAlarmParam.java              |   14 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java                    |   22 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLKeyEvent.java                              |   17 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDao.java                            |   98 +
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java               |    6 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java               |    4 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java                 |   77 +
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java                     |   26 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLGridEvent.java                             |   17 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/TimeOutUnCloseAlarmParam.java           |   34 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java           |  352 ++++++
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CloseGridOneResultEvent.java                 |   30 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/DaoManager.java                                |   11 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java                    |   43 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridListEvent.java                       |   19 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java             |   47 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java                       |    8 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java                         |  185 +++
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java                   |    7 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java                        |    5 
 keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml                                        |   65 +
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDo.java                             |  143 ++
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java                 |    6 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/HttpEvent.java                               |   17 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java                            |   34 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java                          |    2 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java                     |   34 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java                 |   24 
 keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml                                               |    2 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java                                |   42 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java                          |  861 ++++++++++++++-
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java                                |    2 
 keyCabinet-android/app/src/main/res/layout/main_activity.xml                                                  |   37 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java |   11 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java                                |  205 ++
 /dev/null                                                                                                     |   21 
 keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java                  |    7 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java                             |    4 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java                                     |   51 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/CabinetConfigDataBean.java                    |   47 
 keyCabinet-android/app/src/main/AndroidManifest.xml                                                           |    6 
 keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java                            |   22 
 keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java                            |   19 
 52 files changed, 2,843 insertions(+), 336 deletions(-)

diff --git a/keyCabinet-android/app/src/main/AndroidManifest.xml b/keyCabinet-android/app/src/main/AndroidManifest.xml
index 24ba31a..4ee6977 100644
--- a/keyCabinet-android/app/src/main/AndroidManifest.xml
+++ b/keyCabinet-android/app/src/main/AndroidManifest.xml
@@ -93,7 +93,10 @@
             android:name="org.apache.http.legacy"
             android:required="false" />
     </application>
-
+    <uses-permission android:name="android.permission.ACCESS_SURERUSER" />
+    <uses-permission android:name="android.permission.USB_PERMISSION"/>
+    <uses-feature android:name="android.hardware.usb.host"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-feature android:name="android.hardware.nfc" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
@@ -116,6 +119,7 @@
     <uses-permission
         android:name="android.permission.INTERACT_ACROSS_USERS"
         tools:ignore="ProtectedPermissions" />
+
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
     <uses-permission
         android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java
index fb4269e..dd5309b 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java
@@ -143,7 +143,7 @@
     }
 
     private static CountTimerCallBack timerCallBack;
-    public static void initCountTimer(boolean isToGuild,CountTimerCallBack callBack){
+    public static void initCountTimer(long time,CountTimerCallBack callBack){
         if(countTimer!=null){
             countTimer.cancel();
         }
@@ -154,7 +154,7 @@
             return;
         }
         timerCallBack = callBack;
-        countTimer = new CountDownTimer(60*1000, 1*1000) {
+        countTimer = new CountDownTimer(time, 1*1000) {
             @Override
             public void onTick(long millisUntilFinished) {
                 //Timber.tag("CountTimer==>").d(millisUntilFinished+"");
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java
index d9d1fbb..dfab7c0 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java
@@ -68,6 +68,7 @@
         switch (ev.getAction()) {
             //鑾峰彇瑙︽懜鍔ㄤ綔锛屽鏋淎CTION_UP锛岃鏃跺紑濮嬨��
             case MotionEvent.ACTION_UP:
+                downTime = 60;
                 initCountTimer();
                 break;
             //鍚﹀垯鍏朵粬鍔ㄤ綔璁℃椂鍙栨秷
@@ -78,11 +79,13 @@
         return super.dispatchTouchEvent(ev);
     }
 
+    protected long downTime = 60;
+
     protected void initCountTimer(){
         if(!isAddCountTimer){
             return;
         }
-        MApplication.initCountTimer(isToGuild,timerCallBack);
+        MApplication.initCountTimer(downTime*1000,timerCallBack);
         MApplication.startCountTimer();
     }
 
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/CabinetConfigDataBean.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/CabinetConfigDataBean.java
new file mode 100644
index 0000000..5da1b85
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/CabinetConfigDataBean.java
@@ -0,0 +1,47 @@
+package com.doumee.keyCabinet.bean;
+
+/**
+ * 閰掔簿妫�娴嬮厤缃�
+ */
+public class CabinetConfigDataBean {
+    //鍚规皵鏃堕暱锛堢锛�
+    private String blowTime;
+    //鍘嬪姏鍊�
+    private String pressure;
+    //娴撳害闃堝�煎崟浣� (1=mg/100ml;2=mg/L;3=%BAC)
+    private String threshold;
+    //娴撳害闃堝��
+    private String concentration;
+
+    public String getBlowTime() {
+        return blowTime;
+    }
+
+    public void setBlowTime(String blowTime) {
+        this.blowTime = blowTime;
+    }
+
+    public String getPressure() {
+        return pressure;
+    }
+
+    public void setPressure(String pressure) {
+        this.pressure = pressure;
+    }
+
+    public String getThreshold() {
+        return threshold;
+    }
+
+    public void setThreshold(String threshold) {
+        this.threshold = threshold;
+    }
+
+    public String getConcentration() {
+        return concentration;
+    }
+
+    public void setConcentration(String concentration) {
+        this.concentration = concentration;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java
index d2fd780..84039a2 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java
@@ -18,6 +18,9 @@
     private String info;
     //璁惧鍚嶇О
     private String name;
+    private CabinetConfigDataBean cabinetConfigDataVO;
+
+    private List<ManageKeyCabinetBean> cabinetGridInfoVOList;
 
     public List<String> getBannerList() {
         return bannerList;
@@ -74,4 +77,20 @@
     public void setName(String name) {
         this.name = name;
     }
+
+    public List<ManageKeyCabinetBean> getCabinetGridInfoVOList() {
+        return cabinetGridInfoVOList;
+    }
+
+    public void setCabinetGridInfoVOList(List<ManageKeyCabinetBean> cabinetGridInfoVOList) {
+        this.cabinetGridInfoVOList = cabinetGridInfoVOList;
+    }
+
+    public CabinetConfigDataBean getCabinetConfigDataVO() {
+        return cabinetConfigDataVO;
+    }
+
+    public void setCabinetConfigDataVO(CabinetConfigDataBean cabinetConfigDataVO) {
+        this.cabinetConfigDataVO = cabinetConfigDataVO;
+    }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java
index 94ca5b6..d1b2017 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java
@@ -10,47 +10,47 @@
 
 public class KeyCabinetBean implements Serializable {
     //缁戝畾鐘舵�� 0鏈粦瀹氾紱1宸茬粦瀹�
-    private int bindStatus;
+    private Integer bindStatus;
     //鏉垮彿
     private String boardCode;
     //閽ュ寵鏌滅紪鐮�
-    private int cabinetId;
+    private Integer cabinetId;
     //閽ュ寵鏌滃悕绉�
     private String cabinetName;
     //杞︾墝鍙�
     private String carCode;
     //杞﹁締涓婚敭
-    private int carId;
+    private Integer carId;
     //閫氶亾鍙�
     private String channelCode;
     //缂栫爜
     private String code;
     //涓婚敭
-    private int id;
+    private Integer id;
     //澶囨敞
     private String info;
     //閽ュ寵缂栫爜
     private String keyCode;
     //閽ュ寵缂栫爜
-    private int keyId;
+    private Integer keyId;
     //閽ュ寵鐘舵�� 0鏈粦瀹� 1鍦ㄤ綅 2鍊熷嚭 3缁翠慨淇濆吇
-    private int keyStatus;
+    private Integer keyStatus;
     //搴忓垪鍙�
     private String serialNo;
     //鐘舵�� 0鍚敤锛�1绂佺敤
-    private int status;
+    private Integer status;
     //杩愯鐘舵�� 0姝e父 1鏁呴殰
-    private int workingStatus;
+    private Integer workingStatus;
 
     private ObservableField<Boolean> isSelected = new ObservableField<>(false);
     private ObservableField<Integer> text1Color = new ObservableField<>(0xff111111);
     private ObservableField<Integer> text2Color = new ObservableField<>(0xff279baa);
 
-    public int getBindStatus() {
+    public Integer getBindStatus() {
         return bindStatus;
     }
 
-    public void setBindStatus(int bindStatus) {
+    public void setBindStatus(Integer bindStatus) {
         this.bindStatus = bindStatus;
     }
 
@@ -62,11 +62,11 @@
         this.boardCode = boardCode;
     }
 
-    public int getCabinetId() {
+    public Integer getCabinetId() {
         return cabinetId;
     }
 
-    public void setCabinetId(int cabinetId) {
+    public void setCabinetId(Integer cabinetId) {
         this.cabinetId = cabinetId;
     }
 
@@ -86,11 +86,11 @@
         this.carCode = carCode;
     }
 
-    public int getCarId() {
+    public Integer getCarId() {
         return carId;
     }
 
-    public void setCarId(int carId) {
+    public void setCarId(Integer carId) {
         this.carId = carId;
     }
 
@@ -110,11 +110,11 @@
         this.code = code;
     }
 
-    public int getId() {
+    public Integer getId() {
         return id;
     }
 
-    public void setId(int id) {
+    public void setId(Integer id) {
         this.id = id;
     }
 
@@ -134,19 +134,19 @@
         this.keyCode = keyCode;
     }
 
-    public int getKeyId() {
+    public Integer getKeyId() {
         return keyId;
     }
 
-    public void setKeyId(int keyId) {
+    public void setKeyId(Integer keyId) {
         this.keyId = keyId;
     }
 
-    public int getKeyStatus() {
+    public Integer getKeyStatus() {
         return keyStatus;
     }
 
-    public void setKeyStatus(int keyStatus) {
+    public void setKeyStatus(Integer keyStatus) {
         this.keyStatus = keyStatus;
     }
 
@@ -158,19 +158,19 @@
         this.serialNo = serialNo;
     }
 
-    public int getStatus() {
+    public Integer getStatus() {
         return status;
     }
 
-    public void setStatus(int status) {
+    public void setStatus(Integer status) {
         this.status = status;
     }
 
-    public int getWorkingStatus() {
+    public Integer getWorkingStatus() {
         return workingStatus;
     }
 
-    public void setWorkingStatus(int workingStatus) {
+    public void setWorkingStatus(Integer workingStatus) {
         this.workingStatus = workingStatus;
     }
 
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java
index 8563de9..7a6d3be 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java
@@ -3,7 +3,7 @@
 //褰撳墠鐧诲綍淇℃伅
 public class LoginBean {
     private Integer autoMemberId;
-    private Integer memberId;
+    private Integer memberId = 6572;
 
     //鐢ㄦ埛楠岃瘉鏂瑰紡 0鍒疯劯 1鍒峰崱
     private int authType;
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java
index f7e1ae4..6ec7954 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java
@@ -8,7 +8,7 @@
     //鏉垮彿
     private String boardCode;
     //杞︾墝鍙�
-    private int carCode;
+    private String carCode;
     //閫氶亾鍙�
     private String channelCode;
     //缂栫爜
@@ -19,6 +19,10 @@
     private Integer keyId;
     //閽ュ寵鐘舵�� 0鏈粦瀹� 1鍦ㄤ綅 2鍊熷嚭 3缁翠慨淇濆吇
     private Integer keyStatus;
+    //閽ュ寵缂栫爜
+    private String keyCode;
+    //鐘舵�� 0鍚敤锛�1绂佺敤
+    private Integer status;
     //鏌滀綋杩愯鐘舵�� 0姝e父 1鏁呴殰
     private Integer workingStatus;
     private ObservableField<Boolean> isSelected = new ObservableField<>(false);
@@ -43,11 +47,11 @@
         this.boardCode = boardCode;
     }
 
-    public int getCarCode() {
+    public String getCarCode() {
         return carCode;
     }
 
-    public void setCarCode(int carCode) {
+    public void setCarCode(String carCode) {
         this.carCode = carCode;
     }
 
@@ -98,4 +102,20 @@
     public void setWorkingStatus(Integer workingStatus) {
         this.workingStatus = workingStatus;
     }
+
+    public String getKeyCode() {
+        return keyCode;
+    }
+
+    public void setKeyCode(String keyCode) {
+        this.keyCode = keyCode;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDB.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDB.java
new file mode 100644
index 0000000..09a5ffb
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDB.java
@@ -0,0 +1,70 @@
+package com.doumee.keyCabinet.dao;
+
+import android.content.Context;
+
+import androidx.room.Database;
+import androidx.room.Room;
+import androidx.room.RoomDatabase;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+@Database(entities = {CabinetGridDo.class}, version = 1,exportSchema = false)
+public abstract class CabinetGridDB extends RoomDatabase {
+    public abstract CabinetGridDao cabinetGridDao();
+    private static CabinetGridDB INSTANCE;
+    private static final Object sLock = new Object();
+    //鏁版嵁搴撹縼绉� 1-->2
+    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
+        @Override
+        public void migrate(SupportSQLiteDatabase database) {
+            database.execSQL("ALTER TABLE department ADD COLUMN phone_num TEXT");
+            //database.execSQL("ALTER TABLE department ADD COLUMN phone_num INTEGER NOT NULL DEFAULT 0");
+        }
+    };
+    //璺宠穬寮忚縼绉�
+    static final Migration MIGRATION_2_4 = new Migration(2, 4) {
+        @Override
+        public void migrate(SupportSQLiteDatabase database) {
+            //鍒涘缓琛�
+            database.execSQL(
+                    "CREATE TABLE student_new (student_id TEXT, student_name TEXT, phone_num INTEGER, PRIMARY KEY(student_id))");
+            //澶嶅埗琛�
+            database.execSQL(
+                    "INSERT INTO student_new (student_id, student_name, phone_num) SELECT student_id, student_name, phone_num FROM student");
+            //鍒犻櫎琛�
+            database.execSQL("DROP TABLE student");
+            //淇敼琛ㄥ悕绉�
+            database.execSQL("ALTER TABLE student_new RENAME TO students");
+        }
+    };
+    //璺宠穬寮忚縼绉�
+    static final Migration MIGRATION_1_4 = new Migration(1, 4) {
+        @Override
+        public void migrate(SupportSQLiteDatabase database) {
+            //鍒涘缓琛�
+            database.execSQL(
+                    "CREATE TABLE student_new (student_id TEXT, student_name TEXT, phone_num INTEGER, PRIMARY KEY(student_id))");
+            //澶嶅埗琛�
+            database.execSQL(
+                    "INSERT INTO student_new (student_id, student_name, phone_num) SELECT student_id, student_name, phone_num FROM student");
+            //鍒犻櫎琛�
+            database.execSQL("DROP TABLE student");
+            //淇敼琛ㄥ悕绉�
+            database.execSQL("ALTER TABLE student_new RENAME TO students");
+        }
+    };
+
+    public static CabinetGridDB getInstance(Context context) {
+        synchronized (sLock) {
+            if (INSTANCE == null) {
+                INSTANCE =
+                        Room.databaseBuilder(context.getApplicationContext(), CabinetGridDB.class, "CabinetGrid.db")
+                                .allowMainThreadQueries()//Room涓嶅厑璁稿湪涓荤嚎绋嬩腑璁块棶鏁版嵁搴�
+                                //.addMigrations(MIGRATION_1_2)//鏁版嵁搴撹縼绉�
+                                //.addMigrations(MIGRATION_1_2,MIGRATION_2_4,MIGRATION_1_4)//鏁版嵁搴撹縼绉� ,鍙互鐢�1_4,蹇�熻縼绉�
+                                .build();
+            }
+            return INSTANCE;
+        }
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDao.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDao.java
new file mode 100644
index 0000000..26adf80
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDao.java
@@ -0,0 +1,98 @@
+package com.doumee.keyCabinet.dao;
+
+import androidx.room.Dao;
+import androidx.room.Delete;
+import androidx.room.Insert;
+import androidx.room.Query;
+import androidx.room.Transaction;
+import androidx.room.Update;
+
+import java.util.List;
+/**"SELECT user.id, user.name, user.departmentId," +
+        "department.name AS departmentName FROM user " +
+        "INNER JOIN department ON user.departmentId = department.id"*/
+
+/**
+ * 涓�瀵逛竴
+ * @Entity
+    public class User {
+        @PrimaryKey public long userId;
+        public String name;
+        public int age;
+    }
+
+     @Entity
+     public class Library {
+         @PrimaryKey public long libraryId;
+         public long userOwnerId;
+     }
+ */
+@Dao
+public interface CabinetGridDao {
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid")
+    List<CabinetGridDo> loadAll();
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE id = :id")
+    CabinetGridDo getGridBuyId(int id);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE grid_key = :key")
+    CabinetGridDo getGridByKey(String key);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE grid_key IN (:keys)")
+    List<CabinetGridDo> getGridByKeys(List<String> keys);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE id = :id")
+    List<CabinetGridDo> getGridsById(int id);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE id IN (:ids)")
+    List<CabinetGridDo> getGridsByIds(int... ids);
+
+/*
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE cabinet_name = :name LIMIT 1")
+    List<CabinetGridDo> getStudentByName(String name);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE cabinet_name LIKE '%' || :name || '%'")
+    List<CabinetGridDo> searchStudentByName(String name);
+*/
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE is_open = :isOpen")
+    List<CabinetGridDo> getGridByOpenStatus(int isOpen);
+
+    @Transaction
+    @Query("SELECT * FROM cabinet_grid WHERE is_open = 1 and working_status = 0 and grid_status = 0 order by grid_key asc")
+    List<CabinetGridDo> getOpenGrids();
+
+    @Transaction
+    @Query("SELECT count(*) FROM cabinet_grid WHERE is_open = 1")
+    int getOpenGridCount();
+
+    @Transaction
+    @Insert
+    void insert(CabinetGridDo data);
+
+    @Transaction
+    @Insert
+    void insertAll(CabinetGridDo... datas);
+
+    @Transaction
+    @Insert
+    void insert(List<CabinetGridDo> studentLists);
+
+    @Transaction
+    @Update
+    void update(CabinetGridDo... datas);
+
+    @Transaction
+    @Delete
+    void delete(CabinetGridDo... datas);
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDo.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDo.java
new file mode 100644
index 0000000..1d677c0
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDo.java
@@ -0,0 +1,143 @@
+package com.doumee.keyCabinet.dao;
+
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+@Entity(tableName = "cabinet_grid")
+public class CabinetGridDo {
+    @PrimaryKey(autoGenerate = true)
+    private int id;
+    @ColumnInfo(name = "grid_id",typeAffinity = ColumnInfo.INTEGER)
+    //鏌滄牸涓婚敭
+    private int  gridId;;
+
+    @ColumnInfo(name = "is_open",typeAffinity = ColumnInfo.INTEGER)
+    //0锛氬叧锛�1锛氬紑
+    private int isOpen;
+
+    @ColumnInfo(name = "grid_key",typeAffinity = ColumnInfo.TEXT)
+    //鐗堝彿+閫氶亾鍙�
+    private String gridKey;
+    @ColumnInfo(name = "cabinet_name",typeAffinity = ColumnInfo.TEXT)
+    //閽ュ寵鏌滃悕绉�
+    private String cabinetName;
+    @ColumnInfo(name = "key_code",typeAffinity = ColumnInfo.TEXT)
+    //閽ュ寵缂栫爜
+    private String keyCode;
+
+    @ColumnInfo(name = "cur_key_code",typeAffinity = ColumnInfo.TEXT)
+    //褰撳墠閽ュ寵缂栫爜
+    private String curKeyCode;
+
+    @ColumnInfo(name = "bind_status",typeAffinity = ColumnInfo.INTEGER)
+    //缁戝畾鐘舵�� 0鏈粦瀹氾紱1宸茬粦瀹�
+    private int bindStatus;
+    @ColumnInfo(name = "key_status",typeAffinity = ColumnInfo.INTEGER)
+    //閽ュ寵鐘舵�� 0鏈粦瀹� 1鍦ㄤ綅 2鍊熷嚭 3缁翠慨淇濆吇
+    private int keyStatus;
+    @ColumnInfo(name = "grid_status",typeAffinity = ColumnInfo.INTEGER)
+    //鐘舵�� 0鍚敤锛�1绂佺敤
+    private int gridStatus;
+    @ColumnInfo(name = "working_status",typeAffinity = ColumnInfo.INTEGER)
+    //杩愯鐘舵�� 0姝e父 1鏁呴殰
+    private int workingStatus;
+    @ColumnInfo(name = "update_time",typeAffinity = ColumnInfo.TEXT)
+    private String updateTime;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getGridKey() {
+        return gridKey;
+    }
+
+    public void setGridKey(String gridKey) {
+        this.gridKey = gridKey;
+    }
+
+    public int getIsOpen() {
+        return isOpen;
+    }
+
+    public void setIsOpen(int isOpen) {
+        this.isOpen = isOpen;
+    }
+
+    public String getCabinetName() {
+        return cabinetName;
+    }
+
+    public void setCabinetName(String cabinetName) {
+        this.cabinetName = cabinetName;
+    }
+
+    public String getKeyCode() {
+        return keyCode;
+    }
+
+    public void setKeyCode(String keyCode) {
+        this.keyCode = keyCode;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getCurKeyCode() {
+        return curKeyCode;
+    }
+
+    public void setCurKeyCode(String curKeyCode) {
+        this.curKeyCode = curKeyCode;
+    }
+
+    public int getGridId() {
+        return gridId;
+    }
+
+    public void setGridId(int gridId) {
+        this.gridId = gridId;
+    }
+
+    public int getBindStatus() {
+        return bindStatus;
+    }
+
+    public void setBindStatus(int bindStatus) {
+        this.bindStatus = bindStatus;
+    }
+
+    public int getKeyStatus() {
+        return keyStatus;
+    }
+
+    public void setKeyStatus(int keyStatus) {
+        this.keyStatus = keyStatus;
+    }
+
+    public int getGridStatus() {
+        return gridStatus;
+    }
+
+    public void setGridStatus(int gridStatus) {
+        this.gridStatus = gridStatus;
+    }
+
+    public int getWorkingStatus() {
+        return workingStatus;
+    }
+
+    public void setWorkingStatus(int workingStatus) {
+        this.workingStatus = workingStatus;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/DaoManager.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/DaoManager.java
new file mode 100644
index 0000000..5d19688
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/DaoManager.java
@@ -0,0 +1,11 @@
+package com.doumee.keyCabinet.dao;
+
+
+import com.doumee.keyCabinet.MApplication;
+
+public class DaoManager {
+
+    public static CabinetGridDao getCabinetGridDao(){
+        return CabinetGridDB.getInstance(MApplication.mContext).cabinetGridDao();
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLGridEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLGridEvent.java
new file mode 100644
index 0000000..9f5f0d9
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLGridEvent.java
@@ -0,0 +1,17 @@
+package com.doumee.keyCabinet.event;
+
+public class CLGridEvent {
+    private String data;
+
+    public CLGridEvent(String data) {
+        this.data = data;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLKeyEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLKeyEvent.java
new file mode 100644
index 0000000..ba32cbe
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLKeyEvent.java
@@ -0,0 +1,17 @@
+package com.doumee.keyCabinet.event;
+
+public class CLKeyEvent {
+    private String data;
+
+    public CLKeyEvent(String data) {
+        this.data = data;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CloseGridOneResultEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CloseGridOneResultEvent.java
new file mode 100644
index 0000000..a2b68d0
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CloseGridOneResultEvent.java
@@ -0,0 +1,30 @@
+package com.doumee.keyCabinet.event;
+
+/**
+ * 鍗曚釜鍏抽棬闂ㄨ繑鍥�
+ */
+public class CloseGridOneResultEvent {
+    private String key;
+    private int isOpen;
+
+    public CloseGridOneResultEvent(String key, int isOpen) {
+        this.key = key;
+        this.isOpen = isOpen;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public int getIsOpen() {
+        return isOpen;
+    }
+
+    public void setIsOpen(int isOpen) {
+        this.isOpen = isOpen;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java
new file mode 100644
index 0000000..f1c6886
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java
@@ -0,0 +1,8 @@
+package com.doumee.keyCabinet.event;
+
+/**
+ * 鑾峰彇閽ュ寵鐘舵��
+ */
+public class GetKeyStatusEvent {
+
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/HttpEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/HttpEvent.java
new file mode 100644
index 0000000..78384dc
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/HttpEvent.java
@@ -0,0 +1,17 @@
+package com.doumee.keyCabinet.event;
+
+public class HttpEvent {
+    private String msg;
+
+    public HttpEvent(String msg) {
+        this.msg = msg;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyDoorEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyDoorEvent.java
deleted file mode 100644
index 347ace3..0000000
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyDoorEvent.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.doumee.keyCabinet.event;
-
-/**
- * 闂ㄧ洃鍚繑鍥�
- */
-public class KeyDoorEvent {
-    //闂ㄤ俊鎭�
-    private String result;
-
-    public KeyDoorEvent(String result) {
-        this.result = result;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
-}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java
index cb4325a..a344aa7 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java
@@ -4,18 +4,5 @@
  * 閽ュ寵鐩戝惉杩斿洖
  */
 public class KeyResultEvent {
-    //閽ュ寵淇℃伅
-    private String result;
 
-    public KeyResultEvent(String result) {
-        this.result = result;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyStatusListener.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyStatusListener.java
deleted file mode 100644
index 817a981..0000000
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyStatusListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.doumee.keyCabinet.event;
-
-/**
- * 閽ュ寵鐘舵�佸紑濮嬬洃鍚�
- */
-public class KeyStatusListener {
-    //0锛氬紑濮嬶紝1锛氱粨鏉�
-    private int status;
-
-    public KeyStatusListener(int status) {
-        this.status = status;
-    }
-
-    public int getStatus() {
-        return status;
-    }
-
-    public void setStatus(int status) {
-        this.status = status;
-    }
-}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java
new file mode 100644
index 0000000..2897932
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java
@@ -0,0 +1,6 @@
+package com.doumee.keyCabinet.event;
+
+//绠$悊鍛樺紑闂ㄧ粨鏉�
+public class ManageOpenGridResultEvent {
+
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java
new file mode 100644
index 0000000..8fdfaae
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java
@@ -0,0 +1,5 @@
+package com.doumee.keyCabinet.event;
+
+public class OpenAllGridEvent {
+
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridListEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridListEvent.java
new file mode 100644
index 0000000..6b9f032
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridListEvent.java
@@ -0,0 +1,19 @@
+package com.doumee.keyCabinet.event;
+
+import java.util.List;
+
+public class OpenGridListEvent {
+    private List<String> keys;
+
+    public OpenGridListEvent(List<String> keys) {
+        this.keys = keys;
+    }
+
+    public List<String> getKeys() {
+        return keys;
+    }
+
+    public void setKeys(List<String> keys) {
+        this.keys = keys;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridOneResultEvent.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridOneResultEvent.java
new file mode 100644
index 0000000..287ebbd
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridOneResultEvent.java
@@ -0,0 +1,30 @@
+package com.doumee.keyCabinet.event;
+
+/**
+ * 鍗曚釜寮�闂ㄨ繑鍥�
+ */
+public class OpenGridOneResultEvent {
+    private String key;
+    private int isOpen;
+
+    public OpenGridOneResultEvent(String key, int isOpen) {
+        this.key = key;
+        this.isOpen = isOpen;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public int getIsOpen() {
+        return isOpen;
+    }
+
+    public void setIsOpen(int isOpen) {
+        this.isOpen = isOpen;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/SendPortCode.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/SendPortCode.java
new file mode 100644
index 0000000..aa54cae
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/SendPortCode.java
@@ -0,0 +1,27 @@
+package com.doumee.keyCabinet.event;
+
+public class SendPortCode {
+    private int type;
+    private String code;
+
+    public SendPortCode(int type, String code) {
+        this.type = type;
+        this.code = code;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java
index 641f088..e6967f9 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java
@@ -21,12 +21,13 @@
 import retrofit2.http.Query;
 
 public interface Apis {
-    String HTTP = "http://192.168.0.112:8086/";
+    //娴嬭瘯鏈�
+    String HTTP = "http://192.168.1.45:10010/";
     String HEAT_HTTP = "do?c=220301";
     /**
      * 鏌ヨ鐗堟湰淇℃伅
      */
-    @GET("/visitsAdmin/cloudService/web/cabinet/getLastVersion")
+    @GET("visitsAdmin/cloudService/web/cabinet/getLastVersion")
     Observable<BaseResponse<AndroidVersionBean>> getVersion();
 
     /**
@@ -34,13 +35,13 @@
      * @param code
      * @return
      */
-    @GET("/visitsAdmin/cloudService/web/cabinet/getCabinetInfoForDriver")
+    @GET("visitsAdmin/cloudService/web/cabinet/getCabinetInfoForDriver")
     Observable<BaseResponse<DevConfigBean>> getCabinetInfoForDriver(@Query("code")String code);
 
     /**
      * 蹇冭烦
      */
-    @GET("/visitsAdmin/cloudService/web/cabinet/updateRunStatusById")
+    @GET("visitsAdmin/cloudService/web/cabinet/updateRunStatusById")
     Observable<BaseResponse> heart(@Query("id")Integer id);
 
     /**
@@ -52,67 +53,79 @@
     /**
      * 浜鸿劯鍒楄〃
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/getCabinetFaceVO")
-    Observable<BaseResponse<CabinetFaceBean>> allFaceList(@Body RequestBody requestBody);
+    @GET("visitsAdmin/cloudService/web/cabinet/getCabinetFaceVO")
+    Observable<BaseResponse<CabinetFaceBean>> allFaceList(@Query("code")String code);
 
      /**
-     * 鑾峰彇鍙搷浣滄煖鏍� - 鍙告満
+     * 鑾峰彇IC鍗$敤鎴蜂富閿� - 鍙告満
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/getMemberIdByCode")
-    Observable<BaseResponse<Integer>> getMemberIdByCode(@Body RequestBody requestBody);
+    @POST("visitsAdmin/cloudService/web/cabinet/getMemberIdByCode")
+    Observable<BaseResponse<Integer>> getMemberIdByCode(@Query("code")String code);
+
+    /**
+     * 閰掔簿妫�娴嬪憡璀�
+     */
+    @POST("visitsAdmin/cloudService/web/cabinet/alcoholTestAlarm")
+    Observable<BaseResponse> alcoholTestAlarm(@Body RequestBody requestBody);
 
     /**
      * 鑾峰彇鍙搷浣滄煖鏍� - 鍙告満
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/getDriverGrid")
+    @POST("visitsAdmin/cloudService/web/cabinet/getDriverGrid")
     Observable<BaseResponse<List<KeyCabinetBean>>> getDriverGrid(@Body RequestBody requestBody);
 
     /**
      * 寮�鍚煖鏍� - 鍙告満
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/openGridDriver")
+    @POST("visitsAdmin/cloudService/web/cabinet/openGridDriver")
     Observable<BaseResponse> openGridDriver(@Body RequestBody requestBody);
+
+    /**
+     * 鏌滄牸寮�闂ㄨ秴鏃舵湭鍏抽棴鍛婅
+     */
+    @POST("visitsAdmin/cloudService/web/cabinet/timeOutUnCloseAlarm")
+    Observable<BaseResponse> timeOutUnCloseAlarm(@Body RequestBody requestBody);
 
     /**
      * 鍏抽棴鏌滄牸 - 鍙告満
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/closeGrid")
+    @POST("visitsAdmin/cloudService/web/cabinet/closeGrid")
     Observable<BaseResponse> closeGrid(@Body RequestBody requestBody);
 
     /**
      * 鑾峰彇閽ュ寵鏌滆鎯� - 绠$悊鍛�
      */
-    @GET("/visitsAdmin/cloudService/web/cabinet/getCabinetDetail")
+    @GET("visitsAdmin/cloudService/web/cabinet/getCabinetDetail")
     Observable<BaseResponse<CabinetDetailBean>> getCabinetDetail(@Header("dm_user_token") String token,@Query("cabinetId")Integer cabinetId);
 
     /**
      * 鎵归噺寮�闂� - 绠$悊鍛�
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/batchOpenGridAdmin")
+    @POST("visitsAdmin/cloudService/web/cabinet/batchOpenGridAdmin")
     Observable<BaseResponse> batchOpenGridAdmin(@Header("dm_user_token") String token,@Body RequestBody requestBody);
 
     /**
      * 鏍囪鏌滄牸姝e父 - 绠$悊鍛�
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/cancelFault")
+    @POST("visitsAdmin/cloudService/web/cabinet/cancelFault")
     Observable<BaseResponse> cancelFault(@Header("dm_user_token") String token,@Body RequestBody requestBody);
 
     /**
      * 鏍囪鏌滄牸鏁呴殰 - 绠$悊鍛�
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/markFault")
+    @POST("visitsAdmin/cloudService/web/cabinet/markFault")
     Observable<BaseResponse> markFault(@Header("dm_user_token") String token,@Body RequestBody requestBody);
 
     /**
      * 鏍囪缁翠慨淇濆吇 - 绠$悊鍛�
      */
-    @POST("/visitsAdmin/cloudService/web/cabinet/markRepair")
+    @POST("visitsAdmin/cloudService/web/cabinet/markRepair")
     Observable<BaseResponse> markRepair(@Header("dm_user_token") String token,@Body RequestBody requestBody);
 
     /**
-     * 鏍囪缁翠慨淇濆吇 - 绠$悊鍛�
+     * 鐧婚檰 - 绠$悊鍛�
      */
-    @POST("/loginCabinet")
+    @POST("loginCabinet")
     Observable<BaseResponse<String>> loginCabinet(@Body RequestBody requestBody);
 
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/AlcoholTestAlarmParam.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/AlcoholTestAlarmParam.java
new file mode 100644
index 0000000..b6fd389
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/AlcoholTestAlarmParam.java
@@ -0,0 +1,14 @@
+package com.doumee.keyCabinet.http.param;
+
+public class AlcoholTestAlarmParam {
+    //浼氬憳id
+    private Integer memberId;
+
+    public Integer getMemberId() {
+        return memberId;
+    }
+
+    public void setMemberId(Integer memberId) {
+        this.memberId = memberId;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java
index bc73ced..dd82d9d 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java
@@ -12,11 +12,43 @@
     //鐢ㄦ埛涓婚敭
     private Integer memberId;
 
-    public CloseGridParam(Integer authType, Integer cabinetId, Integer gridId, Integer keyStatus, Integer memberId) {
+    public Integer getAuthType() {
+        return authType;
+    }
+
+    public void setAuthType(Integer authType) {
         this.authType = authType;
+    }
+
+    public Integer getCabinetId() {
+        return cabinetId;
+    }
+
+    public void setCabinetId(Integer cabinetId) {
         this.cabinetId = cabinetId;
+    }
+
+    public Integer getGridId() {
+        return gridId;
+    }
+
+    public void setGridId(Integer gridId) {
         this.gridId = gridId;
+    }
+
+    public Integer getKeyStatus() {
+        return keyStatus;
+    }
+
+    public void setKeyStatus(Integer keyStatus) {
         this.keyStatus = keyStatus;
+    }
+
+    public Integer getMemberId() {
+        return memberId;
+    }
+
+    public void setMemberId(Integer memberId) {
         this.memberId = memberId;
     }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java
index b6c2aab..70b7502 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java
@@ -7,43 +7,43 @@
 //鑾峰彇鍙搷浣滄煖鏍� - 鍙告満
 public class GetDriverGridParam implements Serializable {
     //楠岃瘉浜轰富閿�
-    private int autoMemberId;
+    private Integer autoMemberId;
     //閽ュ寵鏌滀富閿�
-    private int cabinetId;
+    private Integer cabinetId;
     //鐢ㄦ埛涓婚敭
-    private int memberId;
+    private Integer memberId;
     //0=鍙� 1=杩�
-    private int type;
+    private Integer type;
 
-    public int getAutoMemberId() {
+    public Integer getAutoMemberId() {
         return autoMemberId;
     }
 
-    public void setAutoMemberId(int autoMemberId) {
+    public void setAutoMemberId(Integer autoMemberId) {
         this.autoMemberId = autoMemberId;
     }
 
-    public int getCabinetId() {
+    public Integer getCabinetId() {
         return cabinetId;
     }
 
-    public void setCabinetId(int cabinetId) {
+    public void setCabinetId(Integer cabinetId) {
         this.cabinetId = cabinetId;
     }
 
-    public int getMemberId() {
+    public Integer getMemberId() {
         return memberId;
     }
 
-    public void setMemberId(int memberId) {
+    public void setMemberId(Integer memberId) {
         this.memberId = memberId;
     }
 
-    public int getType() {
+    public Integer getType() {
         return type;
     }
 
-    public void setType(int type) {
+    public void setType(Integer type) {
         this.type = type;
     }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/TimeOutUnCloseAlarmParam.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/TimeOutUnCloseAlarmParam.java
new file mode 100644
index 0000000..8b45416
--- /dev/null
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/TimeOutUnCloseAlarmParam.java
@@ -0,0 +1,34 @@
+package com.doumee.keyCabinet.http.param;
+
+public class TimeOutUnCloseAlarmParam {
+    //閽ュ寵鏌滀富閿�
+    private Integer cabinetId;
+    //鏌滄牸涓婚敭
+    private Integer gridId;
+    //鐢ㄦ埛涓婚敭
+    private Integer memberId;
+
+    public Integer getCabinetId() {
+        return cabinetId;
+    }
+
+    public void setCabinetId(Integer cabinetId) {
+        this.cabinetId = cabinetId;
+    }
+
+    public Integer getGridId() {
+        return gridId;
+    }
+
+    public void setGridId(Integer gridId) {
+        this.gridId = gridId;
+    }
+
+    public Integer getMemberId() {
+        return memberId;
+    }
+
+    public void setMemberId(Integer memberId) {
+        this.memberId = memberId;
+    }
+}
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java
index 91e67fb..b46bdf9 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java
@@ -38,10 +38,8 @@
     }
 
     public void getDatas(){
-        DevLoginParam param = new DevLoginParam();
-        param.setCode(LMobileInfo.getDeviceUniqueId());
         showLoading(true);
-        getRetrofitService(Apis.class).allFaceList(ParamsUtil.encodeRequestBody(param))
+        getRetrofitService(Apis.class).allFaceList(LMobileInfo.getDeviceUniqueId())
                 .compose(RxUtils.schedulersTransformer())
                 .subscribe(new SimpleObserver<BaseResponse<CabinetFaceBean>>(rxJavaGcManager) {
                     @Override
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java
index a1e6dba..2390109 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java
@@ -467,7 +467,7 @@
                     } else {
                         //浼樺厛浼氬憳
                         if("0".equals(user.getGroupId())){
-11
+
                         }else {
                             if (isCompareCheck) {
                                 getDB().clFail.setVisibility(View.VISIBLE);
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java
index 9937e41..9a45189 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java
@@ -8,10 +8,13 @@
 import com.doumee.keyCabinet.MApplication;
 import com.doumee.keyCabinet.bean.CabinetFaceBean;
 import com.doumee.keyCabinet.bean.FaceUserBean;
+import com.doumee.keyCabinet.bean.KeyCabinetBean;
 import com.doumee.keyCabinet.http.Apis;
+import com.doumee.keyCabinet.http.param.AlcoholTestAlarmParam;
 import com.doumee.keyCabinet.http.param.BaseResponse;
 import com.doumee.keyCabinet.http.param.DevLoginParam;
 import com.doumee.keyCabinet.http.param.GetMemberIdByCodeParam;
+import com.doumee.keyCabinet.http.param.OpenGridDriverParam;
 import com.doumee.keyCabinet.ui.main.MainActivity;
 import com.doumee.keyCabinet.utils.LMobileInfo;
 import com.doumee.keyCabinet.utils.ParamsUtil;
@@ -40,9 +43,8 @@
      * @param type //0锛氱鐞嗗憳锛�1锛氬徃鏈�
      */
     public void getMemberIdByCode(String code,String type){
-        GetMemberIdByCodeParam param = new GetMemberIdByCodeParam(code);
         showLoading(true);
-        getRetrofitService(Apis.class).getMemberIdByCode(ParamsUtil.encodeRequestBody(param))
+        getRetrofitService(Apis.class).getMemberIdByCode(code)
                 .compose(RxUtils.schedulersTransformer())
                 .subscribe(new SimpleObserver<BaseResponse<Integer>>(rxJavaGcManager) {
                     @Override
@@ -52,11 +54,11 @@
                             if(response.getData()!=null){
                                 if("0".equals(type)){
                                     MApplication.getLoginBean().setAutoMemberId(response.getData());
-                                    doAction();
+                                    //doAction();
                                 }else {
                                     MApplication.getLoginBean().setAutoMemberId(response.getData());
                                     MApplication.getLoginBean().setAuthType(1);
-                                    doAction();
+                                    //doAction();
                                 }
                             }
                         }else {
@@ -75,4 +77,36 @@
                     }
                 });
     }
+
+    /**
+     * 閰掔簿妫�娴嬪憡璀�
+     * @param data
+     */
+    public void alcoholTestAlarm(String data){
+        AlcoholTestAlarmParam param = new AlcoholTestAlarmParam();
+        param.setMemberId(MApplication.getLoginBean().getMemberId());
+        showLoading(true);
+        getRetrofitService(Apis.class).alcoholTestAlarm(ParamsUtil.encodeRequestBody(param))
+                .compose(RxUtils.schedulersTransformer())
+                .subscribe(new SimpleObserver<BaseResponse>(rxJavaGcManager) {
+                    @Override
+                    public void onNext(@NonNull BaseResponse response) {
+                        if(200==response.getCode()){
+
+                        }else {
+
+                        }
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+
+                    @Override
+                    public void onComplete() {
+                        hideLoading();
+                    }
+                });
+    }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java
index 03b6978..44934c8 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java
@@ -2,7 +2,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.lifecycle.Observer;
 
 import android.os.Bundle;
@@ -10,6 +9,7 @@
 import android.os.Message;
 import android.text.SpannableString;
 import android.text.Spanned;
+import android.text.TextUtils;
 import android.text.style.TextAppearanceSpan;
 import android.view.View;
 import android.widget.TextView;
@@ -19,23 +19,28 @@
 import com.doumee.keyCabinet.R;
 import com.doumee.keyCabinet.base.MyBaseActivity;
 import com.doumee.keyCabinet.bean.KeyCabinetBean;
+import com.doumee.keyCabinet.dao.CabinetGridDo;
+import com.doumee.keyCabinet.dao.DaoManager;
 import com.doumee.keyCabinet.databinding.KeyCabinetActivityBinding;
-import com.doumee.keyCabinet.event.KeyDoorEvent;
+import com.doumee.keyCabinet.event.CloseGridOneResultEvent;
 import com.doumee.keyCabinet.event.KeyResultEvent;
-import com.doumee.keyCabinet.event.KeyStatusListener;
+import com.doumee.keyCabinet.event.GetKeyStatusEvent;
 import com.doumee.keyCabinet.event.OpenGridEvent;
-import com.doumee.keyCabinet.ui.face.adapter.ErrRcvAdapter;
+import com.doumee.keyCabinet.event.OpenGridOneResultEvent;
 import com.doumee.keyCabinet.ui.keyCabinet.adapter.CabinetRcvAdapter;
-import com.doumee.lib_coremodel.base.BaseActivity;
+import com.doumee.keyCabinet.utils.i485.SportUtils;
 import com.doumee.lib_coremodel.bean.event.ActionEventData;
 import com.doumee.lib_coremodel.util.RecyclerHelp;
-import com.doumee.lib_coremodel.util.SpUtil;
+import com.doumee.lib_coremodel.util.StringUtil;
 
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Random;
 
 import dagger.hilt.android.AndroidEntryPoint;
 
@@ -55,18 +60,18 @@
         public void handleMessage(@NonNull Message msg) {
             switch (msg.what){
                 case 0:
-                    if (ysDownCount==4) {
+                    /*if (ysDownCount==4) {
                         //棰嗗彇閽ュ寵鍊掕鏃�
                         doRegister(7,null);
                         ysDownCount--;
                         handler.sendEmptyMessageDelayed(0,1000);
                     }else if (ysDownCount==0) {
                         //棰嗗彇閽ュ寵鍊掕鏃�
-                        doRegister(MApplication.nextBoolean()?5:6,null);
+                        //doRegister(MApplication.nextBoolean()?5:6,null);
                     }else {
                         ysDownCount--;
                         handler.sendEmptyMessageDelayed(0,1000);
-                    }
+                    }*/
                     break;
                 case 1:
 
@@ -84,6 +89,7 @@
 
     @Override
     public void initView(@Nullable Bundle savedInstanceState) {
+        isAddCountTimer = true;
         normalConfig();
         getDB().setModel(getVM());
         flag = MApplication.getLoginBean().getFlag();
@@ -110,6 +116,8 @@
                     changeBtBg();
                     adapter.refreshData(beans);
                     getVM().emptyVisibility.set(View.GONE);
+                    //鏇存柊淇℃伅
+                    updateDao(beans);
                 }else {
                     getVM().emptyVisibility.set(View.VISIBLE);
                 }
@@ -118,22 +126,78 @@
         getVM().getDatas();
     }
 
+    private void updateDao(List<KeyCabinetBean> beans){
+        List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+        HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+        for(CabinetGridDo d:gridDos){
+            oldMap.put(d.getGridKey(),d);
+        }
+        List<CabinetGridDo> addList = new ArrayList<>();
+        List<CabinetGridDo> updateList = new ArrayList<>();
+        for(KeyCabinetBean bean:beans){
+            String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode()))+SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+            if(oldMap.containsKey(key)){
+                //淇敼
+                CabinetGridDo gridDo = oldMap.get(key);
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                updateList.add(gridDo);
+            }else {
+                //鏂板
+                CabinetGridDo gridDo = new CabinetGridDo();
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setGridKey(key);
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                addList.add(gridDo);
+            }
+        }
+        if(addList.size()>0){
+            DaoManager.getCabinetGridDao().insert(addList);
+        }
+        if(updateList.size()>0){
+            CabinetGridDo[] upList = new CabinetGridDo[updateList.size()];
+            for(int i=0;i<updateList.size();i++){
+                upList[i] = updateList.get(i);
+            }
+            DaoManager.getCabinetGridDao().update(upList);
+        }
+    }
+
     @Override
     protected void timeChange(String djs) {
         getDB().tvDjs.setText(djs);
     }
 
+    private boolean isOpening = false;
     @Override
     protected void doRegister(int type, ActionEventData data) {
+        stopCountTimer();
+        downTime = 30;
         switch (type){
             case 1:
                 if(selectBean==null){
                     Toast.makeText(mContext, "璇烽�夋嫨鏌滈棬", Toast.LENGTH_SHORT).show();
                     return;
                 }
+                if(isOpening){
+                    return;
+                }
+                isOpening = true;
                 //寮�鍚煖闂�
                 getVM().openGridDriver(selectBean);
-                EventBus.getDefault().post(new OpenGridEvent(selectBean.getChannelCode(),selectBean.getBoardCode()));
+                downTime = 60;
                 break;
             case 2:
                 getDB().clTip1.setVisibility(View.GONE);
@@ -141,8 +205,10 @@
                     //閲嶆柊寮�闂�
                     EventBus.getDefault().post(new OpenGridEvent(selectBean.getChannelCode(), selectBean.getBoardCode()));
                 }
+                downTime = 60;
                 break;
             case 3:
+                isOpening = false;
                 //寮�鍚け璐�
                 getDB().btTip.setText("閲嶆柊寮�闂�");
                 getDB().imgJg1.setImageResource(R.mipmap.ic_jjfail);
@@ -150,8 +216,10 @@
                 getDB().tvJg2.setText(getErrPhoneText(),TextView.BufferType.SPANNABLE);
                 getDB().btTip.setVisibility(View.VISIBLE);
                 getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
                 break;
             case 4:
+                isOpening = false;
                 //寮�鍚垚鍔�
                 status=1;
                 if("0".equals(flag)) {
@@ -161,9 +229,10 @@
                     getDB().imgTip2.setImageResource(R.mipmap.ic_notclose);
                     getDB().tvTip22.setText("璇峰綊杩橀挜鍖欏悗鍏抽棴鏌滈棬");
                 }
-                getDB().tvTip21.setText(getTipText(selectBean.getCabinetName(),"鏌滈棬鎵撳紑鎴愬姛"), TextView.BufferType.SPANNABLE);
+                getDB().tvTip21.setText(getTipText(selectBean.getCode(),"鏌滈棬鎵撳紑鎴愬姛"), TextView.BufferType.SPANNABLE);
+                getDB().clTip1.setVisibility(View.GONE);
                 getDB().clTip2.setVisibility(View.VISIBLE);
-                EventBus.getDefault().post(new KeyStatusListener(0));
+                EventBus.getDefault().post(new GetKeyStatusEvent());
                 ysDownCount = 8;
                 handler.sendEmptyMessageDelayed(0,1000);
                 break;
@@ -171,18 +240,20 @@
                 //鎻愰啋鍏虫煖闂�
                 getDB().imgTip2.setImageResource(R.mipmap.ic_notclose);
                 getDB().tvTip22.setText("璇峰叧闂煖闂�");
-                getDB().tvTip21.setText(getTipText(selectBean.getCabinetName(),"鏌滈棬鏈叧闂�"), TextView.BufferType.SPANNABLE);
+                getDB().tvTip21.setText(getTipText(selectBean.getCode(),"鏌滈棬鏈叧闂�"), TextView.BufferType.SPANNABLE);
                 getDB().clTip2.setVisibility(View.VISIBLE);
+                getDB().clTip1.setVisibility(View.GONE);
                 break;
             case 5:
                 //鍏抽棬-閽ュ寵棰嗗彇鎴愬姛
                 status = 0;
-                getDB().clTip2.setVisibility(View.GONE);
                 getDB().imgJg1.setImageResource(R.mipmap.ic_success);
                 getDB().tvJg1.setText(getTipText(selectBean.getCarCode(),"閽ュ寵棰嗗彇鎴愬姛"), TextView.BufferType.SPANNABLE);
                 getDB().tvJg2.setText("鏌滈棬宸插叧闂�");
                 getDB().btTip.setVisibility(View.GONE);
                 getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
+                downTime = 10;
                 break;
             case 6:
                 //鍏抽棬-閽ュ寵棰嗗彇澶辫触
@@ -193,16 +264,27 @@
                 getDB().tvJg2.setText("鏌滈棬宸插叧闂�");
                 getDB().btTip.setVisibility(View.VISIBLE);
                 getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
+                break;
+            case 10:
+                status = 0;
+                getDB().imgJg1.setImageResource(R.mipmap.ic_jjfail);
+                getDB().tvJg1.setText("閽ュ寵瀛樻斁浣嶇疆閿欒");
+                getDB().tvJg2.setText(getErrPhoneText(),TextView.BufferType.SPANNABLE);
+                getDB().btTip.setVisibility(View.GONE);
+                getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
                 break;
             case 8:
                 //鍏抽棬-閽ュ寵褰掕繕鎴愬姛
                 status = 0;
-                getDB().clTip2.setVisibility(View.GONE);
                 getDB().imgJg1.setImageResource(R.mipmap.ic_success);
                 getDB().tvJg1.setText(getTipText(selectBean.getCarCode(),"閽ュ寵褰掕繕鎴愬姛"), TextView.BufferType.SPANNABLE);
                 getDB().tvJg2.setText("鏌滈棬宸插叧闂�");
                 getDB().btTip.setVisibility(View.GONE);
                 getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
+                downTime = 10;
                 break;
             case 9:
                 //鍏抽棬-閽ュ寵褰掕繕澶辫触
@@ -213,10 +295,12 @@
                 getDB().tvJg2.setText(getErrPhoneText(), TextView.BufferType.SPANNABLE);
                 getDB().btTip.setVisibility(View.VISIBLE);
                 getDB().clTip1.setVisibility(View.VISIBLE);
+                getDB().clTip2.setVisibility(View.GONE);
                 break;
             default:
                 break;
         }
+        initCountTimer();
     }
 
     private SpannableString getTipText(String name,String msg){
@@ -244,34 +328,30 @@
         }
     }
 
-    @Subscribe
-    public void KeyDoorEvent(KeyDoorEvent e){
-        if(!isFinishing()){
-            if("0".equals(e.getResult())){
-                //寮�闂ㄦ垚鍔�
-                doRegister(4,null);
-            }else {
-                //澶辫触
-                doRegister(3,null);
-            }
-        }
-    }
-
-    @Subscribe
+    @Subscribe(threadMode= ThreadMode.MAIN)
     public void KeyResultEvent(KeyResultEvent e){
         if(!isFinishing()){
-            if("0".equals(e.getResult())){
-                //鎴愬姛
-                if("0".equals(flag)){
-                    //閽ュ寵鎷胯蛋浜�
-                    //doRegister(5,null);
-                }else {
-                    //閽ュ寵鏀惧叆浜�
-
+            //閽ュ寵鍙樻洿浜�
+            if(selectBean!=null) {
+                String key = SportUtils.intToHex(Integer.parseInt(selectBean.getBoardCode()))
+                        + SportUtils.intToHex(Integer.parseInt(selectBean.getChannelCode()));
+                //鏌ヨ鏌滄牸
+                CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                if (gridDo != null) {
+                    if(flag==0){
+                        //鍙�
+                        if(TextUtils.isEmpty(gridDo.getKeyCode())){
+                            //绌轰簡
+                            doRegister(7,null);
+                        }
+                    }else {
+                        //杩�
+                        if(!TextUtils.isEmpty(gridDo.getKeyCode())){
+                            //鏈夐挜鍖欎簡
+                            doRegister(7,null);
+                        }
+                    }
                 }
-            }else {
-                //澶辫触
-
             }
         }
     }
@@ -282,4 +362,136 @@
         handler.removeCallbacksAndMessages(null);
         handler = null;
     }
+
+    private String openTime = "";
+    @Subscribe(threadMode= ThreadMode.MAIN)
+    public void OpenGridOneResultEvent(OpenGridOneResultEvent e){
+        if(!isFinishing()){
+            if(selectBean!=null){
+                String key = SportUtils.intToHex(Integer.parseInt(selectBean.getBoardCode()))
+                        +SportUtils.intToHex(Integer.parseInt(selectBean.getChannelCode()));
+                if(key.equals(e.getKey())) {
+                    if (e.getIsOpen()==1) {
+                        //寮�闂ㄦ垚鍔�
+                        if (isOpened) {
+                            return;
+                        }
+                        isOpened = true;
+                        openTime = StringUtil.DateToStr(new Date());
+                        Toast.makeText(mContext, "鎿嶄綔4", Toast.LENGTH_LONG).show();
+                        doRegister(4, null);
+                    } else {
+                        //澶辫触
+                        //濡傛灉鏄挜鍖欎笉瀵圭户缁紑闂�
+                        CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                        if (gridDo != null) {
+                            if(gridDo.getUpdateTime().compareTo(openTime)<0){
+                                //寮�闂ㄥ墠鏁版嵁锛屼笉鑳戒娇鐢�
+                                EventBus.getDefault().post(new GetKeyStatusEvent());
+                                return;
+                            }
+                            if (!gridDo.getCurKeyCode().equals(selectBean.getKeyCode())) {
+                                //閽ュ寵涓嶅尮閰�
+                                doRegister(10,null);
+                                EventBus.getDefault().post(new OpenGridEvent(selectBean.getChannelCode(), selectBean.getBoardCode()));
+                                return;
+                            }
+                        }
+                        doRegister(3, null);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isOpened = false;
+    @Subscribe(threadMode= ThreadMode.MAIN)
+    public void CloseGridOneResultEvent(CloseGridOneResultEvent e){
+        if(!isFinishing()){
+            if(selectBean!=null){
+                String key = SportUtils.intToHex(Integer.parseInt(selectBean.getBoardCode()))
+                        +SportUtils.intToHex(Integer.parseInt(selectBean.getChannelCode()));
+                if(key.equals(e.getKey())) {
+                    stopCountTimer();
+                    if(flag==0) {
+                        //棰嗗彇
+                        if (e.getIsOpen() == 0) {
+                            //鍏抽棬鎴愬姛
+                            //鏌ヨ閽ュ寵鍙�
+                            CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                            if (gridDo != null) {
+                                if(gridDo.getUpdateTime().compareTo(openTime)<0){
+                                    //寮�闂ㄥ墠鏁版嵁锛屼笉鑳戒娇鐢�
+                                    EventBus.getDefault().post(new GetKeyStatusEvent());
+                                    return;
+                                }
+                                //Toast.makeText(mContext, "1:"+gridDo.getKeyCode()+"锛�2:"+selectBean.getKeyCode(), Toast.LENGTH_LONG).show();
+                                if (!TextUtils.isEmpty(gridDo.getCurKeyCode())) {
+                                    if (gridDo.getCurKeyCode().equals(selectBean.getKeyCode())) {
+                                        //棰嗗彇澶辫触
+                                        isOpened = false;
+                                        doRegister(6, null);
+                                        getVM().closeGrid(gridDo);
+                                    }else {
+                                        //閽ュ寵涓嶅尮閰�
+                                        Toast.makeText(mContext, "鎿嶄綔10", Toast.LENGTH_LONG).show();
+                                        doRegister(10,null);
+                                        EventBus.getDefault().post(new OpenGridEvent(selectBean.getChannelCode(), selectBean.getBoardCode()));
+                                    }
+                                } else {
+                                    //閽ュ寵鎷胯蛋浜�
+                                    isOpened = false;
+                                    doRegister(5, null);
+                                    getVM().closeGrid(gridDo);
+                                }
+                                if (handler.hasMessages(0)) {
+                                    handler.removeMessages(0);
+                                }
+                            }else {
+                                Toast.makeText(mContext, "鏈煡璇㈠埌", Toast.LENGTH_LONG).show();
+                            }
+                        } else {
+                            //鍏抽棬澶辫触
+                        }
+                    }else {
+                        //褰掕繕
+                        if (e.getIsOpen() == 0) {
+                            //鍏抽棬鎴愬姛
+                            //鏌ヨ閽ュ寵鍙�
+                            CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                            if (gridDo != null) {
+                                if(gridDo.getUpdateTime().compareTo(openTime)<0){
+                                    //寮�闂ㄥ墠鏁版嵁锛屼笉鑳戒娇鐢�
+                                    EventBus.getDefault().post(new GetKeyStatusEvent());
+                                    return;
+                                }
+                                //Toast.makeText(mContext, "1:"+gridDo.getKeyCode()+"锛�2:"+selectBean.getKeyCode(), Toast.LENGTH_LONG).show();
+                                if (!TextUtils.isEmpty(gridDo.getCurKeyCode())) {
+                                    if (gridDo.getCurKeyCode().equals(selectBean.getKeyCode())) {
+                                        //鐩稿悓褰掕繕鎴愬姛
+                                        isOpened = false;
+                                        doRegister(8, null);
+                                        getVM().closeGrid(gridDo);
+                                    }else {
+                                        //閽ュ寵涓嶅尮閰�
+                                        doRegister(10,null);
+                                        EventBus.getDefault().post(new OpenGridEvent(selectBean.getChannelCode(), selectBean.getBoardCode()));
+                                    }
+                                } else {
+                                    //閽ュ寵鏈綊杩�
+                                    isOpened = false;
+                                    doRegister(9, null);
+                                    getVM().closeGrid(gridDo);
+                                }
+                            }else {
+                                Toast.makeText(mContext, "鏈煡璇㈠埌", Toast.LENGTH_LONG).show();
+                            }
+                        } else {
+                            //鍏抽棬澶辫触
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java
index 11eac8f..61cdd3a 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java
@@ -1,6 +1,7 @@
 package com.doumee.keyCabinet.ui.keyCabinet;
 
 import android.app.Application;
+import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
 import androidx.hilt.lifecycle.ViewModelInject;
@@ -9,8 +10,11 @@
 import com.doumee.keyCabinet.MApplication;
 import com.doumee.keyCabinet.bean.FaceUserBean;
 import com.doumee.keyCabinet.bean.KeyCabinetBean;
+import com.doumee.keyCabinet.bean.LoginBean;
+import com.doumee.keyCabinet.dao.CabinetGridDo;
 import com.doumee.keyCabinet.http.Apis;
 import com.doumee.keyCabinet.http.param.BaseResponse;
+import com.doumee.keyCabinet.http.param.CloseGridParam;
 import com.doumee.keyCabinet.http.param.GetDriverGridParam;
 import com.doumee.keyCabinet.http.param.OpenGridDriverParam;
 import com.doumee.keyCabinet.utils.ParamsUtil;
@@ -43,10 +47,16 @@
         /*List<KeyCabinetBean> list = new ArrayList<>();
         KeyCabinetBean b1 = new KeyCabinetBean();
         b1.setCabinetName("A01");
+        b1.setBoardCode("1");
+        b1.setChannelCode("1");
+        b1.setKeyCode("C97B092F");
         b1.setCarCode("鑻廇18829");
         list.add(b1);
         KeyCabinetBean b2 = new KeyCabinetBean();
         b2.setCabinetName("A02");
+        b2.setBoardCode("1");
+        b2.setChannelCode("2");
+        b2.setKeyCode("000000");
         b2.setCarCode("鑻廇18820");
         list.add(b2);
         datasLD.setValue(list);*/
@@ -85,6 +95,7 @@
     }
 
     public void openGridDriver(KeyCabinetBean selectBean){
+        doAction(2);
         OpenGridDriverParam param = new OpenGridDriverParam();
         param.setCabinetId(selectBean.getCabinetId());
         param.setGridId(selectBean.getId());
@@ -116,6 +127,38 @@
                 });
     }
 
+    /**
+     * 鍏抽棬
+     * @param gridDo
+     */
+    public void closeGrid(CabinetGridDo gridDo){
+        CloseGridParam param = new CloseGridParam();
+        LoginBean loginBean = MApplication.getLoginBean();
+        param.setCabinetId(MApplication.getConfigBean().getId());
+        param.setAuthType(loginBean.getAuthType());
+        param.setMemberId(loginBean.getMemberId());
+        param.setGridId(gridDo.getGridId());
+        param.setKeyStatus(!TextUtils.isEmpty(gridDo.getCurKeyCode())?1:2);
+        getRetrofitService(Apis.class).closeGrid(ParamsUtil.encodeRequestBody(param))
+                .compose(RxUtils.schedulersTransformer())
+                .subscribe(new SimpleObserver<BaseResponse>(rxJavaGcManager) {
+                    @Override
+                    public void onNext(@NonNull BaseResponse response) {
+
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+
+                    @Override
+                    public void onComplete() {
+
+                    }
+                });
+    }
+
     public MutableLiveData<List<KeyCabinetBean>> getDatasLD() {
         return datasLD;
     }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java
index 8055157..ef9eb5a 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java
@@ -1,22 +1,43 @@
 package com.doumee.keyCabinet.ui.keyCabinet;
 
 import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.lifecycle.Observer;
 
+import android.os.Build;
 import android.os.Bundle;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
+import android.view.KeyEvent;
 import android.view.View;
+import android.widget.TextView;
 import android.widget.Toast;
 
 import com.doumee.keyCabinet.R;
 import com.doumee.keyCabinet.base.MyBaseActivity;
-import com.doumee.keyCabinet.bean.CabinetDetailBean;
 import com.doumee.keyCabinet.bean.ManageKeyCabinetBean;
+import com.doumee.keyCabinet.dao.CabinetGridDo;
+import com.doumee.keyCabinet.dao.DaoManager;
 import com.doumee.keyCabinet.databinding.ManageCabinetActivityBinding;
+import com.doumee.keyCabinet.event.HttpEvent;
+import com.doumee.keyCabinet.event.ManageOpenGridResultEvent;
+import com.doumee.keyCabinet.event.OpenAllGridEvent;
+import com.doumee.keyCabinet.event.OpenGridListEvent;
+import com.doumee.keyCabinet.event.TimeClockEvent;
 import com.doumee.keyCabinet.ui.keyCabinet.adapter.ManageCabinetRcvAdapter;
+import com.doumee.keyCabinet.utils.i485.SportUtils;
 import com.doumee.lib_coremodel.bean.event.ActionEventData;
+import com.doumee.lib_coremodel.util.RecyclerHelp;
+import com.doumee.lib_coremodel.util.StringUtil;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 
 import dagger.hilt.android.AndroidEntryPoint;
@@ -26,18 +47,42 @@
     private ManageCabinetRcvAdapter adapter;
     //1寰呭叏寮�锛�2寰呮壒閲忓紑
     private int status;
+    private boolean isCanCZ = false;
 
     @Override
     public int getLayoutId() {
         return R.layout.manage_cabinet_activity;
     }
 
+    private HashMap<String,String> waitOpenMap = new HashMap<>();
+
     @Override
     public void initView(@Nullable Bundle savedInstanceState) {
         isAddCountTimer = false;
         normalConfig();
         getDB().setModel(getVM());
-
+        adapter = new ManageCabinetRcvAdapter(this, R.layout.manage_cabinet_rcv_item, new ManageCabinetRcvAdapter.OnItemClick() {
+            @Override
+            public void onItemClick(ManageKeyCabinetBean item) {
+                List<ManageKeyCabinetBean> datas = adapter.getListData();
+                isCanCZ = false;
+                for(ManageKeyCabinetBean d:datas){
+                    if(d.getIsSelected().get()){
+                        isCanCZ = true;
+                        break;
+                    }
+                }
+                if(isCanCZ){
+                    getDB().tvPlOpen.setBackgroundResource(R.drawable.shape_mb_bt_ok);
+                    getDB().tvBj.setBackgroundResource(R.drawable.shape_mb_bt_ok);
+                }else {
+                    getDB().tvPlOpen.setBackgroundResource(R.drawable.shape_mb_bt_faile);
+                    getDB().tvBj.setBackgroundResource(R.drawable.shape_mb_bt_faile);
+                }
+            }
+        });
+        RecyclerHelp.bindVG(this,getDB().rcvKm,3,30);
+        getDB().rcvKm.setAdapter(adapter);
     }
 
     @Override
@@ -45,27 +90,102 @@
         getVM().getDatasLD().observe(this, new Observer<List<ManageKeyCabinetBean>>() {
             @Override
             public void onChanged(List<ManageKeyCabinetBean> gridInfoBeans) {
-
+                if(gridInfoBeans.size()>0){
+                    adapter.refreshData(gridInfoBeans);
+                    getVM().emptyVisibility.set(View.GONE);
+                    //鏇存柊淇℃伅
+                    updateDao(gridInfoBeans);
+                }else {
+                    getVM().emptyVisibility.set(View.VISIBLE);
+                }
             }
         });
         getVM().getCabinetDetail();
     }
 
+    private void updateDao(List<ManageKeyCabinetBean> beans){
+        List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+        HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+        for(CabinetGridDo d:gridDos){
+            oldMap.put(d.getGridKey(),d);
+        }
+        List<CabinetGridDo> addList = new ArrayList<>();
+        List<CabinetGridDo> updateList = new ArrayList<>();
+        for(ManageKeyCabinetBean bean:beans){
+            String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode()))+SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+            if(oldMap.containsKey(key)){
+                //淇敼
+                CabinetGridDo gridDo = oldMap.get(key);
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                updateList.add(gridDo);
+            }else {
+                //鏂板
+                CabinetGridDo gridDo = new CabinetGridDo();
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setGridKey(key);
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                addList.add(gridDo);
+            }
+        }
+        if(addList.size()>0){
+            DaoManager.getCabinetGridDao().insert(addList);
+        }
+        if(updateList.size()>0){
+            CabinetGridDo[] upList = new CabinetGridDo[updateList.size()];
+            for(int i=0;i<updateList.size();i++){
+                upList[i] = updateList.get(i);
+            }
+            DaoManager.getCabinetGridDao().update(upList);
+        }
+    }
+
     private List<Integer> bjIds = new ArrayList<>();
     private boolean isGz = true;
+    private boolean isAllOpen = false;
     @Override
     protected void doRegister(int type, ActionEventData data) {
         switch (type){
             case 1:
-                //todo wmf 鏍¢獙鏌滃瓙鏄惁閮藉凡鍏抽棴
+                //鏍¢獙鏌滃瓙鏄惁閮藉凡鍏抽棴
+                if(checkOpen()){
+                    return;
+                }
                 finish();
                 break;
             case 2:
+            {
                 //鍏ㄥ紑
                 status = 1;
-                //todo 鍏ㄥ紑
+                //鎵归噺寮�闂紝鏍¢獙鏄惁鍙墦寮�
+                List<Integer> ids = new ArrayList<>();
+                List<ManageKeyCabinetBean> datas = adapter.getListData();
+                for (ManageKeyCabinetBean bean : datas) {
+                    ids.add(bean.getId());
+                }
+                if (ids.size() == 0) {
+                    Toast.makeText(mContext, "璇烽�夋嫨鏌滄牸", Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                getVM().batchOpenGridAdmin(ids,true);
+            }
                 break;
             case 3: {
+                if(!isCanCZ){
+                    return;
+                }
                 //鎵归噺寮�闂紝鏍¢獙鏄惁鍙墦寮�
                 List<Integer> ids = new ArrayList<>();
                 List<ManageKeyCabinetBean> datas = adapter.getListData();
@@ -78,14 +198,39 @@
                     Toast.makeText(mContext, "璇烽�夋嫨鏌滄牸", Toast.LENGTH_SHORT).show();
                     return;
                 }
-                getVM().batchOpenGridAdmin(ids);
+                getVM().batchOpenGridAdmin(ids,false);
                 }break;
-            case 8:
-                status = 2;
-                //todo 鎵归噺寮�
-                break;
+            case 8: {
+                //鍏ㄥ紑
+                isAllOpen = true;
+                List<ManageKeyCabinetBean> datas = adapter.getListData();
+                for (ManageKeyCabinetBean bean : datas) {
+                    String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode()))+
+                            SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+                    waitOpenMap.put(key,bean.getCode());
+                }
+                EventBus.getDefault().post(new OpenAllGridEvent());
+                }break;
+            case 10: {
+                //鎵归噺寮�
+                isAllOpen = false;
+                List<ManageKeyCabinetBean> datas = adapter.getListData();
+                List<String> keys = new ArrayList<>();
+                for (ManageKeyCabinetBean bean : datas) {
+                    if(bean.getIsSelected().get()) {
+                        String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode())) +
+                                SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+                        waitOpenMap.put(key, bean.getCode());
+                        keys.add(key);
+                    }
+                }
+                EventBus.getDefault().post(new OpenGridListEvent(keys));
+                }break;
             case 4: {
                 //鏍囪
+                if(!isCanCZ){
+                    return;
+                }
                 bjIds.clear();
                 isGz = true;
                 List<ManageKeyCabinetBean> datas = adapter.getListData();
@@ -130,8 +275,193 @@
                     getVM().markFault(bjIds);
                 }
                 break;
+            case 9: {
+                if(isShowOpenTip==true) {
+                    //娓呯┖寮�闂ㄦ彁閱�
+                    isShowOpenTip = false;
+                    getDB().clKmTip.setVisibility(View.GONE);
+                }else {
+                    getDB().clKmTip.setVisibility(View.GONE);
+                }
+                }break;
             default:
                 break;
         }
     }
+
+    //閫�鍑哄叧闂ㄦ彁閱�
+    private int tipDownCount = 10;
+    private boolean isShowTip;
+
+    //寮�闂ㄦ彁閱�
+    private int openTipDownCount = 60;
+    private boolean isShowOpenTip;
+    @Subscribe
+    public void TimeClockEvent(TimeClockEvent e){
+        if(isShowTip){
+            if(tipDownCount==0){
+                isShowTip = false;
+                getDB().clTip.setVisibility(View.GONE);
+                finish();
+            }else {
+                tipDownCount--;
+                getDB().tvDjs.setText(tipDownCount+"s");
+            }
+        }
+        if(isShowOpenTip){
+            if(openTipDownCount==0){
+                doRegister(9,null);
+            }else {
+                openTipDownCount--;
+                getDB().tvClKmClose.setText(openTipDownCount+"s 鑷姩鍏抽棴");
+            }
+        }
+    }
+
+
+    /**
+     * 鏍¢獙鏄惁鏈夋病鍏抽棬鐨�
+     * @return
+     */
+    private boolean checkOpen(){
+        List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().getOpenGrids();
+        if (gridDos.size() > 0) {
+            tipDownCount = 10;
+            isShowTip = true;
+            getDB().tvDjs.setText(tipDownCount + "s");
+            StringBuilder sb = new StringBuilder();
+            for(CabinetGridDo d:gridDos){
+                if (sb.length()>0) {
+                    sb.append("銆�");
+                }
+                String name = d.getCabinetName();
+                if (TextUtils.isEmpty(name)) {
+                    name = gridDos.get(0).getGridKey();
+                }
+                sb.append(name);
+            }
+            getDB().tvTip22.setText(getTipText(sb.toString()), TextView.BufferType.SPANNABLE);
+            getDB().clTip.setVisibility(View.VISIBLE);
+            return true;
+        }else {
+            isShowTip = false;
+            getDB().clTip.setVisibility(View.GONE);
+            return false;
+        }
+    }
+
+    private SpannableString getTipText(String name){
+        String text = "璇峰叧闂�"+name+"鏌滈棬";
+        SpannableString styledText = new SpannableString(text);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        styledText.setSpan(new TextAppearanceSpan(this, R.style.style_tip1),
+                3, 3+name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), name.length()+3, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return styledText;
+    }
+
+    private SpannableString getTipText2(String begin,String name,String end){
+        String text = begin+name+end;
+        SpannableString styledText = new SpannableString(text);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), 0, begin.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        styledText.setSpan(new TextAppearanceSpan(this, R.style.style_tip1),
+                begin.length(), begin.length()+name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), begin.length()+name.length(), text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return styledText;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if(keyCode == KeyEvent.KEYCODE_BACK){
+            if(checkOpen()){
+                return true;
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void ManageOpenGridResultEvent(ManageOpenGridResultEvent e){
+        if(!isFinishing()){
+            //鏍¢獙鏄惁宸插叏寮�
+            List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+            List<String> msgList = new ArrayList<>();
+            for(String key:waitOpenMap.keySet()){
+                msgList.add(waitOpenMap.get(key));
+            }
+            EventBus.getDefault().post(new HttpEvent("鎬诲叡瑕佹墦寮�鏁�:"+waitOpenMap.size()));
+            for(CabinetGridDo d:gridDos){
+                if(d.getIsOpen()==1) {
+                    EventBus.getDefault().post(new HttpEvent("鎵撳紑浜�:"+d.getGridKey()));
+                    waitOpenMap.remove(d.getGridKey());
+                }
+            }
+            if(waitOpenMap.size()==0){
+                EventBus.getDefault().post(new HttpEvent("鍏ㄩ儴鎵撳紑浜�:"+waitOpenMap.size()));
+                //鎵撳紑鎴愬姛
+                if(isAllOpen){
+                    getDB().tvClKm2.setText("涓�閿叏寮�鎴愬姛锛岄杩樺悗璇峰叧闂�");
+                }else {
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                        msgList.sort((a,b)->{
+                            return a.compareTo(b);
+                        });
+                    }
+                    StringBuilder sb = new StringBuilder();
+                    for(String key:msgList){
+                        if(sb.length()>0){
+                            sb.append("銆�");
+                        }
+                        sb.append(key);
+                    }
+                    getDB().tvClKm2.setText(getTipText2("閽ュ寵鏌�",sb.toString(),"寮�闂ㄦ垚鍔燂紝棰嗚繕鍚庤鍏抽棬"), TextView.BufferType.SPANNABLE);
+                }
+                getDB().imgClKm1.setImageResource(R.mipmap.ic_success);
+                getDB().tvClKm1.setText("鏌滈棬鎵撳紑鎴愬姛");
+            }else {
+                //閮ㄥ垎寮�闂ㄥけ璐�
+                EventBus.getDefault().post(new HttpEvent("閮ㄥ垎鎵撳紑浜�:"+waitOpenMap.size()));
+                msgList.clear();
+                for (String key : waitOpenMap.keySet()) {
+                    msgList.add(waitOpenMap.get(key));
+                }
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                    msgList.sort((a, b) -> {
+                        return a.compareTo(b);
+                    });
+                }
+                StringBuilder sb = new StringBuilder();
+                for (String key : msgList) {
+                    if (sb.length() > 0) {
+                        sb.append("銆�");
+                    }
+                    sb.append(key);
+                }
+                getDB().imgClKm1.setImageResource(R.mipmap.ic_jjfail);
+                getDB().tvClKm1.setText("鏌滈棬鎵撳紑澶辫触");
+                getDB().tvClKm2.setText(getTipText2("閽ュ寵鏌�",sb.toString(),"寮�闂ㄥけ璐�"), TextView.BufferType.SPANNABLE);
+            }
+            getDB().tvClKmClose.setText("60s 鑷姩鍏抽棴");
+            getDB().tvClKmClose.setTextColor(0xff279baa);
+            getDB().tvClKmClose.setBackgroundResource(R.drawable.shape_mb_bg01);
+            openTipDownCount = 60;
+            isShowOpenTip = true;
+            getDB().clKmTip.setVisibility(View.VISIBLE);
+
+            if(!isAllOpen) {
+                //娓呴櫎宸查�夋嫨鐨�
+                List<ManageKeyCabinetBean> datas = adapter.getListData();
+                for (ManageKeyCabinetBean bean : datas) {
+                    if (bean.getIsSelected().get()) {
+                        String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode())) +
+                                SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+                        if (!waitOpenMap.containsKey(key)) {
+                            bean.getIsSelected().set(false);
+                        }
+                    }
+                }
+            }
+            waitOpenMap.clear();
+        }
+    }
 }
\ No newline at end of file
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java
index e7c1ef5..c99ca2e 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java
@@ -40,6 +40,66 @@
     }
 
     public void getCabinetDetail(){
+        CabinetDetailBean bean = new CabinetDetailBean();
+        bean.setGridNum(24);
+        bean.setOnlineKeyNum(1);
+        bean.setOutKeyNum(2);
+        bean.setErrGridNum(3);
+        bean.setServiceKeyNum(4);
+        bean.setUnBindGridNum(5);
+        dataOb.set(bean);
+        List<ManageKeyCabinetBean> datas = new ArrayList<>();
+        for(int i=1;i<=16;i++){
+            ManageKeyCabinetBean b = new ManageKeyCabinetBean();
+            b.setBindStatus(0);
+            b.setBoardCode("1");
+            b.setCarCode("杞︾墝"+i);
+            b.setChannelCode(i+"");
+            b.setCode("A鏌�"+i);
+            b.setId(i);
+            b.setKeyStatus(0);
+            b.setKeyCode(null);
+            b.setStatus(0);
+            b.setWorkingStatus(0);
+            datas.add(b);
+        }
+        for(int i=17;i<=24;i++){
+            ManageKeyCabinetBean b = new ManageKeyCabinetBean();
+            b.setBindStatus(0);
+            b.setBoardCode("2");
+            b.setCarCode("杞︾墝"+i);
+            b.setChannelCode((i-16)+"");
+            b.setCode("B鏌�"+i);
+            b.setId(i);
+            b.setKeyStatus(0);
+            b.setKeyCode(null);
+            b.setStatus(0);
+            b.setWorkingStatus(0);
+            datas.add(b);
+        }
+        ManageKeyCabinetBean b1 = datas.get(0);
+        b1.setKeyCode("C97B092F");
+        b1.setKeyStatus(1);
+        b1.setBindStatus(1);
+
+        ManageKeyCabinetBean b2 = datas.get(1);
+        b2.setKeyStatus(2);
+        b2.setBindStatus(1);
+
+        ManageKeyCabinetBean b3 = datas.get(2);
+        b3.setKeyStatus(3);
+        b3.setBindStatus(1);
+
+        ManageKeyCabinetBean b4 = datas.get(3);
+        b4.setKeyStatus(1);
+        b4.setWorkingStatus(1);
+        b4.setBindStatus(1);
+
+        datasLD.setValue(datas);
+
+        if(true){
+            return;
+        }
         showLoading(true);
         getRetrofitService(Apis.class).getCabinetDetail(MApplication.getLoginBean().getToken(),
                         MApplication.getConfigBean().getId())
@@ -75,7 +135,15 @@
                 });
     }
 
-    public void batchOpenGridAdmin(List<Integer> gridIdList){
+    public void batchOpenGridAdmin(List<Integer> gridIdList,boolean isAll){
+        if(isAll) {
+            doAction(8);
+        }else {
+            doAction(10);
+        }
+        if(true){
+            return;
+        }
         showLoading(true);
         BatchOpenGridAdminParam param = new BatchOpenGridAdminParam();
         param.setCabinetId(MApplication.getConfigBean().getId());
@@ -87,7 +155,11 @@
                     @Override
                     public void onNext(@NonNull BaseResponse response) {
                         if(200==response.getCode()){
-                            doAction(8);
+                            if(isAll) {
+                                doAction(8);
+                            }else {
+                                doAction(10);
+                            }
                         }else {
                             toast(response.getMessage());
                         }
@@ -106,6 +178,7 @@
     }
 
     public void cancelFault(List<Integer> gridIdList){
+
         showLoading(true);
         CancelFaultParam param = new CancelFaultParam();
         param.setCabinetId(MApplication.getConfigBean().getId());
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java
index 608e910..288c1f4 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java
@@ -5,13 +5,20 @@
 
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.text.method.HideReturnsTransformationMethod;
+import android.text.method.PasswordTransformationMethod;
 import android.view.View;
 import android.widget.Toast;
 
+import com.doumee.keyCabinet.BuildConfig;
 import com.doumee.keyCabinet.R;
 import com.doumee.keyCabinet.base.MyBaseActivity;
 import com.doumee.keyCabinet.databinding.ManageLoginActivityBinding;
+import com.doumee.keyCabinet.event.TimeClockEvent;
+import com.doumee.keyCabinet.utils.LMobileInfo;
 import com.doumee.lib_coremodel.bean.event.ActionEventData;
+
+import org.greenrobot.eventbus.Subscribe;
 
 import dagger.hilt.android.AndroidEntryPoint;
 
@@ -33,6 +40,9 @@
 
     @Override
     public void initData(@Nullable Bundle savedInstanceState) {
+        getDB().tvNo.setText("NO锛�"+ LMobileInfo.getDeviceUniqueId());
+        getDB().tvV.setText("V"+ BuildConfig.VERSION_NAME);
+
 
     }
 
@@ -41,7 +51,8 @@
         switch (type){
             case 1:
                 //鏄剧ず瀵嗙爜
-
+                isShowPw = !isShowPw;
+                updatePassword();
                 break;
             case 2:
                 if(TextUtils.isEmpty(getDB().etName.getText().toString())){
@@ -61,10 +72,44 @@
                 break;
             case 4:
                 getDB().clProgress.setVisibility(View.GONE);
+                tipDownCount = 60;
+                isShowTip = true;
                 getDB().clTip.setVisibility(View.VISIBLE);
+                break;
+            case 5:
+                startActivity(ManageCabinetActivity.class);
+                finish();
                 break;
             default:
                 break;
         }
     }
+
+    private boolean isShowPw = false;
+    private void updatePassword() {
+        if(isShowPw){
+            getDB().img3.setImageResource(R.mipmap.login_eyeopen);
+            // 鏄剧ず瀵嗙爜
+            getDB().etPw.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
+        }else {
+            getDB().img3.setImageResource(R.mipmap.login_eyeclose);
+            // 闅愯棌瀵嗙爜
+            getDB().etPw.setTransformationMethod(PasswordTransformationMethod.getInstance());
+        }
+    }
+
+    private int tipDownCount = 60;
+    private boolean isShowTip;
+    @Subscribe
+    public void TimeClockEvent(TimeClockEvent e){
+        if(isShowTip){
+            if(tipDownCount==0){
+                isShowTip = false;
+                finish();
+            }else {
+                tipDownCount--;
+                getDB().tvClKmClose.setText(tipDownCount+"s 鑷姩鍏抽棴");
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java
index 84d3a19..89e58c7 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java
@@ -29,6 +29,10 @@
     }
 
     public void loginCabinet(String userName,String pw){
+        if(true){
+            doAction(5);
+            return;
+        }
         LoginCabinetParam param = new LoginCabinetParam();
         param.setUsername(userName);
         param.setPassword(pw);
@@ -39,8 +43,9 @@
                     @Override
                     public void onNext(@NonNull BaseResponse<String> response) {
                         if(200==response.getCode()){
+                            MApplication.setLoginBean(null);
                             MApplication.getLoginBean().setToken(response.getData());
-                            startActivity(ManageCabinetActivity.class);
+                            doAction(5);
                         }else {
                             doAction(4);
                         }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java
index 7acc26b..eed6774 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java
@@ -12,9 +12,13 @@
 import com.doumee.lib_coremodel.view.recyclerview.adapter.BindingHolder;
 
 public class ManageCabinetRcvAdapter extends BindingAdapter<ManageKeyCabinetBean, ManageCabinetRcvItemBinding> {
-
-    public ManageCabinetRcvAdapter(Context context, int layoutId) {
+    public static interface OnItemClick{
+        void onItemClick(ManageKeyCabinetBean item);
+    }
+    private OnItemClick onItemClick;
+    public ManageCabinetRcvAdapter(Context context, int layoutId,OnItemClick call) {
         super(context, layoutId);
+        onItemClick = call;
     }
 
     @Override
@@ -53,6 +57,9 @@
             @Override
             public void onClick(View v) {
                 item.getIsSelected().set(!item.getIsSelected().get());
+                if(onItemClick!=null){
+                    onItemClick.onItemClick(item);
+                }
             }
         });
     }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java
index fcac3d4..c248eb2 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java
@@ -8,8 +8,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.hardware.Camera;
-import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -17,7 +15,6 @@
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.TextAppearanceSpan;
-import android.util.DisplayMetrics;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -43,20 +40,29 @@
 import com.bumptech.glide.request.transition.Transition;
 import com.doumee.keyCabinet.BuildConfig;
 import com.doumee.keyCabinet.base.BannerPicResponsePara;
+import com.doumee.keyCabinet.bean.CabinetConfigDataBean;
+import com.doumee.keyCabinet.bean.DevConfigBean;
 import com.doumee.keyCabinet.bean.FaceUserBean;
 import com.doumee.keyCabinet.bean.LoginBean;
+import com.doumee.keyCabinet.dao.CabinetGridDo;
+import com.doumee.keyCabinet.dao.DaoManager;
 import com.doumee.keyCabinet.databinding.MainActivityBinding;
+import com.doumee.keyCabinet.event.CLGridEvent;
+import com.doumee.keyCabinet.event.CLKeyEvent;
+import com.doumee.keyCabinet.event.CloseGridOneResultEvent;
 import com.doumee.keyCabinet.event.GetFacesEvent;
+import com.doumee.keyCabinet.event.GetKeyStatusEvent;
 import com.doumee.keyCabinet.event.HeartEvent;
-import com.doumee.keyCabinet.event.KeyDoorEvent;
+import com.doumee.keyCabinet.event.HttpEvent;
 import com.doumee.keyCabinet.event.KeyResultEvent;
-import com.doumee.keyCabinet.event.KeyStatusListener;
+import com.doumee.keyCabinet.event.ManageOpenGridResultEvent;
+import com.doumee.keyCabinet.event.OpenAllGridEvent;
 import com.doumee.keyCabinet.event.OpenGridEvent;
+import com.doumee.keyCabinet.event.OpenGridListEvent;
+import com.doumee.keyCabinet.event.OpenGridOneResultEvent;
 import com.doumee.keyCabinet.event.ReLoginEvent;
 import com.doumee.keyCabinet.event.TimeClockEvent;
 import com.doumee.keyCabinet.ui.face.ActivationActivity;
-import com.doumee.keyCabinet.ui.face.FaceActivity;
-import com.doumee.keyCabinet.ui.guide.GuideActivity;
 import com.doumee.keyCabinet.ui.keyCabinet.ChangeUrlActivity;
 import com.doumee.keyCabinet.ui.keyCabinet.KeyCabinetActivity;
 import com.doumee.keyCabinet.ui.keyCabinet.ManageLoginActivity;
@@ -87,7 +93,6 @@
 import com.doumee.keyCabinet.MApplication;
 import com.doumee.keyCabinet.R;
 import com.doumee.keyCabinet.base.MyBaseActivity;
-import com.doumee.keyCabinet.bean.MemberBean;
 import com.doumee.keyCabinet.utils.AdListResponseParam;
 import com.doumee.lib_coremodel.http.utils.GsonTools;
 import com.doumee.lib_coremodel.util.SpUtil;
@@ -99,16 +104,15 @@
 import com.example.datalibrary.model.User;
 import com.example.datalibrary.view.PreviewTexture;
 import com.yanzhenjie.permission.runtime.Permission;
+
 import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Logger;
 import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Random;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.Executors;
@@ -159,7 +163,7 @@
                     }
                     getVM().upBraceletLog();*/
                     case 2:
-                        getVM().resetReq();
+
                         break;
                 }
             }
@@ -285,14 +289,30 @@
             }
         });
         upErrInfo();
+        getVM().devLogin();
         getVM().devHeart();
-        BraceletLogUtils.saveLog("app鎵撳紑");
+        getVM().getConfidLD().observe(this, new Observer<DevConfigBean>() {
+            @Override
+            public void onChanged(DevConfigBean devConfigBean) {
+                if(devConfigBean!=null){
+                    if(devConfigBean.getBannerList()!=null) {
+                        setBanner(devConfigBean.getBannerList());
+                    }
+                    setJiuConfig();
+                }
+            }
+        });
     }
 
-
+    private void setJiuConfig(){
+        if(MApplication.getConfigBean().getCabinetConfigDataVO()!=null&&
+            jiuPort!=null){
+            setJiuConfig(0);
+        }
+    }
 
     boolean isOne;
-    private void setBanner(List<BannerPicResponsePara> bannerList){
+    private void setBanner(List<String> bannerList){
         getDB().banner.setPages(new CBViewHolderCreator<BannerViewImageHolder>() {
             @Override
             public BannerViewImageHolder createHolder() {
@@ -333,36 +353,97 @@
     protected void doRegister(int type, ActionEventData data) {
         switch (type){
             case 2:
-            case 3:
-                /*tipDownCount = 10;
-                isShowTip = true;
-                getDB().tvDjs.setText(tipDownCount+"s");
-                getDB().tvTip21.setText(getTipText("AC101"), TextView.BufferType.SPANNABLE);
-                getDB().clTip.setVisibility(View.VISIBLE);*/
+            case 3: {
                 //鏍¢獙鏄惁鐧诲綍
-                if(MApplication.getConfigBean().getId()==null){
+                /*if(MApplication.getConfigBean().getId()==null){
                     Toast.makeText(mContext, "璁惧鏈坊鍔狅紝鏃犳硶鎿嶄綔", Toast.LENGTH_SHORT).show();
                     getVM().devLogin();
                     return;
                 }
                 MApplication.getLoginBean().setFlag(type==2?0:1);
-                startActivity(FaceActivity.class);
+                startActivity(FaceActivity.class);*/
+                /*if(type==2){
+                    send485(1,"A002010000000003");
+                }else {
+                    send485(1,"A001010000000002");
+                }*/
+                //send485(1,"A001010000000002");
+                //send485(1,"A002010000000003");
                 //startActivity(KeyCabinetActivity.class,b);
+                checkGridStatus(0);
+                List<CabinetGridDo> gridDos = getVM().getOpenGrids();
+                if (gridDos.size() > 0) {
+                    tipDownCount = 10;
+                    isShowTip = true;
+                    getDB().tvDjs.setText(tipDownCount + "s");
+                    StringBuilder sb = new StringBuilder();
+                    for(CabinetGridDo d:gridDos){
+                        if (sb.length()>0) {
+                            sb.append("銆�");
+                        }
+                        String name = d.getCabinetName();
+                        if (TextUtils.isEmpty(name)) {
+                            name = gridDos.get(0).getGridKey();
+                        }
+                        sb.append(name);
+                    }
+
+                    getDB().tvTip22.setText(getTipText(sb.toString()), TextView.BufferType.SPANNABLE);
+                    getDB().clTip.setVisibility(View.VISIBLE);
+                    return;
+                }
+                MApplication.setLoginBean(null);
+                MApplication.getLoginBean().setFlag(type == 2 ? 0 : 1);
+                if(type==3){
+                    startActivity(ManageLoginActivity.class);
+                    return;
+                }
+                startActivity(KeyCabinetActivity.class);
+                }
                 break;
             case 4:
                 isShowTip = false;
                 getDB().clTip.setVisibility(View.GONE);
+                break;
+            case 5: {
+                List<CabinetGridDo> gridDos = getVM().getOpenGrids();
+                if (gridDos.size() > 0) {
+                    tipDownCount = 10;
+                    isShowTip = true;
+                    getDB().tvDjs.setText(tipDownCount + "s");
+                    StringBuilder sb = new StringBuilder();
+                    for(CabinetGridDo d:gridDos){
+                        if (sb.length()>0) {
+                            sb.append("銆�");
+                        }
+                        String name = d.getCabinetName();
+                        if (TextUtils.isEmpty(name)) {
+                            name = gridDos.get(0).getGridKey();
+                        }
+                        sb.append(name);
+                    }
+                    getDB().tvTip22.setText(getTipText(sb.toString()), TextView.BufferType.SPANNABLE);
+                    getDB().clTip.setVisibility(View.VISIBLE);
+                }else {
+                    isShowTip = false;
+                    getDB().clTip.setVisibility(View.GONE);
+                }
+                }
+                break;
+            case 55:
+                getVM().infoObs.set("");
                 break;
             default:
                 break;
         }
     }
 
+    private boolean isShowing = false;
     @Override
     protected void onResume() {
         super.onResume();
+        isShowing = true;
         showTime = System.currentTimeMillis();
-        MApplication.setLoginBean(new LoginBean());
         if(!isFaceOk) {
             //initLicense();
         }
@@ -370,11 +451,20 @@
             checkUpdate();
         }
         triggerGarbageCollection();
-        getVM().resetReq();
+
         if(!isOne) {
             getDB().banner.startTurning(3000);
         }else {
             getDB().banner.stopTurning();
+        }
+        unCloseGrid();
+    }
+
+    private void unCloseGrid(){
+        //鏈叧闂紝璋冪敤鎺ュ彛
+        List<CabinetGridDo> gridDos = getVM().getOpenGrids();
+        if(gridDos.size()>0){
+            getVM().timeOutUnCloseAlarm(gridDos.get(0));
         }
     }
 
@@ -397,11 +487,15 @@
         faceHandler = null;
         portHandler.removeCallbacksAndMessages(null);
         portHandler = null;
+        closePort(gridPort);
+        closePort(keyPort);
+        closePort(jiuPort);
+        closePort(chosePort);
     }
 
     private void restartApp(){
         // 鍒涘缓涓�涓柊鐨勫惎鍔ㄦ剰鍥�
-        Intent intent = new Intent(mContext, GuideActivity.class);
+        Intent intent = new Intent(mContext, MainActivity.class);
         // 璁剧疆FLAG_ACTIVITY_CLEAR_TASK鏍囧織浣�
         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
         // 浣跨敤PendingIntent鍖呰鍚姩鎰忓浘
@@ -425,14 +519,6 @@
             }else {
                 isNeedUpdateFace = true;
             }
-        }
-    }
-
-    @Subscribe
-    public void ReLoginEvent(ReLoginEvent event){
-        if(!isFinishing()){
-            handler.sendEmptyMessageDelayed(2,20000);
-            getVM().devLogin();
         }
     }
 
@@ -626,6 +712,7 @@
     protected void onPause() {
         super.onPause();
         showTime = null;
+        isShowing = false;
     }
 
     private int finishCount;
@@ -1005,36 +1092,49 @@
      * 鐩戝惉寮�闂�
      * @param e
      */
-    @Subscribe
+    @Subscribe(threadMode=ThreadMode.MAIN)
     public void OpenGridEvent(OpenGridEvent e){
         if(!isFinishing()){
-            EventBus.getDefault().post(new KeyDoorEvent(MApplication.nextBoolean()?"0":"1"));
+            //寮�鍚煖闂�
+            String code = "8A"+SportUtils.intToHex(Integer.parseInt(e.getBoardCode()))
+                    +SportUtils.intToHex(Integer.parseInt(e.getChannelCode()))+"11";
+            code += SportUtils.getBCC(code);
+            send485(0,code);
         }
     }
 
-    /**
-     * 鐩戝惉閽ュ寵
-     * @param e
-     */
-    @Subscribe
-    public void KeyStatusListener(KeyStatusListener e){
+    //鏌滈棬鍏ㄥ紑
+    @Subscribe(threadMode=ThreadMode.MAIN)
+    public void OpenAllGridEvent(OpenAllGridEvent e){
         if(!isFinishing()){
-            if(e.getStatus()==0){
-                //寮�濮�
-                Random random = new Random();
-                EventBus.getDefault().post(new KeyResultEvent(random.nextBoolean()?"0":"1"));
-            }else {
-                //缁撴潫
+            //寮�鍚煖闂�
+            sendPortHandlerMsg(1,"8A01FF1165",0);
+            sendPortHandlerMsg(1,"8A02FF1166",8000);
+        }
+    }
+
+    //鏌滈棬鎵归噺寮�
+    @Subscribe(threadMode=ThreadMode.MAIN)
+    public void OpenGridListEvent(OpenGridListEvent e){
+        if(!isFinishing()){
+            //寮�鍚煖闂�
+            long time = 0;
+            for(String key:e.getKeys()){
+                String code = "8A"+key+"11";
+                code += SportUtils.getBCC(code);
+                sendPortHandlerMsg(1,code,time);
+                time+=400;
             }
         }
     }
 
     private SpannableString getTipText(String name){
-        String text = name+"鏌滈棬鏈叧闂�";
+        String text = "璇峰叧闂�"+name+"鏌滈棬";
         SpannableString styledText = new SpannableString(text);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         styledText.setSpan(new TextAppearanceSpan(this, R.style.style_tip1),
-                0, name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), name.length()+1, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                3, 3+name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip2), name.length()+3, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         return styledText;
     }
 
@@ -1044,6 +1144,7 @@
         getVM().devHeart();
     }
 
+
     @Subscribe
     public void HeartEvent(HeartEvent e){
         if(!isFinishing()){
@@ -1051,136 +1152,708 @@
         }
     }
 
+
+    @Subscribe
+    public void CloseGridOneResultEvent(CloseGridOneResultEvent e){
+        if(!isFinishing()&&isShowing){
+            //鍦ㄩ椤碉紝鏍¢獙鍏抽棬鐨勯挜鍖欐槸鍚﹀尮閰�
+            if (e.getIsOpen() == 0) {
+                //鍏抽棬鎴愬姛
+                //鏌ヨ閽ュ寵鍙�
+                CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(e.getKey());
+                if (gridDo != null) {
+                    getVM().addInfo("姣旇緝閽ュ寵锛氬綋鍓嶏細"+gridDo.getCurKeyCode()+", 鍏宠仈閽ュ寵锛�"+gridDo.getKeyCode());
+                    if(!TextUtils.isEmpty(gridDo.getCurKeyCode())&&
+                            !TextUtils.isEmpty(gridDo.getKeyCode())&&
+                            !gridDo.getCurKeyCode().equals(gridDo.getKeyCode())){
+                        //閽ュ寵涓嶄竴鏍凤紝寮�闂�
+                        Toast.makeText(mContext, "閽ュ寵瀛樻斁浣嶇疆閿欒", Toast.LENGTH_SHORT).show();
+                        EventBus.getDefault().post(new OpenGridEvent(Integer.parseInt(e.getKey().substring(2,4), 16)+"",
+                                Integer.parseInt(e.getKey().substring(0,2), 16)+""));
+                    }else {
+                        //todo 鍏抽棬鎴愬姛
+                        if(isShowTip){
+                            doRegister(5,null);
+                        }
+                        if(isShowing){
+                            //鍦ㄩ椤靛叧闂ㄦ垚鍔燂紝闇�璋冪敤鍏抽棬鏂规硶
+                            getVM().closeGrid(gridDo);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private SerialPortModel gridPort;
     private SerialPortReadObserver gridReadObserver = new SerialPortReadObserver() {
         @Override
         public void onResult(String result) {
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if(result==null){
 
+                    }else {
+                        getVM().addInfo("鍙戦�佹寚浠ゅけ璐ワ細");
+                    }
+                }
+            });
         }
 
         @Override
         public void onResultBytes(byte[] bytes) {
-            if(gridPort!=null && !gridPort.isOk()){
-                gridPort.setOk(true);
+            if(bytes.length==0){
+                return;
             }
+            runOnUiThread(() -> {
+                getVM().addInfo("鑾峰彇鍒伴棬鏁版嵁:"+StringUtil.DateToStrSS(new Date())+"==>"+ SportUtils.bytesToHexSimple(bytes));
+            });
+            EventBus.getDefault().post(new CLGridEvent(SportUtils.bytesToHexSimple(bytes)));
         }
     };
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void HttpEvent(HttpEvent e){
+        if(!isFinishing()){
+            getVM().addInfo(e.getMsg());
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void CLGridEvent(CLGridEvent e){
+        if(!isFinishing()){
+            String data = e.getData();
+            data = data.toUpperCase();
+            data = data.replaceAll("\\s+", "");
+            if(data.startsWith("8A")){
+                //寮�閿佸弽棣�
+                String bh = data.substring(2,4);
+                if(data.length()==10){
+                    //鍗曚釜
+                    String tdh = data.substring(4,6);
+                    String open = data.substring(6,8);
+                    /*runOnUiThread(() -> {
+                        getVM().addInfo("鑾峰彇鍒伴棬鏁版嵁:" + "鐗堝彿锛�"+bh+",閿佸彿锛�"+tdh+",鏄惁寮�闂�--"+("00".equals(open)?"鏄�":"鍚�"));
+                    });*/
+                    String key = bh+tdh;
+                    CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                    if(gridDo==null){
+                        //鏂板
+                        gridDo = new CabinetGridDo();
+                        gridDo.setIsOpen("00".equals(open)?1:0);
+                        gridDo.setGridKey(key);
+                        gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                        DaoManager.getCabinetGridDao().insert(gridDo);
+                    }else {
+                        gridDo.setIsOpen("00".equals(open)?1:0);
+                        gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                        DaoManager.getCabinetGridDao().update(gridDo);
+                    }
+                    //寮�闂ㄨ繑鍥�
+                    EventBus.getDefault().post(new OpenGridOneResultEvent(key,gridDo.getIsOpen()));
+                    if(!portHandler.hasMessages(1)){
+                        EventBus.getDefault().post(new ManageOpenGridResultEvent());
+                    }
+                }else if(data.length()==16){
+                    //鎵归噺
+                    //8A 02 00 00 00 00 11 99
+                    String dm = data.substring(4,12);
+                    dm = SportUtils.hexToBinary(dm);
+                    StringBuilder sb = new StringBuilder(dm);
+                    dm = sb.reverse().toString();
+                    List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+                    HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+                    for(CabinetGridDo d:gridDos){
+                        oldMap.put(d.getGridKey(),d);
+                    }
+                    List<CabinetGridDo> addList = new ArrayList<>();
+                    List<CabinetGridDo> updateList = new ArrayList<>();
+                    String finalDm = dm;
+                    /*runOnUiThread(() -> {
+                        getVM().addInfo("鎵归噺鏌ヨ杩斿洖锛�" +bh+","+ finalDm+",鎬绘暟鎹細"+oldMap.size());
+                    });*/
+                    try {
+                        for(int i=1;i<=dm.length();i++){
+                            String key = bh+SportUtils.intToHex(i);
+                            if(oldMap.containsKey(key)){
+                                CabinetGridDo gridDo = oldMap.get(key);
+                                gridDo.setIsOpen("1".equals(dm.substring(i-1,i))?0:1);
+                                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                                updateList.add(gridDo);
+                            }/*else {
+                                getVM().addInfo("鏂板key锛�" +key);
+                                CabinetGridDo gridDo = new CabinetGridDo();
+                                gridDo.setGridKey(key);
+                                gridDo.setIsOpen("1".equals(dm.substring(i-1,i))?0:1);
+                                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                                addList.add(gridDo);
+                            }*/
+                        }
+                        runOnUiThread(() -> {
+                            getVM().addInfo("鎵归噺寮�闂ㄦ洿鏂板簱鏁版嵁:鐗堝彿锛�" +bh+","+ addList.size()+","+updateList.size());
+                        });
+                        getVM().insertGrids(addList);
+                        getVM().updateGrids(updateList);
+                        if(!portHandler.hasMessages(1)){
+                            EventBus.getDefault().post(new ManageOpenGridResultEvent());
+                        }
+                    }catch (Exception exception){
+                        runOnUiThread(() -> {
+                            getVM().addInfo("鎵归噺寮�闂ㄦ姤閿欙細" +exception.getMessage());
+                        });
+                    }
+                }
+            }else if(data.startsWith("81")){
+                //涓诲姩鍏抽棬 81 01 01 11 90
+                String bh = data.substring(2,4);
+                String tdh = data.substring(4,6);
+                String open = data.substring(6,8);
+                String key = bh+tdh;
+                CabinetGridDo gridDo = DaoManager.getCabinetGridDao().getGridByKey(key);
+                if(gridDo==null){
+                    //鏂板
+                    gridDo = new CabinetGridDo();
+                    gridDo.setIsOpen("00".equals(open)?1:0);
+                    gridDo.setGridKey(key);
+                    gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                    DaoManager.getCabinetGridDao().insert(gridDo);
+                }else {
+                    gridDo.setIsOpen("00".equals(open)?1:0);
+                    gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                    DaoManager.getCabinetGridDao().update(gridDo);
+                }
+                //鍏抽棬杩斿洖
+                EventBus.getDefault().post(new CloseGridOneResultEvent(key,gridDo.getIsOpen()));
+                if(isShowing&&isShowTip){
+                    //淇敼鏄剧ず鎻愰啋
+                    doRegister(5,null);
+                }
+            }else if(data.startsWith("80")){
+                //鏌ヨ鎵�鏈夐棬鐘舵��
+                //80 01 00 00 FF FF 33 B2
+                //80 02 00 00 00 F7 33 46
+                if(data.length()>=14){
+                    String bh = data.substring(2,4);
+                    String dm = data.substring(4,12);
+                    dm = dm.replaceAll("0","");
+                    dm = SportUtils.hexToBinary(dm);
+                    StringBuilder sb = new StringBuilder(dm);
+                    dm = sb.reverse().toString();
+                    List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+                    HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+                    for(CabinetGridDo d:gridDos){
+                        oldMap.put(d.getGridKey(),d);
+                    }
+                    List<CabinetGridDo> addList = new ArrayList<>();
+                    List<CabinetGridDo> updateList = new ArrayList<>();
+                    String finalDm = dm;
+                    runOnUiThread(() -> {
+                        getVM().addInfo("鎵归噺鏌ヨ杩斿洖锛�" +bh+","+ finalDm+",鎬绘暟鎹細"+oldMap.size());
+                    });
+                    try {
+                        for(int i=1;i<=dm.length();i++){
+                            String key = bh+SportUtils.intToHex(i);
+                            /*String finalDm1 = dm;
+                            int finalI = i;
+                            runOnUiThread(() -> {
+                                getVM().addInfo("key锛�" +key+","+("1".equals(finalDm1.substring(finalI -1, finalI))?"鍏�":"寮�"));
+                            });*/
+                            //System.out.println("===>"+key+","+("1".equals(dm.substring(i-1,i))?"鍏�":"寮�"));
+                            if(oldMap.containsKey(key)){
+                                CabinetGridDo gridDo = oldMap.get(key);
+                                gridDo.setIsOpen("1".equals(dm.substring(i-1,i))?0:1);
+                                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                                updateList.add(gridDo);
+                            }else {
+                                CabinetGridDo gridDo = new CabinetGridDo();
+                                gridDo.setGridKey(key);
+                                gridDo.setIsOpen("1".equals(dm.substring(i-1,i))?0:1);
+                                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                                addList.add(gridDo);
+                            }
+                        }
+                        runOnUiThread(() -> {
+                            getVM().addInfo("鏇存柊搴撴暟鎹�:鐗堝彿锛�" +bh+","+ addList.size()+","+updateList.size());
+                        });
+                        getVM().insertGrids(addList);
+                        getVM().updateGrids(updateList);
+                    }catch (Exception exception){
+                        runOnUiThread(() -> {
+                            getVM().addInfo("鎶ラ敊锛�" +exception.getMessage());
+                        });
+                    }
+
+                }
+            }
+        }
+    }
+
     private SerialPortModel keyPort;
+    //涓婁竴娆℃暟鎹�
+    private String keyPreviousData;
     private SerialPortReadObserver keyReadObserver = new SerialPortReadObserver() {
         @Override
         public void onResult(String result) {
+            if(result==null){
 
+            }else {
+                getVM().addInfo("鍙戦�佹寚浠ゅけ璐ワ細");
+            }
         }
 
         @Override
         public void onResultBytes(byte[] bytes) {
-            if(keyPort!=null && !keyPort.isOk()){
-                keyPort.setOk(true);
+            if(bytes.length==0){
+                return;
             }
+            EventBus.getDefault().post(new CLKeyEvent(SportUtils.bytesToHexSimple(bytes)));
         }
     };
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void CLKeyEvent(CLKeyEvent e){
+        if(!isFinishing()){
+            //鏍¢獙鐜板湪鐨勬暟鎹槸鍚︽槸鍏ㄦ暟鎹�
+            String data1 = e.getData();
+            data1 = data1.toUpperCase();
+            String data = data1.replaceAll("\\s+", "");
+            if(data.startsWith("CC01")){
+                keyPreviousData = data;
+            }else if(data.startsWith("CC02")){
+                runOnUiThread(() -> {
+                    getVM().addInfo("鑾峰彇鍒伴挜鍖欐暟鎹�:" + data);
+                    jxKey(data);
+                });
+                keyPreviousData = null;
+            }else {
+                if(!TextUtils.isEmpty(keyPreviousData)){
+                    String data2 = keyPreviousData+data;
+                    runOnUiThread(() -> {
+                        getVM().addInfo("鑾峰彇鍒伴挜鍖欐暟鎹�:" + data2);
+                        jxKey(data2);
+                    });
+                    keyPreviousData = null;
+                }
+            }
+        }
+    }
+
+    @Subscribe
+    public void GetKeyStatusEvent(GetKeyStatusEvent e){
+        if(!isFinishing()){
+            checkKeyStatus(0);
+        }
+    }
+    //瑙f瀽閽ュ寵鏁版嵁
+    private void jxKey(String data){
+        List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+        HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+        for(CabinetGridDo d:gridDos){
+            oldMap.put(d.getGridKey(),d);
+        }
+        List<CabinetGridDo> addList = new ArrayList<>();
+        List<CabinetGridDo> updateList = new ArrayList<>();
+        //浜屽彿鐗�
+        int bh = 2;
+        if(data.startsWith("CC01")){
+            //涓�鍙风増
+            bh = 1;
+        }
+        String[] sp = data.split("AA");
+        for(String s:sp){
+            if(s.length()>=20){
+                String key = SportUtils.intToHex(bh)+s.substring(4,6);
+                String isHaveKey = s.substring(8,10);
+                String keyCode = s.substring(10,18);
+                if(oldMap.containsKey(key)){
+                    //淇敼
+                    CabinetGridDo gridDo = oldMap.get(key);
+                    if("01".equals(isHaveKey)) {
+                        gridDo.setCurKeyCode(keyCode);
+                    }else {
+                        gridDo.setCurKeyCode("");
+                    }
+                    gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                    updateList.add(gridDo);
+                }else {
+                    //鏂板
+                    CabinetGridDo gridDo = new CabinetGridDo();
+                    gridDo.setGridKey(key);
+                    if("01".equals(isHaveKey)) {
+                        gridDo.setCurKeyCode(keyCode);
+                    }else {
+                        gridDo.setCurKeyCode("");
+                    }
+                    gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                    addList.add(gridDo);
+                }
+            }
+        }
+        getVM().insertGrids(addList);
+        getVM().updateGrids(updateList);
+        EventBus.getDefault().post(new KeyResultEvent());
+    }
+
     private SerialPortModel jiuPort;
     private SerialPortReadObserver jiuReadObserver = new SerialPortReadObserver() {
         @Override
         public void onResult(String result) {
+            if(result==null){
 
+            }else {
+                getVM().addInfo("鍙戦�佹寚浠ゅけ璐ワ細");
+            }
         }
 
         @Override
         public void onResultBytes(byte[] bytes) {
-            if(jiuPort!=null && !jiuPort.isOk()){
-                jiuPort.setOk(true);
+            if(bytes.length==0){
+                return;
+            }
+            runOnUiThread(() -> {
+                getVM().addInfo("鑾峰彇鍒伴厭绮炬娴嬫暟鎹�:" + new String(bytes));
+            });
+        }
+    };
+    private SerialPortModel chosePort;
+    private SerialPortReadObserver choseReadObserver = new SerialPortReadObserver() {
+        @Override
+        public void onResult(String result) {
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if(result==null){
+
+                    }else {
+                        getVM().addInfo("鍙戦�佹寚浠ゅけ璐ワ細");
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void onResultBytes(byte[] bytes) {
+            if(bytes.length==0){
+                return;
+            }
+            runOnUiThread(() -> {
+                getVM().addInfo("鑾峰彇鍒伴棬鏁版嵁:" + SportUtils.bytesToHexSimple(bytes));
+            });
+            if(startIndex==1){
+                gridPath = path;
+                getVM().addInfo("璁剧疆闂ㄤ覆鍙h矾寰�:" + path);
+                SpUtil.saveString("port_grid",path);
+            }else if(startIndex==2){
+                keyPath = path;
+                getVM().addInfo("璁剧疆閽ュ寵涓插彛璺緞:" + path);
+                SpUtil.saveString("port_key",path);
+            }else if(startIndex==3){
+                jiuPath = path;
+                getVM().addInfo("璁剧疆閰掔簿涓插彛璺緞:" + path);
+                SpUtil.saveString("port_jiu",path);
             }
         }
     };
 
     List<String> ports;
     private int index = 0;
+    private String path;
+    private int startIndex;
+    private String gridPath;
+    private String keyPath;
+    private String jiuPath;
+    private int xhCount = 0;
     private Handler portHandler = new Handler(){
         @Override
         public void handleMessage(@NonNull Message msg) {
             switch (msg.what){
                 case 0:
                     if(index>=1&&!checkEnd()){
+                        path = ports.get(index);
                         index--;
-                        chosePort(ports.get(index));
+                        portHandler.sendEmptyMessage(4);
+                    }else if(checkEnd()){
+                        initPort();
+                    }else if(xhCount<3){
+                        initPort();
                     }
+                    break;
+                case 1:
+                    //鍙戦�佹煖鏍煎懡浠�
+                    send485(0, (String) msg.obj);
+                    break;
+                case 2:
+                    //鍙戦�侀挜鍖欏懡浠�
+                    send485(1, (String) msg.obj);
+                    break;
+                case 3:
+                    //鍙戦�侀厭绮炬鏌ュ懡浠�
+                    send485(2, (String) msg.obj);
+                    break;
+                case 4:
+                    if(startIndex>2){
+                        portHandler.sendEmptyMessage(0);
+                    }else {
+                        try {
+                            chosePort();
+                        } catch (SecurityException e) {
+                            portHandler.sendEmptyMessageDelayed(5, 1000);
+                        }
+                    }
+                    break;
+                case 5:
+                    closePort(chosePort);
+                    portHandler.sendEmptyMessageDelayed(4,1000);
+                    break;
+                case 6:
+
                     break;
                 default:
                     break;
             }
         }
     };
+
+    //妫�鏌ユ墍鏈夐棬鐘舵��
+    private void checkGridStatus(long time){
+        sendPortHandlerMsg(1,"80010033B2",time+100);
+        sendPortHandlerMsg(1,"80020033B1",time+800);
+    }
+
+    //妫�鏌ユ墍鏈夐挜鍖欑姸鎬�
+    private void checkKeyStatus(long time){
+        sendPortHandlerMsg(2,"A001010000000002",time+200);
+        sendPortHandlerMsg(2,"A002010000000003",time+400);
+    }
+
+    private void setJiuConfig(long time){
+        CabinetConfigDataBean config = MApplication.getConfigBean().getCabinetConfigDataVO();
+        //璁剧疆鍚规皵鏃堕棿
+        sendPortHandlerMsg(3,"blow:"+config.getBlowTime(),time+100);
+        //鍘嬪姏鍊�
+        sendPortHandlerMsg(3,"mic_ad:"+config.getPressure(),time+300);
+        //娴撳害闃堝��
+        sendPortHandlerMsg(3,"alarm:"+config.getConcentration(),time+600);
+        //娴撳害闃堝�煎崟浣� (1=mg/100ml;2=mg/L;3=%BAC)
+        sendPortHandlerMsg(3,"unit:"+config.getThreshold(),time+900);
+    }
+
+    private void sendPortHandlerMsg(int what,String obj,long time){
+        Message mc = Message.obtain();
+        mc.what=what;
+        mc.obj = obj;
+        portHandler.sendMessageDelayed(mc,time);
+    }
+
     //鍒濆鍖栦覆鍙�
     private void initPort(){
-        ports = SportUtils.getSerialPortPaths(this);
-        if(ports.size()>0){
-            index = ports.size()-1;
-            chosePort(ports.get(ports.size()-1));
+        SpUtil.setString("port_grid","/dev/ttyS7");
+        SpUtil.setString("port_key","/dev/ttyS1");
+        SpUtil.setString("port_jiu","/dev/ttyS2");
+        gridPath = SpUtil.getString("port_grid");
+        getVM().addInfo("闂ㄤ覆鍙i摼鎺ワ細"+gridPath);
+        keyPath = SpUtil.getString("port_key");
+        getVM().addInfo("閽ュ寵涓插彛閾炬帴锛�"+keyPath);
+        jiuPath = SpUtil.getString("port_jiu");
+        getVM().addInfo("閰掔簿涓插彛閾炬帴锛�"+jiuPath);
+        if(!TextUtils.isEmpty(SpUtil.getString("port_grid"))&&
+                !TextUtils.isEmpty(SpUtil.getString("port_key"))&&
+                !TextUtils.isEmpty(SpUtil.getString("port_jiu"))){
+            xhCount=0;
+            closePort(chosePort);
+            if(!TextUtils.isEmpty(SpUtil.getString("port_grid"))){
+                String path = SpUtil.getString("port_grid");
+                closePort(gridPort);
+                getVM().addInfo("闂ㄤ覆鍙i摼鎺ワ細"+path);
+                gridPort = new SerialPortModel(path,9600 ,8
+                        ,1 , 0,gridReadObserver);
+                boolean isSucc = gridPort.open();
+                if(isSucc) {
+                    getVM().addInfo("闂ㄤ覆鍙i摼鎺ユ垚鍔燂細"+path);
+                    String msg = isSucc ? "鎴愬姛" : "澶辫触";
+                    //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
+                    gridPort.startRead();
+                    //鏌ヨ鎵�鏈夋煖鏍奸棬淇℃伅
+                   checkGridStatus(300);
+                }else {
+                    getVM().addInfo("闂ㄤ覆鍙i摼鎺ュけ璐ワ細"+path);
+                }
+            }
+            if(!TextUtils.isEmpty(SpUtil.getString("port_key"))){
+                String path = SpUtil.getString("port_key");
+                closePort(keyPort);
+                keyPort = new SerialPortModel(path,115200 ,8
+                        ,1 , 0,keyReadObserver);
+                boolean isSucc = keyPort.open();
+                if(isSucc) {
+                    getVM().addInfo("閽ュ寵涓插彛閾炬帴鎴愬姛锛�"+path);
+                    String msg = isSucc ? "鎴愬姛" : "澶辫触";
+                    //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
+                    keyPort.startRead();
+                    checkKeyStatus(1500);
+                }else {
+                    getVM().addInfo("閽ュ寵涓插彛閾炬帴澶辫触锛�"+path);
+                }
+            }
+            if(!TextUtils.isEmpty(SpUtil.getString("port_jiu"))){
+                String path = SpUtil.getString("port_jiu");
+                closePort(jiuPort);
+                jiuPort = new SerialPortModel(path,9600 ,8
+                        ,1 , 0,jiuReadObserver);
+                boolean isSucc = jiuPort.open();
+                if(isSucc) {
+                    getVM().addInfo("閰掔簿涓插彛閾炬帴鎴愬姛锛�"+path);
+                    String msg = isSucc ? "鎴愬姛" : "澶辫触";
+                    //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
+                    jiuPort.startRead();
+                }else {
+                    getVM().addInfo("閰掔簿涓插彛閾炬帴澶辫触锛�"+path);
+                }
+            }
+        }else {
+            if(xhCount>2){
+                return;
+            }
+            xhCount++;
+            ports = SportUtils.getSerialPortPaths(this);
+            if(ports==null){
+                getVM().addInfo("鏈煡璇㈠埌涓插彛鍒楄〃");
+            }else {
+                getVM().addInfo("涓插彛鍒楄〃锛�"+ports.size());
+            }
+            if(ports.size()>0){
+                index = ports.size()-1;
+                portHandler.sendEmptyMessage(0);
+            }
         }
     }
 
-    private void chosePort(String path){
-        if(gridPort==null||!gridPort.isOk()){
-            closePort(gridPort);
-            gridPort = new SerialPortModel(path,9600 ,8
-                    ,1 , 0);
-            boolean isSucc = gridPort.open();
+    private void chosePort(){
+        getVM().addInfo("褰撳墠涓嬫爣锛�"+startIndex+" ,path="+path);
+        if(startIndex==0&&TextUtils.isEmpty(gridPath)){
+            startIndex++;
+            getVM().addInfo("闂ㄤ覆鍙i摼鎺ワ細"+path);
+            chosePort = new SerialPortModel(path,9600 ,8
+                    ,1 , 0,choseReadObserver);
+            boolean isSucc = chosePort.open();
             if(isSucc) {
+                getVM().addInfo("闂ㄤ覆鍙i摼鎺ユ垚鍔燂細"+path);
                 String msg = isSucc ? "鎴愬姛" : "澶辫触";
                 //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
-                gridPort.startRead(gridReadObserver);
-                //todo 鍙戦�佹煖鏍兼牎楠屼俊鎭�
+                chosePort.startRead();
+                //鍙戦�佹煖鏍兼牎楠屼俊鎭�
+                send485(3,"80010033B2");
+            }else {
+                getVM().addInfo("闂ㄤ覆鍙i摼鎺ュけ璐ワ細"+path);
             }
+            portHandler.sendEmptyMessageDelayed(5,1500);
+            return;
         }
-        if(keyPort==null||!keyPort.isOk()){
-            closePort(keyPort);
-            keyPort = new SerialPortModel(path,115200 ,8
-                    ,1 , 0);
-            boolean isSucc = keyPort.open();
+        if(startIndex==1&&TextUtils.isEmpty(keyPath)){
+            startIndex++;
+            chosePort = new SerialPortModel(path,115200 ,8
+                    ,1 , 0,choseReadObserver);
+            boolean isSucc = chosePort.open();
             if(isSucc) {
+                getVM().addInfo("閽ュ寵涓插彛閾炬帴鎴愬姛锛�"+path);
                 String msg = isSucc ? "鎴愬姛" : "澶辫触";
                 //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
-                keyPort.startRead(keyReadObserver);
-                //todo 鍙戦�侀挜鍖欐牎楠屼俊鎭�
+                chosePort.startRead();
+                //鍙戦�侀挜鍖欐牎楠屼俊鎭�
+                send485(3,"A001010000000002");
+            }else {
+                getVM().addInfo("閽ュ寵涓插彛閾炬帴澶辫触锛�"+path);
             }
+            portHandler.sendEmptyMessageDelayed(5,1500);
+            return;
         }
-        if(jiuPort==null||!jiuPort.isOk()){
-            closePort(jiuPort);
-            jiuPort = new SerialPortModel(path,9600 ,8
-                    ,1 , 0);
-            boolean isSucc = jiuPort.open();
+        if(startIndex==2&&TextUtils.isEmpty(jiuPath)){
+            startIndex++;
+            chosePort = new SerialPortModel(path,9600 ,8
+                    ,1 , 0,choseReadObserver);
+            boolean isSucc = chosePort.open();
             if(isSucc) {
+                getVM().addInfo("閰掔簿涓插彛閾炬帴鎴愬姛锛�"+path);
                 String msg = isSucc ? "鎴愬姛" : "澶辫触";
                 //getVM().append("涓插彛 "+ settingBean.getDevicePath() + " -杩炴帴"+msg);
-                jiuPort.startRead(jiuReadObserver);
-                //todo 鍙戦�侀厭绮炬牎楠屼俊鎭�
+                chosePort.startRead();
+                //鍙戦�侀厭绮炬牎楠屼俊鎭�
+                send485(4,"read");
+            }else {
+                getVM().addInfo("閰掔簿涓插彛閾炬帴澶辫触锛�"+path);
             }
+            portHandler.sendEmptyMessageDelayed(5,1500);
+            return;
         }
+        portHandler.sendEmptyMessageDelayed(0,0);
+    }
 
-        portHandler.sendEmptyMessageDelayed(0,2000);
+    private void send485(int type,String code){
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getVM().addInfo("鍙戦�佹寚浠わ細"+StringUtil.DateToStrSS(new Date())+"==>"+code);
+            }
+        });
+        if(type==0){
+            if(gridPort!=null){
+                byte[] sendByte = SportUtils.hexToByteArray(code);
+                gridPort.write(sendByte);
+            }
+        }else if(type==1){
+            if(keyPort!=null){
+                byte[] sendByte = SportUtils.hexToByteArray(code);
+                keyPort.write(sendByte);
+            }
+        }else if(type==2){
+            if(jiuPort!=null){
+                byte[] sendByte =code.getBytes();
+                jiuPort.write(sendByte);
+            }
+        }else if(type==3){
+            if(chosePort!=null){
+                byte[] sendByte = SportUtils.hexToByteArray(code);
+                chosePort.write(sendByte);
+            }
+        }else if(type==4){
+            if(chosePort!=null){
+                byte[] sendByte =code.getBytes();
+                chosePort.write(sendByte);
+            }
+        }
     }
 
     private void closePort(SerialPortModel port){
-        if(port==null){
-            return;
+        try {
+            if(port==null){
+                return;
+            }
+            port.stopRead();
+            port.close();
+            port = null;
+        }catch (Exception e){
+
         }
-        port.startRead(null);
-        port.stopRead();
-        port.close();
-        port = null;
     }
 
     private boolean checkEnd(){
-        if(gridPort==null||!gridPort.isOk()){
+        if(TextUtils.isEmpty(gridPath)){
+            getVM().addInfo("闂ㄩ敊璇�");
+            startIndex=0;
             return false;
         }
-        if(keyPort==null||!keyPort.isOk()){
+        if(TextUtils.isEmpty(keyPath)){
+            getVM().addInfo("閽ュ寵閿欒");
+            startIndex=1;
             return false;
         }
-        if(jiuPort==null||!jiuPort.isOk()){
+        if(TextUtils.isEmpty(jiuPath)){
+            getVM().addInfo("閰掔簿閿欒");
+            startIndex=2;
             return false;
         }
+        getVM().addInfo("涓插彛鍏ㄩ儴閾炬帴鎴愬姛锛�");
         return true;
     }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java
index 103ae1d..16c401a 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java
@@ -13,27 +13,39 @@
 import com.doumee.keyCabinet.bean.CabinetFaceBean;
 import com.doumee.keyCabinet.bean.DevConfigBean;
 import com.doumee.keyCabinet.bean.FaceUserBean;
+import com.doumee.keyCabinet.bean.KeyCabinetBean;
+import com.doumee.keyCabinet.bean.LoginBean;
+import com.doumee.keyCabinet.bean.ManageKeyCabinetBean;
+import com.doumee.keyCabinet.dao.CabinetGridDo;
+import com.doumee.keyCabinet.dao.DaoManager;
 import com.doumee.keyCabinet.event.DevConfigEvent;
+import com.doumee.keyCabinet.event.HttpEvent;
 import com.doumee.keyCabinet.http.Apis;
 import com.doumee.keyCabinet.http.param.BaseResponse;
+import com.doumee.keyCabinet.http.param.CloseGridParam;
 import com.doumee.keyCabinet.http.param.DevErrInfoParam;
 import com.doumee.keyCabinet.http.param.DevLoginParam;
 import com.doumee.keyCabinet.http.param.FaceUserParam;
 import com.doumee.keyCabinet.http.param.RequestBaseObject;
-import com.doumee.keyCabinet.ui.guide.GuideActivity;
+import com.doumee.keyCabinet.http.param.TimeOutUnCloseAlarmParam;
 import com.doumee.keyCabinet.utils.BraceletLogUtils;
 import com.doumee.keyCabinet.utils.LMobileInfo;
 import com.doumee.keyCabinet.utils.LanguageUtil;
 import com.doumee.keyCabinet.utils.ParamsUtil;
+import com.doumee.keyCabinet.utils.i485.SportUtils;
 import com.doumee.lib_coremodel.base.BaseModel;
 import com.doumee.lib_coremodel.base.DataViewModel;
 import com.doumee.lib_coremodel.http.rxJava.SimpleObserver;
+import com.doumee.lib_coremodel.http.utils.GsonTools;
 import com.doumee.lib_coremodel.http.utils.RxUtils;
 import com.doumee.lib_coremodel.util.SpUtil;
+import com.doumee.lib_coremodel.util.StringUtil;
 
 import org.greenrobot.eventbus.EventBus;
 
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 
 import okhttp3.Headers;
@@ -42,8 +54,10 @@
 public class MainVM extends DataViewModel {
     public ObservableField<String> dayObs = new ObservableField<>("");
     public ObservableField<String> timeObs = new ObservableField<>("");
+    public ObservableField<String> infoObs = new ObservableField<>("");
 
     private MutableLiveData<List<FaceUserBean>> faceLD = new MutableLiveData<>();
+    private MutableLiveData<DevConfigBean> confidLD = new MutableLiveData<>();
 
     @ViewModelInject
     public MainVM(@NonNull Application application, BaseModel model) {
@@ -55,27 +69,23 @@
         doAction(type);
     }
 
-    private boolean isReq = false;
-
-    public void resetReq(){
-        isReq = false;
-    }
-
     public void devLogin(){
         //娓呴櫎鐧诲綍淇℃伅
-        if(isReq){
-            return;
-        }
-        isReq = true;
         MApplication.saveConfigBean(new DevConfigBean());
+        EventBus.getDefault().post(new HttpEvent("鑾峰彇閽ュ寵鏌滃熀鏈俊鎭�-璇锋眰"));
         getRetrofitService(Apis.class).getCabinetInfoForDriver(LMobileInfo.getDeviceUniqueId())
                 .compose(RxUtils.schedulersTransformer())
                 .subscribe(new SimpleObserver<BaseResponse<DevConfigBean>>(rxJavaGcManager) {
                     @Override
                     public void onNext(@NonNull BaseResponse<DevConfigBean> response) {
+                        EventBus.getDefault().post(new HttpEvent("鑾峰彇閽ュ寵鏌滃熀鏈俊鎭�-杩斿洖锛�"+ GsonTools.changeGsonToJson(response)));
                         if(200==response.getCode()){
                             if(response.getData()!=null){
                                 MApplication.saveConfigBean(response.getData());
+                                confidLD.setValue(response.getData());
+                                if(response.getData().getCabinetGridInfoVOList()!=null){
+                                    updateDao(response.getData().getCabinetGridInfoVOList());
+                                }
                             }else {
                                 toast(MApplication.mContext.getString(R.string.guide_toast_1));
                             }
@@ -87,13 +97,63 @@
                     @Override
                     public void onError(@NonNull Throwable e) {
                         toast(e.getMessage());
+                        EventBus.getDefault().post(new HttpEvent("鑾峰彇閽ュ寵鏌滃熀鏈俊鎭�-閿欒锛�"+ e.getMessage()));
                     }
 
                     @Override
                     public void onComplete() {
-                        isReq = false;
+
                     }
                 });
+    }
+
+    private void updateDao(List<ManageKeyCabinetBean> beans){
+        List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll();
+        HashMap<String,CabinetGridDo> oldMap = new HashMap<>();
+        for(CabinetGridDo d:gridDos){
+            oldMap.put(d.getGridKey(),d);
+        }
+        List<CabinetGridDo> addList = new ArrayList<>();
+        List<CabinetGridDo> updateList = new ArrayList<>();
+        for(ManageKeyCabinetBean bean:beans){
+            String key = SportUtils.intToHex(Integer.parseInt(bean.getBoardCode()))+SportUtils.intToHex(Integer.parseInt(bean.getChannelCode()));
+            if(oldMap.containsKey(key)){
+                //淇敼
+                CabinetGridDo gridDo = oldMap.get(key);
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                updateList.add(gridDo);
+            }else {
+                //鏂板
+                CabinetGridDo gridDo = new CabinetGridDo();
+                gridDo.setGridId(bean.getId());
+                gridDo.setCabinetName(bean.getCode());
+                gridDo.setGridKey(key);
+                gridDo.setKeyCode(bean.getKeyCode());
+                gridDo.setBindStatus(bean.getBindStatus());
+                gridDo.setGridStatus(bean.getStatus());
+                gridDo.setKeyStatus(bean.getKeyStatus());
+                gridDo.setWorkingStatus(bean.getWorkingStatus());
+                gridDo.setUpdateTime(StringUtil.DateToStr(new Date()));
+                addList.add(gridDo);
+            }
+        }
+        if(addList.size()>0){
+            DaoManager.getCabinetGridDao().insert(addList);
+        }
+        if(updateList.size()>0){
+            CabinetGridDo[] upList = new CabinetGridDo[updateList.size()];
+            for(int i=0;i<updateList.size();i++){
+                upList[i] = updateList.get(i);
+            }
+            DaoManager.getCabinetGridDao().update(upList);
+        }
     }
 
     public void devHeart(){
@@ -128,10 +188,8 @@
         if (true) {
             return;
         }
-        DevLoginParam param = new DevLoginParam();
-        param.setCode(LMobileInfo.getDeviceUniqueId());
         //showLoading(true);
-        getRetrofitService(Apis.class).allFaceList( ParamsUtil.encodeRequestBody(param))
+        getRetrofitService(Apis.class).allFaceList( LMobileInfo.getDeviceUniqueId())
                 .compose(RxUtils.schedulersTransformer())
                 .subscribe(new SimpleObserver<BaseResponse<CabinetFaceBean>>(rxJavaGcManager) {
                     @Override
@@ -204,44 +262,89 @@
                 });
     }
 
-    /**
-     * 涓婁紶鎵嬬幆鏃ュ織
-     */
-    public void upBraceletLog() {
-        if (true) {
-            return;
+    public List<CabinetGridDo> getOpenGrids(){
+        return DaoManager.getCabinetGridDao().getOpenGrids();
+    }
+
+    public void insertGrids(List<CabinetGridDo> addList){
+        if(addList.size()>0){
+            DaoManager.getCabinetGridDao().insert(addList);
         }
-        if(BraceletLogUtils.COUNT>100||(System.currentTimeMillis() - BraceletLogUtils.lastTime > 600000)){
-            BraceletLogUtils.lastTime = System.currentTimeMillis();
-            String text = BraceletLogUtils.getAllLog();
-            if(TextUtils.isEmpty(text)){
-                return;
+        addInfo("鏇存柊搴撴暟鎹�:鏂板" + addList.size());
+    }
+
+    public void updateGrids(List<CabinetGridDo> updateList){
+        if(updateList.size()>0){
+            CabinetGridDo[] upList = new CabinetGridDo[updateList.size()];
+            for(int i=0;i<updateList.size();i++){
+                upList[i] = updateList.get(i);
             }
-            RequestBaseObject<DevErrInfoParam> request = new RequestBaseObject<>();
-            DevErrInfoParam param = new DevErrInfoParam();
-            param.setDevCode(LMobileInfo.getDeviceUniqueId());
-            param.setErrInfo(text);
-            request.setParam(param);
-            getRetrofitService(Apis.class).upErrInfo(ParamsUtil.encodeRequestBody(request))
-                    .compose(RxUtils.schedulersTransformer())
-                    .subscribe(new SimpleObserver<BaseResponse>(rxJavaGcManager) {
-                        @Override
-                        public void onNext(@NonNull BaseResponse response) {
-                            if(200==response.getCode()){
-
-                            }
-                        }
-
-                        @Override
-                        public void onError(@NonNull Throwable e) {
-
-                        }
-
-                        @Override
-                        public void onComplete() {
-
-                        }
-                    });
+            DaoManager.getCabinetGridDao().update(upList);
         }
+        addInfo("鏇存柊搴撴暟鎹�:淇敼" + updateList.size());
+    }
+
+    public void timeOutUnCloseAlarm(CabinetGridDo gridDo){
+        TimeOutUnCloseAlarmParam param = new TimeOutUnCloseAlarmParam();
+        LoginBean loginBean = MApplication.getLoginBean();
+        param.setCabinetId(MApplication.getConfigBean().getId());
+        param.setMemberId(loginBean.getMemberId());
+        param.setGridId(gridDo.getGridId());
+        getRetrofitService(Apis.class).timeOutUnCloseAlarm(ParamsUtil.encodeRequestBody(param))
+                .compose(RxUtils.schedulersTransformer())
+                .subscribe(new SimpleObserver<BaseResponse>(rxJavaGcManager) {
+                    @Override
+                    public void onNext(@NonNull BaseResponse response) {
+
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+
+                    @Override
+                    public void onComplete() {
+
+                    }
+                });
+    }
+
+    public void closeGrid(CabinetGridDo gridDo){
+        CloseGridParam param = new CloseGridParam();
+        LoginBean loginBean = MApplication.getLoginBean();
+        param.setCabinetId(MApplication.getConfigBean().getId());
+        param.setAuthType(loginBean.getAuthType());
+        param.setMemberId(loginBean.getMemberId());
+        param.setGridId(gridDo.getGridId());
+        param.setKeyStatus(!TextUtils.isEmpty(gridDo.getCurKeyCode())?1:2);
+        getRetrofitService(Apis.class).closeGrid(ParamsUtil.encodeRequestBody(param))
+                .compose(RxUtils.schedulersTransformer())
+                .subscribe(new SimpleObserver<BaseResponse>(rxJavaGcManager) {
+                    @Override
+                    public void onNext(@NonNull BaseResponse response) {
+
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+
+                    @Override
+                    public void onComplete() {
+
+                    }
+                });
+    }
+
+    public MutableLiveData<DevConfigBean> getConfidLD() {
+        return confidLD;
+    }
+
+    public void addInfo(String info){
+        String s = infoObs.get();
+        s+=info+"\n";
+        infoObs.set(s);
     }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java
index b12d2fe..e70819c 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java
@@ -4,7 +4,7 @@
 import android.content.Context;
 import android.content.Intent;
 
-import com.doumee.keyCabinet.ui.guide.GuideActivity;
+import com.doumee.keyCabinet.ui.main.MainActivity;
 
 /**
  * Created by Forrest.
@@ -17,7 +17,7 @@
     public void onReceive(Context context, Intent intent) {
 
         if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
-            Intent thisIntent = new Intent(context, GuideActivity.class);
+            Intent thisIntent = new Intent(context, MainActivity.class);
             thisIntent.setAction("android.intent.action.MAIN");
             thisIntent.addCategory("android.intent.category.LAUNCHER");
             thisIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java
index e01ccd3..524da4f 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java
@@ -14,7 +14,7 @@
 /**
  * Created by Administrator on 2017/4/1 0001.
  */
-public class BannerViewImageHolder implements Holder<BannerPicResponsePara> {
+public class BannerViewImageHolder implements Holder<String> {
    private SimpleDraweeView sim_icon;
 
    @Override
@@ -26,7 +26,7 @@
    }
 
    @Override
-   public void UpdateUI(final Context context, int position, final BannerPicResponsePara data) {
-      FrescoUtils.displayImageFresco(data.getImageFullPath(),sim_icon);
+   public void UpdateUI(final Context context, int position, final String data) {
+      FrescoUtils.displayImageFresco(data,sim_icon);
    }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java
index f7b56c6..81f5e5d 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java
@@ -12,9 +12,13 @@
 import android.os.Looper;
 
 import com.doumee.keyCabinet.ui.guide.GuideActivity;
+import com.doumee.keyCabinet.ui.main.MainActivity;
 import com.doumee.lib_coremodel.util.SpUtil;
 
+import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.io.PrintWriter;
@@ -85,7 +89,7 @@
 			dumpExceptionToSDCard(ex);
 			//System.out.println("閲嶅惎搴旂敤");
 			// 鍒涘缓涓�涓柊鐨勫惎鍔ㄦ剰鍥�
-			Intent intent = new Intent(mContext, GuideActivity.class);
+			/*Intent intent = new Intent(mContext, MainActivity.class);
 			// 璁剧疆FLAG_ACTIVITY_CLEAR_TASK鏍囧織浣�
 			intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
 			// 浣跨敤PendingIntent鍖呰鍚姩鎰忓浘
@@ -93,7 +97,7 @@
 			// 鑾峰彇AlarmManager瀹炰緥
 			AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 			// 鍦�500姣鍚庤Е鍙戦噸鍚搷浣�
-			alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 10, pendingIntent);
+			alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 10, pendingIntent);*/
 
 			android.os.Process.killProcess(android.os.Process.myPid());
 			System.exit(1);
@@ -267,7 +271,7 @@
 			//LogUtils.e(TAG, "dump crash info failed");
 		}
 		//浠ュ綋鍓嶆椂闂村垱寤簂og鏂囦欢
-		/*File file = new File(PATH , FILE_NAME + time + FILE_NAME_SUFFIX);
+		File file = new File(PATH , FILE_NAME + time + FILE_NAME_SUFFIX);
 		try {
 			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
 			//瀵煎嚭鍙戠敓寮傚父鐨勬椂闂�
@@ -282,7 +286,7 @@
 			e.printStackTrace();
 			System.out.println("閿欒鏃ュ織2"+e.getMessage());
 			//LogUtils.e(TAG, "dump crash info failed");
-		}*/
+		}
 	}
 	private void dumpPhoneInfo(PrintStream pw) throws NameNotFoundException {
 		//搴旂敤鐨勭増鏈悕绉板拰鐗堟湰鍙�
@@ -305,4 +309,26 @@
 		//cpu鏋舵瀯
 		pw.print("CPU ABI: ");
 		pw.println(Build.CPU_ABI);   }
+
+	private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {
+		//搴旂敤鐨勭増鏈悕绉板拰鐗堟湰鍙�
+		PackageManager pm = mContext.getPackageManager();
+		PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
+		pw.print("App Version: ");
+		pw.print(pi.versionName);
+		pw.print('_');
+		pw.println(pi.versionCode);
+		//android鐗堟湰鍙�
+		pw.print("OS Version: ");
+		pw.print(Build.VERSION.RELEASE);
+		pw.print("_");
+		pw.println(Build.VERSION.SDK_INT);
+		//鎵嬫満鍒堕�犲晢
+		pw.print("Vendor: ");
+		pw.println(Build.MANUFACTURER);
+		//鎵嬫満鍨嬪彿     pw.print("Model: ");
+		pw.println(Build.MODEL);
+		//cpu鏋舵瀯
+		pw.print("CPU ABI: ");
+		pw.println(Build.CPU_ABI);   }
 }
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java
index af40f4e..f79b81a 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java
@@ -29,16 +29,18 @@
     private ScheduledExecutorService scheduledExecutorService;
     private ExecutorService singleThreadExecutor;
     private ScheduledFuture scheduledFuture;
+    private SerialPortReadObserver serialPortReadObserver;
     private boolean isOk = false;
 
     private final Object writeLock = new Object();
 
-    public SerialPortModel(String serialPortPath, int baudrate, int dataBits, int stopBits, int parity) {
+    public SerialPortModel(String serialPortPath, int baudrate, int dataBits, int stopBits, int parity,SerialPortReadObserver portReadObserver) {
         this.serialPortPath = serialPortPath;
         this.baudrate = baudrate;
         this.dataBits = dataBits;
         this.stopBits = stopBits;
         this.parity = parity;
+        this.serialPortReadObserver = portReadObserver;
     }
 
     public boolean open() {
@@ -72,7 +74,7 @@
         }
     }
 
-    public void startRead(SerialPortReadObserver serialPortReadObserver) {
+    public void startRead() {
         scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
             InputStream inputStream = serialPort.getInputStream();
             byte[] bytes = new byte[2048];
@@ -89,23 +91,29 @@
             for(int i=0;i<length;i++){
                 bytes2[i] = bytes[i];
             }
-            serialPortReadObserver.onResultBytes(bytes2);
-        }, 0, 50, TimeUnit.MILLISECONDS);
+            if(serialPortReadObserver!=null) {
+                serialPortReadObserver.onResultBytes(bytes2);
+            }
+        }, 0, 100, TimeUnit.MILLISECONDS);
     }
 
     public void stopRead() {
         scheduledFuture.cancel(true);
     }
 
-    public void write(byte[] bytes,SerialPortReadObserver serialPortReadObserver) {
+    public void write(byte[] bytes) {
         singleThreadExecutor.execute(() -> {
             synchronized (writeLock) {
                 try {
                     serialPort.getOutputStream().write(bytes);
-                    serialPortReadObserver.onResult(null);
+                    if(serialPortReadObserver!=null) {
+                        serialPortReadObserver.onResult(null);
+                    }
                 } catch (IOException e) {
                     e.printStackTrace();
-                    serialPortReadObserver.onResult(e.getMessage());
+                    if(serialPortReadObserver!=null) {
+                        serialPortReadObserver.onResult(e.getMessage());
+                    }
                 }
             }
         });
diff --git a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java
index 1ce6dc4..d68579e 100644
--- a/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java
+++ b/keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java
@@ -24,6 +24,191 @@
                 }
             }
         }
+        if(serialPaths.size()==0){
+            serialPaths.add("/dev/ttyS0");
+            serialPaths.add("/dev/ttyS1");
+            serialPaths.add("/dev/ttyS2");
+            serialPaths.add("/dev/ttyS3");
+            serialPaths.add("/dev/ttyS4");
+            serialPaths.add("/dev/ttyS5");
+            serialPaths.add("/dev/ttyS6");
+            serialPaths.add("/dev/ttyS7");
+        }
         return serialPaths;
     }
+
+    /**
+     * 瀛楄妭鏁扮粍杞�16杩涘埗
+     * @param bytes 闇�瑕佽浆鎹㈢殑byte鏁扮粍
+     * @return  杞崲鍚庣殑Hex瀛楃涓�
+     */
+    public static String bytesToHexSimple(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xFF));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * hex瀛楃涓茶浆byte鏁扮粍
+     * @param inHex 寰呰浆鎹㈢殑Hex瀛楃涓�
+     * @return  杞崲鍚庣殑byte鏁扮粍缁撴灉
+     */
+    public static byte[] hexToByteArray(String inHex){
+        int hexlen = inHex.length();
+        byte[] result;
+        if (hexlen % 2 == 1){
+            //濂囨暟
+            hexlen++;
+            result = new byte[(hexlen/2)];
+            inHex="0"+inHex;
+        }else {
+            //鍋舵暟
+            result = new byte[(hexlen/2)];
+        }
+        int j=0;
+        for (int i = 0; i < hexlen; i+=2){
+            result[j]=hexToByte(inHex.substring(i,i+2));
+            j++;
+        }
+        return result;
+    }
+
+    /**
+     * 鏍¢獙鏁版嵁鏄惁姝g‘
+     * @param data
+     * @return
+     */
+    public static boolean checkData(String data){
+        if(data.length()>2){
+            String d = data.substring(0,data.length()-2);
+            String hz = data.substring(data.length()-2,data.length());
+            if(hz.equals(SportUtils.getBCC(d))){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Hex瀛楃涓茶浆byte
+     * @param inHex 寰呰浆鎹㈢殑Hex瀛楃涓�
+     * @return  杞崲鍚庣殑byte
+     */
+    public static byte hexToByte(String inHex){
+        return (byte)Integer.parseInt(inHex,16);
+    }
+
+    public static String getBCC(String hex) {
+        int i = 0, j = 0;
+        int len = hex.length();
+        short inb[] = new short[len];
+        for (i = 0; i < len; i++) {
+            inb[i] = charToHex(hex.charAt(i));   //灏哠tring閲岀殑姣忎竴涓猚har杞崲涓篐ex
+        }
+
+        for (i = 0; i < len; i++) {    //灏嗘瘡涓や釜Hex鍚堝苟鎴愪竴涓猙yte
+            inb[j] = (byte) (((inb[i] << 4) & 0x00f0) | ((inb[i + 1]) & 0x000f));
+            i++;
+            j++;
+        }
+        byte temp = 0x00; //鏍¢獙鍊�
+        for (i = 0; i < len / 2; i++) { //寮傛垨
+            temp ^= inb[i];
+        }
+        byte[] bytes = new byte[1];
+        bytes[0] = temp;
+        return byteToStr(bytes, bytes.length);
+    }
+    /**
+     * 鎺ユ敹鍒扮殑瀛楄妭鏁扮粍杞崲16杩涘埗瀛楃涓�
+     */
+    public static String byteToStr(byte[] b, int size) {
+        String ret = "";
+        for (int i = 0; i < size; i++) {
+            String hex = Integer.toHexString(b[i] & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            ret += hex.toUpperCase();
+        }
+        return ret;
+    }
+    public static short charToHex(char x) { //灏嗗崟涓猚har杞崲涓篐ex
+        short result = 0;
+        switch (x) {
+            case 'a':
+                result = 10;
+                break;
+            case 'b':
+                result = 11;
+                break;
+            case 'c':
+                result = 12;
+                break;
+            case 'd':
+                result = 13;
+                break;
+            case 'e':
+                result = 14;
+                break;
+            case 'f':
+                result = 15;
+                break;
+            case 'A':
+                result = 10;
+                break;
+            case 'B':
+                result = 11;
+                break;
+            case 'C':
+                result = 12;
+                break;
+            case 'D':
+                result = 13;
+                break;
+            case 'E':
+                result = 14;
+                break;
+            case 'F':
+                result = 15;
+                break;
+            default:
+                result = (short) Character.getNumericValue(x);
+                break;
+        }
+        return result;
+    }
+
+    public static String intToHex(int n) {
+        //StringBuffer s = new StringBuffer();
+        StringBuilder sb = new StringBuilder(2);
+        String a;
+        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+        while(n != 0){
+            sb = sb.append(b[n%16]);
+            n = n/16;
+        }
+        if(sb.length()==1){
+            sb.append("0");
+        }
+        a = sb.reverse().toString();
+        return a;
+    }
+
+    /**
+     * 16杩涘埗杞�2杩涘埗
+     * @param hexString
+     * @return
+     */
+    public static String hexToBinary(String hexString) {
+        StringBuilder binary = new StringBuilder();
+        for (char c : hexString.toCharArray()) {
+            int value = Character.digit(c, 16);
+            String bits = String.format("%4s", Integer.toBinaryString(value)).replace(' ', '0');
+            binary.append(bits);
+        }
+        return binary.toString();
+    }
 }
diff --git a/keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml b/keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml
index e523dfd..7ca40af 100644
--- a/keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml
+++ b/keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml
@@ -17,7 +17,7 @@
             android:id="@+id/tv1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="@{data.cabinetName}"
+            android:text="@{data.code}"
             android:textColor="@{data.text1Color}"
             android:textSize="24sp"
             app:layout_constraintTop_toTopOf="parent"
diff --git a/keyCabinet-android/app/src/main/res/layout/main_activity.xml b/keyCabinet-android/app/src/main/res/layout/main_activity.xml
index 47ce15b..1df9cf9 100644
--- a/keyCabinet-android/app/src/main/res/layout/main_activity.xml
+++ b/keyCabinet-android/app/src/main/res/layout/main_activity.xml
@@ -353,5 +353,42 @@
 
         </androidx.constraintlayout.widget.ConstraintLayout>
 
+        <androidx.core.widget.NestedScrollView
+            android:layout_width="match_parent"
+            android:layout_height="200dp"
+            app:layout_constraintTop_toTopOf="parent"
+            android:background="@color/white">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintTop_toTopOf="parent"
+                    android:text="@{model.infoObs}"
+                    android:textColor="@color/black"
+                    android:textSize="20sp">
+
+                </TextView>
+
+                <TextView
+                    android:id="@+id/tv11"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="娓呯┖"
+                    android:textColor="#ff279baa"
+                    android:textSize="20sp"
+                    android:textStyle="bold"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:commandType="@{55}"
+                    app:onClickCommand="@{model.myTypeCommand}"/>
+
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
+        </androidx.core.widget.NestedScrollView>
+
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>
\ No newline at end of file
diff --git a/keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml b/keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml
index b72f283..fc6ded8 100644
--- a/keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml
+++ b/keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml
@@ -310,6 +310,7 @@
         </androidx.constraintlayout.widget.ConstraintLayout>
 
         <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rcv_km"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             app:layout_constraintTop_toBottomOf="@+id/cl_2"
@@ -350,7 +351,7 @@
             android:textSize="24sp"
             android:paddingLeft="30dp"
             android:paddingRight="30dp"
-            android:background="@drawable/shape_mb_bt_ok"
+            android:background="@drawable/shape_mb_bt_faile"
             app:layout_constraintTop_toTopOf="@+id/tv_all_open"
             app:layout_constraintLeft_toRightOf="@+id/tv_all_open"
             app:layout_constraintRight_toLeftOf="@+id/tv_bj"
@@ -382,7 +383,7 @@
             android:id="@+id/cl_cz"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:visibility="visible">
+            android:visibility="gone">
 
             <View
                 android:layout_width="match_parent"
@@ -479,7 +480,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:background="#80000000"
-                app:commandType="@{8}"
+                app:commandType="@{9}"
                 app:onClickCommand="@{model.myTypeCommand}"/>
 
             <androidx.constraintlayout.widget.ConstraintLayout
@@ -517,7 +518,7 @@
                     android:id="@+id/tv_cl_km_2"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:text="閽ュ寵鏌淎C103銆丄C104銆丄C105銆丄C104銆丄C105銆丄C104銆丄C105銆丄C105銆丄C104銆丄C105寮�闂ㄦ垚鍔燂紝棰嗚繕鍚庤鍏抽棬"
+                    android:text="閽ュ寵鏌滃紑闂ㄦ垚鍔燂紝棰嗚繕鍚庤鍏抽棬"
                     android:textColor="#ff333333"
                     android:textSize="22sp"
                     android:gravity="center"
@@ -543,5 +544,61 @@
 
         </androidx.constraintlayout.widget.ConstraintLayout>
 
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/cl_tip"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/white"
+            android:visibility="gone">
+
+            <TextView
+                android:id="@+id/tv_djs"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="10s"
+                android:textColor="#ff279baa"
+                android:textSize="24sp"
+                app:layout_constraintTop_toTopOf="parent"
+                android:layout_marginTop="33dp"
+                app:layout_constraintEnd_toEndOf="parent"
+                android:layout_marginRight="30dp"/>
+
+            <ImageView
+                android:id="@+id/img_tip2"
+                android:layout_width="300dp"
+                android:layout_height="205dp"
+                android:src="@mipmap/ic_notclose_key"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                android:layout_marginTop="140dp"/>
+
+            <TextView
+                android:id="@+id/tv_tip2_1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="鏌滈棬鏈叧闂�"
+                android:textColor="#ff111111"
+                android:textSize="33sp"
+                android:textStyle="bold"
+                app:layout_constraintTop_toBottomOf="@+id/img_tip2"
+                android:layout_marginTop="18dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <TextView
+                android:id="@+id/tv_tip2_2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text=""
+                android:textColor="#ff666666"
+                android:textSize="24sp"
+                app:layout_constraintTop_toBottomOf="@+id/tv_tip2_1"
+                android:layout_marginTop="22dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>
\ No newline at end of file
diff --git a/keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml b/keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml
index f2f2c6e..f3bdf42 100644
--- a/keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml
+++ b/keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml
@@ -186,7 +186,7 @@
             android:id="@+id/tv_v"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="V1.1.2"
+            android:text=""
             android:textColor="#b3ffffff"
             android:textSize="18sp"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -257,7 +257,7 @@
                 android:id="@+id/tv_tip_2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="濡傛湁闂璇疯仈绯荤鐞嗗憳15899098765"
+                android:text="濡傛湁闂璇疯仈绯荤鐞嗗憳"
                 android:textColor="#666666"
                 android:textSize="24sp"
                 app:layout_constraintTop_toTopOf="parent"
diff --git a/keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java b/keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java
index ada3742..b65c9df 100644
--- a/keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java
+++ b/keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java
@@ -1,16 +1,30 @@
 package com.doumee.ticketmachine;
 
+import com.doumee.keyCabinet.utils.i485.SportUtils;
+
 import org.junit.Test;
+
+import static com.doumee.keyCabinet.utils.i485.SportUtils.hexToBinary;
 
 public class ExampleUnitTest {
     @Test
     public void addition_isCorrect() {
-        String m = "2025-03-10 15:46:06    寮�濮嬪綊杩榎n2025-03-10 15:46:10    涓嶅彲浠ュ綊杩�(1977169908),鍘熷洜锛氭墜鐜湭缁戝畾\n鏃犳硶褰掕繕\n2025-03-10 15:46:10    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:10    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:10    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:10    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:10    杩樻墜鐜け璐�,鎵嬬幆鏈粦瀹歕n鏃犳硶褰掕繕\n2025-03-10 15:46:10    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:10    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:13    寮�濮嬪綊杩榎n2025-03-10 15:46:15    涓嶅彲浠ュ綊杩�(1977169908),鍘熷洜锛氭墜鐜湭缁戝畾\n鏃犳硶褰掕繕\n2025-03-10 15:46:15    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:15    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:15    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:15    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:15    杩樻墜鐜け璐�,鎵嬬幆鏈粦瀹歕n鏃犳硶褰掕繕\n2025-03-10 15:46:15    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:15    onCompleted 鎵ц瀹屾垚\n2025-03-10 15:46:18    寮�濮嬪綊杩榎n2025-03-10 15:46:22    寮�濮嬪綊杩榎n2025-03-10 15:46:23    onStopBack 鍋滄杩斿洖\n2025-03-10 15:46:23    onCompleted 鎵ц瀹屾垚\n";
-        String[] sp = m.split("\n");
-        for(String s:sp){
-            System.out.println(s);
+        String s = "80010000FFEF33B2";
+        String dm = s.substring(4,12);
+        System.out.println("===1>"+dm);
+        dm = dm.replaceAll("0","");
+        System.out.println("===2>"+dm);
+        dm = SportUtils.hexToBinary(dm);
+        System.out.println("===3>"+dm);
+        StringBuilder sb = new StringBuilder(dm);
+        dm = sb.reverse().toString();
+        System.out.println("===4>"+dm);
+        for(int i=1;i<=dm.length();i++){
+            String key = SportUtils.intToHex(i);
+            System.out.println("===>"+key+","+("1".equals(dm.substring(i-1,i))?"鍏�":"寮�"));
         }
     }
 
 
+
 }
\ No newline at end of file
diff --git a/keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java b/keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java
index f9195d6..a0254bb 100644
--- a/keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java
+++ b/keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java
@@ -1084,6 +1084,13 @@
         return str;
     }
 
+    public static String DateToStrSS(Date date) {
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+        String str = format.format(date);
+        return str;
+    }
+
     public static String getHM() {
 
         SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

--
Gitblit v1.9.3