weimingfei
3 天以前 c7376f8d1091b70597ba4430a281496b585b386e
钥匙柜
已添加17个文件
已删除2个文件
已修改34个文件
3200 ■■■■ 文件已修改
keyCabinet-android/app/src/main/AndroidManifest.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/MApplication.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/CabinetConfigDataBean.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/DevConfigBean.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/KeyCabinetBean.java 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/LoginBean.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/bean/ManageKeyCabinetBean.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDB.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDao.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/CabinetGridDo.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/dao/DaoManager.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLGridEvent.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CLKeyEvent.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/CloseGridOneResultEvent.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/HttpEvent.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyDoorEvent.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyResultEvent.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyStatusListener.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridListEvent.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenGridOneResultEvent.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/SendPortCode.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/Apis.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/AlcoholTestAlarmParam.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/CloseGridParam.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/GetDriverGridParam.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/http/param/TimeOutUnCloseAlarmParam.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceVM.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceActivity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/FaceVM.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetActivity.java 294 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/KeyCabinetVM.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetActivity.java 352 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageCabinetVM.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginActivity.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/ManageLoginVM.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/keyCabinet/adapter/ManageCabinetRcvAdapter.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java 861 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainVM.java 205 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/service/BootCompleteReceiver.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/view/BannerViewImageHolder.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/CrashHandler.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SerialPortModel.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/utils/i485/SportUtils.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/res/layout/cabinet_rcv_item.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/res/layout/main_activity.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/res/layout/manage_cabinet_activity.xml 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/main/res/layout/manage_login_activity.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/app/src/test/java/com/doumee/ticketmachine/ExampleUnitTest.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keyCabinet-android/lib_coremodel/src/main/java/com/doumee/lib_coremodel/util/StringUtil.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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"
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+"");
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/base/MyBaseActivity.java
@@ -68,6 +68,7 @@
        switch (ev.getAction()) {
            //获取触摸动作,如果ACTION_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();
    }
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;
    }
}
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;
    }
}
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正常 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;
    }
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;
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正常 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;
    }
}
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;
        }
    }
}
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);
}
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正常 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;
    }
}
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();
    }
}
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;
    }
}
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;
    }
}
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;
    }
}
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/GetKeyStatusEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
package com.doumee.keyCabinet.event;
/**
 * èŽ·å–é’¥åŒ™çŠ¶æ€
 */
public class GetKeyStatusEvent {
}
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;
    }
}
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyDoorEvent.java
ÎļþÒÑɾ³ý
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;
    }
}
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/KeyStatusListener.java
ÎļþÒÑɾ³ý
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/ManageOpenGridResultEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
package com.doumee.keyCabinet.event;
//管理员开门结束
public class ManageOpenGridResultEvent {
}
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/event/OpenAllGridEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
package com.doumee.keyCabinet.event;
public class OpenAllGridEvent {
}
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;
    }
}
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;
    }
}
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;
    }
}
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);
    /**
     * æ ‡è®°æŸœæ ¼æ­£å¸¸ - ç®¡ç†å‘˜
     */
    @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);
}
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;
    }
}
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;
    }
}
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;
    }
}
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;
    }
}
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
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);
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();
                    }
                });
    }
}
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 {
                            //关门失败
                        }
                    }
                }
            }
        }
    }
}
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("苏A18829");
        list.add(b1);
        KeyCabinetBean b2 = new KeyCabinetBean();
        b2.setCabinetName("A02");
        b2.setBoardCode("1");
        b2.setChannelCode("2");
        b2.setKeyCode("000000");
        b2.setCarCode("苏A18820");
        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;
    }
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();
        }
    }
}
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());
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 è‡ªåЍ关闭");
            }
        }
    }
}
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);
                        }
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);
                }
            }
        });
    }
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);
        }
    }
    //解析钥匙数据
    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("设置门串口路径:" + 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("门串口链接:"+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("门串口链接:"+path);
                gridPort = new SerialPortModel(path,9600 ,8
                        ,1 , 0,gridReadObserver);
                boolean isSucc = gridPort.open();
                if(isSucc) {
                    getVM().addInfo("门串口链接成功:"+path);
                    String msg = isSucc ? "成功" : "失败";
                    //getVM().append("串口 "+ settingBean.getDevicePath() + " -连接"+msg);
                    gridPort.startRead();
                    //查询所有柜格门信息
                   checkGridStatus(300);
                }else {
                    getVM().addInfo("门串口链接失败:"+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("门串口链接:"+path);
            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);
                gridPort.startRead(gridReadObserver);
                //todo å‘送柜格校验信息
                chosePort.startRead();
                //发送柜格校验信息
                send485(3,"80010033B2");
            }else {
                getVM().addInfo("门串口链接失败:"+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;
    }
}
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);
    }
}
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);
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);
   }
}
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");
        }
        //以当前时间创建log文件
        /*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);   }
}
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());
                    }
                }
            }
        });
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;
    }
    /**
     * æ ¡éªŒæ•°æ®æ˜¯å¦æ­£ç¡®
     * @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));   //将String里的每一个char转换为Hex
        }
        for (i = 0; i < len; i++) {    //将每两个Hex合并成一个byte
            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) { //将单个char转换为Hex
        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();
    }
}
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"
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>
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="钥匙柜AC103、AC104、AC105、AC104、AC105、AC104、AC105、AC105、AC104、AC105开门成功,领还后请关门"
                    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>
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"
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))?"关":"开"));
        }
    }
}
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");