weimingfei
2 天以前 fab8c02a0aa8f941a507bdcb3e4d72deb6eb2242
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;
@@ -42,21 +39,28 @@
import com.bumptech.glide.request.target.Target;
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.ReLoginEvent;
import com.doumee.keyCabinet.event.OpenGridListEvent;
import com.doumee.keyCabinet.event.OpenGridOneResultEvent;
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 +91,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 +102,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 +161,7 @@
                    }
                    getVM().upBraceletLog();*/
                    case 2:
                        getVM().resetReq();
                        break;
                }
            }
@@ -269,6 +271,7 @@
        getDB().tvId.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(ManageLoginActivity.class);
                //更改url
                if(lastDownTime2!=null){
                    if(System.currentTimeMillis()-lastDownTime2>1000){
@@ -284,15 +287,40 @@
                }
            }
        });
        getDB().tvVersion.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //todo 临时代码
                setJiuConfig();
            }
        });
        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(){
        getVM().addInfo("酒精配置:"+(MApplication.getConfigBean().getCabinetConfigDataVO()!=null)+
                ",串口开启:"+(jiuPort!=null));
        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 +361,81 @@
    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){
                    Toast.makeText(mContext, "设备未添加,无法操作", Toast.LENGTH_SHORT).show();
                    getVM().devLogin();
                    return;
                }
                MApplication.getLoginBean().setFlag(type==2?0:1);
                startActivity(FaceActivity.class);
                //startActivity(KeyCabinetActivity.class,b);
                checkGridStatus(0);
                List<CabinetGridDo> gridDos = getVM().getOpenGrids();
                if (gridDos.size() > 0) {
                    showUnCloseTip(gridDos);
                    return;
                }
                MApplication.setLoginBean(null);
                MApplication.getLoginBean().setFlag(type == 2 ? 0 : 1);
                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) {
                    showUnCloseTip(gridDos);
                }else {
                    isShowTip = false;
                    getDB().clTip.setVisibility(View.GONE);
                }
                }
                break;
            case 55:
                getVM().infoObs.set("");
                break;
            default:
                break;
        }
    }
    private void showUnCloseTip(List<CabinetGridDo> gridDos){
        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().tvTip23.setText(getErrPhoneText(), TextView.BufferType.SPANNABLE);
        getDB().clTip.setVisibility(View.VISIBLE);
    }
    private SpannableString getErrPhoneText(){
        String phone = MApplication.getConfigBean().getLinkPhone();
        String text = "如有问题请联系管理员"+phone;
        SpannableString styledText = new SpannableString(text);
        styledText.setSpan(new TextAppearanceSpan(this, R.style.style_tip3), 0, text.length()-phone.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        styledText.setSpan(new TextAppearanceSpan(this,R.style.style_tip1), text.length()-phone.length()+1, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return styledText;
    }
    private boolean isShowing = false;
    @Override
    protected void onResume() {
        super.onResume();
        isShowing = true;
        showTime = System.currentTimeMillis();
        MApplication.setLoginBean(new LoginBean());
        if(!isFaceOk) {
            //initLicense();
        }
@@ -370,11 +443,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 +479,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 +511,6 @@
            }else {
                isNeedUpdateFace = true;
            }
        }
    }
    @Subscribe
    public void ReLoginEvent(ReLoginEvent event){
        if(!isFinishing()){
            handler.sendEmptyMessageDelayed(2,20000);
            getVM().devLogin();
        }
    }
@@ -626,6 +704,7 @@
    protected void onPause() {
        super.onPause();
        showTime = null;
        isShowing = false;
    }
    private int finishCount;
@@ -1005,36 +1084,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 +1136,7 @@
        getVM().devHeart();
    }
    @Subscribe
    public void HeartEvent(HeartEvent e){
        if(!isFinishing()){
@@ -1051,136 +1144,707 @@
        }
    }
    @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 {
                        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;
    }
}