From 94b4a8117885c70b51b0d877545db5362dfcbd3a Mon Sep 17 00:00:00 2001 From: xinfengkun Date: Sun, 24 Apr 2022 15:14:51 +0800 Subject: [PATCH] =?UTF-8?q?[change]=E5=B0=86=E8=BF=9E=E6=8E=A5=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=8F=98=E6=9B=B4=E4=BB=A5=E6=96=87=E5=AD=97=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E5=9B=9E=E8=B0=83=E5=88=B0=E9=B9=B0=E7=9C=BC=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=8E=92=E6=9F=A5=E6=96=AD=E5=BC=80=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E6=88=96=E8=80=85=E9=87=8D=E8=BF=9E=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/AndroidManifest.xml | 2 +- .../client/adapter/ConnectStatusAdapter.java | 67 +++++++ .../adas/client/bean/IPCConnectState.java | 2 + .../zhidao/adas/client/ui/FloatWindow.java | 181 ++++++++++++++++++ .../zhidao/adas/client/ui/MainActivity.java | 85 ++++---- .../src/main/res/drawable/bg_float.xml | 9 + .../src/main/res/layout/item_status.xml | 31 +++ .../src/main/res/layout/layout_float.xml | 15 ++ .../zhidao/support/adas/high/AdasChannel.java | 42 ++-- .../high/OnAdasConnectStatusListener.java | 6 +- .../adas/high/common/IPCFixationIPHelper.java | 34 ++-- .../high/common/ReceiveTimeoutManager.java | 11 +- .../support/adas/high/protocol/RawPack.java | 9 +- .../support/adas/high/socket/FpgaSocket.java | 74 ++++--- 14 files changed, 458 insertions(+), 110 deletions(-) create mode 100644 app_ipc_monitoring/src/main/java/com/zhidao/adas/client/adapter/ConnectStatusAdapter.java create mode 100644 app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/FloatWindow.java create mode 100644 app_ipc_monitoring/src/main/res/drawable/bg_float.xml create mode 100644 app_ipc_monitoring/src/main/res/layout/item_status.xml create mode 100644 app_ipc_monitoring/src/main/res/layout/layout_float.xml diff --git a/app_ipc_monitoring/src/main/AndroidManifest.xml b/app_ipc_monitoring/src/main/AndroidManifest.xml index 7b879c95e6..b4e003c0bc 100644 --- a/app_ipc_monitoring/src/main/AndroidManifest.xml +++ b/app_ipc_monitoring/src/main/AndroidManifest.xml @@ -29,7 +29,7 @@ - + { + private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ", Locale.getDefault()); + private static final String POS = "%03d. "; + + public void refreshView() { +// notifyItemChanged(mDatas.size()-1,0); + notifyItemRangeChanged(0, getItemCount()); + } + + @Override + public long getItemId(int position) { + return position; + } + + @SuppressLint("SetTextI18n") + @Override + protected void onBindDataToItem(ViewHolder viewHolder, IPCConnectState data, int position) { + viewHolder.id.setText(String.format(Locale.getDefault(), POS, getItemCount() - position)); + viewHolder.editText.setText(sdf.format(new Date(data.time)) + "\n" + data.status); + viewHolder.editText.setTextColor(mContext.getResources().getColor(data.color)); + } + + @Override + protected View getItemViewResource(ViewGroup viewGroup) { + return LayoutInflater.from(mContext).inflate(R.layout.item_status, viewGroup, false); + } + + + @Override + protected ViewHolder getViewHolder(View view) { + return new ViewHolder(view, this); + } + + + class ViewHolder extends BaseViewHolder { + EditText editText; + TextView id; + + public ViewHolder(View itemView, ConnectStatusAdapter adapter) { + super(itemView, adapter); + editText = itemView.findViewById(R.id.log); + id = itemView.findViewById(R.id.id); + } + } +} \ No newline at end of file diff --git a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/bean/IPCConnectState.java b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/bean/IPCConnectState.java index d5ee3b31e3..cc1ca7c09b 100644 --- a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/bean/IPCConnectState.java +++ b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/bean/IPCConnectState.java @@ -3,6 +3,7 @@ package com.zhidao.adas.client.bean; import androidx.annotation.ColorRes; public class IPCConnectState { + public final long time; public final String status; @ColorRes public final int color; @@ -10,5 +11,6 @@ public class IPCConnectState { public IPCConnectState(String status, @ColorRes int color) { this.status = status; this.color = color; + time = System.currentTimeMillis(); } } diff --git a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/FloatWindow.java b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/FloatWindow.java new file mode 100644 index 0000000000..67a7a2ce87 --- /dev/null +++ b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/FloatWindow.java @@ -0,0 +1,181 @@ +package com.zhidao.adas.client.ui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.PixelFormat; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; + +import androidx.recyclerview.widget.RecyclerView; + +import com.zhidao.adas.client.R; +import com.zhidao.adas.client.adapter.ConnectStatusAdapter; +import com.zhidao.adas.client.adapter.DataShowAdapter; +import com.zhidao.adas.client.bean.IPCConnectState; +import com.zhidao.adas.client.utils.MyLinearLayoutManager; + +import java.lang.reflect.Field; +import java.util.List; + +/** + * @author xuxinchao + * @description + * @since: 2022/4/20 + */ +public class FloatWindow implements View.OnTouchListener { + + private final Activity mContext; + private WindowManager.LayoutParams mWindowParams; + private WindowManager mWindowManager; + + private View mFloatLayout; + private float mInViewX; + private float mInViewY; + private float mDownInScreenX; + private float mDownInScreenY; + private float mInScreenX; + private float mInScreenY; + private RecyclerView rv_status; + private ConnectStatusAdapter adapter; + private List list; + + public FloatWindow(Activity context, List list) { + this.mContext = context; + this.list = list; + initFloatWindow(); + } + public void refreshView(){ + if (adapter!=null){ + adapter.refreshView(); + } + } + + private void initRV() { + //创建默认的线性LayoutManager 横向的GridLayoutManager + MyLinearLayoutManager linearLayoutManager = new MyLinearLayoutManager(mContext); +// linearLayoutManager.setStackFromEnd(true);//列表再底部开始展示,反转后由上面开始展示 +// linearLayoutManager.setReverseLayout(true);//列表翻转 + rv_status.setLayoutManager(linearLayoutManager); + //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能 + rv_status.setHasFixedSize(false); + rv_status.setNestedScrollingEnabled(false); + adapter = new ConnectStatusAdapter(); + adapter.setHasStableIds(true); + rv_status.setAdapter(adapter); + adapter.setData(list); + } + + private void initFloatWindow() { + LayoutInflater inflater = LayoutInflater.from(mContext); + if (inflater == null) + return; + mFloatLayout = (View) inflater.inflate(R.layout.layout_float, null); + rv_status = mFloatLayout.findViewById(R.id.rv_status); + mFloatLayout.setOnTouchListener(this); + initRV(); + mWindowParams = new WindowManager.LayoutParams(); +// mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); +// if (Build.VERSION.SDK_INT >= 26) {//8.0新特性 +// mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +// }else{ +// mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; +// } + + mWindowManager = mContext.getWindowManager(); + + mWindowParams.format = PixelFormat.RGBA_8888; + mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + mWindowParams.gravity = Gravity.START | Gravity.TOP; + mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT; + mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + mWindowParams.alpha = 0.9F; + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + return floatLayoutTouch(motionEvent); + } + + private boolean floatLayoutTouch(MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + // 获取相对View的坐标,即以此View左上角为原点 + mInViewX = motionEvent.getX(); + mInViewY = motionEvent.getY(); + // 获取相对屏幕的坐标,即以屏幕左上角为原点 + mDownInScreenX = motionEvent.getRawX(); + mDownInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + mInScreenX = motionEvent.getRawX(); + mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + break; + case MotionEvent.ACTION_MOVE: + // 更新浮动窗口位置参数 + mInScreenX = motionEvent.getRawX(); + mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + mWindowParams.x = (int) (mInScreenX - mInViewX); + mWindowParams.y = (int) (mInScreenY - mInViewY); + // 手指移动的时候更新小悬浮窗的位置 + mWindowManager.updateViewLayout(mFloatLayout, mWindowParams); + break; + case MotionEvent.ACTION_UP: + // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 + if (mDownInScreenX == mInScreenX && mDownInScreenY == mInScreenY) { + + } + break; + } + return true; + } + + public void showFloatWindow(float y) { + if (mFloatLayout.getParent() == null) { + DisplayMetrics metrics = new DisplayMetrics(); + // 默认固定位置,靠屏幕右边缘的中间 + mWindowManager.getDefaultDisplay().getMetrics(metrics); + mWindowParams.x = metrics.widthPixels; + mWindowParams.y = (int) (y); + mWindowManager.addView(mFloatLayout, mWindowParams); + } + } + + + public void hideFloatWindow() { + if (mFloatLayout.getParent() != null) + mWindowManager.removeView(mFloatLayout); + } + + public void setFloatLayoutAlpha(boolean alpha) { + if (alpha) + mFloatLayout.setAlpha((float) 0.5); + else + mFloatLayout.setAlpha(1); + } + + private int sbar = -1; + + // 获取系统状态栏高度 + public int getSysBarHeight(Context contex) { + if (sbar == -1) { + Class c; + Object obj; + Field field; + int x; + sbar = 0; + try { + c = Class.forName("com.android.internal.R$dimen"); + obj = c.newInstance(); + field = c.getField("status_bar_height"); + x = Integer.parseInt(field.get(obj).toString()); + sbar = contex.getResources().getDimensionPixelSize(x); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + return sbar; + } + +} diff --git a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java index 5a61091fe3..b112608253 100644 --- a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java +++ b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java @@ -97,7 +97,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas private final static String TAG = MainActivity.class.getSimpleName(); private static final int WHAT_IPC_IP = 0x00; private static final int WHAT_DRIVER_IP = 0x01; - private static final int WHATIPC_CONNECT_STATE = 0x02; + private static final int WHAT_IPC_CONNECT_STATE = 0x02; private EditText etIp; private ImageView role; private ImageView tvIp; @@ -123,7 +123,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas private final List titleFragmentData = new ArrayList<>(); private final List titleBtnData = new ArrayList<>(); - + private final List connectStatusList = new ArrayList<>(); private InfoTitleAdapter btnAdapter; private InfoTitleAdapter fragmentAdapter; @@ -150,7 +150,8 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas private int connectStatus; private AutoPilotModeDialog autoPilotModeDialog; private ListPopupWindow listPopupWindow; - + private FloatWindow floatWindow; + private View include_title; // @Override // protected void onStart() { // super.onStart(); @@ -206,6 +207,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas private void initView() { + include_title = findViewById(R.id.include_title); etIp = findViewById(R.id.et_ip); role = findViewById(R.id.role); line = findViewById(R.id.line); @@ -391,6 +393,18 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas } } }); + tvConnectState.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (floatWindow == null) { + floatWindow = new FloatWindow(MainActivity.this, connectStatusList); + floatWindow.showFloatWindow(include_title.getY() + include_title.getHeight()); + } else { + floatWindow.hideFloatWindow(); + floatWindow = null; + } + } + }); } private void showListPopupWindow() { @@ -627,36 +641,52 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas } } - - private String onUpdateConnectStateView() { - String status; + private int getStatusColor(int connectStatus) { int color; switch (connectStatus) { case IPC_CONNECTION_STATUS.CONNECTED: - status = "已连接"; color = R.color.connect_status_connected; break; default: case IPC_CONNECTION_STATUS.DISCONNECTED: - status = "未连接"; color = R.color.connect_status_disconnected; break; case IPC_CONNECTION_STATUS.CONNECTING: - status = "连接中"; color = R.color.connect_status_connecting; break; case IPC_CONNECTION_STATUS.SEARCH_ADDRESS: - status = "搜索IP"; color = R.color.connect_status_search_address; break; case IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS: - status = "未找到"; color = R.color.connect_status_disconnecting; break; } + return color; + } + + private String onUpdateConnectStateView() { + String status; + switch (connectStatus) { + case IPC_CONNECTION_STATUS.CONNECTED: + status = "已连接"; + break; + default: + case IPC_CONNECTION_STATUS.DISCONNECTED: + status = "未连接"; + break; + case IPC_CONNECTION_STATUS.CONNECTING: + status = "连接中"; + break; + case IPC_CONNECTION_STATUS.SEARCH_ADDRESS: + status = "搜索IP"; + break; + case IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS: + status = "未找到"; + break; + } Message msg = Message.obtain(); - msg.obj = new IPCConnectState(status, color); - msg.what = WHATIPC_CONNECT_STATE; + msg.obj = new IPCConnectState(status, getStatusColor(connectStatus)); + msg.what = WHAT_IPC_CONNECT_STATE; getHandler().sendMessage(msg); return status; } @@ -854,7 +884,6 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas AdasManager.getInstance().create(options, this); AdasManager.getInstance().setOnAdasListener(this); -// AdasManager.getInstance().setOnAdasConnectStatusListener(this); if (BuildConfig.IS_CLIENT) { /*—————————————作为乘客端———————————*/ @@ -878,18 +907,6 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas } - @Override - protected void onPause() { - super.onPause(); -// AdasManager.getInstance().pause(); - } - - @Override - protected void onResume() { - super.onResume(); -// AdasManager.getInstance().resume(); - } - @Override protected void onDestroy() { super.onDestroy(); @@ -903,7 +920,12 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas @Override - public void onConnectionIPCStatus(int ipcConnectionStatus, String failedMsg) { + public void onConnectionIPCStatus(int ipcConnectionStatus, String reason) { + Log.i(TAG, "连接状态=" + (reason == null ? "主动断开连接" : reason)); + connectStatusList.add(0, new IPCConnectState(reason == null ? "主动断开连接" : reason, getStatusColor(ipcConnectionStatus))); + if (connectStatusList.size() > 100) { + connectStatusList.remove(connectStatusList.size() - 1); + } connectStatus = ipcConnectionStatus; String status = onUpdateConnectStateView(); if (connectStatus == IPC_CONNECTION_STATUS.CONNECTED) { @@ -914,10 +936,6 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas Constants.addIpcUsedIps(this, ips, tem); } } else if (connectStatus == IPC_CONNECTION_STATUS.DISCONNECTED) { - if (!TextUtils.isEmpty(failedMsg)) { - status += " failedMsg=" + failedMsg; - showToastCenter("连接失败:" + failedMsg); - } getHandler().sendEmptyMessage(WHAT_IPC_IP); } // LogSave.getInstance().saveLog("连接状态", status); @@ -1098,7 +1116,10 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas ipcIp.setVisibility(View.VISIBLE); ipcIp.setText("司机IP:" + NSDNettyManager.getInstance().getConnServerIp()); break; - case WHATIPC_CONNECT_STATE: + case WHAT_IPC_CONNECT_STATE: + if (floatWindow != null) { + floatWindow.refreshView(); + } IPCConnectState status = (IPCConnectState) msg.obj; tvConnectState.setText(status.status); tvConnectState.setTextColor(getResources().getColor(status.color)); diff --git a/app_ipc_monitoring/src/main/res/drawable/bg_float.xml b/app_ipc_monitoring/src/main/res/drawable/bg_float.xml new file mode 100644 index 0000000000..eeb2ab95b9 --- /dev/null +++ b/app_ipc_monitoring/src/main/res/drawable/bg_float.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app_ipc_monitoring/src/main/res/layout/item_status.xml b/app_ipc_monitoring/src/main/res/layout/item_status.xml new file mode 100644 index 0000000000..a4cfdf3b81 --- /dev/null +++ b/app_ipc_monitoring/src/main/res/layout/item_status.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/app_ipc_monitoring/src/main/res/layout/layout_float.xml b/app_ipc_monitoring/src/main/res/layout/layout_float.xml new file mode 100644 index 0000000000..7abc108fc0 --- /dev/null +++ b/app_ipc_monitoring/src/main/res/layout/layout_float.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasChannel.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasChannel.java index 411dd18b8d..42e62465e7 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasChannel.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasChannel.java @@ -17,7 +17,6 @@ import com.zhidao.support.adas.high.bean.SSHResult; import com.zhidao.support.adas.high.common.Base64; import com.zhidao.support.adas.high.common.Constants; import com.zhidao.support.adas.high.common.CupidLogUtils; -import com.zhidao.support.adas.high.common.Define; import com.zhidao.support.adas.high.common.DigitalTrans; import com.zhidao.support.adas.high.common.IPCFixationIPHelper; import com.zhidao.support.adas.high.common.MessageType; @@ -40,8 +39,8 @@ import com.zhjt.service.chain.TracingConstants; import org.json.JSONObject; -import java.nio.charset.StandardCharsets; import java.util.HashSet; +import java.util.concurrent.atomic.AtomicInteger; import mogo.telematics.pad.MessagePad; import okio.ByteString; @@ -67,8 +66,7 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec /** * 与工控机链接状态 */ - @Define.IPCConnectionStatus - private int ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.DISCONNECTED; + private final AtomicInteger ipcConnectionStatus = new AtomicInteger(Constants.IPC_CONNECTION_STATUS.DISCONNECTED); /** @@ -111,16 +109,16 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec @Override public void onStartFindIP() { if (adasConnectStatusListener != null) { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.SEARCH_ADDRESS; - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, null); + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.SEARCH_ADDRESS); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), "正在搜索IP"); } } @Override public void onStopFindIP() { if (adasConnectStatusListener != null) { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.DISCONNECTED; - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, null); + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.DISCONNECTED); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), "停止搜索IP"); } } @@ -356,12 +354,8 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec public void connect() { //当是司机屏才启用 if (!adasOptions.isClient()) { - if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.DISCONNECTED || - ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS) { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.SEARCH_ADDRESS; - if (adasConnectStatusListener != null) { - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, null); - } + if (ipcConnectionStatus.get() == Constants.IPC_CONNECTION_STATUS.DISCONNECTED || + ipcConnectionStatus.get() == Constants.IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS) { switch (adasOptions.getIpcConnectionMode()) { case AdasOptions.IPC_CONNECTION_MODE.FIXATION: ipcFixationIPHelper(adasOptions.getIpcFixationIP()); @@ -402,31 +396,31 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec } @Override - public void onConnecting() { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.CONNECTING; + public void onConnecting(String msg) { + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.CONNECTING); if (adasConnectStatusListener != null) { - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, null); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), msg); } } @Override public void onWebSocketConnectSuccess(String ipAddress, int port) { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.CONNECTED; + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.CONNECTED); ipcConnectedIp = ipAddress; ipcConnectedPort = port; if (adasConnectStatusListener != null) { - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, null); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), "已连接"); } sendCarConfigReq(); } @Override public void onWebSocketConnectFailed(String t) { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.DISCONNECTED; + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.DISCONNECTED); ipcConnectedIp = null; ipcConnectedPort = Constants.DEFAULT_PORT; if (adasConnectStatusListener != null) { - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, t); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), t); } } @@ -441,9 +435,9 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec } private void notFoundAddress() { - ipcConnectionStatus = Constants.IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS; + ipcConnectionStatus.set(Constants.IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS); if (adasConnectStatusListener != null) { - adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus, "地址不可用或不合法"); + adasConnectStatusListener.onConnectionIPCStatus(ipcConnectionStatus.get(), "地址不可用或不合法"); } } @@ -501,7 +495,7 @@ public class AdasChannel implements IAdasNetCommApi, FpgaSocket.IWebSocketConnec @Override public int getIpcConnectionStatus() { - return ipcConnectionStatus; + return ipcConnectionStatus.get(); } diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/OnAdasConnectStatusListener.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/OnAdasConnectStatusListener.java index c2d9dd96d2..c2c7a1b4db 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/OnAdasConnectStatusListener.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/OnAdasConnectStatusListener.java @@ -16,9 +16,9 @@ public interface OnAdasConnectStatusListener { * 与工控机链接状态变化 * * @param ipcConnectionStatus {@link Constants.IPC_CONNECTION_STATUS} - * @param failedMsg 连接异常信息 需要判null - * 如果ipcConnectionStatus==Constants.IPC_CONNECTION_STATUS.DISCONNECTED&&failedMsg==null 表示主动断开连接 + * @param reason 连接信息 需要判null + * 如果ipcConnectionStatus==Constants.IPC_CONNECTION_STATUS.DISCONNECTED&&reason==null 表示主动断开连接 */ - void onConnectionIPCStatus(@Define.IPCConnectionStatus int ipcConnectionStatus, @Nullable String failedMsg); + void onConnectionIPCStatus(@Define.IPCConnectionStatus int ipcConnectionStatus, @Nullable String reason); } diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/IPCFixationIPHelper.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/IPCFixationIPHelper.java index 966b1498ad..152c4a8e52 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/IPCFixationIPHelper.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/IPCFixationIPHelper.java @@ -10,6 +10,8 @@ import java.util.List; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; /** * 工控机固定IP查询 @@ -18,8 +20,8 @@ public class IPCFixationIPHelper { private static final String TAG = IPCFixationIPHelper.class.getSimpleName(); private final IIPCFixationIPListener listener; private final List futures = new ArrayList<>(); - private volatile boolean isCallListener = false;//是否已经调用了回调 - private volatile int unavailableCount = 0;//不可用IP个数 + private final AtomicBoolean isCallListener = new AtomicBoolean(false);//是否已经调用了回调 + private final AtomicInteger unavailableCount = new AtomicInteger(0);//不可用IP个数 private volatile int queryCount;//要查询的IP个数 private Timer retryTimer; @@ -48,8 +50,9 @@ public class IPCFixationIPHelper { void onAvailableIP(String ip); } - private void interrupted() { - if (!futures.isEmpty()) { + private boolean interrupted() { + boolean isEm = futures.isEmpty(); + if (!isEm) { for (Future future : futures) { if (!future.isCancelled()) { future.cancel(true); @@ -57,6 +60,7 @@ public class IPCFixationIPHelper { } futures.clear(); } + return isEm; } public void stop() { @@ -64,9 +68,10 @@ public class IPCFixationIPHelper { retryTimer.cancel(); retryTimer = null; } - isCallListener = true; - interrupted(); - listener.onStopFindIP(); + isCallListener.set(true); + if (!interrupted()) { + listener.onStopFindIP(); + } } /** @@ -83,8 +88,8 @@ public class IPCFixationIPHelper { } else { interrupted(); queryCount = ips.size(); - unavailableCount = 0; - isCallListener = false; + unavailableCount.set(0); + isCallListener.set(false); for (final String temp : ips) { Runnable runnable = new Runnable() { @Override @@ -92,8 +97,8 @@ public class IPCFixationIPHelper { CupidLogUtils.i(TAG, "ip=" + temp); boolean isAvailable = ping(temp); if (isAvailable) { - if (!isCallListener && !Thread.currentThread().isInterrupted()) { - isCallListener = true; + if (!isCallListener.get() && !Thread.currentThread().isInterrupted()) { + isCallListener.set(true); listener.onAvailableIP(temp); CupidLogUtils.i(TAG, "可用IP=" + temp); interrupted(); @@ -110,10 +115,9 @@ public class IPCFixationIPHelper { } private synchronized void allNotAvailable(final HashSet ips) { - unavailableCount++; - if (queryCount == unavailableCount) { - if (!isCallListener) { - isCallListener = true; + if (queryCount == unavailableCount.incrementAndGet()) { + if (!isCallListener.get()) { + isCallListener.set(true); listener.onAvailableIP(null); CupidLogUtils.i(TAG, "所有IP均不可用"); //当配置中的所有IP都ping不通时,需要继续ping diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceiveTimeoutManager.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceiveTimeoutManager.java index 22ad7964ad..71d3db44fb 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceiveTimeoutManager.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/ReceiveTimeoutManager.java @@ -2,6 +2,7 @@ package com.zhidao.support.adas.high.common; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicBoolean; /** * 写成单例比较好控制 比如refreshLast()方法可以放到任何接收的回调中,目前放在AutopilotStateMessage 数据接口中,此接口数据刷新不是太频繁 @@ -12,7 +13,7 @@ public class ReceiveTimeoutManager { private static final String TAG = ReceiveTimeoutManager.class.getSimpleName(); private static volatile ReceiveTimeoutManager INSTANCE; private static final long DEFAULT_TIMEOUT = 4 * 1000L;//默认超时时间 - private volatile boolean isEnable = true;//是否启用超时检测 + private final AtomicBoolean isEnable = new AtomicBoolean(true);//是否启用超时检测 private volatile long lastReceiveTime; private OnTimeoutListener listener; private volatile Timer timer; @@ -40,7 +41,7 @@ public class ReceiveTimeoutManager { } public boolean isEnable() { - return isEnable; + return isEnable.get(); } /** @@ -50,7 +51,7 @@ public class ReceiveTimeoutManager { * @param ipcConnectionStatus 当前连接状态 */ public void setEnable(boolean isEnable, @Define.IPCConnectionStatus int ipcConnectionStatus) { - this.isEnable = isEnable; + this.isEnable.set(isEnable); //如果启动并且当前已连接 if (isEnable) { if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTED) @@ -65,12 +66,12 @@ public class ReceiveTimeoutManager { * 刷新最后一次接收数据时间 */ public void refreshLast() { - if (isEnable) + if (isEnable.get()) lastReceiveTime = System.currentTimeMillis(); } public synchronized void start() { - if (isEnable) + if (isEnable.get()) if (timer == null) { refreshLast(); timer = new Timer(); diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/protocol/RawPack.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/protocol/RawPack.java index a66992829f..293b392338 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/protocol/RawPack.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/protocol/RawPack.java @@ -3,6 +3,8 @@ package com.zhidao.support.adas.high.protocol; import com.zhidao.support.adas.high.common.Constants; import com.zhidao.support.adas.high.common.DigitalTrans; +import java.util.concurrent.atomic.AtomicLong; + import mogo.telematics.pad.MessagePad; import okio.ByteString; @@ -16,22 +18,21 @@ import okio.ByteString; public class RawPack { private static final String TAG = RawPack.class.getSimpleName(); private final DefaultMessageProtocol messageProtocol; - private volatile long msgID = 0L; + private final AtomicLong msgID = new AtomicLong(0L); public RawPack() { messageProtocol = new DefaultMessageProtocol(); } - public synchronized ByteString pack(MessagePad.MessageType msgType, byte[] data) { + public synchronized ByteString pack(MessagePad.MessageType msgType, byte[] data) { if (msgType == null) { return null; } - msgID++; double time = System.nanoTime() / 1000000000.0; //封装Header MessagePad.Header.Builder headerBuilder = MessagePad.Header.newBuilder(); - headerBuilder.setMsgID(msgID);//消息唯一ID,生成数据累加。从1开始,程序或者就一直累加,断开连接或者更换连接的工控机不做重置 + headerBuilder.setMsgID(msgID.incrementAndGet());//消息唯一ID,生成数据累加。从1开始,连接未重新初始化就一直累加 headerBuilder.setMsgType(msgType); headerBuilder.setTimestamp(time); headerBuilder.setSourceTimestamp(time); diff --git a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/socket/FpgaSocket.java b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/socket/FpgaSocket.java index 46f975f2a3..bb3106009f 100644 --- a/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/socket/FpgaSocket.java +++ b/libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/socket/FpgaSocket.java @@ -23,6 +23,7 @@ import com.zhjt.service.chain.TracingConstants; import java.util.Locale; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -62,7 +63,11 @@ public class FpgaSocket implements IWebSocket { /** * 是否是用户主动关闭socket */ - private volatile boolean isUserCloseWebSocket = false; + private final AtomicBoolean isUserClose = new AtomicBoolean(false); + /** + * 是否是被动关闭 + */ + private final AtomicBoolean isPassiveClose = new AtomicBoolean(false); /** * 是否启用自动重连 */ @@ -88,8 +93,8 @@ public class FpgaSocket implements IWebSocket { ReceiveTimeoutManager.getInstance().setListener(new ReceiveTimeoutManager.OnTimeoutListener() { @Override public void onTimeout(double time) { - receiveTimeoutReason = "已超过" + time + "秒未收到工控机数据,将要进行重连"; - onClose(receiveTimeoutReason); + receiveTimeoutReason = "心跳超时(" + time + "秒)"; + onPassiveClose(receiveTimeoutReason); } }); } @@ -102,17 +107,18 @@ public class FpgaSocket implements IWebSocket { public void connectWebSocket(String address, int port) { this.ipAddress = address; this.port = port; - isUserCloseWebSocket = false; + isUserClose.set(false); + isPassiveClose.set(false); wsHost = WS_IP_HOST_HEAD + address + String.format(Locale.getDefault(), RESOURCE_PATH, port); CupidLogUtils.i(TAG, "WebSocket 主动连接= " + wsHost); init(); - connect(); + connect("连接中"); } - private void connect() { + private void connect(String msg) { if (client != null && mWebSocket == null) { if (mWebSocketConnectListener != null) - mWebSocketConnectListener.onConnecting(); + mWebSocketConnectListener.onConnecting(msg); if (request == null) request = new Request.Builder() .url(wsHost) @@ -126,15 +132,15 @@ public class FpgaSocket implements IWebSocket { */ public void reconnect() { if (isReconnect) { - if (!isUserCloseWebSocket) { + if (!isUserClose.get()) { try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } - connect(); + connect("重连中"); } else { - isUserCloseWebSocket = false; + isUserClose.set(false); } } } @@ -146,7 +152,8 @@ public class FpgaSocket implements IWebSocket { WebSocketQueueManager.getInstance().release(); WSByteQueueManager.getInstance().release(); } - isUserCloseWebSocket = true; + isUserClose.set(true); + isPassiveClose.set(false); if (mWebSocket != null) { close(true, 1000); } else { @@ -187,7 +194,7 @@ public class FpgaSocket implements IWebSocket { /** * 正在连接 */ - void onConnecting(); + void onConnecting(String msg); void onWebSocketConnectSuccess(String ipAddress, int port); @@ -270,31 +277,39 @@ public class FpgaSocket implements IWebSocket { @Override public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) { super.onClosing(webSocket, code, reason); - CupidLogUtils.e(TAG, "WebSocket onClosing= " + reason); + CupidLogUtils.e(TAG, code + "WebSocket onClosing= " + reason); + String msg = "Code=" + code + " "; if (TextUtils.isEmpty(reason)) - reason = "onClosing"; - onClose(reason); + reason = "未知原因"; + msg += reason; + onPassiveClose("Closing " + msg); } @Override public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) { super.onClosed(webSocket, code, reason); - CupidLogUtils.e(TAG, "WebSocket onClosed= " + reason); + CupidLogUtils.e(TAG, code + "WebSocket onClosed= " + reason); + String msg = "Code=" + code + " "; if (TextUtils.isEmpty(reason)) - reason = "onClosed"; - onClose(reason); + reason = "未知原因"; + msg += reason; + onPassiveClose("Closed " + msg); } @Override public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, Response response) { super.onFailure(webSocket, t, response); - CupidLogUtils.e(TAG, "WebSocket onFailure= " + t); + CupidLogUtils.e(TAG, "WebSocket onFailure 是否是被动关闭:" + isPassiveClose + " Throwable=" + t); + if (isPassiveClose.get()) { + isPassiveClose.set(false); + return; + } String reason = t.toString(); //连接异常或关闭异常不进行堆栈打印 if (!reason.toLowerCase().contains("failed to connect to") && !reason.contains("Socket closed")) - t.printStackTrace(); + CupidLogUtils.e(TAG, "WebSocket onFailure", t); if (TextUtils.isEmpty(reason)) - reason = "onFailure"; + reason = "未知原因"; if (!TextUtils.isEmpty(receiveTimeoutReason)) { reason = receiveTimeoutReason; receiveTimeoutReason = null; @@ -302,26 +317,33 @@ public class FpgaSocket implements IWebSocket { if (mWebSocket != null) { close(false, 1001); } - onConnectFailed(reason); + onConnectFailed("Failure " + reason); } } private void onConnectFailed(String reason) { + receiveTimeoutReason = null; ReceiveTimeoutManager.getInstance().stop(); if (mWebSocketConnectListener != null) { - if (isUserCloseWebSocket) + reason = "未连接 " + reason; + if (isUserClose.get()) reason = null; mWebSocketConnectListener.onWebSocketConnectFailed(reason); } reconnect(); } - private void onClose(String reason) { + /** + * 被动关闭 包含:服务断开 心跳超时 异常断开 等 + * + * @param reason + */ + private void onPassiveClose(String reason) { + isPassiveClose.set(true); if (mWebSocket != null) { close(false, 1001); - } else { - onConnectFailed(reason); } + onConnectFailed(reason); } /**