[清扫车]feat: 清扫车各控制面板中按钮点击事件及相关逻辑处理;

This commit is contained in:
aibingbing
2022-08-25 21:42:52 +08:00
parent 09f15cdbe7
commit 7e55339bb6
5 changed files with 692 additions and 155 deletions

View File

@@ -1,16 +1,30 @@
package com.mogo.och.sweeper.ui;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_BOTH_SIDE;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_LEFT_SIDE;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_RIGHT_SIDE;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_INTENSITY_STRAND;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_INTENSITY_STRONG;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_DRAW;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_SWEEP;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_WASH;
import static com.mogo.och.sweeper.util.SweeperFutianCmdUtil.CLEAN_MODE_WASH_SWEEP;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckedTextView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotVehicleStateListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
@@ -19,6 +33,11 @@ import com.mogo.eagle.core.utilcode.util.ThreadUtils;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.module.common.view.OnPreventFastClickListener;
import com.mogo.och.sweeper.R;
import com.mogo.och.sweeper.util.SweeperFutianCmdUtil;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import chassis.Chassis;
import chassis.SpecialVehicleTaskCmdOuterClass;
@@ -27,25 +46,71 @@ import chassis.VehicleStateOuterClass;
/**
* 清扫车操作面板View
*/
public class SweeperOperatePanelView extends LinearLayout{
public class SweeperOperatePanelView extends LinearLayout {
private static final String TAG = "SweeperOperatePanelView";
private static final int CMD_EXECUTE_TIMEOUT_SECONDS = 5;
private static final int CMD_EXECUTE_MOCK_SUCCESS_SECONDS = 3;
TextView mBtnMainSwitchOpenClose;//开关
TextView mBtnOperateModePureSweep;//纯扫
TextView mBtnOperateModePureWash;//纯洗
TextView mBtnOperateModeSweepWash;//洗扫
TextView mBtnOperateModePureAbsorption;//纯吸
TextView mBtnCleanDirectionLeftSide;//左侧
TextView mBtnCleanDirectionRightSide;//右侧
TextView mBtnCleanDirectionBothSide;//两侧
TextView mBtnCleanIntensityStandard;//普通
TextView mBtnCleanIntensityStrong;//强力
CheckedTextView mBtnCleanWorkOpenClose;//开关
CheckedTextView mBtnCleanModePureSweep;//纯扫
CheckedTextView mBtnCleanModePureWash;//纯洗
CheckedTextView mBtnCleanModeSweepWash;//洗扫
CheckedTextView mBtnCleanModePureAbsorption;//纯吸
CheckedTextView mBtnCleanDirectionLeftSide;//左侧
CheckedTextView mBtnCleanDirectionRightSide;//右侧
CheckedTextView mBtnCleanDirectionBothSide;//两侧
CheckedTextView mBtnCleanIntensityStandard;//普通
CheckedTextView mBtnCleanIntensityStrong;//强力
LinearLayout mLoadingContainer;//loading container
TextView mLoadingHintTop;//loading 提示-上面
TextView mLoadingHintBottom;//loading 提示-下面
// 作业模式相关操作按钮的id
List<Integer> cleanModeBtnViewIds = Arrays.asList(
R.id.btn_clean_mode_pure_sweep,
R.id.btn_clean_mode_pure_wash,
R.id.btn_clean_mode_sweep_wash,
R.id.btn_clean_mode_pure_absorption);
// 作业模式相关操作按钮,对应命令参数值
HashMap<Integer, Integer> cleanModeBtnAndCmdValueMap = new HashMap<Integer, Integer>() {
{
put(R.id.btn_clean_mode_pure_sweep, CLEAN_MODE_PURE_SWEEP);
put(R.id.btn_clean_mode_pure_wash, CLEAN_MODE_PURE_WASH);
put(R.id.btn_clean_mode_sweep_wash, CLEAN_MODE_WASH_SWEEP);
put(R.id.btn_clean_mode_pure_absorption, CLEAN_MODE_PURE_DRAW);
}
};
// 清扫方向相关操作按钮的id
List<Integer> cleanDirectionBtnViewIds = Arrays.asList(
R.id.btn_clean_direction_left_side,
R.id.btn_clean_direction_right_side,
R.id.btn_clean_direction_both_side);
// 清扫方向相关按钮操作,对应命令参数值
HashMap<Integer, Integer> cleanDirectionBtnAndCmdValueMap = new HashMap<Integer, Integer>() {
{
put(R.id.btn_clean_direction_left_side, CLEAN_DIRECTION_LEFT_SIDE);
put(R.id.btn_clean_direction_right_side, CLEAN_DIRECTION_RIGHT_SIDE);
put(R.id.btn_clean_direction_both_side, CLEAN_DIRECTION_BOTH_SIDE);
}
};
// 作业强度相关按钮操作
List<Integer> cleanIntensityBtnViewIds = Arrays.asList(
R.id.btn_clean_intensity_standard,
R.id.btn_clean_intensity_strong);
// 作业强度相关按钮操作,对应命令参数值
HashMap<Integer, Integer> cleanIntensityBtnAndCmdValueMap = new HashMap<Integer, Integer>() {
{
put(R.id.btn_clean_intensity_standard, CLEAN_INTENSITY_STRAND);
put(R.id.btn_clean_intensity_strong, CLEAN_INTENSITY_STRONG);
}
};
public SweeperOperatePanelView(Context context) {
super(context);
}
@@ -67,16 +132,16 @@ public class SweeperOperatePanelView extends LinearLayout{
private void initView(Context context) {
LayoutInflater.from(context).inflate(R.layout.sweeper_operate_panel_view, this, true);
mBtnMainSwitchOpenClose = findViewById(R.id.btn_main_switch_open_close);
mBtnOperateModePureSweep = findViewById(R.id.btn_operate_mode_pure_sweep);
mBtnOperateModePureWash = findViewById(R.id.btn_operate_mode_pure_wash);
mBtnOperateModeSweepWash = findViewById(R.id.btn_operate_mode_sweep_wash);
mBtnOperateModePureAbsorption = findViewById(R.id.btn_operate_mode_pure_absorption);
mBtnCleanDirectionLeftSide = findViewById(R.id.btn_clean_direction_left_side);
mBtnCleanDirectionRightSide = findViewById(R.id.btn_clean_direction_right_side);
mBtnCleanDirectionBothSide = findViewById(R.id.btn_clean_direction_both_side);
mBtnCleanIntensityStandard = findViewById(R.id.btn_clean_intensity_standard);
mBtnCleanIntensityStrong = findViewById(R.id.btn_clean_intensity_strong);
mBtnCleanWorkOpenClose = (CheckedTextView) findViewById(R.id.btn_clean_work_open_close);
mBtnCleanModePureSweep = (CheckedTextView) findViewById(R.id.btn_clean_mode_pure_sweep);
mBtnCleanModePureWash = (CheckedTextView) findViewById(R.id.btn_clean_mode_pure_wash);
mBtnCleanModeSweepWash = (CheckedTextView) findViewById(R.id.btn_clean_mode_sweep_wash);
mBtnCleanModePureAbsorption = (CheckedTextView) findViewById(R.id.btn_clean_mode_pure_absorption);
mBtnCleanDirectionLeftSide = (CheckedTextView) findViewById(R.id.btn_clean_direction_left_side);
mBtnCleanDirectionRightSide = (CheckedTextView) findViewById(R.id.btn_clean_direction_right_side);
mBtnCleanDirectionBothSide = (CheckedTextView) findViewById(R.id.btn_clean_direction_both_side);
mBtnCleanIntensityStandard = (CheckedTextView) findViewById(R.id.btn_clean_intensity_standard);
mBtnCleanIntensityStrong = (CheckedTextView) findViewById(R.id.btn_clean_intensity_strong);
mLoadingContainer = findViewById(R.id.loading_hint_container);
mLoadingHintTop = findViewById(R.id.loading_hint_top);
mLoadingHintBottom = findViewById(R.id.loading_hint_bottom);
@@ -84,85 +149,502 @@ public class SweeperOperatePanelView extends LinearLayout{
}
private void initViewListener() {
mBtnMainSwitchOpenClose.setOnClickListener(new OnPreventFastClickListener() {
setClickListener(mBtnCleanWorkOpenClose, (v) -> onCleanWorkBtnClick());
setClickListener(mBtnCleanModePureSweep, (v) -> onCleanModeBtnClick(v));
setClickListener(mBtnCleanModePureWash, (v) -> onCleanModeBtnClick(v));
setClickListener(mBtnCleanModeSweepWash, (v) -> onCleanModeBtnClick(v));
setClickListener(mBtnCleanModePureAbsorption, (v) -> onCleanModeBtnClick(v));
setClickListener(mBtnCleanDirectionLeftSide, (v) -> onCleanDirectionBtnClick(v));
setClickListener(mBtnCleanDirectionRightSide, (v) -> onCleanDirectionBtnClick(v));
setClickListener(mBtnCleanDirectionBothSide, (v) -> onCleanDirectionBtnClick(v));
setClickListener(mBtnCleanIntensityStandard, (v) -> onCleanIntensityBtnClick(v));
setClickListener(mBtnCleanIntensityStrong, (v) -> onCleanIntensityBtnClick(v));
}
/**
* 清扫任务开关按钮点击事件
*/
private void onCleanWorkBtnClick() {
// 是否是 关闭 操作
boolean isCloseAction = mBtnCleanWorkOpenClose.isChecked();
CmdRequestCallback cmdRequestCallback = new CmdRequestCallback() {
@Override
public void onSendCmd() {
showLoadingMask(CMD_EXECUTE_TIMEOUT_SECONDS);
}
@Override
public void onCountDownTick(int seconds) {
updateLoadingCountDown(seconds);
}
@Override
public boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) {
//TODO
return true;
}
@Override
public void onCmdSuccess() {
if (isCloseAction) {
mBtnCleanWorkOpenClose.setText("Open");
mBtnCleanWorkOpenClose.setChecked(false);
toggleCleanModeBtnsStatus(false);
toggleCleanDirectionBtnsStatus(false);
toggleCleanIntensityBtnsStatus(false);
} else {
mBtnCleanWorkOpenClose.setText("Close");
mBtnCleanWorkOpenClose.setChecked(true);
toggleCleanModeBtnsStatus(true);
}
hideLoadingMask();
showCmdExecuteSuccessToast();
}
@Override
public void onCmdFailed() {
}
@Override
public void onCmdTimeout() {
//按钮样式恢复原样
if (isCloseAction) {
mBtnCleanWorkOpenClose.setText("Close");
mBtnCleanWorkOpenClose.setChecked(true);
} else {
mBtnCleanWorkOpenClose.setText("Open");
mBtnCleanWorkOpenClose.setChecked(false);
}
hideLoadingMask();
showCmdExecuteTimeoutToast();
}
};
if (isCloseAction) {
//关闭操作,点击时需要弹框提示确认后,关闭
showConfirmCleanWorkCloseDialog(() -> {
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanWorkStopCmd(),
cmdRequestCallback
, CMD_EXECUTE_TIMEOUT_SECONDS);
});
} else {
//打开操作,点击时打开
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanWorkStartCmd(),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
}
}
/**
* 作业模式按钮点击事件
*
* @param currentClickView
*/
private void onCleanModeBtnClick(final View currentClickView) {
CheckedTextView currentChoosedModeBtnView = null;
for (Integer viewId : cleanModeBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
if (view.isChecked()) {
currentChoosedModeBtnView = view;
break;
}
}
boolean isClickCurrentChoosedModeBtn = currentChoosedModeBtnView != null
&& currentChoosedModeBtnView.getId() == currentClickView.getId();
//是否纯吸
boolean isPureAbsorption = currentClickView.getId() == R.id.btn_clean_mode_pure_absorption;
CmdRequestCallback cmdRequestCallback = new CmdRequestCallback() {
@Override
public void onSendCmd() {
showLoadingMask(CMD_EXECUTE_TIMEOUT_SECONDS);
}
@Override
public void onCountDownTick(int seconds) {
updateLoadingCountDown(seconds);
}
@Override
public boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) {
//TODO
return true;
}
@Override
public void onCmdSuccess() {
((CheckedTextView) currentClickView).setChecked(!isClickCurrentChoosedModeBtn);
toggleCleanModeBtnsByChoosedViewId(currentClickView.getId(), isClickCurrentChoosedModeBtn);
if (isClickCurrentChoosedModeBtn) {
toggleCleanDirectionBtnsStatus(false);
toggleCleanIntensityBtnsStatus(false);
} else {
// 如果是纯吸,没有设置清扫方向,同时自动设置作业强度为标准
if (isPureAbsorption) {
toggleCleanDirectionBtnsStatus(false);
setCleanIntensityStandard();
} else {
toggleCleanDirectionBtnsStatus(true);
toggleCleanIntensityBtnsStatus(false);
}
}
hideLoadingMask();
showCmdExecuteSuccessToast();
}
@Override
public void onCmdFailed() {
}
@Override
public void onCmdTimeout() {
((CheckedTextView) currentClickView).setChecked(isClickCurrentChoosedModeBtn);
hideLoadingMask();
showCmdExecuteTimeoutToast();
}
};
if (isClickCurrentChoosedModeBtn) {
//当前已选择模式的按钮,取消当前模式,并关闭清扫方向
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanModeCloseCmd(),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
} else {
//开启新的作业模式,直接发送命令(纯吸需要一并设置作业强度为标准)
int cmdValue = cleanModeBtnAndCmdValueMap.get(currentClickView.getId());
sendSweeperCmd(
isPureAbsorption ? SweeperFutianCmdUtil.buildCleanModePureDrawCmd()
: SweeperFutianCmdUtil.buildCleanModeCmd(cmdValue),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
}
}
private void onCleanDirectionBtnClick(final View currentClickView) {
CheckedTextView currentChoosedDirectionBtnView = null;
for (Integer viewId : cleanDirectionBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
if (view.isChecked()) {
currentChoosedDirectionBtnView = view;
break;
}
}
boolean isClickCurrentChoosedDirectionBtn = currentChoosedDirectionBtnView != null
&& currentChoosedDirectionBtnView.getId() == currentClickView.getId();
CmdRequestCallback cmdRequestCallback = new CmdRequestCallback() {
@Override
public void onSendCmd() {
showLoadingMask(CMD_EXECUTE_TIMEOUT_SECONDS);
}
@Override
public void onCountDownTick(int seconds) {
updateLoadingCountDown(seconds);
}
@Override
public boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) {
//TODO
return true;
}
@Override
public void onCmdSuccess() {
((CheckedTextView) currentClickView).setChecked(!isClickCurrentChoosedDirectionBtn);
toggleCleanDirectionBtnsByChoosedViewId(currentClickView.getId(), isClickCurrentChoosedDirectionBtn);
if (isClickCurrentChoosedDirectionBtn) {
toggleCleanIntensityBtnsStatus(false);
} else {
toggleCleanIntensityBtnsStatus(true);
// 一并设置作业强度为标准
setCleanIntensityStandard();
}
hideLoadingMask();
showCmdExecuteSuccessToast();
}
@Override
public void onCmdFailed() {
}
@Override
public void onCmdTimeout() {
((CheckedTextView) currentClickView).setChecked(isClickCurrentChoosedDirectionBtn);
hideLoadingMask();
showCmdExecuteTimeoutToast();
}
};
if (isClickCurrentChoosedDirectionBtn) {
//当前已选择模式的按钮,取消当前模式,重置作业强度为标准,并置灰作业强度按钮
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanDirectionCloseCmd(),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
} else {
//开启新的作业模式,直接发送命令(作业强度默认为标准)
int cmdValue = cleanDirectionBtnAndCmdValueMap.get(currentClickView.getId());
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanDirectionCmd(cmdValue),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
}
}
private void onCleanIntensityBtnClick(final View currentClickView) {
boolean isStandardBtnClick = currentClickView.getId() == R.id.btn_clean_intensity_standard;
CmdRequestCallback cmdRequestCallback = new CmdRequestCallback() {
@Override
public void onSendCmd() {
showLoadingMask(CMD_EXECUTE_TIMEOUT_SECONDS);
}
@Override
public void onCountDownTick(int seconds) {
updateLoadingCountDown(seconds);
}
@Override
public boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) {
//TODO
return true;
}
@Override
public void onCmdSuccess() {
((CheckedTextView) currentClickView).setChecked(true);
if (isStandardBtnClick) {
setCleanIntensityStandard();
} else {
setCleanIntensityStrong();
}
hideLoadingMask();
showCmdExecuteSuccessToast();
}
@Override
public void onCmdFailed() {
}
@Override
public void onCmdTimeout() {
((CheckedTextView) currentClickView).setChecked(false);
hideLoadingMask();
showCmdExecuteTimeoutToast();
}
};
int cmdValue = cleanIntensityBtnAndCmdValueMap.get(currentClickView.getId());
sendSweeperCmd(
SweeperFutianCmdUtil.buildCleanIntensityCmd(cmdValue),
cmdRequestCallback,
CMD_EXECUTE_TIMEOUT_SECONDS);
}
/**
* 作业模式按钮状态切换-置灰/开启 按钮
*
* @param enable
*/
private void toggleCleanModeBtnsStatus(boolean enable) {
for (Integer viewId : cleanModeBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
view.setEnabled(enable);
view.setChecked(false);
}
}
/**
* 作业模式按钮状态切换-将当前点击按钮之外的其他按钮 置灰或开启
*
* @param choosedBtnId
* @param enable
*/
private void toggleCleanModeBtnsByChoosedViewId(int choosedBtnId, boolean enable) {
for (Integer viewId : cleanModeBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
if (view.getId() != choosedBtnId) {
view.setEnabled(enable);
view.setChecked(false);
}
}
}
/**
* 清扫方向按钮状态切换-置灰/开启 按钮
*
* @param enable
*/
private void toggleCleanDirectionBtnsStatus(boolean enable) {
for (Integer viewId : cleanDirectionBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
view.setEnabled(enable);
view.setChecked(false);
}
}
/**
* 清扫方向按钮状态切换-将当前点击按钮之外的其他按钮 置灰或开启
*
* @param choosedBtnId
* @param enable
*/
private void toggleCleanDirectionBtnsByChoosedViewId(int choosedBtnId, boolean enable) {
for (Integer viewId : cleanDirectionBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
if (view.getId() != choosedBtnId) {
view.setEnabled(enable);
view.setChecked(false);
}
}
}
/**
* 作业强度按钮状态切换-置灰/开启 按钮
*
* @param enable
*/
private void toggleCleanIntensityBtnsStatus(boolean enable) {
for (Integer viewId : cleanIntensityBtnViewIds) {
CheckedTextView view = (CheckedTextView) findViewById(viewId);
view.setEnabled(enable);
view.setChecked(false);
}
}
/**
* 设置作业强度-标准
*/
private void setCleanIntensityStandard() {
mBtnCleanIntensityStandard.setChecked(true);
mBtnCleanIntensityStandard.setEnabled(true);
mBtnCleanIntensityStrong.setChecked(false);
mBtnCleanIntensityStrong.setEnabled(true);
}
/**
* 设置作业强度-加强
*/
private void setCleanIntensityStrong() {
mBtnCleanIntensityStandard.setChecked(false);
mBtnCleanIntensityStandard.setEnabled(true);
mBtnCleanIntensityStrong.setChecked(true);
mBtnCleanIntensityStrong.setEnabled(true);
}
/**
* 发送命令后等待时展示loading
*
* @param timeout
*/
private void showLoadingMask(int timeout) {
showLoadingMask("执行中,请稍后。。。", timeout);
}
/**
* 发送命令后等待时展示loading
*
* @param hint
* @param timeout
*/
private void showLoadingMask(String hint, int timeout) {
runOnUIThread(() -> {
mLoadingContainer.setVisibility(View.VISIBLE);
mLoadingHintTop.setText(hint);
mLoadingHintBottom.setText(
String.format(
getContext().getApplicationContext().getString(R.string.sweeper_operate_panel_cmd_execute_timeout),
timeout
));
});
}
/**
* 隐藏loading
*/
private void hideLoadingMask() {
runOnUIThread(() -> {
mLoadingContainer.setVisibility(View.GONE);
});
}
/**
* 更新loading中倒计时
*
* @param timeout
*/
private void updateLoadingCountDown(int timeout) {
runOnUIThread(() -> {
mLoadingHintBottom.setText(
String.format(
getContext().getApplicationContext().getString(R.string.sweeper_operate_panel_cmd_execute_timeout),
timeout
));
});
}
/**
* 命令执行成功toast
*/
private void showCmdExecuteSuccessToast() {
ToastUtils.showLong("设备已响应,操作成功");
}
/**
* 命令执行超时toast
*/
private void showCmdExecuteTimeoutToast() {
ToastUtils.showLong("超时未响应,操作失败");
}
/**
* 关闭清扫作业时,确认操作的弹框
*
* @param runnable
*/
private void showConfirmCleanWorkCloseDialog(Runnable runnable) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMessage("是否关闭清扫作业?");
builder.setCancelable(true);
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
runnable.run();
dialog.dismiss();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private void runOnUIThread(Runnable runnable) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
runnable.run();
}
});
}
private void setClickListener(View view, OnClickListener listener) {
view.setOnClickListener(new OnPreventFastClickListener() {
@Override
public void onClickImpl(View v) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd fuTianCleanCmd = builder.build();
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd fuTianTaskCmd = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd.newBuilder()
.setRoboSweeperFutianCleanCmd(fuTianCleanCmd).build();
sendSweeperCmd(fuTianTaskCmd, new CmdRequestCallback() {
@Override
public void onSendCmd() {
showLoadingMask("命令执行中。。。", 10);
}
@Override
public void onCountDownTick(int senonds) {
updateLoadingCountDown(senonds);
}
@Override
public boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) {
return false;
}
@Override
public void onCmdSuccess() {
ToastUtils.showLong("执行成功");
}
@Override
public void onCmdFailed() {
}
@Override
public void onCmdTimeout() {
hideLoadingMask();
}
}, 10);
}
});
}
private void showLoadingMask(String hint, int timeout) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadingContainer.setVisibility(View.VISIBLE);
mLoadingHintTop.setText(hint);
mLoadingHintBottom.setText(
String.format(
getContext().getApplicationContext().getString(R.string.sweeper_operate_panel_cmd_execute_timeout),
timeout
));
}
});
}
private void hideLoadingMask() {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadingContainer.setVisibility(View.GONE);
}
});
}
private void updateLoadingCountDown(int timeout) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadingHintBottom.setText(
String.format(
getContext().getApplicationContext().getString(R.string.sweeper_operate_panel_cmd_execute_timeout),
timeout
));
listener.onClick(v);
}
});
}
/**
* 底盘数据透传listener
*/
private final IMoGoAutopilotVehicleStateListener mIMoGoAutopilotVehicleStateListener = new IMoGoAutopilotVehicleStateListener() {
@Override
public void onAutopilotDataException(long timestamp) {
@@ -221,7 +703,7 @@ public class SweeperOperatePanelView extends LinearLayout{
}
/**
* 发送清扫车作业命令
* 发送清扫车相关作业命令
*
* @param fuTianCleanCmd
* @param cmdRequestCallback
@@ -237,17 +719,41 @@ public class SweeperOperatePanelView extends LinearLayout{
mCurrentCmdRequestCallback.onSendCmd();
// 发送命令
CallerAutoPilotManager.INSTANCE.sendSweeperFuTianTaskCmd(fuTianCleanCmd);
// log发送命令
logSweeperCmdValue(fuTianCleanCmd);
// 开启倒计时
Message msg = Message.obtain();
msg.what = MSG_CMD_EXECUTE_COUNT_DOWN;
msg.obj = timeout;
mSweeperOperateCmdHandler.sendMessage(msg);
// Mock Cmd Success
Message successMsg = Message.obtain();
successMsg.what = MSG_CMD_EXECUTE_MOCK_SUCCESS;
mSweeperOperateCmdHandler.sendMessageDelayed(successMsg, 1000L * CMD_EXECUTE_MOCK_SUCCESS_SECONDS);
}
private void logSweeperCmdValue(SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd taskCmd) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd roboSweeperFutianCleanCmd = taskCmd.getRoboSweeperFutianCleanCmd();
int clean_open_requirement = roboSweeperFutianCleanCmd.getCleanOpenRequirement();
int clean_mode_requirement = roboSweeperFutianCleanCmd.getCleanModeRequirement();
int clean_direction_requirement = roboSweeperFutianCleanCmd.getCleanDirectionRequirement();
int clean_intensity_requirement = roboSweeperFutianCleanCmd.getCleanIntensityRequirement();
Log.d(TAG, "---- sendSweeperFuTianTaskCmd ----"
+ "[clean_open_requirement = " + clean_open_requirement + "],"
+ "[clean_mode_requirement = " + clean_mode_requirement + "],"
+ "[clean_direction_requirement = " + clean_direction_requirement + "],"
+ "[clean_intensity_requirement = " + clean_intensity_requirement + "]"
);
}
private final static SweeperOperateCmdHandler mSweeperOperateCmdHandler = new SweeperOperateCmdHandler();
private static CmdRequestCallback mCurrentCmdRequestCallback;
private static final int MSG_CMD_EXECUTE_COUNT_DOWN = 10001;
private static final int MSG_CMD_EXECUTE_MOCK_SUCCESS = 10002;
/**
* 执行命令时倒计时的Handler
*/
static class SweeperOperateCmdHandler extends Handler {
@Override
@@ -256,17 +762,26 @@ public class SweeperOperatePanelView extends LinearLayout{
if (msg.what == MSG_CMD_EXECUTE_COUNT_DOWN) {
int seconds = (int) msg.obj;
if (seconds > 0) {
mCurrentCmdRequestCallback.onCountDownTick(seconds);
if (mCurrentCmdRequestCallback != null) {
mCurrentCmdRequestCallback.onCountDownTick(seconds);
}
Message newMsg = Message.obtain();
newMsg.what = MSG_CMD_EXECUTE_COUNT_DOWN;
newMsg.obj = seconds-1;
newMsg.obj = seconds - 1;
mSweeperOperateCmdHandler.sendMessageDelayed(newMsg, 1000L);
} else {
if (mCurrentCmdRequestCallback != null) {
mCurrentCmdRequestCallback.onCmdTimeout();
mCurrentCmdRequestCallback = null;
}
removeMessages(MSG_CMD_EXECUTE_COUNT_DOWN);
}
} else if (msg.what == MSG_CMD_EXECUTE_MOCK_SUCCESS) {
if (mCurrentCmdRequestCallback != null) {
mCurrentCmdRequestCallback.onCmdSuccess();
mCurrentCmdRequestCallback = null;
}
removeMessages(MSG_CMD_EXECUTE_COUNT_DOWN);
}
}
}

View File

@@ -8,17 +8,17 @@ import chassis.SpecialVehicleTaskCmdOuterClass;
public class SweeperFutianCmdUtil {
private static final int CLEAN_WORK_OPEN = 1; //清扫作业-开启
private static final int CLEAN_WORK_CLOSE = 2;//清扫作业-关闭
private static final int CLEAN_MODE_PURE_SWEEP = 1;//作业模式-纯扫
private static final int CLEAN_MODE_WASH_SWEEP = 2;//作业模式-洗扫
private static final int CLEAN_MODE_PURE_WASH = 3;//作业模式-纯洗
private static final int CLEAN_MODE_PURE_DRAW = 4;//作业模式-纯吸
public static final int CLEAN_MODE_PURE_SWEEP = 1;//作业模式-纯扫
public static final int CLEAN_MODE_WASH_SWEEP = 2;//作业模式-洗扫
public static final int CLEAN_MODE_PURE_WASH = 3;//作业模式-纯洗
public static final int CLEAN_MODE_PURE_DRAW = 4;//作业模式-纯吸
private static final int CLEAN_MODE_CLOSE = 5;//作业模式-关闭
private static final int CLEAN_DIRECTION_BOTH_SIDE = 1;//清扫方向-两侧
private static final int CLEAN_DIRECTION_LEFT_SIDE = 2;//清扫方向-左侧
private static final int CLEAN_DIRECTION_RIGHT_SIDE = 3;//清扫方向-右侧
public static final int CLEAN_DIRECTION_BOTH_SIDE = 1;//清扫方向-两侧
public static final int CLEAN_DIRECTION_LEFT_SIDE = 2;//清扫方向-左侧
public static final int CLEAN_DIRECTION_RIGHT_SIDE = 3;//清扫方向-右侧
private static final int CLEAN_DIRECTION_CLOSE = 4;//清扫方向-关闭
private static final int CLEAN_INTENSITY_STRAND = 1;//作业强度-标准
private static final int CLEAN_INTENSITY_STRONG = 2;//作业强度-加强
public static final int CLEAN_INTENSITY_STRAND = 1;//作业强度-标准
public static final int CLEAN_INTENSITY_STRONG = 2;//作业强度-加强
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkStartCmd() {
return buildCleanWorkCmd(CLEAN_WORK_OPEN);
@@ -40,29 +40,41 @@ public class SweeperFutianCmdUtil {
return buildTaskCmd(builder.build());
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModePureDrawCmd() {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanModeRequirement(CLEAN_MODE_PURE_DRAW);
//不用设置作业方向,自动设置作业强度为:标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModeCloseCmd() {
return buildCleanModeCmd(CLEAN_MODE_CLOSE);
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanModeRequirement(CLEAN_MODE_CLOSE);
//关闭清扫方向,待下次在选择
builder.setCleanDirectionRequirement(CLEAN_DIRECTION_CLOSE);
//自动设置作业强度为:标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanDirectionCmd(int value) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanDirectionRequirement(value);
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
// 同时作业强度默认:标准
return buildTaskCmd(builder.build());
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanDirectionCloseCmd() {
return buildCleanDirectionCmd(CLEAN_DIRECTION_CLOSE);
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanDirectionRequirement(CLEAN_DIRECTION_CLOSE);
//重置作业强度为标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityStandardCmd() {
return buildCleanIntensityCmd(CLEAN_INTENSITY_STRAND);
}
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityStrongCmd() {
return buildCleanIntensityCmd(CLEAN_INTENSITY_STRONG);
}
private static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityCmd(int value) {
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityCmd(int value) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanIntensityRequirement(value);
return buildTaskCmd(builder.build());

View File

@@ -1,4 +1,4 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_close" android:state_selected="true"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_open" />
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_close" android:state_checked="true"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_open" android:state_checked="false"/>
</selector>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_disabled" android:state_enabled="false"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_pressed" android:state_selected="true"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_default" />
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_disabled" android:state_enabled="false" android:state_checked="false"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_pressed" android:state_enabled="true" android:state_checked="true"/>
<item android:drawable="@drawable/bg_sweeper_operate_panel_btn_default" android:state_enabled="true" android:state_checked="false"/>
</selector>

View File

@@ -6,7 +6,7 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/hint_main_switch"
android:id="@+id/hint_clean_work"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffff"
@@ -16,8 +16,8 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/btn_main_switch_open_close"
<CheckedTextView
android:id="@+id/btn_clean_work_open_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_32"
@@ -27,20 +27,21 @@
android:paddingEnd="@dimen/dp_20"
android:paddingBottom="@dimen/dp_6"
android:text="open"
android:checked="false"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toRightOf="@id/hint_main_switch"
app:layout_constraintTop_toTopOf="@id/hint_main_switch" />
app:layout_constraintLeft_toRightOf="@id/hint_clean_work"
app:layout_constraintTop_toTopOf="@id/hint_clean_work" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/main_switch_barrier"
android:id="@+id/clean_work_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="hint_main_switch, btn_main_switch_open_close" />
app:constraint_referenced_ids="hint_clean_work, btn_clean_work_open_close" />
<TextView
android:id="@+id/hint_operate_mode"
android:id="@+id/hint_clean_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_32"
@@ -49,10 +50,10 @@
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/main_switch_barrier" />
app:layout_constraintTop_toBottomOf="@id/clean_work_barrier" />
<TextView
android:id="@+id/btn_operate_mode_pure_sweep"
<CheckedTextView
android:id="@+id/btn_clean_mode_pure_sweep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_32"
@@ -64,11 +65,12 @@
android:text="纯扫"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toRightOf="@id/hint_operate_mode"
app:layout_constraintTop_toTopOf="@id/hint_operate_mode" />
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/hint_clean_mode"
app:layout_constraintTop_toTopOf="@id/hint_clean_mode" />
<TextView
android:id="@+id/btn_operate_mode_pure_wash"
<CheckedTextView
android:id="@+id/btn_clean_mode_pure_wash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_32"
@@ -80,11 +82,12 @@
android:text="纯洗"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toRightOf="@id/btn_operate_mode_pure_sweep"
app:layout_constraintTop_toTopOf="@id/hint_operate_mode" />
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/btn_clean_mode_pure_sweep"
app:layout_constraintTop_toTopOf="@id/hint_clean_mode" />
<TextView
android:id="@+id/btn_operate_mode_sweep_wash"
<CheckedTextView
android:id="@+id/btn_clean_mode_sweep_wash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_32"
@@ -96,11 +99,12 @@
android:text="洗扫"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toLeftOf="@id/btn_operate_mode_pure_sweep"
app:layout_constraintTop_toBottomOf="@id/btn_operate_mode_pure_sweep" />
android:enabled="false"
app:layout_constraintLeft_toLeftOf="@id/btn_clean_mode_pure_sweep"
app:layout_constraintTop_toBottomOf="@id/btn_clean_mode_pure_sweep" />
<TextView
android:id="@+id/btn_operate_mode_pure_absorption"
<CheckedTextView
android:id="@+id/btn_clean_mode_pure_absorption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_32"
@@ -112,15 +116,16 @@
android:text="纯吸"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toRightOf="@id/btn_operate_mode_sweep_wash"
app:layout_constraintTop_toTopOf="@id/btn_operate_mode_sweep_wash" />
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/btn_clean_mode_sweep_wash"
app:layout_constraintTop_toTopOf="@id/btn_clean_mode_sweep_wash" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/operate_mode_barrier"
android:id="@+id/clean_mode_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="hint_operate_mode, btn_operate_mode_pure_sweep, btn_operate_mode_pure_wash, btn_operate_mode_sweep_wash, btn_operate_mode_pure_absorption" />
app:constraint_referenced_ids="hint_clean_mode, btn_clean_mode_pure_sweep, btn_clean_mode_pure_wash, btn_clean_mode_sweep_wash, btn_clean_mode_pure_absorption" />
<TextView
android:id="@+id/hint_clean_direction"
@@ -132,9 +137,9 @@
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/operate_mode_barrier" />
app:layout_constraintTop_toBottomOf="@id/clean_mode_barrier" />
<TextView
<CheckedTextView
android:id="@+id/btn_clean_direction_left_side"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -147,10 +152,11 @@
android:text="左侧"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/hint_clean_direction"
app:layout_constraintTop_toTopOf="@id/hint_clean_direction" />
<TextView
<CheckedTextView
android:id="@+id/btn_clean_direction_right_side"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -163,10 +169,11 @@
android:text="右侧"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/btn_clean_direction_left_side"
app:layout_constraintTop_toTopOf="@id/hint_clean_direction" />
<TextView
<CheckedTextView
android:id="@+id/btn_clean_direction_both_side"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -179,6 +186,7 @@
android:text="两侧"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
android:enabled="false"
app:layout_constraintLeft_toLeftOf="@id/btn_clean_direction_left_side"
app:layout_constraintTop_toBottomOf="@id/btn_clean_direction_left_side" />
@@ -201,7 +209,7 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/clean_direction_barrier" />
<TextView
<CheckedTextView
android:id="@+id/btn_clean_intensity_standard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -214,10 +222,11 @@
android:text="标准"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/hint_clean_intensity"
app:layout_constraintTop_toTopOf="@id/hint_clean_intensity" />
<TextView
<CheckedTextView
android:id="@+id/btn_clean_intensity_strong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -230,6 +239,7 @@
android:text="强力"
android:textColor="#000000"
android:textSize="@dimen/sweeper_operate_panel_btn_text_size"
android:enabled="false"
app:layout_constraintLeft_toRightOf="@id/btn_clean_intensity_standard"
app:layout_constraintTop_toTopOf="@id/hint_clean_intensity" />