| package com.doumee.keyCabinet.ui.main; | 
|   | 
| import android.app.ActivityManager; | 
| import android.app.AlarmManager; | 
| import android.app.PendingIntent; | 
| import android.content.Context; | 
| import android.content.Intent; | 
| import android.graphics.Bitmap; | 
| import android.graphics.PixelFormat; | 
| import android.graphics.drawable.BitmapDrawable; | 
| import android.hardware.Camera; | 
| import android.opengl.Visibility; | 
| import android.os.Build; | 
| 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.text.style.TextAppearanceSpan; | 
| import android.view.Gravity; | 
| import android.view.LayoutInflater; | 
| import android.view.View; | 
| import android.view.ViewGroup; | 
| import android.view.WindowManager; | 
| import android.widget.PopupWindow; | 
| import android.widget.RelativeLayout; | 
| import android.widget.TextView; | 
| import android.widget.Toast; | 
|   | 
| import androidx.annotation.NonNull; | 
| import androidx.annotation.Nullable; | 
| import androidx.lifecycle.Observer; | 
|   | 
| 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.load.engine.GlideException; | 
| import com.bumptech.glide.request.RequestListener; | 
| import com.bumptech.glide.request.target.SimpleTarget; | 
| import com.bumptech.glide.request.target.Target; | 
| import com.bumptech.glide.request.transition.Transition; | 
| import com.doumee.keyCabinet.BuildConfig; | 
| 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.CheckGridStatusEvent; | 
| import com.doumee.keyCabinet.event.CloseGridOneResultEvent; | 
| import com.doumee.keyCabinet.event.GetFacesEvent; | 
| import com.doumee.keyCabinet.event.GetKeyStatusEvent; | 
| import com.doumee.keyCabinet.event.HeartEvent; | 
| import com.doumee.keyCabinet.event.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.OpenErrEvent; | 
| 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.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.ui.face.AddFaceActivity; | 
| import com.doumee.keyCabinet.ui.face.ErrActivity; | 
| import com.doumee.keyCabinet.ui.face.UserInfoManager; | 
| import com.doumee.keyCabinet.ui.face.UserManagerActivity; | 
| import com.doumee.keyCabinet.ui.view.BannerViewImageHolder; | 
| import com.doumee.keyCabinet.utils.BraceletLogUtils; | 
| import com.doumee.keyCabinet.utils.CircularQueue; | 
| import com.doumee.keyCabinet.utils.CrashHandler; | 
| import com.doumee.keyCabinet.utils.LMobileInfo; | 
| import com.doumee.keyCabinet.utils.TimeUtils; | 
| import com.doumee.keyCabinet.utils.face.FaceSDKManager; | 
| import com.doumee.keyCabinet.utils.face.FaceUtils; | 
| import com.doumee.keyCabinet.utils.face.GateConfigUtils; | 
| 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.lib_coremodel.bean.event.ActionEventData; | 
| import com.doumee.keyCabinet.MApplication; | 
| import com.doumee.keyCabinet.R; | 
| import com.doumee.keyCabinet.base.MyBaseActivity; | 
| import com.doumee.keyCabinet.utils.AdListResponseParam; | 
| import com.doumee.lib_coremodel.http.utils.GsonTools; | 
| import com.doumee.lib_coremodel.util.SpUtil; | 
| import com.doumee.lib_coremodel.util.StringUtil; | 
| import com.doumee.lib_coremodel.view.ToastView; | 
| import com.example.datalibrary.api.FaceApi; | 
| import com.example.datalibrary.listener.DBLoadListener; | 
| import com.example.datalibrary.listener.SdkInitListener; | 
| import com.example.datalibrary.model.ImportFeatureResult; | 
| import com.example.datalibrary.model.User; | 
| import com.example.datalibrary.utils.ToastUtils; | 
| import com.example.datalibrary.view.PreviewTexture; | 
| import com.innohi.YNHAPI; | 
| 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.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; | 
|   | 
| import static android.Manifest.permission.RECEIVE_BOOT_COMPLETED; | 
|   | 
| @AndroidEntryPoint | 
| public class MainActivity extends MyBaseActivity<MainVM, MainActivityBinding> { | 
|     private List<AdListResponseParam> lbs = new ArrayList<>(); | 
|     //是否已激活 | 
|     public static boolean isFaceOk = false; | 
|     private boolean isActivation = false; | 
|     private boolean isDBLoad; | 
|     private PopupWindow popupWindow; | 
|     private Future future; | 
|   | 
|     //相机相关 | 
|     private Camera[] mCamera; | 
|     private PreviewTexture[] previewTextures; | 
|     private static final int PREFER_WIDTH = 640; | 
|     private static final int PREFER_HEIGHT = 480; | 
|     //是否有要更新人脸 | 
|     private boolean isNeedUpdateFace; | 
|     //是否正在更新中 | 
|     private boolean isUpdatingFace; | 
|     private boolean isUpdateVersion; | 
|     private int downCount = 0; | 
|     private Long lastDownTime; | 
|     private Long showTime; | 
|   | 
|     private Handler handler = new Handler(){ | 
|         @Override | 
|         public void handleMessage(@NonNull Message msg) { | 
|             if(!isFinishing()){ | 
|                 switch (msg.what) { | 
|                     case 0: | 
|                     initM(); | 
|                     TimeUtils.updateTimeUi(getVM().dayObs, getVM().timeObs); | 
|                     handler.sendEmptyMessageDelayed(0, 1000); | 
|                     EventBus.getDefault().post(new TimeClockEvent()); | 
|                     /*if (isDBLoad && isNeedUpdateFace && !isUpdatingFace) { | 
|                         isNeedUpdateFace = false; | 
|                         getVM().getFaceLD(); | 
|                     } | 
|                     getVM().upBraceletLog();*/ | 
|                     case 1: | 
|                         if(isShowing) { | 
|                             EventBus.getDefault().post(new OpenGridEvent((String) msg.obj)); | 
|                             handler.sendEmptyMessageDelayed(1, 1000); | 
|                         } | 
|                         break; | 
|                     case 2: | 
|                         if(isShowing){ | 
|                             //重新发送钥匙查询 | 
|                             //发送查询钥匙号 | 
|                             EventBus.getDefault().post(new GetKeyStatusEvent()); | 
|                             handler.sendEmptyMessageDelayed(2,1200); | 
|                         } | 
|                         break; | 
|                     default: | 
|                         break; | 
|                 } | 
|             } | 
|         } | 
|     }; | 
|   | 
|   | 
|     @Override | 
|     public int getLayoutId() { | 
|         return R.layout.main_activity; | 
|     } | 
|   | 
|     @Override | 
|     public void initView(@Nullable Bundle savedInstanceState) { | 
|         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(); | 
|         Timber.tag("====>").d(LMobileInfo.getDeviceUniqueId()); | 
|     } | 
|   | 
|     private void initM(){ | 
|         ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); | 
|         ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); | 
|         activityManager.getMemoryInfo(memoryInfo); | 
|   | 
|         long totalMemory = memoryInfo.totalMem/(1024*1024); | 
|         long availableMemory = memoryInfo.availMem/(1024*1024); | 
|         long usedMemory = totalMemory - availableMemory; | 
|         //getDB().tvM.setText("总内存:"+totalMemory+",使用内存:"+usedMemory+",可用内存:"+availableMemory); | 
|         if((availableMemory<100&&showTime!=null&&(System.currentTimeMillis()-showTime>5000))|| | 
|                 ("02:00:00".equals(StringUtil.getHM()))){ | 
|             //可用内存小于400M,或者每天凌晨2点,重启app | 
|             restartApp(); | 
|         } | 
|     } | 
|   | 
|     private void upErrInfo(){ | 
|         List<SpUtil.SPBean> datas = SpUtil.getMatchingStrings(CrashHandler.FILE_NAME); | 
|         for(SpUtil.SPBean data : datas){ | 
|             getVM().upErrInfo(data); | 
|         } | 
|     } | 
|   | 
|     @Override | 
|     public void initData(@Nullable Bundle savedInstanceState) { | 
|         //handler.sendEmptyMessageDelayed(0,1000); | 
|         getDB().tvId.setText("NO:"+LMobileInfo.getDeviceUniqueId()); | 
|         getDB().tvVersion.setText("V"+BuildConfig.VERSION_NAME); | 
|         getVM().getFaceLD().observe(this, new Observer<List<FaceUserBean>>() { | 
|             @Override | 
|             public void onChanged(List<FaceUserBean> beans) { | 
|                 //更新人脸数据 | 
|                 if(beans!=null&&beans.size()>0){ | 
|                     initModel(beans); | 
|                 } | 
|             } | 
|         }); | 
|         getDB().img.setOnClickListener(new View.OnClickListener() { | 
|             @Override | 
|             public void onClick(View v) { | 
|                 if(lastDownTime!=null){ | 
|                     if(System.currentTimeMillis()-lastDownTime>1000){ | 
|                         downCount=0; | 
|                     } | 
|                 } | 
|                 lastDownTime = System.currentTimeMillis(); | 
|                 Timber.d("downCount="+downCount); | 
|                 downCount++; | 
|                 if(downCount>4) { | 
|                     downCount=0; | 
|                     lastDownTime=null; | 
|                     initPopupWindow(); | 
|                 } | 
|             } | 
|         }); | 
|         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) { | 
|                 //更改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().imgLeft.setOnClickListener(new View.OnClickListener() { | 
|             @Override | 
|             public void onClick(View v1) { | 
|                 //todo 临时代码 | 
|                 if (getDB().nsv.getVisibility()== View.VISIBLE) { | 
|                     getDB().nsv.setVisibility(View.GONE); | 
|                 }else { | 
|                     getDB().nsv.setVisibility(View.VISIBLE); | 
|                 } | 
|                 YNHAPI mAPI = YNHAPI.getInstance(); | 
|                 mAPI.setNavigationBarVisibility(YNHAPI.NavigationBarVisibility.VISIBLE); | 
|             } | 
|         }); | 
|         upErrInfo(); | 
|         getVM().devLogin(); | 
|         getVM().devHeart(); | 
|         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<String> bannerList){ | 
|         getDB().banner.setPages(new CBViewHolderCreator<BannerViewImageHolder>() { | 
|             @Override | 
|             public BannerViewImageHolder createHolder() { | 
|                 return new BannerViewImageHolder(); | 
|             } | 
|         },bannerList ).setPageIndicator(new int[]{R.drawable.bg_dot_gray, R.drawable.bg_dot_blue}); | 
|         isOne = bannerList.size()==1; | 
|         if(!isOne) { | 
|             getDB().banner.startTurning(3000); | 
|         }else { | 
|             getDB().banner.stopTurning(); | 
|         } | 
|     } | 
|   | 
|     private boolean isHavePermission = false; | 
|     //获取权限 | 
|     private void getPermission(){ | 
|         PermissionUtils.getPermission(this, new PermissionUtils.CallBack() { | 
|             @Override | 
|             public void sucess() { | 
|                 //显示 | 
|                 isHavePermission = true; | 
|                 checkUpdate(); | 
|             } | 
|   | 
|             @Override | 
|             public void fail(List<String> permissions) { | 
|                 showNoPermissionTip(); | 
|             } | 
|         }, new String[]{Permission.WRITE_EXTERNAL_STORAGE,RECEIVE_BOOT_COMPLETED}); | 
|     } | 
|   | 
|     private Long lastDownTime1; | 
|     private int downCount1; | 
|     private Long lastDownTime2; | 
|     private int downCount2; | 
|     @Override | 
|     protected void doRegister(int type, ActionEventData data) { | 
|         switch (type){ | 
|             case 2: | 
|             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: | 
|                 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; | 
|         YNHAPI mAPI = YNHAPI.getInstance(); | 
|         mAPI.setNavigationBarVisibility(YNHAPI.NavigationBarVisibility.ALWAYS_INVISIBLE); | 
|         mAPI.setBootLaunchApk("com.doumee.keyCabinet", true); | 
|         showTime = System.currentTimeMillis(); | 
|         if(!isFaceOk) { | 
|             initLicense(); | 
|         } | 
|         if(isHavePermission) { | 
|             checkUpdate(); | 
|         } | 
|         triggerGarbageCollection(); | 
|   | 
|         if(!isOne) { | 
|             getDB().banner.startTurning(3000); | 
|         }else { | 
|             getDB().banner.stopTurning(); | 
|         } | 
|         //检查所有柜格门、钥匙状态 | 
|         checkKeyStatus(0); | 
|         checkGridStatus(900); | 
|     } | 
|   | 
|     private void unCloseGrid(){ | 
|         //未关门,调用接口 | 
|         List<CabinetGridDo> gridDos = getVM().getOpenGrids(); | 
|         if(gridDos.size()>0){ | 
|             getVM().timeOutUnCloseAlarm(gridDos.get(0)); | 
|         } | 
|     } | 
|   | 
|     // 这是一个示例方法,用于手动触发垃圾回收 | 
|     public void triggerGarbageCollection() { | 
|         // 请求进行垃圾回收 | 
|         System.gc(); | 
|     } | 
|   | 
|     @Override | 
|     protected void onDestroy() { | 
|         super.onDestroy(); | 
|         if (future != null && !future.isDone()) { | 
|             future.cancel(true); | 
|         } | 
|         FaceApi.getInstance().cleanRecords(); | 
|         handler.removeCallbacksAndMessages(null); | 
|         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, MainActivity.class); | 
|         // 设置FLAG_ACTIVITY_CLEAR_TASK标志位 | 
|         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); | 
|         // 使用PendingIntent包装启动意图 | 
|         PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); | 
|         // 获取AlarmManager实例 | 
|         AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); | 
|         // 在500毫秒后触发重启操作 | 
|         alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 10, pendingIntent); | 
|   | 
|         android.os.Process.killProcess(android.os.Process.myPid()); | 
|         System.exit(1); | 
|     } | 
|   | 
|     @Subscribe | 
|     public void GetFacesEvent(GetFacesEvent event){ | 
|         if(!isFinishing()&&!isUpdatingFace){ | 
|             if(isDBLoad){ | 
|                 isNeedUpdateFace = false; | 
|                 //查询人脸 | 
|                 getVM().getFaceDatas(); | 
|             }else { | 
|                 isNeedUpdateFace = true; | 
|             } | 
|         } | 
|     } | 
|   | 
|     //判断设备是否已激活 | 
|     private void initLicense() { | 
|         FaceSDKManager.getInstance().init(mContext, new SdkInitListener() { | 
|             @Override | 
|             public void initStart() { | 
|   | 
|             } | 
|   | 
|             public void initLicenseSuccess() { | 
|                 //已激活 | 
|                 isFaceOk = true; | 
|                 initDBApi(); | 
|             } | 
|   | 
|             @Override | 
|             public void initLicenseFail(int errorCode, String msg) { | 
|                 //未激活,跳转激活页面 | 
|                 TimerTask task = new TimerTask() { | 
|                     @Override | 
|                     public void run() { | 
|                         /* | 
|                          *要执行的操作*/ | 
|   | 
|                         startActivity(new Intent(mContext, ActivationActivity.class)); | 
|                     } | 
|                 }; | 
|                 Timer timer = new Timer(); | 
|                 timer.schedule(task, 2000); | 
|             } | 
|   | 
|             @Override | 
|             public void initModelSuccess() { | 
|   | 
|             } | 
|   | 
|             @Override | 
|             public void initModelFail(int errorCode, String msg) { | 
|   | 
|             } | 
|         }); | 
|     } | 
|   | 
|     private void initDBApi(){ | 
|         if (future != null && !future.isDone()) { | 
|             future.cancel(true); | 
|         } | 
|         isDBLoad = false; | 
|         future = Executors.newSingleThreadExecutor().submit(new Runnable() { | 
|             @Override | 
|             public void run() { | 
|                 FaceApi.getInstance().init(new DBLoadListener() { | 
|   | 
|                     @Override | 
|                     public void onStart(int successCount) { | 
|                         if (successCount < 5000 && successCount != 0){ | 
|   | 
|                             runOnUiThread(new Runnable() { | 
|                                 @Override | 
|                                 public void run() { | 
|                                     loadProgress(10); | 
|                                 } | 
|                             }); | 
|                         } | 
|                     } | 
|   | 
|                     @Override | 
|                     public void onLoad(final int finishCount, final int successCount, final float progress) { | 
|                         if (successCount > 5000 || successCount == 0) { | 
|                             runOnUiThread(new Runnable() { | 
|                                 @Override | 
|                                 public void run() { | 
|                                     getDB().progressBar.setProgress((int) (progress * 100)); | 
|                                     getDB().progressText.setText(((int) (progress * 100)) + "%"); | 
|                                 } | 
|                             }); | 
|                         } | 
|                     } | 
|   | 
|                     @Override | 
|                     public void onComplete(final List<User> users , final int successCount) { | 
| //                        FileUtils.saveDBList(HomeActivity.this, users); | 
|                         runOnUiThread(new Runnable() { | 
|                             @Override | 
|                             public void run() { | 
|                                 FaceApi.getInstance().setUsers(users); | 
|                                 initFaceSDKManager(null); | 
|                                 if (successCount > 5000 || successCount == 0) { | 
|                                     getDB().progressGroup.setVisibility(View.GONE); | 
|                                     isDBLoad = true; | 
|                                     isFaceOk = true; | 
|                                 } | 
|                             } | 
|                         }); | 
|                     } | 
|   | 
|                     @Override | 
|                     public void onFail(final int finishCount, final int successCount, final List<User> users) { | 
|                         runOnUiThread(new Runnable() { | 
|                             @Override | 
|                             public void run() { | 
|                                 FaceApi.getInstance().setUsers(users); | 
|                                 initFaceSDKManager(null); | 
|                                 getDB().progressGroup.setVisibility(View.GONE); | 
|                                 Toast.makeText(MainActivity.this, String.format(getString(R.string.main_tip3),successCount,finishCount), Toast.LENGTH_SHORT).show(); | 
|                                 isDBLoad = true; | 
|                                 isFaceOk = true; | 
|                             } | 
|                         }); | 
|                     } | 
|                 }, mContext); | 
|             } | 
|         }); | 
|     } | 
|   | 
|     private void loadProgress(float i){ | 
|         getDB().progressGroup.setVisibility(View.VISIBLE); | 
|         new Handler().postDelayed(new Runnable() { | 
|             @Override | 
|             public void run() { | 
|                 getDB().progressBar.setProgress((int) ((i / 5000f) * 100)); | 
|                 getDB().progressText.setText(((int) ((i / 5000f) * 100)) + "%"); | 
|                 if (i < 5000){ | 
|                     loadProgress(i + 100); | 
|                 }else { | 
|                     getDB().progressGroup.setVisibility(View.GONE); | 
|                     isDBLoad = true; | 
|                     isFaceOk = true; | 
|                 } | 
|             } | 
|         },10); | 
|     } | 
|   | 
|     private void initModel(List<FaceUserBean> userBeans) { | 
|         if (com.example.datalibrary.manager.FaceSDKManager.initStatus == com.example.datalibrary.manager.FaceSDKManager.SDK_MODEL_LOAD_SUCCESS) { | 
|             waitUpdate(userBeans); | 
|         }else { | 
|             initFaceSDKManager(userBeans); | 
|         } | 
|     } | 
|   | 
|     private void initFaceSDKManager(List<FaceUserBean> userBeans){ | 
|         //开始后去初始化 | 
|         com.example.datalibrary.manager.FaceSDKManager.getInstance().initModel(mContext, | 
|                 FaceUtils.getInstance().getBDFaceSDKConfig() , new SdkInitListener() { | 
|                     @Override | 
|                     public void initStart() { | 
|                     } | 
|   | 
|                     @Override | 
|                     public void initLicenseSuccess() { | 
|                     } | 
|   | 
|                     @Override | 
|                     public void initLicenseFail(int errorCode, String msg) { | 
|                     } | 
|   | 
|                     @Override | 
|                     public void initModelSuccess() { | 
|                         com.example.datalibrary.manager.FaceSDKManager.initModelSuccess = true; | 
|                         runOnUiThread(new Runnable() { | 
|                             @Override | 
|                             public void run() { | 
|                                 Toast.makeText(mContext, getString(R.string.main_tip4), Toast.LENGTH_SHORT).show(); | 
|                                 getDB().progressGroup.setVisibility(View.GONE); | 
|                                 if(userBeans!=null){ | 
|                                     waitUpdate(userBeans); | 
|                                 } | 
|                             } | 
|                         }); | 
|                     } | 
|   | 
|                     @Override | 
|                     public void initModelFail(int errorCode, String msg) { | 
|                         com.example.datalibrary.manager.FaceSDKManager.initModelSuccess = false; | 
|                         if (errorCode != -12) { | 
|                             runOnUiThread(new Runnable() { | 
|                                 @Override | 
|                                 public void run() { | 
|                                     Toast.makeText(mContext, getString(R.string.main_tip5), Toast.LENGTH_SHORT).show(); | 
|                                 } | 
|                             }); | 
|                         } | 
|                     } | 
|                 }); | 
|     } | 
|   | 
|     @Override | 
|     protected void onPause() { | 
|         super.onPause(); | 
|         showTime = null; | 
|         isShowing = false; | 
|     } | 
|   | 
|     private int finishCount; | 
|     private List<FaceUserBean> selectBeans = new ArrayList<>(); | 
|     //待更新数据 | 
|     private List<FaceUserBean> waitBeans = new ArrayList<>(); | 
|   | 
|     private Handler faceHandler = new Handler(){ | 
|   | 
|         @Override | 
|         public void handleMessage(@NonNull Message msg) { | 
|             if(!isFinishing()){ | 
|                 switch (msg.what){ | 
|                     case 0: | 
|                         if(finishCount<selectBeans.size()){ | 
|                             isUpdatingFace = true; | 
|                             repeatCount = 0; | 
|                             updateFace(selectBeans.get(finishCount)); | 
|                         }else { | 
|                             //结束 | 
|                             isUpdatingFace = false; | 
|                             //System.out.println("==UpdatingFace==>更新结束:"); | 
|                             // 清除内存缓存 | 
|                             Glide.get(MainActivity.this).clearMemory(); | 
|                         } | 
|                         break; | 
|                     default: | 
|                         break; | 
|                 } | 
|             } | 
|         } | 
|     }; | 
|   | 
|     private void waitUpdate(List<FaceUserBean> userBeans){ | 
|         if(isUpdatingFace){ | 
|             //正在更新 | 
|             waitBeans.addAll(userBeans); | 
|         }else { | 
|             selectBeans.clear(); | 
|             selectBeans.addAll(waitBeans); | 
|             waitBeans.clear(); | 
|             selectBeans.addAll(userBeans); | 
|             finishCount=0; | 
|             /*//删除全部 | 
|             FaceApi.getInstance().userClean(); | 
|             faceHandler.sendEmptyMessage(0);*/ | 
|   | 
|             HashMap<String,String> uMap = new HashMap<>(); | 
|             for(FaceUserBean d:selectBeans){ | 
|                 String key = d.getMemberId().toString()+"_"+d.getGroupId(); | 
|                 uMap.put(key,""); | 
|             } | 
|             //删除不存在用户 | 
|             List<User> users = FaceApi.getInstance().getAllUserList(); | 
|             List<User> dels = new ArrayList<>(); | 
|             for(User u:users){ | 
|                 String key = u.getUserId()+"_"+u.getGroupId(); | 
|                 if(!uMap.containsKey(key)){ | 
|                     dels.add(u); | 
|                 } | 
|             } | 
|             if(dels.size()>0){ | 
|                 UserInfoManager.getInstance().deleteUserListInfo(dels, | 
|                         "", new UserInfoManager.UserInfoListener() { | 
|                             @Override | 
|                             public void userListDeleteSuccess() { | 
|                                 // 用户列表删除成功 | 
|                                 faceHandler.sendEmptyMessage(0); | 
|                             } | 
|   | 
|                             @Override | 
|                             public void userListDeleteFailure(String message) { | 
|                                 // 用户列表删除失败 | 
|                                 faceHandler.sendEmptyMessage(0); | 
|                             } | 
|                         }, | 
|                         new DBLoadListener() { | 
|                             @Override | 
|                             public void onStart(int successCount) { | 
|   | 
|                             } | 
|   | 
|                             @Override | 
|                             public void onLoad(int finishCount, int successCount, float progress) { | 
|   | 
|                             } | 
|   | 
|                             @Override | 
|                             public void onComplete(List<User> features, int successCount) { | 
|   | 
|                             } | 
|   | 
|                             @Override | 
|                             public void onFail(int finishCount, int successCount, List<User> features) { | 
|   | 
|                             } | 
|                         }); | 
|             }else { | 
|                 faceHandler.sendEmptyMessage(0); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private int repeatCount = 0; | 
|     private void updateFace(FaceUserBean bean){ | 
|         Timber.d("==UpdatingFace==>完成数量 "+finishCount); | 
|         if (TextUtils.isEmpty(bean.getFaceImg())||bean.getFaceImg().endsWith("null")) { | 
|             finishCount++; | 
|             faceHandler.sendEmptyMessage(0); | 
|             return; | 
|         } | 
|         repeatCount++; | 
|         //System.out.println("==UpdatingFace==>开始:" + bean.getName()); | 
|         Glide.with(this) | 
|                 .asBitmap() | 
|                 .load(bean.getFaceImg()) | 
|                 .addListener(new RequestListener<Bitmap>() { | 
|                     @Override | 
|                     public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) { | 
|                         if(repeatCount==1) { | 
|                             finishCount++; | 
|                         } | 
|                         faceHandler.sendEmptyMessage(0); | 
|                         return false; | 
|                     } | 
|   | 
|                     @Override | 
|                     public boolean onResourceReady(Bitmap bitmap, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) { | 
|                         if(repeatCount==1) { | 
|                             finishCount++; | 
|                         } | 
|                         if (bitmap != null) { | 
|                             //System.out.println("==UpdatingFace==>开始解析人脸"); | 
|                             byte[] secondFeature = new byte[512]; | 
|                             ImportFeatureResult result = null; | 
|                             // 10、走人脸SDK接口,通过人脸检测、特征提取拿到人脸特征值 | 
|                             try { | 
|                                 result = ImportFileManager.getInstance().getFeature(bitmap, secondFeature, | 
|                                         BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO); | 
|                             }catch (OutOfMemoryError e){ | 
|                                 e.printStackTrace(); | 
|                                 faceHandler.sendEmptyMessage(0); | 
|                                 return false; | 
|                             }catch (Exception e){ | 
|                                 e.printStackTrace(); | 
|                                 faceHandler.sendEmptyMessage(0); | 
|                                 return false; | 
|                             } | 
|   | 
|                             // 11、判断是否提取成功:128为成功,-1为参数为空,-2表示未检测到人脸 | 
|                             float ret = result.getResult(); | 
|                             //System.out.println("==UpdatingFace==>提取特征值" + ret); | 
|                             // 提取特征值 | 
|                             if (ret != -1) { | 
|                                 //有人脸 | 
|                                 // 判断质量检测,针对模糊度、遮挡、角度 | 
|                                 if (ret == 128) { | 
|                                     Timber.d("==UpdatingFace==>图片特征抽取成功: %s", JSON.toJSONString(bean)); | 
|                                     User user = new User(); | 
|                                     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); | 
|                                     faceHandler.sendEmptyMessage(0); | 
|                                 } else { | 
|                                     Timber.e("==UpdatingFace==>图片特征抽取失败: %s", JSON.toJSONString(bean)); | 
|                                     if(repeatCount>3) { | 
|                                         faceHandler.sendEmptyMessage(0); | 
|                                     }else { | 
|                                         updateFace(bean); | 
|                                     } | 
|                                 } | 
|                             } else { | 
|                                 // 上传图片无人脸隐藏 | 
|                                 Timber.e("==UpdatingFace==>图片特征抽取失败: %s", JSON.toJSONString(bean)); | 
|                                 if(repeatCount>3) { | 
|                                     faceHandler.sendEmptyMessage(0); | 
|                                 }else { | 
|                                     updateFace(bean); | 
|                                 } | 
|                             } | 
|                         } else { | 
|                             if(repeatCount>3) { | 
|                                 faceHandler.sendEmptyMessage(0); | 
|                             }else { | 
|                                 updateFace(bean); | 
|                             } | 
|                         } | 
|                         return false; | 
|                     } | 
|                 }) | 
|                 .into(new SimpleTarget<Bitmap>() { | 
|   | 
|                     @Override | 
|                     public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) { | 
|   | 
|                     } | 
|                 }); | 
|     } | 
|   | 
|     private void insertOrUpdate(User newDo){ | 
|         //插入数据库 | 
|         //System.out.println("==isOk==>bean" + GsonTools.changeGsonToJson(newDo)); | 
|         User user = FaceApi.getInstance().getByUserId(newDo.getGroupId(), newDo.getUserId()); | 
|         //System.out.println("==isOk==>查询" + user.getId()+","+user.getUserId()+","+user.getUserName()); | 
|         boolean isSave = false; | 
|         if (user == null) { | 
|             //新增 | 
|             isSave = FaceApi.getInstance().registerUserIntoDBmanager(newDo.getGroupId(), | 
|                     newDo.getUserId(), newDo.getUserName(), newDo.getImageName(), newDo.getUserInfo(), newDo.getFeature()); | 
|             //System.out.println("==isOk==>保存成功"); | 
|         } else { | 
|             //更新 | 
|             user.setUserName(newDo.getUserName()); | 
|             user.setImageName(newDo.getImageName()); | 
|             user.setFeature(newDo.getFeature()); | 
|             isSave = FaceApi.getInstance().userUpdateOnly(user); | 
|             //System.out.println("==isOk==>更新成功"); | 
|         } | 
|   | 
|         if (isSave) { | 
|             //保存成功 | 
|             //System.out.println("==UpdatingFace==>修改成功"); | 
|             UserInfoManager.getInstance(); | 
|         } else { | 
|             Timber.d("==isOk==>人脸保存失败: %s", JSON.toJSONString(newDo)); | 
|         } | 
|     } | 
|   | 
|     //弹窗 | 
|     private void initPopupWindow() { | 
|         if(popupWindow!=null&&popupWindow.isShowing()){ | 
|             return; | 
|         } | 
|         View contentView = LayoutInflater.from(mContext).inflate(R.layout.popup_menu_home, null); | 
|         popupWindow = new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); | 
|         // 点击框外可以使得popupwindow消失 | 
|         popupWindow.setFocusable(false); | 
|         popupWindow.setOutsideTouchable(false); | 
|         popupWindow.setTouchable(true); | 
|         popupWindow.setBackgroundDrawable(new BitmapDrawable()); | 
|         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 mRlErr = contentView.findViewById(R.id.rl_err); | 
|         relativeRegister.setOnClickListener(new View.OnClickListener() { | 
|             @Override | 
|             public void onClick(View v) { | 
|                 startActivity(AddFaceActivity.class); | 
|             } | 
|         }); | 
|         mPopRelativeManager.setOnClickListener(new View.OnClickListener() { | 
|             @Override | 
|             public void onClick(View v) { | 
|                 startActivity(UserManagerActivity.class); | 
|             } | 
|         }); | 
|         mRlErr.setOnClickListener(new View.OnClickListener() { | 
|             @Override | 
|             public void onClick(View v) { | 
|                 startActivity(ErrActivity.class); | 
|             } | 
|         }); | 
|         //自动关闭 | 
|         initHandler(); | 
|     } | 
|   | 
|     private void initHandler() { | 
|         new Handler(new Handler.Callback() { | 
|             @Override | 
|             public boolean handleMessage(Message msg) { | 
|                 // 实现页面跳转 | 
|                 popupWindow.dismiss(); | 
|                 return false; | 
|             } | 
|         }).sendEmptyMessageDelayed(0, 5000); | 
|     } | 
|   | 
|     private void initRGBCheck(){ | 
|         String index = SpUtil.getString("rbgCameraId","0"); | 
|         setRgbCameraId(Integer.parseInt(index)); | 
|         /*if (isSetCameraId()){ | 
|             setRgbCameraId(SingleBaseConfig.getBaseConfig().getRBGCameraId()); | 
|             return; | 
|         } | 
|         int mCameraNum = Camera.getNumberOfCameras(); | 
|         Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); | 
|         for (int i = 0; i < Camera.getNumberOfCameras(); i++) { | 
|             Camera.getCameraInfo(i, cameraInfo); | 
|         } | 
|         if (mCameraNum > 1){ | 
|             try { | 
|                 mCamera = new Camera[mCameraNum]; | 
|                 previewTextures = new PreviewTexture[mCameraNum]; | 
|                 mCamera[0] = Camera.open(0); | 
|                 previewTextures[0] = new PreviewTexture(this, getDB().checkRgbTexture); | 
|                 previewTextures[0].setCamera(mCamera[0], PREFER_WIDTH, PREFER_HEIGHT); | 
|                 mCamera[0].setPreviewCallback(new Camera.PreviewCallback() { | 
|                     @Override | 
|                     public void onPreviewFrame(byte[] data, Camera camera) { | 
|                         int check = StreamUtil.checkNirRgb(data, PREFER_WIDTH, PREFER_HEIGHT); | 
|                         if (check == 1){ | 
|                             setRgbCameraId(0); | 
|                         } | 
|                         release(0); | 
|                     } | 
|                 }); | 
|             }catch (Exception e){ | 
|                 e.printStackTrace(); | 
|             } | 
|             try { | 
|                 mCamera[1] = Camera.open(1); | 
|                 previewTextures[1] = new PreviewTexture(this, getDB().checkNirTexture); | 
|                 previewTextures[1].setCamera(mCamera[1], PREFER_WIDTH, PREFER_HEIGHT); | 
|                 mCamera[1].setPreviewCallback(new Camera.PreviewCallback() { | 
|                     @Override | 
|                     public void onPreviewFrame(byte[] data, Camera camera) { | 
|                         int check = StreamUtil.checkNirRgb(data, PREFER_WIDTH, PREFER_HEIGHT); | 
|                         if (check == 1){ | 
|                             setRgbCameraId(1); | 
|                         } | 
|                         release(1); | 
|                     } | 
|                 }); | 
|             }catch (Exception e){ | 
|                 e.printStackTrace(); | 
|             } | 
|         } else { | 
|             setRgbCameraId(0); | 
|         }*/ | 
|     } | 
|   | 
|     private void setRgbCameraId(int index){ | 
|         getVM().addInfo("设置相机:"+index); | 
|         //Toast.makeText(mContext, "设置相机"+index, Toast.LENGTH_SHORT).show(); | 
|         SpUtil.saveString("rbgCameraId",index+""); | 
|         BraceletLogUtils.saveLog("设置相机("+index+")"); | 
|         SingleBaseConfig.getBaseConfig().setRBGCameraId(index); | 
|         SingleBaseConfig.getBaseConfig().setRgbRevert(true); | 
|         SingleBaseConfig.getBaseConfig().setRgbDetectDirection(90); | 
|         SingleBaseConfig.getBaseConfig().setRgbVideoDirection(270); | 
|         GateConfigUtils.modityJson(); | 
|         RegisterConfigUtils.modityJson(); | 
|     } | 
|     private boolean isSetCameraId(){ | 
|         if (SingleBaseConfig.getBaseConfig().getRBGCameraId() == -1){ | 
|             return false; | 
|         }else { | 
|             return true; | 
|         } | 
|     } | 
|   | 
|     private void release(int id){ | 
|         if (mCamera != null && mCamera[id] != null) { | 
|             if (mCamera[id] != null) { | 
|                 mCamera[id].setPreviewCallback(null); | 
|                 mCamera[id].stopPreview(); | 
|                 previewTextures[id].release(); | 
|                 mCamera[id].release(); | 
|                 mCamera[id] = null; | 
|             } | 
|         } | 
|     } | 
|   | 
|     private UpdateUtil updateUtil; | 
|     private void checkUpdate(){ | 
|         //版本更新 | 
|         if(updateUtil==null){ | 
|             updateUtil = new UpdateUtil(this); | 
|             updateUtil.setShowToast(false); | 
|         } | 
|         if(!updateUtil.isShowing()){ | 
|             updateUtil.getServerVerCode(new UpdateUtil.VersionCallBack() { | 
|                 @Override | 
|                 public void isNeedUpdate(boolean isUpdate) { | 
|                     isUpdateVersion = isUpdate; | 
|                 } | 
|             }); | 
|         } | 
|     } | 
|   | 
|     private PermissiondDialog permissiondDialog; | 
|     private void showNoPermissionTip() { | 
|         try { | 
|             Toast.makeText(this,getString(R.string.guide_permiss_1) , Toast.LENGTH_LONG).show(); | 
|             if (permissiondDialog == null) { | 
|                 permissiondDialog = new PermissiondDialog(this, getString(R.string.help), getString(R.string.guide_permiss_2), getString(R.string.cancel), | 
|                         getString(R.string.empower), new PermissiondDialog.OnClickListener() { | 
|                     @Override | 
|                     public void clickOk() { | 
|                         permissiondDialog.dismiss(); | 
|                         PermissionUtils.gotoPermission(getContext()); | 
|                     } | 
|   | 
|                     @Override | 
|                     public void clickNo() { | 
|                         permissiondDialog.dismiss(); | 
|                         finish(); | 
|                     } | 
|                 }); | 
|             } | 
|             if (!permissiondDialog.isShowing()) { | 
|                 permissiondDialog.show(); | 
|             } | 
|         } catch (Exception e) { | 
|   | 
|         } | 
|     } | 
|   | 
|     private int tipDownCount = 10; | 
|     private int loopDownCount = 60; | 
|     private boolean isShowTip; | 
|     @Subscribe | 
|     public void TimeClockEvent(TimeClockEvent e){ | 
|         if(!isFinishing()) { | 
|             if(isShowTip){ | 
|                 if(tipDownCount==0){ | 
|                     isShowTip = false; | 
|                     getDB().clTip.setVisibility(View.GONE); | 
|                 }else { | 
|                     tipDownCount--; | 
|                     getDB().tvDjs.setText(tipDownCount+"s"); | 
|                 } | 
|             } | 
|             if(loopDownCount==0){ | 
|                 loopDownCount = SpUtil.getInt("loop_time",60); | 
|                 //定时拉取基本信息 | 
|                 getVM().devLogin(); | 
|                 getPermission(); | 
|                 getVM().devHeart(); | 
|                 EventBus.getDefault().post(new GetFacesEvent()); | 
|             }else { | 
|                 loopDownCount--; | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 监听开门 | 
|      * @param e | 
|      */ | 
|     @Subscribe(threadMode=ThreadMode.MAIN) | 
|     public void OpenGridEvent(OpenGridEvent e){ | 
|         if(!isFinishing()){ | 
|             //开启柜门 | 
|             String key = e.getKey(); | 
|             if(TextUtils.isEmpty(key)) { | 
|                 key = SportUtils.intToHex(Integer.parseInt(e.getBoardCode())) | 
|                         + SportUtils.intToHex(Integer.parseInt(e.getChannelCode())); | 
|             } | 
|             String code = "8A" + key + "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() { | 
|         super.onRestart(); | 
|         getVM().devHeart(); | 
|     } | 
|   | 
|   | 
|     @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); | 
|         } | 
|     } | 
|   | 
|     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.setIsOpen("00".equals(open)?1:0); | 
|                         gridDo.setUpdateTime(StringUtil.DateToStr(new Date())); | 
|   | 
|                         DaoManager.getCabinetGridDao().update(gridDo); | 
|                         EventBus.getDefault().post(new ManageOpenGridResultEvent()); | 
|                         if(gridDo.getIsOpen()==0) { | 
|                             //开门失败 | 
|                             EventBus.getDefault().post(new OpenErrEvent(key)); | 
|                         }else { | 
|                             //开门返回 | 
|                             EventBus.getDefault().post(new OpenGridOneResultEvent(key,"00".equals(open)?1:0)); | 
|                         } | 
|                     } | 
|   | 
|                 }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> updateList = new ArrayList<>(); | 
|                     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); | 
|                             } | 
|                         } | 
|   | 
|                         getVM().updateGrids(updateList); | 
|                         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.setIsOpen("00".equals(open)?1:0); | 
|                     gridDo.setUpdateTime(StringUtil.DateToStr(new Date())); | 
|                     DaoManager.getCabinetGridDao().update(gridDo); | 
|                 } | 
|                 //关门返回 | 
|                 EventBus.getDefault().post(new CloseGridOneResultEvent(key,"00".equals(open)?1:0)); | 
|                 if(isShowing&&isShowTip){ | 
|                     //修改显示提醒 | 
|                     getVM().doAction(5); | 
|                 } | 
|             }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); | 
|                         if(isShowing){ | 
|                             unCloseGrid(); | 
|                         } | 
|                     }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); | 
|                         if(data2.contains("CC01")&&data2.contains("CC02")){ | 
|                             String[] sp = data2.split("CC02"); | 
|                             if(sp.length==2){ | 
|                                 jxKey(sp[0]); | 
|                                 jxKey("CC02"+sp[1]); | 
|                             } | 
|                         }else { | 
|                             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(""); | 
|                     } | 
|                     if("0101".equals(key)) { | 
|                         getVM().addInfo(key+" , "+isHaveKey+"  "+keyCode); | 
|                         getVM().addInfo(key + "设置钥匙:" + gridDo.getCurKeyCode()); | 
|                     } | 
|                     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); | 
|                 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; | 
|             } | 
|         } | 
|     }; | 
|   | 
|     @Subscribe(threadMode = ThreadMode.MAIN) | 
|     public void CheckGridStatusEvent(CheckGridStatusEvent e){ | 
|         if(!isFinishing()){ | 
|             checkGridStatus(0); | 
|         } | 
|     } | 
|   | 
|     //检查所有门状态 | 
|     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 String jiu_blow; | 
|     private String jiu_mic_ad; | 
|     private String jiu_alarm; | 
|     private String jiu_unit; | 
|     private void setJiuConfig(long time){ | 
|         CabinetConfigDataBean config = MApplication.getConfigBean().getCabinetConfigDataVO(); | 
|         if(!config.getBlowTime().equals(jiu_blow)) { | 
|             //设置吹气时间 | 
|             jiu_blow = config.getBlowTime(); | 
|             sendPortHandlerMsg(3, "blow:" + config.getBlowTime(), time += 100); | 
|         } | 
|         if(!config.getPressure().equals(jiu_mic_ad)) { | 
|             //压力值 | 
|             jiu_mic_ad = config.getPressure(); | 
|             sendPortHandlerMsg(3, "mic_ad:" + config.getPressure(), time += 300); | 
|         } | 
|         if(!config.getConcentration().equals(jiu_alarm)) { | 
|             //浓度阈值 | 
|             jiu_alarm = config.getConcentration(); | 
|             sendPortHandlerMsg(3, "alarm:" + config.getConcentration(), time += 300); | 
|         } | 
|         if("3".equals(config.getThreshold())){ | 
|             config.setThreshold("0"); | 
|         } | 
|         if(!config.getThreshold().equals(jiu_unit)) { | 
|             //浓度阈值单位 (1=mg/100ml;2=mg/L;3=%BAC) | 
|             jiu_unit = config.getThreshold(); | 
|             sendPortHandlerMsg(3, "unit:" + config.getThreshold(), time += 300); | 
|         } | 
|     } | 
|   | 
|     private void sendPortHandlerMsg(int what,String obj,long time){ | 
|         Message mc = Message.obtain(); | 
|         mc.what=what; | 
|         mc.obj = obj; | 
|         portHandler.sendMessageDelayed(mc,time); | 
|     } | 
|   | 
|     private boolean isInitPort; | 
|     //初始化串口 | 
|     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"))){ | 
|             if(isInitPort){ | 
|                 return; | 
|             } | 
|             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) { | 
|                     isInitPort = true; | 
|                     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) { | 
|                     isInitPort = true; | 
|                     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) { | 
|                     isInitPort = true; | 
|                     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 CircularQueue openGridQueue = new CircularQueue(); | 
|     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){ | 
|                 if(code.startsWith("8A")){ | 
|                     openGridQueue.enqueue(code); | 
|                 } | 
|                 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; | 
|     } | 
|   | 
|     //开门 | 
|     @Subscribe | 
|     public void OpenGridOneResultEvent(OpenGridOneResultEvent e){ | 
|         if(!isFinishing()&&isShowing){ | 
|             //开门成功,移除开门 | 
|             if(handler.hasMessages(1)){ | 
|                 handler.removeMessages(1); | 
|                 getVM().addInfo("==移除开门任务"); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private Long keyTime; | 
|     private HashMap<String,String> closeMap = new HashMap<>(); | 
|     /** | 
|      * 关门 | 
|      * @param e | 
|      */ | 
|     @Subscribe(threadMode= ThreadMode.MAIN) | 
|     public void CloseGridOneResultEvent(CloseGridOneResultEvent e){ | 
|         if(!isFinishing()&&isShowing){ | 
|             //关门成功,移除开门 | 
|             if(handler.hasMessages(1)){ | 
|                 handler.removeMessages(1); | 
|                 getVM().addInfo("==移除开门任务"); | 
|             } | 
|             closeMap.put(e.getKey(),""); | 
|             //发送查询钥匙号 | 
|             EventBus.getDefault().post(new GetKeyStatusEvent()); | 
|             keyTime = new Date().getTime()+500; | 
|             if(handler.hasMessages(2)){ | 
|                 handler.removeMessages(2); | 
|             } | 
|             handler.sendEmptyMessageDelayed(2,1200); | 
|         } | 
|     } | 
|   | 
|     @Subscribe(threadMode= ThreadMode.MAIN) | 
|     public void OpenErrEvent(OpenErrEvent e){ | 
|         //开门失败 | 
|         if(!isFinishing()&&isShowing){ | 
|             //开门 | 
|             if(handler.hasMessages(1)){ | 
|                 handler.removeMessages(1); | 
|                 getVM().addInfo("==移除开门任务"); | 
|             } | 
|             EventBus.getDefault().post(new OpenGridEvent(e.getKey())); | 
|             Message msg = Message.obtain(); | 
|             msg.what=1; | 
|             msg.obj = e.getKey(); | 
|             handler.sendMessageDelayed(msg,1000); | 
|         } | 
|     } | 
|   | 
|     @Subscribe | 
|     public void KeyResultEvent(KeyResultEvent e){ | 
|         if(!isFinishing()&&isShowing){ | 
|             //校验时间 | 
|             if(keyTime==null){ | 
|                 return; | 
|             } | 
|             if(keyTime!=null&&keyTime>System.currentTimeMillis()){ | 
|                 //校验返回时间<命令时间 | 
|                 return; | 
|             } | 
|             if(handler.hasMessages(2)){ | 
|                 handler.removeMessages(2); | 
|             } | 
|   | 
|             HashMap<String,String> copyMap = new HashMap<>(); | 
|             copyMap.putAll(closeMap); | 
|             closeMap.clear(); | 
|             //校验卡号不对的,直接弹出 | 
|             List<CabinetGridDo> gridDos = DaoManager.getCabinetGridDao().loadAll(); | 
|             List<String> keys = new ArrayList<>(); | 
|             StringBuilder sb = new StringBuilder(); | 
|             for(CabinetGridDo gridDo:gridDos){ | 
|                 //要在范围内 | 
|                 if(copyMap.containsKey(gridDo.getGridKey())){ | 
|                     boolean isFail = false; | 
|                     if(TextUtils.isEmpty(gridDo.getGridKey())){ | 
|                         if(!TextUtils.isEmpty(gridDo.getCurKeyCode())&&gridDo.getIsOpen()==0){ | 
|                             //未绑定的存放了钥匙 | 
|                             keys.add(gridDo.getGridKey()); | 
|                             if(sb.length()>0){ | 
|                                 sb.append("、"); | 
|                             } | 
|                             sb.append(gridDo.getCabinetName()); | 
|                             isFail = true; | 
|                         } | 
|                     }else { | 
|                         if(!TextUtils.isEmpty(gridDo.getCurKeyCode())){ | 
|                             if(!gridDo.getCurKeyCode().equals(gridDo.getKeyCode())&&gridDo.getIsOpen()==0){ | 
|                                 //钥匙不匹配 | 
|                                 keys.add(gridDo.getGridKey()); | 
|                                 if(sb.length()>0){ | 
|                                     sb.append("、"); | 
|                                 } | 
|                                 sb.append(gridDo.getCabinetName()); | 
|                                 isFail = true; | 
|                             } | 
|                         } | 
|                     } | 
|                     if(!isFail){ | 
|                         //关门成功 | 
|                         EventBus.getDefault().post(new HttpEvent(StringUtil.DateToStrSS(new Date())+"门关闭成功***************************>目标:"+gridDo.getKeyCode()+",当前:"+gridDo.getCurKeyCode())); | 
|                         getVM().closeGrid(gridDo); | 
|                     } | 
|                 } | 
|             } | 
|             if(sb.length()>0){ | 
|                 ToastView.show(MApplication.mContext, sb.toString() + "钥匙存放位置错误"); | 
|             } | 
|             if(keys.size()>0){ | 
|                 //开门 | 
|                 EventBus.getDefault().post(new OpenGridListEvent(keys)); | 
|             } | 
|         } | 
|     } | 
| } |