weimingfei
2 天以前 fab8c02a0aa8f941a507bdcb3e4d72deb6eb2242
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/main/MainActivity.java
@@ -11,14 +11,17 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.text.style.TextAppearanceSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -36,16 +39,30 @@
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.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.ReLoginEvent;
import com.doumee.keyCabinet.event.GetKeyStatusEvent;
import com.doumee.keyCabinet.event.HeartEvent;
import com.doumee.keyCabinet.event.HttpEvent;
import com.doumee.keyCabinet.event.KeyResultEvent;
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.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;
import com.doumee.keyCabinet.ui.service.FaceUpdateService;
import com.doumee.keyCabinet.ui.service.HeartbeatService;
@@ -64,6 +81,9 @@
import com.doumee.keyCabinet.utils.face.ImportFileManager;
import com.doumee.keyCabinet.utils.face.RegisterConfigUtils;
import com.doumee.keyCabinet.utils.face.model.SingleBaseConfig;
import com.doumee.keyCabinet.utils.i485.SerialPortModel;
import com.doumee.keyCabinet.utils.i485.SerialPortReadObserver;
import com.doumee.keyCabinet.utils.i485.SportUtils;
import com.doumee.keyCabinet.utils.update.PermissionUtils;
import com.doumee.keyCabinet.utils.update.PermissiondDialog;
import com.doumee.keyCabinet.utils.update.UpdateUtil;
@@ -71,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;
@@ -83,12 +102,14 @@
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.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.Timer;
import java.util.TimerTask;
@@ -130,17 +151,17 @@
            if(!isFinishing()){
                switch (msg.what) {
                    case 0:
                    initM();
                    //initM();
                    TimeUtils.updateTimeUi(getVM().dayObs, getVM().timeObs);
                    handler.sendEmptyMessageDelayed(0, 1000);
                    EventBus.getDefault().post(new TimeClockEvent());
                    if (isDBLoad && isNeedUpdateFace && !isUpdatingFace) {
                    /*if (isDBLoad && isNeedUpdateFace && !isUpdatingFace) {
                        isNeedUpdateFace = false;
                        getVM().getFaceLD();
                    }
                    getVM().upBraceletLog();
                    getVM().upBraceletLog();*/
                    case 2:
                        getVM().resetReq();
                        break;
                }
            }
@@ -155,19 +176,21 @@
    @Override
    public void initView(@Nullable Bundle savedInstanceState) {
        //isToGuild = true;
        isAddCountTimer = false;
        SpUtil.initWH(this);
        normalConfig();
        getDB().setModel(getVM());
        //initRGBCheck();
        handler.sendEmptyMessageDelayed(0, 1000);
        //启动心跳
        Intent intent = new Intent(MainActivity.this, HeartbeatService.class);
        startService(intent);
        //启动更新人脸
        Intent intent2 = new Intent(MainActivity.this, FaceUpdateService.class);
        startService(intent2);
        //getPermission();
        //getDB().tvName.setText(String.format(getString(R.string.main_name),MApplication.getConfigBean().getName(), LMobileInfo.getDeviceUniqueId()));
        getPermission();
        Timber.tag("====>").d(LMobileInfo.getDeviceUniqueId());
        initPort();
    }
    private void initM(){
@@ -225,15 +248,79 @@
                }
            }
        });
        getDB().tv1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //管理员登录
                if(lastDownTime1!=null){
                    if(System.currentTimeMillis()-lastDownTime1>1000){
                        downCount1=0;
                    }
                }
                lastDownTime1 = System.currentTimeMillis();
                downCount1++;
                System.out.println();
                Timber.tag("==>").d(""+downCount1);
                if(downCount1>4) {
                    downCount1=0;
                    lastDownTime1=null;
                    startActivity(ManageLoginActivity.class);
                }
            }
        });
        getDB().tvId.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(ManageLoginActivity.class);
                //更改url
                if(lastDownTime2!=null){
                    if(System.currentTimeMillis()-lastDownTime2>1000){
                        downCount2=0;
                    }
                }
                lastDownTime2 = System.currentTimeMillis();
                downCount2++;
                if(downCount2>4) {
                    downCount2=0;
                    lastDownTime2=null;
                    startActivity(ChangeUrlActivity.class);
                }
            }
        });
        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() {
@@ -273,56 +360,82 @@
    @Override
    protected void doRegister(int type, ActionEventData data) {
        switch (type){
            case 1:
                {
                    //管理员登录
                    if(lastDownTime1!=null){
                        if(System.currentTimeMillis()-lastDownTime1>1000){
                            downCount1=0;
                        }
                    }
                    lastDownTime1 = System.currentTimeMillis();
                    downCount1++;
                    if(downCount1>4) {
                        downCount1=0;
                        lastDownTime1=null;
                        startActivity(ManageLoginActivity.class);
                    }
                }
                break;
            case 2:
            case 3:
                Bundle b = new Bundle();
                b.putString("flag",type==2?"0":"1");
                startActivity(FaceActivity.class,b);
            case 3: {
                //校验是否登录
                if(MApplication.getConfigBean().getId()==null){
                    Toast.makeText(mContext, "设备未添加,无法操作", Toast.LENGTH_SHORT).show();
                    getVM().devLogin();
                    return;
                }
                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:
                {
                    //更改url
                    if(lastDownTime2!=null){
                        if(System.currentTimeMillis()-lastDownTime2>1000){
                            downCount2=0;
                        }
                    }
                    lastDownTime2 = System.currentTimeMillis();
                    downCount2++;
                    if(downCount2>4) {
                        downCount2=0;
                        lastDownTime2=null;
                        startActivity(ChangeUrlActivity.class);
                    }
                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.saveMemberBean(new MemberBean());
        if(!isFaceOk) {
            //initLicense();
        }
@@ -330,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));
        }
    }
@@ -355,11 +477,17 @@
        handler = null;
        faceHandler.removeCallbacksAndMessages(null);
        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包装启动意图
@@ -383,14 +511,6 @@
            }else {
                isNeedUpdateFace = true;
            }
        }
    }
    @Subscribe
    public void ReLoginEvent(ReLoginEvent event){
        if(!isFinishing()){
            handler.sendEmptyMessageDelayed(2,20000);
            getVM().devLogin();
        }
    }
@@ -584,6 +704,7 @@
    protected void onPause() {
        super.onPause();
        showTime = null;
        isShowing = false;
    }
    private int finishCount;
@@ -606,14 +727,6 @@
                            //结束
                            isUpdatingFace = false;
                            //System.out.println("==UpdatingFace==>更新结束:");
                            FaceUserBean bean = selectBeans.get(selectBeans.size()-1);
                            if(!TextUtils.isEmpty(bean.getEditTime())){
                                Date date = StringUtil.StrToDate(bean.getEditTime());
                                Calendar cal = Calendar.getInstance();
                                cal.setTime(date);
                                cal.add(Calendar.SECOND,1);
                                SpUtil.saveString("LastTime",StringUtil.DateToStr(cal.getTime()));
                            }
                            // 清除内存缓存
                            Glide.get(MainActivity.this).clearMemory();
                        }
@@ -642,7 +755,7 @@
    private int repeatCount = 0;
    private void updateFace(FaceUserBean bean){
        Timber.d("==UpdatingFace==>完成数量 "+finishCount);
        if (TextUtils.isEmpty(bean.getFaceUrl())||bean.getFaceUrl().endsWith("null")) {
        if (TextUtils.isEmpty(bean.getFaceImg())||bean.getFaceImg().endsWith("null")) {
            finishCount++;
            faceHandler.sendEmptyMessage(0);
            return;
@@ -651,7 +764,7 @@
        //System.out.println("==UpdatingFace==>开始:" + bean.getName());
        Glide.with(this)
                .asBitmap()
                .load(bean.getFaceUrl())
                .load(bean.getFaceImg())
                .addListener(new RequestListener<Bitmap>() {
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
@@ -695,10 +808,10 @@
                                if (ret == 128) {
                                    Timber.d("==UpdatingFace==>图片特征抽取成功: %s", JSON.toJSONString(bean));
                                    User user = new User();
                                    user.setUserId(bean.getId());
                                    user.setGroupId(bean.getType());
                                    user.setUserName(bean.getName());
                                    user.setImageName(bean.getFaceUrl());
                                    user.setUserId(bean.getMemberId());
                                    user.setGroupId(bean.getGroupId());
                                    user.setUserName(bean.getMemberName());
                                    user.setImageName(bean.getFaceImg());
                                    user.setUserInfo(GsonTools.changeGsonToJson(bean));
                                    user.setFeature(secondFeature);
                                    insertOrUpdate(user);
@@ -952,12 +1065,70 @@
        }
    }
    private int tipDownCount = 10;
    private boolean isShowTip;
    @Subscribe
    public void TimeClockEvent(TimeClockEvent e){
        if(isShowTip){
            if(tipDownCount==0){
                isShowTip = false;
                getDB().clTip.setVisibility(View.GONE);
            }else {
                tipDownCount--;
                getDB().tvDjs.setText(tipDownCount+"s");
            }
        }
    }
    /**
     * 监听开门
     * @param e
     */
    @Subscribe(threadMode=ThreadMode.MAIN)
    public void OpenGridEvent(OpenGridEvent e){
        if(!isFinishing()){
            //开启柜门
            String code = "8A"+SportUtils.intToHex(Integer.parseInt(e.getBoardCode()))
                    +SportUtils.intToHex(Integer.parseInt(e.getChannelCode()))+"11";
            code += SportUtils.getBCC(code);
            send485(0,code);
        }
    }
    //柜门全开
    @Subscribe(threadMode=ThreadMode.MAIN)
    public void OpenAllGridEvent(OpenAllGridEvent e){
        if(!isFinishing()){
            //开启柜门
            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+"柜门";
        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;
    }
    @Override
    protected void onRestart() {
@@ -966,5 +1137,714 @@
    }
    @Subscribe
    public void HeartEvent(HeartEvent e){
        if(!isFinishing()){
            getVM().devHeart();
        }
    }
    @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(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(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(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--;
                        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(){
        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(){
        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);
                chosePort.startRead();
                //发送柜格校验信息
                send485(3,"80010033B2");
            }else {
                getVM().addInfo("门串口链接失败:"+path);
            }
            portHandler.sendEmptyMessageDelayed(5,1500);
            return;
        }
        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);
                chosePort.startRead();
                //发送钥匙校验信息
                send485(3,"A001010000000002");
            }else {
                getVM().addInfo("钥匙串口链接失败:"+path);
            }
            portHandler.sendEmptyMessageDelayed(5,1500);
            return;
        }
        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);
                chosePort.startRead();
                //发送酒精校验信息
                send485(4,"read");
            }else {
                getVM().addInfo("酒精串口链接失败:"+path);
            }
            portHandler.sendEmptyMessageDelayed(5,1500);
            return;
        }
        portHandler.sendEmptyMessageDelayed(0,0);
    }
    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){
        try {
            if(port==null){
                return;
            }
            port.stopRead();
            port.close();
            port = null;
        }catch (Exception e){
        }
    }
    private boolean checkEnd(){
        if(TextUtils.isEmpty(gridPath)){
            getVM().addInfo("门错误");
            startIndex=0;
            return false;
        }
        if(TextUtils.isEmpty(keyPath)){
            getVM().addInfo("钥匙错误");
            startIndex=1;
            return false;
        }
        if(TextUtils.isEmpty(jiuPath)){
            getVM().addInfo("酒精错误");
            startIndex=2;
            return false;
        }
        getVM().addInfo("串口全部链接成功:");
        return true;
    }
}