diff --git a/OCH/README.md b/OCH/README.md index 1c22eb2ceb..8b20c7f940 100644 --- a/OCH/README.md +++ b/OCH/README.md @@ -3,4 +3,5 @@ 2. mogo-och-bus-passenger:Bus乘客端(BusPassenger) 3. mogo-och-taxi:Taxi司机端(Taxi) 4. mogo-och-taxi-passenger:Taxi乘客端(TaxiPassenger) -5. mogo-och-noop:空实现,用于独立鹰眼打包 \ No newline at end of file +5. mogo-och-noop:空实现,用于独立鹰眼打包 +6. mogo-och-sweeper: 清扫车(Sweeper) \ No newline at end of file diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java index 50049c41ec..cec4565c8c 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java @@ -175,8 +175,10 @@ public class BusPassengerModel { @Override public void onFail(int code, String msg) { - //code = 1003; message = bus车辆已收车或未出车; + //code = 1003; message = bus车辆已收车或未出车;bus driver shadow,not exists if (code == 1003){ + routesResult = null; + startOrStopCalculateRouteInfo(false); queryDriverOperationDelay(); } } diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java index 7c72fc813e..e56557e570 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java @@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.amap.api.maps.model.LatLng; import com.elegant.utils.UiThreadHandler; +import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.function.call.hmi.CallerHmiManager; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; @@ -98,19 +99,21 @@ public class BusPassengerRouteFragment extends mMapArrowIcon = findViewById(R.id.bus_p_arrow_nor); //测试 - mSpeedTv.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - BPRouteDataTestUtils.converToRouteData(); - UiThreadHandler.postDelayed(new Runnable() { - @Override - public void run() { - updateWayPointList(mStationsList,1); - } - },1000); - return false; - } - }); + if (DebugConfig.isDebug()){ + mSpeedTv.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + BPRouteDataTestUtils.converToRouteData(); + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() { + updateWayPointList(mStationsList,1); + } + },1000); + return false; + } + }); + } } @Override diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java new file mode 100644 index 0000000000..186fc0b5f4 --- /dev/null +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java @@ -0,0 +1,11 @@ +package com.mogo.och.bus.callback; + +/** + * Created on 2021/9/8 + * + * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等) + */ +public interface IBusADASStatusCallback { + //自驾返回失败 + void onStartAdasFailure(); +} diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/constant/BusConst.kt b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/constant/BusConst.kt index b75ef88c4c..686e08b4e4 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/constant/BusConst.kt +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/constant/BusConst.kt @@ -63,6 +63,7 @@ class BusConst { const val EVENT_PARAM_END_NAME = "end_name" const val EVENT_PARAM_LINE_ID = "line_id" const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false + const val EVENT_PARAM_START_FAILURE_MSG = "start_autopilot_failure_msg" // 启动自驾失败原因 const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号 const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境:true/false // 埋点key:开启自动驾驶前已识别的异常,会导致无法开启自驾 diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java index bcd6018ea8..39b42c5749 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java @@ -4,6 +4,7 @@ import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS import static com.mogo.och.bus.constant.BusConst.TIMER_START_AUTOPILOT_INTERVAL; import android.animation.ObjectAnimator; +import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -19,9 +20,12 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.Group; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.debug.DebugConfig; import com.mogo.commons.mvp.IView; import com.mogo.commons.mvp.MvpFragment; import com.mogo.commons.mvp.Presenter; +import com.mogo.commons.voice.AIAssist; import com.mogo.eagle.core.data.config.HmiBuildConfig; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; @@ -30,21 +34,26 @@ import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListener import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager; import com.mogo.eagle.core.function.call.hmi.CallerHmiManager; import com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView; +import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.ToastUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.map.MogoMapUIController; +import com.mogo.map.MogoMarkerManager; import com.mogo.map.listener.IMogoMapListener; import com.mogo.map.uicontroller.VisualAngleMode; import com.mogo.module.common.MogoApisHandler; import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener; import com.mogo.och.bus.R; import com.mogo.och.bus.bean.BusRoutesResult; +import com.mogo.och.bus.constant.BusConst; import com.mogo.och.bus.model.BusOrderModel; import com.mogo.och.bus.util.BDRouteDataTestUtils; import com.mogo.och.bus.view.SlidePanelView; import com.mogo.och.common.module.utils.SoundPoolHelper; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.ThreadMode; import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -178,7 +187,7 @@ public abstract class BaseBusTabFragment ); findViewById(R.id.btnAutopilotRoute).setOnClickListener(view -> debugArrivedRoute()); - + tvArrived.setOnClickListener(view -> { onArriveStation(); }); @@ -366,15 +375,19 @@ public abstract class BaseBusTabFragment // 主动开启自动驾驶中,不为2(为0、1)则继续loading return; } - if (isAnimateRunning) { - stopAutopilotAnimation(); - updateAutopilotStatus(autopilotStatus); - } else { + if (isAnimateRunning){ + stopAnimAndUpdateBtnStatus(); + }else { setAutopilotBtnStatus(autopilotStatus); } } + public void stopAnimAndUpdateBtnStatus(){ + stopAutopilotAnimation(); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + } + /** * 隐藏【自动驾驶】按钮 */ diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java index 4c8665a874..3cd5556952 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java @@ -43,6 +43,7 @@ import com.mogo.och.bus.bean.BusRoutesResponse; import com.mogo.och.bus.bean.BusRoutesResult; import com.mogo.och.bus.bean.BusStationBean; import com.mogo.och.bus.bean.WriteOffPassenger; +import com.mogo.och.bus.callback.IBusADASStatusCallback; import com.mogo.och.bus.callback.IBusControllerStatusCallback; import com.mogo.och.bus.callback.IPassengerCallback; import com.mogo.och.bus.callback.IRefreshBusStationsCallback; @@ -56,6 +57,7 @@ import com.mogo.och.bus.util.BusTrajectoryManager; import com.mogo.och.common.module.biz.constant.OchCommonConst; import com.mogo.och.common.module.biz.network.OchCommonServiceCallback; import com.mogo.och.common.module.biz.provider.LoginService; +import com.mogo.och.common.module.callback.OchAdasStartFailureCallback; import com.mogo.och.common.module.manager.OCHAdasAbilityManager; import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; import com.mogo.och.common.module.utils.DateTimeUtil; @@ -105,6 +107,7 @@ public class BusOrderModel { private ISlidePannelHideCallback slidePanelHideCallback; private IBusControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 private IPassengerCallback mPassengerCallback; //乘客核销回调 + private IBusADASStatusCallback mADASStatusCallback; List points = new ArrayList<>();//全路径信息 @@ -157,6 +160,9 @@ public class BusOrderModel { //自动驾驶路线规划接口 CallerAutopilotPlanningListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener); + + //开启自驾后 异常信息返回 + OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener); } //2022.1.28 @@ -197,7 +203,11 @@ public class BusOrderModel { }); } - public void setRefreshBusStationsCallback(IRefreshBusStationsCallback callback) { + public void setAdasStatusCallback(IBusADASStatusCallback callback){ + this.mADASStatusCallback = callback; + } + + public void setRefreshBusStationsCallback(IRefreshBusStationsCallback callback){ this.refreshBusStationsCallback = callback; } @@ -291,6 +301,8 @@ public class BusOrderModel { //自动驾驶路线规划接口 CallerAutopilotPlanningListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); loginService = null; + + OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null); } private Object readResolve() { @@ -310,6 +322,17 @@ public class BusOrderModel { } }; + private final OchAdasStartFailureCallback mAdasStartFailureListener = new OchAdasStartFailureCallback() { + @Override + public void onStartAutopilotFailure(@NonNull String startFailedMessage) { + BusAnalyticsManager.getInstance().triggerStartAutopilotFailureEventByAdas(startFailedMessage); + if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode){ + CallerLogger.INSTANCE.e( M_BUS + TAG, "mAdasStartFailureListener = "+startFailedMessage ); + mADASStatusCallback.onStartAdasFailure(); + } + } + }; + // 自车定位 private final IMogoCarLocationChangedListener2 mCarLocationChangedListener2 = new IMogoCarLocationChangedListener2() { diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java index 7bc2b51727..c4d1be3b85 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java @@ -21,6 +21,7 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.bus.R; import com.mogo.och.bus.bean.BusStationBean; import com.mogo.och.bus.bean.WriteOffPassenger; +import com.mogo.och.bus.callback.IBusADASStatusCallback; import com.mogo.och.bus.callback.IBusControllerStatusCallback; import com.mogo.och.bus.callback.IPassengerCallback; import com.mogo.och.bus.callback.IRefreshBusStationsCallback; @@ -51,7 +52,7 @@ import system_master.SystemStatusInfo; */ public class BusPresenter extends Presenter implements IRefreshBusStationsCallback, ISlidePannelHideCallback - , IMoGoAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IPassengerCallback { + , IMoGoAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IPassengerCallback, IBusADASStatusCallback { private static final String TAG = "BusPresenter"; @@ -86,6 +87,7 @@ public class BusPresenter extends Presenter BusOrderModel.getInstance().setSlidePanelHideCallback(this); BusOrderModel.getInstance().setControllerStatusCallback(this); BusOrderModel.getInstance().setPassengerCallback(this); + BusOrderModel.getInstance().setAdasStatusCallback(this); } public void releaseListener() { @@ -93,6 +95,7 @@ public class BusPresenter extends Presenter BusOrderModel.getInstance().setSlidePanelHideCallback(null); BusOrderModel.getInstance().setControllerStatusCallback(null); BusOrderModel.getInstance().setPassengerCallback(null); + BusOrderModel.getInstance().setAdasStatusCallback(null); OCHAdasAbilityManager.getInstance().release(); } @@ -304,10 +307,16 @@ public class BusPresenter extends Presenter @Override public void playPassenger(WriteOffPassenger passenger) { int passengerNum = passenger.passengerSize; - if (passengerNum > 1){ //多人播报 "x人" - VoiceNotice.showNotice(passengerNum+"人", AIAssist.LEVEL3); - }else { //是 1 播放 "滴" - mView.playDI(); + if (passengerNum > 1){ //多人播报 "x人" ---》x人核验通过 + VoiceNotice.showNotice(passengerNum+"人核验通过", AIAssist.LEVEL3); + }else { //是 1 播放 "滴" 2022.11.09 改为: "核验通过" +// mView.playDI(); + VoiceNotice.showNotice("核验通过", AIAssist.LEVEL3); } } + + @Override + public void onStartAdasFailure() { + runOnUIThread(() -> mView.stopAnimAndUpdateBtnStatus()); + } } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java index 63d749bf3c..f06c6bbd72 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java @@ -1,5 +1,6 @@ package com.mogo.och.bus.util; +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; import android.text.TextUtils; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; @@ -8,12 +9,12 @@ import com.mogo.eagle.core.data.app.AppConfigInfo; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.function.call.analytics.AnalyticsManager; import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.util.DateTimeUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.bus.constant.BusConst; import java.util.HashMap; -import java.util.Map; /** * OCH Bus埋点工具 @@ -30,18 +31,35 @@ public class BusAnalyticsManager { return BusAnalyticsManager.SingletonHolder.INSTANCE; } - - private String mStartAutopilotKey; private HashMap mStartAutopilotParams = new HashMap<>(); private Runnable startAutopilotRunnable = () -> { // 15s内未开启,上报失败埋点 + triggerStartAutopilotFailureEvent("15s后app等待超时"); + }; + + public void triggerStartAutopilotFailureEventByAdas(String failMsg){ + removeWaitingCallback(); + triggerStartAutopilotFailureEvent(failMsg); + } + + private void triggerStartAutopilotFailureEvent(String failMsg){ + CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG, + failMsg); AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); - }; + } + + private void removeWaitingCallback() { + if (startAutopilotRunnable != null && + UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) { + UiThreadHandler.removeCallbacks(startAutopilotRunnable); + } + } /** * 触发'开启自动驾驶'埋点流程 @@ -69,10 +87,7 @@ public class BusAnalyticsManager { if (send) { // 开启成功,上报埋点 - if (startAutopilotRunnable != null && - UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) { - UiThreadHandler.removeCallbacks(startAutopilotRunnable); - } + removeWaitingCallback(); mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT, true); AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); } else { diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/callback/OchAdasStartFailureCallback.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/callback/OchAdasStartFailureCallback.kt new file mode 100644 index 0000000000..b66f82d19a --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/callback/OchAdasStartFailureCallback.kt @@ -0,0 +1,9 @@ +package com.mogo.och.common.module.callback + +/** + * @author: wangmingjun + * @date: 2022/11/9 + */ +interface OchAdasStartFailureCallback { + fun onStartAutopilotFailure(startFailedMessage : String) +} \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/OCHAdasAbilityManager.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/OCHAdasAbilityManager.java index 0804a47687..33d7fead37 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/OCHAdasAbilityManager.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/OCHAdasAbilityManager.java @@ -6,9 +6,13 @@ import androidx.annotation.Nullable; import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotActionsListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatisticsListener; import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotActionsListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotStatisticsListenerManager; import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.och.common.module.callback.OchAdasStartFailureCallback; import com.zhidao.support.adas.high.bean.AutopilotAbility; +import com.zhidao.support.adas.high.bean.AutopilotStatistics; import chassis.Chassis; import system_master.SystemStatusInfo; @@ -18,12 +22,15 @@ import system_master.SystemStatusInfo; * 工控机状态信息回调(判断是否能否启动自动驾驶的回调) * 目前定的是3秒回调一次 */ -public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener { +public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener, IMoGoAutopilotStatisticsListener { private static final String TAG = OCHAdasAbilityManager.class.getSimpleName(); private boolean isAutopilotAbility = true; private String autopilotAbilityReason = ""; + private String startFailedMessage = ""; + + private OchAdasStartFailureCallback failureCallback = null; private static final class SingletonHolder { private static final OCHAdasAbilityManager INSTANCE = new OCHAdasAbilityManager(); @@ -37,6 +44,10 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener { initListeners(); } + public void setAdasStartFailureCallback(OchAdasStartFailureCallback callback){ + failureCallback = callback; + } + public boolean getAutopilotAbilityStatus(){ return isAutopilotAbility; } @@ -45,13 +56,19 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener { return autopilotAbilityReason; } + public String getStartFailedMessage() { + return startFailedMessage; + } + private void initListeners() { //2022.10.9 工控机状态信息回调(判断是否能否启动自动驾驶的回调), 目前定的是3秒回调一次 CallerAutopilotActionsListenerManager.INSTANCE.addListener(TAG, this); + CallerAutopilotStatisticsListenerManager.INSTANCE.addListener(TAG,this); } private void releaseListeners() { CallerAutopilotActionsListenerManager.INSTANCE.removeListener(this); + CallerAutopilotStatisticsListenerManager.INSTANCE.removeListener(this); } @Override @@ -88,6 +105,18 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener { Logger.d(TAG, "是否可以启动自动驾驶=" + isAutopilotAbility + " 原因=" + autopilotAbilityReason); } + + @Override + public void onAutopilotStatistics(@Nullable AutopilotStatistics statistics) { + if (statistics == null) return; + Logger.d(TAG, "AutopilotStatistics= " + statistics.status); + if (failureCallback != null && 1 == statistics.status){ + startFailedMessage = statistics.failedMessage.getMsg(); + failureCallback.onStartAutopilotFailure(startFailedMessage); + Logger.d(TAG, "statistics-startFailedMessage= " + startFailedMessage); + } + } + public void release() { releaseListeners(); } diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/voice/VoiceNotice.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/voice/VoiceNotice.kt index f57f4c3648..43ef0ffb30 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/voice/VoiceNotice.kt +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/voice/VoiceNotice.kt @@ -36,4 +36,14 @@ object VoiceNotice { } } } + + /** + * 中断当前在播语音 + */ + @JvmStatic + fun stopCurrentTts(){ + UiThreadHandler.post { + AIAssist.getInstance(AbsMogoApplication.getApp()).stopTts() + } + } } \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/.gitignore b/OCH/mogo-och-sweeper/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/OCH/mogo-och-sweeper/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/build.gradle b/OCH/mogo-och-sweeper/build.gradle new file mode 100644 index 0000000000..eea68114f8 --- /dev/null +++ b/OCH/mogo-och-sweeper/build.gradle @@ -0,0 +1,75 @@ +apply plugin: 'com.android.library' +apply plugin: 'com.alibaba.arouter' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + // buildToolsVersion rootProject.ext.android.buildToolsVersion + defaultConfig { + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + versionCode Integer.valueOf(VERSION_CODE) + versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION") + + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + + javaCompileOptions { + annotationProcessorOptions { + arguments = [AROUTER_MODULE_NAME: project.getName()] + } + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation rootProject.ext.dependencies.kotlinstdlibjdk7 + implementation rootProject.ext.dependencies.androidxappcompat + implementation rootProject.ext.dependencies.arouter + annotationProcessor rootProject.ext.dependencies.aroutercompiler + implementation rootProject.ext.dependencies.androidxconstraintlayout + implementation rootProject.ext.dependencies.amapnavi3dmap + + implementation rootProject.ext.dependencies.rxjava + implementation rootProject.ext.dependencies.rxandroid + + implementation project(":OCH:mogo-och-common-module") + + implementation rootProject.ext.dependencies.androidxrecyclerview + if (Boolean.valueOf(USE_MAVEN_PACKAGE)) { + implementation rootProject.ext.dependencies.mogoutils + implementation rootProject.ext.dependencies.mogocommons + implementation rootProject.ext.dependencies.modulecommon + implementation rootProject.ext.dependencies.mogo_core_data + implementation rootProject.ext.dependencies.mogo_core_function_call + implementation rootProject.ext.dependencies.mogo_core_function_hmi + }else { + implementation project(":core:mogo-core-utils") + implementation project(":foudations:mogo-commons") + implementation project(':modules:mogo-module-common') + implementation project(':core:mogo-core-data') + implementation project(':core:mogo-core-function-call') + implementation project(':core:function-impl:mogo-core-function-hmi') + } +} + +apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString() \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/gradle.properties b/OCH/mogo-och-sweeper/gradle.properties new file mode 100644 index 0000000000..6153f2df71 --- /dev/null +++ b/OCH/mogo-och-sweeper/gradle.properties @@ -0,0 +1,3 @@ +GROUP=com.mogo.och +POM_ARTIFACT_ID=och-sweeper +VERSION_CODE=1 diff --git a/OCH/mogo-och-sweeper/proguard-rules.pro b/OCH/mogo-och-sweeper/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/OCH/mogo-och-sweeper/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt b/OCH/mogo-och-sweeper/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt new file mode 100644 index 0000000000..ccebc3709a --- /dev/null +++ b/OCH/mogo-och-sweeper/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.mogo.och.sweeper + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.mogo.och.sweeper", appContext.packageName) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/AndroidManifest.xml b/OCH/mogo-och-sweeper/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..b8d998f9b0 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + /> + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/IMogoOCH.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/IMogoOCH.java new file mode 100644 index 0000000000..0f584c6b1d --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/IMogoOCH.java @@ -0,0 +1,24 @@ +package com.mogo.och.sweeper; + +import androidx.annotation.IdRes; +import androidx.fragment.app.FragmentActivity; + +import com.mogo.eagle.core.function.api.base.IMoGoFunctionProvider; + +public +/** + * @author congtaowang + * @since 2021/1/15 + * + * 网约车抽象接口 + */ +interface IMogoOCH extends IMoGoFunctionProvider { + + /** + * 初始化网约车容器 + * + * @param activity + * @param containerId 容器ID + */ + void createCoverage(FragmentActivity activity, @IdRes int containerId); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/SweeperProvider.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/SweeperProvider.java new file mode 100644 index 0000000000..0db6a47aff --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/SweeperProvider.java @@ -0,0 +1,114 @@ +package com.mogo.och.sweeper; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.content.Context; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.mogo.commons.module.status.IMogoStatusChangedListener; +import com.mogo.commons.module.status.MogoStatusManager; +import com.mogo.commons.module.status.StatusDescriptor; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.map.MogoMapUIController; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.fragment.SweeperFragment; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * 清扫车业务实现入口 + * + * @author tongchenfei + */ +@Route(path = SweeperConst.PATH) +public class SweeperProvider implements IMogoOCH { + + private static final String TAG = "SweeperProvider"; + + private SweeperFragment sweeperFragment; + private int containerId; + private FragmentActivity activity; + + /** + * 进入鹰眼模式,设置手势缩放地图失效 + */ + private void stepIntoVrMode(){ + CallerLogger.INSTANCE.d( M_BUS + TAG, "进入vr模式" ); + MogoMapUIController.getInstance() + .stepInVrMode(false); + } + + @Override + public void init(Context context) { + MogoStatusManager.getInstance().registerStatusChangedListener("OchSweeper" + , StatusDescriptor.VR_MODE, statusChangedListener); + } + + private void showFragment() { + if (sweeperFragment == null) { + CallerLogger.INSTANCE.d(TAG, "准备add fragment======"); + sweeperFragment = new SweeperFragment(); + activity.getSupportFragmentManager().beginTransaction().add(containerId, sweeperFragment).commitAllowingStateLoss(); + return; + } + CallerLogger.INSTANCE.d(TAG, "准备show fragment"); + activity.getSupportFragmentManager().beginTransaction().show(sweeperFragment).commitAllowingStateLoss(); + } + + private void hideFragment() { + if (sweeperFragment != null) { + CallerLogger.INSTANCE.d(TAG, "准备hide fragment"); + activity.getSupportFragmentManager().beginTransaction().hide(sweeperFragment).commitAllowingStateLoss(); + } + + } + + private final IMogoStatusChangedListener statusChangedListener = (descriptor, isTrue) -> { + if (descriptor == StatusDescriptor.VR_MODE) { + // 进入vr模式默认显示网约车小巴fragment + if (isTrue) { + showFragment(); + } else { + hideFragment(); + } + } else if (MogoStatusManager.getInstance().isVrMode()) { + // topView进行展示时推出网约车界面,但是不隐藏整个fragment + if (sweeperFragment != null && isTrue) { + sweeperFragment.hideOchSweeper(); + } + } + }; + + @Override + public void createCoverage(FragmentActivity activity, int containerId) { + + } + + @NotNull + @Override + public String getFunctionName() { + return null; + } + + @Nullable + @Override + public Fragment createCoverage(@Nullable FragmentActivity fragmentActivity, @Nullable Integer integer) { + + this.containerId = integer; + this.activity = fragmentActivity; + +// UiThreadHandler.postDelayed(this::stepIntoVrMode, 5_000L ); + return null; + } + + @Override + public void onDestroy() { + //若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠 + if (activity == null) return; + activity.finish(); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/CarHeartbeatReqBean.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/CarHeartbeatReqBean.java new file mode 100644 index 0000000000..5aa4d7205f --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/CarHeartbeatReqBean.java @@ -0,0 +1,26 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.och.sweeper.constant.SweeperConst; + +import java.util.UUID; + +/** + * Created on 2021/9/16 + * + * 上传车机心跳信息请求数据 + */ +public class CarHeartbeatReqBean { + public String sn; + public double lon; //经度 + public double lat; //纬度 + public String msgId; //心跳信息唯一标识 + public int interval; //上报间隔,单位秒,非必传,默认60秒 + + public CarHeartbeatReqBean(String sn, double lon, double lat) { + this.sn = sn; + this.lon = lon; + this.lat = lat; + this.msgId = UUID.randomUUID().toString(); + this.interval = (int) (SweeperConst.LOOP_PERIOD_60S / 1000); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersRequest.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersRequest.java new file mode 100644 index 0000000000..c0a9b96dcf --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersRequest.java @@ -0,0 +1,36 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * 查询下车乘客请求参数 + * + * @author tongchenfei + */ +public class QueryLeaveAwayPassengersRequest { + private String sn; + private int seq; //站点在线路中的序号 + private int siteId; //站点id + + public QueryLeaveAwayPassengersRequest(int seq, int siteId) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.seq = seq; + this.siteId = siteId; + } + + public void setSeq(int seq) { + this.seq = seq; + } + + public void setSiteId(int siteId) { + this.siteId = siteId; + } + + public int getSeq() { + return seq; + } + + public int getSiteId() { + return siteId; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersResponse.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersResponse.java new file mode 100644 index 0000000000..dffc722d9b --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/QueryLeaveAwayPassengersResponse.java @@ -0,0 +1,60 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +public +/** + * @author congtaowang + * @since 2021/3/26 + * + * 到站查询下车乘客 + */ +class QueryLeaveAwayPassengersResponse extends BaseData { + + public Result data; + + public static class Result { + + public List< LeaveAwayPassenger > orders; + } + + public static class LeaveAwayPassenger { + /** + * orderNo: 订单no + * orderStatus: 订单状态 + * orderType:订单类型:0及时,1预约 + * bookingTime:预计用车时间 + * businessType:订单运营类型 9:taxi,10:bus + * startSiteId: 起点站点id + * userPhone: 乘客联系方式 + * startSitePoint:开始站点坐标 + * startSiteAddr:开始地址 + * endSiteId:结束站点id + * endSitePoint:结束站点坐标 + * carNumber:车牌号 + * createTime: 创建时间 + * startTime:开始时间 + * startSiteGcjPoint:高精坐标 + * endSiteGcjPoint: + */ +//todo 目前是需要乘客电话来通知乘客下车 目前后台没有乘客信息userPhone + public String orderNo; + public int orderStatus; + public int orderType; + public long bookingTime; + public int businessType; + public int startSiteId; + public String passengerPhone; + public List startSitePoint; + public String startSiteAddr; + public int endSiteId; + public List endSitePoint; + public String carNumber; + public long createTime; + public long startTime; + public List< Double > startSiteGcjPoint; + public List< Double > endSiteGcjPoint; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusRequest.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusRequest.java new file mode 100644 index 0000000000..c8b9995b24 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusRequest.java @@ -0,0 +1,42 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态请求参数 + */ +class SweeperOperationStatusRequest { + + private String sn; + private double lat; + private double lon; + public SweeperOperationStatusRequest(double lon, double lat) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.lat = lat; + this.lon = lon; + } + public void setLat(double lat) { + this.lat = lat; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public String getSn() { + return sn; + } + + public double getLat() { + return lat; + } + + public double getLon() { + return lon; + } + +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusResponse.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusResponse.java new file mode 100644 index 0000000000..664def47df --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOperationStatusResponse.java @@ -0,0 +1,20 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态返回参数 + */ +public class SweeperOperationStatusResponse extends BaseData { + + public Result data; + + public static class Result { + + public int serviceStatus;//0:已收车,1:已出车 + + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrderBean.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrderBean.java new file mode 100644 index 0000000000..14be117b5b --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrderBean.java @@ -0,0 +1,86 @@ +package com.mogo.och.sweeper.bean; + +/** + * @author congtaowang + * @since 2021/3/23 + *

+ * 小巴订单 + */ +public class SweeperOrderBean { + + /** + * orderNo number + * passengerPhone string 下单用户电话 + * startStationId integer 开始站点 + * startStationName string + * endStationId integer 结束站点 + * endStationName string + */ + + private String orderNo; + private String passengerPhone; + private int startStationId;//乘客上车点 + private String startStationName; + private String endStationName; + private int endStationId;//乘客下车点 + + public void setOrderNo(String orderNo) { + this.orderNo = orderNo; + } + + public void setPassengerPhone(String passengerPhone) { + this.passengerPhone = passengerPhone; + } + + public void setStartStationId(int startStationId) { + this.startStationId = startStationId; + } + + public void setStartStationName(String startStationName) { + this.startStationName = startStationName; + } + + public void setEndStationName(String endStationName) { + this.endStationName = endStationName; + } + + public void setEndStationId(int endStationId) { + this.endStationId = endStationId; + } + + public String getOrderNo() { + return orderNo; + } + + public String getPassengerPhone() { + return passengerPhone; + } + + public int getStartStationId() { + return startStationId; + } + + public String getStartStationName() { + return startStationName; + } + + public String getEndStationName() { + return endStationName; + } + + public int getEndStationId() { + return endStationId; + } + + @Override + public String toString() { + return "BusOrderBean{" + + "orderNo=" + orderNo + + ", passengerPhone='" + passengerPhone + '\'' + + ", startStationId=" + startStationId + + ", startStationName='" + startStationName + '\'' + + ", endStationName='" + endStationName + '\'' + + ", endStationId=" + endStationId + + '}'; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrdersResponse.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrdersResponse.java new file mode 100644 index 0000000000..38ab2a6e4e --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperOrdersResponse.java @@ -0,0 +1,23 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2021/10/19 + */ +public class SweeperOrdersResponse extends BaseData { + public Result data; + public static class Result{ + public List orders; + } + + @Override + public String toString() { + return "BusOrdersResponse{" + + "data=" + data + + '}'; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLineStationsRequest.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLineStationsRequest.java new file mode 100644 index 0000000000..2289886b1a --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLineStationsRequest.java @@ -0,0 +1,61 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; +/** + * @author congtaowang + * @since 2021/3/22 + * + * 根据车机行驶线路站点信息 + */ +public class SweeperQueryLineStationsRequest { + + private String sn; + private double lat; + private double lon; + private boolean markDrivingStatus; // 默认false;true:是否需要返回站点的行驶状态,对应返回的drivingStatus + // 0 - 关闭、1 - 启动 +// public String status; + public SweeperQueryLineStationsRequest(double lon, double lat, boolean markDrivingStatus) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.lat = lat; + this.lon = lon; + this.markDrivingStatus = markDrivingStatus; + } + + public boolean isMarkDrivingStatus() { + return markDrivingStatus; + } + + public void setMarkDrivingStatus(boolean markDrivingStatus) { + this.markDrivingStatus = markDrivingStatus; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public String getSn() { + return sn; + } + + public double getLat() { + return lat; + } + + public double getLon() { + return lon; + } + // public BusOperationStatusRequest shutdown() { +// status = "0"; +// return this; +// } +// +// public BusOperationStatusRequest launch() { +// status = "1"; +// return this; +// } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLinesResponse.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLinesResponse.java new file mode 100644 index 0000000000..e1cf271b2d --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperQueryLinesResponse.java @@ -0,0 +1,23 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class SweeperQueryLinesResponse extends BaseData { + public List data; + + public static class Result { + + public int lineId;//线路id + public String name;//线路名字 + public int choose; // 1:绑定 2:未被绑定 + public String startSiteName;//始发站名称 + public String endSiteName;//终点名称 + + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperResetDrivingLineRequest.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperResetDrivingLineRequest.java new file mode 100644 index 0000000000..718ba66504 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperResetDrivingLineRequest.java @@ -0,0 +1,17 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * @author: wangmingjun + * @date: 2021/10/18 + */ +public class SweeperResetDrivingLineRequest { + public String sn; + public int lineId; //切换到的线路id + + public SweeperResetDrivingLineRequest(int lineId) { + sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.lineId = lineId; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutePlanningUpdateReqBean.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutePlanningUpdateReqBean.java new file mode 100644 index 0000000000..9d58dbb4c4 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutePlanningUpdateReqBean.java @@ -0,0 +1,30 @@ +package com.mogo.och.sweeper.bean; + +import java.util.List; + +/** + * Created by pangfan on 2021/8/19 + * + * 订单状态更新请求数据结构 + */ +public class SweeperRoutePlanningUpdateReqBean { + public String sn; + public int lineId; + public int startSiteId; + public int endSiteId; + public List points; + + public static class Result { + public Double latitude; + public Double longitude; + } + + public SweeperRoutePlanningUpdateReqBean(String sn, int lineId, int startSiteId + , int endSiteId, List points) { + this.sn = sn; + this.lineId = lineId; + this.startSiteId = startSiteId; + this.endSiteId = endSiteId; + this.points = points; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResponse.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResponse.java new file mode 100644 index 0000000000..6779f61b80 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResponse.java @@ -0,0 +1,27 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * 网约车小巴路线接口请求响应结果 + * + * @author tongchenfei + */ +public class SweeperRoutesResponse extends BaseData { + private SweeperRoutesResult data; + + public SweeperRoutesResult getResult() { + return data; + } + + public void setResult(SweeperRoutesResult data) { + this.data = data; + } + + @Override + public String toString() { + return "BusRoutesResponse{" + + "data=" + data + + '}'; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResult.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResult.java new file mode 100644 index 0000000000..545304b948 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperRoutesResult.java @@ -0,0 +1,69 @@ +package com.mogo.och.sweeper.bean; + +import java.util.List; + +/** + * 网约车小巴路线接口返回接口数据封装 + * + * @author tongchenfei + */ +public class SweeperRoutesResult { + private List sites; + private int lineId; + private String name; + private int lineType; //线路类型,0:环形 + private String description; + private int status; + + //线路轨迹相关字段 + public String csvFileUrl = ""; //轨迹文件下载的cos url,默认“” + public String csvFileMd5 = ""; //轨迹文件md5,默认“” + public String txtFileUrl = ""; //打点文件下载的cos url,默认“” + public String txtFileMd5 = ""; //轨迹文件md5,默认“” + public long contrailSaveTime; //上传轨迹完成时间戳ms:用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖 + public String carModel = ""; //[optional] 车型号(如红旗H9),默认“”,暂不加入校验逻辑、用于人工排查问题 + public String csvFileUrlDPQP = ""; //轨迹文件下载的cos url,默认“” + public String csvFileMd5DPQP = ""; //轨迹文件md5,默认“” + public String txtFileUrlDPQP = ""; //打点文件下载的cos url,默认“” + public String txtFileMd5DPQP = ""; //轨迹文件md5,默认“” + public long contrailSaveTimeDPQP; //上传轨迹完成时间戳ms:用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖 + + public int getLineId() { + return lineId; + } + + public String getName() { + return name; + } + + public List getSites() { + return sites; + } + + public void setSite(List site) { + this.sites = sites; + } + + @Override + public String toString() { + return "BusRoutesResult{" + + "sites=" + sites + + ", lineId=" + lineId + + ", name='" + name + '\'' + + ", lineType=" + lineType + + ", description='" + description + '\'' + + ", status=" + status + + ", csvFileUrl='" + csvFileUrl + '\'' + + ", csvFileMd5='" + csvFileMd5 + '\'' + + ", txtFileUrl='" + txtFileUrl + '\'' + + ", txtFileMd5='" + txtFileMd5 + '\'' + + ", contrailSaveTime=" + contrailSaveTime + + ", carModel='" + carModel + '\'' + + ", csvFileUrlDPQP='" + csvFileUrlDPQP + '\'' + + ", csvFileMd5DPQP='" + csvFileMd5DPQP + '\'' + + ", txtFileUrlDPQP='" + txtFileUrlDPQP + '\'' + + ", txtFileMd5DPQP='" + txtFileMd5DPQP + '\'' + + ", contrailSaveTimeDPQP=" + contrailSaveTimeDPQP + + '}'; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperStationBean.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperStationBean.java new file mode 100644 index 0000000000..ad4fef2b65 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperStationBean.java @@ -0,0 +1,162 @@ +package com.mogo.och.sweeper.bean; + +/** + * 单个网约车小巴车站信息 + * + * @author tongchenfei + */ +public class SweeperStationBean { +// private int lineId; +// private int siteId; +// private String siteName; +// private String cityCode; +// private String areaCode; +// private String areaName; +// private double lat; +// private double lon; +// private String siteDesc; +// private int siteState; +// private int isCurrentSite;// @see OchBusConst 是否是当前站 1:是 2:下一站 0:普通站 +// private int siteColor; +// private String peoples; +// private int ifStop; // 是否需要停靠、1需要、0不需要 + + + private String name; + private String description; + private String cityCode; + private double lon; //高精坐标 + private double lat; //高精坐标 + private int businessType; //站点类型,9:taxi,10:bus + private double gcjLon; //高德 + private double gcjLat; //高德 + private int status; + private int siteId; + private int seq; + private int drivingStatus;//行驶信息,0初始值;1已经过;2当前站;3未到站 + private int ifStop = 1; // 是否需要停靠、1需要、0不需要 // TODO: 2021/10/19 原来站点里有设计是否需要停靠字段,现设计暂无,默认都需要停靠 + private boolean leaving; + + public double getGcjLon() { + return gcjLon; + } + + public double getGcjLat() { + return gcjLat; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public void setBusinessType(int businessType) { + this.businessType = businessType; + } + + public void setStatus(int status) { + this.status = status; + } + + public void setSiteId(int siteId) { + this.siteId = siteId; + } + + public void setSeq(int seq) { + this.seq = seq; + } + + public void setDrivingStatus(int drivingStatus) { + this.drivingStatus = drivingStatus; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getCityCode() { + return cityCode; + } + + + public int getBusinessType() { + return businessType; + } + + public int getStatus() { + return status; + } + + public int getSiteId() { + return siteId; + } + + public int getSeq() { + return seq; + } + + public int getDrivingStatus() { + return drivingStatus; + } + + public double getLon() { + return lon; + } + + public double getLat() { + return lat; + } + + public void setIfStop(int ifStop) { + this.ifStop = ifStop; + } + + public int getIfStop() { + return ifStop; + } + + public void setLeaving(boolean leaving) { + this.leaving = leaving; + } + + public boolean isLeaving() { + return leaving; + } + + @Override + public String toString() { + return "BusStationBean{" + + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", cityCode='" + cityCode + '\'' + + ", lon=" + lon + + ", lat=" + lat + + ", businessType=" + businessType + + ", status=" + status + + ", siteId=" + siteId + + ", seq=" + seq + + ", drivingStatus=" + drivingStatus + + ", ifStop=" + ifStop + + ", leaving=" + leaving + + '}'; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperUpdateSiteStatusRequest.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperUpdateSiteStatusRequest.java new file mode 100644 index 0000000000..422d5113fa --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/bean/SweeperUpdateSiteStatusRequest.java @@ -0,0 +1,26 @@ +package com.mogo.och.sweeper.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态请求参数 + */ +public class SweeperUpdateSiteStatusRequest { + + public String sn; + public int seq;//站点序号 + public int siteId;//站点id + public double lon; + public double lat; + + public SweeperUpdateSiteStatusRequest(int seq, int siteId, double lon, double lat) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.seq = seq; + this.siteId = siteId; + this.lon = lon; + this.lat = lat; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ICarOperationStatusCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ICarOperationStatusCallback.java new file mode 100644 index 0000000000..cdd2a06f24 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ICarOperationStatusCallback.java @@ -0,0 +1,9 @@ +package com.mogo.och.sweeper.callback; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface ICarOperationStatusCallback { + void changeOperationStatus(boolean changeStatus); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/IRefreshSweeperStationsCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/IRefreshSweeperStationsCallback.java new file mode 100644 index 0000000000..f6fd3ae0ab --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/IRefreshSweeperStationsCallback.java @@ -0,0 +1,13 @@ +package com.mogo.och.sweeper.callback; + +import com.mogo.och.sweeper.bean.SweeperStationBean; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface IRefreshSweeperStationsCallback { + void refreshBusStations(String lineName, List stationList, int currentStation, int nextStation, boolean isArrived); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISlidePannelHideCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISlidePannelHideCallback.java new file mode 100644 index 0000000000..246ccd2118 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISlidePannelHideCallback.java @@ -0,0 +1,9 @@ +package com.mogo.och.sweeper.callback; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface ISlidePannelHideCallback { + void hideSlidePanel(); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperControllerStatusCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperControllerStatusCallback.java new file mode 100644 index 0000000000..95543610ff --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperControllerStatusCallback.java @@ -0,0 +1,17 @@ +package com.mogo.och.sweeper.callback; + +import android.location.Location; + +/** + * Created on 2021/9/10 + * + * Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等) + */ +public interface ISweeperControllerStatusCallback { + // 是否vr map模式 + void onVRModeChanged(boolean isVRMode); + // 自车定位 + void onCarLocationChanged(Location location); + //开始开启自动驾驶 + void startOpenAutopilot(); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperLinesCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperLinesCallback.java new file mode 100644 index 0000000000..74e166b736 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/callback/ISweeperLinesCallback.java @@ -0,0 +1,12 @@ +package com.mogo.och.sweeper.callback; + +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public interface ISweeperLinesCallback { + void onBusLinesChange(SweeperQueryLinesResponse lines); + void onChangeLineIdSuccess(); +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/constant/SweeperConst.kt b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/constant/SweeperConst.kt new file mode 100644 index 0000000000..9a534d3a85 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/constant/SweeperConst.kt @@ -0,0 +1,79 @@ +package com.mogo.och.sweeper.constant + +import com.mogo.commons.debug.DebugConfig + +/** + * Created on 2021/12/6 + */ +class SweeperConst { + companion object { + + private const val BASE_URL_OCH_DEV = "http://tech-dev.zhidaohulian.com" + private const val BASE_URL_OCH_QA = "https://tech-qa.zhidaohulian.com" + private const val BASE_URL_OCH_RELEASE = "https://tech.zhidaohulian.com" + + @JvmStatic + fun getBaseUrl(): String { + return when (DebugConfig.getNetMode()) { + DebugConfig.NET_MODE_DEV, DebugConfig.NET_MODE_DEMO -> BASE_URL_OCH_DEV + DebugConfig.NET_MODE_QA -> BASE_URL_OCH_QA + DebugConfig.NET_MODE_RELEASE -> BASE_URL_OCH_RELEASE + else -> BASE_URL_OCH_RELEASE + } + } + + // OCH arouter 路由path + const val PATH = "/och/api" + + // 测试用的广播 + const val BROADCAST_TEST_SWEEPER_CONTROL_TYPE_EXTRA_KEY = "sceneType" + // 无状态 + const val STATION_STATUS_IDLE = 0 + // 已过站(历史站) + const val STATION_STATUS_LEAVING = 1 + // 到站(当前站) + const val STATION_STATUS_STOPPED = 2 + // 未到站(未到站) + const val STATION_STATUS_ARRIVING = 3 + + // 上报心跳轮询ms + const val LOOP_PERIOD_60S = 60 * 1000L + // 开始服务启动自动驾驶等待时间(埋点上传) + const val LOOP_PERIOD_15S = 15 * 1000L + const val LOOP_PERIOD_1S = 1 * 1000L + const val LOOP_DELAY = 100L + + // 下发给MEC轨迹信息间隔时间 10秒 + const val LOOP_PERIOD_10S = 10 * 1000L + // 尝试下发给MEC轨迹最多10次 + const val LOOP_SEND_TRAJ_TIMES = 10 + + //起点UUID + const val SWEEPER_START_MAP_MAKER = "sweeper_start_map_maker"; + //终点UUID + const val SWEEPER_END_MAP_MAKER = "sweeper_end_map_maker"; + + // 埋点key:接管后点击'自动驾驶'按钮启动 + const val EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_sweeper_restart_autopilot" + // 埋点key:开始服务开启自动驾驶(成功/失败) + const val EVENT_KEY_START_SERVICE = "event_key_och_sweeper_start_service" + const val EVENT_PARAM_SN = "sn" + const val EVENT_PARAM_TIME = "time" + const val EVENT_PARAM_START_NAME = "start_name" + const val EVENT_PARAM_END_NAME = "end_name" + const val EVENT_PARAM_LINE_ID = "line_id" + const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false + const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号 + const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境:true/false + + /** + * 订单起终点Marker类型 + */ + const val TYPE_MARKER_SWEEPER_ORDER = "TYPE_MARKER_SWEEPER_ORDER" + + const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L + + //围栏到站 暂定10米 + const val ARRIVE_AT_END_STATION_DISTANCE = 10 + } +} \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java new file mode 100644 index 0000000000..e82be6de13 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/BaseSweeperTabFragment.java @@ -0,0 +1,573 @@ +package com.mogo.och.sweeper.fragment; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; +import static com.mogo.och.sweeper.constant.SweeperConst.TIMER_START_AUTOPILOT_INTERVAL; + +import android.animation.ObjectAnimator; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.Group; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.module.intent.IntentManager; +import com.mogo.commons.mvp.IView; +import com.mogo.commons.mvp.MvpFragment; +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.config.HmiBuildConfig; +import com.mogo.eagle.core.data.constants.DataTypes; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager; +import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager; +import com.mogo.eagle.core.function.call.hmi.CallerHmiManager; +import com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.map.MogoMapUIController; +import com.mogo.map.MogoMarkerManager; +import com.mogo.map.listener.IMogoMapListener; +import com.mogo.map.uicontroller.VisualAngleMode; +import com.mogo.module.common.MogoApisHandler; +import com.mogo.och.sweeper.R; +import com.mogo.och.sweeper.bean.SweeperRoutesResult; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.model.SweeperOrderModel; +import com.mogo.och.sweeper.util.BDRouteDataTestUtils; +import com.mogo.och.sweeper.view.SlidePanelView; + +import mogo.telematics.pad.MessagePad; +import record_cache.RecordPanelOuterClass; + +/** + * 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况 + *

+ * 部分业务放在了此处处理 + * + * @author tongchenfei + */ +public abstract class BaseSweeperTabFragment> extends MvpFragment implements IMogoMapListener, IMoGoAutopilotRecordListener { + + private static final String TAG = "BaseOchFragment"; + + protected SlidePanelView slidePanelView; + private RelativeLayout ctvAutopilotStatus; + private ImageView ctvAutopilotStatusIv; + private TextView ctvAutopilotStatusTv; + protected TextView tvOperationStatus; + protected RelativeLayout mSettingBtn; + protected RelativeLayout mBadcaseBtn; + protected RelativeLayout mAICollectBtn; + public boolean isOperationStatus;//false-收车,true-出车 + private FrameLayout flStationPanelContainer; + private Group groupTestPanel; + private FrameLayout flSpeed; + // private BusArcView mouduleArc; + private TrafficDataView mTrafficDataView; + private ImageView mUpgradeTipIv; + // private BusTrafficLightView mTrafficLightView; + + public static final String TYPE_ENTRANCE = "entrance"; + + //远景和中景的切换 + private ImageView mSwitchMapModeImage; + private LinearLayout mSwitchMapModeLayout; + + private ObjectAnimator autopilotLoadingAnimator; + + public boolean isAnimateRunning = false; + + /** + * 滑动按钮触发的事件 + */ + private final SlidePanelView.OnSlidePanelMoveToEndListener onSlideToEndListener = () -> { + // 此处做一个代理,处理一下共有情况 + if (getSlidePanelOnEndListener() != null) { + getSlidePanelOnEndListener().moveToEnd(); + } + }; + + @Override + protected int getLayoutId() { + return R.layout.sweeper_base_fragment; + } + + private View panelView; + + @Override + protected void initViews() { + groupTestPanel = findViewById(R.id.groupTestPanel); + slidePanelView = findViewById(R.id.module_mogo_och_slide_panel); + ctvAutopilotStatus = findViewById(R.id.module_mogo_och_autopilot_status); + ctvAutopilotStatusIv = findViewById(R.id.sweeper_autopilot_btn_iv); + ctvAutopilotStatusTv = findViewById(R.id.sweeper_autopolot_btn_tv); + flStationPanelContainer = findViewById(R.id.module_mogo_och_station_panel_container); + + // mTrafficLightView = findViewById(R.id.bus_traffic_light_view); + // CallerHmiManager.INSTANCE.setProxyTrafficLightView(mTrafficLightView); + + tvOperationStatus = findViewById(R.id.module_mogo_och_operation_status); + + flSpeed = (FrameLayout) findViewById(R.id.fl_speed); + mTrafficDataView = (TrafficDataView) findViewById(R.id.sweeper_arc); + + panelView = LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer); + slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener); + + mSwitchMapModeLayout = findViewById(R.id.sweeper_switch_model_layout); + mSwitchMapModeImage = findViewById(R.id.sweeper_switch_model_icon); + updateSwitchMapIcon(); + + mSwitchMapModeLayout.setOnClickListener(new OnPreventFastClickListener() { + + @Override + public void onClickImpl(View v) { + //切换地图的远近视图 + if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isLongSight()) { + MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).visibleAllMarkers(); + MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_medium); + } else if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isMediumSight()) { + MogoMarkerManager.getInstance(AbsMogoApplication.getApp()) + .inVisibleWithoutMarkers(DataTypes.TYPE_MARKER_ADAS, SweeperConst.TYPE_MARKER_SWEEPER_ORDER); + MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_LONG_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_long); + } + } + }); + + if (DebugConfig.isDebug()) { + mTrafficDataView.setLongClickable(true); + mTrafficDataView.setOnLongClickListener(v -> { + CallerLogger.INSTANCE.d(M_BUS + TAG, "长按显示状态工具栏"); + Intent intent = new Intent(); + intent.putExtra("oper", 52); + return true; + }); + } + initListener(); + ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener() { + + @Override + public void onClickImpl(View v) { +// if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE){ + restartAutopilot(); +// }else { +// ToastUtils.showShort(getResources().getString(R.string.sweeper_auto_disable_tip)); +// } + } + }); + + setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + // 模拟 不可自动驾驶,目前场景是刚开机,adas还未和工控机连接 + findViewById(R.id.btnAutopilotDisable).setOnClickListener(view -> + debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) + ); + + // 模拟 可自动驾驶,工控机连接正常,且处于人工干预状态 + findViewById(R.id.btnAutopilotEnable).setOnClickListener(view -> + debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) + ); + + // 模拟 自动驾驶能力,自动驾驶中,可能是停车,可能是行进,但是是机器在处理车的前进后退,不是人 + findViewById(R.id.btnAutopilotRunning).setOnClickListener(view -> + debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) + ); + + // 模拟 自动驾驶网约车回调数据 + findViewById(R.id.btnAutopilotArrive).setOnClickListener(view -> + debugArrivedStation() + ); + + findViewById(R.id.btnAutopilotRoute).setOnClickListener(view -> debugArrivedRoute()); + + tvOperationStatus.setOnClickListener(view -> { + onChangeOperationStatus(); + }); + + mSettingBtn = findViewById(R.id.module_mogo_och_setting_layout); + mSettingBtn.setOnClickListener(v -> { + // TODO: 2021/12/9 + CallerHmiManager.INSTANCE.showToolsView(); + }); + + // mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理 + mBadcaseBtn = findViewById(R.id.module_mogo_och_badcase_rl); +// CallerHmiManager.INSTANCE.registerBadCaseCallback( +// () -> { // onShow() +// return mBadcaseBtn; }, +// () -> { // onHide() +// return null; }); + + if (mBadcaseBtn != null) { + CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn); + if (!HmiBuildConfig.isShowBadCaseView) { + CallerAutopilotRecordListenerManager.INSTANCE.addListener(TAG, this); + } + } + + mAICollectBtn = findViewById(R.id.module_mogo_och_ai_collet_rl); + if (mAICollectBtn != null) { + CallerDevaToolsManager.INSTANCE.initAiCollect(mAICollectBtn); + } + } + + private void updateSwitchMapIcon() { + if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isLongSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_long); + } else if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isMediumSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_medium); + } else { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_medium); + } + } + + private void debugArrivedRoute() { + BDRouteDataTestUtils.converToRouteData(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (!HmiBuildConfig.isShowBadCaseView) { + CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG); + } + } + + + @Override + public void onAutopilotRecordResult(@Nullable RecordPanelOuterClass.RecordPanel recordPanel) { +// if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) { +// CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel); +// } + } + + @Override + public void onAutopilotRecordConfig(@NonNull MessagePad.RecordDataConfig config) { + } + + + /** + * 测试到站 + */ + protected abstract void debugArrivedStation(); + + private void initListener() { + MogoApisHandler.getInstance().getApis().getRegisterCenterApi().registerMogoMapListener(TYPE_ENTRANCE, this); + } + + protected void onChangeOperationStatus() { + + } + + /** + * 展示滑动按钮 + * + * @param text 指定的文字 + */ + public void showSlidePanle(String text) { + if (isOperationStatus) { + getActivity().runOnUiThread(() -> { + slidePanelView.setText(text); + slidePanelView.setVisibility(View.VISIBLE); + }); + } + } + + /** + * 隐藏滑动按钮 + */ + public void hideSlidePanel() { + getActivity().runOnUiThread(() -> { + slidePanelView.setVisibility(View.GONE); + }); + } + + /** + * 改变自动驾驶状态 + * + * @param autopilotStatus 0:不可用 1:可用状态 2:自动驾驶中 + */ + public void onAutopilotStatusChanged(int autopilotStatus) { + getActivity().runOnUiThread(() -> { + changeAutopilotBtnView(autopilotStatus, isAnimateRunning); + }); + } + + public void setAutopilotBtnStatus(int autopilotStatus) { + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE + == autopilotStatus) {//0不可用 + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweeper_autopilot_text_color_disable)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweeper_loading_autopilot_runnig_tv)); + ctvAutopilotStatusIv.setImageResource(R.drawable.sweeper_disable_autopilot_icon); + ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setFocusableInTouchMode(true); + + } else { + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweeper_autopilot_text_color_normal)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweeper_loading_autopilot_runnig_tv)); + ctvAutopilotStatusIv.setImageResource(R.drawable.sweeper_ic_autopilot); + ctvAutopilotStatus.setFocusableInTouchMode(true); + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) {//1可用 + ctvAutopilotStatus.setSelected(false); + } else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus) { + ctvAutopilotStatus.setSelected(true); + } + } + } + + public void updateAutopilotStatus(int autopilotStatus) { + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING + == autopilotStatus) {//2 running + ctvAutopilotStatusIv.setImageResource(R.drawable.sweeper_right_autopilot_icon); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweeper_autopilot_text_color_normal)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweeper_loading_autopilot_success_tv)); + ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setFocusableInTouchMode(false); + } else { + ctvAutopilotStatusIv.setImageResource(R.drawable.sweeper_wrong_autopilot_icon); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweeper_autopilot_text_color_normal)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweeper_loading_autopilot_failure_tv)); + ctvAutopilotStatus.setFocusableInTouchMode(false); + ctvAutopilotStatus.setSelected(false); + } + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() { + setAutopilotBtnStatus(autopilotStatus); + } + }, 1000); + } + + private void changeAutopilotBtnView(int autopilotStatus, boolean isAnimateRunning) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChangeChangeAutopilotBtnView: " + + autopilotStatus + "isAnimateRunning = " + isAnimateRunning); + if (isAnimateRunning && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING + != autopilotStatus) { + // 主动开启自动驾驶中,不为2(为0、1)则继续loading + return; + } + if (isAnimateRunning) { + stopAutopilotAnimation(); + updateAutopilotStatus(autopilotStatus); + } else { + setAutopilotBtnStatus(autopilotStatus); + } + + } + + /** + * 隐藏【自动驾驶】按钮 + */ + public void hideAutopilotBiz() { + getActivity().runOnUiThread(() -> { +// ctvAutopilotStatus.setVisibility(View.GONE); +// slidePanelView.setVisibility(View.GONE); + }); + } + + /** + * 展示【自动驾驶】按钮 + */ + public void showAutopilotBiz() { + getActivity().runOnUiThread(() -> { + ctvAutopilotStatus.setVisibility(View.VISIBLE); + }); + } + + public void hidPanel() { + getActivity().runOnUiThread(() -> { + flStationPanelContainer.setVisibility(View.GONE); + }); + } + + public void showPanel() { + getActivity().runOnUiThread(() -> { + flStationPanelContainer.setVisibility(View.VISIBLE); + }); + } + + public View getPanelView() { + return panelView; + } + + public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() { + return null; + } + + /** + * 获取站点面板view,在{@link #initViews()}时候添加到container中 + * + * @return 站点面板view + */ + public abstract int getStationPanelViewId(); + + /** + * 获取清扫车操作面板layout id + * + * @return + */ + public abstract int getSweepOperatePanelViewId(); + + /** + * 重新开启自动驾驶 + */ + public abstract void restartAutopilot(); + + /** + * 模拟自动驾驶返回状态 + * + * @param status + */ + public abstract void debugAutoPilotStatus(int status); + + /** + * 开启自动驾驶中间动画 + */ + public void startAutopilotAnimation() { + isAnimateRunning = true; + ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweeper_loading_autopilot_tv)); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweeper_autopilot_text_color_normal)); + ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setFocusableInTouchMode(true); + ctvAutopilotStatusIv.setImageResource(R.drawable.sweeper_loading_autopilot_icon); + if (autopilotLoadingAnimator == null) { + autopilotLoadingAnimator = ObjectAnimator.ofFloat(ctvAutopilotStatusIv, "rotation", 0f, 360f); + autopilotLoadingAnimator.setInterpolator(new LinearInterpolator()); + autopilotLoadingAnimator.setRepeatCount(-1);//无限循环 + autopilotLoadingAnimator.setDuration(1000);//设置持续时间 + } + autopilotLoadingAnimator.start();//动画开始 + + startingAutoApilotCountDown(); + + } + + private void startingAutoApilotCountDown() { + //10s 若自动驾驶没有开启,则结束动画 + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() { //未启动成功做处理 + if (isAnimateRunning) {// 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态 + stopAutopilotAnimation(); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + } + } + }, TIMER_START_AUTOPILOT_INTERVAL); + + } + + /** + * 停止自动驾驶中间动画 + */ + protected void stopAutopilotAnimation() { + if (autopilotLoadingAnimator != null) { + autopilotLoadingAnimator.end(); + ctvAutopilotStatusIv.clearAnimation(); + autopilotLoadingAnimator = null; + isAnimateRunning = false; + } + } + + /** + * 迈速表实时更新 + * + * @param newSpeed + */ + public void updateSpeedView(float newSpeed) { + int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值 + if (mTrafficDataView != null) { + mTrafficDataView.updateSpeedWithValue(speed); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + MogoApisHandler.getInstance().getApis().getRegisterCenterApi().unregisterMogoMapListener(TYPE_ENTRANCE); + } + + @Override + public void onMapVisualAngleChanged(VisualAngleMode visualAngleMode) { + if (visualAngleMode.isMediumSight()) { + mSwitchMapModeLayout.setVisibility(View.VISIBLE); + } else if (visualAngleMode.isLongSight()) { + mSwitchMapModeLayout.setVisibility(View.VISIBLE); + } else if (visualAngleMode.isCloseSight()) { + mSwitchMapModeLayout.setVisibility(View.GONE); + } + } + + /** + * bus调试面板打开关闭 + */ + public void debugTestBar() { + if (groupTestPanel.getVisibility() == View.VISIBLE) { + groupTestPanel.setVisibility(View.GONE); + } else { + groupTestPanel.setVisibility(View.VISIBLE); + } + } + + /** + * Bus调试信息:线路、轨迹等信息 + *

+ * START + */ + private View busTestBar; + private TextView lineIdTV; + private TextView trajMd5TV; + private TextView stopMd5TV; + private TextView trajMd5DPQPTV; + private TextView stopMd5DPQPTV; + + public void showHideTestBar() { + if (busTestBar == null) { + busTestBar = findViewById(R.id.module_mogo_och_sweeper_test_bar); + lineIdTV = findViewById(R.id.sweeper_test_bar_current_line_id); + trajMd5TV = findViewById(R.id.sweeper_test_bar_current_traj_md5); + stopMd5TV = findViewById(R.id.sweeper_test_bar_current_stop_md5); + trajMd5DPQPTV = findViewById(R.id.sweeper_test_bar_current_traj_md5_dpqp); + stopMd5DPQPTV = findViewById(R.id.sweeper_test_bar_current_stop_md5_dpqp); + } + + if (busTestBar.getVisibility() == View.VISIBLE) { + busTestBar.setVisibility(View.GONE); + } else { + SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult(); + lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId()))); + trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5)); + stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5)); + trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP)); + stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP)); + busTestBar.setVisibility(View.VISIBLE); + } + } + + public void updateSweeperTestBarInfo() { + if (busTestBar != null && busTestBar.getVisibility() == View.VISIBLE) { + SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult(); + lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId()))); + trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5)); + stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5)); + trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP)); + stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP)); + } + } + /** + * END + */ +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/SweeperFragment.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/SweeperFragment.java new file mode 100644 index 0000000000..e47c57a817 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/fragment/SweeperFragment.java @@ -0,0 +1,406 @@ +package com.mogo.och.sweeper.fragment; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.content.Intent; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.voice.AIAssist; +import com.mogo.eagle.core.data.map.CenterLine; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.map.CallerHDMapManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.map.MogoMarkerManager; +import com.mogo.map.marker.IMogoMarker; +import com.mogo.map.marker.MogoMarkerOptions; +import com.mogo.och.sweeper.R; +import com.mogo.och.sweeper.bean.SweeperStationBean; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.presenter.SweeperPresenter; +import com.mogo.och.sweeper.ui.SweeperSwitchLineActivity; +import com.mogo.och.sweeper.view.SlidePanelView; +import com.mogo.och.common.module.utils.OCHThreadPoolManager; + +import java.util.List; + + +/** + * 网约车小巴界面 + * + * @author tongchenfei + */ +public class SweeperFragment extends BaseSweeperTabFragment + implements SlidePanelView.OnSlidePanelMoveToEndListener, View.OnClickListener { + private static final String TAG = "SweeperFragment"; + + private TextView mCurrentStationName; + private TextView mNextStationName; + private TextView mCurrentTag; + private TextView mNextTag; + private TextView mSwitchLine; //切换路线 + private TextView mLineName; + private int mCurrentStation = 0; + + private View mSweepers; + + private SweeperStationBean startStation = null; + private SweeperStationBean endStation = null; + + @Override + public String getTagName() { + return "SweepersFragment"; + } + + @Override + protected void initViews() { + super.initViews(); + mSweepers = findViewById(R.id.module_och_sweeper_tag); + mCurrentStationName = findViewById(R.id.module_och_sweeper_current_station); + mCurrentTag = findViewById(R.id.module_och_sweeper_current_station_anchor); + mNextStationName = findViewById(R.id.module_och_sweeper_order_end_station); + mNextTag = findViewById(R.id.module_och_sweeper_next_station_anchor); + mSwitchLine = findViewById(R.id.switch_line_btn); + mLineName = findViewById(R.id.module_och_sweeper_line_name); + + if (DebugConfig.isDebug()) { + mSweepers.setOnClickListener(view -> { + ToastUtils.showShort("重置了车站状态"); + mPresenter.querySweepersRoutes(); + }); + + //debug下调用测试面板 + mCurrentStationName.setOnLongClickListener(v -> { + debugTestBar(); + showHideTestBar(); + return true; + }); + } + + CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + // 初始化的时候设置 UI 按钮状态 + switch (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) { + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE: + hideAutopilotBiz(); + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE: + showAutopilotBiz(); + onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE); + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING: + showAutopilotBiz(); + onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); + break; + default: + break; + } + mSwitchLine.setOnClickListener(this); + } + + @Override + protected void debugArrivedStation() { + mPresenter.onAutopilotArriveAtStation(null); + } + + @NonNull + @Override + protected SweeperPresenter createPresenter() { + return new SweeperPresenter(this); + } + + @Override + public void onResume() { + super.onResume(); + } + + /** + * 根据站点列表信息刷新车站面板,滑块面板 + * + * @param stationList 车站列表信息 + * @param currentStation 当前站点 + * @param nextStation 下个站点 + * @param isArrived 是否都站 + */ + public void refreshSweeperStations(String lineName, List stationList + , int currentStation, int nextStation, boolean isArrived) { + mCurrentStation = currentStation; + if (getActivity() == null) { + return; + } + getActivity().runOnUiThread(() -> { + if (stationList == null) { + // 获取小巴数据失败 + return; + } + + // 渲染小巴路线数据 + renderCurrentStationStatus(lineName,stationList, currentStation, nextStation, isArrived); + }); + } + + /** + * 重新刷新站点信息 isArrived 是否到站 + */ + private void renderCurrentStationStatus(String lineName, List stationList, int currentStation + , int nextStation, boolean isArrived) { + CallerLogger.INSTANCE.d(M_BUS + "MapMaker ", "currentStation=" + currentStation + ",nextStation=" + nextStation + "isArrived=" + isArrived); + String currentStationName = null; + String nextStationName = null; + + boolean isArriveEndStation = false; + boolean isArriveAtStation = false; + boolean isArriveAtStartStation = false; + + mLineName.setText(lineName); + + // 获取当前站点的名称 + currentStationName = stationList.get(currentStation).getName(); + + startStation = stationList.get(0); + endStation = stationList.get(stationList.size() - 1); + + // 是否到达起点 + if (currentStation == 0) { + isArriveAtStartStation = true; + mCurrentTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_start)); + + setOrRemoveMapMaker(true, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } else if (currentStation > 0 && currentStation < stationList.size() - 1) {// 是否到达站点 + isArriveAtStation = true; + mCurrentTag.setText(getResources().getString(R.string.sweeper_arrive_to_current_tag)); + mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_next_tag)); + + setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } else if (currentStation == stationList.size() - 1) {// 是否到达终点 + isArriveEndStation = true; + nextStationName = "--"; + mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_end)); + + setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + + if (isArrived) { + setOrRemoveMapMaker(false, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } else { + setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } + } + + // 获取下一站点名称 + if (nextStation > currentStation && nextStation <= stationList.size() - 1) { + nextStationName = stationList.get(nextStation).getName(); + } + + // 是否到达终点 + if ( nextStation == stationList.size() - 1 || nextStation == -1) { + mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_end)); + }else { + mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_next_tag)); + } + + if (currentStation == 0 && isArrived){ + showOrHideSwitchLineBtn(true); + }else { + showOrHideSwitchLineBtn(false); + } + + // 重置滑动按钮文字 + if (isArriveEndStation) { + showSlidePanle("单程结束"); + } else if (isArriveAtStartStation) { + showSlidePanle("滑动出发"); + } else if (isArriveAtStation) { + showSlidePanle("滑动出发"); + } + + mCurrentStationName.setText(currentStationName); + mNextStationName.setText(nextStationName); + updateSweeperTestBarInfo(); + } + + private void showOrHideSwitchLineBtn(boolean isShow) { + if (isShow){ + mSwitchLine.setVisibility(View.VISIBLE); + }else { + mSwitchLine.setVisibility(View.GONE); + } + } + + public void hideOchSweeper() { +// tvNotice.setVisibility(View.GONE); + } + + @Override + public int getStationPanelViewId() { + return R.layout.fragment_och_sweeper; + } + + @Override + public int getSweepOperatePanelViewId() { + return R.layout.sweeper_operate_panel_view; + } + + @Override + public void restartAutopilot() { + if (!isAnimateRunning) { + mPresenter.restartAutopilot(); + } + } + + @Override + public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() { + return this; + } + + @Override + public void moveToEnd() { + // 开启自动驾驶到下一站 + if (isAnimateRunning){ + stopAutopilotAnimation(); + } + mPresenter.autoDriveToNextStation(false); + } + + /** + * 设置自动驾驶可用状态 + */ + public void onAutopilotEnableChange(boolean isEnable) { + if (isEnable) { + showAutopilotBiz(); + } else { + hideAutopilotBiz(); + } + } + + @Override + protected void onChangeOperationStatus() { + super.onChangeOperationStatus(); + mPresenter.onChangeOperationStatus(); + } + + /** + * 修改经营状态 + * + * @param launch true-收车,false-出车 + */ + public void changeOperationStatus(boolean launch) { + isOperationStatus = launch; + if (launch) { + // 出车的时候重制站点状态 + mPresenter.querySweepersRoutes(); + tvOperationStatus.setText("收车"); + showPanel(); + } else { + AIAssist.getInstance(getContext()).speakTTSVoice("已收车"); + tvOperationStatus.setText("出车"); + hideSlidePanel(); + hidPanel(); + + //移除起点终点 + if (null != startStation) { + setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + } + if (null != endStation) { + setOrRemoveMapMaker(false, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } + } + } + + /** + * VR模式切换 + * + * @param isVRMode + */ + public void onVRModeChanged(boolean isVRMode) { + if (mRootView != null) { + mRootView.setVisibility(isVRMode ? View.VISIBLE : View.GONE); + } + } + + /** + * 绘制地图起点终点 + * + * @param isAdd + * @param uuid + */ + private void setOrRemoveMapMaker(boolean isAdd, String uuid, double lat, double longi,int resourceId) { + if (isAdd) { + Runnable setMapMarkerRunnable = new Runnable() { + @Override + public void run() { + CallerLogger.INSTANCE.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(), + uuid + "=latitude=" + lat + ",longitude=" + longi); + + MogoMarkerOptions options = new MogoMarkerOptions() + .owner(SweeperConst.TYPE_MARKER_SWEEPER_ORDER) + .anchor(0.5f, 0.5f) + .set3DMode(true) + .gps(true) + .controlAngle(true) + .icon3DRes(resourceId) + .latitude(lat) + .longitude(longi); + IMogoMarker marker = MogoMarkerManager.getInstance(AbsMogoApplication.getApp()) .addMarker(uuid, options); + CenterLine centerLine = CallerHDMapManager.INSTANCE.getCenterLineInfo( + longi,lat,-1); + if (null != centerLine){ // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 + marker.setRotateAngle(centerLine.getAngle().floatValue()); + } + } + }; + + OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable); + + }else { + Runnable removeMapMarkerRunnable = new Runnable() { + @Override + public void run() { + CallerLogger.INSTANCE.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(), + uuid+"=latitude="+lat+",longitude="+longi); + MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).removeMarkers(uuid); + } + }; + + OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable); + } + } + + @Override + public void debugAutoPilotStatus(int status) { + mPresenter.debugAutoPilotStatus(status); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中,点击则toast提示:自动驾驶中,不可切换路线 + //本次行程未结束,不支持切换路线。点击则toast提示:当前行程未完成,不可切换路线 + if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + ToastUtils.showLong(getResources().getString(R.string.sweeper_switch_line_btn_warning1)); + return; + } + if (mCurrentStation > 0) { + ToastUtils.showLong(getResources().getString(R.string.sweeper_switch_line_btn_warning2)); + return; + } + Intent intent = new Intent(getContext(), SweeperSwitchLineActivity.class); + startActivity(intent); + } + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperLineModel.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperLineModel.java new file mode 100644 index 0000000000..e297e5053e --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperLineModel.java @@ -0,0 +1,86 @@ +package com.mogo.och.sweeper.model; + +import android.content.Context; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.eagle.core.utilcode.util.NetworkUtils; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; +import com.mogo.och.sweeper.bean.SweeperRoutesResponse; +import com.mogo.och.sweeper.callback.ISweeperLinesCallback; +import com.mogo.och.sweeper.net.SweeperServiceManager; +import com.mogo.och.sweeper.net.ISweeperServiceCallback; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class SweeperLineModel { + private static volatile SweeperLineModel sInstance; + private Context mContext; + private ISweeperLinesCallback mBusLinesCallback; + public static SweeperLineModel getInstance() { + if ( sInstance == null ) { + synchronized ( SweeperLineModel.class ) { + if ( sInstance == null ) { + sInstance = new SweeperLineModel(); + } + } + } + return sInstance; + } + private SweeperLineModel() { + + } + public void init() { + mContext = AbsMogoApplication.getApp(); + } + public void setBusLinesCallback(ISweeperLinesCallback callback){ + mBusLinesCallback = callback; + } + public void queryBusLines(){ + SweeperServiceManager.getInstance().queryBusLines(mContext, new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperQueryLinesResponse data) { + if (null == data && mBusLinesCallback != null) { + mBusLinesCallback.onBusLinesChange(null); + return; + } + + if (mBusLinesCallback != null){ + mBusLinesCallback.onBusLinesChange(data); + } + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort("查询所有绑定路线失败:"+failMsg); + } + } + }); + } + + public void commitSwitchLineId(int lineId){ + SweeperServiceManager.getInstance().resetStationStatus(mContext,lineId, new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperRoutesResponse o) { + if (mBusLinesCallback != null){ + mBusLinesCallback.onChangeLineIdSuccess(); + } + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort("切换路线失败:"+failMsg); + } + } + }); + } + +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperOrderModel.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperOrderModel.java new file mode 100644 index 0000000000..46958b0642 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/model/SweeperOrderModel.java @@ -0,0 +1,896 @@ +package com.mogo.och.sweeper.model; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; +import static com.mogo.och.sweeper.constant.SweeperConst.STATION_STATUS_STOPPED; + +import android.content.Context; +import android.location.Location; +import android.os.Handler; +import android.os.Message; + +import androidx.annotation.NonNull; + +import com.amap.api.maps.model.LatLng; +import com.elegant.network.utils.GsonUtil; +import com.mogo.cloud.commons.utils.CoordinateUtils; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.module.status.IMogoStatusChangedListener; +import com.mogo.commons.module.status.MogoStatusManager; +import com.mogo.commons.module.status.StatusDescriptor; +import com.mogo.commons.voice.AIAssist; +import com.mogo.eagle.core.data.BaseData; +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotPlanningListenerManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.util.NetworkUtils; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.map.navi.IMogoCarLocationChangedListener2; +import com.mogo.module.common.MogoApisHandler; +import com.mogo.och.sweeper.bean.SweeperOperationStatusResponse; +import com.mogo.och.sweeper.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweeper.bean.SweeperRoutesResponse; +import com.mogo.och.sweeper.bean.SweeperRoutesResult; +import com.mogo.och.sweeper.bean.SweeperStationBean; +import com.mogo.och.sweeper.bean.QueryLeaveAwayPassengersResponse; +import com.mogo.och.sweeper.callback.ICarOperationStatusCallback; +import com.mogo.och.sweeper.callback.ISweeperControllerStatusCallback; +import com.mogo.och.sweeper.callback.IRefreshSweeperStationsCallback; +import com.mogo.och.sweeper.callback.ISlidePannelHideCallback; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.net.SweeperServiceManager; +import com.mogo.och.sweeper.net.ISweeperServiceCallback; +import com.mogo.och.sweeper.presenter.SweeperModelLoopManager; +import com.mogo.och.sweeper.util.SweeperAnalyticsManager; +import com.mogo.och.sweeper.util.SweeperTrajectoryManager; +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; +import com.mogo.och.common.module.utils.PinYinUtil; +import com.zhjt.service.chain.ChainLog; +import com.zhjt.service.chain.TracingConstants; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.exceptions.UndeliverableException; +import io.reactivex.functions.Consumer; +import io.reactivex.plugins.RxJavaPlugins; +import mogo.telematics.pad.MessagePad; + +/** + * @author congtaowang + * @since 2021/3/23 + *

+ * 小巴订单管理 + */ +public class SweeperOrderModel { + private final String TAG = SweeperOrderModel.class.getSimpleName(); + private int currentLineId = -1; + private int backgroundCurrentStationIndex = 0;//A->B 此处值是A站点索引 + /** + * 运营状态、后端更具运营状态来判断车辆是否派单 + */ + private boolean mIsWorking = false; + private static volatile SweeperOrderModel sInstance; + public double mLongitude = 0; + public double mLatitude = 0; + private Context mContext; + private final List stationList = new ArrayList<>(); + private SweeperRoutesResult sweeperRoutesResult = null; + /** + * 用来表示是否正在开往下一站 + */ + private boolean isGoingToNextStation = false; + // 运营类型 + private static final int VEHICLE_TYPE = 10; + private static final int MSG_QUERY_BUS_STATION = 1001; + private static final long QUERY_BUS_STATION_DELAY = 5000; + + private ICarOperationStatusCallback carOperationStatusCallback; + private IRefreshSweeperStationsCallback refreshBusStationsCallback; + private ISlidePannelHideCallback slidePannelHideCallback; + private ISweeperControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 + + List points = new ArrayList<>();//全路径信息 + + private boolean hadQueryLeaveAwayPassager = false; + + private volatile boolean isArrivedStation = false; + + private final Handler handler = new Handler(msg -> { + if (msg.what == MSG_QUERY_BUS_STATION) { + SweeperOrderModel.getInstance().querySweeperRoutes(); + return true; + } + return false; + }); + + public static SweeperOrderModel getInstance() { + if (sInstance == null) { + synchronized (SweeperOrderModel.class) { + if (sInstance == null) { + sInstance = new SweeperOrderModel(); + } + } + } + return sInstance; + } + + private SweeperOrderModel() { + + } + + public void init() { + mContext = AbsMogoApplication.getApp(); + // 2021/10/20 衡阳小巴业务,使用LenovoPad时需要此app自己获取坐标并上传 + String productFlavor = DebugConfig.getProductFlavor(); + if (productFlavor != null && productFlavor.contains("fPadLenovoOchBus")) { + MogoApisHandler.getInstance() + .getApis() + .getRegisterCenterApi() + .registerCarLocationChangedListener(TAG, mCarLocationChangedListener2); + MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + + //自动驾驶路线规划接口 + CallerAutopilotPlanningListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener); + } + + //2022.1.28 + // 调用Disposable.dispose() 时候会出现InterruptedException 导致出现崩溃 + // The exception could not be delivered to the consumer because it has already canceled/disposed + // the flow or the excTeption has nowhere to go to begin with + RxJavaPlugins.setErrorHandler(new Consumer() { + @Override + public void accept(Throwable e) { + if (e instanceof UndeliverableException) { + e = e.getCause(); + CallerLogger.INSTANCE.d(M_BUS + TAG, "UndeliverableException"); + } + if ((e instanceof IOException)) {// + // fine, irrelevant network problem or API that throws on cancellation + CallerLogger.INSTANCE.d(M_BUS + TAG, "IOException"); + return; + } + if (e instanceof InterruptedException) { + // fine, some blocking code was interrupted by a dispose call + CallerLogger.INSTANCE.d(M_BUS + TAG, "InterruptedException"); + return; + } + if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) { + // that's likely a bug in the application + CallerLogger.INSTANCE.d(M_BUS + TAG, "NullPointerException or IllegalArgumentException"); + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + return; + } + if (e instanceof IllegalStateException) { + // that's a bug in RxJava or in a custom operator + CallerLogger.INSTANCE.d(M_BUS + TAG, "IllegalStateException"); + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "Undeliverable exception"); + } + }); + + } + + public void setCarOperationStatusCallback(ICarOperationStatusCallback callback) { + this.carOperationStatusCallback = callback; + } + + public void setRefreshBusStationsCallback(IRefreshSweeperStationsCallback callback) { + this.refreshBusStationsCallback = callback; + } + + public void setSlidePannelHideCallback(ISlidePannelHideCallback callback) { + this.slidePannelHideCallback = callback; + } + + public void setControllerStatusCallback(ISweeperControllerStatusCallback callback) { + this.mControllerStatusCallback = callback; + } + + private final IMoGoAutopilotPlanningListener moGoAutopilotPlanningListener = new IMoGoAutopilotPlanningListener() { + + @Override + public void onAutopilotTrajectory(@NonNull List trajectoryInfos) { + + } + + @Override + public void onAutopilotRotting(MessagePad.GlobalPathResp routeList) { + if (null != routeList && routeList.getWayPointsList().size() > 0) { + points.clear(); + points.addAll(coordinateConverterWgsToGcjList(mContext, routeList.getWayPointsList())); + updateOrderRoute(); + } + } + + }; + + public static List coordinateConverterWgsToGcjList(Context mContext, List mogoLatLngList) { + List points = new ArrayList<>(); + for (MessagePad.Location m : mogoLatLngList) { + LatLng mogoLatLng = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj(mContext, m); + SweeperRoutePlanningUpdateReqBean.Result result = new SweeperRoutePlanningUpdateReqBean.Result(); + result.latitude = mogoLatLng.latitude; + result.longitude = mogoLatLng.longitude; + points.add(result); + } + return points; + } + + /** + * 上报订单全路径规划数据 + */ + public void updateOrderRoute() { + if (!isGoingToNextStation || backgroundCurrentStationIndex + 1 >= stationList.size() || points.size() == 0) { + return; + } + + SweeperStationBean currentStation = stationList.get(backgroundCurrentStationIndex); + SweeperStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1); + + SweeperServiceManager.getInstance().updateOrderRoute(mContext, currentLineId, currentStation.getSiteId() + , nextStation.getSiteId(), points, new ISweeperServiceCallback() { + @Override + public void onSuccess(BaseData o) { + + } + + @Override + public void onFail(String failMsg) { + if (isGoingToNextStation) {//重试 + updateOrderRoute(); + } + } + }); + } + + public void debugUpdateOrderRoute(List list) { + points.clear(); + points.addAll(coordinateConverterWgsToGcjList(mContext, list)); + updateOrderRoute(); + } + + public void release() { + startOrStopOrderLoop(false); + MogoStatusManager.getInstance().unregisterStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + // 注销到达起始站围栏监听 + MogoApisHandler.getInstance() + .getApis() + .getRegisterCenterApi() + .unregisterCarLocationChangedListener(TAG, mCarLocationChangedListener2); + + //自动驾驶路线规划接口 + CallerAutopilotPlanningListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); + } + + private Object readResolve() { + // 阻止反序列化,必须实现 Serializable 接口 + return sInstance; + } + + private final IMogoStatusChangedListener mMogoStatusChangedListener = new IMogoStatusChangedListener() { + // VR mode变更回调 + @Override + public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) { + if (StatusDescriptor.VR_MODE == descriptor) { + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onVRModeChanged(isTrue); + } + } + } + }; + + // 自车定位 + private final IMogoCarLocationChangedListener2 mCarLocationChangedListener2 = new IMogoCarLocationChangedListener2() { + + @Override + public void onCarLocationChanged2(Location location) { +// CallerLogger.INSTANCE.d(M_BUS + TAG,"location = "+location.getLongitude()+","+location.getLatitude()); + mLongitude = location.getLongitude(); + mLatitude = location.getLatitude(); + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onCarLocationChanged(location); + } + + //是否到站的围栏判断 离站状态并且自动驾驶还未触发到站 + if (isGoingToNextStation && !isArrivedStation) { + judgeStartStation(location); + } + } + }; + + //根据围栏判断,是否到达起点 + private void judgeStartStation(Location location) { + + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) { + return; + } + SweeperStationBean upcomingStation = stationList.get(backgroundCurrentStationIndex + 1); + + double startLon = upcomingStation.getGcjLon(); + double startLat = upcomingStation.getGcjLat(); + double distance = CoordinateUtils.calculateLineDistance( + startLon, startLat, + location.getLongitude(), location.getLatitude()); + + Logger.i(TAG, "judgeStartStation() distance = " + distance); + + if (distance > SweeperConst.ARRIVE_AT_END_STATION_DISTANCE) { + distance = CoordinateUtils.calculateLineDistance(startLon, startLat, + CallerAutoPilotStatusListenerManager.INSTANCE.getCurWgs84Lon(), + CallerAutoPilotStatusListenerManager.INSTANCE.getCurWgs84Lat()); + } + + if (distance <= SweeperConst.ARRIVE_AT_END_STATION_DISTANCE) { + onArriveAt(null); //无自动驾驶到站信息传null + return; + } + } + + /** + * 查询小巴路线 + */ + public void querySweeperRoutes() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "查询小巴路线"); + SweeperServiceManager.getInstance().queryBusRoutes(mContext, new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperRoutesResponse data) { + if (data == null + || data.getResult() == null + || data.getResult().getSites() == null + || data.getResult().getSites().isEmpty()) { + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "获取到小巴路线数据: " + data); + renderBusStationsStatus(data.getResult()); + } + + @Override + public void onFail(String failMsg) { + // 重复请求小巴路线,直至成功 + queryBusStationDelay(); + } + }); + + } + + /** + * 测试、重置站点状态 + */ + public void debugResetStationStatus() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "测试、重置站点状态"); + SweeperServiceManager.getInstance().resetStationStatus(mContext, currentLineId + , new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperRoutesResponse o) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "获取到小巴路线数据: " + o); + isGoingToNextStation = false; + if (o.getResult() == null || o.getResult().getSites() == null || o.getResult().getSites().isEmpty()) { + return; + } + renderBusStationsStatus(o.getResult()); + } + + @Override + public void onFail(String failMsg) { + // 重复请求小巴路线,直至成功 + queryBusStationDelay(); + } + }); + + } + + /** + * 离站上报 + */ + public void leaveStation(boolean isOneWayOver, boolean isRestart) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "leaveStation-backgroundCurrentStationIndex = " + backgroundCurrentStationIndex); + SweeperServiceManager.getInstance().leaveStation(mContext, stationList.get(backgroundCurrentStationIndex).getSeq() + , stationList.get(backgroundCurrentStationIndex).getSiteId(), new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperRoutesResponse o) { + if (o.getResult() == null || o.getResult().getSites() == null || o.getResult().getSites().isEmpty()) { + return; + } + isArrivedStation = false; + if (!isOneWayOver) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "自动驾驶开启开往下一站===="); + //需要更改当前站和下一站的状态 然后渲染 + leaveStationSuccess(o.getResult(), isRestart); + } else { + CallerLogger.INSTANCE.d(M_BUS + TAG, "单程真的结束了===="); + isGoingToNextStation = false; + backgroundCurrentStationIndex = 0; + CallerAutoPilotManager.INSTANCE.cancelAutoPilot(); + querySweeperRoutes(); + } + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + ToastUtils.showShort("离站上报失败:" + failMsg); + } + } + }); + } + + /** + * 离站上报成功后渲染站点 + * 服务端返回的OchBusRoutesResult逻辑, 离开站为当前站, 到达下一站后才会将下一站置为当前站, + * 车机端展示是离开当前站,下一站设置为当前站, 所以服务端数据回来要做处理,不能直接渲染 + */ + private void leaveStationSuccess(SweeperRoutesResult result, boolean isRestart) { + renderBusStationsStatus(result); + if (slidePannelHideCallback != null) { + slidePannelHideCallback.hideSlidePanel(); + } + //开启自动驾驶 + startAutopilot(isRestart); + if (isGoingToNextStation) { + // 为了避免恢复自动驾驶时重复的接口请求 + return; + } + isGoingToNextStation = true; + AIAssist.getInstance(mContext).speakTTSVoice("欢迎乘坐’蘑菇车联‘无人驾驶小巴车,请您坐好,注意乘车安全,行程即将开始"); + } + + /** + * 开启自动驾驶 + * + * @param isRestart + */ + private void startAutopilot(boolean isRestart) { + + triggerStartServiceEvent(isRestart, false); + + isArrivedStation = false; +// SweeperStationBean currentStation = stationList.get( backgroundCurrentStationIndex); +// SweeperStationBean nextStation = stationList.get( backgroundCurrentStationIndex + 1); + +// if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE +// == CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) { +// ToastUtils.showShort("自动驾驶状态为不可用!"); +// } + AutopilotControlParameters parameters = new AutopilotControlParameters(); +// parameters.isSpeakVoice = !isRestart; +// parameters.routeID = sweeperRoutesResult.getLineId(); +// parameters.routeName = sweeperRoutesResult.getName(); +// parameters.startName = PinYinUtil.getPinYinHeadChar(currentStation.getName()); +// parameters.endName = PinYinUtil.getPinYinHeadChar(nextStation.getName()); +// parameters.startLatLon = new AutopilotControlParameters +// .AutoPilotLonLat( currentStation.getLat(), currentStation.getLon() ); +// parameters.endLatLon = new AutopilotControlParameters +// .AutoPilotLonLat( nextStation.getLat(), nextStation.getLon() ); +// parameters.vehicleType = VEHICLE_TYPE; +// if (parameters.autoPilotLine == null) { +// parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine( +// sweeperRoutesResult.getLineId(), +// sweeperRoutesResult.csvFileUrl, sweeperRoutesResult.csvFileMd5, +// sweeperRoutesResult.txtFileUrl, sweeperRoutesResult.txtFileMd5, +// sweeperRoutesResult.contrailSaveTime, sweeperRoutesResult.carModel, +// sweeperRoutesResult.csvFileUrlDPQP, sweeperRoutesResult.csvFileMd5DPQP, +// sweeperRoutesResult.txtFileUrlDPQP, sweeperRoutesResult.txtFileMd5DPQP, +// sweeperRoutesResult.contrailSaveTimeDPQP); +// } +// CallerLogger.INSTANCE.d( M_BUS + TAG, "开启自动驾驶====" + GsonUtil.jsonFromObject(parameters) +// +" startLatLon="+currentStation.getName()+",endLatLon="+nextStation.getName()); + CallerLogger.INSTANCE.d(M_BUS + TAG, "开启自动驾驶====" + GsonUtil.jsonFromObject(parameters)); + CallerAutoPilotManager.INSTANCE.startAutoPilot(parameters); + + if (mControllerStatusCallback != null) { + mControllerStatusCallback.startOpenAutopilot(); + } + } + + /** + * 到站后重置站点状态 + */ + private void arriveSiteStation(boolean isRestart) { + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) { //到站短时间内调用多次 + CallerLogger.INSTANCE.e(M_BUS + TAG, "数组越界"); + return; + } + int arrivedStationIndex = 0; + if (!isRestart) { + arrivedStationIndex = backgroundCurrentStationIndex + 1; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "arriveSiteStation-currentStationIndex = " + arrivedStationIndex); + + SweeperServiceManager.getInstance().arriveSiteStation(mContext + , stationList.get(arrivedStationIndex).getSeq(), stationList.get(arrivedStationIndex).getSiteId() + , new ISweeperServiceCallback() { + @Override + public void onSuccess(BaseData o) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "arriveSiteStation success"); + if (!isRestart) { + renderArriveBusStation(); + } + } + + @Override + public void onFail(String failMsg) { +// if (!NetworkUtils.isConnected(mContext)) { +// ToastUtils.showShort("网络异常,请稍后重试"); +// }else { +// ToastUtils.showShort("离站上报失败:"+failMsg); +// } + + } + }); + } + + private void renderArriveBusStation() { + List site = sweeperRoutesResult.getSites(); + if (site != null && site.size() > 0) { + backgroundCurrentStationIndex++; + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.refreshBusStations(sweeperRoutesResult.getName(), stationList, backgroundCurrentStationIndex + , getNextStopStation(), true); + } + } + } + + /** + * 收车 + */ + public void stopTakeOrder() { + SweeperServiceManager.getInstance().stopTakeOrder(mContext, new ISweeperServiceCallback() { + @Override + public void onSuccess(BaseData o) { + mIsWorking = !mIsWorking; + closeBeautificationMode(); + carOperationStatusCallback.changeOperationStatus(isWorking()); + startOrStopOrderLoop(mIsWorking); + SweeperTrajectoryManager.getInstance().stopTrajReqLoop(); + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + ToastUtils.showShort("收车失败:" + failMsg); + } + } + }); + } + + /** + * 关闭美化模式 + */ + private void closeBeautificationMode() { + if (FunctionBuildConfig.isDemoMode) {//收车结束美化 + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为false(收车)"); + } + } + + /** + * 出车 + */ + public void startTakeOrder() { + SweeperServiceManager.getInstance().startTakeOrder(mContext, new ISweeperServiceCallback() { + @Override + public void onSuccess(BaseData o) { + mIsWorking = !mIsWorking; + startOrStopOrderLoop(mIsWorking); + if (stationList != null && stationList.size() > 0) { + AIAssist.getInstance(mContext).speakTTSVoice("车辆已整备完毕,请前往" + + stationList.get(backgroundCurrentStationIndex).getName() + "站点"); + } + carOperationStatusCallback.changeOperationStatus(isWorking()); + querySweeperRoutes(); + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + ToastUtils.showShort("出车失败:" + failMsg); + } + } + }); + } + + /** + * 查询运营状态 + */ + public void queryOperationStatus() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "查询运营状态"); + SweeperServiceManager.getInstance().queryOperationStatus(mContext + , new ISweeperServiceCallback() { + @Override + public void onSuccess(SweeperOperationStatusResponse o) { + if (o.data != null) { + mIsWorking = o.data.serviceStatus == 1; + CallerLogger.INSTANCE.d(M_BUS + TAG, "查询运营状态 result.status: " + o.data.serviceStatus); + startOrStopOrderLoop(mIsWorking); + } + carOperationStatusCallback.changeOperationStatus(isWorking()); + } + + @Override + public void onFail(String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + ToastUtils.showShort("出车收车状态查询:" + failMsg); + } +// queryOperationStatus(); + } + }); + } + + /** + * 开启自动驾驶到下一站 + */ + public void autoDriveToNextStation(boolean isRestart) { +// if ( backgroundCurrentStationIndex >= stationList.size() - 1 ) { +// // 当前站是最后一站,结束当前行程 +// travelOver(); +// return; +// } +// leaveStation(false,isRestart); + startAutopilot(isRestart); + } + + /** + * 渲染站点信息 + * 服务端返回的OchBusRoutesResult逻辑, 离开站为当前站, 到达下一站后才会将下一站置为当前站, + * 车机端展示 离开站为当前站点,前往站为下一站, 下一站到站后在置为当前站 + * + * @param result + */ + private void renderBusStationsStatus(SweeperRoutesResult result) { + if (result == null) return; + sweeperRoutesResult = result; + List site = result.getSites(); + currentLineId = result.getLineId(); + stationList.clear(); + stationList.addAll(site); + for (int i = 0; i < stationList.size(); i++) { + SweeperStationBean s = stationList.get(i); + + CallerLogger.INSTANCE.d(M_BUS + "renderBusStationsStatus--", + "Index=" + i + " ,name = " + s.getName() + " ," + s.isLeaving() + "," + s.getDrivingStatus()); + + // 是否正在开往下一站 + if (s.isLeaving()) { + isGoingToNextStation = true; + } + // 当前站点信息 + if (s.getDrivingStatus() == STATION_STATUS_STOPPED) { + backgroundCurrentStationIndex = i; + break; + } + } + + SweeperStationBean currentStation = stationList.get(backgroundCurrentStationIndex); + + CallerLogger.INSTANCE.d(M_BUS + TAG, + "渲染站点信息服务端currentStationIndex=" + backgroundCurrentStationIndex + + " isLeaving()=" + currentStation.isLeaving()); + + //当前站点是始发站,告诉服务端到达始发站。 如果没有这个节点, 服务器不知道始发站到达状态 + // ,订单开始站下在始发站的状态流转有问题 + if (backgroundCurrentStationIndex == 0 && !currentStation.isLeaving()) { + arriveSiteStation(true); + } + + // 美化是否开始 + if (FunctionBuildConfig.isDemoMode && (backgroundCurrentStationIndex >= 0 + && backgroundCurrentStationIndex <= stationList.size() - 1) + && stationList.get(backgroundCurrentStationIndex).isLeaving()) {//行驶过程中设置美化 + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotManager.INSTANCE.setIPCDemoMode(true); + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为true(每次滑动出发)"); + } + + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.refreshBusStations(result.getName(), stationList + , backgroundCurrentStationIndex, getNextStopStation(), !currentStation.isLeaving()); + } + + if (currentStation.isLeaving() && slidePannelHideCallback != null) { + slidePannelHideCallback.hideSlidePanel(); + } + + //需放在currentStationIndex赋值之后 + SweeperTrajectoryManager.getInstance().syncTrajectoryInfo(); + } + + /** + * 根据订单状态、获取下一站靠站的的站点 + * + * @return -1 当前已是最后一个站点 + */ + private int getNextStopStation() { + if (backgroundCurrentStationIndex >= stationList.size() - 1) { + return -1; + } + int nextStationIndex = backgroundCurrentStationIndex + 1; + for (; nextStationIndex < stationList.size() - 1; nextStationIndex++) { + if (stationList.get(nextStationIndex).getIfStop() == 1) { + break; + } + break; + } + return nextStationIndex; + } + + /** + * 延时查询站点信心 + */ + private void queryBusStationDelay() { + handler.sendEmptyMessageDelayed(MSG_QUERY_BUS_STATION, QUERY_BUS_STATION_DELAY); + } + + /** + * 在踩刹车、控制方向盘等操作后,会停止自动驾驶,重启自动驾驶的话相当于重新设置自动驾驶目的地 + */ + public void restartAutopilot() { +// CallerLogger.INSTANCE.d( M_BUS + TAG, "重启自动驾驶===" + isGoingToNextStation ); +// autoDriveToNextStation( true ); + //直接开启自动驾驶 + startAutopilot(true); + } + + /** + * 播报下车乘客信息 + * + * @param awayPassengersResponse + */ + private void playLeavePassengersMsg(QueryLeaveAwayPassengersResponse awayPassengersResponse) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "播报下车乘客信息currentStationIndex=" + + String.valueOf(backgroundCurrentStationIndex + 1)); + + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) { + return; + } + String station = stationList.get(backgroundCurrentStationIndex + 1).getName(); + StringBuilder builder = new StringBuilder("已到达"); + builder.append(station); + if (!station.endsWith("站")) { + builder.append("站"); + } + if (awayPassengersResponse == null || awayPassengersResponse.data == null + || awayPassengersResponse.data.orders == null || awayPassengersResponse.data.orders.isEmpty()) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "播报下车乘客信息为null"); + } else { + builder.append(",请尾号为 "); + for (QueryLeaveAwayPassengersResponse.LeaveAwayPassenger leaveAwayPassenger : awayPassengersResponse.data.orders) { + if (leaveAwayPassenger == null) { + continue; + } + String tailNum = null; + try { + tailNum = leaveAwayPassenger.passengerPhone.substring(leaveAwayPassenger.passengerPhone.length() - 4); + } catch (Exception e) { + e.printStackTrace(); + tailNum = leaveAwayPassenger.passengerPhone; + } + builder.append(tailNum).append("。"); + } + builder.append("的乘客下车"); + } + builder.append(",带好随身物品,下车请注意安全"); + CallerLogger.INSTANCE.d(M_BUS + TAG, "TTS:" + builder.toString()); + AIAssist.getInstance(mContext).speakTTSVoice(builder.toString()); + } + + /** + * 修改小巴运营状态 + */ + public void onChangeOperationStatus() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "修改小巴运营状态"); + if (isWorking()) {//收车 + stopTakeOrder(); + } else {//出车 + startTakeOrder(); + } + } + + /** + * 行程结束 + */ + private void travelOver() { + + if (backgroundCurrentStationIndex >= stationList.size()) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "travel over index out of station list"); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "单程结束===="); + CallerAutoPilotManager.INSTANCE.cancelAutoPilot(); + AIAssist.getInstance(mContext).speakTTSVoice("感谢您体验'蘑菇车联'无人驾驶小巴车,请您携带好随身物品,我们下次再见"); + leaveStation(true, true); + } + + public boolean isWorking() { + return mIsWorking; + } + + /** + * 到站 + * + * @param data + */ + public void onArriveAt(MessagePad.ArrivalNotification data) { +// if ( backgroundCurrentStationIndex +1 > stationList.size() - 1 ) { +// CallerLogger.INSTANCE.e( M_BUS + TAG, "到站异常,取消后续操作结束" ); +// return; +// } + + if (isArrivedStation) return; + isArrivedStation = true; + + if (FunctionBuildConfig.isDemoMode && backgroundCurrentStationIndex <= stationList.size() - 1) {//到达一站结束美化 + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为false(到最后一站)"); + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "到站====currentStationIndex=" + backgroundCurrentStationIndex); + isGoingToNextStation = false; + +// arriveSiteStation(false);//到站上报 + } + + public boolean isGoingToNextStation() { + return isGoingToNextStation; + } + + // 车机端上传心跳数据(只在出车状态时上传) + public void runCarHeartbeat() { + SweeperServiceManager.getInstance().runCarHeartbeat(mContext, mLongitude, mLatitude, + new ISweeperServiceCallback() { + @Override + public void onSuccess(BaseData data) { + + } + + @Override + public void onFail(String failMsg) { + + } + }); + } + + private void startOrStopOrderLoop(boolean start) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "startOrStopOrderLoop() " + start); + if (start) { + SweeperModelLoopManager.getInstance().startHeartbeatLoop(); + } else { + SweeperModelLoopManager.getInstance().stopHeartbeatLoop(); + } + } + + public void triggerStartServiceEvent(boolean isRestart, boolean send) { + if (stationList == null || backgroundCurrentStationIndex >= stationList.size() - 1) { + return; + } + SweeperStationBean currentStation = stationList.get(backgroundCurrentStationIndex); + SweeperStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1); + SweeperAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestart, send, + currentStation.getName(), nextStation.getName(), currentLineId); + } + + public SweeperRoutesResult getBusRoutesResult() { + return sweeperRoutesResult; + } + + public int getCurrentStationIndex() { + return backgroundCurrentStationIndex; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperApiService.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperApiService.java new file mode 100644 index 0000000000..db8c6b3264 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperApiService.java @@ -0,0 +1,117 @@ +package com.mogo.och.sweeper.net; +import com.mogo.eagle.core.data.BaseData; +import com.mogo.och.sweeper.bean.SweeperOperationStatusRequest; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; +import com.mogo.och.sweeper.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweeper.bean.SweeperRoutesResponse; +import com.mogo.och.sweeper.bean.CarHeartbeatReqBean; +import com.mogo.och.sweeper.bean.SweeperQueryLineStationsRequest; +import com.mogo.och.sweeper.bean.SweeperOperationStatusResponse; +import com.mogo.och.sweeper.bean.SweeperResetDrivingLineRequest; +import com.mogo.och.sweeper.bean.SweeperUpdateSiteStatusRequest; + +import io.reactivex.Observable; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.Headers; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * 小巴车相关接口 + * + * @author tongchenfei + *

+ * wiki: http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48970072 + */ +public interface ISweeperApiService { + /** + * 根据车机坐标获取所在区域全部站点信息 + * + * @param request 请求参数 + * @return 接口返回数据 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/autopilot-car-hailing/line/v2/driver/bus/lineDataWithDriver/query" ) + Observable querySiteByCoordinate(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperQueryLineStationsRequest request); + + /** + * 重置巴士路线: 点击小巴车tab 或者出车后会使用 + * + * @param request 请求参数{"destLine":1,"sn":"F803EB2046PZD00229"} 这个接口是重置bus线路的, 不是重置线路中站点的 + * @return 返回值是重置后的车站列表 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/autopilot-car-hailing/car/v2/driver/bus/drivingLine/reset" ) + Observable resetStationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperResetDrivingLineRequest request); + + /** + * 离站,通知服务器 + * @param request + * @return + */ + @Headers({"Content-Type:application/json;charset=UTF-8"}) + @POST("/autopilot-car-hailing/car/v2/driver/bus/driving/away") + Observable leaveStation(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperUpdateSiteStatusRequest request); + + /** + * 到站 更新到站信息 + * @param request + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/autopilot-car-hailing/order/v2/driver/bus/driving/attachSite") + Observable< BaseData > arriveSiteStation(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperUpdateSiteStatusRequest request); + + /** + * 出车 + * @param request + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST("/autopilot-car-hailing/car/v2/driver/bus/startTakeOrder") + Observable startTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperOperationStatusRequest request); + + /** + * 收车 + * @param request + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/autopilot-car-hailing/car/v2/driver/bus/stopTakeOrder") + Observable stopTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperOperationStatusRequest request); + + /** + * 查询小巴出车/收车状态 + * @param sn + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @GET("/autopilot-car-hailing/car/v2/driver/bus/takeOrderStatus/query") + Observable queryOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + /** + * 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度 + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST( "/autopilot-car-hailing/location/v2/driver/bus/heartbeat" ) + Observable runCarHeartbeat(@Header ("appId") String appId,@Header("ticket") String ticket,@Body CarHeartbeatReqBean data); + + /** + * 查询车辆配置的所有路线 + * @param appId + * @param ticket + * @param sn + * @return + */ + @GET("/autopilot-car-hailing/line/v2/driver/bus/bindLine/query") + Observable queryBusLines(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST( "/autopilot-car-hailing/location/v2/driver/bus/saveLineCoordinate" ) + Observable updateOrderRoute(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperRoutePlanningUpdateReqBean data); +} + diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperServiceCallback.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperServiceCallback.java new file mode 100644 index 0000000000..0a57b49d1e --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/ISweeperServiceCallback.java @@ -0,0 +1,15 @@ +package com.mogo.och.sweeper.net; + +/** + * @author: wangmingjun + * @date: 2021/10/20 + */ +public interface ISweeperServiceCallback< T >{ + void onSuccess(T o); + + void onFail(String failMsg); + + default void onError() { + + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/SweeperServiceManager.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/SweeperServiceManager.java new file mode 100644 index 0000000000..f6cd975dbd --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/net/SweeperServiceManager.java @@ -0,0 +1,225 @@ +package com.mogo.och.sweeper.net; +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.content.Context; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; +import com.mogo.eagle.core.data.BaseData; +import com.mogo.eagle.core.network.MoGoRetrofitFactory; +import com.mogo.eagle.core.network.RequestOptions; +import com.mogo.eagle.core.network.SubscribeImpl; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; +import com.mogo.och.sweeper.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweeper.bean.SweeperRoutesResponse; +import com.mogo.och.sweeper.bean.CarHeartbeatReqBean; +import com.mogo.och.sweeper.bean.SweeperOperationStatusRequest; +import com.mogo.och.sweeper.bean.SweeperOperationStatusResponse; +import com.mogo.och.sweeper.bean.SweeperQueryLineStationsRequest; +import com.mogo.och.sweeper.bean.SweeperResetDrivingLineRequest; +import com.mogo.och.sweeper.bean.SweeperUpdateSiteStatusRequest; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.model.SweeperOrderModel; + +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * @author: wangmingjun + * @date: 2021/10/20 + */ +public class SweeperServiceManager { + + private static final String TAG = SweeperServiceManager.class.getSimpleName(); + + private final ISweeperApiService mService; + + private static final class SingletonHolder { + private static final SweeperServiceManager INSTANCE = new SweeperServiceManager(); + } + + public static SweeperServiceManager getInstance(){ + return SingletonHolder.INSTANCE; + } + + private SweeperServiceManager(){ + mService = MoGoRetrofitFactory.getInstance(SweeperConst.getBaseUrl()).create(ISweeperApiService.class); + } + + /** + * 查询小巴车线路 + * @param context + * @param callback + */ + public void queryBusRoutes(Context context, ISweeperServiceCallback callback) { + //获取当前高德坐标 + + mService.querySiteByCoordinate(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + , new SweeperQueryLineStationsRequest(SweeperOrderModel.getInstance().mLongitude + , SweeperOrderModel.getInstance().mLatitude,true)) + .subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() ) + .subscribe( getSubscribeImpl(context,callback,"querySiteByCoordinate")); + } + + /** + * 重置线路站点 + * @param context + * @param lineId + * @param callback + */ + public void resetStationStatus(Context context, int lineId, ISweeperServiceCallback callback){ + mService.resetStationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken(),new SweeperResetDrivingLineRequest(lineId)) + .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"debugResetStationStatus")); + } + + /** + * 离站上报 + * @param context + * @param seq + * @param siteId + * @param callback + */ + public void leaveStation(Context context, int seq, int siteId, ISweeperServiceCallback callback){ + mService.leaveStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new SweeperUpdateSiteStatusRequest(seq,siteId, SweeperOrderModel.getInstance().mLongitude + , SweeperOrderModel.getInstance().mLatitude)) + .subscribeOn( Schedulers.io() ) + .observeOn( AndroidSchedulers.mainThread() ) + .subscribe(getSubscribeImpl(context,callback,"leaveStation")); + } + + /** + * 到站更新站点状态 + * @param context + * @param seq + * @param siteId + * @param callback + */ + public void arriveSiteStation(Context context, int seq, int siteId, ISweeperServiceCallback callback){ + mService.arriveSiteStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new SweeperUpdateSiteStatusRequest(seq,siteId + , SweeperOrderModel.getInstance().mLongitude, SweeperOrderModel.getInstance().mLatitude)) + .subscribeOn( Schedulers.io() ) + .observeOn( AndroidSchedulers.mainThread() ) + .subscribe(getSubscribeImpl(context,callback,"leaveStation")); + } + + /** + * 收车 + * @param context + * @param callback + */ + public void stopTakeOrder(Context context, ISweeperServiceCallback callback){ + mService.stopTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new SweeperOperationStatusRequest(SweeperOrderModel.getInstance().mLongitude + , SweeperOrderModel.getInstance().mLatitude)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"stopTakeOrder")); + } + + /** + * 出车 + * @param context + * @param callback + */ + public void startTakeOrder(Context context, ISweeperServiceCallback callback){ + mService.startTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new SweeperOperationStatusRequest(SweeperOrderModel.getInstance().mLongitude + , SweeperOrderModel.getInstance().mLatitude)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"startTakeOrder")); + } + + /** + * 查询出车/收车状态 + * @param context + * @param callback + */ + public void queryOperationStatus(Context context, ISweeperServiceCallback callback){ + mService.queryOperationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn()) + .subscribeOn( Schedulers.io() ) + .observeOn( AndroidSchedulers.mainThread() ) + .subscribe(getSubscribeImpl(context,callback,"queryOperationStatus")); + } + + + public void queryBusLines(Context context, ISweeperServiceCallback callback){ + mService.queryBusLines(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"queryBusLines")); + } + + public void updateOrderRoute(Context context,int lineId, int startSiteId, int endSiteId + , List< SweeperRoutePlanningUpdateReqBean.Result > points + , ISweeperServiceCallback callback){ + mService.updateOrderRoute(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new SweeperRoutePlanningUpdateReqBean(MoGoAiCloudClientConfig.getInstance().getSn() + ,lineId,startSiteId,endSiteId, points)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"updateOrderRoute")); + } + + /** + * 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度 + * @param context + * @param lon + * @param lat + * @param callback + */ + public void runCarHeartbeat(Context context, double lon, double lat, + ISweeperServiceCallback callback) { + mService.runCarHeartbeat(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken(),new CarHeartbeatReqBean( + MoGoAiCloudClientConfig.getInstance().getSn(), lon, lat)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context, callback, "runCarHeartbeat")); + } + + private SubscribeImpl getSubscribeImpl(Context context, ISweeperServiceCallback callback, String apiName){ + return new SubscribeImpl(RequestOptions.create(context)){ + @Override + public void onSuccess(T o) { + super.onSuccess(o); + CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onSuccess() " + o.msg); + if (callback != null) { + callback.onSuccess(o); + } + } + + @Override + public void onError(String message, int code) { + super.onError(message, code); + CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onError() " +"msg="+ message+" code="+code); + if (callback != null) { + callback.onFail("msg="+ message+" code="+code); + } + } + + @Override + public void onError(Throwable e) { + super.onError(e); + CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onError() " +" e="+e.getMessage()); + if (callback != null) { + callback.onFail(e.getMessage()); + } + } + }; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperLinePresenter.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperLinePresenter.java new file mode 100644 index 0000000000..5cfb5b80f2 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperLinePresenter.java @@ -0,0 +1,79 @@ +package com.mogo.och.sweeper.presenter; + +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; + +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; +import com.mogo.och.sweeper.callback.ISweeperLinesCallback; +import com.mogo.och.sweeper.model.SweeperLineModel; +import com.mogo.och.sweeper.model.SweeperOrderModel; +import com.mogo.och.sweeper.ui.SweeperSwitchLineView; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class SweeperLinePresenter extends Presenter implements ISweeperLinesCallback { + + public SweeperLinePresenter(SweeperSwitchLineView view) { + super(view); + SweeperLineModel.getInstance().init(); + SweeperOrderModel.getInstance().init(); + } + + @Override + public void onCreate(@NonNull LifecycleOwner owner) { + super.onCreate(owner); + initListener(); + } + + private void initListener() { + SweeperLineModel.getInstance().setBusLinesCallback(this); + } + + private void runOnUIThread( Runnable executor ) { + if ( executor == null ) { + return; + } + if ( Looper.myLooper() != Looper.getMainLooper() ) { + UiThreadHandler.post( executor ); + } else { + executor.run(); + } + } + + @Override + public void onBusLinesChange(SweeperQueryLinesResponse lines) { + runOnUIThread(() -> mView.onBusLinesChange(lines)); + } + + @Override + public void onChangeLineIdSuccess() { + runOnUIThread(() -> mView.onChangeLineIdSuccess()); + } + + public void queryBusLines(){ + SweeperLineModel.getInstance().queryBusLines(); + } + + public void commitSwitchLineId(int lineId){ + SweeperLineModel.getInstance().commitSwitchLineId(lineId); + } + + public void removeListener(){ + SweeperLineModel.getInstance().setBusLinesCallback(null); + } + + public void queryBusRoutes(){ + SweeperOrderModel.getInstance().querySweeperRoutes(); + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + super.onDestroy(owner); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperModelLoopManager.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperModelLoopManager.java new file mode 100644 index 0000000000..ac03cc4800 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperModelLoopManager.java @@ -0,0 +1,55 @@ +package com.mogo.och.sweeper.presenter; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.model.SweeperOrderModel; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +/** + * Created on 2021/11/22 + * + * 管理轮询逻辑(订单轮询、新单轮询、新单抢单结果轮询等等) + */ +public class SweeperModelLoopManager { + + private static final String TAG = SweeperModelLoopManager.class.getSimpleName(); + + private static final class SingletonHolder { + private static final SweeperModelLoopManager INSTANCE = new SweeperModelLoopManager(); + } + + public static SweeperModelLoopManager getInstance() { + return SingletonHolder.INSTANCE; + } + + private Disposable mHeartbeatDisposable; //心跳轮询 + + public void startHeartbeatLoop() { + if (mHeartbeatDisposable != null && !mHeartbeatDisposable.isDisposed()) { + return; + } + CallerLogger.INSTANCE.i(M_BUS + TAG, "startHeartbeatLoop()"); + mHeartbeatDisposable = Observable.interval(SweeperConst.LOOP_DELAY, + SweeperConst.LOOP_PERIOD_60S, TimeUnit.MILLISECONDS) + .map((aLong -> aLong + 1)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> SweeperOrderModel.getInstance().runCarHeartbeat()); + } + + public void stopHeartbeatLoop() { + if (mHeartbeatDisposable != null) { + CallerLogger.INSTANCE.i(M_BUS + TAG, "stopHeartbeatLoop()"); + mHeartbeatDisposable.dispose(); + mHeartbeatDisposable = null; + } + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperPresenter.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperPresenter.java new file mode 100644 index 0000000000..02a7075a08 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/presenter/SweeperPresenter.java @@ -0,0 +1,288 @@ +package com.mogo.och.sweeper.presenter; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.location.Location; +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleOwner; + +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.sweeper.bean.SweeperStationBean; +import com.mogo.och.sweeper.callback.ICarOperationStatusCallback; +import com.mogo.och.sweeper.callback.ISweeperControllerStatusCallback; +import com.mogo.och.sweeper.callback.IRefreshSweeperStationsCallback; +import com.mogo.och.sweeper.callback.ISlidePannelHideCallback; +import com.mogo.och.sweeper.fragment.SweeperFragment; +import com.mogo.och.sweeper.model.SweeperOrderModel; +import com.mogo.och.sweeper.util.SweeperTrajectoryManager; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; +import mogo_msg.MogoReportMsg; +import system_master.SystemStatusInfo; + +/** + * 网约车小巴 + * + * @author tongchenfei + */ +public class SweeperPresenter extends Presenter + implements ICarOperationStatusCallback, IRefreshSweeperStationsCallback, ISlidePannelHideCallback + , IMoGoAutopilotStatusListener, ISweeperControllerStatusCallback { + + private static final String TAG = "BusPresenter"; + + private int currentAutopilotStatus = -1; + private List mStationList = new ArrayList<>(); + private int mCurrentStation = 0; + private boolean isRestartAutopilot = false; + + public SweeperPresenter(SweeperFragment view) { + super(view); + //2021.11.1 鹰眼架构整合,由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口 + CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, this); + SweeperOrderModel.getInstance().init(); + } + + @Override + public void onCreate(@NonNull LifecycleOwner owner) { + super.onCreate(owner); + SweeperOrderModel.getInstance().queryOperationStatus(); + SweeperOrderModel.getInstance().querySweeperRoutes(); + initModelListener(); + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + super.onDestroy(owner); + SweeperOrderModel.getInstance().release(); + releaseListener(); + } + + public void initModelListener() { + SweeperOrderModel.getInstance().setCarOperationStatusCallback(this); + SweeperOrderModel.getInstance().setRefreshBusStationsCallback(this); + SweeperOrderModel.getInstance().setSlidePannelHideCallback(this); + SweeperOrderModel.getInstance().setControllerStatusCallback(this); + } + + public void releaseListener() { + SweeperOrderModel.getInstance().setCarOperationStatusCallback(null); + SweeperOrderModel.getInstance().setRefreshBusStationsCallback(null); + SweeperOrderModel.getInstance().setSlidePannelHideCallback(null); + SweeperOrderModel.getInstance().setControllerStatusCallback(null); + } + + public void querySweepersRoutes() { + SweeperOrderModel.getInstance().querySweeperRoutes(); + } + + public void debugResetStationStatus() { + SweeperOrderModel.getInstance().debugResetStationStatus(); + } + + public void autoDriveToNextStation(boolean isRestart) { + currentAutopilotStatus = -1; + SweeperOrderModel.getInstance().autoDriveToNextStation(isRestart); + isRestartAutopilot = false; + } + + public void restartAutopilot() { +// if (SweeperOrderModel.getInstance().isGoingToNextStation()){ + currentAutopilotStatus = -1; + SweeperOrderModel.getInstance().restartAutopilot(); + isRestartAutopilot = true; +// } + } + + public void onChangeOperationStatus() { + SweeperOrderModel.getInstance().onChangeOperationStatus(); + } + + @Override + public void changeOperationStatus(boolean changeStatus) { + if (mView != null) { + runOnUIThread(() -> mView.changeOperationStatus(changeStatus)); + } + } + + @Override + public void refreshBusStations(String lineName,List stationList + , int currentStation, int nextStation, boolean isArrived) { + mStationList.clear(); + mStationList.addAll(stationList); + mCurrentStation = currentStation; +// functionDemoModeChange(); + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation); + if (mView != null) { + runOnUIThread(() -> mView.refreshSweeperStations(lineName, + stationList, currentStation, nextStation, isArrived)); + } + } + + private void functionDemoModeChange() { +// CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel ="," functionDemoModeChange ="+mCurrentStation); + if (FunctionBuildConfig.isDemoMode + && ((mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1) + || ((mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1) + && SweeperOrderModel.getInstance().isGoingToNextStation()))) { + runOnUIThread(() -> mView.onAutopilotStatusChanged( + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)); + } + } + + @Override + public void hideSlidePanel() { + if (mView != null) { + runOnUIThread(() -> mView.hideSlidePanel()); + } + } + + @Override + public void onAutopilotArriveAtStation(MessagePad.ArrivalNotification arrivalNotification) { + SweeperOrderModel.getInstance().onArriveAt(arrivalNotification); + } + + @Override + public void onAutopilotSNRequest() { + + } + + @Override + public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { + if (autopilotStatusInfo == null) return; + int state = autopilotStatusInfo.getState(); +// CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChange: " + state + "currentAutopilotStatus = " + currentAutopilotStatus); + switch (state) { + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE: + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { + if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->1语音提示 +// AIAssist.getInstance( getContext() ).speakTTSVoice( "已进入人工驾驶模式" ); + } + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE; + // 设置UI【自动驾驶】按钮是否展示 + runOnUIThread(() -> mView.onAutopilotEnableChange(true)); + if (SweeperOrderModel.getInstance().isGoingToNextStation()) { + runOnUIThread(() -> mView.hideSlidePanel()); + } + if (FunctionBuildConfig.isDemoMode + && ( + (mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1) + || ( + (mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1) + && SweeperOrderModel.getInstance().isGoingToNextStation() + ) + ) + ) { + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); + return; + } + // 改变UI自动驾驶状态 + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); + } + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING: + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING; + // 改变UI自动驾驶状态 + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); + SweeperOrderModel.getInstance().triggerStartServiceEvent( + isRestartAutopilot, true); + } + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE: + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { + if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->0语音提示 +// AIAssist.getInstance( getContext() ).speakTTSVoice( "自动驾驶已停止,请人工接管" ); + } + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; + if (FunctionBuildConfig.isDemoMode + && ( + (mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1) + || ( + (mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1) + && SweeperOrderModel.getInstance().isGoingToNextStation() + ) + ) + ) { + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); + return; + } + runOnUIThread(() -> { + mView.onAutopilotStatusChanged(currentAutopilotStatus); + }); + } + break; + default: + runOnUIThread(() -> mView.onAutopilotEnableChange(false)); + break; + } + } + + @Override + public void onVRModeChanged(boolean isVRMode) { + runOnUIThread(() -> mView.onVRModeChanged(isVRMode)); + } + + @Override + public void onCarLocationChanged(Location location) { + if (null != location) { + runOnUIThread(() -> mView.updateSpeedView(location.getSpeed())); + } + } + + @Override + public void startOpenAutopilot() { + //非美化模式下启动动画 + runOnUIThread(() -> mView.startAutopilotAnimation()); + } + + private void runOnUIThread(Runnable executor) { + if (executor == null) { + return; + } + if (Looper.myLooper() != Looper.getMainLooper()) { + UiThreadHandler.post(executor); + } else { + executor.run(); + } + } + + /** + * 测试使用 + * + * @param status + */ + public void debugAutoPilotStatus(int status) { + AutopilotStatusInfo info = new AutopilotStatusInfo(); + info.setState(status); + onAutopilotStatusResponse(info); + } + + @Override + public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo) { + SweeperTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo); + } + + @Override + public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) { + } + + @Override + public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { + + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/receiver/TestSweeperBroadcastReceiver.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/receiver/TestSweeperBroadcastReceiver.java new file mode 100644 index 0000000000..b2ef6bcadd --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/receiver/TestSweeperBroadcastReceiver.java @@ -0,0 +1,42 @@ +package com.mogo.och.sweeper.receiver; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.sweeper.constant.SweeperConst; + +/** + * 测试小巴车的场景 + * + * @author donghongyu + * @date 4/26/21 12:08 PM + */ +public class TestSweeperBroadcastReceiver extends BroadcastReceiver { + private static final String TAG = "TestBusBroadcastReceiver"; + + private Context mContext; + + @Override + public void onReceive(Context context, Intent intent) { + try { + this.mContext = context; + int sceneType = intent.getIntExtra(SweeperConst.BROADCAST_TEST_SWEEPER_CONTROL_TYPE_EXTRA_KEY, 0); + CallerLogger.INSTANCE.d(M_BUS + TAG, "sceneType:" + sceneType); + + // 分发场景 + dispatchSceneTest(sceneType); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void dispatchSceneTest(int sceneType) { + + } + + +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperOperatePanelView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperOperatePanelView.java new file mode 100644 index 0000000000..c58f59b384 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperOperatePanelView.java @@ -0,0 +1,1063 @@ +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; +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotVehicleStateListenerManager; +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; +import chassis.VehicleStateOuterClass; + +/** + * 清扫车操作面板View + */ +public class SweeperOperatePanelView extends LinearLayout { + + private static final String TAG = "SweeperOperatePanelView"; + private static final int CMD_EXECUTE_TIMEOUT_SECONDS = 30; + private static final int CMD_EXECUTE_MOCK_SUCCESS_SECONDS = 3; + + 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 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 cleanModeBtnAndCmdValueMap = new HashMap() { + { + 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 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 cleanDirectionBtnAndCmdValueMap = new HashMap() { + { + 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 cleanIntensityBtnViewIds = Arrays.asList( + R.id.btn_clean_intensity_standard, + R.id.btn_clean_intensity_strong); + + // 作业强度相关按钮操作,对应命令参数值 + HashMap cleanIntensityBtnAndCmdValueMap = new HashMap() { + { + 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); + } + + public SweeperOperatePanelView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public SweeperOperatePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + public SweeperOperatePanelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initView(context); + } + + private void initView(Context context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_operate_panel_view, this, true); + 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); + initViewListener(); + } + + private void initViewListener() { + 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) { + boolean success = false; + if (cleanSystemState == null) { + return success; + } + if (isCloseAction) { + success = !cleanSystemState.getSecuMotWorkSts(); + } else { + success = cleanSystemState.getSecuMotWorkSts(); + } + return success; + } + + @Override + public void onCmdSuccess() { + runOnUIThread(() -> { + 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() { + //按钮样式恢复原样 + runOnUIThread(() -> { + 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(); + //是否纯吸View + boolean isPureAbsorptionClick = currentClickView.getId() == R.id.btn_clean_mode_pure_absorption; + //是否纯洗View + boolean isPureWashClick = currentClickView.getId() == R.id.btn_clean_mode_pure_wash; + //是否纯扫View + boolean isPureSweepClick = currentClickView.getId() == R.id.btn_clean_mode_pure_sweep; + //是否洗扫View + boolean isWashSweepClick = currentClickView.getId() == R.id.btn_clean_mode_sweep_wash; + + 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) { + boolean success = false; + if (cleanSystemState == null) { + return success; + } + // 洗扫 + boolean clean_mode_wash_sweep = cleanSystemState.getSecuModWashSweepSts(); + // 纯洗 + boolean clean_mode_pure_wash = cleanSystemState.getSecuModWashSts(); + // 纯吸 + boolean clean_mode_pure_draw = cleanSystemState.getSecuWorkTonSts(); + // 纯扫 模式判断:不是另外其他3个模式,同时有清扫方向,说明开启了纯扫模式 + boolean clean_mode_pure_sweep = checkIfCleanModePureSweep(cleanSystemState); + // 关闭作业模式(实际执行了3个操作: 关闭作业模式 关闭清扫方向 切换标准强度,实际以关闭作业模式成功为准) + boolean clean_mode_close = !clean_mode_wash_sweep + && !clean_mode_pure_wash + && !clean_mode_pure_draw + && !clean_mode_pure_sweep; + + if (isClickCurrentChoosedModeBtn && clean_mode_close) {// 关闭放第一判断 + success = clean_mode_close; + } else if (isPureSweepClick) { + //success = clean_mode_pure_sweep; + //纯扫 这个模式实际在福田清扫车上没有这个按钮,只是发送指令给特种车端,默认此命令肯定是正确的 + success = true; + } else if (isPureWashClick) { + success = clean_mode_pure_wash; + } else if (isWashSweepClick) { + success = clean_mode_wash_sweep; + } else if (isPureAbsorptionClick) { + success = clean_mode_pure_draw; + } + return success; + } + + @Override + public void onCmdSuccess() { + runOnUIThread(() -> { + ((CheckedTextView) currentClickView).setChecked(!isClickCurrentChoosedModeBtn); + toggleCleanModeBtnsByChoosedViewId(currentClickView.getId(), isClickCurrentChoosedModeBtn); + if (isClickCurrentChoosedModeBtn) { + toggleCleanDirectionBtnsStatus(false); + toggleCleanIntensityBtnsStatus(false); + } else { + // 如果是纯吸,没有设置清扫方向,同时自动设置作业强度为标准 + if (isPureAbsorptionClick) { + toggleCleanDirectionBtnsStatus(false); + setCleanIntensityStandard(); + } else { + toggleCleanDirectionBtnsStatus(true); + toggleCleanIntensityBtnsStatus(false); + } + } + hideLoadingMask(); + showCmdExecuteSuccessToast(); + }); + } + + @Override + public void onCmdFailed() { + } + + @Override + public void onCmdTimeout() { + runOnUIThread(() -> { + ((CheckedTextView) currentClickView).setChecked(isClickCurrentChoosedModeBtn); + hideLoadingMask(); + showCmdExecuteTimeoutToast(); + }); + } + }; + + if (isClickCurrentChoosedModeBtn) { + //当前已选择模式的按钮,取消当前模式,并关闭清扫方向 + sendSweeperCmd( + SweeperFutianCmdUtil.buildCleanModeCloseCmd(), + cmdRequestCallback, + CMD_EXECUTE_TIMEOUT_SECONDS); + } else { + //开启新的作业模式,直接发送命令(纯吸需要一并设置作业强度为标准) + int cmdValue = cleanModeBtnAndCmdValueMap.get(currentClickView.getId()); + sendSweeperCmd( + isPureAbsorptionClick ? 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(); + + boolean isLeftSide = currentClickView.getId() == R.id.btn_clean_direction_left_side; + boolean isRightSide = currentClickView.getId() == R.id.btn_clean_direction_right_side; + boolean isBothSide = currentClickView.getId() == R.id.btn_clean_direction_both_side; + + + 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) { + boolean success = false; + if (cleanSystemState == null) { + return success; + } + // 左侧 + boolean clean_direction_left_side = cleanSystemState.getSecuWorkLeftSts(); + // 右侧 + boolean clean_direction_right_side = cleanSystemState.getSecuWorkRightSts(); + // 两侧 + boolean clean_direction_both_side = cleanSystemState.getSecuWorkOnBothsidesSts(); + // 关闭清扫方向(实际执行了2个操作:关闭清扫方向 切换标准强度,实际以关闭清扫方向成功为准) + boolean clean_direction_close = !clean_direction_left_side && !clean_direction_right_side + && !clean_direction_both_side; + + if (isClickCurrentChoosedDirectionBtn && clean_direction_close) {//关闭放第一判断 + success = clean_direction_close; + } else if (isLeftSide) { + success = clean_direction_left_side; + } else if (isRightSide) { + success = clean_direction_right_side; + } else if (isBothSide) { + success = clean_direction_both_side; + } + return success; + } + + @Override + public void onCmdSuccess() { + runOnUIThread(() -> { + ((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() { + runOnUIThread(() -> { + ((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; + boolean isStrongBtnClick = currentClickView.getId() == R.id.btn_clean_intensity_strong; + 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) { + boolean success = false; + if (cleanSystemState == null) { + return success; + } + boolean clean_intensity_standard = cleanSystemState.getSecuWorkStandSts(); + boolean clean_intensity_strong = cleanSystemState.getSecuWorkStrongSts(); + if (isStandardBtnClick) { + success = clean_intensity_standard; + } else if (isStrongBtnClick) { + success = clean_intensity_strong; + } + return success; + } + + @Override + public void onCmdSuccess() { + runOnUIThread(() -> { + ((CheckedTextView) currentClickView).setChecked(true); + if (isStandardBtnClick) { + setCleanIntensityStandard(); + } else { + setCleanIntensityStrong(); + } + hideLoadingMask(); + showCmdExecuteSuccessToast(); + }); + } + + @Override + public void onCmdFailed() { + } + + @Override + public void onCmdTimeout() { + runOnUIThread(() -> { + ((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 + )); + mLoadingHintBottom.setVisibility(timeout < 0 ? View.INVISIBLE : View.VISIBLE); + }); + } + + /** + * 隐藏loading + */ + private void hideLoadingMask() { + runOnUIThread(() -> { + mSweeperOperateCmdHandler.removeMessages(MSG_CMD_EXECUTE_COUNT_DOWN); + 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("超时未响应,操作失败"); + } + + /** + * 根据底盘数据恢复操作面板中相关按钮状态 成功toast + */ + private void showRecoverPanelButtonStateSuccessToast() { + 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) { + listener.onClick(v); + } + }); + } + + // 当前时间戳 + private long mCurrentTimeMillis; + // 底盘数据回调时间间隔 + private static final long VEHICLE_STATE_INTERVAL_MILLIS = 500L; + + /** + * 底盘数据透传listener + */ + private final IMoGoAutopilotVehicleStateListener mIMoGoAutopilotVehicleStateListener = new IMoGoAutopilotVehicleStateListener() { + @Override + public void onAutopilotDataException(long timestamp) { + } + + @Override + public void onAutopilotLightSwitchData(@Nullable Chassis.LightSwitch lightSwitch) { + } + + @Override + public void onAutopilotBrakeLightData(boolean brakeLight) { + } + + @Override + public void onAutopilotSteeringData(float steering) { + } + + @Override + public void onAutopilotGearData(@NonNull Chassis.GearPosition gear) { + } + + @Override + public void onAutopilotAcc(float carAcc) { + } + + @Override + public void onAutopilotThrottle(float throttle) { + } + + @Override + public void onAutopilotBrake(float brake) { + } + + @Override + public void onSweeperFutianCleanSystemState(@NonNull VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) { + long current = System.currentTimeMillis(); + if (current - mCurrentTimeMillis <= VEHICLE_STATE_INTERVAL_MILLIS) { + return; + } + mCurrentTimeMillis = current; + + Log.d(TAG, "onSweeperFutianCleanSystemState"); + // 第一次进入时同步底盘状态,只拿第一次的数据 + if (mSyncingVehicleState) { + onSyncVehicleStateCallBack(cleanSystemState); + return; + } + // 有命令正在执行 + if (mCurrentCmdRequestCallback != null) { + Log.d(TAG, "getSecuWorkLeftSts = " + cleanSystemState.getSecuWorkLeftSts()); + if (mCurrentCmdRequestCallback.onCheckIfCmdSuccess(cleanSystemState)) { + mCurrentCmdRequestCallback.onCmdSuccess(); + mCurrentCmdRequestCallback = null; + } + } + } + }; + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + CallerAutopilotVehicleStateListenerManager.INSTANCE.addListener(TAG, mIMoGoAutopilotVehicleStateListener); + // 最终调试时需要打开 + syncVehicleStateAndRecoverOperatePanelStates(); + // Mock VehicleState 数据回调 + // UiThreadHandler.postDelayed(() -> { + // onSyncVehicleStateCallBack(SweeperFutianCmdUtil.buildSweeperFuTionCleanSystemStateMockData()); + // }, 3000L); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + CallerAutopilotVehicleStateListenerManager.INSTANCE.removeListener(TAG); + } + + /** + * 等待同步底盘数据,并根据底盘数据恢复操作面板中按钮的状态 + */ + private synchronized void syncVehicleStateAndRecoverOperatePanelStates() { + // show sync loading + showLoadingMask("状态同步中,请稍后", -1); + mSyncingVehicleState = true; + } + + private synchronized void onSyncVehicleStateCallBack(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) { + if (cleanSystemState == null) return; + mSyncingVehicleState = false; + // 清扫作业开启状态(以电机状态为true代表Open成功,实际控制端控制步骤为:1.发送远程控制上装指令 2.发送电机启动指令) + boolean clean_open_requirement = cleanSystemState.getSecuMotWorkSts(); + // 作业模式状态 + // 洗扫 + boolean clean_mode_wash_sweep = cleanSystemState.getSecuModWashSweepSts(); + // 纯洗 + boolean clean_mode_pure_wash = cleanSystemState.getSecuModWashSts(); + // 纯吸 + boolean clean_mode_pure_draw = cleanSystemState.getSecuWorkTonSts(); + + // 清扫方向状态 + // 左侧 + boolean clean_direction_left_side = cleanSystemState.getSecuWorkLeftSts(); + // 右侧 + boolean clean_direction_right_side = cleanSystemState.getSecuWorkRightSts(); + // 两侧 + boolean clean_direction_both_side = cleanSystemState.getSecuWorkOnBothsidesSts(); + + // 纯扫 模式判断:不是另外其他3个模式,同时有清扫方向,说明开启了纯扫模式 + boolean clean_mode_pure_sweep = checkIfCleanModePureSweep(cleanSystemState); + + // 作业强度状态 + boolean clean_intensity_standard = cleanSystemState.getSecuWorkStandSts(); + boolean clean_intensity_strong = cleanSystemState.getSecuWorkStrongSts(); + + runOnUIThread(() -> { + if (clean_open_requirement) { + // 打开状态 + mBtnCleanWorkOpenClose.setText("Close"); + mBtnCleanWorkOpenClose.setChecked(true); + } else { + // 关闭状态 + mBtnCleanWorkOpenClose.setText("Open"); + mBtnCleanWorkOpenClose.setChecked(false); + } + if (clean_mode_pure_sweep) { + //纯扫 + mBtnCleanModePureSweep.setChecked(true); + mBtnCleanModePureSweep.setEnabled(true); + toggleCleanModeBtnsByChoosedViewId(R.id.btn_clean_mode_pure_sweep, false); + } else if (clean_mode_pure_wash) { + //纯洗 + mBtnCleanModePureWash.setChecked(true); + mBtnCleanModePureWash.setEnabled(true); + toggleCleanModeBtnsByChoosedViewId(R.id.btn_clean_mode_pure_wash, false); + } else if (clean_mode_wash_sweep) { + //洗扫 + mBtnCleanModeSweepWash.setChecked(true); + mBtnCleanModeSweepWash.setEnabled(true); + toggleCleanModeBtnsByChoosedViewId(R.id.btn_clean_mode_sweep_wash, false); + } else if (clean_mode_pure_draw) { + //纯吸,需要disable作业方向 + mBtnCleanModePureAbsorption.setChecked(true); + mBtnCleanModePureAbsorption.setEnabled(true); + toggleCleanModeBtnsByChoosedViewId(R.id.btn_clean_mode_pure_absorption, false); + toggleCleanDirectionBtnsStatus(false); + } + + if (!clean_mode_pure_draw) {// 非纯吸模式才有清扫方向 + if (clean_direction_left_side) { + mBtnCleanDirectionLeftSide.setChecked(true); + mBtnCleanDirectionLeftSide.setEnabled(true); + toggleCleanDirectionBtnsByChoosedViewId(R.id.btn_clean_direction_left_side, false); + } else if (clean_direction_right_side) { + mBtnCleanDirectionRightSide.setChecked(true); + mBtnCleanDirectionRightSide.setEnabled(true); + toggleCleanDirectionBtnsByChoosedViewId(R.id.btn_clean_direction_right_side, false); + } else if (clean_direction_both_side) { + mBtnCleanDirectionBothSide.setChecked(true); + mBtnCleanDirectionBothSide.setEnabled(true); + toggleCleanDirectionBtnsByChoosedViewId(R.id.btn_clean_direction_both_side, false); + } + } + if (clean_intensity_standard) { + setCleanIntensityStandard(); + } else if (clean_intensity_strong) { + setCleanIntensityStrong(); + } + hideLoadingMask(); + showRecoverPanelButtonStateSuccessToast(); + }); + } + + /** + * 通过底盘数据判断是纯扫模式 + * + * @param cleanSystemState + * @return + */ + private boolean checkIfCleanModePureSweep(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState) { + // 作业模式状态 + // 洗扫 + boolean clean_mode_wash_sweep = cleanSystemState.getSecuModWashSweepSts(); + // 纯洗 + boolean clean_mode_pure_wash = cleanSystemState.getSecuModWashSts(); + // 纯吸 + boolean clean_mode_pure_draw = cleanSystemState.getSecuWorkTonSts(); + + // 清扫方向状态 + // 左侧 + boolean clean_direction_left_side = cleanSystemState.getSecuWorkLeftSts(); + // 右侧 + boolean clean_direction_right_side = cleanSystemState.getSecuWorkRightSts(); + // 两侧 + boolean clean_direction_both_side = cleanSystemState.getSecuWorkOnBothsidesSts(); + + // 纯扫 模式判断:不是另外其他3个模式,同时有清扫方向,说明开启了纯扫模式 + boolean clean_mode_pure_sweep = (clean_direction_left_side || clean_direction_right_side || clean_direction_both_side) + && (!clean_mode_wash_sweep && !clean_mode_pure_wash && !clean_mode_pure_draw); + return clean_mode_pure_sweep; + } + + /** + * 发送清扫车相关作业命令 + * + * @param fuTianCleanCmd + * @param cmdRequestCallback + * @param timeout + */ + private void sendSweeperCmd( + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd fuTianCleanCmd, + CmdRequestCallback cmdRequestCallback, + int timeout) { + // 设置当前请求的回调 + mCurrentCmdRequestCallback = cmdRequestCallback; + // onSendCmd + 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 +// mockSendCmdSuccess(); + } + + private void mockSendCmdSuccess() { + 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 boolean mSyncingVehicleState;//第一次进入页面时,同步底盘状态的标志位 + 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 + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + if (msg.what == MSG_CMD_EXECUTE_COUNT_DOWN) { + int seconds = (int) msg.obj; + if (seconds > 0) { + if (mCurrentCmdRequestCallback != null) { + mCurrentCmdRequestCallback.onCountDownTick(seconds); + } + Message newMsg = Message.obtain(); + newMsg.what = MSG_CMD_EXECUTE_COUNT_DOWN; + 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); + } + } + } + + interface CmdRequestCallback { + void onSendCmd(); + + void onCountDownTick(int senonds); + + boolean onCheckIfCmdSuccess(VehicleStateOuterClass.SweeperFuTianCleanSystemState cleanSystemState); + + void onCmdSuccess(); + + void onCmdFailed(); + + void onCmdTimeout(); + } + +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineActivity.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineActivity.java new file mode 100644 index 0000000000..dedd34cb21 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineActivity.java @@ -0,0 +1,300 @@ +package com.mogo.och.sweeper.ui; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Point; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.mogo.commons.mvp.MvpActivity; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.sweeper.R; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; +import com.mogo.och.sweeper.presenter.SweeperLinePresenter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/2/8 + */ +public class SweeperSwitchLineActivity extends MvpActivity + implements View.OnClickListener, SweeperSwitchLineView { + + private ImageView mClose; + private ConstraintLayout mNoDatasView; + private RecyclerView mLinesListView; + private TextView mLineCommitBtn; + private SwitchLineAdapter mAdapter; + private List mData = new ArrayList<>(); + private int mSelectLineId = -1; + + @Override + protected int getLayoutId() { + return R.layout.activity_sweeper_switch_line; + } + + @NonNull + @Override + protected SweeperLinePresenter createPresenter() { + return new SweeperLinePresenter(this); + } + + @Override + protected void initViews() { + initWH(); + initView(); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initDatas(); + } + + /** + * 初始化view + */ + private void initView() { + mClose = findViewById(R.id.switch_line_close); + mClose.setOnClickListener(this); + mNoDatasView = findViewById(R.id.no_order_data_view); + + mLineCommitBtn = findViewById(R.id.switch_line_btn_commit); + mLineCommitBtn.setOnClickListener(this); + + mLinesListView = findViewById(R.id.switch_line_rv); + mLinesListView.setLayoutManager(new LinearLayoutManager(this)); + mAdapter = new SwitchLineAdapter(getApplicationContext(),mData); + mLinesListView.setAdapter(mAdapter); + //设置item 点击事件 + mAdapter.setOnLineItemClickListener(new LineItemClickListener() { + @Override + public void onItemClick(int position) { + if (mData.size() > position && !TextUtils.isEmpty(mData.get(position).startSiteName ) + && !TextUtils.isEmpty(mData.get(position).endSiteName)){ + mSelectLineId = mData.get(position).lineId; + }else { + mSelectLineId = -1; + } + } + }); + } + + /** + * 设置布局宽高 + */ + private void initWH() { + + Window window = getWindow(); + + WindowManager.LayoutParams params = window.getAttributes(); + WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE); + Point point = new Point(); + windowManager.getDefaultDisplay().getSize(point);//用于获取屏幕高度 + + params.width = (int)(point.x * 0.375); + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + window.setAttributes(params); + window.setGravity(Gravity.LEFT|Gravity.BOTTOM); + } + + /** + * 初始化数据 + */ + private void initDatas() { + mPresenter.queryBusLines(); + } + + /** + * 查询返回绑定路线集合 + * @param data + */ + @Override + public void onBusLinesChange(SweeperQueryLinesResponse data){ + if (null == data){ + showNoData(true); + return; + } + if (data.data != null && data.data.size() > 0){ + showNoData(false); + mData.clear(); + mData.addAll(data.data); + mAdapter.notifyDataSetChanged(); + changeCommitBtnBg(); + }else { + showNoData(true); + } + } + + /** + * 根据路线选中情况设置提交按钮样式 + */ + private void changeCommitBtnBg() { + for (int i=0; i -1){ + mPresenter.commitSwitchLineId(mSelectLineId); + }else { + finish(); + } + return; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + /** + * 路线列表adapter + */ + static class SwitchLineAdapter extends RecyclerView.Adapter{ + + private Context mContext; + private List mData; + // RecyclerView设置点击事件 + private LineItemClickListener mItemClickListener ; + private int clickPos = -1; + + public SwitchLineAdapter(Context context, List data){ + mContext = context; + mData = data; + } + + @NonNull + @Override + public SwitchLineViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.sweeper_switch_line_list_item + ,parent,false); + SwitchLineViewHolder viewHolder = new SwitchLineViewHolder(view); + return viewHolder; + } + + @Override + public void onBindViewHolder(@NonNull SwitchLineViewHolder holder, @SuppressLint("RecyclerView") int position) { + SweeperQueryLinesResponse.Result line = mData.get(position); + holder.lineName.setText(mContext.getString(R.string.sweeper_switch_line_name)+" "+line.name); + holder.lineStartName.setText(mContext.getString(R.string.sweeper_line_start)+" "+line.startSiteName); + holder.lineEndName.setText(mContext.getString(R.string.sweeper_line_end)+" "+line.endSiteName); + + //设置item点击事件 + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mItemClickListener != null){ + mItemClickListener.onItemClick(position); + clickPos = position; + notifyDataSetChanged(); + } + } + }); + //选中绑定 + if (clickPos > -1){ + if (clickPos == position){ + holder.selectIv.setImageResource(R.drawable.sweeper_selected_btn); + }else { + holder.selectIv.setImageResource(R.drawable.sweeper_unselect_btn); + } + }else { + if (line.choose == 1){//1:绑定 2:未绑定 默认绑定 + if (mItemClickListener != null) { + mItemClickListener.onItemClick(position); + } + holder.selectIv.setImageResource(R.drawable.sweeper_selected_btn); + }else { + holder.selectIv.setImageResource(R.drawable.sweeper_unselect_btn); + } + } + + } + + @Override + public int getItemCount() { + return mData.size(); + } + public void setOnLineItemClickListener(LineItemClickListener itemClickListener){ + this.mItemClickListener = itemClickListener ; + + } + } + + static class SwitchLineViewHolder extends RecyclerView.ViewHolder{ + + private ImageView selectIv; + private TextView lineName; //线路名称 + private TextView lineStartName; //起点 + private TextView lineEndName; //终点 + + public SwitchLineViewHolder(@NonNull View itemView) { + super(itemView); + selectIv = itemView.findViewById(R.id.switch_line_item_select_iv); + lineName = itemView.findViewById(R.id.switch_line_name); + lineStartName = itemView.findViewById(R.id.switch_line_start_station); + lineEndName = itemView.findViewById(R.id.switch_line_end_station); + } + } + + public interface LineItemClickListener { + void onItemClick(int position) ; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineView.java new file mode 100644 index 0000000000..3cfdb9fdb9 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperSwitchLineView.java @@ -0,0 +1,15 @@ +package com.mogo.och.sweeper.ui; + +import com.mogo.commons.mvp.IView; +import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse; + +/** + * @author: wangmingjun + * @date: 2022/2/10 + */ +public interface SweeperSwitchLineView extends IView { + + void onBusLinesChange(SweeperQueryLinesResponse data); + void onChangeLineIdSuccess(); +} + diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperTrafficLightView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperTrafficLightView.java new file mode 100644 index 0000000000..5f99d4836e --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/ui/SweeperTrafficLightView.java @@ -0,0 +1,167 @@ +package com.mogo.och.sweeper.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.ImageView; + +import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.sweeper.R; +import com.mogo.och.common.module.wigets.OCHGradientTextView; + +import org.jetbrains.annotations.Nullable; + +/** + * Bus司机端:红绿灯view + * + * Created on 2022/3/29 + */ +public class SweeperTrafficLightView extends IViewTrafficLight { + + private ImageView mLightIconIV; + private OCHGradientTextView mLightTimeTV; + private int mCurrentLightId; + + public SweeperTrafficLightView(@Nullable Context context) { + this(context, null, 0); + } + + public SweeperTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SweeperTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_traffic_light_view, this, true); + mLightIconIV = findViewById(R.id.sweeper_traffic_light_iv); + mLightTimeTV = findViewById(R.id.sweeper_traffic_light_time_tv); + } + + /** + * 展示红绿灯预警 + * + * @param checkLightId 0-都是默认,1-红,2-黄,3-绿 + * @param lightSource 1:云端下发;2:自车感知 + */ + @Override + public void showWarningTrafficLight(int checkLightId,int lightSource) { + super.showWarningTrafficLight(checkLightId,lightSource); + mCurrentLightId = checkLightId; + updateTrafficLightIcon(checkLightId); + } + + /** + * 关闭红绿灯预警展示,并重制灯态 + */ + @Override + public void disableWarningTrafficLight() { + super.disableWarningTrafficLight(); + UiThreadHandler.post(() -> { + mCurrentLightId = 0; + SweeperTrafficLightView.this.setVisibility(GONE); + }); + } + + /** + * @param redNum 红灯倒计时 + * @param yellowNum 黄灯倒计时 + * @param greenNum 绿灯倒计时 + */ + @Override + public void changeCountdownTrafficLightNum(int redNum, int yellowNum, int greenNum) { + super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum); + switch (mCurrentLightId) { + case 1: + changeCountdownRed(redNum); + break; + case 2: + changeCountdownYellow(yellowNum); + break; + case 3: + changeCountdownGreen(greenNum); + break; + default: + UiThreadHandler.post(() -> { + mLightTimeTV.setText(""); + }); + break; + } + } + + @Override + public void changeCountdownRed(int redNum) { + super.changeCountdownRed(redNum); + UiThreadHandler.post(() -> { + if (redNum > 0) { + mLightTimeTV.setVertrial(true); + mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_red_color_up), + getResources().getColor(R.color.sweeper_traffic_light_red_color_down)}); + mLightTimeTV.setText(String.valueOf(redNum)); + } else { + mLightTimeTV.setText(""); + } + }); + } + + @Override + public void changeCountdownGreen(int greenNum) { + super.changeCountdownGreen(greenNum); + UiThreadHandler.post(() -> { + if (greenNum > 0) { + mLightTimeTV.setVertrial(true); + mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_green_color_up), + getResources().getColor(R.color.sweeper_traffic_light_green_color_down)}); + mLightTimeTV.setText(String.valueOf(greenNum)); + } else { + mLightTimeTV.setText(""); + } + }); + } + + @Override + public void changeCountdownYellow(int yellowNum) { + super.changeCountdownYellow(yellowNum); + UiThreadHandler.post(() -> { + if (yellowNum > 0) { + mLightTimeTV.setVertrial(true); + mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_yellow_color_up), + getResources().getColor(R.color.sweeper_traffic_light_yellow_color_down)}); + mLightTimeTV.setText(String.valueOf(yellowNum)); + } else { + mLightTimeTV.setText(""); + } + }); + } + + /** + * 更新红绿灯icon + * + * @param lightId 0-都是默认,1-红,2-黄,3-绿 + */ + private void updateTrafficLightIcon(int lightId) { + UiThreadHandler.post(() -> { + switch (lightId) { + case 1: + mLightIconIV.setBackgroundResource(R.drawable.sweeper_light_red_nor); + SweeperTrafficLightView.this.setVisibility(VISIBLE); + break; + case 2: + mLightIconIV.setBackgroundResource(R.drawable.sweeper_lightyellow_nor); + SweeperTrafficLightView.this.setVisibility(VISIBLE); + break; + case 3: + mLightIconIV.setBackgroundResource(R.drawable.sweeper_light_green_nor); + SweeperTrafficLightView.this.setVisibility(VISIBLE); + break; + default: + SweeperTrafficLightView.this.setVisibility(GONE); + break; + } + }); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/BDRouteDataTestUtils.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/BDRouteDataTestUtils.java new file mode 100644 index 0000000000..85634178f1 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/BDRouteDataTestUtils.java @@ -0,0 +1,45 @@ +package com.mogo.och.sweeper.util; + +import com.mogo.och.sweeper.model.SweeperOrderModel; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; + +/** + * @author: wangmingjun + * @date: 2022/4/13 + */ +public class BDRouteDataTestUtils { + + static String jsonStr ="{\n" + + " \"models\": [\n" + + " {\n" + + " \"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927760268911,\"lon\":116.73512607061035,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927736555187,\"lon\":116.73498243020299,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927135941599,\"lon\":116.73482951462647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199260672670036,\"lon\":116.73468429259535,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199251260349946,\"lon\":116.73453933465,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924691997577,\"lon\":116.7343756435551,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199247953493625,\"lon\":116.73421240809087,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924986849947,\"lon\":116.73400425509712,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199249431152175,\"lon\":116.73378579041055,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199248921305724,\"lon\":116.73357811807278,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925012387371,\"lon\":116.73337650020184,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252270195075,\"lon\":116.73318223781153,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992521615169,\"lon\":116.73298632625203,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925202633083,\"lon\":116.73279582043983,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199261230205735,\"lon\":116.73263403473568,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199327991681926,\"lon\":116.73251962434813,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19944850496711,\"lon\":116.73249661840195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199582026896415,\"lon\":116.73251038561487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199743326352014,\"lon\":116.73253087453938,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199908347167394,\"lon\":116.73255070500186,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200065950595445,\"lon\":116.7325720694418,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20022747460407,\"lon\":116.73259461416663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384057310536,\"lon\":116.73261575018056,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20053849777916,\"lon\":116.73263451936387,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200696919444624,\"lon\":116.7326540541723,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2008524952796,\"lon\":116.7326743511824,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20101429705625,\"lon\":116.73269393580199,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118279997041,\"lon\":116.73271564378308,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201342388452076,\"lon\":116.73273653366076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201476063822355,\"lon\":116.73275292393079,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163479199852,\"lon\":116.73277440686762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181243476041,\"lon\":116.7328052766508,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201991767093304,\"lon\":116.7328453845644,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20215573733484,\"lon\":116.73287624009339,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202313648759784,\"lon\":116.73289887933315,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434745374454,\"lon\":116.7329182210956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253164952098,\"lon\":116.73297539811277,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258043275509,\"lon\":116.73312335324984,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258233576585,\"lon\":116.73331077089557,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20257107560234,\"lon\":116.73351244039137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202561578580514,\"lon\":116.73370176209845,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20256256788661,\"lon\":116.73391325024126,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20255633158834,\"lon\":116.73413195000244,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202543311179575,\"lon\":116.73436614303907,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253067346457,\"lon\":116.73458032609663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20251776111356,\"lon\":116.73477082198242,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202503997557805,\"lon\":116.73498624001282,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20249129260376,\"lon\":116.73518976336872,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247877796589,\"lon\":116.73537786253135,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246651610268,\"lon\":116.73559239130266,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245754388014,\"lon\":116.73574239922202,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20244749208,\"lon\":116.73589674090469,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243806550113,\"lon\":116.73607057284322,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243550556816,\"lon\":116.73628106525871,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243654127756,\"lon\":116.7364949950665,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243738221016,\"lon\":116.7367061649993,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243672476754,\"lon\":116.73691115930336,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243590788176,\"lon\":116.73710722104272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202436434375336,\"lon\":116.73730688607075,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243749821501,\"lon\":116.73750140347998,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243625962803,\"lon\":116.73771330926793,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434515480725,\"lon\":116.73791895606205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024326561388,\"lon\":116.73815206945737,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243092086137,\"lon\":116.73838655528765,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202430876006126,\"lon\":116.73861890759498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242914053177,\"lon\":116.73882029918758,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242843336561,\"lon\":116.73904465495175,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242661219026,\"lon\":116.73922453252953,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426462811076,\"lon\":116.7393708046956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242687134937,\"lon\":116.73954685547025,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242694967377,\"lon\":116.73975021183773,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202424630601236,\"lon\":116.73999740812975,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202422502184625,\"lon\":116.74028266774337,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202419634158936,\"lon\":116.7405942561498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241975959762,\"lon\":116.7409069557092,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241920524113,\"lon\":116.74120156191647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241765540262,\"lon\":116.74149288504978,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241569149764,\"lon\":116.7418080096762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202414529497084,\"lon\":116.74210262897205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241419532155,\"lon\":116.74241767661879,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202413879360954,\"lon\":116.7427571218185,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241287045245,\"lon\":116.7431284691325,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241214965105,\"lon\":116.74343354359334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241141271715,\"lon\":116.7437220210538,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024080520075,\"lon\":116.74399113498052,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202391714280026,\"lon\":116.74427625698272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20238163805639,\"lon\":116.74452083315958,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379293010274,\"lon\":116.74475703837204,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379007817086,\"lon\":116.7449961645494,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20237814181231,\"lon\":116.7452036063558,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202375477619896,\"lon\":116.74539567654291,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2023632396621,\"lon\":116.74555457589031,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20229396554444,\"lon\":116.7456716047369,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20217800547467,\"lon\":116.74574081942625,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202047498095304,\"lon\":116.74573659255675,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20188573786706,\"lon\":116.74571018281719,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201738240263026,\"lon\":116.74568463148606,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20157507049073,\"lon\":116.74565525041498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20137985142042,\"lon\":116.745619970576,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201187335613575,\"lon\":116.74558631350607,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20098251429043,\"lon\":116.74555055587679,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2007748533628,\"lon\":116.74551426934663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20057082986032,\"lon\":116.74547749663195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20036944224329,\"lon\":116.74544156175533,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016365229035,\"lon\":116.74540577510051,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1999958572445,\"lon\":116.74537505807076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19984100521566,\"lon\":116.7453433678602,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1996863960282,\"lon\":116.74529675648621,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19953919567943,\"lon\":116.74525916493474,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19940587189373,\"lon\":116.74523402869453,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19929047792381,\"lon\":116.74518617038383,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922141745155,\"lon\":116.74506912884067,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920798885308,\"lon\":116.744896716334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920912644279,\"lon\":116.74467216715483,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199209186509314,\"lon\":116.74448257515108,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920910709997,\"lon\":116.74430613406223,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992100786082,\"lon\":116.74410888316238,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921081961254,\"lon\":116.74391968819582,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921040855518,\"lon\":116.7437082083402,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921085053439,\"lon\":116.74346931155634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921197237373,\"lon\":116.74325149697013,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921248248983,\"lon\":116.74301103786591,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992139724646,\"lon\":116.74277237066539,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215818352386,\"lon\":116.74253219408898,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216175018876,\"lon\":116.74228853120842,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215970354246,\"lon\":116.74204663206451,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216627492966,\"lon\":116.74183871233049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921789170398,\"lon\":116.74165788334192,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922000138535,\"lon\":116.74144512197054,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199221559127494,\"lon\":116.741249370491,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922287231889,\"lon\":116.7410525810756,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922229019589,\"lon\":116.74085266662037,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992216995901,\"lon\":116.74061957723823,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922263073874,\"lon\":116.74041638149129,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922478093337,\"lon\":116.7402123910757,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199227066091595,\"lon\":116.74003419421553,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199228634241756,\"lon\":116.73985841944678,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922951636012,\"lon\":116.7397079274105,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252095329484,\"lon\":116.73956265582487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199346162997905,\"lon\":116.73944690416265,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199470799628024,\"lon\":116.73941941053417,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19962513314346,\"lon\":116.7394280706812,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199780626058924,\"lon\":116.73944255215424,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199961525343376,\"lon\":116.73945856750177,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016196947193,\"lon\":116.73947572081121,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384479551936,\"lon\":116.7394949225795,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200595083817475,\"lon\":116.73951027963179,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200792203321086,\"lon\":116.73952526850614,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200985930701684,\"lon\":116.73954125209579,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20115978977055,\"lon\":116.73955610094161,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201321019536124,\"lon\":116.7395695239138,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20147117943043,\"lon\":116.7395823299481,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163699848565,\"lon\":116.73959633422596,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20178484338371,\"lon\":116.7396085776486,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201962185646316,\"lon\":116.73962351991214,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021018923927,\"lon\":116.7396354059821,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2022137620686,\"lon\":116.73964348380458,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20232600820075,\"lon\":116.73961190446633,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241090270993,\"lon\":116.73951649703137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245777783807,\"lon\":116.73937664238166,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246906634823,\"lon\":116.73920146119093,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470916682884,\"lon\":116.73898763065634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247034830421,\"lon\":116.73878158418357,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246978204673,\"lon\":116.73857680142473,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247082638905,\"lon\":116.73834517890637,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202471943178196,\"lon\":116.7381047689514,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247131648035,\"lon\":116.73787761484981,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470799473765,\"lon\":116.73766230702478,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247013054322,\"lon\":116.73743619407796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246999515433,\"lon\":116.73724916823292,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247199652478,\"lon\":116.73704888970806,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202473960263525,\"lon\":116.73684083235807,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202474504753205,\"lon\":116.73665462440796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247501354581,\"lon\":116.73650710371837,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246541231906,\"lon\":116.73635807696789,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426768984274,\"lon\":116.73622283382787,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20236638788854,\"lon\":116.73610589402243,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20227106919894,\"lon\":116.73600895001849,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021428343084,\"lon\":116.73596816020945,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20197815580698,\"lon\":116.73594623645097,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181789535303,\"lon\":116.73593148707488,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201667906886954,\"lon\":116.73591743008926,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201505897730755,\"lon\":116.7359002912543,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20135083580946,\"lon\":116.73588579696379,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118617904595,\"lon\":116.73586970398149,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20102374028594,\"lon\":116.73585314703226,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20085554043743,\"lon\":116.73583763953049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20069451888229,\"lon\":116.73582073901778,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200530837344964,\"lon\":116.73580314359012,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2003608457064,\"lon\":116.73578183888779,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20021770046798,\"lon\":116.73575292592922,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20003454701824,\"lon\":116.7357174959358,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19986125116602,\"lon\":116.73569499961796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19969408518737,\"lon\":116.73567725223492,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19955533048882,\"lon\":116.73566375985422,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19943174810538,\"lon\":116.73564927714162,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19933167546824,\"lon\":116.735595995086,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199280357603875,\"lon\":116.73546293260645,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927848361656,\"lon\":116.73531579486274,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19928127892504,\"lon\":116.73505848474375,\"speed\": 0.0\n" + + " }\n" + + " ]\n" + + "}"; + public static void converToRouteData(){ + List list = new ArrayList<>(); + + try { + JSONObject jsonObject = new JSONObject(jsonStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++) { + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(s.getDouble("lat")); + builder.setLongitude(s.getDouble("lon")); + list.add(builder.build()); + } + SweeperOrderModel.getInstance().debugUpdateOrderRoute(list); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java new file mode 100644 index 0000000000..76f43e4388 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java @@ -0,0 +1,81 @@ +package com.mogo.och.sweeper.util; + +import android.text.TextUtils; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; +import com.mogo.commons.debug.DebugConfig; +import com.mogo.eagle.core.data.app.AppConfigInfo; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.call.analytics.AnalyticsManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.utilcode.util.DateTimeUtils; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.sweeper.constant.SweeperConst; + +import java.util.HashMap; + +/** + * OCH sweeper埋点工具 + * + * Created on 2022/3/24 + */ +public class SweeperAnalyticsManager { + + private static final class SingletonHolder { + private static final SweeperAnalyticsManager INSTANCE = new SweeperAnalyticsManager(); + } + + public static SweeperAnalyticsManager getInstance() { + return SweeperAnalyticsManager.SingletonHolder.INSTANCE; + } + + + + private String mStartAutopilotKey; + private HashMap mStartAutopilotParams = new HashMap<>(); + + private Runnable startAutopilotRunnable = () -> { + // 15s内未开启,上报失败埋点 + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_RESULT + , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); + AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); + }; + + /** + * 触发'开启自动驾驶'埋点流程 + * 开启自动驾驶,15s内成功则发送成功埋点,否则发送失败埋点 + * @param restart false(点击'滑动出发'启动)/true(接管后点击'自动驾驶'按钮启动) + * @param send 是否直接发送埋点(15s内开启成功则直接发送成功埋点) + */ + public void triggerStartAutopilotEvent( + boolean restart, boolean send, String startName, String endName, int lineId) { + mStartAutopilotKey = restart ? + SweeperConst.EVENT_KEY_RESTART_AUTOPILOT : SweeperConst.EVENT_KEY_START_SERVICE; + String sn = MoGoAiCloudClientConfig.getInstance().getSn(); + String plateNum = AppConfigInfo.INSTANCE.getPlateNumber(); + String dateTime = DateTimeUtils.getTimeText( + System.currentTimeMillis(), DateTimeUtils.yyyy_MM_dd_HH_mm_ss); + + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_SN, sn); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_ENV_ONLINE, + DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_TIME, dateTime); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_NAME, startName); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_END_NAME, endName); + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_LINE_ID, lineId); + + if (send) { + // 开启成功,上报埋点 + if (startAutopilotRunnable != null && + UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) { + UiThreadHandler.removeCallbacks(startAutopilotRunnable); + } + mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_RESULT, true); + AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); + } else { + UiThreadHandler.postDelayed(startAutopilotRunnable, SweeperConst.LOOP_PERIOD_15S); + } + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperFutianCmdUtil.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperFutianCmdUtil.java new file mode 100644 index 0000000000..969b0dbc34 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperFutianCmdUtil.java @@ -0,0 +1,148 @@ +package com.mogo.och.sweeper.util; + +import chassis.SpecialVehicleTaskCmdOuterClass; +import chassis.VehicleStateOuterClass; + +/** + * 清扫车-福田,构建业务命令数据的工具类 + */ +public class SweeperFutianCmdUtil { + private static final int CLEAN_WORK_OPEN = 1; //清扫作业-开启 + private static final int CLEAN_WORK_CLOSE = 2;//清扫作业-关闭 + 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;//作业模式-关闭 + 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;//清扫方向-关闭 + public static final int CLEAN_INTENSITY_STRAND = 1;//作业强度-标准 + public static final int CLEAN_INTENSITY_STRONG = 2;//作业强度-加强 + + /** + * 清扫作业:打开 + * + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkStartCmd() { + return buildCleanWorkCmd(CLEAN_WORK_OPEN); + } + + /** + * 清扫作业:关闭 + * + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkStopCmd() { + return buildCleanWorkCmd(CLEAN_WORK_CLOSE); + } + + + private static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkCmd(int startOrStop) { + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder(); + builder.setCleanOpenRequirement(startOrStop); + return buildTaskCmd(builder.build()); + } + + /** + * 作业模式:传入具体的模式对应的值 + * + * @param value + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModeCmd(int value) { + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder(); + builder.setCleanModeRequirement(value); + return buildTaskCmd(builder.build()); + } + + /** + * 作业模式:纯吸 + * + * @return + */ + 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()); + } + + /** + * 作业模式:关闭作业模式 + * + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModeCloseCmd() { + 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()); + } + + /** + * 作业方向:根据具体的方向传入具体的值 + * + * @param value + * @return + */ + 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()); + } + + /** + * 作业方向:关闭作业方向 + * + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanDirectionCloseCmd() { + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder(); + builder.setCleanDirectionRequirement(CLEAN_DIRECTION_CLOSE); + //重置作业强度为标准 + builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND); + return buildTaskCmd(builder.build()); + } + + /** + * 作业强度:传入具体的值 + * + * @param value + * @return + */ + public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityCmd(int value) { + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder(); + builder.setCleanIntensityRequirement(value); + return buildTaskCmd(builder.build()); + } + + private static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildTaskCmd( + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd fuTianCleanCmd) { + return SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd.newBuilder() + .setRoboSweeperFutianCleanCmd(fuTianCleanCmd).build(); + } + + /** + * 构建底盘Mock数据 + * + * @return + */ + public static VehicleStateOuterClass.SweeperFuTianCleanSystemState buildSweeperFuTionCleanSystemStateMockData() { + VehicleStateOuterClass.SweeperFuTianCleanSystemState.Builder builder = VehicleStateOuterClass.SweeperFuTianCleanSystemState.newBuilder(); + builder.setSecuMotWorkSts(true); + builder.setSecuModWashSts(true); + builder.setSecuWorkOnBothsidesSts(true); + builder.setSecuWorkStrongSts(true); + return builder.build(); + } + +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperTrajectoryManager.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperTrajectoryManager.java new file mode 100644 index 0000000000..8f054bf16a --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperTrajectoryManager.java @@ -0,0 +1,204 @@ +package com.mogo.och.sweeper.util; + +import androidx.annotation.Nullable; + +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.GsonUtils; +import com.mogo.och.sweeper.bean.SweeperRoutesResult; +import com.mogo.och.sweeper.constant.SweeperConst; +import com.mogo.och.sweeper.model.SweeperOrderModel; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; +import mogo_msg.MogoReportMsg; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +/** + * Bus轨迹管理:给MEC下发用于轨迹下载的信息 + * Created on 2022/6/23 + */ +public class SweeperTrajectoryManager { + private static final String TAG = SweeperTrajectoryManager.class.getSimpleName(); + + private static final class SingletonHolder { + private static final SweeperTrajectoryManager INSTANCE = new SweeperTrajectoryManager(); + } + + public static SweeperTrajectoryManager getInstance() { + return SweeperTrajectoryManager.SingletonHolder.INSTANCE; + } + + private AutopilotControlParameters.AutoPilotLine mAutoPilotLine = null; + private Disposable mSendReqDisposable = null; + + public SweeperTrajectoryManager() { + mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(-1, + "", "", "", "", 0, "", + "", "", "", "", 0); + } + + /** + * 同步Bus路线信息 + */ + public void syncTrajectoryInfo() { + SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult(); + if (SweeperOrderModel.getInstance().isWorking() && routesResult != null + && SweeperOrderModel.getInstance().getCurrentStationIndex() == 0 + && !SweeperOrderModel.getInstance().isGoingToNextStation()) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() start."); + startTrajReqLoop(); + } else { + // 无路线信息or当前未在始发站 + CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() stop."); + stopTrajReqLoop(); + } + } + + /** + * 接口MEC反馈的常规信息(MAP v2.5.0新增轨迹相关信息) + * @param guardianInfo + */ + public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { + if (guardianInfo == null || !guardianInfo.hasCode()) return; + if ("ISYS_INIT_TRAJECTORY_START".equals(guardianInfo.getCode())) { + // 1. 轨迹管理_轨迹开始下载(本地已有对应轨迹也触发) + CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹开始下载"); + // ToastUtils.showShort("轨迹开始下载"); + stopTrajReqLoop(); + } else if ("ISYS_INIT_TRAJECTORY_SUCCESS".equals(guardianInfo.getCode())) { + // 2. 轨迹管理_轨迹下载成功(本地已有对应轨迹也触发) + CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载成功"); + // ToastUtils.showShort("轨迹下载成功"); + stopTrajReqLoop(); + } else if ("ISYS_INIT_TRAJECTORY_FAILURE".equals(guardianInfo.getCode())) { + // 3. 轨迹管理_轨迹下载失败,本地无对应轨迹 + CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " + + "轨迹下载失败,本地无对应轨迹"); + // ToastUtils.showShort("轨迹下载失败,本地无对应轨迹"); + } else if ("ISYS_INIT_TRAJECTORY_WARNING".equals(guardianInfo.getCode())) { + // 4. 轨迹管理_轨迹下载失败,本地有对应轨迹,认为成功 + CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " + + "轨迹下载失败,本地有对应轨迹,认为成功"); + // ToastUtils.showShort("轨迹下载失败,本地有对应轨迹,认为成功"); + } else if ("ISYS_INIT_TRAJECTORY_TIMEOUT".equals(guardianInfo.getCode())) { + // 5. 轨迹管理_轨迹下载超时 + CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载超时"); + // ToastUtils.showShort("轨迹下载超时"); + } + } + + private void setupAutoPilotLine() { + SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult(); + if (routesResult == null) { + CallerLogger.INSTANCE.e(M_BUS + TAG, + "setupAutoPilotLine(): routesResult is null."); + return; + } else { + if (mAutoPilotLine == null) { + mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(routesResult.getLineId(), + routesResult.csvFileUrl, routesResult.csvFileMd5, + routesResult.txtFileUrl, routesResult.txtFileMd5, + routesResult.contrailSaveTime, routesResult.carModel, + routesResult.csvFileUrlDPQP, routesResult.csvFileMd5DPQP, + routesResult.txtFileUrlDPQP, routesResult.txtFileMd5DPQP, + routesResult.contrailSaveTimeDPQP); + } else { + mAutoPilotLine.setLineId(routesResult.getLineId()); + mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl); + mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5); + mAutoPilotLine.setStopUrl(routesResult.txtFileUrl); + mAutoPilotLine.setStopMd5(routesResult.txtFileMd5); + mAutoPilotLine.setTimestamp(routesResult.contrailSaveTime); + mAutoPilotLine.setVehicleModel(routesResult.carModel); + mAutoPilotLine.setTrajUrl_dpqp(routesResult.csvFileUrlDPQP); + mAutoPilotLine.setTrajMd5_dpqp(routesResult.csvFileMd5DPQP); + mAutoPilotLine.setStopUrl_dpqp(routesResult.txtFileUrlDPQP); + mAutoPilotLine.setStopMd5_dpqp(routesResult.txtFileMd5DPQP); + mAutoPilotLine.setTimestamp_dpqp(routesResult.contrailSaveTimeDPQP); + } + } + } + + private void clearAutoPilotLine() { + if (mAutoPilotLine == null) return; + mAutoPilotLine.setLineId(-1); + mAutoPilotLine.setTrajUrl(""); + mAutoPilotLine.setTrajMd5(""); + mAutoPilotLine.setStopUrl(""); + mAutoPilotLine.setStopMd5(""); + mAutoPilotLine.setTimestamp(0); + mAutoPilotLine.setVehicleModel(""); + mAutoPilotLine.setTrajUrl_dpqp(""); + mAutoPilotLine.setTrajMd5_dpqp(""); + mAutoPilotLine.setStopUrl_dpqp(""); + mAutoPilotLine.setStopMd5_dpqp(""); + mAutoPilotLine.setTimestamp_dpqp(0); + } + + private void startTrajReqLoop() { + if (mSendReqDisposable != null && !mSendReqDisposable.isDisposed()) { + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "startTrajReqLoop()"); + setupAutoPilotLine(); + mSendReqDisposable = Observable.interval(SweeperConst.LOOP_DELAY, + SweeperConst.LOOP_PERIOD_10S, TimeUnit.MILLISECONDS) + .map((aLong -> aLong + 1)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> { + if (aLong > SweeperConst.LOOP_SEND_TRAJ_TIMES) { + stopTrajReqLoop(); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "loop sendTrajectoryReq: " + aLong); + sendTrajectoryReq(); + }); + } + + public void stopTrajReqLoop() { + if (mSendReqDisposable != null) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "stopTrajReqLoop()"); + mSendReqDisposable.dispose(); + mSendReqDisposable = null; + clearAutoPilotLine(); + } + } + + private void sendTrajectoryReq() { + if (mAutoPilotLine == null) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "sendTrajectoryReq(): mAutoPilotLine is null!!!"); + return; + } + + // TODO: 2022/6/24 + // test1 +// mAutoPilotLine.setLineId(148); +// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/e27c20c2da32481021d934c3ef084536/traj_148.csv"); +// mAutoPilotLine.setTrajMd5("e27c20c2da32481021d934c3ef084536"); +// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/6224c9dd2c0e2bd990c6482c0464de45/stop_148.txt"); +// mAutoPilotLine.setStopMd5("6224c9dd2c0e2bd990c6482c0464de45"); +// mAutoPilotLine.setTimestamp(1654596000000L); //20220607 18:00 +// mAutoPilotLine.setVehicleModel("红旗H9"); + + // test2 +// mAutoPilotLine.setLineId(148); +// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/8654497cf918be461a59c7ad8e22920d/traj_148.csv"); +// mAutoPilotLine.setTrajMd5("8654497cf918be461a59c7ad8e22920d"); +// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/1bb098b244922649bf3e7bada0d3950f/stop_148.txt"); +// mAutoPilotLine.setStopMd5("1bb098b244922649bf3e7bada0d3950f"); +// mAutoPilotLine.setTimestamp(1654761600000L); //20220609 16:00 +// mAutoPilotLine.setVehicleModel("红旗H9"); + + CallerAutoPilotManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine); + CallerLogger.INSTANCE.d(M_BUS + TAG, "sendTrajectoryReq(): " + + GsonUtils.toJson(mAutoPilotLine)); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/BusArcView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/BusArcView.java new file mode 100644 index 0000000000..d559214b15 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/BusArcView.java @@ -0,0 +1,190 @@ +package com.mogo.och.sweeper.view; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.mogo.och.sweeper.R; + +/** + * created by wujifei on 2021/3/24 16:20 + * describe: + */ +public class BusArcView extends View { + + //中心的文字描述 + private String mDes = "KM/H"; + //根据数据显示的圆弧Paint + private Paint mArcPaint; + //圆弧颜色 + private int mArcColor; + //圆弧的画笔的宽度 + private float mStrokeWith = getResources().getDimension(R.dimen.sweeper_ext_arcView_stroke_with); + //文字描述的paint + private Paint mTextPaint; + + //当前进度夹角大小 + private float mIncludedAngle = 0; + //当前数据 + private int currentValue; + //最大数据 + private int maxValue = 240; + //圆弧背景的开始和结束间的夹角大小 + private float mAngle = 270; + //上次绘制圆弧夹角 + private float lastAngle = 0; + + public BusArcView(Context context) { + this(context, null); + } + + public BusArcView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public BusArcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + //初始化paint + initPaint(); + //绘制弧度 + drawArc(canvas); + //绘制文本 + drawText(canvas); + } + + private void drawText(Canvas canvas) { + Rect mRect = new Rect(); + String mValue = String.valueOf(currentValue); + mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + //绘制中心的数值 + mTextPaint.getTextBounds(mValue, 0, mValue.length(), mRect); + canvas.drawText(mValue, getWidth() / 2, getHeight() / 2 + mRect.height() / 2 - 10, mTextPaint); + + mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + //绘制中心文字描述 + mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweeper_ext_arcView_des_text_size)); + mTextPaint.getTextBounds(mDes, 0, mDes.length(), mRect); + canvas.drawText(mDes, getWidth() / 2, getHeight() * 17 / 20 + mRect.height() / 2, mTextPaint); + } + + private void drawArc(Canvas canvas) { + //绘制圆弧背景 + RectF mRectF = new RectF(mStrokeWith, mStrokeWith, getWidth() - mStrokeWith, getHeight() - mStrokeWith); + canvas.drawArc(mRectF, 135, mAngle, false, mArcPaint); + + //绘制当前数值对应的圆弧 + mArcPaint.setColor(mArcColor); + //根据当前数据绘制对应的圆弧 + canvas.drawArc(mRectF, 135, mIncludedAngle, false, mArcPaint); + } + + private void initPaint() { + //圆弧的paint + mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + //抗锯齿 + mArcPaint.setAntiAlias(true); + mArcPaint.setColor(Color.parseColor("#151D4C")); + //设置透明度(数值为0-255) + mArcPaint.setAlpha(100); + //设置画笔的画出的形状 + mArcPaint.setStrokeJoin(Paint.Join.ROUND); + mArcPaint.setStrokeCap(Paint.Cap.ROUND); + //设置画笔类型 + mArcPaint.setStyle(Paint.Style.STROKE); + //画笔宽度 + mArcPaint.setStrokeWidth(mStrokeWith); + + //中心文字的paint + mTextPaint = new Paint(); + mTextPaint.setAntiAlias(true); + mTextPaint.setColor(Color.parseColor("#FFFFFF")); + //设置文本的对齐方式 + mTextPaint.setTextAlign(Paint.Align.CENTER); + //mTextPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.dp_12)); + mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweeper_ext_arcView_center_text_size)); + + } + + + /** + * 为绘制弧度及数据设置动画 + * + * @param startAngle 开始的弧度 + * @param currentAngle 需要绘制的弧度 + * @param time 动画执行的时长 + */ + private void setAnimation(float startAngle, float currentAngle, int time) { + //绘制当前数据对应的圆弧的动画效果 + ValueAnimator progressAnimator = ValueAnimator.ofFloat(startAngle, currentAngle); + progressAnimator.setDuration(time); + progressAnimator.setTarget(mIncludedAngle); + progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mIncludedAngle = (float) animation.getAnimatedValue(); + //重新绘制,不然不会出现效果 + postInvalidate(); + } + }); + //开始执行动画 + progressAnimator.start(); + } + + + /** + * 设置弧形颜色 + * + * @param value 颜色值 + */ + public void setArcColor(int value) { + mArcColor = value; + } + + /** + * 设置数据 + * + * @param value 当前绘制的值 + */ + public void setValues(int value) { + //完全覆盖 + if (value > maxValue) { + value = maxValue; + } + if (value < 0) { + value = 0; + } + currentValue = value; + //计算弧度比重 + float scale = (float) currentValue / maxValue; + //计算弧度 + float currentAngle = scale * mAngle; + //开始执行动画 + setAnimation(lastAngle, currentAngle, 1000); + lastAngle = currentAngle; + //重新绘制 + postInvalidate(); + } + + + private float dp2px(float dp) { + DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); + return dp * metrics.density; + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/NoTouchConstraintLayout.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/NoTouchConstraintLayout.java new file mode 100644 index 0000000000..6922b9596f --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/NoTouchConstraintLayout.java @@ -0,0 +1,37 @@ +package com.mogo.och.sweeper.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.mogo.commons.debug.DebugConfig; + +/** + * 强制拦截所有touch时间的约束布局 + * + * @author tongchenfei + */ +public class NoTouchConstraintLayout extends ConstraintLayout { + public NoTouchConstraintLayout(Context context) { + super(context); + } + + public NoTouchConstraintLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoTouchConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if(DebugConfig.isDebug()){ + return super.onInterceptTouchEvent(ev); + }else { + return true; + } + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/SlidePanelView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/SlidePanelView.java new file mode 100644 index 0000000000..f7171bce89 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/SlidePanelView.java @@ -0,0 +1,270 @@ +package com.mogo.och.sweeper.view; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import androidx.annotation.Nullable; + +import com.mogo.och.sweeper.R; + +/** + * 滑块滑动面板 + * + * @author tongchenfei + */ +public class SlidePanelView extends View { + private static final String TAG = "SlidePanelView"; + + public SlidePanelView(Context context) { + this(context, null); + } + + public SlidePanelView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidePanelView); + textSize = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_textSize, textSize); + BLOCK_START_X = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_X, BLOCK_START_X); + BLOCK_START_Y = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_Y, BLOCK_START_Y); + NORMAL_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_LEFT, NORMAL_TEXT_MARGIN_LEFT); + NORMAL_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_RIGHT, NORMAL_TEXT_MARGIN_RIGHT); + SHORT_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_LEFT, SHORT_TEXT_MARGIN_LEFT); + SHORT_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_RIGHT, SHORT_TEXT_MARGIN_RIGHT); + init(); + } + + private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private static int textSize = 40; + private static int BLOCK_START_X = 15; + private static int BLOCK_START_Y = 15; + private static int NORMAL_TEXT_MARGIN_LEFT = 40; + private static int NORMAL_TEXT_MARGIN_RIGHT = 60; + private static int SHORT_TEXT_MARGIN_LEFT = 60; + private static int SHORT_TEXT_MARGIN_RIGHT = 70; + + private int textMarginLeft = NORMAL_TEXT_MARGIN_LEFT; + private int textMarginRight = NORMAL_TEXT_MARGIN_RIGHT; + + private OnSlidePanelMoveToEndListener moveToEndListener; + + private int blockWidth = 0; + private int blockOffset = 0; + + private float lastX; + private boolean isToEnd = false; + + private static final String STRING_SLIDE_TO_RIGHT = "向右滑动"; + private RectF bgRectF; + private Bitmap bmBlock; + + private final Matrix gradientMatrix = new Matrix(); + private float matrixTranslate; + private final Rect textRect = new Rect(); + private LinearGradient textGradient; + + private ObjectAnimator matrixAnim; + + private String blockText = STRING_SLIDE_TO_RIGHT; + private Paint.FontMetrics blockTextMetrics = new Paint.FontMetrics(); + + private static final int GRADIENT_OFFSET = 200; + + public void setOnSlidePanelMoveToEndListener(OnSlidePanelMoveToEndListener moveToEndListener) { + this.moveToEndListener = moveToEndListener; + } + + private void setBlockOffset(int blockOffset) { + this.blockOffset = blockOffset; + invalidate(); + } + + private void setMatrixTranslate(float matrixTranslate) { + this.matrixTranslate = matrixTranslate; + invalidate(); + } + + public void setText(String text) { + this.blockText = text; + requestLayout(); + invalidate(); + } + + private void init() { + bgRectF = new RectF(0, 0, 0, 0); + bgPaint.setColor(Color.parseColor("#CC0F1325")); + bgPaint.setStyle(Paint.Style.FILL); + + textPaint.setStyle(Paint.Style.FILL); + textPaint.setTextSize(textSize); + textPaint.setTextAlign(Paint.Align.LEFT); + textGradient = new LinearGradient(-GRADIENT_OFFSET, 0, 0, 0, new int[]{0x33ffffff, 0xffffffff, 0x33ffffff}, null, Shader.TileMode.CLAMP); + textGradient.setLocalMatrix(gradientMatrix); + textPaint.setShader(textGradient); + textPaint.getFontMetrics(blockTextMetrics); + + bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.sweeper_base_slide_block); + blockWidth = bmBlock.getWidth(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize; + int heightSize; + + if (blockText.length() < 5) { + textMarginLeft = SHORT_TEXT_MARGIN_LEFT; + textMarginRight = SHORT_TEXT_MARGIN_RIGHT; + } else { + textMarginLeft = NORMAL_TEXT_MARGIN_LEFT; + textMarginRight = NORMAL_TEXT_MARGIN_RIGHT; + } + + if (widthMode == MeasureSpec.AT_MOST) { + // 宽度根据图片大小,字符串长度,各种间隔确定 + // 高度根据图片大小和上下间隔确定 + textPaint.getTextBounds(blockText, 0, blockText.length(), textRect); + widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + textMarginLeft + textMarginRight + textRect.width(); + heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight(); + widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private float textOffset = 0; + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (bgRectF != null){ + bgRectF.left = 0; + bgRectF.top = 0; + bgRectF.right = w; + bgRectF.bottom = h; + } + + if (matrixAnim != null) { + matrixAnim.cancel(); + } + textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2; + matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + GRADIENT_OFFSET).setDuration(2000); + matrixAnim.setRepeatCount(ValueAnimator.INFINITE); + matrixAnim.start(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (matrixAnim != null) { + matrixAnim.start(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (matrixAnim != null) { + matrixAnim.cancel(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) { + isToEnd = false; + lastX = x; + } + break; + case MotionEvent.ACTION_MOVE: + if (lastX != 0) { + blockOffset = (int) (x - lastX); + if (blockOffset < 0) { + blockOffset = 0; + } + if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) { + // 超出右边界 + blockOffset = getWidth() - BLOCK_START_X - blockWidth; + if (!isToEnd) { + isToEnd = true; + if (moveToEndListener != null) { + moveToEndListener.moveToEnd(); + } + startBlockBackAnim(); + } + } + invalidate(); + } + break; + case MotionEvent.ACTION_UP: + // 执行滑块回归动画 + if (!isToEnd) { + startBlockBackAnim(); + } + break; + default: + break; + } + + return true; + } + + private void startBlockBackAnim() { + ObjectAnimator blockBackanimator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0); + blockBackanimator.setInterpolator(new DecelerateInterpolator()); + blockBackanimator.setDuration(1000 * blockOffset / getWidth()); + blockBackanimator.start(); + lastX = 0; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 画背景 + canvas.drawRoundRect(bgRectF, (float) getHeight() / 2, (float) getHeight() / 2, bgPaint); + // 画文字 + gradientMatrix.setTranslate(matrixTranslate, 0); + textGradient.setLocalMatrix(gradientMatrix); + canvas.save(); + canvas.drawText(blockText, blockWidth + BLOCK_START_X + textMarginLeft, textOffset, textPaint); + canvas.restore(); + // 画滑块 + canvas.drawBitmap(bmBlock, BLOCK_START_X + blockOffset, BLOCK_START_Y, blockPaint); + } + + public interface OnSlidePanelMoveToEndListener { + /** + * 滑块滑到了末尾 + */ + void moveToEnd(); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/VerticalDashLineView.java b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/VerticalDashLineView.java new file mode 100644 index 0000000000..875722ea11 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/view/VerticalDashLineView.java @@ -0,0 +1,64 @@ +package com.mogo.och.sweeper.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +/** + * 垂直虚线 + * + * @author tongchenfei + */ +public class VerticalDashLineView extends View { + public VerticalDashLineView(Context context) { + this(context,null); + } + + public VerticalDashLineView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public VerticalDashLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private final Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path dashPath = new Path(); + + private void init(){ + linePaint.setColor(Color.GREEN); + linePaint.setStyle(Paint.Style.STROKE); + linePaint.setStrokeWidth(2); + linePaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0)); + } + + public void setGradient(int startColor, int endColor) { + LinearGradient linearGradient = new LinearGradient(0, 0, getWidth(), getHeight(), startColor, endColor, Shader.TileMode.CLAMP); + linePaint.setShader(linearGradient); + invalidate(); + } + + public void setColor(int color) { + linePaint.setShader(null); + linePaint.setColor(color); + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + dashPath.reset(); + dashPath.moveTo((float) getWidth()/2, 0); + dashPath.lineTo((float) getWidth()/2,getHeight()); + canvas.drawPath(dashPath,linePaint); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/res/color/sweeper_autopilot_text_color_selector.xml b/OCH/mogo-och-sweeper/src/main/res/color/sweeper_autopilot_text_color_selector.xml new file mode 100644 index 0000000000..afd0b1f78c --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/color/sweeper_autopilot_text_color_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/end_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/end_maker_icon.png new file mode 100755 index 0000000000..8acf113151 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/end_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_normal.png new file mode 100755 index 0000000000..e98738b192 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_select.png new file mode 100755 index 0000000000..d3e0107c02 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_ai_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_normal.png new file mode 100755 index 0000000000..c0a978fc2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_select.png new file mode 100755 index 0000000000..ebacf3a11a Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_bad_case_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_station_start_end.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_station_start_end.png new file mode 100644 index 0000000000..04580a8f0d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/icon_station_start_end.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/press_start_status.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/press_start_status.png new file mode 100755 index 0000000000..af32c20cb5 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/press_start_status.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_failure.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_failure.png new file mode 100755 index 0000000000..5737f93ad8 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_failure.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_maker_icon.png new file mode 100644 index 0000000000..9eca61e199 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_success.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_success.png new file mode 100755 index 0000000000..84246fd323 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/start_success.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_icon_not_in_autopilot.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_icon_not_in_autopilot.png new file mode 100644 index 0000000000..927296d690 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_icon_not_in_autopilot.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_slide_block.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_slide_block.png new file mode 100644 index 0000000000..ed7b293b90 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_base_slide_block.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_disable_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_disable_autopilot_icon.png new file mode 100644 index 0000000000..170f254cd1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_disable_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arrived_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arrived_station.png new file mode 100644 index 0000000000..8a065b66dd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arrived_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arriving_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arriving_station.png new file mode 100644 index 0000000000..4ed57a0e30 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_icon_arriving_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_green_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_green_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_red_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_light_red_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_lightyellow_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_lightyellow_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg.png new file mode 100755 index 0000000000..3166d20e37 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg_1.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg_1.png new file mode 100755 index 0000000000..09a9c252da Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_line_panel_bg_1.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_loading_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_loading_autopilot_icon.png new file mode 100644 index 0000000000..f21a1081f1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_loading_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_och_dot_line.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_och_dot_line.png new file mode 100644 index 0000000000..a720a532ea Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_och_dot_line.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_right_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_right_autopilot_icon.png new file mode 100644 index 0000000000..cc2b18083d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_right_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_selected_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_selected_btn.png new file mode 100644 index 0000000000..3f05565483 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_selected_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_setting_btn_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_setting_btn_bg.png new file mode 100644 index 0000000000..ba41bf3a53 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_setting_btn_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_line_close.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_line_close.png new file mode 100644 index 0000000000..370b61de38 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_line_close.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_long.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_long.png new file mode 100755 index 0000000000..cf3e5a3778 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_long.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_medium.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_medium.png new file mode 100755 index 0000000000..bdc2725468 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_switch_map_medium.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_unselect_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_unselect_btn.png new file mode 100644 index 0000000000..0114bb4f2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_unselect_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_wrong_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_wrong_autopilot_icon.png new file mode 100644 index 0000000000..0c8988acb3 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1440/sweeper_wrong_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/end_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/end_maker_icon.png new file mode 100755 index 0000000000..8acf113151 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/end_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_normal.png new file mode 100755 index 0000000000..e98738b192 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_select.png new file mode 100755 index 0000000000..d3e0107c02 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_ai_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_normal.png new file mode 100755 index 0000000000..c0a978fc2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_select.png new file mode 100755 index 0000000000..ebacf3a11a Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_bad_case_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_station_start_end.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_station_start_end.png new file mode 100644 index 0000000000..04580a8f0d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/icon_station_start_end.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/press_start_status.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/press_start_status.png new file mode 100755 index 0000000000..af32c20cb5 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/press_start_status.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_failure.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_failure.png new file mode 100755 index 0000000000..5737f93ad8 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_failure.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_maker_icon.png new file mode 100644 index 0000000000..9eca61e199 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_success.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_success.png new file mode 100755 index 0000000000..84246fd323 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/start_success.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_icon_not_in_autopilot.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_icon_not_in_autopilot.png new file mode 100644 index 0000000000..927296d690 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_icon_not_in_autopilot.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_slide_block.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_slide_block.png new file mode 100644 index 0000000000..ed7b293b90 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_base_slide_block.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_disable_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_disable_autopilot_icon.png new file mode 100644 index 0000000000..170f254cd1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_disable_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arrived_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arrived_station.png new file mode 100644 index 0000000000..8a065b66dd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arrived_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arriving_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arriving_station.png new file mode 100644 index 0000000000..4ed57a0e30 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_icon_arriving_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_green_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_green_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_red_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_light_red_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_lightyellow_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_lightyellow_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg.png new file mode 100755 index 0000000000..3166d20e37 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg_1.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg_1.png new file mode 100755 index 0000000000..09a9c252da Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_line_panel_bg_1.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_loading_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_loading_autopilot_icon.png new file mode 100644 index 0000000000..f21a1081f1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_loading_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_och_dot_line.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_och_dot_line.png new file mode 100644 index 0000000000..a720a532ea Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_och_dot_line.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_right_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_right_autopilot_icon.png new file mode 100644 index 0000000000..cc2b18083d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_right_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_selected_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_selected_btn.png new file mode 100644 index 0000000000..3f05565483 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_selected_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_setting_btn_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_setting_btn_bg.png new file mode 100644 index 0000000000..ba41bf3a53 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_setting_btn_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_line_close.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_line_close.png new file mode 100644 index 0000000000..370b61de38 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_line_close.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_long.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_long.png new file mode 100755 index 0000000000..cf3e5a3778 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_long.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_medium.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_medium.png new file mode 100755 index 0000000000..bdc2725468 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_switch_map_medium.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_unselect_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_unselect_btn.png new file mode 100644 index 0000000000..0114bb4f2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_unselect_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_wrong_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_wrong_autopilot_icon.png new file mode 100644 index 0000000000..0c8988acb3 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi-2560x1600/sweeper_wrong_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/end_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/end_maker_icon.png new file mode 100755 index 0000000000..8acf113151 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/end_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_normal.png new file mode 100755 index 0000000000..e98738b192 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_select.png new file mode 100755 index 0000000000..d3e0107c02 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_normal.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_normal.png new file mode 100755 index 0000000000..c0a978fc2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_normal.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_select.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_select.png new file mode 100755 index 0000000000..ebacf3a11a Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_bad_case_select.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_station_start_end.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_station_start_end.png new file mode 100644 index 0000000000..04580a8f0d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_station_start_end.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/img_sweeper_status_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/img_sweeper_status_bg.png new file mode 100644 index 0000000000..27cb9285d3 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/img_sweeper_status_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/no_order_data.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/no_order_data.png new file mode 100644 index 0000000000..0e61996d3f Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/no_order_data.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/press_start_status.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/press_start_status.png new file mode 100755 index 0000000000..af32c20cb5 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/press_start_status.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_failure.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_failure.png new file mode 100755 index 0000000000..5737f93ad8 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_failure.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_maker_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_maker_icon.png new file mode 100644 index 0000000000..9eca61e199 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_maker_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_success.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_success.png new file mode 100755 index 0000000000..84246fd323 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/start_success.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_in_autopilot.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_in_autopilot.png new file mode 100644 index 0000000000..75c26c3d71 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_in_autopilot.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_not_in_autopilot.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_not_in_autopilot.png new file mode 100644 index 0000000000..927296d690 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_icon_not_in_autopilot.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_notice_box_bg.9.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_notice_box_bg.9.png new file mode 100644 index 0000000000..8b4b579b56 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_notice_box_bg.9.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png new file mode 100644 index 0000000000..ed7b293b90 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_disable_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_disable_autopilot_icon.png new file mode 100644 index 0000000000..170f254cd1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_disable_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_dot_line.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_dot_line.png new file mode 100644 index 0000000000..186001352c Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_dot_line.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_ic_autopilot.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_ic_autopilot.png new file mode 100644 index 0000000000..be978145dc Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_ic_autopilot.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arrived_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arrived_station.png new file mode 100644 index 0000000000..8a065b66dd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arrived_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arriving_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arriving_station.png new file mode 100644 index 0000000000..4ed57a0e30 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_arriving_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_not_arrive_station.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_not_arrive_station.png new file mode 100644 index 0000000000..e0bb24c526 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_not_arrive_station.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg.png new file mode 100755 index 0000000000..3166d20e37 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg_1.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg_1.png new file mode 100755 index 0000000000..09a9c252da Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line_panel_bg_1.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_loading_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_loading_autopilot_icon.png new file mode 100644 index 0000000000..f21a1081f1 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_loading_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png new file mode 100644 index 0000000000..a720a532ea Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_right_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_right_autopilot_icon.png new file mode 100644 index 0000000000..cc2b18083d Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_right_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_selected_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_selected_btn.png new file mode 100644 index 0000000000..3f05565483 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_selected_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png new file mode 100644 index 0000000000..ba41bf3a53 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_line_close.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_line_close.png new file mode 100644 index 0000000000..370b61de38 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_line_close.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png new file mode 100755 index 0000000000..cf3e5a3778 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png new file mode 100644 index 0000000000..bdc2725468 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png new file mode 100644 index 0000000000..0114bb4f2b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_wrong_autopilot_icon.png b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_wrong_autopilot_icon.png new file mode 100644 index 0000000000..0c8988acb3 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_wrong_autopilot_icon.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/ai_collect_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/ai_collect_selector.xml new file mode 100755 index 0000000000..a1211f3c47 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/ai_collect_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bad_case_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bad_case_selector.xml new file mode 100755 index 0000000000..bc47ce95d7 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bad_case_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel.xml new file mode 100644 index 0000000000..c9f7378baa --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml new file mode 100644 index 0000000000..8455e0cafb --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml new file mode 100644 index 0000000000..84464f5307 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml new file mode 100644 index 0000000000..a5cb095bc8 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml new file mode 100644 index 0000000000..ec0eeb317b --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml new file mode 100644 index 0000000000..8d7970361a --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_traffic_light_background.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_traffic_light_background.xml new file mode 100644 index 0000000000..a74b1ff75f --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_traffic_light_background.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/img_sweeper_status_bg.9.png b/OCH/mogo-och-sweeper/src/main/res/drawable/img_sweeper_status_bg.9.png new file mode 100644 index 0000000000..0af2b9db73 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable/img_sweeper_status_bg.9.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg.xml new file mode 100644 index 0000000000..ad57da1c3a --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_check.png b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_check.png new file mode 100644 index 0000000000..28857974b5 Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_check.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_nor.png b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_nor.png new file mode 100644 index 0000000000..f7d4f92c4b Binary files /dev/null and b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_autopilot_status_bg_nor.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_base_autopilot_status_icon_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_base_autopilot_status_icon_selector.xml new file mode 100644 index 0000000000..6b646eac98 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_base_autopilot_status_icon_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_checkbox_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_checkbox_selector.xml new file mode 100644 index 0000000000..191827e786 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_checkbox_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line1_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line1_selector.xml new file mode 100644 index 0000000000..b00fbd8bd6 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line1_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line2_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line2_selector.xml new file mode 100644 index 0000000000..ee555aae15 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_line_dividing_line2_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml new file mode 100644 index 0000000000..ba7719ba91 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml new file mode 100755 index 0000000000..c51538216c --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg.xml new file mode 100644 index 0000000000..753d85e3ec --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg_selector.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg_selector.xml new file mode 100755 index 0000000000..996c623455 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_select_bg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_select_bg.xml new file mode 100644 index 0000000000..835c1fbaff --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_select_bg.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_anchor_bkg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_anchor_bkg.xml new file mode 100644 index 0000000000..38fc28d893 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_anchor_bkg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_bkg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_bkg.xml new file mode 100644 index 0000000000..d7937835a0 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_bkg.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_setting_tip_red_cir_bg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_setting_tip_red_cir_bg.xml new file mode 100644 index 0000000000..0f456d52c7 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_setting_tip_red_cir_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_green_dash_line.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_green_dash_line.xml new file mode 100644 index 0000000000..d1fbaeb3b9 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_green_dash_line.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_v_green_dash.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_v_green_dash.xml new file mode 100644 index 0000000000..f43c213363 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_v_green_dash.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn.xml new file mode 100644 index 0000000000..be0bd24850 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_commit.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_commit.xml new file mode 100644 index 0000000000..324b9ece10 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_commit.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_un_commit.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_un_commit.xml new file mode 100644 index 0000000000..d0ea7fa041 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_line_btn_un_commit.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_bg.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_bg.xml new file mode 100644 index 0000000000..943ebcac05 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_nor.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_nor.xml new file mode 100644 index 0000000000..4bde0e73c1 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_nor.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_speeding.xml b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_speeding.xml new file mode 100644 index 0000000000..dea7a88bb6 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_yi_biao_pan_bg_speeding.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/activity_sweeper_switch_line.xml b/OCH/mogo-och-sweeper/src/main/res/layout/activity_sweeper_switch_line.xml new file mode 100644 index 0000000000..83f6208652 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/layout/activity_sweeper_switch_line.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/fragment_och_sweeper.xml b/OCH/mogo-och-sweeper/src/main/res/layout/fragment_och_sweeper.xml new file mode 100644 index 0000000000..31e2ba482f --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/layout/fragment_och_sweeper.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/item_och_sweeper_station.xml b/OCH/mogo-och-sweeper/src/main/res/layout/item_och_sweeper_station.xml new file mode 100644 index 0000000000..ddcc6f38d7 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/layout/item_och_sweeper_station.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/sweeper_base_fragment.xml b/OCH/mogo-och-sweeper/src/main/res/layout/sweeper_base_fragment.xml new file mode 100644 index 0000000000..3329a05a39 --- /dev/null +++ b/OCH/mogo-och-sweeper/src/main/res/layout/sweeper_base_fragment.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +