[工控机监控]添加ping命令用于检测设备连通性

This commit is contained in:
xinfengkun
2023-03-17 17:25:59 +08:00
parent 5a76fc8840
commit 3d0338e0a8
7 changed files with 420 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
package com.zhidao.adas.client.adapter;
import android.annotation.SuppressLint;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -38,7 +39,8 @@ public class ConnectStatusAdapter extends BaseAdapter<IPCConnectState, ConnectSt
@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);
String str = "<font color='#999999'>" + sdf.format(new Date(data.time)) + "\n</font> <br />" + data.status;
viewHolder.editText.setText(Html.fromHtml(str));
viewHolder.editText.setTextColor(mContext.getResources().getColor(data.color));
}

View File

@@ -17,6 +17,7 @@ import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
@@ -43,6 +44,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator;
import com.google.protobuf.TextFormat;
import com.mogo.support.obu.ObuScene;
import com.mogo.support.obu.constants.MogoObuConstants;
import com.zhidao.adas.client.App;
import com.zhidao.adas.client.BuildConfig;
import com.zhidao.adas.client.DataDistribution;
@@ -79,6 +81,7 @@ import com.zhidao.support.adas.high.common.Constants.IPC_CONNECTION_STATUS;
import com.zhidao.support.adas.high.common.CupidLogUtils;
import com.zhidao.support.adas.high.common.ProtocolStatus;
import com.zhidao.support.adas.high.common.ReceiveTimeoutManager;
import com.zhidao.support.adas.high.common.RegexUtils;
import com.zhjt.mogo.adas.data.bean.AutopilotStatistics;
import org.jetbrains.annotations.NotNull;
@@ -139,7 +142,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
private RecyclerView infoFragment;
private TextView tvConnectState;
private ScheduledExecutorService mExecutorServiceConfigTimer;
private PingFloatWindow pingFloatWindow;
private final List<String> titleFragmentData = new ArrayList<>();
private final List<String> titleBtnData = new ArrayList<>();
@@ -291,6 +294,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
private void initView() {
ImageView btn_ping = findViewById(R.id.btn_ping);
include_title = findViewById(R.id.include_title);
etIp = findViewById(R.id.et_ip);
background = findViewById(R.id.background);
@@ -589,6 +593,67 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
} else {
background.setVisibility(View.GONE);
}
btn_ping.setSelected(pingFloatWindow != null);
btn_ping.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (pingFloatWindow == null) {
Pair<String, Integer> pair = getInputIp();
if (pair != null) {
pingFloatWindow = new PingFloatWindow(MainActivity.this, pair.first);
int[] location = new int[2];
btn_ping.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
pingFloatWindow.showFloatWindow(x + (btn_ping.getWidth() / 2) - 260, btn_ping.getY() + btn_ping.getHeight());
}
} else {
pingFloatWindow.hideFloatWindow();
pingFloatWindow = null;
}
btn_ping.setSelected(pingFloatWindow != null);
}
});
}
private Pair<String, Integer> getInputIp() {
String address = etIp.getText().toString().trim();
if (TextUtils.isEmpty(address)) {
Toast.makeText(this, "请输入OBU地址", Toast.LENGTH_SHORT).show();
return null;
}
String tempIp;
int tempPort;
if (address.contains(":")) {
String[] temp = address.split(":");
if (temp.length < 2) {
Toast.makeText(this, "地址输入有误", Toast.LENGTH_SHORT).show();
return null;
}
tempIp = temp[0];
try {
tempPort = Integer.parseInt(temp[1]);
if (tempPort <= 0 || tempPort > 65535) {
Toast.makeText(this, "端口范围溢出", Toast.LENGTH_SHORT).show();
return null;
}
} catch (NumberFormatException e) {
e.printStackTrace();
Toast.makeText(this, "端口不合法", Toast.LENGTH_SHORT).show();
return null;
}
} else {
tempIp = address;
tempPort = MogoObuConstants.DEFAULT_OBU_PORT;
}
if (!RegexUtils.isIP(tempIp)) {
Toast.makeText(this, "地址不合法", Toast.LENGTH_SHORT).show();
return null;
}
return new Pair<>(tempIp, tempPort);
}
private void showListPopupWindow() {

View File

@@ -0,0 +1,310 @@
package com.zhidao.adas.client.ui;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
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.mogo.support.obu.common.L;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.adapter.ConnectStatusAdapter;
import com.zhidao.adas.client.bean.IPCConnectState;
import com.zhidao.adas.client.utils.MyLinearLayoutManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
/**
* ping命令窗口
*/
public class PingFloatWindow implements View.OnTouchListener {
private static final String TAG = PingFloatWindow.class.getSimpleName();
private static final int WHAT_STATE = 8;
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 final List<IPCConnectState> list = new ArrayList<>();
private final String ip;
private Timer timer;
public PingFloatWindow(Activity context, String ip) {
this.mContext = context;
this.ip = ip;
initFloatWindow();
initHandler();
pingTimer(true);
}
private void pingTimer(boolean isStart) {
if (isStart) {
if (timer == null) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
ping();
}
}, 100L, 2500L);//延时
}
} else {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
private void ping() {
Process p;
try {
//ping -c 3 -w 100 中 -c 是指ping的次数 3是指ping 3次 -w 100 以秒为单位指定超时间隔是指超时时间为100秒
p = Runtime.getRuntime().exec("ping -c 1 -w 2 " + ip);
int status = p.waitFor();
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuilder builder = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
builder.append(line).append("\n");
}
String str = "IP:" + ip + " 是否可以连通:" + (status == 0 ? "" : "");
L.i(TAG, builder.toString() + str);
add(str, status == 0);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
private void add(String str, boolean isConnect) {
int color;
if (isConnect) {
color = R.color.connect_status_connected;
} else {
color = R.color.connect_status_disconnected;
}
IPCConnectState status = new IPCConnectState(str, color);
list.add(0, status);
if (list.size() > 100) {
list.remove(list.size() - 1);
}
Message msg = Message.obtain();
msg.what = WHAT_STATE;
getHandler().sendMessage(msg);
}
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 x, float y) {
if (mFloatLayout.getParent() == null) {
// DisplayMetrics metrics = new DisplayMetrics();
// 默认固定位置,靠屏幕右边缘的中间
// mWindowManager.getDefaultDisplay().getMetrics(metrics);
mWindowParams.x = (int) x;
mWindowParams.y = (int) (y);
mWindowManager.addView(mFloatLayout, mWindowParams);
}
}
public void hideFloatWindow() {
pingTimer(false);
if (getHandler() != null) {
getHandler().removeCallbacksAndMessages(null);
}
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;
}
private BaseHandler mBaseHandler;
/**
* 初始化一个Handler如果需要使用Handler先调用此方法
* 然后可以使用postRunnable(Runnable runnable)
* sendMessage在handleMessageMessage msg中接收msg
*/
public void initHandler() {
mBaseHandler = new BaseHandler(this);
}
/**
* 返回Handler在此之前确定已经调用initHandler
*
* @return Handler
*/
public Handler getHandler() {
return mBaseHandler;
}
/**
* 同Handler 的 handleMessage
* getHandler.sendMessage,发送的Message在此接收
* 在此之前确定已经调用initHandler
*
* @param msg
*/
protected void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_STATE:
refreshView();
break;
}
}
protected static class BaseHandler extends Handler {
private final WeakReference<PingFloatWindow> mObjects;
public BaseHandler(PingFloatWindow mPresenter) {
mObjects = new WeakReference<PingFloatWindow>(mPresenter);
}
@Override
public void handleMessage(Message msg) {
PingFloatWindow mPresenter = mObjects.get();
if (mPresenter != null)
mPresenter.handleMessage(msg);
}
}
}

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M998.4,262.4c0,-38.4 -32,-70.4 -70.4,-70.4H518.4L448,134.4c-6.4,-6.4 -12.8,-6.4 -12.8,-6.4h-320c-51.2,-6.4 -89.6,38.4 -89.6,89.6v569.6c0,64 51.2,108.8 108.8,108.8H672c12.8,0 25.6,-12.8 25.6,-25.6s-12.8,-25.6 -25.6,-25.6H134.4c-32,0 -64,-25.6 -64,-64V217.6c0,-25.6 19.2,-44.8 44.8,-44.8H416l230.4,185.6h307.2v428.8c0,32 -25.6,64 -64,64h-32c-12.8,0 -25.6,12.8 -25.6,25.6s12.8,25.6 25.6,25.6h32c64,0 108.8,-51.2 108.8,-108.8V262.4z"
android:fillColor="#ffffff"/>
<path
android:pathData="M249.6,460.8h-64v204.8L224,665.6v-83.2h70.4c6.4,0 12.8,-6.4 19.2,-12.8 6.4,0 12.8,-12.8 19.2,-19.2s6.4,-19.2 6.4,-32c0,-19.2 -6.4,-32 -12.8,-38.4 -6.4,-6.4 -12.8,-19.2 -25.6,-19.2h-51.2zM294.4,537.6c0,6.4 -6.4,6.4 -12.8,12.8s-19.2,0 -32,0L224,550.4v-57.6h51.2c6.4,0 12.8,6.4 19.2,6.4v38.4zM371.2,460.8h38.4v204.8h-38.4zM492.8,460.8h-38.4v198.4h38.4v-128l76.8,128h44.8L614.4,460.8L576,460.8v134.4zM838.4,550.4h-89.6v32h44.8L793.6,608c-6.4,6.4 -12.8,6.4 -19.2,12.8 -6.4,6.4 -19.2,6.4 -25.6,6.4 -19.2,0 -32,-6.4 -44.8,-19.2 -12.8,-12.8 -19.2,-32 -19.2,-51.2 0,-19.2 6.4,-38.4 12.8,-51.2 12.8,-12.8 25.6,-19.2 44.8,-19.2 12.8,0 19.2,0 32,6.4 6.4,6.4 12.8,12.8 19.2,25.6l44.8,-6.4c-6.4,-19.2 -12.8,-32 -25.6,-44.8 -12.8,-12.8 -32,-12.8 -57.6,-12.8 -19.2,0 -38.4,6.4 -51.2,12.8 -19.2,6.4 -32,19.2 -38.4,38.4 -6.4,19.2 -12.8,32 -12.8,57.6 0,19.2 6.4,38.4 12.8,51.2 6.4,19.2 19.2,32 38.4,38.4 12.8,6.4 32,12.8 57.6,12.8 19.2,0 32,0 51.2,-6.4s19.2,-19.2 25.6,-25.6v-83.2z"
android:fillColor="#ffffff"/>
</vector>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#D81B60"
android:pathData="M998.4,262.4c0,-38.4 -32,-70.4 -70.4,-70.4H518.4L448,134.4c-6.4,-6.4 -12.8,-6.4 -12.8,-6.4h-320c-51.2,-6.4 -89.6,38.4 -89.6,89.6v569.6c0,64 51.2,108.8 108.8,108.8H672c12.8,0 25.6,-12.8 25.6,-25.6s-12.8,-25.6 -25.6,-25.6H134.4c-32,0 -64,-25.6 -64,-64V217.6c0,-25.6 19.2,-44.8 44.8,-44.8H416l230.4,185.6h307.2v428.8c0,32 -25.6,64 -64,64h-32c-12.8,0 -25.6,12.8 -25.6,25.6s12.8,25.6 25.6,25.6h32c64,0 108.8,-51.2 108.8,-108.8V262.4z" />
<path
android:fillColor="#D81B60"
android:pathData="M249.6,460.8h-64v204.8L224,665.6v-83.2h70.4c6.4,0 12.8,-6.4 19.2,-12.8 6.4,0 12.8,-12.8 19.2,-19.2s6.4,-19.2 6.4,-32c0,-19.2 -6.4,-32 -12.8,-38.4 -6.4,-6.4 -12.8,-19.2 -25.6,-19.2h-51.2zM294.4,537.6c0,6.4 -6.4,6.4 -12.8,12.8s-19.2,0 -32,0L224,550.4v-57.6h51.2c6.4,0 12.8,6.4 19.2,6.4v38.4zM371.2,460.8h38.4v204.8h-38.4zM492.8,460.8h-38.4v198.4h38.4v-128l76.8,128h44.8L614.4,460.8L576,460.8v134.4zM838.4,550.4h-89.6v32h44.8L793.6,608c-6.4,6.4 -12.8,6.4 -19.2,12.8 -6.4,6.4 -19.2,6.4 -25.6,6.4 -19.2,0 -32,-6.4 -44.8,-19.2 -12.8,-12.8 -19.2,-32 -19.2,-51.2 0,-19.2 6.4,-38.4 12.8,-51.2 12.8,-12.8 25.6,-19.2 44.8,-19.2 12.8,0 19.2,0 32,6.4 6.4,6.4 12.8,12.8 19.2,25.6l44.8,-6.4c-6.4,-19.2 -12.8,-32 -25.6,-44.8 -12.8,-12.8 -32,-12.8 -57.6,-12.8 -19.2,0 -38.4,6.4 -51.2,12.8 -19.2,6.4 -32,19.2 -38.4,38.4 -6.4,19.2 -12.8,32 -12.8,57.6 0,19.2 6.4,38.4 12.8,51.2 6.4,19.2 19.2,32 38.4,38.4 12.8,6.4 32,12.8 57.6,12.8 19.2,0 32,0 51.2,-6.4s19.2,-19.2 25.6,-25.6v-83.2z" />
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_ping_selected" android:state_selected="true" />
<item android:drawable="@drawable/ic_ping" />
</selector>

View File

@@ -17,9 +17,9 @@
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:minWidth="110dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minWidth="110dp"
android:text="@string/app_name"
android:textColor="@color/colorWhile"
android:textSize="18sp"
@@ -288,10 +288,20 @@
<ImageView
android:id="@+id/btn_router"
android:layout_width="40dp"
android:layout_gravity="center_vertical"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="18dp"
android:src="@drawable/selector_router" />
<ImageView
android:id="@+id/btn_ping"
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="30dp"
android:padding="3dp"
android:scaleType="centerInside"
android:src="@drawable/selector_ping" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>