[change]将连接状态变更以文字方式回调到鹰眼,用于排查断开连接或者重连问题

This commit is contained in:
xinfengkun
2022-04-24 15:14:51 +08:00
parent 90da3537a6
commit 94b4a81178
14 changed files with 458 additions and 110 deletions

View File

@@ -29,7 +29,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:allowBackup="true"
android:icon="@drawable/icon"

View File

@@ -0,0 +1,67 @@
package com.zhidao.adas.client.adapter;
import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.base.BaseAdapter;
import com.zhidao.adas.client.base.BaseViewHolder;
import com.zhidao.adas.client.bean.IPCConnectState;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* 连接状态
*/
public class ConnectStatusAdapter extends BaseAdapter<IPCConnectState, ConnectStatusAdapter.ViewHolder> {
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<ConnectStatusAdapter> {
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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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<IPCConnectState> list;
public FloatWindow(Activity context, List<IPCConnectState> 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;
}
}

View File

@@ -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<String> titleFragmentData = new ArrayList<>();
private final List<String> titleBtnData = new ArrayList<>();
private final List<IPCConnectState> 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));

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FAFFFFFF" />
<stroke
android:width="0.8dp"
android:color="#A140E0D0" />
<!-- 圆角 -->
<corners android:radius="6dp" />
</shape>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?><!--测试列表Item-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="3dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="3dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal">
<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textSize="12sp" />
<EditText
android:id="@+id/log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:cursorVisible="false"
android:focusable="false"
android:textColor="#ff0000"
android:textSize="12sp" />
</LinearLayout>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_float"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_status"
android:layout_width="260dp"
android:layout_height="280dp" />
</LinearLayout>

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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<Future> 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<String> 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

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
}
/**