|  |  | 
 |  |  | import android.graphics.Bitmap; | 
 |  |  | import android.graphics.drawable.BitmapDrawable; | 
 |  |  | import android.hardware.Camera; | 
 |  |  | import android.opengl.Visibility; | 
 |  |  | 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; | 
 |  |  | 
 |  |  |  | 
 |  |  | import com.alibaba.fastjson.JSON; | 
 |  |  | import com.baidu.idl.main.facesdk.model.BDFaceSDKCommon; | 
 |  |  | import com.baidu.idl.main.facesdk.utils.StreamUtil; | 
 |  |  | import com.bigkoo.convenientbanner.holder.CBViewHolderCreator; | 
 |  |  | import com.bumptech.glide.Glide; | 
 |  |  | import com.bumptech.glide.load.DataSource; | 
 |  |  | 
 |  |  | 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.JiujinBeginEvent; | 
 |  |  | import com.doumee.keyCabinet.event.JiujinResultEvent; | 
 |  |  | 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; | 
 |  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  | 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.math.BigDecimal; | 
 |  |  | 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; | 
 |  |  | import java.util.concurrent.Executors; | 
 |  |  | import java.util.concurrent.Future; | 
 |  |  | import java.util.regex.Matcher; | 
 |  |  | import java.util.regex.Pattern; | 
 |  |  |  | 
 |  |  | import dagger.hilt.android.AndroidEntryPoint; | 
 |  |  | import timber.log.Timber; | 
 |  |  | 
 |  |  |                     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; | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public void initView(@Nullable Bundle savedInstanceState) { | 
 |  |  |         //isToGuild = true; | 
 |  |  |         isAddCountTimer = false; | 
 |  |  |         SpUtil.initWH(this); | 
 |  |  |         normalConfig(); | 
 |  |  |         getDB().setModel(getVM()); | 
 |  |  |         //initRGBCheck(); | 
 |  |  |         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()); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void initM(){ | 
 |  |  | 
 |  |  |         if((availableMemory<400&&showTime!=null&&(System.currentTimeMillis()-showTime>5000))|| | 
 |  |  |                 ("02:00:00".equals(StringUtil.getHM()))){ | 
 |  |  |             //可用内存小于400M,或者每天凌晨2点,重启app | 
 |  |  |             restartApp(); | 
 |  |  |             //restartApp(); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         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(); | 
 |  |  |                 SpUtil.saveString("rbgCameraId","0"); | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         getDB().imgLeft.setOnClickListener(new View.OnClickListener() { | 
 |  |  |             @Override | 
 |  |  |             public void onClick(View v) { | 
 |  |  |                 //todo 临时代码 | 
 |  |  |                 if (getDB().nsv.getVisibility()== View.VISIBLE) { | 
 |  |  |                     getDB().nsv.setVisibility(View.GONE); | 
 |  |  |                 }else { | 
 |  |  |                     getDB().nsv.setVisibility(View.VISIBLE); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         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(); | 
 |  |  |                     initPort(); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     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() { | 
 |  |  | 
 |  |  |     @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(FaceActivity.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(); | 
 |  |  |             initLicense(); | 
 |  |  |         } | 
 |  |  |         if(isHavePermission) { | 
 |  |  |             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)); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |         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包装启动意图 | 
 |  |  | 
 |  |  |             }else { | 
 |  |  |                 isNeedUpdateFace = true; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Subscribe | 
 |  |  |     public void ReLoginEvent(ReLoginEvent event){ | 
 |  |  |         if(!isFinishing()){ | 
 |  |  |             handler.sendEmptyMessageDelayed(2,20000); | 
 |  |  |             getVM().devLogin(); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |     protected void onPause() { | 
 |  |  |         super.onPause(); | 
 |  |  |         showTime = null; | 
 |  |  |         isShowing = false; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private int finishCount; | 
 |  |  | 
 |  |  |                             //结束 | 
 |  |  |                             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(); | 
 |  |  |                         } | 
 |  |  | 
 |  |  |     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; | 
 |  |  | 
 |  |  |         //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) { | 
 |  |  | 
 |  |  |                                 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().toString()); | 
 |  |  |                                     user.setGroupId(bean.getGroupId()); | 
 |  |  |                                     user.setUserName(bean.getMemberName()); | 
 |  |  |                                     user.setImageName(bean.getFaceImg()); | 
 |  |  |                                     user.setUserInfo(GsonTools.changeGsonToJson(bean)); | 
 |  |  |                                     user.setFeature(secondFeature); | 
 |  |  |                                     insertOrUpdate(user); | 
 |  |  | 
 |  |  |         popupWindow.showAtLocation(getDB().clRoot, Gravity.CENTER, 0, 0); | 
 |  |  |         RelativeLayout relativeRegister = contentView.findViewById(R.id.relative_register); | 
 |  |  |         RelativeLayout mPopRelativeManager = contentView.findViewById(R.id.relative_manager); | 
 |  |  |         RelativeLayout mPopRelativeCamra = contentView.findViewById(R.id.relative_camra); | 
 |  |  |         RelativeLayout mRlErr = contentView.findViewById(R.id.rl_err); | 
 |  |  |         relativeRegister.setOnClickListener(new View.OnClickListener() { | 
 |  |  |             @Override | 
 |  |  | 
 |  |  |             @Override | 
 |  |  |             public void onClick(View v) { | 
 |  |  |                 startActivity(UserManagerActivity.class); | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         mPopRelativeCamra.setOnClickListener(new View.OnClickListener() { | 
 |  |  |             @Override | 
 |  |  |             public void onClick(View v) { | 
 |  |  |                 //startActivity(); | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |         mRlErr.setOnClickListener(new View.OnClickListener() { | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void initRGBCheck(){ | 
 |  |  |         if(true){ | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         String index = SpUtil.getString("rbgCameraId"); | 
 |  |  |         if(index==null){ | 
 |  |  |         if(!"1".equals(index)){ | 
 |  |  |             index = "0"; | 
 |  |  |         } | 
 |  |  |         setRgbCameraId(Integer.parseInt(index)); | 
 |  |  |         /*if (isSetCameraId()){ | 
 |  |  |             setRgbCameraId(SingleBaseConfig.getBaseConfig().getRBGCameraId()); | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         int mCameraNum = Camera.getNumberOfCameras(); | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void setRgbCameraId(int index){ | 
 |  |  |         getVM().addInfo("设置相机:"+index); | 
 |  |  |         //Toast.makeText(mContext, "设置相机"+index, Toast.LENGTH_SHORT).show(); | 
 |  |  |         SpUtil.saveString("rbgCameraId",index+""); | 
 |  |  |         BraceletLogUtils.saveLog("设置相机("+index+")"); | 
 |  |  | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     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() { | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     @Subscribe | 
 |  |  |     public void HeartEvent(HeartEvent e){ | 
 |  |  |         if(!isFinishing()){ | 
 |  |  |             getVM().devHeart(); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Subscribe(threadMode = ThreadMode.MAIN) | 
 |  |  |     public void JiujinBeginEvent(JiujinBeginEvent e){ | 
 |  |  |         if(!isFinishing()){ | 
 |  |  |             //开启酒精检测 | 
 |  |  |             sendPortHandlerMsg(3,"go_wnd:0",0); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     @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(isFinishing()){ | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |             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().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); | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                         runOnUiThread(() -> { | 
 |  |  |                             getVM().addInfo("更新库数据:版号:" +bh+","+ addList.size()+","+updateList.size()); | 
 |  |  |                         }); | 
 |  |  |                         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(isFinishing()){ | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |             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); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         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(isFinishing()){ | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |             if(bytes.length==0){ | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |             try { | 
 |  |  |                 runOnUiThread(() -> { | 
 |  |  |                     getVM().addInfo("获取到酒精检测数据:"+StringUtil.DateToStrSS(new Date())+" " + new String(bytes)); | 
 |  |  |                 }); | 
 |  |  |                 String data = new String(bytes); | 
 |  |  |                 runOnUiThread(() -> { | 
 |  |  |                     getVM().addInfo("获取到酒精检测是否检测失败:" + (data.contains("blow fail"))); | 
 |  |  |                 }); | 
 |  |  |                 if(data.contains("blow fail")){ | 
 |  |  |                     //检测失败 | 
 |  |  |                     EventBus.getDefault().post(new JiujinResultEvent(false,null)); | 
 |  |  |                 }else if(data.startsWith("Result:")){ | 
 |  |  |                     Pattern pattern = Pattern.compile("([0-9]+\\.[0-9]+)"); | 
 |  |  |                     Matcher matcher = pattern.matcher(data); | 
 |  |  |                     if (matcher.find()) { | 
 |  |  |                         EventBus.getDefault().post(new JiujinResultEvent(true,new BigDecimal(matcher.group(1)))); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             }catch (Exception e){ | 
 |  |  |                 getVM().addInfo("获取到酒精检测报错:" + e.getMessage()); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     }; | 
 |  |  |     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); | 
 |  |  |  | 
 |  |  |         sendPortHandlerMsg(3,"read"+config.getThreshold(),time+1200); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     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; | 
 |  |  |     } | 
 |  |  | } |