diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java index 28e451dced..7f07057f98 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java @@ -1,6 +1,7 @@ package com.mogo.och.bus.passenger.callback; import com.amap.api.maps.model.LatLng; +import com.mogo.eagle.core.data.map.MogoLocation; import java.util.List; @@ -8,7 +9,7 @@ import java.util.List; * Created on 2022/3/31 */ public interface IBusPassengerAutopilotPlanningCallback { - void routeResult(List models,int haveArrivedIndex); + void routeResult(List routeArrivied, List routeArriving, MogoLocation location); void routePlanningToNextStationChanged(long meters, long timeInSecond); void updateTotalDistance(); } diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java deleted file mode 100644 index 3967989855..0000000000 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java +++ /dev/null @@ -1,685 +0,0 @@ -package com.mogo.och.bus.passenger.model; - -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; -import static com.mogo.och.bus.passenger.constant.BusPassengerConst.QUERY_BUS_P_STATION_DELAY; -import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED; - -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.os.Handler; -import android.os.Message; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.amap.api.maps.model.LatLng; -import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager; -import com.mogo.commons.debug.DebugConfig; -import com.mogo.commons.module.intent.IMogoIntentListener; -import com.mogo.commons.module.intent.IntentManager; -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.data.autopilot.AutopilotControlParameters; -import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo; -import com.mogo.eagle.core.data.config.FunctionBuildConfig; -import com.mogo.eagle.core.data.map.MogoLocation; -import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; -import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; -import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener; -import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener; -import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; -import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; -import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; -import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager; -import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager; -import com.mogo.eagle.core.network.utils.GsonUtil; -import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils; -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; -import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant; -import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; -import com.mogo.eagle.core.utilcode.util.CoordinateUtils; -import com.mogo.eagle.core.utilcode.util.GsonUtils; -import com.mogo.eagle.core.utilcode.util.NetworkUtils; -import com.mogo.eagle.core.utilcode.util.ToastUtils; -import com.mogo.och.bus.passenger.R; -import com.mogo.och.bus.passenger.bean.BusPassengerOperationStatusResponse; -import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResponse; -import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResult; -import com.mogo.och.bus.passenger.bean.BusPassengerStation; -import com.mogo.och.bus.passenger.callback.IBusPassegerDriverStatusCallback; -import com.mogo.och.bus.passenger.callback.IBusPassengerADASStatusCallback; -import com.mogo.och.bus.passenger.callback.IBusPassengerAutopilotPlanningCallback; -import com.mogo.och.bus.passenger.callback.IBusPassengerControllerStatusCallback; -import com.mogo.och.bus.passenger.callback.IBusPassengerRouteLineInfoCallback; -import com.mogo.och.bus.passenger.constant.BusPassengerConst; -import com.mogo.och.bus.passenger.network.BusPassengerModelLoopManager; -import com.mogo.och.bus.passenger.network.BusPassengerServiceManager; -import com.mogo.och.common.module.bean.dpmsg.AppConnectMsg; -import com.mogo.och.common.module.bean.dpmsg.BaseDPMsg; -import com.mogo.och.common.module.bean.dpmsg.DPMsgType; -import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager; -import com.mogo.och.common.module.biz.constant.OchCommonConst; -import com.mogo.och.common.module.biz.network.OchCommonServiceCallback; -import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager; -import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; -import com.mogo.och.common.module.utils.PinYinUtil; -import com.mogo.och.common.module.utils.DateTimeUtil; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import mogo.telematics.pad.MessagePad; -import mogo_msg.MogoReportMsg; -import system_master.SystemStatusInfo; - -/** - * Created on 2022/3/31 - */ -public class BusPassengerModel { - private static final String TAG = BusPassengerModel.class.getSimpleName(); - - private List mRoutePoints = new ArrayList<>(); - - private static final class SingletonHolder { - private static final BusPassengerModel INSTANCE = new BusPassengerModel(); - } - - public static BusPassengerModel getInstance() { - return SingletonHolder.INSTANCE; - } - - private Context mContext; - private IBusPassengerADASStatusCallback mADASStatusCallback; //Model->Presenter:自动驾驶状态相关 - private IBusPassengerAutopilotPlanningCallback mAutopilotPlanningCallback; //Model->Presenter:自动驾驶线路规划 - private Map mControllerStatusCallbackMap = new ConcurrentHashMap<>(); - - private IBusPassegerDriverStatusCallback mDriverStatusCallback; //出车收车状态 - private IBusPassengerRouteLineInfoCallback mRouteLineInfoCallback; // bus路线信息更新 - - private MogoLocation mLocation = null; - - private BusPassengerRoutesResult routesResult = null; - - List mStations = new ArrayList<>(); - private int mNextStationIndex = 0;// 要到达站的index - private final List mTwoStationsRouts = new ArrayList<>(); - private int mPreRouteIndex = 0; - private int mWipePreIndex = 0; - - private static final int MSG_QUERY_BUS_P_STATION = 1001; - private final Handler handler = new Handler(new Handler.Callback() { - @Override - public boolean handleMessage(Message msg) { - if ( msg.what == MSG_QUERY_BUS_P_STATION ) { - queryDriverOperationStatus(); - return true; - } - return false; - } - }); - - private BusPassengerModel() { - } - - public void init( Context context ) { - mContext = context.getApplicationContext(); - initListeners(); - // TODO: 2022/3/31 - queryDriverOperationStatus(); - startOrStopOrderLoop(true); - } - - public void setDriverStatusCallback(IBusPassegerDriverStatusCallback callback){ - this.mDriverStatusCallback = callback; - } - - public void setRouteLineInfoCallback(IBusPassengerRouteLineInfoCallback callback){ - this.mRouteLineInfoCallback = callback; - } - - private void queryDriverOperationDelay() { - handler.sendEmptyMessageDelayed( MSG_QUERY_BUS_P_STATION, QUERY_BUS_P_STATION_DELAY ); - } - - private void queryDriverOperationStatus() { - BusPassengerServiceManager.queryDriverOperationStatus(mContext - , new OchCommonServiceCallback() { - @Override - public void onSuccess(BusPassengerOperationStatusResponse data) { - if (data == null || data.data == null) return; - if (mDriverStatusCallback != null) { - CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverOperationStatus = %s", data.data.plateNumber ); - mDriverStatusCallback.changeOperationStatus(data.data.driverStatus == 1); - mDriverStatusCallback.updatePlateNumber(data.data.plateNumber); - } - } - - @Override - public void onError() { - if (!NetworkUtils.isConnected(mContext)) { - ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); - } else { - ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); - } - queryDriverOperationDelay(); - } - - @Override - public void onFail(int code, String msg) { - //延迟3s再次查询 - queryDriverOperationDelay(); - } - }); - } - - public void queryDriverSiteByCoordinate(){ - BusPassengerServiceManager.queryDriverSiteByCoordinate(mContext - , new OchCommonServiceCallback() { - @Override - public void onSuccess(BusPassengerRoutesResponse data) { - if ( data == null || data.getResult() == null) { - CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = null"); - if (routesResult != null) { - routesResult = null; - mNextStationIndex = 0; - } - - startOrStopCalculateRouteInfo(false); - - if (mRouteLineInfoCallback != null){ - mRouteLineInfoCallback.showNoTaskView(); - } - - mRoutePoints.clear(); - - return; - } - if (routesResult != null && data.getResult().equals(routesResult)){ - CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = not update"); - return; - } - routesResult = data.getResult(); - updatePassengerRouteInfo(data.getResult()); - } - - @Override - public void onFail(int code, String msg) { - CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = %s", msg - + ", sn = " +BusPassengerServiceManager.INSTANCE.getDriverAppSn()); - if (code == 1003){ - queryDriverOperationDelay(); - } - if (BusPassengerServiceManager.INSTANCE.getDriverAppSn().isEmpty()){ - //此处拦截是为了防止过程中乘客屏和司机端断连,拿不到司机端sn, 造成请求失败去刷新了界面 - return; - } - if (code == 1003){ - routesResult = null; - startOrStopCalculateRouteInfo(false); - return; - } - } - }); - } - - private void updatePassengerRouteInfo(BusPassengerRoutesResult result) { - if (mRouteLineInfoCallback != null){ - mRouteLineInfoCallback.updateLineInfo(result.getName(),result.getRunningDur()); - mRouteLineInfoCallback.hideNoTaskView(); - if (result.getSites() != null){ - List stations = result.getSites(); - mStations.clear(); - mStations.addAll(stations); - for (int i = 0; i< stations.size(); i++){ - BusPassengerStation station = stations.get(i); - if (station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving() && i+1 < stations.size()){ //离站 - mRouteLineInfoCallback.updateStationsInfo(stations,i+1,false); - if(mNextStationIndex != i+1){ - mTwoStationsRouts.clear(); - startRemainRouteInfo(); - } - mNextStationIndex = i+1; - - updateAutopilotControlParameters(result,i); - return; - }else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){ //到站 - if (i == 0){ - startOrStopRouteAndWipe(false); - } - mPreRouteIndex = 0; - startOrStopCalculateRouteInfo(false); - mRouteLineInfoCallback.updateStationsInfo(stations,i,true); - clearAutopilotControlParameters(); - return; - } - } - } - } - - } - - private void updateAutopilotControlParameters(BusPassengerRoutesResult busRoutesResult, - int leaveIndex) { - - AutopilotControlParameters parameters = initAutopilotControlParameters(busRoutesResult,leaveIndex); - if (null == parameters) { - CallerLogger.INSTANCE.e(M_BUS_P + TAG, "AutopilotControlParameters is empty."); - return; - } - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "AutopilotControlParameters is update."); - CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(parameters); - } - - private void clearAutopilotControlParameters() { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "AutopilotControlParameters is clear."); - CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(null); - } - - private AutopilotControlParameters initAutopilotControlParameters(BusPassengerRoutesResult busRoutesResult, - int leaveIndex) { - if (busRoutesResult.getSites() == null){ return null ;} - List stations = busRoutesResult.getSites(); - if (leaveIndex + 1 > stations.size() - 1) { - CallerLogger.INSTANCE.e(M_BUS_P + TAG, "行程日志-mismatch condition1."); - return null; - } - BusPassengerStation currentStation = stations.get(leaveIndex); - BusPassengerStation nextStation = stations.get(leaveIndex + 1); - - AutopilotControlParameters parameters = new AutopilotControlParameters(); - parameters.routeID = busRoutesResult.getLineId(); - parameters.routeName = busRoutesResult.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 = 10; - if (parameters.autoPilotLine == null) { - parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine( - busRoutesResult.getLineId(), - busRoutesResult.csvFileUrl, busRoutesResult.csvFileMd5, - busRoutesResult.txtFileUrl, busRoutesResult.txtFileMd5, - busRoutesResult.contrailSaveTime, busRoutesResult.carModel, - busRoutesResult.csvFileUrlDPQP, busRoutesResult.csvFileMd5DPQP, - busRoutesResult.txtFileUrlDPQP, busRoutesResult.txtFileMd5DPQP, - busRoutesResult.contrailSaveTimeDPQP); - } - - return parameters; - } - - public void release() { - releaseListeners(); - startOrStopCalculateRouteInfo(false); - startOrStopOrderLoop(false); - } - - public void setMoGoAutopilotPlanningListener(IBusPassengerAutopilotPlanningCallback - moGoAutopilotPlanningCallback) { - this.mAutopilotPlanningCallback = moGoAutopilotPlanningCallback; - } - - public void setADASStatusCallback(IBusPassengerADASStatusCallback callback) { - this.mADASStatusCallback = callback; - } - - public void setControllerStatusCallback(String tag, IBusPassengerControllerStatusCallback callback) { - if (tag == null || "".equals(tag)) return; - - if (callback == null) { - mControllerStatusCallbackMap.remove(tag); - return; - } - - mControllerStatusCallbackMap.put(tag,callback); - - } - - private void initListeners() { - - // 2021.11.1重构自动驾驶 实现接口 IMoGoAutopilotStatusListener 注册监听 替换IMogoAdasOCHCallback接口 - CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, mGoAutopilotStatusListener); - IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener ); - MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener ); - // 定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, mMapLocationListener); - - //2021.11.1 自动驾驶路线规划接口 - CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG,moGoAutopilotPlanningListener); - - //监听司机端消息 - CallerTelematicListenerManager.INSTANCE.addListener(TAG,mReceivedMsgListener); - - AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext); - } - - private void releaseListeners() { - MogoStatusManager.getInstance().unregisterStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); - - // 注销定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); - - MogoAiCloudSocketManager.getInstance(mContext) - .unregisterLifecycleListener(10010); - - CallerAutoPilotStatusListenerManager.INSTANCE.removeListener(mGoAutopilotStatusListener); - CallerPlanningRottingListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); - CallerTelematicListenerManager.INSTANCE.removeListener(TAG); - - AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors(); - } - - private final IReceivedMsgListener mReceivedMsgListener = new IReceivedMsgListener() { - @Override - public void onReceivedServerSn(@Nullable String sn) { - Logger.d(SceneConstant.M_BUS_P+TAG,"onReceivedServerSn = "+sn); - if (mDriverStatusCallback != null) { - mDriverStatusCallback.updateDriverSn(sn); - } - } - - @Override - public void onReceivedMsg(int type, @NonNull byte[] byteArray) { - if (OchCommonConst.BUSINESS_STRING == type){ - - BaseDPMsg baseMsg = GsonUtils.fromJson(new String(byteArray), BaseDPMsg.class); - Logger.d(SceneConstant.M_BUS_P+TAG,"onReceivedMsg = "+GsonUtils.toJson(baseMsg)); - - if (baseMsg != null && baseMsg.getType() == DPMsgType.TYPE_COMMON.getType()){ - AppConnectMsg msg = GsonUtils.fromJson(new String(byteArray), AppConnectMsg.class); - if (msg.isViewShow()){ //消息盒子显示内容 - OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox( - DateTimeUtil.getCurrentTimeStamp(),msg.getMsg(), - OCHSocketMessageManager.OPERATION_SYSTEM); - } - } - } - } - }; - - //监听网络变化,避免启动机器时无网导致无法更新订单信息 - private final IMogoIntentListener mNetWorkIntentListener = new IMogoIntentListener() { - @Override - public void onIntentReceived( String intentStr, Intent intent ) { - CallerLogger.INSTANCE.d( M_BUS_P + TAG, "onIntentReceived = %s", intentStr ); - if ( ConnectivityManager.CONNECTIVITY_ACTION.equals( intentStr ) ) { - if ( NetworkUtils.isConnected( mContext ) ) { - queryDriverOperationStatus(); - } - } - } - }; - - // VR mode变更回调 - private final IMogoStatusChangedListener mMogoStatusChangedListener = (descriptor, isTrue) -> { - if (StatusDescriptor.VR_MODE == descriptor) { - if (mControllerStatusCallbackMap.size() > 0) { - for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){ - callback.onVRModeChanged(isTrue); - } - } - } - }; - - private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() { - @Override - public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { - if (null == gnssInfo) return; - mLocation = gnssInfo; - for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){ - callback.onCarLocationChanged(gnssInfo); - } - } - }; - - private volatile int mPreAutoStatus = -1; - - private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ - - @Override - public void onAutopilotRouteLineId(long lineId) { - - } - - @Override - public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) { - } - - @Override - public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { - - } - - private boolean arriveAtEnd = false; //乘客app专用字段 - - @Override - public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { - if (autopilotStatusInfo == null) return; - int state = autopilotStatusInfo.getState(); - if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning(); - } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { - if(state != mPreAutoStatus){ - mTwoStationsRouts.clear(); - } - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotEnable(); - } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { - if(state != mPreAutoStatus){ - mTwoStationsRouts.clear(); - } - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotDisable(); - }else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){ - if(state != mPreAutoStatus){ - mTwoStationsRouts.clear(); - } - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning(); - } - mPreAutoStatus = state; - } - - @Override - public void onAutopilotSNRequest() { - - } - - @Override - public void onAutopilotArriveAtStation(@Nullable MessagePad.ArrivalNotification arrivalNotification) { - if (FunctionBuildConfig.isDemoMode - && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) { - arriveAtEnd = true; - } - - // TODO: 2022/3/31 - if (DebugConfig.isDebug()) { - // ToastUtils.showShort("到达目的地"); - } - if (mADASStatusCallback != null){ - mADASStatusCallback.onAutopilotArriveEnd(); - } - } - - @Override - public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { - - } - }; - - private final IMoGoPlanningRottingListener moGoAutopilotPlanningListener = new IMoGoPlanningRottingListener(){ - - @Override - public void onAutopilotRotting(@Nullable MessagePad.GlobalPathResp routeList) { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "onAutopilotRotting = " - + GsonUtil.jsonFromObject(routeList)); - List routePoints = routeList.getWayPointsList(); - if (null != routePoints && routePoints.size() > 0){ - updateRoutePoints(routePoints); - startToRouteAndWipe(); - } - } - }; - - public void updateRoutePoints(List routePoints){ - mRoutePoints.clear(); - List latLngModels = CoordinateCalculateRouteUtil - .coordinateConverterWgsToGcjLocations(mContext,routePoints); - mRoutePoints.addAll(latLngModels); - calculateTwoStationsRoute(); - } - - private void calculateTwoStationsRoute(){ - //找出前往站对应的轨迹点,拿出两站点的集合 - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "mRoutePoints.size() = " + mRoutePoints.size()); - if (mRoutePoints.size() > 0) { - if (mStations.size() > 1){ //两个站点及以上要计算两个站点间的轨迹路线 - if (mNextStationIndex <= mStations.size()-1 && mNextStationIndex - 1 >=0){ - mTwoStationsRouts.clear(); - BusPassengerStation stationNext = mStations.get(mNextStationIndex); - BusPassengerStation stationCur = mStations.get(mNextStationIndex - 1); - //当前站在轨迹中对应的点 - int currentRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew(0 - ,mRoutePoints - ,stationCur.getGcjLon(),stationCur.getGcjLat()); - //要前往的站在轨迹中对应的点 - int nextRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew(currentRouteIndex - ,mRoutePoints - ,stationNext.getGcjLon(),stationNext.getGcjLat()); - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==currentRouteIndex = " + currentRouteIndex - + ", nextRouteIndex = " + nextRouteIndex); - if (currentRouteIndex < nextRouteIndex){ //如果找到的next在起点的轨迹前面,直接舍弃这个轨迹,不显示 - mTwoStationsRouts.addAll(mRoutePoints.subList(currentRouteIndex,nextRouteIndex + 1)); - } - } - } -// else { //只有两个站点的时候整个路线就是两个站点之间的轨迹 -// mTwoStationsRouts.clear(); -// mTwoStationsRouts.addAll(mRoutePoints); -// } - if (mTwoStationsRouts.size() > 0){ - float sumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(mTwoStationsRouts); - SharedPrefsMgr.getInstance(mContext).putInt(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS,(int) sumLength); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.updateTotalDistance(); - } - } - } - } - - public void dynamicCalculateRouteInfo() { - //计算当前位置和下一站的剩余点集合 - //计算剩余点总里程和时间 - if (mTwoStationsRouts.size() == 0){ - calculateTwoStationsRoute(); - } - if (mTwoStationsRouts.size() > 0 && mLocation != null){ - Map> lastPointsMap = CoordinateCalculateRouteUtil - .getRemainPointListByCompareNew(mPreRouteIndex,mTwoStationsRouts,mLocation); - for (int index: lastPointsMap.keySet()) { - mPreRouteIndex = index; - break; - } - - for (List lastPoints: lastPointsMap.values()){ - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==lastPoints.size() = " + lastPoints.size()); - float lastSumLength = 0; - if (lastPoints.size() == 1){ //只是最后一个点,计算当前位置和最后一个点的距离 - if (mNextStationIndex <= mStations.size()-1 && mNextStationIndex >= 0){ - BusPassengerStation stationNext = mStations.get(mNextStationIndex); - lastSumLength = CoordinateUtils.calculateLineDistance( - stationNext.getGcjLon(), stationNext.getGcjLat(), - mLocation.getLongitude(), mLocation.getLatitude()); - }else { - lastSumLength = CoordinateUtils.calculateLineDistance( - lastPoints.get(0).getLongitude(), lastPoints.get(0).getLatitude(), - mLocation.getLongitude(), mLocation.getLatitude()); - } - - }else { - lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(lastPoints); - } - - double lastTime = lastSumLength / getAverageSpeed() * 3.6 ; //秒 - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==lastSumLength = " + lastSumLength); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.routePlanningToNextStationChanged((long)lastSumLength,(long) lastTime); - } - } - } - } - - public int getAverageSpeed(){ - return BusPassengerConst.BUS_AVERAGE_SPEED; - } - - public void startRemainRouteInfo() { - //开启实时计算剩余距离,剩余时间,预计时间 - startOrStopCalculateRouteInfo(true); - } - - public void startToRouteAndWipe() { - startOrStopRouteAndWipe(true); - } - - /** - * 实时轨迹擦除 - * @param isStart - */ - public void startOrStopRouteAndWipe(boolean isStart){ - if (isStart){ - BusPassengerModelLoopManager.getInstance().startOrStopRouteAndWipe(); - }else { - mWipePreIndex = 0; - BusPassengerModelLoopManager.getInstance().stopOrStopRouteAndWipe(); - } - } - - public void loopRouteAndWipe() { - if (mRoutePoints != null && mRoutePoints.size() > 0 && mLocation != null){ - int haveArrivedIndex = CoordinateCalculateRouteUtil - .getArrivedPointIndexNew(mWipePreIndex, - mRoutePoints, - mLocation); - - mWipePreIndex = haveArrivedIndex; - - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "thread = "+ Thread.currentThread().getName()+" haveArrivedIndex== " + haveArrivedIndex); - if (mAutopilotPlanningCallback != null){ - List routePoints = CoordinateCalculateRouteUtil - .coordinateConverterLocationToLatLng(mContext,mRoutePoints); - mAutopilotPlanningCallback.routeResult(routePoints,haveArrivedIndex); - } - } - } - - /** - * 开始轮询计算剩余里程和时间 - * @param isStart - */ - public void startOrStopCalculateRouteInfo(boolean isStart) { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "startOrStopCalculateRouteInfo() " + isStart); - if (isStart) { - BusPassengerModelLoopManager.getInstance().startCalculateRouteInfoLoop(); - } else { - mTwoStationsRouts.clear(); - BusPassengerModelLoopManager.getInstance().stopCalculateRouteInfLoop(); - } - } - - private void startOrStopOrderLoop(boolean start) { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "startOrStopOrderLoop() " + start); - if (start) { - BusPassengerModelLoopManager.getInstance().startQueryDriverLineLoop(); - } else { - BusPassengerModelLoopManager.getInstance().stopQueryDriverLineLoop(); - } - } - -} diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.kt b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.kt new file mode 100644 index 0000000000..8a3c91eb77 --- /dev/null +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.kt @@ -0,0 +1,607 @@ +package com.mogo.och.bus.passenger.model + +import android.annotation.SuppressLint +import android.content.Context +import android.net.ConnectivityManager +import android.os.Handler +import com.amap.api.maps.model.LatLng +import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager +import com.mogo.commons.debug.DebugConfig +import com.mogo.commons.module.intent.IMogoIntentListener +import com.mogo.commons.module.intent.IntentManager +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.data.autopilot.AutopilotControlParameters +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLine +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLonLat +import com.mogo.eagle.core.data.config.FunctionBuildConfig +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener +import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.updateAutopilotControlParameters +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager.addListener +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager +import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager +import com.mogo.eagle.core.network.utils.GsonUtil +import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils.isPassenger +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr +import com.mogo.eagle.core.utilcode.util.GsonUtils +import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.bean.BusPassengerOperationStatusResponse +import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResponse +import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResult +import com.mogo.och.bus.passenger.bean.BusPassengerStation +import com.mogo.och.bus.passenger.callback.IBusPassegerDriverStatusCallback +import com.mogo.och.bus.passenger.callback.IBusPassengerADASStatusCallback +import com.mogo.och.bus.passenger.callback.IBusPassengerAutopilotPlanningCallback +import com.mogo.och.bus.passenger.callback.IBusPassengerControllerStatusCallback +import com.mogo.och.bus.passenger.callback.IBusPassengerRouteLineInfoCallback +import com.mogo.och.bus.passenger.constant.BusPassengerConst +import com.mogo.och.bus.passenger.network.BusPassengerModelLoopManager +import com.mogo.och.bus.passenger.network.BusPassengerServiceManager +import com.mogo.och.bus.passenger.network.BusPassengerServiceManager.driverAppSn +import com.mogo.och.common.module.bean.dpmsg.AppConnectMsg +import com.mogo.och.common.module.bean.dpmsg.BaseDPMsg +import com.mogo.och.common.module.bean.dpmsg.DPMsgType +import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager +import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager.pushAppOperationalMsgBox +import com.mogo.och.common.module.biz.constant.OchCommonConst +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback +import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager.startLoopAbnormalFactors +import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager.stopLoopAbnormalFactors +import com.mogo.och.common.module.manager.distancemamager.IDistanceListener +import com.mogo.och.common.module.manager.distancemamager.ITrajectoryListener +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager.addDistanceListener +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager.addTrajectoryListener +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager.setStationPoint +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager.suspendCalculate +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil.calculateRouteSumLength +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil.coordinateConverterWgsToGcjLocations +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil.getArrivedPointIndexNew +import com.mogo.och.common.module.utils.DateTimeUtil +import com.mogo.och.common.module.utils.PinYinUtil +import mogo.telematics.pad.MessagePad +import mogo.telematics.pad.MessagePad.ArrivalNotification +import mogo.telematics.pad.MessagePad.GlobalPathResp +import system_master.SystemStatusInfo +import java.util.concurrent.ConcurrentHashMap + +/** + * Created on 2022/3/31 + */ +@SuppressLint("StaticFieldLeak") +object BusPassengerModel{ + + private val TAG = BusPassengerModel::class.java.simpleName + private const val MSG_QUERY_BUS_P_STATION = 1001 + + private val mRoutePoints: MutableList = ArrayList() + + private var mContext: Context? = null + private var mADASStatusCallback //Model->Presenter:自动驾驶状态相关 + : IBusPassengerADASStatusCallback? = null + private var mAutopilotPlanningCallback //Model->Presenter:自动驾驶线路规划 + : IBusPassengerAutopilotPlanningCallback? = null + private val mControllerStatusCallbackMap: MutableMap = + ConcurrentHashMap() + private var mDriverStatusCallback //出车收车状态 + : IBusPassegerDriverStatusCallback? = null + private var mRouteLineInfoCallback // bus路线信息更新 + : IBusPassengerRouteLineInfoCallback? = null + private var mLocation: MogoLocation? = null + private var routesResult: BusPassengerRoutesResult? = null + var mStations: MutableList = ArrayList() + private var mNextStationIndex = 0 // 要到达站的index + private val mTwoStationsRouts: MutableList = ArrayList() + private val handler = Handler(Handler.Callback { msg -> + if (msg.what == MSG_QUERY_BUS_P_STATION) { + queryDriverOperationStatus() + return@Callback true + } + false + }) + + fun init(context: Context) { + mContext = context.applicationContext + initListeners() + // TODO: 2022/3/31 + queryDriverOperationStatus() + startOrStopOrderLoop(true) + } + + fun setDriverStatusCallback(callback: IBusPassegerDriverStatusCallback?) { + mDriverStatusCallback = callback + } + + fun setRouteLineInfoCallback(callback: IBusPassengerRouteLineInfoCallback?) { + mRouteLineInfoCallback = callback + } + + private fun queryDriverOperationDelay() { + handler.sendEmptyMessageDelayed( + MSG_QUERY_BUS_P_STATION, + BusPassengerConst.QUERY_BUS_P_STATION_DELAY + ) + } + + private fun queryDriverOperationStatus() { + BusPassengerServiceManager.queryDriverOperationStatus( + mContext!!, object : OchCommonServiceCallback { + override fun onSuccess(data: BusPassengerOperationStatusResponse?) { + if (data?.data == null) return + if (mDriverStatusCallback != null) { + d( + M_BUS_P + TAG, + "queryDriverOperationStatus = %s", + data.data.plateNumber + ) + mDriverStatusCallback!!.changeOperationStatus(data.data.driverStatus == 1) + mDriverStatusCallback!!.updatePlateNumber(data.data.plateNumber) + } + } + + override fun onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext!!.getString(R.string.network_error_tip)) + } else { + ToastUtils.showShort(mContext!!.getString(R.string.request_error_tip)) + } + queryDriverOperationDelay() + } + + override fun onFail(code: Int, msg: String) { + //延迟3s再次查询 + queryDriverOperationDelay() + } + }) + } + + fun queryDriverSiteByCoordinate() { + BusPassengerServiceManager.queryDriverSiteByCoordinate( + mContext!!, object : OchCommonServiceCallback { + override fun onSuccess(data: BusPassengerRoutesResponse) { + if (data.result == null) { + d(M_BUS_P + TAG, "order = queryDriverSiteByCoordinate = null") + if (routesResult != null) { + routesResult = null + mNextStationIndex = 0 + } + cleanStation() + if (mRouteLineInfoCallback != null) { + mRouteLineInfoCallback!!.showNoTaskView() + } + mRoutePoints.clear() + return + } + if (routesResult != null && data.result == routesResult) { + d(M_BUS_P + TAG, "order = queryDriverSiteByCoordinate = not update") + return + } + routesResult = data.result + updatePassengerRouteInfo(data.result) + } + + override fun onFail(code: Int, msg: String) { + d( + M_BUS_P + TAG, "queryDriverSiteByCoordinate = %s", msg + + ", sn = " + driverAppSn + ) + if (code == 1003) { + queryDriverOperationDelay() + } + if (driverAppSn.isEmpty()) { + //此处拦截是为了防止过程中乘客屏和司机端断连,拿不到司机端sn, 造成请求失败去刷新了界面 + return + } + if (code == 1003) { + routesResult = null + cleanStation() + return + } + } + }) + } + + private fun updatePassengerRouteInfo(result: BusPassengerRoutesResult) { + if (mRouteLineInfoCallback != null) { + Logger.d(M_BUS_P + TAG, "order = BusPassengerRoutesResult= " +GsonUtil.jsonFromObject(result)) + mRouteLineInfoCallback!!.updateLineInfo(result.name, result.runningDur) + mRouteLineInfoCallback!!.hideNoTaskView() + if (result.sites != null) { + val stations = result.sites + mStations.clear() + mStations.addAll(stations) + for (i in stations.indices) { + val station = stations[i] + if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && station.isLeaving && i + 1 < stations.size) { //离站 + Logger.d(M_BUS_P + TAG, "order = station= leave") + mRouteLineInfoCallback!!.updateStationsInfo(stations, i + 1, false) + if (mNextStationIndex != i + 1) { + mTwoStationsRouts.clear() + val startStation = mStations[i] + val endStation = mStations[i + 1] + setTrajectoryStation(startStation, endStation, result.lineId) + } + mNextStationIndex = i + 1 + updateAutopilotControlParameters(result, i) + return + } else if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !station.isLeaving) { //到站 + if (i == stations.size - 1) { + cleanStation() + } + suspendCalculate() + + Logger.d(M_BUS_P + TAG, "order = station= arrive") + + mRouteLineInfoCallback!!.updateStationsInfo(stations, i, true) + clearAutopilotControlParameters() + return + } + } + } + } + } + + private fun updateAutopilotControlParameters( + busRoutesResult: BusPassengerRoutesResult, + leaveIndex: Int + ) { + val parameters = initAutopilotControlParameters(busRoutesResult, leaveIndex) + if (null == parameters) { + e(M_BUS_P + TAG, "AutopilotControlParameters is empty.") + return + } + d(M_BUS_P + TAG, "AutopilotControlParameters is update.") + updateAutopilotControlParameters(parameters) + } + + private fun clearAutopilotControlParameters() { + d(M_BUS_P + TAG, "AutopilotControlParameters is clear.") + updateAutopilotControlParameters(null) + } + + private fun initAutopilotControlParameters( + busRoutesResult: BusPassengerRoutesResult, + leaveIndex: Int + ): AutopilotControlParameters? { + if (busRoutesResult.sites == null) { + return null + } + val stations = busRoutesResult.sites + if (leaveIndex + 1 > stations.size - 1) { + e(M_BUS_P + TAG, "行程日志-mismatch condition1.") + return null + } + val currentStation = stations[leaveIndex] + val nextStation = stations[leaveIndex + 1] + val parameters = AutopilotControlParameters() + parameters.routeID = busRoutesResult.lineId + parameters.routeName = busRoutesResult.name + parameters.startName = PinYinUtil.getPinYinHeadChar(currentStation.name) + parameters.endName = PinYinUtil.getPinYinHeadChar(nextStation.name) + parameters.startLatLon = AutoPilotLonLat(currentStation.lat, currentStation.lon) + parameters.endLatLon = AutoPilotLonLat(nextStation.lat, nextStation.lon) + parameters.vehicleType = 10 + if (parameters.autoPilotLine == null) { + parameters.autoPilotLine = AutoPilotLine( + busRoutesResult.lineId.toLong(), + busRoutesResult.csvFileUrl, busRoutesResult.csvFileMd5, + busRoutesResult.txtFileUrl, busRoutesResult.txtFileMd5, + busRoutesResult.contrailSaveTime, busRoutesResult.carModel, + busRoutesResult.csvFileUrlDPQP, busRoutesResult.csvFileMd5DPQP, + busRoutesResult.txtFileUrlDPQP, busRoutesResult.txtFileMd5DPQP, + busRoutesResult.contrailSaveTimeDPQP + ) + } + return parameters + } + + fun release() { + releaseListeners() + cleanStation() + startOrStopOrderLoop(false) + } + + fun setMoGoAutopilotPlanningListener(moGoAutopilotPlanningCallback: IBusPassengerAutopilotPlanningCallback?) { + mAutopilotPlanningCallback = moGoAutopilotPlanningCallback + } + + fun setADASStatusCallback(callback: IBusPassengerADASStatusCallback?) { + mADASStatusCallback = callback + } + + fun setControllerStatusCallback( + tag: String?, + callback: IBusPassengerControllerStatusCallback? + ) { + if (tag == null || "" == tag) return + if (callback == null) { + mControllerStatusCallbackMap.remove(tag) + return + } + mControllerStatusCallbackMap[tag] = callback + } + + private fun initListeners() { + + // 2021.11.1重构自动驾驶 实现接口 IMoGoAutopilotStatusListener 注册监听 替换IMogoAdasOCHCallback接口 + CallerAutoPilotStatusListenerManager.addListener(TAG, mGoAutopilotStatusListener) + IntentManager.getInstance() + .registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener) + MogoStatusManager.getInstance().registerStatusChangedListener( + TAG, + StatusDescriptor.VR_MODE, + mMogoStatusChangedListener + ) + // 定位监听 + addListener(TAG, 10, mMapLocationListener) + + //2021.11.1 自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.addListener(TAG, moGoAutopilotPlanningListener) + + //监听司机端消息 + CallerTelematicListenerManager.addListener(TAG, mReceivedMsgListener) + startLoopAbnormalFactors(mContext!!) + addDistanceListener(TAG, distanceListener) + addTrajectoryListener(TAG, trajectoryListener) + } + + private fun releaseListeners() { + MogoStatusManager.getInstance().unregisterStatusChangedListener( + TAG, + StatusDescriptor.VR_MODE, + mMogoStatusChangedListener + ) + + // 注销定位监听 + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + MogoAiCloudSocketManager.getInstance(mContext) + .unregisterLifecycleListener(10010) + CallerAutoPilotStatusListenerManager.removeListener(mGoAutopilotStatusListener) + CallerPlanningRottingListenerManager.removeListener(moGoAutopilotPlanningListener) + CallerTelematicListenerManager.removeListener(TAG) + stopLoopAbnormalFactors() + } + + private val distanceListener: IDistanceListener = object : IDistanceListener { + override fun distanceCallback(distance: Float) { + val lastTime: Double = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6 //秒 + d(M_BUS_P + TAG, "轨迹排查==lastSumLength = $distance") + for (site in routesResult!!.sites) { + if (site.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !site.isLeaving) { + return + } + } + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback!!.routePlanningToNextStationChanged( + distance.toLong(), + lastTime.toLong() + ) + } + } + } + private val trajectoryListener: ITrajectoryListener = + object : ITrajectoryListener { + override fun trajectoryCallback( + routeArrivied: MutableList, + routeArriving: MutableList, + location: MogoLocation + ) { + if (mAutopilotPlanningCallback != null) { + val routeArriviedTemp: MutableList = ArrayList() + val routeArrivingTemp: MutableList = ArrayList() + var temp: LatLng + for (mogoLocation in routeArrivied) { + temp = LatLng(mogoLocation.latitude, mogoLocation.longitude) + routeArriviedTemp.add(temp) + } + for (mogoLocation in routeArriving) { + temp = LatLng(mogoLocation.latitude, mogoLocation.longitude) + routeArrivingTemp.add(temp) + } + mAutopilotPlanningCallback!!.routeResult( + routeArriviedTemp, + routeArrivingTemp, + location + ) + } + } + } + private val mReceivedMsgListener: IReceivedMsgListener = object : IReceivedMsgListener { + override fun onReceivedServerSn(sn: String?) { + Logger.d(M_BUS_P + TAG, "onReceivedServerSn = $sn") + if (mDriverStatusCallback != null) { + mDriverStatusCallback!!.updateDriverSn(sn) + } + } + + override fun onReceivedMsg(type: Int, byteArray: ByteArray) { + if (OchCommonConst.BUSINESS_STRING == type) { + val baseMsg = GsonUtils.fromJson(String(byteArray), BaseDPMsg::class.java) + Logger.d( + M_BUS_P + TAG, + "onReceivedMsg = " + GsonUtils.toJson(baseMsg) + ) + if (baseMsg != null && baseMsg.type == DPMsgType.TYPE_COMMON.type) { + val (isViewShow, _, msg1) = GsonUtils.fromJson( + String(byteArray), + AppConnectMsg::class.java + ) + if (isViewShow) { //消息盒子显示内容 + pushAppOperationalMsgBox( + DateTimeUtil.getCurrentTimeStamp(), msg1, + OCHSocketMessageManager.OPERATION_SYSTEM + ) + } + } + } + } + } + + //监听网络变化,避免启动机器时无网导致无法更新订单信息 + private val mNetWorkIntentListener = IMogoIntentListener { intentStr, intent -> + d(M_BUS_P + TAG, "onIntentReceived = %s", intentStr) + if (ConnectivityManager.CONNECTIVITY_ACTION == intentStr) { + if (NetworkUtils.isConnected(mContext)) { + queryDriverOperationStatus() + } + } + } + + // VR mode变更回调 + private val mMogoStatusChangedListener = + IMogoStatusChangedListener { descriptor: StatusDescriptor, isTrue: Boolean -> + if (StatusDescriptor.VR_MODE == descriptor) { + if (mControllerStatusCallbackMap.isNotEmpty()) { + for (callback in mControllerStatusCallbackMap.values) { + callback.onVRModeChanged(isTrue) + } + } + } + } + private val mMapLocationListener: IMoGoChassisLocationGCJ02Listener = + object : IMoGoChassisLocationGCJ02Listener { + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (null == mogoLocation) return + mLocation = mogoLocation + for (callback in mControllerStatusCallbackMap.values) { + callback.onCarLocationChanged(mogoLocation) + } + } + } + private val mGoAutopilotStatusListener: IMoGoAutopilotStatusListener = + object : IMoGoAutopilotStatusListener { + private var arriveAtEnd = false //乘客app专用字段 + override fun onAutopilotStatusResponse(state: Int) { + if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + if (mADASStatusCallback != null) mADASStatusCallback!!.onAutopilotRunning() + } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { + mTwoStationsRouts.clear() + if (mADASStatusCallback != null) mADASStatusCallback!!.onAutopilotEnable() + } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { + mTwoStationsRouts.clear() + if (mADASStatusCallback != null) mADASStatusCallback!!.onAutopilotDisable() + } else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) { + mTwoStationsRouts.clear() + if (mADASStatusCallback != null) mADASStatusCallback!!.onAutopilotRunning() + } + } + override fun onAutopilotArriveAtStation(arrivalNotification: ArrivalNotification?) { + if (FunctionBuildConfig.isDemoMode + && isPassenger(FunctionBuildConfig.appIdentityMode) + ) { + arriveAtEnd = true + } + + // TODO: 2022/3/31 + if (DebugConfig.isDebug()) { + // ToastUtils.showShort("到达目的地"); + } + if (mADASStatusCallback != null) { + mADASStatusCallback!!.onAutopilotArriveEnd() + } + } + + override fun onAutopilotStatusRespByQuery(status: SystemStatusInfo.StatusInfo) {} + } + private val moGoAutopilotPlanningListener: IMoGoPlanningRottingListener = + object : IMoGoPlanningRottingListener { + override fun onAutopilotRotting(globalPathResp: GlobalPathResp?) { + globalPathResp?.wayPointsList?.let { + if (it.size > 0) { + d(M_BUS_P + TAG, "收到轨迹:${it.size}--第一个点${it[0]}--最后一个点:${it.last()}") + updateRoutePoints(it) + } + } + } + } + + fun updateRoutePoints(routePoints: List) { + mRoutePoints.clear() + val latLngModels: List = coordinateConverterWgsToGcjLocations(mContext, routePoints) + mRoutePoints.addAll(latLngModels) + calculateTwoStationsRoute() + } + + private fun calculateTwoStationsRoute() { + //找出前往站对应的轨迹点,拿出两站点的集合 + d(M_BUS_P + TAG, "mRoutePoints.size() = " + mRoutePoints.size) + if (mRoutePoints.size > 0) { + if (mStations.size > 1) { //两个站点及以上要计算两个站点间的轨迹路线 + if (mNextStationIndex <= mStations.size - 1 && mNextStationIndex - 1 >= 0) { + mTwoStationsRouts.clear() + val stationNext = mStations[mNextStationIndex] + val stationCur = mStations[mNextStationIndex - 1] + //当前站在轨迹中对应的点 + val currentRouteIndex = getArrivedPointIndexNew( + 0, mRoutePoints, stationCur.gcjLon, stationCur.gcjLat + ) + //要前往的站在轨迹中对应的点 + val nextRouteIndex = getArrivedPointIndexNew( + currentRouteIndex, mRoutePoints, stationNext.gcjLon, stationNext.gcjLat + ) + d( + M_BUS_P + TAG, + "轨迹排查==currentRouteIndex = " + currentRouteIndex + + ", nextRouteIndex = " + nextRouteIndex + ) + if (currentRouteIndex < nextRouteIndex) { //如果找到的next在起点的轨迹前面,直接舍弃这个轨迹,不显示 + mTwoStationsRouts.addAll( + mRoutePoints.subList( + currentRouteIndex, + nextRouteIndex + 1 + ) + ) + } + } + } + if (mTwoStationsRouts.size > 0) { + val sumLength = calculateRouteSumLength(mTwoStationsRouts) + SharedPrefsMgr.getInstance(mContext!!) + .putInt(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS, sumLength.toInt()) + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback!!.updateTotalDistance() + } + } + } + } + + private fun startOrStopOrderLoop(start: Boolean) { + d(M_BUS_P + TAG, "startOrStopOrderLoop() $start") + if (start) { + BusPassengerModelLoopManager.getInstance().startQueryDriverLineLoop() + } else { + BusPassengerModelLoopManager.getInstance().stopQueryDriverLineLoop() + } + } + + private fun setTrajectoryStation( + startStationInfo: BusPassengerStation, + endStationInfo: BusPassengerStation, + lineId: Int + ) { + val startStation = MogoLocation() + startStation.longitude = startStationInfo.gcjLon + startStation.latitude = startStationInfo.gcjLat + val endStation = MogoLocation() + endStation.longitude = endStationInfo.gcjLon + endStation.latitude = endStationInfo.gcjLat + setStationPoint(startStation, endStation, lineId.toLong()) + } + + fun cleanStation() { + setStationPoint(null, null, -1L) + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java index c0d1db411d..2c7963cf07 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java @@ -37,45 +37,6 @@ public class BusPassengerModelLoopManager { } private Disposable mQueryLineDisposable; //心跳轮询 - private CompositeDisposable mRouteWipeDisposable; - private CompositeDisposable mCalculateRouteDisposable; //每隔2s计算一次剩余里程和时间 - - public void startOrStopRouteAndWipe() { - CallerLogger.INSTANCE.i(M_BUS_P + TAG, "startOrStopRouteWipe()"); - if (mRouteWipeDisposable != null) return; - if (mRouteWipeDisposable == null){ - mRouteWipeDisposable = new CompositeDisposable(); - } - Disposable disposable = startLoopRouteAndWipe() - .doOnSubscribe(new Consumer() { - @Override - public void accept(Disposable disposable) throws Exception { - } - }) - .doOnError(new Consumer() { - @Override - public void accept(Throwable throwable) throws Exception { - } - }) - .delay(LOOP_LINE_1S, TimeUnit.MILLISECONDS, true) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 - .subscribeOn(Schedulers.io()) - .repeat() // repeat保证请求成功后能够重新订阅。 - .retry() // retry保证请求失败后能重新订阅 - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { - @Override - public void accept(Integer integer) throws Exception { - } - }); - mRouteWipeDisposable.add(disposable); - } - - public void stopOrStopRouteAndWipe() { - if (mRouteWipeDisposable != null) { - mRouteWipeDisposable.dispose(); - mRouteWipeDisposable = null; - } - } public void startQueryDriverLineLoop() { if (mQueryLineDisposable != null && !mQueryLineDisposable.isDisposed()) { @@ -87,7 +48,7 @@ public class BusPassengerModelLoopManager { .map((aLong -> aLong + 1)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(aLong -> BusPassengerModel.getInstance().queryDriverSiteByCoordinate()); + .subscribe(aLong -> BusPassengerModel.INSTANCE.queryDriverSiteByCoordinate()); } public void stopQueryDriverLineLoop() { @@ -98,63 +59,4 @@ public class BusPassengerModelLoopManager { } } - public void startCalculateRouteInfoLoop() { - CallerLogger.INSTANCE.i(M_BUS_P + TAG, "startCalculateRouteInfoLoop()"); - if (mCalculateRouteDisposable != null) return; - if (mCalculateRouteDisposable == null){ - mCalculateRouteDisposable = new CompositeDisposable(); - } - Disposable disposable = startLoopCalculateRouteInfo() - .doOnSubscribe(new Consumer() { - @Override - public void accept(Disposable disposable) throws Exception { - } - }) - .doOnError(new Consumer() { - @Override - public void accept(Throwable throwable) throws Exception { - } - }) - .delay(LOOP_LINE_2S, TimeUnit.MILLISECONDS, true) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 - .subscribeOn(Schedulers.io()) - .repeat() // repeat保证请求成功后能够重新订阅。 - .retry() // retry保证请求失败后能重新订阅 - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { - @Override - public void accept(Integer integer) throws Exception { - } - }); - mCalculateRouteDisposable.add(disposable); - } - - public void stopCalculateRouteInfLoop() { - if (mCalculateRouteDisposable != null) { - CallerLogger.INSTANCE.i(M_BUS_P + TAG, "stopCalculateRouteInfLoop()"); - mCalculateRouteDisposable.dispose(); - mCalculateRouteDisposable = null; - } - } - - private Observable startLoopRouteAndWipe(){ - return Observable.create(new ObservableOnSubscribe() { - @Override - public void subscribe(ObservableEmitter emitter) throws Exception { - if (emitter.isDisposed()) return; - BusPassengerModel.getInstance().loopRouteAndWipe(); - emitter.onComplete(); - } - }); - } - - private Observable startLoopCalculateRouteInfo(){ - return Observable.create(new ObservableOnSubscribe() { - @Override - public void subscribe(ObservableEmitter emitter) throws Exception { - if (emitter.isDisposed()) return; - BusPassengerModel.getInstance().dynamicCalculateRouteInfo(); - emitter.onComplete(); - } - }); - } } diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java index 20bfc21db5..a448c2cd36 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java @@ -35,7 +35,7 @@ public class BaseBusPassengerPresenter extends Presenter models, int haveArrivedIndex) { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "routeResult:" + models.size() - + " haveArrivedIndex = "+haveArrivedIndex); - runOnUIThread(() ->mView.routeResult(models,haveArrivedIndex)); + public void routeResult(List routeArrivied,List routeArriving,MogoLocation location) { + runOnUIThread(() ->mView.routeResult(routeArrivied,routeArriving,location)); } @Override diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java index 4eafc8271c..c3a0911815 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java @@ -15,7 +15,9 @@ import com.mogo.commons.mvp.Presenter; import com.mogo.eagle.core.data.multidisplay.TelematicConstant; import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener; import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager; +import com.mogo.eagle.core.function.hmi.ui.widget.RomaPassengerView; import com.mogo.eagle.core.function.view.MapBizView; +import com.mogo.eagle.core.utilcode.util.DeviceUtils; import com.mogo.och.bus.passenger.R; /** @@ -28,6 +30,7 @@ public abstract class BusPassengerBaseFragment openOrCloseLiveVideo()); CallerTelematicListenerManager.INSTANCE.addListener(TAG, new IReceivedMsgListener() { @Override diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java deleted file mode 100644 index 6f8411205b..0000000000 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java +++ /dev/null @@ -1,352 +0,0 @@ -package com.mogo.och.bus.passenger.ui; - -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; - -import android.content.Context; -import android.os.Bundle; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.widget.RelativeLayout; - -import androidx.annotation.Nullable; - -import com.amap.api.maps.AMap; -import com.amap.api.maps.CameraUpdate; -import com.amap.api.maps.CameraUpdateFactory; -import com.amap.api.maps.TextureMapView; -import com.amap.api.maps.UiSettings; -import com.amap.api.maps.model.BitmapDescriptor; -import com.amap.api.maps.model.BitmapDescriptorFactory; -import com.amap.api.maps.model.CameraPosition; -import com.amap.api.maps.model.CustomMapStyleOptions; -import com.amap.api.maps.model.LatLng; -import com.amap.api.maps.model.LatLngBounds; -import com.amap.api.maps.model.Marker; -import com.amap.api.maps.model.MarkerOptions; -import com.amap.api.maps.model.Polyline; -import com.amap.api.maps.model.PolylineOptions; -import com.mogo.eagle.core.data.map.MogoLocation; -import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; -import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; -import com.mogo.och.bus.passenger.R; -import com.mogo.och.bus.passenger.callback.IBusPassengerMapViewCallback; -import com.mogo.och.bus.passenger.utils.BusPassengerMapAssetStyleUtil; - -import java.util.ArrayList; -import java.util.List; - -/** - * 乘客屏小地图 - */ -public class BusPassengerMapDirectionView - extends RelativeLayout - implements IMoGoChassisLocationGCJ02Listener, - IBusPassengerMapDirectionView, - AMap.OnCameraChangeListener { - - //小地图名称 - public static final String TAG = "TPMapDirectionView"; - - private TextureMapView mAMapNaviView; - private AMap mAMap; - private Marker mCarMarker; - - private List mCoordinatesLatLng = new ArrayList<>(); //轨迹坐标数据 - private List mLineStationLatLng = new ArrayList<>();//站点坐标数据 - private Polyline mPolyline; - private CameraUpdate mCameraUpdate; - private Context mContext; - - List textureList = new ArrayList<>(); - List texIndexList = new ArrayList<>(); - private int mHaveArrivedIndex = 0; - - private List mLineMarkers = new ArrayList<>(); - -// private IBusPassengerMapViewCallback mIBusPassengerMapViewCallback; - private BitmapDescriptor mArrivedRes; - private BitmapDescriptor mUnArrivedRes; - - public BusPassengerMapDirectionView(Context context) { - this(context, null); - } - - public BusPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public BusPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - try { - initView(context); - } catch (Exception e) { - e.printStackTrace(); - } - } - -// public void setTaxiPassengerMapViewCallback(IBusPassengerMapViewCallback iBusPassengerMapViewCallback) { -// this.mIBusPassengerMapViewCallback = iBusPassengerMapViewCallback; -// } - - private void initView(Context context) { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "initView"); - - mContext = context; - - View smpView = LayoutInflater.from(context).inflate(R.layout.bus_p_map_view, this); - - mAMapNaviView = (TextureMapView) smpView.findViewById(R.id.bus_p_line_amap_view); - - initAMapView(); - - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, this); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); - } - - private void initAMapView() { -// mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel); - mAMap = mAMapNaviView.getMap(); - // 设置导航地图模式,aMap是地图控制器对象。 - mAMap.setMapType(AMap.MAP_TYPE_NIGHT); - - // 关闭显示实时路况图层,aMap是地图控制器对象。 - mAMap.setTrafficEnabled(false); - - // 设置 锚点 图标 - mCarMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_car)) - .anchor(0.5f, 0.5f)); - - mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_arrived); - mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_un_arrive); - - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(BusPassengerMapAssetStyleUtil.getAssetsStyle(getContext(), "map_style.data")) - .setStyleExtraData(BusPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(), "map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - - //设置希望展示的地图缩放级别 -// mAMap.moveCamera(mCameraUpdate); - - // 设置地图的样式 - UiSettings uiSettings = mAMap.getUiSettings(); - uiSettings.setZoomControlsEnabled(false);// 地图缩放级别的交换按钮 - uiSettings.setAllGesturesEnabled(false);// 所有手势 - uiSettings.setMyLocationButtonEnabled(false); // 显示默认的定位按钮 - uiSettings.setLogoBottomMargin(-150); //设置Logo下边界距离屏幕底部的边距,设置为负值即可 - - mAMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() { - @Override - public void onMapLoaded() { - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "smp---onMapLoaded"); - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(BusPassengerMapAssetStyleUtil.getAssetsStyle(getContext(), "map_style.data")) - .setStyleExtraData(BusPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(), "map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - mAMapNaviView.getMap().setPointToCenter(mAMapNaviView.getWidth() / 2, mAMapNaviView.getHeight() / 2); - } - }); - - //设置地图状态的监听接口 - mAMap.setOnCameraChangeListener(this); - } - - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return true; - } - - @Override - public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { - if (gnssInfo == null) { - return; - } -// CallerLogger.INSTANCE.d(M_BUS_P + TAG, "onCarLocationChanged2 :" + location.getLatitude() + ":" + location.getLongitude()); - LatLng currentLatLng = new LatLng(gnssInfo.getLatitude(), gnssInfo.getLongitude()); - - //更新车辆位置 - if (mCarMarker != null) { -// CallerLogger.INSTANCE.d(M_BUS_P + TAG, "location.getBearing() = " + location.getBearing()); - mCarMarker.setRotateAngle((float) (360 - gnssInfo.getHeading())); - mCarMarker.setPosition(currentLatLng); - mCarMarker.setToTop(); - } - - try { - - //圈定地图显示范围 - LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); - - if (mCoordinatesLatLng.size() > 0){ - //存放经纬度 - for (int i = 0; i < mCoordinatesLatLng.size(); i++) { - boundsBuilder.include(mCoordinatesLatLng.get(i)); - } - //第二个参数为四周留空宽度 - }else if (mLineStationLatLng.size() > 0){ - for (int i = 0; i< mLineStationLatLng.size();i++){ - boundsBuilder.include(mLineStationLatLng.get(i)); - } - } - - boundsBuilder.include(currentLatLng); - mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(),100,100,100,100)); - - }catch (Exception e){ - - } - } - - - @Override - public void drawablePolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - if (mAMap != null) { - - addRouteColorList(); - CallerLogger.INSTANCE.d(M_BUS_P + TAG, "mLinePointsLatLng.size() = " +mLineStationLatLng.size() - +" mCoordinatesLatLng.size()= " + mCoordinatesLatLng.size()); - if (mLineStationLatLng.size() >= 2 && mCoordinatesLatLng.size() > 2) { - //设置线段纹理 - PolylineOptions polylineOptions = new PolylineOptions(); - polylineOptions.addAll(mCoordinatesLatLng); - polylineOptions.width(14); //线段宽度 - polylineOptions.setUseTexture(true); - polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound); - polylineOptions.setCustomTextureList(textureList); - polylineOptions.setCustomTextureIndex(texIndexList); -// polylineOptions.colorValues(colorList); -// polylineOptions.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow)); - - // 绘制线 - mPolyline = mAMap.addPolyline(polylineOptions); - - } - } - } - - /** - * 添加画线颜色值 - */ - private void addRouteColorList() { - textureList.clear(); - texIndexList.clear(); - for (int i = 0; i < mCoordinatesLatLng.size(); i++){ - if (i <= mHaveArrivedIndex){ - textureList.add(mArrivedRes); - }else { - textureList.add(mUnArrivedRes); - } - texIndexList.add(i); - } - } - - @Override - public void clearPolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - } - - @Override - public void setLineMarker() { - - } - - public void clearCoordinatesLatLng(){ - textureList.clear(); - texIndexList.clear(); - mCoordinatesLatLng.clear(); - mLineStationLatLng.clear(); - CallerLogger.INSTANCE.d(M_BUS_P + TAG, " mCoordinatesLatLng.clear " ); - } - - public void onCreateView(Bundle savedInstanceState) { - if (mAMapNaviView != null) { - mAMapNaviView.onCreate(savedInstanceState); - } - } - - public void onResume() { - if (mAMapNaviView != null) { - mAMapNaviView.onResume(); - } - } - - public void onPause() { - if (mAMapNaviView != null) { - mAMapNaviView.onPause(); - } - } - - public void onDestroy() { - if (mAMapNaviView != null) { - mAMapNaviView.onDestroy(); - } - } - - public void setCoordinatesLatLng(List latLngs,int haveArrivedIndex) { - mCoordinatesLatLng.clear(); - mCoordinatesLatLng.addAll(latLngs); - mHaveArrivedIndex = haveArrivedIndex; - } - - public void clearLineMarkers(){ - for (int i =0; i< mLineMarkers.size();i++){ - mLineMarkers.get(i).setVisible(false); - mLineMarkers.get(i).remove(); - } - mLineMarkers.clear(); - } - - public void setLinePointMarkerAndDraw(List mLineStationsList, int currentIndex) { - clearLineMarkers(); - mLineStationLatLng.clear(); - mLineStationLatLng.addAll(mLineStationsList); - - if (mLineStationsList.size() > 0){ - for (int i = 0; i < mLineStationsList.size(); i++) { - if (currentIndex == i){ - Marker mEndMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_end_point))); - mEndMarker.setPosition(mLineStationsList.get(i)); - mLineMarkers.add(i,mEndMarker); - }else { - Marker mStartMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_way_point))); - mStartMarker.setPosition(mLineStationsList.get(i)); - mLineMarkers.add(i,mStartMarker); - } - } - } - } - - @Override - public void onCameraChange(CameraPosition cameraPosition) { -// mIBusPassengerMapViewCallback.onCameraChange(cameraPosition.bearing); - } - - @Override - public void onCameraChangeFinish(CameraPosition cameraPosition) { - - } -} diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.kt b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.kt new file mode 100644 index 0000000000..df13122d1e --- /dev/null +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.kt @@ -0,0 +1,331 @@ +package com.mogo.och.bus.passenger.ui + +import android.content.Context +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.widget.RelativeLayout +import com.amap.api.maps.AMap +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.TextureMapView +import com.amap.api.maps.model.BitmapDescriptor +import com.amap.api.maps.model.BitmapDescriptorFactory +import com.amap.api.maps.model.CameraPosition +import com.amap.api.maps.model.CustomMapStyleOptions +import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker +import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.model.Polyline +import com.amap.api.maps.model.PolylineOptions +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.utils.BusPassengerMapAssetStyleUtil + +/** + * 乘客屏小地图 + */ +class BusPassengerMapDirectionView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener, + IBusPassengerMapDirectionView, AMap.OnCameraChangeListener { + + companion object { + //小地图名称 + const val TAG = "BusPassengerMapDirectionView" + } + + private lateinit var mAMapNaviView: TextureMapView + private lateinit var mAMap: AMap + private var mPolyline: Polyline? = null + private val mLineMarkers: MutableList = ArrayList() + private lateinit var mCarMarker: Marker + + private val mLineStationLatLng: MutableList = ArrayList() //站点坐标数据 + var textureList: MutableList = ArrayList() + var texIndexList: MutableList = ArrayList() + private var mArrivedRes: BitmapDescriptor? = null + private var mUnArrivedRes: BitmapDescriptor? = null + + private val routeArrivied: MutableList = ArrayList() + private val routeArriving: MutableList = ArrayList() + private var location: MogoLocation? = null + + init { + try { + initView(context) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun initView(context: Context) { + d(M_BUS_P + TAG, "initView") + val smpView = LayoutInflater.from(context).inflate(R.layout.bus_p_map_view, this) + mAMapNaviView = smpView.findViewById(R.id.bus_p_line_amap_view) as TextureMapView + initAMapView() + + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 10, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + } + + private fun initAMapView() { + mAMap = mAMapNaviView.map + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap.mapType = AMap.MAP_TYPE_NIGHT + + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap.isTrafficEnabled = false + + // 设置 锚点 图标 + mCarMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_car)).anchor(0.5f, 0.5f)) + mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_arrived) + mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_un_arrive) + + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData( + BusPassengerMapAssetStyleUtil.getAssetsStyle( + context, "map_style.data" + ) + ) + .setStyleExtraData( + BusPassengerMapAssetStyleUtil.getAssetsExtraStyle( + context, "map_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions) + + // 设置地图的样式 + mAMap.uiSettings.apply { + isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + setAllGesturesEnabled(true) // 所有手势 + isMyLocationButtonEnabled = false // 显示默认的定位按钮 + setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + } + + mAMap.setOnMapLoadedListener { + d(M_BUS_P + TAG, "smp---onMapLoaded") + // 加载自定义样式 + val options = CustomMapStyleOptions() + .setEnable(true) + .setStyleData( + BusPassengerMapAssetStyleUtil.getAssetsStyle( + context, "map_style.data" + ) + ) + .setStyleExtraData( + BusPassengerMapAssetStyleUtil.getAssetsExtraStyle( + context, "map_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap.setCustomMapStyle(options) + mAMapNaviView.map.setPointToCenter( + mAMapNaviView.width / 2, + mAMapNaviView.height / 2 + ) + } + + //设置地图状态的监听接口 + mAMap.setOnCameraChangeListener(this) + } + +// override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { +// return true +// } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (mogoLocation == null) { + return + } + val currentLatLng = LatLng(mogoLocation.latitude, mogoLocation.longitude) + + //更新车辆位置 + mCarMarker.rotateAngle = (360 - mogoLocation.heading).toFloat() + mCarMarker.position = currentLatLng + mCarMarker.setToTop() + try { + //圈定地图显示范围 + val boundsBuilder = LatLngBounds.Builder() + routeArrivied.forEach { + boundsBuilder.include(it) + } + routeArriving.forEach { + boundsBuilder.include(it) + } + mLineStationLatLng.forEach { + boundsBuilder.include(it) + } + boundsBuilder.include(currentLatLng) + mAMap.moveCamera( + CameraUpdateFactory.newLatLngBoundsRect( + boundsBuilder.build(), + 100, + 100, + 100, + 100 + ) + ) + } catch (e: Exception) { + e.printStackTrace() + } + } + + override fun drawablePolyline() { + if (routeArrivied.isEmpty() && routeArriving.isEmpty()) { + d(SceneConstant.M_TAXI + TAG, "没有点") + return + } + texIndexList.clear() + val allPoints = ArrayList(routeArrivied) + for (i in routeArrivied.indices) { + if (routeArrivied.size > 1 && i < routeArrivied.size - 1) { + texIndexList.add(0) + } + } + texIndexList.add(0) + allPoints.add(LatLng(location!!.latitude, location!!.longitude)) + allPoints.addAll(routeArriving) + for (ignored in routeArrivied) { + texIndexList.add(1) + } + if (mPolyline != null) { + mPolyline!!.points = allPoints + mPolyline!!.options.customTextureIndex = texIndexList + return + } + if(textureList.isEmpty()) { + textureList.add(mArrivedRes) + textureList.add(mUnArrivedRes) + } + //设置线段纹理 + val polylineOptions = PolylineOptions().apply { + addAll(allPoints) + isUseTexture = true + width(15f) + lineCapType(PolylineOptions.LineCapType.LineCapRound) + customTextureList = textureList + customTextureIndex = texIndexList + } + + // 绘制线 + mPolyline = mAMap.addPolyline(polylineOptions) + } + + override fun clearPolyline() { + if (mPolyline != null) { + mPolyline!!.remove() + mPolyline = null + } + } + + override fun setLineMarker() {} + + fun clearCoordinatesLatLng() { + textureList.clear() + texIndexList.clear() + routeArrivied.clear() + routeArriving.clear() + mLineStationLatLng.clear() + d(M_BUS_P + TAG, " mCoordinatesLatLng.clear ") + } + + fun onCreateView(savedInstanceState: Bundle?) { + mAMapNaviView.onCreate(savedInstanceState) + } + + fun onResume() { + mAMapNaviView.onResume() + } + + fun onPause() { + mAMapNaviView.onPause() + } + + fun onDestroy() { + mAMapNaviView.onDestroy() + } + + fun setCoordinatesLatLng( + routeArrivied: List?, + routeArriving: List?, + location: MogoLocation? + ) { + this.routeArrivied.clear() + this.routeArrivied.addAll(routeArrivied!!) + this.routeArriving.clear() + this.routeArriving.addAll(routeArriving!!) + this.location = location + } + + fun clearLineMarkers() { + for (i in mLineMarkers.indices) { + mLineMarkers[i].isVisible = false + mLineMarkers[i].remove() + } + mLineMarkers.clear() + } + + fun setLinePointMarkerAndDraw(mLineStationsList: List, currentIndex: Int) { + clearLineMarkers() + mLineStationLatLng.clear() + mLineStationLatLng.addAll(mLineStationsList) + if (mLineStationsList.isNotEmpty()) { + // 起点marker, 终点marker, 过站marker, 未过站marker + val size = mLineStationsList.size + val mStartMarker = mAMap.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_start_point)) + ) + val mEndMarker = mAMap.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_end_point)) + ) + mStartMarker.position = mLineStationsList[0] + mLineMarkers.add(0, mStartMarker) + for (i in mLineStationsList.indices) { + if (currentIndex <= i && i < size - 1 && i > 0) { //未到达 + val unArrivedMarker = mAMap.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_unarrived_point)) + ) + unArrivedMarker.position = mLineStationsList[i] + mLineMarkers.add(i, unArrivedMarker) + } else if (i in 1 until currentIndex) { + val arrivedMarker = mAMap.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrived_point)) + ) + arrivedMarker.position = mLineStationsList[i] + mLineMarkers.add(i, arrivedMarker) + } + } + mEndMarker.position = mLineStationsList[size - 1] + mLineMarkers.add(size - 1, mEndMarker) + } + } + + override fun onCameraChange(cameraPosition: CameraPosition) { + } + + override fun onCameraChangeFinish(cameraPosition: CameraPosition) {} + +} \ No newline at end of file diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java index 5041b7e52f..33d497dbf3 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java @@ -240,9 +240,9 @@ public class BusPassengerRouteFragment extends } } - public void routeResult(List latLngList,int haveArrivedIndex) { - if (latLngList.size() > 0) { - drawablePolyline(latLngList,haveArrivedIndex); + public void routeResult(List routeArrivied,List routeArriving,MogoLocation location) { + if (routeArrivied.size() > 0||routeArriving.size()>0) { + drawablePolyline(routeArrivied,routeArriving,location); } else { clearMapView(); } @@ -253,15 +253,10 @@ public class BusPassengerRouteFragment extends * * @param coordinates */ - private void drawablePolyline(List coordinates,int haveArrivedIndex) { + private void drawablePolyline(List routeArrivied,List routeArriving,MogoLocation location) { if (mMapDirectionView != null) { - mMapDirectionView.setCoordinatesLatLng(coordinates,haveArrivedIndex); - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapDirectionView.drawablePolyline(); - } - }); + mMapDirectionView.setCoordinatesLatLng(routeArrivied,routeArriving,location); + UiThreadHandler.post(() -> mMapDirectionView.drawablePolyline()); } } @@ -290,10 +285,7 @@ public class BusPassengerRouteFragment extends } public void changeOperationStatus(boolean status) { - if (status) { - mNoLineInfoView.setVisibility(View.GONE); - mRouteInfoView.setVisibility(View.VISIBLE); - } else { + if (!status) { emptyTv.setText(getString(R.string.bus_p_no_out)); mNoLineInfoView.setVisibility(View.VISIBLE); mRouteInfoView.setVisibility(View.GONE); diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java index ac7db3446d..7346b58bbf 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java @@ -48,9 +48,7 @@ public class BPRouteDataTestUtils { builder.setLongitude(s.getDouble("longitude_")); list.add(builder.build()); } - BusPassengerModel.getInstance().updateRoutePoints(list); - BusPassengerModel.getInstance().startRemainRouteInfo(); - BusPassengerModel.getInstance().startToRouteAndWipe(); + BusPassengerModel.INSTANCE.updateRoutePoints(list); } catch (JSONException e) { e.printStackTrace(); } diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png new file mode 100644 index 0000000000..ac317649b4 Binary files /dev/null and b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png index 17beb894a6..702f10f265 100644 Binary files a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png and b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png new file mode 100644 index 0000000000..39262e5ecb Binary files /dev/null and b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png new file mode 100644 index 0000000000..b2e4c69ada Binary files /dev/null and b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png new file mode 100644 index 0000000000..ec6081f5a3 Binary files /dev/null and b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png deleted file mode 100644 index 1e64713481..0000000000 Binary files a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png and /dev/null differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png deleted file mode 100644 index ff04c01f13..0000000000 Binary files a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png and /dev/null differ diff --git a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml index 46bf3aefed..339efd6fc5 100644 --- a/OCH/mogo-och-bus-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml +++ b/OCH/mogo-och-bus-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml @@ -27,7 +27,7 @@ app:layout_constraintStart_toStartOf="parent" /> B 此处值是A站点索引 private static volatile OrderModel sInstance; - public double mLongitude = 0; - public double mLatitude = 0; private Context mContext; private final List stationList = new ArrayList<>(); private BusRoutesResult busRoutesResult = null; @@ -153,7 +154,7 @@ public class OrderModel { mContext = AbsMogoApplication.getApp(); loginService = (LoginService) ARouter.getInstance().build(OchCommonConst.LOGINSERVICE).navigation(); // 定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, mMapLocationListener); + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,10, mMapLocationListener); MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); @@ -173,6 +174,8 @@ public class OrderModel { AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext); + TrajectoryAndDistanceManager.INSTANCE.addTrajectoryListener(TAG,trajectoryListener); + //2022.1.28 // 调用Disposable.dispose() 时候会出现InterruptedException 导致出现崩溃 // The exception could not be delivered to the consumer because it has already canceled/disposed @@ -268,6 +271,12 @@ public class OrderModel { this.mControllerStatusCallback = callback; } + private final ITrajectoryListener trajectoryListener = new ITrajectoryListener() { + @Override + public void trajectoryCallback(@NonNull List routeArrivied, @NonNull List routeArriving, @NonNull MogoLocation location) { + + } + }; private final IMoGoPlanningRottingListener moGoAutopilotPlanningListener = new IMoGoPlanningRottingListener() { @Override @@ -347,6 +356,8 @@ public class OrderModel { OCHSocketMessageManager.msgWriteOffPassengerType); AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors(); + + TrajectoryAndDistanceManager.INSTANCE.removeListener(TAG); } private Object readResolve() { @@ -382,8 +393,6 @@ public class OrderModel { @Override public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { if (null == gnssInfo) return; - mLongitude = gnssInfo.getLongitude(); - mLatitude = gnssInfo.getLatitude(); if (mControllerStatusCallback != null) { mControllerStatusCallback.onCarLocationChanged(gnssInfo); } @@ -410,10 +419,26 @@ public class OrderModel { startLon, startLat, location.getLongitude(), location.getLatitude()); - if (distance <= BusConst.ARRIVE_AT_END_STATION_DISTANCE) { + if (distance <= BusConst.ARRIVE_AT_END_STATION_DISTANCE) {//1、当前位置和站点围栏15m内 CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-judgeArrivedStation() distance = " + distance + " to " + upcomingStation.getName()); - onArriveAt(null); //无自动驾驶到站信息传null + + //2、开始计算当前位置和站点的向量角度 < 90度 未经过 >90度 经过 + double stationAngle = DrivingDirectionUtils.getDegreeOfCar2Poi( + location.getLongitude(), + location.getLatitude(), + startLon, + startLat, + (int) location.getHeading()); + + CallerLogger.INSTANCE.d(M_BUS + TAG, "judgeArrivedStation() stationAngle = " + stationAngle); + + //3、刚过站且过站距离在15m内, 提交到站 + if (stationAngle > 90 && distance <= BusConst.ARRIVE_AT_END_STATION_DISTANCE){ + CallerLogger.INSTANCE.d(M_BUS + TAG, "judgeArrivedStation() = 刚过站且在15m内"); + onArriveAt(null); //无自动驾驶到站信息传null + } + return; } } @@ -601,12 +626,13 @@ public class OrderModel { , nextStation , isLastStop); } + } private void onStartAutopilot(int leaveIndex) { //开启自动驾驶 2.10.0: 如果自动驾驶状态下开启, 非自动驾驶状态下不开启,需手动点击自动驾驶按钮开启 isGoingToNextStation = true; - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { startAutopilot(false, leaveIndex); } else { @@ -743,16 +769,24 @@ public class OrderModel { CallerLogger.INSTANCE.d(M_BUS + TAG, "leaveStation-backgroundCurrentStationIndex = " + backgroundCurrentStationIndex); String nextStationName = ""; String nextStationNameKr = ""; + MogoLocation nextStationPoint = new MogoLocation(); if (backgroundCurrentStationIndex < stationList.size() - 1) { - nextStationName = stationList.get(backgroundCurrentStationIndex + 1).getName(); - nextStationNameKr = stationList.get(backgroundCurrentStationIndex + 1).getNameKr(); + BusStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1); + nextStationName = nextStation.getName(); + nextStationNameKr = nextStation.getNameKr(); + nextStationPoint.setLongitude(nextStation.getGcjLon()); + nextStationPoint.setLatitude(nextStation.getGcjLat()); } - final String currentStationName = stationList.get(backgroundCurrentStationIndex).getName(); + BusStationBean busStationBean = stationList.get(backgroundCurrentStationIndex); + final String currentStationName = busStationBean.getName(); String finalNextStationName = nextStationName; String finalNextStationNameKr = nextStationNameKr; + MogoLocation currentStationPoint = new MogoLocation(); + currentStationPoint.setLongitude(busStationBean.getGcjLon()); + currentStationPoint.setLatitude(busStationBean.getGcjLat()); OrderServiceManager.leaveStation(mContext, - stationList.get(backgroundCurrentStationIndex).getSeq(), - stationList.get(backgroundCurrentStationIndex).getSiteId(), + busStationBean.getSeq(), + busStationBean.getSiteId(), currentTaskId, new OchCommonServiceCallback() { @Override @@ -764,6 +798,7 @@ public class OrderModel { queryBusRoutes(); leaveStationSuccess(backgroundCurrentStationIndex, currentStationName, finalNextStationName,finalNextStationNameKr); + setTrajectoryStation(currentStationPoint,nextStationPoint, (long) currentLineId); } @@ -1019,7 +1054,7 @@ public class OrderModel { } CallerLogger.INSTANCE.d(M_BUS + TAG, "单程结束===="); CallerAutoPilotControlManager.INSTANCE.cancelAutoPilot(); - + setTrajectoryStation(null,null,-1L); endTask(); } @@ -1090,6 +1125,10 @@ public class OrderModel { String arriveLat = NumberFormatUtil.cutOutNumber(arriveStation.getLat(), 5); String arriveLon = NumberFormatUtil.cutOutNumber(arriveStation.getLon(), 5); + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-dataLatitude = "+ latitude+ + ", dataLongitude = " + longitude + "; arriveLat = " + arriveLat + + ", arriveLon = " +arriveLon); + if (!latitude.equals(arriveLat) || !longitude.equals(arriveLon)) { CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-到站拦截,到站坐标不一致"); return; @@ -1113,6 +1152,8 @@ public class OrderModel { // 车机端上传心跳数据(只在出车状态时上传) public void runCarHeartbeat() { + double mLatitude = CallerChassisLocationGCJ02ListenerManager.INSTANCE.getChassisLocationGCJ02().getLatitude(); + double mLongitude =CallerChassisLocationGCJ02ListenerManager.INSTANCE.getChassisLocationGCJ02().getLongitude(); OrderServiceManager.runCarHeartbeat(mContext, mLongitude, mLatitude, new OchCommonServiceCallback() { @Override @@ -1138,6 +1179,8 @@ public class OrderModel { // 登出 public void logout() { + double mLatitude = CallerChassisLocationGCJ02ListenerManager.INSTANCE.getChassisLocationGCJ02().getLatitude(); + double mLongitude =CallerChassisLocationGCJ02ListenerManager.INSTANCE.getChassisLocationGCJ02().getLongitude(); loginService.loginOut(mLatitude, mLongitude); } @@ -1232,4 +1275,8 @@ public class OrderModel { return parameters; } + + public void setTrajectoryStation(MogoLocation startStation,MogoLocation endStation,Long lineId){ + TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation,endStation,lineId); + } } 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 7eadb3d41f..711fe90a39 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 @@ -64,7 +64,7 @@ class BusConst { const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L //围栏到站 暂定10米 - const val ARRIVE_AT_END_STATION_DISTANCE = 10 + const val ARRIVE_AT_END_STATION_DISTANCE = 15 // 轮询 const val LOOP_PASSENGER_5S = 5 * 1000L 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 7b70977f1b..7a584acfbb 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 @@ -158,7 +158,7 @@ public abstract class BaseBusTabFragment }); initListener(); - setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener() { @Override @@ -301,9 +301,6 @@ public abstract class BaseBusTabFragment @Override public void onAutopilotRecordResult(@Nullable RecordPanelOuterClass.RecordPanel recordPanel) { -// if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) { -// CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel); -// } } @Override @@ -448,7 +445,7 @@ public abstract class BaseBusTabFragment public void stopAnimAndUpdateBtnStatus() { stopAutopilotAnimation(); - updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); } /** @@ -522,7 +519,7 @@ public abstract class BaseBusTabFragment public void run() { //未启动成功做处理 if (isAnimateRunning) {// 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态 stopAutopilotAnimation(); - updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); } } }, TIMER_START_AUTOPILOT_INTERVAL); diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java index bcb1422d46..cd80f7b6e0 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java @@ -13,7 +13,6 @@ import androidx.constraintlayout.widget.Group; import androidx.annotation.Nullable; import com.alibaba.android.arouter.launcher.ARouter; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; -import com.mogo.commons.AbsMogoApplication; import com.mogo.eagle.core.data.config.FunctionBuildConfig; import com.mogo.eagle.core.data.map.CenterLine; import com.mogo.eagle.core.data.temp.EventLogout; @@ -108,7 +107,7 @@ public class BusFragment extends BaseBusTabFragment groupStationsPanel = findViewById(R.id.group_stations_panel); noDataView = findViewById(R.id.no_line_data_view); - CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getState()); // 初始化的时候设置 UI 按钮状态 showAutopilotBiz(); @@ -455,7 +454,7 @@ public class BusFragment extends BaseBusTabFragment } //清除鹰眼右下角小地图轨迹 - CallerLogger.INSTANCE.d(SceneConstant.M_MAP, "clearBusStationsMarkers --------->"); + CallerLogger.INSTANCE.d(SceneConstant.M_BUS, "clearBusStationsMarkers --------->"); smallMapView.clearPolyline(); } @@ -532,7 +531,7 @@ public class BusFragment extends BaseBusTabFragment public void onClick(View v) { if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中,点击则toast提示:自动驾驶中,不可切换路线 //本次行程未结束,不支持切换路线。点击则toast提示:当前行程未完成,不可切换路线 - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { ToastUtils.showLong(getResources().getString(R.string.bus_switch_line_btn_warning1)); return; 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 a2d0ae8d4a..c823b12043 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 @@ -34,8 +34,6 @@ import com.mogo.och.common.module.biz.constant.LoginStatusManager; import com.mogo.och.common.module.manager.OCHAdasAbilityManager; import com.mogo.och.common.module.voice.VoiceNotice; -import org.jetbrains.annotations.NotNull; - import java.util.ArrayList; import java.util.List; @@ -45,8 +43,6 @@ import system_master.SystemStatusInfo; /** * 网约车小巴 - * - * @author tongchenfei */ public class BusPresenter extends Presenter implements IRefreshBusStationsCallback, ISlidePannelHideCallback @@ -54,8 +50,8 @@ public class BusPresenter extends Presenter private static final String TAG = "BusPresenter"; - private int currentAutopilotStatus = -1; - private List mStationList = new ArrayList<>(); + private volatile int currentAutopilotStatus = -1; + private final List mStationList = new ArrayList<>(); private int mCurrentStation = 0; public BusPresenter(BusFragment view) { @@ -168,9 +164,7 @@ public class BusPresenter extends Presenter } @Override - public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { - int state = autopilotStatusInfo.getState(); -// CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChange: " + state + "currentAutopilotStatus = " + currentAutopilotStatus); + public void onAutopilotStatusResponse(int state) { switch (state) { case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE: if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { @@ -206,26 +200,21 @@ public class BusPresenter extends Presenter && ( (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) && OrderModel.getInstance().isGoingToNextStation() - ) ) { CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); return; } - if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; } - runOnUIThread(() -> { - mView.onAutopilotStatusChanged(currentAutopilotStatus); - }); + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); break; case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING: if (FunctionBuildConfig.isDemoMode && ( (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) && OrderModel.getInstance().isGoingToNextStation() - ) ) { CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); @@ -234,9 +223,7 @@ public class BusPresenter extends Presenter if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) { currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING; } - runOnUIThread(() -> { - mView.onAutopilotStatusChanged(currentAutopilotStatus); - }); + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); break; default: runOnUIThread(() -> mView.onAutopilotEnableChange(false)); @@ -275,13 +262,9 @@ public class BusPresenter extends Presenter /** * 测试使用 - * - * @param status */ public void debugAutoPilotStatus(int status) { - AutopilotStatusInfo info = new AutopilotStatusInfo(); - info.setState(status); - onAutopilotStatusResponse(info); + onAutopilotStatusResponse(status); } @Override @@ -340,4 +323,13 @@ public class BusPresenter extends Presenter public void onStartAdasFailure() { runOnUIThread(() -> mView.stopAnimAndUpdateBtnStatus()); } + + @Override + public void onAutopilotStatusResponse(@NonNull AutopilotStatusInfo autoPilotStatusInfo) { + } + + @Override + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + } + } 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 b37e399e18..947adbfc0c 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 @@ -50,13 +50,13 @@ public class BusAnalyticsManager { CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_CODE, failCode); mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG, failMsg); } mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT - , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + , CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/view/SlidePanelView.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/view/SlidePanelView.java index f04edddbdb..e010f37a76 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/view/SlidePanelView.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/view/SlidePanelView.java @@ -54,6 +54,7 @@ public class SlidePanelView extends View { 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); + mTypedArray.recycle(); init(); } @@ -129,7 +130,7 @@ public class SlidePanelView extends View { textPaint.setShader(textGradient); textPaint.getFontMetrics(blockTextMetrics); int size = AutoSizeUtils.dp2px(getContext(), 120); - BitmapFactory.Options opts = new BitmapFactory.Options(); + BitmapFactory.Options opts = new BitmapFactory.Options(); //todo yakun 优化 opts.inDensity = (int) AutoSizeConfig.getInstance().getInitDensity(); bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.bus_base_slide_block,opts); bmBlock = Bitmap.createScaledBitmap(bmBlock, size, size, true); diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/model/CharterPassengerModel.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/model/CharterPassengerModel.kt index ab0e27b25d..dd5ffce344 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/model/CharterPassengerModel.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/model/CharterPassengerModel.kt @@ -10,11 +10,9 @@ import com.mogo.eagle.core.data.BaseData import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLine import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters.AutoPilotLonLat -import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo import com.mogo.eagle.core.data.map.MogoLocation import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener -import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationWGS84Listener import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener import com.mogo.eagle.core.function.call.autopilot.* import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager.startAutoPilot @@ -28,11 +26,11 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P import com.mogo.eagle.core.utilcode.util.* import com.mogo.och.bus.passenger.R -import com.mogo.och.bus.passenger.bean.LoopInfo +import com.mogo.och.common.module.manager.loopmanager.LoopInfo import com.mogo.och.bus.passenger.bean.response.* import com.mogo.och.bus.passenger.callback.* import com.mogo.och.bus.passenger.constant.CharterPassengerConst -import com.mogo.och.bus.passenger.net.BusPassengerModelLoopManager +import com.mogo.och.common.module.manager.loopmanager.BusPassengerModelLoopManager import com.mogo.och.bus.passenger.net.BusPassengerServiceManager import com.mogo.och.bus.passenger.utils.ToastCharterUtils import com.mogo.och.bus.passenger.utils.VoiceFocusManager @@ -78,7 +76,8 @@ object CharterPassengerModel { private var mContext: Context = AbsMogoApplication.getApp() //Model->Presenter:自动驾驶状态相关 - var mAutoStatusChnageListener = ConcurrentHashMap() + var mAutoStatusChnageListener = + ConcurrentHashMap() // 定位监听 private val mControllerStatusCallbackMap = @@ -86,7 +85,6 @@ object CharterPassengerModel { // 当前位置坐标 private var mLocationGCJ02: MogoLocation? = null - private var mLocationWgs: MogoLocation? = null // 订单信息 有订单有线路结束订单 @Volatile @@ -112,17 +110,18 @@ object CharterPassengerModel { * 到站是否播报 key 线路id+业务 value 是否播报 * */ - private var broadcastList : MutableMap = HashMap() + private var broadcastList: MutableMap = HashMap() + // 到站仅一次 private val endKey = "arrivedLine" private val endKeyRequestIng = "arrivedLineRequestIng" private val ending100Key = "arrivingLine" private val min5Speak = "min5Speak" - private var carTypeChageListener: IOrderChangeCallback?=null + private var carTypeChageListener: IOrderChangeCallback? = null - private var subscribeCountDown: Disposable?=null - var switchLine5minWait: Disposable?=null + private var subscribeCountDown: Disposable? = null + var switchLine5minWait: Disposable? = null @Volatile var newCheckedSite: SiteInfoResponse.SiteInfo? = null @@ -140,7 +139,6 @@ object CharterPassengerModel { CallerAutoPilotStatusListenerManager.removeListener(mGoAutopilotStatusListener) CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) CallerPlanningRottingListenerManager.removeListener(moGoAutopilotPlanningListener) - CallerChassisLocationWGS84ListenerManager.removeListener(TAG) } private fun initListeners() { @@ -150,8 +148,7 @@ object CharterPassengerModel { // 自动驾驶状态变化监听 CallerAutoPilotStatusListenerManager.addListener(TAG, mGoAutopilotStatusListener) // 定位监听 - CallerChassisLocationGCJ02ListenerManager.addListener(TAG, mMapLocationListener) - CallerChassisLocationWGS84ListenerManager.addListener(TAG, 2, mMapWGS84LocationListener) + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 4, mMapLocationListener) // 自动驾驶路线规划接口 返回自动驾驶轨迹 CallerPlanningRottingListenerManager.addListener(TAG, moGoAutopilotPlanningListener) // 登录状态监听 @@ -167,6 +164,7 @@ object CharterPassengerModel { } mControllerStatusCallbackMap[tag] = callback } + fun setAutoStatusCallback(tag: String, callback: ICharterPassengerAutoStatusChangeCallback?) { if (tag.isBlank()) return if (callback == null) { @@ -216,32 +214,18 @@ object CharterPassengerModel { } } } - private val mMapWGS84LocationListener: IMoGoChassisLocationWGS84Listener = - object : IMoGoChassisLocationWGS84Listener { - override fun onChassisLocationWGS84(gnssInfo: MogoLocation) { - if (null == gnssInfo) return - mLocationWgs = gnssInfo - } - } - - // 前一个自动驾驶状体 - @Volatile - private var mPreAutoStatus = -1 // 自动驾驶状态监听 private val mGoAutopilotStatusListener: IMoGoAutopilotStatusListener = object : IMoGoAutopilotStatusListener { - override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { - val state = autoPilotStatusInfo.state - if(mPreAutoStatus!=state){ - mPreAutoStatus = state - mAutoStatusChnageListener.forEach { - it.value.onAutoStatusChange(state) - } + override fun onAutopilotStatusResponse(state: Int) { + mAutoStatusChnageListener.forEach { + it.value.onAutoStatusChange(state) } } + override fun onAutopilotArriveAtStation(arrivalNotification: MessagePad.ArrivalNotification?) { - CallerLogger.d(M_BUS_P + TAG,"底盘给到站信息") + CallerLogger.d(M_BUS_P + TAG, "底盘给到站信息") arriveDest() } } @@ -252,13 +236,9 @@ object CharterPassengerModel { private val moGoAutopilotPlanningListener: IMoGoPlanningRottingListener = object : IMoGoPlanningRottingListener { override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) { - CallerLogger.d( - M_BUS_P + TAG, - "onAutopilotRotting = ${GsonUtil.jsonFromObject(globalPathResp)}" - ) globalPathResp?.wayPointsList?.let { if (it.size > 0) { - CallerLogger.d( + d( M_BUS_P + TAG, "收到轨迹:${it.size}--第一个点${it[0]}--最后一个点:${it.last()}" ) @@ -269,17 +249,21 @@ object CharterPassengerModel { } } - fun updateRoutePoints(routePoints: List?) { + fun updateRoutePoints(routePoints: List) { mRoutePoints = null val latLngModels = CoordinateCalculateRouteUtil .coordinateConverterWgsToGcjLocations(mContext, routePoints) mRoutePoints = latLngModels } - fun cleanRoutePoints(){ + + fun cleanRoutePoints() { mRoutePoints = null } - fun setStatusChangeListener(tag:String,orderStatusChangeListener: IOrderStatusChangeListener?) { + fun setStatusChangeListener( + tag: String, + orderStatusChangeListener: IOrderStatusChangeListener? + ) { if (tag.isBlank()) return if (orderStatusChangeListener == null) { orderStatusChangeListeners.remove(tag) @@ -287,7 +271,8 @@ object CharterPassengerModel { } orderStatusChangeListeners[tag] = orderStatusChangeListener } - fun setStationDistanceListener(tag:String,orderStatusChangeListener: IDistanceCallback?) { + + fun setStationDistanceListener(tag: String, orderStatusChangeListener: IDistanceCallback?) { if (tag.isBlank()) return if (orderStatusChangeListener == null) { stationDistanceListener.remove(tag) @@ -295,7 +280,8 @@ object CharterPassengerModel { } stationDistanceListener[tag] = orderStatusChangeListener } - fun setOrderLeftTimeListeners(tag:String,orderStatusChangeListener: ITimeCallback?) { + + fun setOrderLeftTimeListeners(tag: String, orderStatusChangeListener: ITimeCallback?) { if (tag.isBlank()) return if (orderStatusChangeListener == null) { orderLeftTimeListeners.remove(tag) @@ -306,14 +292,15 @@ object CharterPassengerModel { orderStatusChangeListener.setOrderTimeCallBack(leftTime) } - fun setCarTypeChangeListener(carTypeChageListener: IOrderChangeCallback?){ + fun setCarTypeChangeListener(carTypeChageListener: IOrderChangeCallback?) { this.carTypeChageListener = carTypeChageListener } fun getCurrentOrderStatus(): OrderStatusEnum { return this.orderStatus } - fun getCurrentOrderInfo():OrderInfoResponse.OrderInfo?{ + + fun getCurrentOrderInfo(): OrderInfoResponse.OrderInfo? { return orderInfo } // endregion @@ -372,13 +359,13 @@ object CharterPassengerModel { BusPassengerServiceManager.queryOrderInfo( mContext, object : OchCommonServiceCallback { override fun onSuccess(data: OrderInfoResponse?) { - CallerLogger.d(M_BUS_P+TAG,"订单信息:$data") - if (data?.data == null){ - if(orderInfo!=null){ + CallerLogger.d(M_BUS_P + TAG, "订单信息:$data") + if (data?.data == null) { + if (orderInfo != null) { // 启动车辆服务状态 startCarStatusLoop() } - }else { + } else { // 判断是否有订单 ordrLagic(data.data) } @@ -397,21 +384,26 @@ object CharterPassengerModel { // 有订单有线路后结束轮训 orderData.let { order -> //设置车模 - if (this.orderInfo?.productType!=orderData.productType) { + if (this.orderInfo?.productType != orderData.productType) { this.carTypeChageListener?.setCarChangeListener(orderData.productType) - CallerLogger.d(M_BUS_P+TAG,"设置车模") + CallerLogger.d(M_BUS_P + TAG, "设置车模") } - if(this.orderInfo?.siteId!=orderData.siteId){ + if (this.orderInfo?.siteId != orderData.siteId) { val coordinateConverterWgsToGcj = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj( mContext, order.wgs84Lon!!, order.wgs84Lat!! ) - this.carTypeChageListener?.setEndStationCallBack(order.siteId,order.siteName,coordinateConverterWgsToGcj.longitude,coordinateConverterWgsToGcj.latitude) + this.carTypeChageListener?.setEndStationCallBack( + order.siteId, + order.siteName, + coordinateConverterWgsToGcj.longitude, + coordinateConverterWgsToGcj.latitude + ) } this.orderInfo?.orderNo?.let { - if(it!=orderData.orderNo){ + if (it != orderData.orderNo) { // orderNo 变后清理 SharedPrefs.getInstance(mContext).remove("${it}$min5Speak") } @@ -428,7 +420,7 @@ object CharterPassengerModel { this.orderInfo = orderData setOrderStatus(OrderStatusEnum.OrdersWithLine) updateAutopilotControlParameters() - }else{ + } else { this.orderInfo = orderData } //计算终点距离 @@ -448,7 +440,7 @@ object CharterPassengerModel { ) // 小于15m到站 if (calculateLineDistance < CharterPassengerConst.ARRIVE_AT_START_STATION_DISTANCE && calculateLineDistance > 0) { - CallerLogger.d(M_BUS_P + TAG,"小于15米到站1") + CallerLogger.d(M_BUS_P + TAG, "小于15米到站1") arriveDest() } if (calculateLineDistance < CharterPassengerConst.ARRIVE_SOON_AT_START_STATION_DISTANCE && calculateLineDistance > 0) { @@ -465,7 +457,7 @@ object CharterPassengerModel { fun hasSetLineAndSite(): Pair? { orderInfo?.let { if (it.lineId != null && it.lineId > 0 && it.siteId != null && it.siteId!! > 0) { - if(it.arriveStatus==OrderInfoResponse.ARRIVED){ + if (it.arriveStatus == OrderInfoResponse.ARRIVED) { return null } val lineInfo = LineInfoResponse.LineInfo(it.lineName, it.lineId) @@ -486,7 +478,8 @@ object CharterPassengerModel { } return null } - fun hasOrder():Boolean{ + + fun hasOrder(): Boolean { return orderInfo != null } // endregion @@ -557,7 +550,7 @@ object CharterPassengerModel { private fun startCalibrationLoop() { BusPassengerModelLoopManager.setLoopFunction( TAGCALIBRATION, - LoopInfo(120, ::queryBusinessTime,immediately = true) + LoopInfo(120, ::queryBusinessTime, immediately = true) ) CallerLogger.d(M_BUS_P + TAG, "启动时间校准轮询") } @@ -587,42 +580,43 @@ object CharterPassengerModel { } val leadTime = endlast / 1000 subscribeCountDown = - Observable.intervalRange(0L, leadTime, 0, 5, TimeUnit.SECONDS) - .map { aLong -> leadTime - aLong } - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) - .subscribe{millisUntilFinished-> - if (millisUntilFinished <= 300L) { - orderInfo?.let { - val isPlayed = SharedPrefs.getInstance(mContext) - .getBoolean("${it.orderNo}$min5Speak", false) - if (!isPlayed) { - //发送 通知 - OCHSocketMessageManager.pushAppOperationalMsgBox( - DateTimeUtil.getCurrentTimeStamp(), - AbsMogoApplication.getApp() - .getString(R.string.m1_end_order_5min), 2 - ) - VoiceManager.surplus5min(VoiceFocusManager.getVoiceCmdCallBack()) - CallerLogger.d(M_BUS_P+ TAG,"倒计时5分钟${it.orderNo}") - SharedPrefs.getInstance(mContext).putBoolean("${it.orderNo}$min5Speak",true) + Observable.intervalRange(0L, leadTime, 0, 5, TimeUnit.SECONDS) + .map { aLong -> leadTime - aLong } + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe { millisUntilFinished -> + if (millisUntilFinished <= 300L) { + orderInfo?.let { + val isPlayed = SharedPrefs.getInstance(mContext) + .getBoolean("${it.orderNo}$min5Speak", false) + if (!isPlayed) { + //发送 通知 + OCHSocketMessageManager.pushAppOperationalMsgBox( + DateTimeUtil.getCurrentTimeStamp(), + AbsMogoApplication.getApp() + .getString(R.string.m1_end_order_5min), 2 + ) + VoiceManager.surplus5min(VoiceFocusManager.getVoiceCmdCallBack()) + CallerLogger.d(M_BUS_P + TAG, "倒计时5分钟${it.orderNo}") + SharedPrefs.getInstance(mContext) + .putBoolean("${it.orderNo}$min5Speak", true) + } } } - } - if(orderInfo==null){ - subscribeCountDown?.let { - if (!it.isDisposed) { - it.dispose() + if (orderInfo == null) { + subscribeCountDown?.let { + if (!it.isDisposed) { + it.dispose() + } } + invokeOrderLeftTimeListeners(-1) + invokeStationDistanceListener(-1, -1) + } else { + invokeOrderLeftTimeListeners(millisUntilFinished) } - invokeOrderLeftTimeListeners(-1) - invokeStationDistanceListener(-1,-1) - }else{ - invokeOrderLeftTimeListeners(millisUntilFinished) + CallerLogger.d(M_BUS_P + TAG, "订单倒计时${millisUntilFinished}") } - CallerLogger.d(M_BUS_P + TAG, "订单倒计时${millisUntilFinished}") - } } } @@ -642,9 +636,12 @@ object CharterPassengerModel { //设置全局轨迹信息 locusInfo = data.data - CallerLogger.d(M_BUS_P+TAG,"查询自动驾驶轨迹信息") - CallerLogger.d(M_BUS_P+TAG,GsonUtil.jsonFromObject( - locusInfo)) + CallerLogger.d(M_BUS_P + TAG, "查询自动驾驶轨迹信息") + CallerLogger.d( + M_BUS_P + TAG, GsonUtil.jsonFromObject( + locusInfo + ) + ) } override fun onFail(code: Int, msg: String) { @@ -682,15 +679,15 @@ object CharterPassengerModel { mLocationGCJ02?.let { orderInfo?.let { order -> CallerLogger.d(M_BUS_P + "calculateDistance", "订单信息:$order") - if(order.siteId==null||order.siteId==0L|| - order.wgs84Lat==null||order.wgs84Lat==0.0|| - order.wgs84Lon==null||order.wgs84Lon==0.0 - ){ + if (order.siteId == null || order.siteId == 0L || + order.wgs84Lat == null || order.wgs84Lat == 0.0 || + order.wgs84Lon == null || order.wgs84Lon == 0.0 + ) { CallerLogger.d(M_BUS_P + "calculateDistance", "站点信息未获得") return } newCheckedSite?.let { - if(it.siteId!=order.siteId){ + if (it.siteId != order.siteId) { CallerLogger.d(M_BUS_P + "calculateDistance", "站点和已选不吻合") return } @@ -714,46 +711,52 @@ object CharterPassengerModel { mogoLocation.latitude ) CallerLogger.d(M_BUS_P + "calculateDistance", "两点距离和站点的直线距离:${lastSumLength}") - if(lastSumLength>100) { - if (mRoutePoints==null||mRoutePoints?.size == 0){ + if (lastSumLength > 100) { + if (mRoutePoints == null || mRoutePoints?.size == 0) { //ToastCharterUtils.showLong("缺少轨迹数据暂停计算") - CallerLogger.d(M_BUS_P + "calculateDistance两点距离", + CallerLogger.d( + M_BUS_P + "calculateDistance两点距离", "缺少轨迹数据" ) return } // 计算距离 - val templastSumLength = + val templastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength( mRoutePoints, it, mogoLocation ) - CallerLogger.d(M_BUS_P + TAG, "使用轨迹轨迹:${mRoutePoints?.size}--第一个点${mRoutePoints!![0]}--最后一个点:${mRoutePoints!!.last()}") + CallerLogger.d( + M_BUS_P + TAG, + "使用轨迹轨迹:${mRoutePoints?.size}--第一个点${mRoutePoints!![0]}--最后一个点:${mRoutePoints!!.last()}" + ) CallerLogger.d(M_BUS_P + "calculateDistance", "轨迹计算的距离$templastSumLength") - if(templastSumLength>100){ + if (templastSumLength > 100) { lastSumLength = templastSumLength } } - val lastTime: Double = lastSumLength / CharterPassengerConst.Charter_AVERAGE_SPEED * 3.6 //秒 + val lastTime: Double = + lastSumLength / CharterPassengerConst.Charter_AVERAGE_SPEED * 3.6 //秒 - CallerLogger.d(M_BUS_P + "calculateDistance", + CallerLogger.d( + M_BUS_P + "calculateDistance", "最终信息:lastSumLength: ${lastSumLength}lastTime : $lastTime thread = ${Thread.currentThread().name}" ) - if (lastSumLength < CharterPassengerConst.ARRIVE_SOON_AT_START_STATION_DISTANCE&&lastSumLength>0) { - CallerLogger.d(M_BUS_P + TAG,"小于100米到站2") + if (lastSumLength < CharterPassengerConst.ARRIVE_SOON_AT_START_STATION_DISTANCE && lastSumLength > 0) { + CallerLogger.d(M_BUS_P + TAG, "小于100米到站2") arriveDestSoon() } - if (lastSumLength < CharterPassengerConst.ARRIVE_AT_START_STATION_DISTANCE&&lastSumLength>0) { - CallerLogger.d(M_BUS_P + TAG,"小于15米到站2") + if (lastSumLength < CharterPassengerConst.ARRIVE_AT_START_STATION_DISTANCE && lastSumLength > 0) { + CallerLogger.d(M_BUS_P + TAG, "小于15米到站2") arriveDest() return } - if(order.arriveStatus==OrderInfoResponse.ARRIVING) { + if (order.arriveStatus == OrderInfoResponse.ARRIVING) { invokeStationDistanceListener(lastSumLength.toLong(), lastTime.toLong()) - }else{ - invokeStationDistanceListener(-1,-1) + } else { + invokeStationDistanceListener(-1, -1) } } } @@ -763,7 +766,7 @@ object CharterPassengerModel { private fun setOrderStatus(orderStatus: OrderStatusEnum) { if (this.orderStatus != orderStatus) { - CallerLogger.d(M_BUS_P + TAG,"${this.orderInfo?.orderNo}新的状态:$orderStatus") + CallerLogger.d(M_BUS_P + TAG, "${this.orderInfo?.orderNo}新的状态:$orderStatus") this.orderStatus = orderStatus for (callback in orderStatusChangeListeners.values) { callback.onStatusChange(this.orderStatus) @@ -771,10 +774,10 @@ object CharterPassengerModel { } } - fun setEndOrderStatus(){ + fun setEndOrderStatus() { UiThreadHandler.postDelayed({ setOrderStatus(OrderStatusEnum.NoOrderUse) - },1000) + }, 1000) } /** @@ -801,16 +804,16 @@ object CharterPassengerModel { val calculateLineDistanceNext = CoordinateUtils.calculateLineDistance( currentInfo.longitude, currentInfo.latitude, - data[index+1].GcjLon!!, - data[index+1].GcjLat!! + data[index + 1].GcjLon!!, + data[index + 1].GcjLat!! ) - if(calculateLineDistanceNext= 2) { @@ -830,7 +833,7 @@ object CharterPassengerModel { middle = mutableEntry.value break } - if(middle==0){ + if (middle == 0) { return Pair(1, false) } mLocationGCJ02?.let { @@ -839,7 +842,7 @@ object CharterPassengerModel { // middle middle+1 // middle-1 middle-2 // middle+1 middle+2 - if(middle-1>=0) { + if (middle - 1 >= 0) { val degree = CoordinateCalculateRouteUtil.getDegree( it.longitude, it.latitude, data.get(middle).GcjLon!!, data.get(middle).GcjLat!!, @@ -849,17 +852,17 @@ object CharterPassengerModel { return Pair(middle, false) } } - if(middle+1 90) { - return Pair(middle+1, false) + return Pair(middle + 1, false) } } - if(middle-2>=0) { + if (middle - 2 >= 0) { val degree = CoordinateCalculateRouteUtil.getDegree( it.longitude, it.latitude, data.get(middle - 1).GcjLon!!, data.get(middle - 1).GcjLat!!, @@ -869,11 +872,11 @@ object CharterPassengerModel { return Pair(middle - 1, false) } } - if(middle+2 90) { return Pair(middle + 2, false) @@ -891,21 +894,29 @@ object CharterPassengerModel { BusPassengerServiceManager.endOrder(mContext, it, callback) } } - fun getLineTrajectory(lineId: Long,callback: OchCommonServiceCallback?) { + + fun getLineTrajectory(lineId: Long, callback: OchCommonServiceCallback?) { BusPassengerServiceManager.queryLineLocation(mContext, lineId = lineId.toString(), callback) } @Synchronized fun arriveDest() { val (order, lineId, siteId) = getOrderInfo() - if(order!=null&&lineId!=null&&siteId!=null){ + if (order != null && lineId != null && siteId != null) { val requestSuccessSign = "${siteId}$endKey" val requestIngSign = "${siteId}$endKeyRequestIng"//正在请求中 - CallerLogger.d(M_BUS_P + BaseDPMsg.TAG, - "requestSuccessSign${isSuccess(requestSuccessSign)}---requestIngSign${isSuccess(requestIngSign)}") + CallerLogger.d( + M_BUS_P + BaseDPMsg.TAG, + "requestSuccessSign${isSuccess(requestSuccessSign)}---requestIngSign${ + isSuccess( + requestIngSign + ) + }" + ) if (order.arriveStatus == OrderInfoResponse.ARRIVING) { - if (isSuccess(requestSuccessSign)&&//true 请求还没有成功 false 请求成功 - isSuccess(requestIngSign)) {// true 还没有正在请求 false 正在请求中 + if (isSuccess(requestSuccessSign) &&//true 请求还没有成功 false 请求成功 + isSuccess(requestIngSign) + ) {// true 还没有正在请求 false 正在请求中 val currentTimeStamp = DateTimeUtil.getCurrentTimeStamp() broadcastList[requestIngSign] = true //正在请求中 BusPassengerServiceManager.arriveDest( @@ -913,23 +924,23 @@ object CharterPassengerModel { lindId = lineId, writtenVersion = currentTimeStamp, object : OchCommonServiceCallback { - override fun onSuccess(data: BaseData?) { - if (null != data && 0 == data.code) { - arrivedDeskSuccess(currentTimeStamp,true) - broadcastList[requestIngSign] = false - } - } - - override fun onFail(code: Int, msg: String) { - ToastCharterUtils.showShort("$code:$msg") + override fun onSuccess(data: BaseData?) { + if (null != data && 0 == data.code) { + arrivedDeskSuccess(currentTimeStamp, true) broadcastList[requestIngSign] = false } + } - override fun onError() { - super.onError() - broadcastList[requestIngSign] = false - } - }) + override fun onFail(code: Int, msg: String) { + ToastCharterUtils.showShort("$code:$msg") + broadcastList[requestIngSign] = false + } + + override fun onError() { + super.onError() + broadcastList[requestIngSign] = false + } + }) } } } @@ -937,16 +948,16 @@ object CharterPassengerModel { fun arrivedDeskSuccess( currentTimeStamp: Long, - needSendDriver:Boolean + needSendDriver: Boolean ) { val (order, lineId, siteId) = getOrderInfo() val requestSuccessSign = "${siteId}$endKey" - if (!isSuccess(requestSuccessSign)){ + if (!isSuccess(requestSuccessSign)) { return } - if(order!=null&&lineId!=null&&siteId!=null){ + if (order != null && lineId != null && siteId != null) { VoiceManager.arrivedStation( order.siteName!!, order.siteNameKr ?: "", @@ -963,7 +974,7 @@ object CharterPassengerModel { order.startSiteId ?: 0, order.startSiteName ?: "", siteId.toInt(), - order.siteName?:"", + order.siteName ?: "", true, OrderInfoResponse.ARRIVED, currentTimeStamp @@ -987,15 +998,15 @@ object CharterPassengerModel { } } - private fun getOrderInfo():Triple{ - this.orderInfo?.let { order-> + private fun getOrderInfo(): Triple { + this.orderInfo?.let { order -> this.orderInfo?.lineId?.let { lineId -> this.orderInfo?.siteId?.let { siteId -> - return Triple(order,lineId,siteId) + return Triple(order, lineId, siteId) } } } - return Triple(null,null,null) + return Triple(null, null, null) } @Synchronized @@ -1004,7 +1015,8 @@ object CharterPassengerModel { order.siteId?.let { siteId -> if (order.arriveStatus == OrderInfoResponse.ARRIVING) { if (isSuccess("${siteId}$ending100Key")) { - val string = mContext.getString(R.string.arrived_station_left_100,order.siteName) + val string = + mContext.getString(R.string.arrived_station_left_100, order.siteName) VoiceNotice.showNotice(string) broadcastList["${siteId}$ending100Key"] = true } @@ -1040,8 +1052,12 @@ object CharterPassengerModel { } fun leaveStation() { - orderInfo?.siteName?.let {cn-> - VoiceManager.leaveStation(cn,orderInfo?.siteNameKr?:"", VoiceFocusManager.getVoiceCmdCallBack()) + orderInfo?.siteName?.let { cn -> + VoiceManager.leaveStation( + cn, + orderInfo?.siteNameKr ?: "", + VoiceFocusManager.getVoiceCmdCallBack() + ) } } @@ -1065,14 +1081,17 @@ object CharterPassengerModel { return } orderInfo?.let { - if(it.arriveStatus==OrderInfoResponse.ARRIVED){ + if (it.arriveStatus == OrderInfoResponse.ARRIVED) { ToastCharterUtils.showLong("已到达目的地请重新选择线路") return } val parameters = initAutopilotControlParameters() if (null == parameters) { ToastCharterUtils.showShort("请选择站点") - CallerLogger.e(SceneConstant.M_BUS + TAG, "行程日志-AutopilotControlParameters is empty.") + CallerLogger.e( + SceneConstant.M_BUS + TAG, + "行程日志-AutopilotControlParameters is empty." + ) return } ToastCharterUtils.showShort("启动自动驾驶中") @@ -1099,7 +1118,7 @@ object CharterPassengerModel { } val parameters = AutopilotControlParameters() orderInfo?.let { orderInfo -> - mLocationWgs?.let { startPoint -> + CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84().let { startPoint -> val startWgsLon: Double = startPoint.longitude val startWgsLat: Double = startPoint.latitude val endWgsLon: Double = orderInfo.wgs84Lon!! @@ -1133,12 +1152,14 @@ object CharterPassengerModel { fun sendTripInfo() { //发送前后屏出站消息 3:代表出站 orderInfo?.let { - CharterSendTripInfoManager.sendCharterTripInfo(LEAVE_STATION, - it.lineName!!,it.startSiteName!!,it.siteName!!,false) + CharterSendTripInfoManager.sendCharterTripInfo( + LEAVE_STATION, + it.lineName!!, it.startSiteName!!, it.siteName!!, false + ) } } - private fun invokeOrderLeftTimeListeners(timeInSecond: Long){ + private fun invokeOrderLeftTimeListeners(timeInSecond: Long) { leftTime = timeInSecond UiThreadHandler.post({ for (value in orderLeftTimeListeners.values) { @@ -1147,7 +1168,7 @@ object CharterPassengerModel { }, UiThreadHandler.MODE.QUEUE) } - private fun invokeStationDistanceListener(meters:Long , timeInSecond:Long){ + private fun invokeStationDistanceListener(meters: Long, timeInSecond: Long) { var tempMeters = meters var tempTimeInSecond = timeInSecond if (orderInfo?.arriveStatus == OrderInfoResponse.ARRIVED) { @@ -1156,7 +1177,7 @@ object CharterPassengerModel { } UiThreadHandler.post({ for (value in stationDistanceListener.values) { - value.setDistancecAndTime(tempMeters,tempTimeInSecond) + value.setDistancecAndTime(tempMeters, tempTimeInSecond) } }, UiThreadHandler.MODE.QUEUE) diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerFunctionOrderPresenter.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerFunctionOrderPresenter.kt index 3165f5ed7a..d7bd2cb1ac 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerFunctionOrderPresenter.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerFunctionOrderPresenter.kt @@ -9,11 +9,10 @@ import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02Lis import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger -import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P import com.mogo.eagle.core.utilcode.util.GsonUtils import com.mogo.och.bus.passenger.utils.ToastCharterUtils -import com.mogo.och.bus.passenger.bean.LoopInfo +import com.mogo.och.common.module.manager.loopmanager.LoopInfo import com.mogo.och.bus.passenger.bean.event.EventLineSites import com.mogo.och.bus.passenger.bean.response.LineInfoListResponse import com.mogo.och.bus.passenger.bean.response.LineInfoResponse @@ -21,7 +20,7 @@ import com.mogo.och.bus.passenger.bean.response.SiteInfoResponse import com.mogo.och.bus.passenger.model.CharterPassengerModel import com.mogo.och.bus.passenger.model.IOrderStatusChangeListener import com.mogo.och.bus.passenger.model.OrderStatusEnum -import com.mogo.och.bus.passenger.net.BusPassengerModelLoopManager +import com.mogo.och.common.module.manager.loopmanager.BusPassengerModelLoopManager import com.mogo.och.bus.passenger.net.BusPassengerServiceManager import com.mogo.och.bus.passenger.ui.dialogfragment.fragment.M1OrderLineFragment import com.mogo.och.common.module.bean.dpmsg.BaseDPMsg @@ -67,7 +66,7 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : CharterPassengerModel.setStatusChangeListener(TAG,this) CallerTelematicListenerManager.addListener(TAG, msgReceived) val currentOrderStatus = CharterPassengerModel.getCurrentOrderStatus() - onStatusChange(currentOrderStatus) + needRunUI(currentOrderStatus) extracted() } @@ -185,7 +184,7 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) - CallerLogger.d(SceneConstant.M_BUS_P + TAG, "onDestroy") + CallerLogger.d(M_BUS_P + TAG, "onDestroy") RxUtils.disposeSubscribe(subscribeSelectLine) RxUtils.disposeSubscribe(subscribeSelectSite) BusPassengerModelLoopManager.removeLoopFunction(TAGLINELOOP) @@ -196,7 +195,7 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : /** * 接收司机屏反馈信息 */ - val msgReceived = object : IReceivedMsgListener { + private val msgReceived = object : IReceivedMsgListener { override fun onReceivedMsg(type: Int, byteArray: ByteArray) { UiThreadHandler.post { if (type == OchCommonConst.BUSINESS_STRING) { @@ -287,23 +286,27 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : ToastCharterUtils.showShort("断开和司机端连接、请联系安全员") BusPassengerModelLoopManager.removeLoopFunction(TAGLINELOOP) mView?.hideDataDriverRefuse() - CallerLogger.d(SceneConstant.M_BUS_P + TAG, "endAni666") + CallerLogger.d(M_BUS_P + TAG, "endAni666") } } override fun onStatusChange(currentStatus: OrderStatusEnum) { UiThreadHandler.post { - when (currentStatus) { - OrderStatusEnum.OrderNoLine -> { - mView?.setVisableByTrun(showBiz = true) - extracted() - } - OrderStatusEnum.OrdersWithLine ->{ - mView?.setVisableByTrun(showBiz = true) - } - else ->{ - mView?.setVisableByTrun(showNorOrder = true) - } + needRunUI(currentStatus) + } + } + + private fun needRunUI(currentStatus: OrderStatusEnum){ + when (currentStatus) { + OrderStatusEnum.OrderNoLine -> { + mView?.setVisableByTrun(showBiz = true) + extracted() + } + OrderStatusEnum.OrdersWithLine ->{ + mView?.setVisableByTrun(showBiz = true) + } + else ->{ + mView?.setVisableByTrun(showNorOrder = true) } } } @@ -312,7 +315,7 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : val gnssSpeed = CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02().gnssSpeed if (gnssSpeed < 0.5) { - when (CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state) { + when (CallerAutoPilotStatusListenerManager.getState()) { IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> {// 不可自动驾驶 return true } @@ -321,13 +324,13 @@ class BusPassengerFunctionOrderPresenter(view: M1OrderLineFragment?) : } IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING -> { // 自动驾驶中 - when (StopSideStatusManager.stopSiteStatus) { + return when (StopSideStatusManager.stopSiteStatus) { StopSideStatusManager.Status.EndingSuccess -> { - return true + true } else ->{ ToastCharterUtils.showShort("自动驾驶中无法切换线路") - return false + false } } } diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerPresenter.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerPresenter.kt index be25f6b913..a06052e277 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerPresenter.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/presenter/BusPassengerPresenter.kt @@ -163,7 +163,7 @@ class BusPassengerPresenter(view: MainFragment?) : } OrderStatusEnum.OrdersWithLine -> {} OrderStatusEnum.NoOrderUse -> { - when (CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state) { + when (CallerAutoPilotStatusListenerManager.getState()) { IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> {// 不可自动驾驶 ToastCharterUtils.showShort("设备未就绪请稍等,请安全员主动停止车辆") } diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/dialogfragment/M1ContainFragment.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/dialogfragment/M1ContainFragment.kt index b165fb86dd..a3d1cde613 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/dialogfragment/M1ContainFragment.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/dialogfragment/M1ContainFragment.kt @@ -57,7 +57,7 @@ class M1ContainFragment : setStyle(STYLE_NO_TITLE, R.style.DialogFullScreen) //dialog全屏 } - private fun setCheckView() { + private fun setCheckView() { //todo yakun 优化 CallerLogger.d(M_BUS_P+ TAG, "setCheckView") when (tab) { VIDEOTAB -> { @@ -211,7 +211,7 @@ class M1ContainFragment : mShownByMe.isAccessible = true mDismissed.setBoolean(this, false) mShownByMe.setBoolean(this, true) - if (isAdded) { //解决方法就是添加这行代码,如果已经添加了,就移除掉然后再show,就不会出现Fragment already added的错误了。 + if (isAdded) { return } val ft: FragmentTransaction = manager.beginTransaction() @@ -300,10 +300,8 @@ class M1ContainFragment : } if (ClickUtils.isFastClick()) { if (bpFunctionGroup.isAdded) { - //解决方法就是添加这行代码,如果已经添加了,就移除掉然后再show,就不会出现Fragment already added的错误了。 - parentFragmentManager.beginTransaction().remove(bpFunctionGroup) - .commitNowAllowingStateLoss() - CallerLogger.d(M_BUS_P + DebugViewWatchDogFragment.TAG, "已经添加正在移除") + CallerLogger.d(M_BUS_P + DebugViewWatchDogFragment.TAG, "已经添加") + return } bpFunctionGroup.show(parentFragmentManager, TAG) CallerLogger.d(M_BUS_P + TAG, "展示$tab---$bpFunctionGroup") diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/layoutmanage/CarouselLayoutManager.java b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/layoutmanage/CarouselLayoutManager.java index c82d57dac4..334e0ede44 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/layoutmanage/CarouselLayoutManager.java +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/layoutmanage/CarouselLayoutManager.java @@ -934,7 +934,7 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements } private CarouselSavedState(@NonNull final Parcel in) { - mSuperState = in.readParcelable(Parcelable.class.getClassLoader()); + mSuperState = in.readParcelable(RecyclerView.LayoutManager.class.getClassLoader()); mCenterItemPosition = in.readInt(); } diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/GoViewWithArrive.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/GoViewWithArrive.kt index a7ad0f56cd..bd02492dd7 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/GoViewWithArrive.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/GoViewWithArrive.kt @@ -82,7 +82,7 @@ class GoViewWithArrive @JvmOverloads constructor( ToastCharterUtils.showShort(string) return } - when (CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state) { + when (CallerAutoPilotStatusListenerManager.getState()) { IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> {// 不可自动驾驶 ToastCharterUtils.showShort("设备未就绪请稍等") } @@ -122,7 +122,7 @@ class GoViewWithArrive @JvmOverloads constructor( }) RxUtils.disposeSubscribe(startAutoTimeOut) startAutoTimeOut = RxUtils.createSubscribe(20_000) { - if (CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + if (CallerAutoPilotStatusListenerManager.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { val string = AbsMogoApplication.getApp().getString(R.string.m1_start_auto_fail) ToastCharterUtils.showLong(string) } diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/StopSiteView.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/StopSiteView.kt index 444c35b3da..8266b48292 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/StopSiteView.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/ui/view/bottom/impl/StopSiteView.kt @@ -29,7 +29,7 @@ class StopSiteView @JvmOverloads constructor( } private fun stopSite(){ - when (CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state) { + when (CallerAutoPilotStatusListenerManager.getState()) { IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> {// 不可自动驾驶 ToastCharterUtils.showShort("设备未就绪请稍等,请稍后再试") } diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/view/statusbar/StatusBarView.kt b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/view/statusbar/StatusBarView.kt index df793fbdf9..0b82c76464 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/view/statusbar/StatusBarView.kt +++ b/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/view/statusbar/StatusBarView.kt @@ -9,7 +9,6 @@ import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import chassis.ChassisStatesOuterClass -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.api.autopilot.IMoGoBatteryManagementSystemListener @@ -25,7 +24,6 @@ import com.mogo.eagle.core.utilcode.util.ClickUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.bus.passenger.R import com.mogo.och.bus.passenger.bean.event.DebugView -import com.mogo.och.bus.passenger.model.CharterPassengerModel import kotlinx.android.synthetic.main.m1_statusview_datetime.view.* import me.jessyan.autosize.utils.AutoSizeUtils import org.greenrobot.eventbus.EventBus @@ -47,8 +45,6 @@ class StatusBarView @JvmOverloads constructor( private var mHits = LongArray(COUNTS) - private var preStatus = -1 - private fun continuousClick(type:String) { //每次点击时,数组向前移动一位 System.arraycopy(mHits, 1, mHits, 0, mHits.size - 1) @@ -93,15 +89,11 @@ class StatusBarView @JvmOverloads constructor( progress.progress = 50 tv_power_cos.text = "50%" - val state = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state - setAutoPilotSatusInfo(state) + val state = CallerAutoPilotStatusListenerManager.getState() + setAutoPilotStatusInfo(state) } - private fun setAutoPilotSatusInfo(state: Int) { - if(preStatus==state){ - return - } - preStatus = state + private fun setAutoPilotStatusInfo(state: Int) { when (state) { IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> { actv_auto_status.text = "安全接管中" @@ -126,9 +118,9 @@ class StatusBarView @JvmOverloads constructor( } } - override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { + override fun onAutopilotStatusResponse(state: Int) { UiThreadHandler.post { - setAutoPilotSatusInfo(autoPilotStatusInfo.state) + setAutoPilotStatusInfo(state) } } diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.png deleted file mode 100644 index 766ec25cb4..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.webp new file mode 100644 index 0000000000..5d5d74a099 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_end_order_openclosedoor.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.png deleted file mode 100644 index f89f87c8c6..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.webp new file mode 100644 index 0000000000..c7a69ec5c8 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_1.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.png deleted file mode 100644 index be354f9b64..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.webp new file mode 100644 index 0000000000..9a52c9671a Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_2.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.png deleted file mode 100644 index 51429b9b48..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.webp new file mode 100644 index 0000000000..4f732eeb63 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_3.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.png deleted file mode 100644 index 01f5efeae8..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.webp new file mode 100644 index 0000000000..99bfd7223f Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_guidace_4.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.png deleted file mode 100644 index ceef4281b4..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.webp new file mode 100644 index 0000000000..8533cad601 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_image_welcome_nor.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.png deleted file mode 100644 index 1137f9cebd..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.webp new file mode 100644 index 0000000000..9e806cd695 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit01.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.png deleted file mode 100644 index 94225fbd19..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.webp new file mode 100644 index 0000000000..0a3fbde266 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit02.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.png deleted file mode 100644 index 12ac2c7cd7..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.webp new file mode 100644 index 0000000000..3d28e24c7d Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit03.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.png deleted file mode 100644 index e96dcba42f..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.webp new file mode 100644 index 0000000000..458dd26de0 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit04.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.png deleted file mode 100644 index bb21fdc7b8..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.webp new file mode 100644 index 0000000000..7bcb191449 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit05.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.png deleted file mode 100644 index a59ac743c0..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.webp new file mode 100644 index 0000000000..9899f85a6f Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit06.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.png deleted file mode 100644 index 1e6e98e749..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.webp new file mode 100644 index 0000000000..3a54db13cc Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit07.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.png deleted file mode 100644 index 8031d522b4..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.webp new file mode 100644 index 0000000000..d8ac4c610e Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit08.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.png deleted file mode 100644 index 5104b3e154..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.webp new file mode 100644 index 0000000000..1f7231c2d9 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit09.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.png deleted file mode 100644 index c2f6dfe467..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.webp new file mode 100644 index 0000000000..b1feddc55f Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit10.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.png deleted file mode 100644 index 55169260b0..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.webp new file mode 100644 index 0000000000..f8e38aa30d Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit11.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.png deleted file mode 100644 index 70a9a4d4e2..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.webp new file mode 100644 index 0000000000..5a464a2c61 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit12.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.png deleted file mode 100644 index 7249bd6c00..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.webp new file mode 100644 index 0000000000..69f99544fc Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit13.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.png deleted file mode 100644 index dd9b20e123..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.webp new file mode 100644 index 0000000000..4f6ed398c0 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit14.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.png deleted file mode 100644 index 158f9bd472..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.webp new file mode 100644 index 0000000000..16aa545e83 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit15.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.png deleted file mode 100644 index 451ba3fee4..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.webp new file mode 100644 index 0000000000..b4a08f5e4a Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit16.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.png deleted file mode 100644 index bc84a61f8d..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.webp new file mode 100644 index 0000000000..3004510b20 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit17.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.png deleted file mode 100644 index 9557bb4287..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.webp new file mode 100644 index 0000000000..597e938c97 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit18.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.png deleted file mode 100644 index c60d988f87..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.webp new file mode 100644 index 0000000000..8359f171fe Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit19.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.png deleted file mode 100644 index 426eb26312..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.webp new file mode 100644 index 0000000000..72bd01e8b5 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit20.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.png deleted file mode 100644 index 228aa09df2..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.webp new file mode 100644 index 0000000000..70130c216f Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit21.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.png deleted file mode 100644 index f1301f2bfd..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.webp new file mode 100644 index 0000000000..38b8e3b2d4 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit22.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.png deleted file mode 100644 index 7eed395b23..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.webp new file mode 100644 index 0000000000..4e346b4462 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit23.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.png deleted file mode 100644 index 19979e347e..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.webp new file mode 100644 index 0000000000..fff4e1e074 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit24.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.png deleted file mode 100644 index c07d6f9f38..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.webp new file mode 100644 index 0000000000..4757a32709 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit25.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.png deleted file mode 100644 index 6790b9eb73..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.webp new file mode 100644 index 0000000000..f36b82c50c Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit26.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.png deleted file mode 100644 index a64acf4098..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.webp new file mode 100644 index 0000000000..5790ca8d24 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit27.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.png deleted file mode 100644 index c87efa80b8..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.webp new file mode 100644 index 0000000000..2744cf3294 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit28.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.png deleted file mode 100644 index 99addfa297..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.webp new file mode 100644 index 0000000000..7b94aa562f Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit29.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.png deleted file mode 100644 index 1137f9cebd..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.webp new file mode 100644 index 0000000000..9e806cd695 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/charter_p_wait_driver_submit30.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.png deleted file mode 100644 index 5b15490684..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.webp new file mode 100644 index 0000000000..48f8e50b35 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/m1_function_bg.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.png b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.png deleted file mode 100644 index 99bfcefc6f..0000000000 Binary files a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.png and /dev/null differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.webp b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.webp new file mode 100644 index 0000000000..d3df5084d4 Binary files /dev/null and b/OCH/mogo-och-charter-passenger/src/main/res/drawable-nodpi/taxi_p_video_holder.webp differ diff --git a/OCH/mogo-och-charter-passenger/src/main/res/drawable/bus_p_function_setting_soft_b_shape.xml b/OCH/mogo-och-charter-passenger/src/main/res/drawable/bus_p_function_setting_soft_b_shape.xml index 9fc3f02d44..42a5ef35c1 100644 --- a/OCH/mogo-och-charter-passenger/src/main/res/drawable/bus_p_function_setting_soft_b_shape.xml +++ b/OCH/mogo-och-charter-passenger/src/main/res/drawable/bus_p_function_setting_soft_b_shape.xml @@ -3,4 +3,4 @@ android:shape="rectangle"> - \ No newline at end of file + diff --git a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/manager/CharterAnalyticsManager.java b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/manager/CharterAnalyticsManager.java index 7418517a4d..0338c6f393 100644 --- a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/manager/CharterAnalyticsManager.java +++ b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/manager/CharterAnalyticsManager.java @@ -49,13 +49,13 @@ public class CharterAnalyticsManager { CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ mStartAutopilotParams.put(CharterConst.EVENT_PARAM_START_FAILURE_CODE, failCode); mStartAutopilotParams.put(CharterConst.EVENT_PARAM_START_FAILURE_MSG, failMsg); } mStartAutopilotParams.put(CharterConst.EVENT_PARAM_START_RESULT - , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + , CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); diff --git a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/model/DriverM1Model.kt b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/model/DriverM1Model.kt index 65ca0483fa..e77143325d 100644 --- a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/model/DriverM1Model.kt +++ b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/model/DriverM1Model.kt @@ -110,8 +110,7 @@ class DriverM1Model { fun init(context: Context) { mContext = context // 定位监听 - CallerChassisLocationGCJ02ListenerManager.addListener(TAG, mMapLocationListener) -// CallerChassisLocationGCJ02ListenerManager.setListenerHz(TAG,2) + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 10,mMapLocationListener) //开启自驾后 异常信息返回 OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener) diff --git a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/presenter/DriverM1Presenter.kt b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/presenter/DriverM1Presenter.kt index 2b13464cfd..085738af28 100644 --- a/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/presenter/DriverM1Presenter.kt +++ b/OCH/mogo-och-charter/src/driverm1/java/com/magic/mogo/och/charter/presenter/DriverM1Presenter.kt @@ -10,7 +10,6 @@ import com.magic.mogo.och.charter.fragment.DriverM1Fragment import com.magic.mogo.och.charter.manager.CharterTrajectoryManager import com.magic.mogo.och.charter.model.DriverM1Model import com.mogo.commons.mvp.Presenter -import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo import com.mogo.eagle.core.data.map.MogoLocation import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager @@ -36,8 +35,9 @@ class DriverM1Presenter(view: DriverM1Fragment?) : IMoGoAutopilotStatusListener, StopSideStatusManager.OCHPlanningActionsCallback, IDriverM1ControllerStatusCallback { - private val TAG = DriverM1Presenter::class.java.name - private var mCurrentAutopilotStatus : Int = -1 + companion object{ + private const val TAG = "DriverM1Presenter" + } init { DriverM1Model.get().init(context) @@ -139,19 +139,14 @@ class DriverM1Presenter(view: DriverM1Fragment?) : DriverM1Model.get().onAutopilotArriveAtStation() } - override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { - val status = autoPilotStatusInfo.state - if (mCurrentAutopilotStatus == status) return - - mView?.onAutopilotStatusChanged(status) - mCurrentAutopilotStatus = status - when(status){ - + override fun onAutopilotStatusResponse(state: Int) { + mView?.onAutopilotStatusChanged(state) + when(state){ // IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE -> { // // // } IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING ->{ - DriverM1Model.get().triggerStartServiceEvent(false,true) + DriverM1Model.get().triggerStartServiceEvent(isRestart = false, send = true) } // IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE ->{ // @@ -187,14 +182,12 @@ class DriverM1Presenter(view: DriverM1Fragment?) : } override fun startOpenAutopilot() { - mCurrentAutopilotStatus = -1 ThreadUtils.runOnUiThread { mView?.startAutopilotAnimation() } } override fun onStartAdasFailure() { - mCurrentAutopilotStatus = -1 ThreadUtils.runOnUiThread { mView?.stopAnimAndUpdateBtnStatus() } diff --git a/OCH/mogo-och-charter/src/main/java/com/magic/mogo/och/charter/base/CharterBaseFragment.kt b/OCH/mogo-och-charter/src/main/java/com/magic/mogo/och/charter/base/CharterBaseFragment.kt index 0527ff1675..96bc9a4150 100644 --- a/OCH/mogo-och-charter/src/main/java/com/magic/mogo/och/charter/base/CharterBaseFragment.kt +++ b/OCH/mogo-och-charter/src/main/java/com/magic/mogo/och/charter/base/CharterBaseFragment.kt @@ -17,7 +17,7 @@ import com.mogo.commons.mvp.MvpFragment import com.mogo.commons.mvp.Presenter 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.getAutoPilotStatusInfo +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.getState import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager.initAiCollect import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager.initBadCase @@ -126,7 +126,7 @@ abstract class CharterBaseFragment?>() : } }) initListener() - setAutopilotBtnStatus(getAutoPilotStatusInfo().state) + setAutopilotBtnStatus(getState()) ctvAutopilotStatus!!.setOnClickListener(object : OnPreventFastClickListener() { override fun onClickImpl(v: View) { restartAutopilot() @@ -394,7 +394,7 @@ abstract class CharterBaseFragment?>() : open fun stopAnimAndUpdateBtnStatus() { stopAutopilotAnimation() - updateAutopilotStatus(getAutoPilotStatusInfo().state) + updateAutopilotStatus(getState()) } @@ -453,7 +453,7 @@ abstract class CharterBaseFragment?>() : //未启动成功做处理 if (isAnimateRunning) { // 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态 stopAutopilotAnimation() - updateAutopilotStatus(getAutoPilotStatusInfo().state) + updateAutopilotStatus(getState()) } }, CharterConst.TIMER_START_AUTOPILOT_INTERVAL) } diff --git a/OCH/mogo-och-common-module/src/debug/AndroidManifest.xml b/OCH/mogo-och-common-module/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..7d64112bb0 --- /dev/null +++ b/OCH/mogo-och-common-module/src/debug/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/BizBroadcastReceiver.kt b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/BizBroadcastReceiver.kt new file mode 100644 index 0000000000..b33df5e396 --- /dev/null +++ b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/BizBroadcastReceiver.kt @@ -0,0 +1,38 @@ +package com.mogo.och.common.module.debug + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant + +class BizBroadcastReceiver: BroadcastReceiver() { + + private var mContext: Context? = null + + companion object { + private const val TAG = "BizBroadcastReceiver" + // 类型 + private const val type = "type" + // 数据源 + private const val sourceFile = "path" + // 数据频率 默认1s一次 -1 发送一次 + private const val frequencyKey = "fre" + } + + override fun onReceive(context: Context, intent: Intent) { + try { + mContext = context + val type = intent.getStringExtra(type) + val frequency = intent.getIntExtra(frequencyKey,1) + val sourceFilePath = intent.getStringExtra(sourceFile) + CallerLogger.d("${SceneConstant.M_OCHCOMMON}${TAG}", + "类型:${type} 频率:${frequency} 命令所在文件:${sourceFilePath}" + ) + DebugDataDispatch.disPathc(type,frequency,sourceFilePath) + } catch (e: Exception) { + e.printStackTrace() + } + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt new file mode 100644 index 0000000000..ed7619f7b4 --- /dev/null +++ b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/DebugDataDispatch.kt @@ -0,0 +1,125 @@ +package com.mogo.och.common.module.debug + +import android.os.Environment +import com.amap.api.maps.model.LatLng +import com.google.gson.reflect.TypeToken +import com.mogo.eagle.core.data.enums.DataSourceType +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.GsonUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.common.module.debug.location.MogoLocationExit +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil +import mogo.telematics.pad.MessagePad +import java.io.BufferedReader +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.io.InputStreamReader + +object DebugDataDispatch { + + const val TAG = "DebugDataDispatch" + + const val globalPathMock = "globalPath" + const val locationMock = "location" + + val ROOT_PATH = + Environment.getExternalStorageDirectory().absolutePath + File.separator + "MLog" + File.separator + "APPLog" + File.separator //程序外部存储跟目录 + + + fun disPathc(type: String?, frequency: Int, sourceFilePath: String?) { + when (type) { + globalPathMock -> { + sourceFilePath?.let { + loadRawPoints(ROOT_PATH+it) + } + } + locationMock -> { + sourceFilePath?.let { + getLocaitonByLog(ROOT_PATH+it) + } + } + else -> {} + } + } + + fun getLocaitonByLog(path:String) { + ThreadUtils.getIoPool().execute { + val inputStream = FileInputStream(path) + val reader = BufferedReader(InputStreamReader(inputStream)) + var line: String? = "" + try { + while (reader.readLine().also { line = it } != null) { + val list = GsonUtils.fromJson( + line.toString(), + object : TypeToken() {}.type + ) + val mogoLocation = MogoLocation() + mogoLocation.latitude = list.msg.GnssInfo.latitude + mogoLocation.longitude = list.msg.GnssInfo.longitude + mogoLocation.heading = list.msg.GnssInfo.heading + mogoLocation.gnssSpeed = list.msg.GnssInfo.gnssSpeed.toFloat() + CallerChassisLocationGCJ02ListenerManager.invokeChassisLocationGCJ02( + mogoLocation, + DataSourceType.OBU + ) + Thread.sleep(100) + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + + fun loadRawPoints(path:String) { + val inputStream = FileInputStream(path) + val reader = BufferedReader(InputStreamReader(inputStream)) + val jsonStr = StringBuilder() + var line: String? = "" + try { + while (reader.readLine().also { line = it } != null) { + jsonStr.append(line) + } + } catch (e: IOException) { + e.printStackTrace() + } + val list = GsonUtils.fromJson>( + jsonStr.toString(), + object : TypeToken?>() {}.type + ) + val newBuilder = MessagePad.GlobalPathResp.newBuilder() + + for (latLng in list) { + val locationBuilder = MessagePad.Location.newBuilder() + locationBuilder.latitude = latLng.latitude + locationBuilder.longitude = latLng.longitude + newBuilder.addWayPoints(locationBuilder) + } + + val mogoLocation = MogoLocation() + + mogoLocation.latitude = list[0].latitude + mogoLocation.longitude = list[0].longitude + + val mogoSecondLocation = MogoLocation() + mogoSecondLocation.latitude = list[1].latitude + mogoSecondLocation.longitude = list[1].longitude + val angle = CoordinateCalculateRouteUtil.getHeadingAngle( + mogoLocation, + mogoSecondLocation + ) + mogoLocation.heading = angle + + CallerChassisLocationGCJ02ListenerManager.invokeChassisLocationGCJ02( + mogoLocation, + DataSourceType.OBU + ) + CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG,"轨迹点个数:${list.size}") + // 发送轨迹 + CallerPlanningRottingListenerManager.invokeAutopilotRotting(newBuilder.build()) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/location/MogoLocationExit.kt b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/location/MogoLocationExit.kt new file mode 100644 index 0000000000..838e172b40 --- /dev/null +++ b/OCH/mogo-och-common-module/src/debug/java/com/mogo/och/common/module/debug/location/MogoLocationExit.kt @@ -0,0 +1,30 @@ +package com.mogo.och.common.module.debug.location + +data class MogoLocationExit( + val localTime: Long, + val msg: Msg +) +data class Msg( + val GnssInfo: GnssInfo, + val Header: Header, + val stringDate0: String +) + +data class Header( + val msgID: Int, + val msgType: String, + val sourceTimestamp: Double, + val timestamp: Double +) + +data class GnssInfo( + val acceleration: Double, + val altitude: Double, + val gnssSpeed: Double, + val heading: Double, + val latitude: Double, + val longitude: Double, + val satelliteTime: Double, + val systemTime: Double, + val yawRate: Double +) \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/constant/OchCommonConst.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/constant/OchCommonConst.kt index 7102e3a8f3..fe0e21da28 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/constant/OchCommonConst.kt +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/constant/OchCommonConst.kt @@ -15,6 +15,10 @@ class OchCommonConst { fun getShuttleUrl(): String { return FunctionBuildConfig.urlJson.shuttleUrl } + @JvmStatic + fun getSweeperUrl(): String { + return FunctionBuildConfig.urlJson.sweeperUrl + } // token 失效 重新获取token const val WAIT_TAKEN = 100046 diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/DistanceDegree.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/DistanceDegree.kt new file mode 100644 index 0000000000..205510c9da --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/DistanceDegree.kt @@ -0,0 +1,13 @@ +package com.mogo.och.common.module.manager.distancemamager + +data class DistanceDegree(var distance:Float,var degree:Double?,var isNext:Boolean?):Comparable{ + override fun compareTo(other: DistanceDegree): Int { + // 对比距离 + if(distance == other.distance){ + return 0; + } else if(distance < other.distance){ + return -1; + } + return 1; + } +} diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/IDistanceListener.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/IDistanceListener.kt new file mode 100644 index 0000000000..d199f69d5b --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/IDistanceListener.kt @@ -0,0 +1,38 @@ +package com.mogo.och.common.module.manager.distancemamager + +import com.mogo.eagle.core.data.map.MogoLocation + +interface IDistanceListener { + /** + * @param distance 距离终点坐标的距离 + */ + fun distanceCallback(distance: Float) +} + +interface ITrajectoryListener{ + /** + * @param routeArrivied 已经走过的坐标 + * @param routeArriving 没有走过的坐标 + * @param location 车的坐标 + * @return + */ + fun trajectoryCallback( + routeArrivied: MutableList, + routeArriving: MutableList, + location: MogoLocation + ) +} + +interface ITrajectoryWithStationListener{ + /** + * @param routeArrivied 已经走过的坐标 第一个是站点坐标 + * @param routeArriving 没有走过的坐标 最后一个事站点坐标 + * @param location 车的坐标 + * @return + */ + fun trajectoryWithStationCallback( + routeArrivied: MutableList, + routeArriving: MutableList, + location: MogoLocation + ) +} \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/StationAndIndex.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/StationAndIndex.kt new file mode 100644 index 0000000000..9b76dcc949 --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/StationAndIndex.kt @@ -0,0 +1,10 @@ +package com.mogo.och.common.module.manager.distancemamager + +import com.mogo.eagle.core.data.map.MogoLocation + +data class StationAndIndex( + var stationPoint: MogoLocation?,// 站点坐标 + var index: Int?,// 坐标对应轨迹中最近的点 + var distance: Float?,//轨迹中最近的点 + var isNext:Boolean?,// 最近的点在轨迹中是在站点的下一个还是上一个 +) diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/TrajectoryAndDistanceManager.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/TrajectoryAndDistanceManager.kt new file mode 100644 index 0000000000..fffccac800 --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/distancemamager/TrajectoryAndDistanceManager.kt @@ -0,0 +1,421 @@ +package com.mogo.och.common.module.manager.distancemamager + +import com.mogo.commons.AbsMogoApplication +import com.mogo.eagle.core.data.deva.chain.ChainConstant +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.och.common.module.manager.loopmanager.BusPassengerModelLoopManager +import com.mogo.och.common.module.manager.loopmanager.LoopInfo +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil +import com.zhjt.service.chain.ChainLog +import mogo.telematics.pad.MessagePad +import java.util.concurrent.ConcurrentHashMap + +object TrajectoryAndDistanceManager: IMoGoPlanningRottingListener{ + + private val distanceListeners: ConcurrentHashMap = ConcurrentHashMap() + private val trajectoryListeners: ConcurrentHashMap = ConcurrentHashMap() + private val trajectoryWithStationListeners: ConcurrentHashMap = ConcurrentHashMap() + + const val TAG = "DistanceManager" + const val TAGDISTANCE = "BusPassengerModelDistance" + + + fun addDistanceListener(tag: String, listener: IDistanceListener) { + if (distanceListeners.containsKey(tag)) { return } + distanceListeners[tag] = listener + } + fun addTrajectoryListener(tag: String, listener: ITrajectoryListener) { + if (trajectoryListeners.containsKey(tag)) { return } + trajectoryListeners[tag] = listener + } + fun addTrajectoryWithStationListener(tag: String, listener: ITrajectoryWithStationListener) { + if (trajectoryWithStationListeners.containsKey(tag)) { return } + trajectoryWithStationListeners[tag] = listener + } + + /** + * 删除监听 + * @param tag 标记,用来注销监听使用 + */ + fun removeListener(tag: String) { + distanceListeners.remove(tag) + trajectoryListeners.remove(tag) + trajectoryWithStationListeners.remove(tag) + } + + + + @Volatile + private var mRoutePoints: MutableList? = ArrayList() + + @Volatile + private var lineId:Long? = null + + @Volatile + private var endStationInfo: StationAndIndex = StationAndIndex(null, null, null, null) + + @Volatile + private var startStationInfo: StationAndIndex = StationAndIndex(null, null, null, null) + + //上一次计算最近点的缓存 + private var preCarLocationIndexInTrajectory = 0 + + // TODO: 计算整个轨迹的长度 + // TODO: 计算轨迹点之间的长度、及轨迹点间最大长度 + + init { + CallerPlanningRottingListenerManager.addListener(TAG, this) + } + + override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) { + d(M_OCHCOMMON + TAG, "onAutopilotRotting: 收到轨迹") + globalPathResp?.wayPointsList?.let { + if (it.size > 0) { + d(M_OCHCOMMON + TAG, "收到轨迹:${it.size}第一个点${it[0]}最后一个点:${it.last()}") + if(globalPathResp.lineId!=null) { + if (globalPathResp.lineId == lineId) { + d(M_OCHCOMMON + TAG, "重复轨迹") + startCalculateDistanceLoop() + return + } + this.lineId = globalPathResp.lineId + } + endCalculateDistanceLoop() + updateRoutePoints(it) + preCarLocationIndexInTrajectory = 0 + startCalculateDistanceLoop() + } + } + } + + private fun updateRoutePoints(routePoints: List?) { + mRoutePoints = null + val latLngModels = CoordinateCalculateRouteUtil + .coordinateConverterWgsToGcjLocations(AbsMogoApplication.getApp(), routePoints!!) + mRoutePoints = latLngModels + } + + private fun removeTempData() { + resetStation() + preCarLocationIndexInTrajectory = 0 + lineId = null + } + private fun resetStation() { + this.endStationInfo.index = null + this.endStationInfo.distance = null + this.endStationInfo.isNext = null + this.startStationInfo.index = null + this.startStationInfo.distance = null + this.startStationInfo.isNext = null + } + + fun cleanRoutePoints() { + mRoutePoints = null + } + + /** + * 设置或清理站点坐标 + */ + fun setStationPoint(startStationInfo: MogoLocation?,endStationInfo: MogoLocation?,lineId:Long?) { + if (startStationInfo == null || endStationInfo == null || lineId == -1L) { + removeTempData() + endCalculateDistanceLoop() + cleanRoutePoints() + }else{ + if(isSameStation(this.startStationInfo.stationPoint,startStationInfo)&& + isSameStation(this.endStationInfo.stationPoint,endStationInfo)){ + if(this.lineId!=lineId){ + resetStation() + } + }else{ + resetStation() + } + this.endStationInfo.stationPoint = endStationInfo + this.startStationInfo.stationPoint = startStationInfo + this.lineId = lineId + startCalculateDistanceLoop() + } + } + + private fun isSameStation(stationOne: MogoLocation?,stationTwo: MogoLocation?):Boolean{ + if(stationOne==null||stationTwo==null){ + return false + } + if(stationOne.longitude==stationTwo.longitude&&stationOne.latitude==stationTwo.latitude){ + return true + } + return false + } + + /** + * 根据两点距离和轨迹距离来计算真实距离 + */ + private fun calculateDistance() { + //mLocation gcj坐标 + CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02().let { + if (mRoutePoints.isNullOrEmpty() || endStationInfo.stationPoint == null) { + d(M_OCHCOMMON + TAG, "没有轨迹或站点坐标停止计算") + //结束距离计算 + endCalculateDistanceLoop() + return + } + if(it.latitude==0.0&&it.longitude==0.0){ + return + } + calculateRouteSumLength(it) + } + } + + /** + * 暂停路距计算 + */ + fun suspendCalculate(){ + endCalculateDistanceLoop() + } + + fun reStartCalculate(){ + startCalculateDistanceLoop() + } + + /** + * 启动路距计算 + */ + private fun startCalculateDistanceLoop() { + BusPassengerModelLoopManager.setLoopFunction(TAGDISTANCE, LoopInfo(1, ::calculateDistance)) + d(SceneConstant.M_BUS_P + TAG, "开始路距计算") + } + + /** + * 结束启动路距计算 + */ + private fun endCalculateDistanceLoop() { + BusPassengerModelLoopManager.removeLoopFunction(TAGDISTANCE) + d(SceneConstant.M_BUS_P + TAG, "结束路距计算") + } + + + @Synchronized + fun calculateRouteSumLength( + location: MogoLocation, + ) { + val autoPilotState = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state + val locationInfo = "自动驾驶状态:$autoPilotState line信息:${lineId}定位信息:${location.latitude},${location.longitude},${location.heading}" + if (mRoutePoints.isNullOrEmpty()) return + // 计算起始站点在轨迹中的信息 这个是一个常量 + if (startStationInfo.stationPoint != null + && startStationInfo.isNext == null + && startStationInfo.index == null + && startStationInfo.distance == null + ) { + //要前往的站在轨迹中对应的点的信息 + val startStationInfo = CoordinateCalculateRouteUtil.getNearestPointInfo( + preCarLocationIndexInTrajectory, mRoutePoints!!.size,mRoutePoints!!, startStationInfo.stationPoint!!,1 + ) + this.startStationInfo.isNext = startStationInfo.second + this.startStationInfo.index = startStationInfo.first + this.startStationInfo.distance = startStationInfo.third + preCarLocationIndexInTrajectory = startStationInfo.first + val calculateData = "距离起始站点最近的点:${startStationInfo.first} 点在站的后面:${startStationInfo.second} 距离点的距离:${startStationInfo.third}" + writeLog(calculateData,locationInfo) + } + + // 计算结束站点在轨迹中的信息 这个是一个常量可以缓存 + if (endStationInfo.stationPoint != null + && endStationInfo.isNext == null + && endStationInfo.index == null + && endStationInfo.distance == null + ) { + //要前往的站在轨迹中对应的点 + val endStationInfo = CoordinateCalculateRouteUtil.getNearestPointInfo( + preCarLocationIndexInTrajectory,mRoutePoints!!.size, mRoutePoints!!, endStationInfo.stationPoint!!,3 + ) + this.endStationInfo.isNext = endStationInfo.second + this.endStationInfo.index = endStationInfo.first + this.endStationInfo.distance = endStationInfo.third + val calculateData = "距离结束站点最近的点:${endStationInfo.first} 点在站的后面:${endStationInfo.second} 距离点的距离:${endStationInfo.third}" + writeLog(calculateData, locationInfo) + } + + val carLocationInfo:Triple + if(endStationInfo.isNext==true){ + // 计算车的位置在轨迹中的信息 这个是一个变量可以缓存 + carLocationInfo = CoordinateCalculateRouteUtil.getNearestPointInfo( + preCarLocationIndexInTrajectory,endStationInfo.index!!, mRoutePoints!!, location,2 + ) + }else{ + carLocationInfo = CoordinateCalculateRouteUtil.getNearestPointInfo( + preCarLocationIndexInTrajectory,endStationInfo.index!!+1, mRoutePoints!!, location,2 + ) + } + val calculateData = "距离结束站点最近的点:${carLocationInfo.first} 点在站的后面:${carLocationInfo.second} 距离点的距离:${carLocationInfo.third}" + writeLog(calculateData, locationInfo) + if(carLocationInfo.second==null||carLocationInfo.third>1_000){ + preCarLocationIndexInTrajectory = 0 + return + } + preCarLocationIndexInTrajectory = carLocationInfo.first + + // 距离回调 + try { + if(distanceListeners.size>0) { + invokeDistance(carLocationInfo, location) + } + }catch (e:Exception){ + e(M_OCHCOMMON+ TAG,"距离计算错误") + } + // 不带站点轨迹回调 + try { + if(trajectoryListeners.size>0) { + invokeTrajectory(carLocationInfo, location) + } + }catch (e:Exception){ + e(M_OCHCOMMON+ TAG,"轨迹线(轨迹两头)计算错误") + } + + // 只展示站点之间轨迹 + try { + if(trajectoryWithStationListeners.size>0) { + invokeTrajectoryWithStation(carLocationInfo, location) + } + }catch (e:Exception){ + e(M_OCHCOMMON+ TAG,"轨迹线(站点两头)计算错误") + } + + } + + + private fun invokeDistance(carLocationInfo:Triple,location: MogoLocation){ + var lastSumLength = 0f + + val stationIndex = endStationInfo.index?:0 + if (carLocationInfo.first < stationIndex-1) { + // subList 是[) 需要的是[] + val subList = mRoutePoints!!.subList(carLocationInfo.first, stationIndex + 1) + // 轨迹点所有的距离 + lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(subList) + val stationDistance = endStationInfo.distance ?: 0f + if (endStationInfo.isNext == true) {// isNext = true + lastSumLength -= stationDistance + } else {// isNext = false + lastSumLength += stationDistance + } + if (carLocationInfo.second == true) {// 是否是下一个 true 下一个 + lastSumLength += carLocationInfo.third + } else { + lastSumLength -= carLocationInfo.third + } + } else { + val lastPoints = endStationInfo.stationPoint + lastSumLength = CoordinateUtils.calculateLineDistance( + lastPoints!!.longitude, lastPoints!!.latitude, + location.longitude, location.latitude + ) + } + d(M_OCHCOMMON+ TAG,"距离终点:$lastSumLength") + if(distanceListeners.size>0) { + distanceListeners.forEach { + //val tag = it.key + val listener = it.value + listener.distanceCallback(lastSumLength) + } + } + } + + private fun invokeTrajectory( + carLocationInfo: Triple, + location: MogoLocation + ) { + if (mRoutePoints.isNullOrEmpty()) return + val routeArrivied = mutableListOf() + val routeArriving = mutableListOf() + if(carLocationInfo.second==true){// isNext = true + routeArrivied.addAll(mRoutePoints!!.subList(0,carLocationInfo.first)) + routeArriving.addAll(mRoutePoints!!.subList(carLocationInfo.first,mRoutePoints!!.size)) + }else{// isNext = false + val indexNext = carLocationInfo.first+1 + routeArrivied.addAll(mRoutePoints!!.subList(0,indexNext)) + routeArriving.addAll(mRoutePoints!!.subList(indexNext,mRoutePoints!!.size)) + } + if(trajectoryListeners.size>0) { + trajectoryListeners.forEach { + //val tag = it.key + val listener = it.value + listener.trajectoryCallback(routeArrivied, routeArriving, location) + } + } + } + + private fun invokeTrajectoryWithStation( + carLocationInfo: Triple, + location: MogoLocation + ) { + if (mRoutePoints.isNullOrEmpty()) return + val routeArrivied = mutableListOf() + val routeArriving = mutableListOf() + var fromCut = 0 + var endCut = mRoutePoints!!.size + if (startStationInfo.stationPoint != null + && startStationInfo.isNext != null + && startStationInfo.index != null + && startStationInfo.distance != null + ) { + if(startStationInfo.isNext==true){ + fromCut = startStationInfo.index!! + }else{ + fromCut = startStationInfo.index!!+1 + } + } + + if (endStationInfo.stationPoint != null + && endStationInfo.isNext != null + && endStationInfo.index != null + && endStationInfo.distance != null + ) { + if(endStationInfo.isNext==true){ + endCut = endStationInfo.index!! + }else{ + endCut = endStationInfo.index!!+1 + } + } + d(M_OCHCOMMON+ TAG,"根据站点切个:第一个点:$fromCut 最后一个点$endCut") + if(carLocationInfo.second==true){// isNext = true + routeArrivied.addAll(mRoutePoints!!.subList(fromCut,carLocationInfo.first)) + routeArriving.addAll(mRoutePoints!!.subList(carLocationInfo.first,endCut)) + }else{// isNext = false + val indexNext = carLocationInfo.first+1 + routeArrivied.addAll(mRoutePoints!!.subList(fromCut,indexNext)) + routeArriving.addAll(mRoutePoints!!.subList(indexNext,endCut)) + } + + routeArrivied.add(0, startStationInfo.stationPoint!!) + routeArriving.add(endStationInfo.stationPoint!!) + if(trajectoryWithStationListeners.size>0) { + trajectoryWithStationListeners.forEach { + //val tag = it.key + val listener = it.value + listener.trajectoryWithStationCallback(routeArrivied, routeArriving, location) + } + } + } + + @ChainLog( + linkChainLog = ChainConstant.CHAIN_TYPE_OCH, + linkCode = ChainConstant.CHAIN_SOURCE_OCH, + nodeAliasCode = ChainConstant.CHAIN_CODE_OCH_COMMON_DISTANCE, + paramIndexes = [0,1] + ) + fun writeLog(carLocationInfo: String, location: String) { + d(M_OCHCOMMON+ TAG,carLocationInfo) + d(M_OCHCOMMON+ TAG,location) + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/net/BusPassengerModelLoopManager.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/BusPassengerModelLoopManager.kt similarity index 89% rename from OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/net/BusPassengerModelLoopManager.kt rename to OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/BusPassengerModelLoopManager.kt index a0b3b6a44f..aaacdf7319 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/net/BusPassengerModelLoopManager.kt +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/BusPassengerModelLoopManager.kt @@ -1,9 +1,7 @@ -package com.mogo.och.bus.passenger.net +package com.mogo.och.common.module.manager.loopmanager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P -import com.mogo.och.bus.passenger.bean.LoopInfo -import com.mogo.och.bus.passenger.constant.CharterPassengerConst import com.mogo.och.common.module.utils.RxUtils import io.reactivex.Observable import io.reactivex.disposables.Disposable @@ -22,6 +20,9 @@ object BusPassengerModelLoopManager { private val mControllerStatusCallbackMap = ConcurrentHashMap() + const val LOOP_LINE_2S = 2 * 1000L + const val LOOP_LINE_1S = 1 * 1000L + const val LOOP_DELAY = 100L fun setLoopFunction(tag: String, function: LoopInfo) { if (tag.isBlank()) return @@ -56,10 +57,7 @@ object BusPassengerModelLoopManager { return } CallerLogger.i(M_BUS_P + TAG, "startQueryDriverLineLoop()") - mQueryLineDisposable = Observable.interval( - CharterPassengerConst.LOOP_DELAY, - CharterPassengerConst.LOOP_LINE_1S, TimeUnit.MILLISECONDS - ) + mQueryLineDisposable = Observable.interval(LOOP_DELAY, LOOP_LINE_1S, TimeUnit.MILLISECONDS) .map { aLong: Long -> aLong + 1 } .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) diff --git a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/bean/LoopInfo.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/LoopInfo.kt similarity index 63% rename from OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/bean/LoopInfo.kt rename to OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/LoopInfo.kt index 9092b0146a..88aba91287 100644 --- a/OCH/mogo-och-charter-passenger/src/main/java/com/mogo/och/bus/passenger/bean/LoopInfo.kt +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/manager/loopmanager/LoopInfo.kt @@ -1,3 +1,3 @@ -package com.mogo.och.bus.passenger.bean +package com.mogo.och.common.module.manager.loopmanager data class LoopInfo(val interval:Long,val function: () -> Unit,val immediately:Boolean=false) \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java index 513bfa6c34..df497db14a 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java @@ -34,6 +34,8 @@ public class AnimatorDrawableUtil { private ImageView mImageView = null; //图片资源的ID列表 private List mResourceIdList = null; + //图片bitmap列表 + private List mBitmapList = null; //定时任务器 private final Timer mTimer = new Timer(); //定时任务 @@ -54,10 +56,17 @@ public class AnimatorDrawableUtil { mImageView = imageview; if(mResourceIdList==null){ mResourceIdList = new ArrayList(); + mBitmapList = new ArrayList<>(); }else{ mResourceIdList.clear(); + mBitmapList.clear(); } mResourceIdList.addAll(resourceIdList); + + //在初始化时候就将资源文件decode + for (int i = 0; i <= resourceIdList.size()-1; i++){ + mBitmapList.add(readBitMap(mImageView.getContext(),resourceIdList.get(i))); + } } /** @@ -67,14 +76,19 @@ public class AnimatorDrawableUtil { this.mImageView = imageview; if(mResourceIdList==null){ mResourceIdList = new ArrayList(); + mBitmapList = new ArrayList<>(); }else{ mResourceIdList.clear(); + mBitmapList.clear(); } loadFromXml(context, resourceId, new OnParseListener() { @Override public void onParse(List res) { mResourceIdList.addAll(res); + for (int i = 0; i <= res.size()-1; i++){ + mBitmapList.add(readBitMap(mImageView.getContext(),res.get(i))); + } } }); } @@ -219,8 +233,13 @@ public class AnimatorDrawableUtil { case MSG_START: { if (mFrameIndex >= 0 && mFrameIndex < mResourceIdList.size() && mState == STATE_RUNNING) { //这里不能使用image.setImageResource 因为源码中也是创建了bitmap 所以这里我们自己创建 - Bitmap bitmap=readBitMap(mImageView.getContext(),mResourceIdList.get(mFrameIndex)); - mImageView.setImageBitmap(bitmap); + if (mBitmapList != null && mBitmapList.size()-1 >= mFrameIndex){ + Bitmap bitmap= mBitmapList.get(mFrameIndex); + mImageView.setImageBitmap(bitmap); + }else { + Bitmap bitmap=readBitMap(mImageView.getContext(),mResourceIdList.get(mFrameIndex)); + mImageView.setImageBitmap(bitmap); + } mFrameIndex++; } } diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.java deleted file mode 100644 index c4c38034c1..0000000000 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.java +++ /dev/null @@ -1,504 +0,0 @@ -package com.mogo.och.common.module.utils; - -import android.content.Context; -import android.location.Location; - -import com.amap.api.maps.CoordinateConverter; -import com.amap.api.maps.model.LatLng; -import com.mogo.eagle.core.data.map.MogoLocation; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; -import com.mogo.eagle.core.utilcode.util.CoordinateUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import kotlin.Triple; -import mogo.telematics.pad.MessagePad; - -/** - * @author: wangmingjun - * @date: 2022/3/28 - */ -public class CoordinateCalculateRouteUtil { - - public static float calculateRouteSumLength(List points){ - if (null == points || points.size() == 0) return 0; - - float sumLength = 0; - - if (points.get(0) instanceof MogoLocation){ - //计算全路径总距离 - for (int i = 0;i + 1< points.size();i++){ - MogoLocation locationPre = (MogoLocation) points.get(i); - MogoLocation location = (MogoLocation) points.get(i+1); - double preLat = locationPre.getLatitude(); - double preLon = locationPre.getLongitude(); - double laLat = location.getLatitude(); - double laLon = location.getLongitude(); - - float length = CoordinateUtils.calculateLineDistance(laLon,laLat,preLon,preLat); - sumLength += length; - } - }else if (points.get(0) instanceof Location){ - //计算全路径总距离 - for (int i = 0;i + 1< points.size();i++){ - Location locationPre = (Location) points.get(i); - Location location = (Location) points.get(i+1); - double preLat = locationPre.getLatitude(); - double preLon = locationPre.getLongitude(); - double laLat = location.getLatitude(); - double laLon = location.getLongitude(); - - float length = CoordinateUtils.calculateLineDistance(laLon,laLat,preLon,preLat); - sumLength += length; - } - }else if (points.get(0) instanceof LatLng){ - for (int i = 0;i + 1< points.size();i++){ - LatLng locationPre = (LatLng) points.get(i); - LatLng location = (LatLng) points.get(i+1); - double preLat = locationPre.latitude; - double preLon = locationPre.longitude; - double laLat = location.latitude; - double laLon = location.longitude; - - float length = CoordinateUtils.calculateLineDistance(laLon,laLat,preLon,preLat); - sumLength += length; - } - } - return sumLength; - } - - public static float calculateRouteSumLength(List mRoutePoints, MogoLocation location, MogoLocation station){ - if (null == mRoutePoints || mRoutePoints.size() == 0) return 0; - - float lastSumLength = 0f; - - //当前位置距离轨迹中最近的点 - int currentRouteIndex = getArrivedPointIndexNew( - 0, mRoutePoints, location.getLongitude(), location.getLatitude() - ); - // 距离当前位置轨迹中最近的轨迹点坐标 - MogoLocation currentPoint = mRoutePoints.get(currentRouteIndex); - // 当前位置距离最近的点的距离 - float calculateCurrentdex = CoordinateUtils.calculateLineDistance( - location.getLongitude(), location.getLatitude(), - currentPoint.getLongitude(), currentPoint.getLatitude() - ); - - - //要前往的站在轨迹中对应的点 - int stationPointInRouteIndex = getArrivedPointIndexNew( - currentRouteIndex, mRoutePoints, - station.getLongitude(), - station.getLatitude() - ); - // 距离站点最近的轨迹点 - MogoLocation stationPointInRoute = mRoutePoints.get(stationPointInRouteIndex); - // 站点距离轨迹中最近点的距离 - float calculateLineDistance = CoordinateUtils.calculateLineDistance( - stationPointInRoute.getLongitude(), stationPointInRoute.getLatitude(), - station.getLongitude(), station.getLatitude() - ); - - if (currentRouteIndex < stationPointInRouteIndex) { - // subList 是[) 需要的是[] - List subList = mRoutePoints.subList(currentRouteIndex, stationPointInRouteIndex + 1); - // 轨迹点所有的距离 - lastSumLength = calculateRouteSumLength(subList); - // region 站点坐标和 站点坐标对应轨迹点的坐标距离 - // 需要加距离 和下一个轨迹点成钝角 - if (stationPointInRouteIndex + 1 < mRoutePoints.size()) { - MogoLocation lastPointsNext = mRoutePoints.get(stationPointInRouteIndex + 1); - double degree = getDegree( - station.getLongitude(),station.getLatitude(), - stationPointInRoute.getLongitude(), stationPointInRoute.getLatitude(), - lastPointsNext.getLongitude(), lastPointsNext.getLatitude()); - if (degree > 90) { - lastSumLength = lastSumLength + calculateLineDistance; - } - } - // 需要减距离 和上一个轨迹点成钝角 - if (stationPointInRouteIndex - 1 >= 0) { - MogoLocation lastPointsPre = mRoutePoints.get(stationPointInRouteIndex - 1); - double degree = getDegree( - station.getLongitude(),station.getLatitude(), - stationPointInRoute.getLongitude(), stationPointInRoute.getLatitude(), - lastPointsPre.getLongitude(), lastPointsPre.getLatitude()); - if (degree > 90) { - lastSumLength = lastSumLength - calculateLineDistance; - } - } - // endregion - - // region 当前位置和 对应轨迹点的坐标距离 - // 需要加距离 和下一个轨迹点成钝角 - if (currentRouteIndex + 1 < stationPointInRouteIndex) { - MogoLocation currentPointsNext = mRoutePoints.get(currentRouteIndex + 1); - double degree = getDegree( - location.getLongitude(),location.getLatitude(), - currentPoint.getLongitude(), currentPoint.getLatitude(), - currentPointsNext.getLongitude(), currentPointsNext.getLatitude()); - if (degree > 90) { - lastSumLength = lastSumLength - calculateCurrentdex; - } - } - - // 需要减距离 和上一个轨迹点成钝角 - if (currentRouteIndex - 1 >= 0) { - MogoLocation lastPointsPre = mRoutePoints.get(currentRouteIndex - 1); - double degree = getDegree( - location.getLongitude(),location.getLatitude(), - currentPoint.getLongitude(), currentPoint.getLatitude(), - lastPointsPre.getLongitude(), lastPointsPre.getLatitude()); - if (degree > 90) { - lastSumLength = lastSumLength + calculateCurrentdex; - } - } - // endregion - - } else { - MogoLocation lastPoints = mRoutePoints.get(stationPointInRouteIndex); - lastSumLength = CoordinateUtils.calculateLineDistance( - lastPoints.getLongitude(), lastPoints.getLatitude(), - location.getLongitude(), location.getLatitude() - ); - } - return lastSumLength; - } - - public static List coordinateConverterWgsToGcjListCommon(Context mContext, List models) { - //转成MogoLatLng集合 - List list = new ArrayList<>(); - for (MessagePad.Location m : models) { - LatLng mogoLatLng = coordinateConverterWgsToGcj(mContext, m); - list.add(mogoLatLng); - } - return list; - } - - public static LatLng coordinateConverterWgsToGcj(Context mContext, MessagePad.Location mogoLatLng) { - CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); - mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); - mCoordinateConverter.coord(new LatLng(mogoLatLng.getLatitude(), mogoLatLng.getLongitude())); - LatLng latLng = mCoordinateConverter.convert(); - return latLng; - } - - public static LatLng coordinateConverterWgsToGcj(Context mContext, double lon, double lat) { - CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); - mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); - mCoordinateConverter.coord(new LatLng(lat,lon)); - LatLng latLng = mCoordinateConverter.convert(); - return latLng; - } - - /** - * 简单粗暴 直接比较 todo 需要优化 - * @param mRoutePoints - * @param realLon - * @param realLat - * @return - */ - public static List getRemainPointListByCompare(List mRoutePoints,double realLon,double realLat) { - List latePoints = new ArrayList<>(); - int currentIndex = 0; //记录疑似点 - if (mRoutePoints.size() > 0){ - //基础点 - LatLng baseLatLng = mRoutePoints.get(0); - if (baseLatLng != null){ - float baseDiffDis = CoordinateUtils.calculateLineDistance(realLon,realLat - ,baseLatLng.longitude,baseLatLng.latitude);// lon,lat, prelon, prelat - - for (int i= 1; i < mRoutePoints.size(); i++){ - LatLng latLng = mRoutePoints.get(i); - float diff = CoordinateUtils.calculateLineDistance(realLon,realLat - ,latLng.longitude,latLng.latitude); - if (baseDiffDis > diff){ -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); - baseDiffDis = diff; - currentIndex = i; - } - } -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+currentIndex+"-------是最近的点------ "); - if (currentIndex == mRoutePoints.size()-1){ - latePoints.add(mRoutePoints.get(currentIndex)); - }else if(currentIndex < mRoutePoints.size()-1){ - latePoints.addAll(mRoutePoints.subList(currentIndex,mRoutePoints.size())); - } - return latePoints; - } - - } - return latePoints; - } - - /** - * 简单粗暴 直接比较 todo 需要优化 - * @param mRoutePoints - * @param realLon - * @param realLat - * @return 返回已经到达点的index - */ - public static int getArrivedPointIndex(List mRoutePoints,double realLon,double realLat) { - int currentIndex = 0; //记录疑似点 - if (mRoutePoints.size() > 0){ - //基础点 - LatLng baseLatLng = mRoutePoints.get(0); - if (baseLatLng != null){ - float baseDiffDis = CoordinateUtils.calculateLineDistance(realLon,realLat - ,baseLatLng.longitude,baseLatLng.latitude);// lon,lat, prelon, prelat - - for (int i= 1; i < mRoutePoints.size(); i++){ - LatLng latLng = mRoutePoints.get(i); - float diff = CoordinateUtils.calculateLineDistance(realLon,realLat - ,latLng.longitude,latLng.latitude); - if (baseDiffDis > diff){ -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); - baseDiffDis = diff; - currentIndex = i; - } - } - return currentIndex; - } - } - return currentIndex; - } - - public static float calculateRouteSumLengthByLocation(List points){ - if (null == points || points.size() == 0) return 0; - - float sumLength = 0; - - //计算全路径总距离 - for (int i = 0;i + 1< points.size();i++){ - double preLat = points.get(i).getLatitude(); - double preLon = points.get(i).getLongitude(); - double laLat = points.get(i+1).getLatitude(); - double laLon = points.get(i+1).getLongitude(); - - float length = CoordinateUtils.calculateLineDistance(laLon,laLat,preLon,preLat); - sumLength += length; - } - return sumLength; - } - - - public static List coordinateConverterWgsToGcjLocations(Context mContext, List models) { - //转成MogoLatLng集合 - List list = new ArrayList<>(); - for (MessagePad.Location m : models) { - LatLng mogoLatLng = coordinateConverterWgsToGcj(mContext, m); - MogoLocation location = new MogoLocation(); - location.setHeading((float) m.getHeading()); - location.setLatitude(mogoLatLng.latitude); - location.setLongitude(mogoLatLng.longitude); - list.add(location); - } - return list; - } - - public static List coordinateConverterLatlngToLocation(List models) { - //转成MogoLatLng集合 - List list = new ArrayList<>(); - for (LatLng m : models) { - MogoLocation location = new MogoLocation(); - location.setLatitude(m.latitude); - location.setLongitude(m.longitude); - list.add(location); - } - return list; - } - - public static List coordinateConverterLocationToLatLng(Context mContext, List models) { - //转成MogoLatLng集合 - List list = new ArrayList<>(); - for (MogoLocation m : models) { - LatLng mogoLatLng = new LatLng(m.getLatitude(), m.getLongitude()); - list.add(mogoLatLng); - } - return list; - } - - /** - * 根据前一个index,经纬度航向角,确认剩余轨迹 - * @param preIndex - * @param mRoutePoints - * @param realLocation - * @return - */ - public static Map> getRemainPointListByCompareNew(int preIndex, - List mRoutePoints, - MogoLocation realLocation) { - Map> routePonits = new HashMap<>(); - List latePoints = new ArrayList<>(); // 剩余轨迹集合 - int currentIndex = 0; //记录疑似点 - if (mRoutePoints.size() > 0){ - //基础点 - MogoLocation baseLatLng = mRoutePoints.get(0); - float baseDiffDis = CoordinateUtils.calculateLineDistance(realLocation.getLongitude(), - realLocation.getLatitude() - ,baseLatLng.getLongitude(),baseLatLng.getLongitude());// lon,lat, prelon, prelat - - for (int i= 0; i < mRoutePoints.size(); i++){ - MogoLocation latLng = mRoutePoints.get(i); - //todo 先看index对应点的方向和realLocation方向是否一致, 方向角度不能过90度 - if (realLocation.getHeading() == realLocation.getHeading() - latLng.getHeading() || - Math.abs(realLocation.getHeading() - latLng.getHeading()) <= 90){ - float diff = CoordinateUtils.calculateLineDistance(realLocation.getLongitude(), - realLocation.getLatitude(), - latLng.getLongitude(),latLng.getLatitude()); - if (baseDiffDis > diff ){ -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); - baseDiffDis = diff; - currentIndex = i; - } - } - } - Logger.d( "calculateRouteSumLength", "点:"+currentIndex+"-------是最近的点------ "); - if (currentIndex == mRoutePoints.size()-1){ - MogoLocation location = mRoutePoints.get(currentIndex); -// LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); - latePoints.add(location); - }else { - List locations = mRoutePoints.subList(currentIndex,mRoutePoints.size()); - for (MogoLocation location: locations) { -// LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); - latePoints.add(location); - } - } - routePonits.put(currentIndex,latePoints); - return routePonits; - } - return routePonits; - } - - public static int getArrivedPointIndexNew(int preIndex, List mRoutePoints, - MogoLocation realLocation) { - int currentIndex = 0; //记录疑似点 //基础点 - MogoLocation baseLatLng = mRoutePoints.get(0); - float baseDiffDis = CoordinateUtils.calculateLineDistance(realLocation.getLongitude(), - realLocation.getLatitude() - , baseLatLng.getLongitude(), baseLatLng.getLongitude());// lon,lat, prelon, prelat - - for (int i = 0; i < mRoutePoints.size(); i++) { - MogoLocation latLng = mRoutePoints.get(i); - if (realLocation.getHeading() == realLocation.getHeading() - latLng.getHeading() || - Math.abs(realLocation.getHeading() - latLng.getHeading()) <= 90){ - float diff = CoordinateUtils.calculateLineDistance(realLocation.getLongitude(), - realLocation.getLatitude(), - latLng.getLongitude(), latLng.getLatitude()); - if (baseDiffDis > diff && i>currentIndex) { -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); - baseDiffDis = diff; - currentIndex = i; - } - } - } - Logger.d("calculateRouteSumLength", "点:" + currentIndex + "-------是最近的点------ "); - return currentIndex; - } - - public static int getArrivedPointIndexNew(int preIndex, List mRoutePoints, - double realLon,double realLat) { - int currentIndex = preIndex; //记录疑似点 //基础点 - MogoLocation baseLatLng = mRoutePoints.get(0); - float baseDiffDis = CoordinateUtils.calculateLineDistance(realLon, - realLat - , baseLatLng.getLongitude(), baseLatLng.getLongitude());// lon,lat, prelon, prelat - - for (int i = preIndex; i < mRoutePoints.size(); i++) { - MogoLocation latLng = mRoutePoints.get(i); -// if (realLocation.getBearing() == realLocation.getBearing() - latLng.getBearing() || -// Math.abs(realLocation.getBearing() - latLng.getBearing()) <= 90){ - float diff = CoordinateUtils.calculateLineDistance(realLon, - realLat, - latLng.getLongitude(), latLng.getLatitude()); - if (baseDiffDis > diff && i>currentIndex) { -// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); - baseDiffDis = diff; - currentIndex = i; - } -// } - } - Logger.d("calculateRouteSumLength", "点:" + currentIndex + "-------是最近的点------ "); - return currentIndex; - } - - /** - * https://blog.csdn.net/Jeanne_0523/article/details/106056255 - * @param vertexPointX - * @param vertexPointY - * @param point0X 角 - * @param point0Y 角 - * @param point1X - * @param point1Y - * @return - */ - public static int getDegree(double vertexPointX, double vertexPointY, double point0X, double point0Y, double point1X, double point1Y) { - //向量的点乘 - double vector = (point0X - vertexPointX) * (point1X - vertexPointX) + (point0Y - vertexPointY) * (point1Y - vertexPointY); - //向量的模乘 - double sqrt = Math.sqrt( - (Math.abs((point0X - vertexPointX) * (point0X - vertexPointX)) + Math.abs((point0Y - vertexPointY) * (point0Y - vertexPointY))) - * (Math.abs((point1X - vertexPointX) * (point1X - vertexPointX)) + Math.abs((point1Y - vertexPointY) * (point1Y - vertexPointY))) - ); - //反余弦计算弧度 - double radian = Math.acos(vector / sqrt); - //弧度转角度制 - return (int) (180 * radian / Math.PI); - } - - - private static Triple ball2xyz(Double thera,Double fie,Double r){ - double x = r * Math.cos(thera) * Math.cos(fie); - double y = r * Math.cos(thera) * Math.sin(fie); - double z = r * Math.sin(thera); - return new Triple(x,y,z); - } - - /** - * https://blog.csdn.net/reborn_lee/article/details/82497577 - * 将地理经纬度转换成笛卡尔坐标系 - */ - private static Triple geo2xyz(double lat,double lng){ - double thera = (Math.PI * lat) / 180; - double fie = (Math.PI * lng) / 180; - return ball2xyz(thera, fie,6400.0); - } - - /** - * 计算3个地理坐标点之间的夹角 - * @param l1 顶点坐标 - * @param l2 - * @param l3 - * @return l1为顶点的角度 精度没有angleOflocation高 - */ - public static double getDegree(LatLng l2,LatLng l1,LatLng l3) { - Triple p1 = geo2xyz(l1.latitude,l1.longitude); - Triple p2 = geo2xyz(l2.latitude,l2.longitude); - Triple p3 = geo2xyz(l3.latitude,l3.longitude); - - double x1 = p1.getFirst(); - double y1 = p1.getSecond(); - double z1 = p1.getThird(); - - double x2 = p2.getFirst(); - double y2 = p2.getSecond(); - double z2 = p2.getThird(); - - double x3 = p3.getFirst(); - double y3 = p3.getSecond(); - double z3 = p3.getThird(); - - // 计算向量 P2P1 和 P2P3 的夹角 https://www.zybang.com/question/3379a30c0dd3041b3ef966803f0bf758.html - double p1P2 = Math.sqrt(Math.pow(x2 - x1,2.0) + Math.pow(y2 - y1,2.0) + Math.pow(z2 - z1,2.0)); - double p2p3 = Math.sqrt(Math.pow(x3 - x2,2.0) + Math.pow(y3 - y2,2.0) + Math.pow(z3 - z2,2.0)); - - double p = (x1 - x2) * (x3 - x2) + (y1 - y2) * (y3 - y2) + (z1 - z2) * (z3 - z2); //P2P1*P2P3 - - return (Math.acos(p / (p1P2 * p2p3)) / Math.PI) * 180; - } - -} diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.kt new file mode 100644 index 0000000000..79444f76f5 --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/CoordinateCalculateRouteUtil.kt @@ -0,0 +1,805 @@ +package com.mogo.och.common.module.utils + +import android.content.Context +import android.location.Location +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.LatLng +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils +import com.mogo.och.common.module.manager.distancemamager.DistanceDegree +import mogo.telematics.pad.MessagePad +import java.util.TreeMap +import kotlin.math.acos +import kotlin.math.atan2 +import kotlin.math.cos +import kotlin.math.pow +import kotlin.math.sin +import kotlin.math.sqrt + +/** + * @author: wangmingjun + * @date: 2022/3/28 + */ +object CoordinateCalculateRouteUtil { + @JvmStatic + fun calculateRouteSumLength(points: List?): Float { + if (null == points || points.size == 0) return 0f + var sumLength = 0f + if (points[0] is MogoLocation) { + //计算全路径总距离 + var i = 0 + while (i + 1 < points.size) { + val locationPre = points[i] as MogoLocation + val location = points[i + 1] as MogoLocation + val preLat = locationPre.latitude + val preLon = locationPre.longitude + val laLat = location.latitude + val laLon = location.longitude + val length = CoordinateUtils.calculateLineDistance(laLon, laLat, preLon, preLat) + sumLength += length + i++ + } + } else if (points[0] is Location) { + //计算全路径总距离 + var i = 0 + while (i + 1 < points.size) { + val locationPre = points[i] as Location + val location = points[i + 1] as Location + val preLat = locationPre.latitude + val preLon = locationPre.longitude + val laLat = location.latitude + val laLon = location.longitude + val length = CoordinateUtils.calculateLineDistance(laLon, laLat, preLon, preLat) + sumLength += length + i++ + } + } else if (points[0] is LatLng) { + var i = 0 + while (i + 1 < points.size) { + val locationPre = points[i] as LatLng + val location = points[i + 1] as LatLng + val preLat = locationPre.latitude + val preLon = locationPre.longitude + val laLat = location.latitude + val laLon = location.longitude + val length = CoordinateUtils.calculateLineDistance(laLon, laLat, preLon, preLat) + sumLength += length + i++ + } + } + return sumLength + } + + fun calculateRouteSumLength( + mRoutePoints: List?, + location: MogoLocation, + station: MogoLocation + ): Float { + if (null == mRoutePoints || mRoutePoints.size == 0) return 0f + var lastSumLength = 0f + + //当前位置距离轨迹中最近的点 + val currentRouteIndex = getArrivedPointIndexNew( + 0, mRoutePoints, location.longitude, location.latitude + ) + // 距离当前位置轨迹中最近的轨迹点坐标 + val currentPoint = mRoutePoints[currentRouteIndex] + // 当前位置距离最近的点的距离 + val calculateCurrentdex = CoordinateUtils.calculateLineDistance( + location.longitude, location.latitude, + currentPoint.longitude, currentPoint.latitude + ) + + + //要前往的站在轨迹中对应的点 + val stationPointInRouteIndex = getArrivedPointIndexNew( + currentRouteIndex, mRoutePoints, + station.longitude, + station.latitude + ) + // 距离站点最近的轨迹点 + val stationPointInRoute = mRoutePoints[stationPointInRouteIndex] + // 站点距离轨迹中最近点的距离 + val calculateLineDistance = CoordinateUtils.calculateLineDistance( + stationPointInRoute.longitude, stationPointInRoute.latitude, + station.longitude, station.latitude + ) + if (currentRouteIndex < stationPointInRouteIndex) { + // subList 是[) 需要的是[] + val subList = mRoutePoints.subList(currentRouteIndex, stationPointInRouteIndex + 1) + // 轨迹点所有的距离 + lastSumLength = calculateRouteSumLength(subList) + // region 站点坐标和 站点坐标对应轨迹点的坐标距离 + // 需要加距离 和下一个轨迹点成钝角 + if (stationPointInRouteIndex + 1 < mRoutePoints.size) { + val lastPointsNext = mRoutePoints[stationPointInRouteIndex + 1] + val degree = getDegree( + station.longitude, station.latitude, + stationPointInRoute.longitude, stationPointInRoute.latitude, + lastPointsNext.longitude, lastPointsNext.latitude + ).toDouble() + if (degree > 90) { + lastSumLength = lastSumLength + calculateLineDistance + } + } + // 需要减距离 和上一个轨迹点成钝角 + if (stationPointInRouteIndex - 1 >= 0) { + val lastPointsPre = mRoutePoints[stationPointInRouteIndex - 1] + val degree = getDegree( + station.longitude, station.latitude, + stationPointInRoute.longitude, stationPointInRoute.latitude, + lastPointsPre.longitude, lastPointsPre.latitude + ).toDouble() + if (degree > 90) { + lastSumLength = lastSumLength - calculateLineDistance + } + } + // endregion + + // region 当前位置和 对应轨迹点的坐标距离 + // 需要加距离 和下一个轨迹点成钝角 + if (currentRouteIndex + 1 < stationPointInRouteIndex) { + val currentPointsNext = mRoutePoints[currentRouteIndex + 1] + val degree = getDegree( + location.longitude, location.latitude, + currentPoint.longitude, currentPoint.latitude, + currentPointsNext.longitude, currentPointsNext.latitude + ).toDouble() + if (degree > 90) { + lastSumLength = lastSumLength - calculateCurrentdex + } + } + + // 需要减距离 和上一个轨迹点成钝角 + if (currentRouteIndex - 1 >= 0) { + val lastPointsPre = mRoutePoints[currentRouteIndex - 1] + val degree = getDegree( + location.longitude, location.latitude, + currentPoint.longitude, currentPoint.latitude, + lastPointsPre.longitude, lastPointsPre.latitude + ).toDouble() + if (degree > 90) { + lastSumLength = lastSumLength + calculateCurrentdex + } + } + // endregion + } else { + val lastPoints = mRoutePoints[stationPointInRouteIndex] + lastSumLength = CoordinateUtils.calculateLineDistance( + lastPoints.longitude, lastPoints.latitude, + location.longitude, location.latitude + ) + } + return lastSumLength + } + + @JvmStatic + fun coordinateConverterWgsToGcjListCommon( + mContext: Context?, + models: List + ): List { + //转成MogoLatLng集合 + val list: MutableList = ArrayList() + for (m in models) { + val mogoLatLng = coordinateConverterWgsToGcj(mContext, m) + list.add(mogoLatLng) + } + return list + } + + @JvmStatic + fun coordinateConverterWgsToGcj( + mContext: Context?, + mogoLatLng: MessagePad.Location + ): LatLng { + val mCoordinateConverter = + CoordinateConverter(mContext) + mCoordinateConverter.from(CoordinateConverter.CoordType.GPS) + mCoordinateConverter.coord( + LatLng( + mogoLatLng.latitude, + mogoLatLng.longitude + ) + ) + return mCoordinateConverter.convert() + } + + @JvmStatic + fun coordinateConverterWgsToGcj( + mContext: Context?, + lon: Double, + lat: Double + ): LatLng { + val mCoordinateConverter = + CoordinateConverter(mContext) + mCoordinateConverter.from(CoordinateConverter.CoordType.GPS) + mCoordinateConverter.coord(LatLng(lat, lon)) + return mCoordinateConverter.convert() + } + + /** + * 简单粗暴 直接比较 todo 需要优化 + * @param mRoutePoints + * @param realLon + * @param realLat + * @return + */ + fun getRemainPointListByCompare( + mRoutePoints: List, + realLon: Double, + realLat: Double + ): List { + val latePoints: MutableList = ArrayList() + var currentIndex = 0 //记录疑似点 + if (mRoutePoints.size > 0) { + //基础点 + val baseLatLng = mRoutePoints[0] + if (baseLatLng != null) { + var baseDiffDis = CoordinateUtils.calculateLineDistance( + realLon, realLat, baseLatLng.longitude, baseLatLng.latitude + ) // lon,lat, prelon, prelat + for (i in 1 until mRoutePoints.size) { + val latLng = mRoutePoints[i] + val diff = CoordinateUtils.calculateLineDistance( + realLon, realLat, latLng.longitude, latLng.latitude + ) + if (baseDiffDis > diff) { +// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); + baseDiffDis = diff + currentIndex = i + } + } + // Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+currentIndex+"-------是最近的点------ "); + if (currentIndex == mRoutePoints.size - 1) { + latePoints.add(mRoutePoints[currentIndex]) + } else if (currentIndex < mRoutePoints.size - 1) { + latePoints.addAll(mRoutePoints.subList(currentIndex, mRoutePoints.size)) + } + return latePoints + } + } + return latePoints + } + + /** + * 简单粗暴 直接比较 todo 需要优化 + * @param mRoutePoints + * @param realLon + * @param realLat + * @return 返回已经到达点的index + */ + fun getArrivedPointIndex(mRoutePoints: List, realLon: Double, realLat: Double): Int { + var currentIndex = 0 //记录疑似点 + if (mRoutePoints.size > 0) { + //基础点 + val baseLatLng = mRoutePoints[0] + if (baseLatLng != null) { + var baseDiffDis = CoordinateUtils.calculateLineDistance( + realLon, realLat, baseLatLng.longitude, baseLatLng.latitude + ) // lon,lat, prelon, prelat + for (i in 1 until mRoutePoints.size) { + val latLng = mRoutePoints[i] + val diff = CoordinateUtils.calculateLineDistance( + realLon, realLat, latLng.longitude, latLng.latitude + ) + if (baseDiffDis > diff) { +// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); + baseDiffDis = diff + currentIndex = i + } + } + return currentIndex + } + } + return currentIndex + } + + fun calculateRouteSumLengthByLocation(points: List?): Float { + if (points.isNullOrEmpty()) return 0f + var sumLength = 0f + + //计算全路径总距离 + var i = 0 + while (i + 1 < points.size) { + val preLat = points[i].latitude + val preLon = points[i].longitude + val laLat = points[i + 1].latitude + val laLon = points[i + 1].longitude + val length = CoordinateUtils.calculateLineDistance(laLon, laLat, preLon, preLat) + sumLength += length + i++ + } + return sumLength + } + + @JvmStatic + fun coordinateConverterWgsToGcjLocations( + mContext: Context?, + models: List + ): MutableList { + //转成MogoLatLng集合 + val list = mutableListOf() + for (m in models) { + val mogoLatLng = coordinateConverterWgsToGcj(mContext, m) + val location = MogoLocation() + location.heading = m.heading.toFloat().toDouble() + location.latitude = mogoLatLng.latitude + location.longitude = mogoLatLng.longitude + list.add(location) + } + return list + } + + @JvmStatic + fun coordinateConverterLatlngToLocation(models: List): List { + //转成MogoLatLng集合 + val list: MutableList = ArrayList() + for (m in models) { + val location = MogoLocation() + location.latitude = m.latitude + location.longitude = m.longitude + list.add(location) + } + return list + } + + @JvmStatic + fun coordinateConverterLocationToLatLng( + mContext: Context?, + models: List + ): List { + //转成MogoLatLng集合 + val list: MutableList = ArrayList() + for (m in models) { + val mogoLatLng = LatLng(m.latitude, m.longitude) + list.add(mogoLatLng) + } + return list + } + + /** + * 根据前一个index,经纬度航向角,确认剩余轨迹 + * @param preIndex + * @param mRoutePoints + * @param realLocation + * @return + */ + @JvmStatic + fun getRemainPointListByCompareNew( + preIndex: Int, + mRoutePoints: List, + realLocation: MogoLocation + ): Map> { + val routePonits: MutableMap> = HashMap() + val latePoints: MutableList = ArrayList() // 剩余轨迹集合 + var currentIndex = 0 //记录疑似点 + if (mRoutePoints.size > 0) { + //基础点 + val baseLatLng = mRoutePoints[0] + var baseDiffDis = CoordinateUtils.calculateLineDistance( + realLocation.longitude, + realLocation.latitude, baseLatLng.longitude, baseLatLng.longitude + ) // lon,lat, prelon, prelat + for (i in mRoutePoints.indices) { + val latLng = mRoutePoints[i] + //todo 先看index对应点的方向和realLocation方向是否一致, 方向角度不能过90度 + if (realLocation.heading == realLocation.heading - latLng.heading || + Math.abs(realLocation.heading - latLng.heading) <= 90 + ) { + val diff = CoordinateUtils.calculateLineDistance( + realLocation.longitude, + realLocation.latitude, + latLng.longitude, latLng.latitude + ) + if (baseDiffDis > diff) { + baseDiffDis = diff + currentIndex = i + } + } + } + Logger.d("calculateRouteSumLength", "点:$currentIndex-------是最近的点------ ") + if (currentIndex == mRoutePoints.size - 1) { + val location = mRoutePoints[currentIndex] + // LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); + latePoints.add(location) + } else { + val locations = mRoutePoints.subList(currentIndex, mRoutePoints.size) + for (location in locations) { +// LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); + latePoints.add(location) + } + } + routePonits[currentIndex] = latePoints + return routePonits + } + return routePonits + } + + @JvmStatic + fun getArrivedPointIndexNew( + preIndex: Int, mRoutePoints: List, + realLocation: MogoLocation + ): Int { + var currentIndex = 0 //记录疑似点 //基础点 + val baseLatLng = mRoutePoints[0] + var baseDiffDis = CoordinateUtils.calculateLineDistance( + realLocation.longitude, + realLocation.latitude, baseLatLng.longitude, baseLatLng.longitude + ) // lon,lat, prelon, prelat + for (i in mRoutePoints.indices) { + val latLng = mRoutePoints[i] + if (realLocation.heading == realLocation.heading - latLng.heading || + Math.abs(realLocation.heading - latLng.heading) <= 90 + ) { + val diff = CoordinateUtils.calculateLineDistance( + realLocation.longitude, + realLocation.latitude, + latLng.longitude, latLng.latitude + ) + if (baseDiffDis > diff && i > currentIndex) { + baseDiffDis = diff + currentIndex = i + } + } + } + Logger.d("calculateRouteSumLength", "点:$currentIndex-------是最近的点------ ") + return currentIndex + } + + @JvmStatic + fun getArrivedPointIndexNew( + preIndex: Int, mRoutePoints: List, + realLon: Double, realLat: Double + ): Int { + var currentIndex = preIndex //记录疑似点 //基础点 + val baseLatLng = mRoutePoints[0] + var baseDiffDis = CoordinateUtils.calculateLineDistance( + realLon, + realLat, baseLatLng.longitude, baseLatLng.longitude + ) // lon,lat, prelon, prelat + for (i in preIndex until mRoutePoints.size) { + val latLng = mRoutePoints[i] + // if (realLocation.getBearing() == realLocation.getBearing() - latLng.getBearing() || +// Math.abs(realLocation.getBearing() - latLng.getBearing()) <= 90){ + val diff = CoordinateUtils.calculateLineDistance( + realLon, + realLat, + latLng.longitude, latLng.latitude + ) + if (baseDiffDis > diff && i > currentIndex) { +// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+i+"-------先记录点----- "); + baseDiffDis = diff + currentIndex = i + } + // } + } + Logger.d("calculateRouteSumLength", "点:$currentIndex-------是最近的点------ ") + return currentIndex + } + + /** + * https://blog.csdn.net/Jeanne_0523/article/details/106056255 + * @param vertexPointX + * @param vertexPointY + * @param point0X 角 + * @param point0Y 角 + * @param point1X + * @param point1Y + * @return + */ + fun getDegree( + vertexPointX: Double, + vertexPointY: Double, + point0X: Double, + point0Y: Double, + point1X: Double, + point1Y: Double + ): Int { + //向量的点乘 + val vector = + (point0X - vertexPointX) * (point1X - vertexPointX) + (point0Y - vertexPointY) * (point1Y - vertexPointY) + //向量的模乘 + val sqrt = Math.sqrt( + (Math.abs((point0X - vertexPointX) * (point0X - vertexPointX)) + Math.abs((point0Y - vertexPointY) * (point0Y - vertexPointY))) + * (Math.abs((point1X - vertexPointX) * (point1X - vertexPointX)) + Math.abs((point1Y - vertexPointY) * (point1Y - vertexPointY))) + ) + //反余弦计算弧度 + val radian = Math.acos(vector / sqrt) + //弧度转角度制 + return (180 * radian / Math.PI).toInt() + } + + private fun ball2xyz(thera: Double, fie: Double, r: Double): Triple { + val x = r * cos(thera) * cos(fie) + val y = r * cos(thera) * sin(fie) + val z = r * sin(thera) + return Triple(x, y, z) + } + + /** + * https://blog.csdn.net/reborn_lee/article/details/82497577 + * 将地理经纬度转换成笛卡尔坐标系 + */ + private fun geo2xyz(lat: Double, lng: Double): Triple { + val thera = Math.PI * lat / 180 + val fie = Math.PI * lng / 180 + return ball2xyz(thera, fie, 6400.0) + } + + /** + * 计算3个地理坐标点之间的夹角 + * @param l1 顶点坐标 + * @param l2 + * @param l3 + * @return l1为顶点的角度 精度没有angleOflocation高 + */ + fun getDegree(l2: MogoLocation, l1: MogoLocation, l3: MogoLocation): Double { + val (x1, y1, z1) = geo2xyz(l1.latitude, l1.longitude) + val (x2, y2, z2) = geo2xyz(l2.latitude, l2.longitude) + val (x3, y3, z3) = geo2xyz(l3.latitude, l3.longitude) + + // 计算向量 P2P1 和 P2P3 的夹角 https://www.zybang.com/question/3379a30c0dd3041b3ef966803f0bf758.html + val p1P2 = sqrt((x2 - x1).pow(2.0) + (y2 - y1).pow(2.0) + (z2 - z1).pow(2.0)) + val p2p3 = sqrt((x3 - x2).pow(2.0) + (y3 - y2).pow(2.0) + (z3 - z2).pow(2.0)) + val p = (x1 - x2) * (x3 - x2) + (y1 - y2) * (y3 - y2) + (z1 - z2) * (z3 - z2) //P2P1*P2P3 + return acos(p / (p1P2 * p2p3)) / Math.PI * 180 + } + + fun getHeadingAngle(location: MogoLocation, nextPoint: MogoLocation): Double { + return getHeadingAngle( + location.longitude, + location.latitude, + nextPoint.longitude, + nextPoint.latitude + ) + } + + fun getHeadingAngle(location: LatLng, nextPoint: LatLng): Double { + return getHeadingAngle( + location.longitude, + location.latitude, + nextPoint.longitude, + nextPoint.latitude + ) + } + fun getHeadingAngle(locationLongitude: Double, locationLatitude: Double, + nextPointLongitude: Double, nextPointLatitude: Double): Double { + val y = sin(nextPointLongitude - locationLongitude) * cos(nextPointLatitude) + val x = cos(locationLatitude) * sin(nextPointLatitude) - sin(locationLatitude) * + cos(nextPointLatitude) * cos(nextPointLongitude - locationLongitude) + var bearing = atan2(y, x) + bearing = Math.toDegrees(bearing) + if (bearing < 0) { + bearing += 360.0 + } + return 360-bearing + } + + + + /** + * 支持带航行角的和不带航向角的 + * 带航向角的会删除 航向角差大于90°的点 + * @param preIndex 上次计算缓存 + * @param mRoutePoints 轨迹点 + * @param location 目标坐标 + * @param type 1 开始站点 2 定位点 3 结束站点 + * @return Triple + * 距离目标坐标最近的轨迹点下标、 + * 最近点坐标是目标坐标的上一个点还是下一个点 + * 目标到最近轨迹点的距离 + */ + @JvmStatic + fun getNearestPointInfo( + preIndex: Int, + endIndex: Int, + mRoutePoints: List, + location: MogoLocation, + type:Int, + size:Int = 4 + ): Triple { + Logger.d(SceneConstant.M_OCHCOMMON + "calculateRouteSumLength", + "参数:[$preIndex $endIndex) mRoutePoints:${mRoutePoints.size} type:$type size:$size" + + " location:(${location.latitude},${location.longitude},${location.heading})") + var currentIndex:Int = preIndex //记录疑似点 //基础点 + // 轨迹中的点和定位点的距离集合 + val distanceMap: TreeMap = TreeMap() + for (index in preIndex until endIndex) { + val latLngIndex = mRoutePoints[index] + val distance = CoordinateUtils.calculateLineDistance( + location.longitude, + location.latitude, + latLngIndex.longitude, + latLngIndex.latitude + ) + distanceMap[DistanceDegree(distance, null,null)] = index + if (distanceMap.size > size) { + distanceMap.pollLastEntry() + } + } + distanceMap.forEach { + val distanceDegree = it.key + val pointIndex = it.value + val currentPoint = mRoutePoints[pointIndex]// 疑似最近的点 + var nextDegree = 0.0 + var preDegree = 0.0 + + if (pointIndex + 1 < mRoutePoints.size) { + val nextPoint = mRoutePoints[pointIndex + 1] + nextDegree = getDegree(location, currentPoint, nextPoint) + }else{ + nextDegree = 135.0 + } + // 需要减距离 和上一个轨迹点成钝角 + if (pointIndex - 1 >= 0) { + val prePoint = mRoutePoints[pointIndex - 1] + preDegree = getDegree( + location, + currentPoint, + prePoint + ) + }else{// 第一个个点处理 + preDegree = 135.0 + } + fun getDegreeNext(){ + if (pointIndex + 1 < mRoutePoints.size) { + val nextPoint = mRoutePoints[pointIndex + 1] + val headingAngle = getHeadingAngle(currentPoint, nextPoint) + distanceDegree.degree = headingAngle + distanceDegree.isNext = false + }else{ + val prePoint = mRoutePoints[pointIndex - 1] + val headingAngle = getHeadingAngle(prePoint,currentPoint) + distanceDegree.degree = headingAngle + distanceDegree.isNext = true + } + } + fun getDegreePre(){ + if (pointIndex - 1 >= 0) { + val prePoint = mRoutePoints[pointIndex - 1] + val headingAngle = getHeadingAngle(prePoint, currentPoint) + distanceDegree.degree = headingAngle; + distanceDegree.isNext = true + }else{ + val nextPoint = mRoutePoints[pointIndex + 1] + val headingAngle = getHeadingAngle(currentPoint,nextPoint) + distanceDegree.degree = headingAngle + distanceDegree.isNext = false + } + } + if(nextDegree>90){ + getDegreeNext() + } + if(preDegree>90){ + getDegreePre() + } + if(preDegree<90&&nextDegree<90&&preDegree+nextDegree>90){ + if (pointIndex + 1 < mRoutePoints.size&&pointIndex - 1 >= 0) { + val nextPoint = mRoutePoints[pointIndex + 1] + val prePoint = mRoutePoints[pointIndex - 1] + val degree = getDegree(currentPoint, prePoint, nextPoint) + if(degree>90) { + getDegreePre() + // isNext 值无所谓了 就 ture和false都行 + // 通过航向角过滤一遍 + if(distanceDegree.degree!=null&&DrivingDirectionUtils.getAngleDiff(location.heading, distanceDegree.degree!!)<90){ + currentIndex = pointIndex + return Triple(currentIndex,distanceDegree.isNext,distanceDegree.distance) + } + } + } + } + } + + // 根据角度来排除一些点 + val iterator = distanceMap.iterator() + // 有航向角比较航向角 + while (iterator.hasNext()) { + val next = iterator.next() + val key = next.key + if (key.degree == null) { + iterator.remove() + } else { + if (location.heading != 0.0) { + key.degree?.let { + val dexAngle = DrivingDirectionUtils.getAngleDiff(location.heading, it) + if (dexAngle > 90) { + iterator.remove() + } + } + } + } + } + + if(distanceMap.size==0&&size<16){ + return getNearestPointInfo(preIndex,endIndex,mRoutePoints,location,type,size+2) + } + + // 最近点中包含上次计算的点和上次计算的最近的一个点 + if(distanceMap.containsValue(preIndex)&&distanceMap.containsValue(preIndex+1)){ + var preIndexDistance:DistanceDegree?=null + var preIndexNextDistance:DistanceDegree?=null + distanceMap.iterator().forEach { en -> + val key = en.key + val value = en.value + if(value==preIndex){ + preIndexDistance = key + }else if(value==preIndex+1){ + preIndexNextDistance = key + } + } + if(preIndexDistance!=null&&preIndexNextDistance!=null){ + if(preIndexDistance!!.distance + val value = en.value + if(valuemaxIndex){ + maxIndex = value + } + } + + val middleVale =minIndex + (maxIndex-minIndex)/2 + when (type) { + 1 -> {// 求开始站点 + val iteratorRemove = distanceMap.iterator() + while (iteratorRemove.hasNext()) { + val next = iteratorRemove.next() + val key = next.key + if(next.value>middleVale){ + iteratorRemove.remove() + } + } + } + 3 -> {// 求结束站点 + val iteratorRemove = distanceMap.iterator() + while (iteratorRemove.hasNext()) { + val next = iteratorRemove.next() + val key = next.key + if(next.value {} + } + + // 根据距离来计算 最近的点 只有一个前面的点 + var tempDistance = Float.MAX_VALUE + var isNext:Boolean? = null + distanceMap.iterator().forEach { en -> + val key = en.key + val value = en.value + // 排除没有第一个值0是 + if(value==preIndex+1&&preIndex!=0){ + currentIndex = value + return Triple(currentIndex,key.isNext,key.distance) + } + key.distance.let { + if (it < tempDistance) { + tempDistance = it + currentIndex = value + isNext = key.isNext + } + } + } + + return Triple(currentIndex,isNext,tempDistance) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/NumberFormatUtil.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/NumberFormatUtil.java index 1af162ef26..2a88ec1dd2 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/NumberFormatUtil.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/NumberFormatUtil.java @@ -30,7 +30,8 @@ public class NumberFormatUtil { */ public static String cutOutNumber(double num,int cutNum){ try{ - BigDecimal bg = new BigDecimal(num).setScale(cutNum, RoundingMode.DOWN); + //注:将double类型转成String类型再处理截取。 使用double部分数据截取有问题 + BigDecimal bg = new BigDecimal(String.valueOf(num)).setScale(cutNum, RoundingMode.DOWN); return String.valueOf(bg.doubleValue()); }catch (Exception e){ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java index caf252a64e..615185f0e0 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java @@ -9,7 +9,7 @@ import java.util.List; * @date: 2022/4/6 */ public interface IBusPassengerRouteLineInfoCallback { - void updateLineInfo(String lineName, String lineDurTime); + void updateLineInfo(String lineName); void updateStationsInfo(List stations, int currentStationIndex, boolean isArrived); void showNoTaskView(); void hideNoTaskView(); diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java index 87f0874556..0a899b87e2 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java @@ -281,7 +281,7 @@ public class BusPassengerModel { routesResult = result; if (mRouteLineInfoCallback != null){ - mRouteLineInfoCallback.updateLineInfo(result.getName(),result.getRunningDur()); + mRouteLineInfoCallback.updateLineInfo(result.getName()); mRouteLineInfoCallback.hideNoTaskView(); if (result.getSites() != null){ List stations = result.getSites(); @@ -346,7 +346,7 @@ public class BusPassengerModel { IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener ); MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener ); // 定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, mMapLocationListener); + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, 10,mMapLocationListener); //2021.11.1 自动驾驶路线规划接口 CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG,moGoAutopilotPlanningListener); @@ -455,6 +455,16 @@ public class BusPassengerModel { private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ + @Override + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + // TODO: 2023/6/19 mingjun + } + + @Override + public void onAutopilotStatusResponse(int state) { + // TODO: 2023/6/19 mingjun + } + @Override public void onAutopilotRouteLineId(long lineId) { @@ -608,6 +618,9 @@ public class BusPassengerModel { if (mTwoStationsRouts.size() > 0 && mLocation != null){ Map> lastPointsMap = CoordinateCalculateRouteUtil .getRemainPointListByCompareNew(mPreRouteIndex,mTwoStationsRouts,mLocation); + if(lastPointsMap==null){ + return; + } for (int index: lastPointsMap.keySet()) { mPreRouteIndex = index; break; diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java index e7dd425241..c32e05fe05 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java @@ -127,8 +127,8 @@ public class BaseBusPassengerPresenter extends Presenter mView.updateLineInfo(lineName, lineDurTime)); + public void updateLineInfo(String lineName) { + runOnUIThread(() -> mView.updateLineInfo(lineName)); } @Override diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java index 73fd07a86e..8f5bfed4cd 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java @@ -21,6 +21,7 @@ import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener; import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager; import com.mogo.eagle.core.function.hmi.ui.widget.DriverMonitorView; +import com.mogo.eagle.core.function.hmi.ui.widget.RomaPassengerView; import com.mogo.eagle.core.function.view.MapBizView; import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; @@ -28,6 +29,7 @@ import com.mogo.och.bus.passenger.R; import com.mogo.och.bus.passenger.constant.BusPassengerConst; import com.mogo.och.common.module.utils.NumberFormatUtil; import com.mogo.och.common.module.wigets.OCHBorderShadowLayout; +import com.mogo.eagle.core.utilcode.util.DeviceUtils; /** * Created on 2022/3/31 @@ -39,6 +41,7 @@ public abstract class BusPassengerBaseFragment 0){ + // 起点marker, 终点marker, 过站marker, 未过站marker + + int size = mLineStationsList.size(); + + Marker mStartMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_start_point))); + Marker mEndMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_end_point))); + + mStartMarker.setPosition(mLineStationsList.get(0)); + mLineMarkers.add(0,mStartMarker); + for (int i = 0; i < mLineStationsList.size(); i++) { - if (currentIndex == i){ - Marker mEndMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_end_point))); - mEndMarker.setPosition(mLineStationsList.get(i)); - mLineMarkers.add(i,mEndMarker); - }else { - Marker mStartMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_way_point))); - mStartMarker.setPosition(mLineStationsList.get(i)); - mLineMarkers.add(i,mStartMarker); + if (currentIndex <= i && i < size-1 && i > 0){ //未到达 + Marker unArrivedMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_unarrived_point))); + unArrivedMarker.setPosition(mLineStationsList.get(i)); + mLineMarkers.add(i,unArrivedMarker); + }else if (i < currentIndex && i > 0){ + Marker arrivedMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrived_point))); + arrivedMarker.setPosition(mLineStationsList.get(i)); + mLineMarkers.add(i,arrivedMarker); } } + + mEndMarker.setPosition(mLineStationsList.get(size-1)); + mLineMarkers.add(size-1,mEndMarker); } } diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java index 00834c42d4..cbd98e6ba9 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java @@ -1,14 +1,9 @@ package com.mogo.och.bus.passenger.ui; -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; - import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.text.Html; import android.view.View; -import android.view.animation.Animation; -import android.view.animation.RotateAnimation; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -23,12 +18,9 @@ import com.elegant.utils.UiThreadHandler; import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.data.map.MogoLocation; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.och.bus.passenger.R; import com.mogo.och.bus.passenger.adapter.BusPassengerLineStationsAdapter; -import com.mogo.och.bus.passenger.bean.BusPassengerStation; -import com.mogo.och.bus.passenger.callback.IBusPassengerMapViewCallback; import com.mogo.och.bus.passenger.constant.BusPassengerConst; import com.mogo.och.bus.passenger.presenter.BaseBusPassengerPresenter; import com.mogo.och.bus.passenger.ui.layoutmanager.CenterLayoutManager; @@ -209,10 +201,7 @@ public class BusPassengerRouteFragment extends } public void changeOperationStatus(boolean status) { - if (status) { - mNoLineInfoView.setVisibility(View.GONE); - mRouteInfoView.setVisibility(View.VISIBLE); - } else { + if (!status) { emptyTv.setText(getString(R.string.bus_p_no_out)); mNoLineInfoView.setVisibility(View.VISIBLE); mRouteInfoView.setVisibility(View.GONE); @@ -242,17 +231,8 @@ public class BusPassengerRouteFragment extends } } -// public void updatePlateNum(String plateNum){ -// if ("".equals(plateNum) || null == plateNum) { -// mCarPlateNum.setText("-- --"); -// }else { -// mCarPlateNum.setText((plateNum)); -// } -// } - - public void updateLineInfo(String lineName, String lineDurTime) { + public void updateLineInfo(String lineName) { mLineName.setText(lineName); -// mOperationTime.setText(lineDurTime); } /** diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png new file mode 100644 index 0000000000..ac317649b4 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrived_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png index 17beb894a6..702f10f265 100644 Binary files a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png new file mode 100644 index 0000000000..39262e5ecb Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_end_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png new file mode 100644 index 0000000000..b2e4c69ada Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_start_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png new file mode 100644 index 0000000000..ec6081f5a3 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_unarrived_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png deleted file mode 100644 index 1e64713481..0000000000 Binary files a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png and /dev/null differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png deleted file mode 100644 index ff04c01f13..0000000000 Binary files a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png and /dev/null differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml index b3dbf98f8c..aa903a44ce 100644 --- a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml @@ -28,7 +28,7 @@ app:layout_constraintStart_toStartOf="parent" /> = 0 && mNextStationIndex <= mStations.size - 1 @@ -319,11 +312,9 @@ class PM2DrivingModel private constructor() { }else{//非美化模式下 mAutoStatusCallback?.updateAutoStatus(false) } - }else{//自驾状态 2 mAutoStatusCallback?.updateAutoStatus(true) } - mCurrentAutoStatus = status } } diff --git a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data index 8e06219090..d4d4bc8214 100644 Binary files a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data and b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data differ diff --git a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data index e5a16d46be..88c4e33256 100644 Binary files a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data and b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data differ diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java index 5affa4b9ac..a76f2be2cb 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java @@ -17,11 +17,11 @@ public class BusUpdateSiteStatusRequest { public int siteId;//站点id public long writeVersion; //更新时间戳 - public BusUpdateSiteStatusRequest(int taskId,int siteId,int seq) { + public BusUpdateSiteStatusRequest(int taskId,int siteId,int seq, long writeVersion) { this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); this.seq = seq; this.siteId = siteId; this.taskId = taskId; - this.writeVersion = DateTimeUtil.getCurrentTimeStamp(); + this.writeVersion = writeVersion; } } diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java index 2afd1c117d..fcaa20a6ad 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java @@ -161,7 +161,7 @@ public abstract class BaseBusTabFragment }); initListener(); - setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener() { @Override @@ -308,9 +308,6 @@ public abstract class BaseBusTabFragment @Override public void onAutopilotRecordResult(@Nullable RecordPanelOuterClass.RecordPanel recordPanel) { -// if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) { -// CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel); -// } } @Override @@ -455,7 +452,7 @@ public abstract class BaseBusTabFragment public void stopAnimAndUpdateBtnStatus() { stopAutopilotAnimation(); - updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); } /** @@ -529,7 +526,7 @@ public abstract class BaseBusTabFragment public void run() { //未启动成功做处理 if (isAnimateRunning) {// 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态 stopAutopilotAnimation(); - updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState()); } } }, TIMER_START_AUTOPILOT_INTERVAL); diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java index 737a96683a..2ee9511215 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java @@ -113,7 +113,7 @@ public class BusFragment extends BaseBusTabFragment groupStationsPanel = findViewById(R.id.group_stations_panel); noDataView = findViewById(R.id.no_line_data_view); - CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getState()); // 初始化的时候设置 UI 按钮状态 showAutopilotBiz(); @@ -461,7 +461,7 @@ public class BusFragment extends BaseBusTabFragment } //清除鹰眼右下角小地图轨迹 - CallerLogger.INSTANCE.d(SceneConstant.M_MAP, "clearBusStationsMarkers --------->"); + CallerLogger.INSTANCE.d(SceneConstant.M_BUS, "clearBusStationsMarkers --------->"); smallMapView.clearPolyline(); } @@ -535,7 +535,7 @@ public class BusFragment extends BaseBusTabFragment public void onClick(View v) { if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中,点击则toast提示:自动驾驶中,不可切换路线 //本次行程未结束,不支持切换路线。点击则toast提示:当前行程未完成,不可切换路线 - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { ToastUtils.showLong(getResources().getString(R.string.bus_switch_line_btn_warning1)); return; diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java index 7fe377e205..787429540c 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java @@ -163,8 +163,7 @@ public class OrderModel { mContext = AbsMogoApplication.getApp(); loginService = (LoginService) ARouter.getInstance().build(OchCommonConst.LOGINSERVICE).navigation(); // 定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,mMapLocationListener); -// CallerChassisLocationGCJ02ListenerManager.INSTANCE.setListenerHz(TAG,2);//设置5hz, 1s返回一次 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,10,mMapLocationListener); MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); @@ -649,7 +648,8 @@ public class OrderModel { * 车机端展示是离开当前站,下一站设置为当前站, 所以服务端数据回来要做处理,不能直接渲染 */ private void leaveStationSuccess(int leaveIndex, String leaveStation, - String nextStation,String nextStationKr) { + String nextStation,String nextStationKr, + long writeVersion) { onStartAutopilot(leaveIndex); @@ -670,12 +670,13 @@ public class OrderModel { , isLastStop); } - reBuildCacheRouteData(leaveIndex,BusConst.STATION_STATUS_STOPPED,true); + reBuildCacheRouteData(leaveIndex,BusConst.STATION_STATUS_STOPPED,true,writeVersion); } - private void reBuildCacheRouteData(int currentIndex, int currentDrivingStatus, boolean isLeaving) { + private void reBuildCacheRouteData(int currentIndex, int currentDrivingStatus, boolean isLeaving + , long writeVersion) { if (busRoutesResult != null){ - busRoutesResult.setWriteVersion(DateTimeUtil.getCurrentTimeStamp()); + busRoutesResult.setWriteVersion(writeVersion); List sites = busRoutesResult.getSites(); BusStationBean bean = sites.get(currentIndex); bean.setDrivingStatus(currentDrivingStatus); @@ -698,7 +699,7 @@ public class OrderModel { private void onStartAutopilot(int leaveIndex) { //开启自动驾驶 2.10.0: 如果自动驾驶状态下开启, 非自动驾驶状态下不开启,需手动点击自动驾驶按钮开启 isGoingToNextStation = true; - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { startAutopilot(false, leaveIndex); } else { @@ -757,13 +758,15 @@ public class OrderModel { isArrivedStation = true; isGoingToNextStation = false; + + long writeVersion = DateTimeUtil.getCurrentTimeStamp(); arriveStationSuccess(arrivedStationIndex, departureStopName, - arriveStation,arriveStationKr); + arriveStation,arriveStationKr,writeVersion); OrderServiceManager.arriveSiteStation(mContext, stationList.get(arrivedStationIndex).getSeq(), stationList.get(arrivedStationIndex).getSiteId(), - currentTaskId, + currentTaskId,writeVersion, new OchCommonServiceCallback() { @Override public void onSuccess(BaseData o) { @@ -803,7 +806,8 @@ public class OrderModel { } private void arriveStationSuccess(int arrivedStationIndex, String departureStopName, - String arriveStation,String arriveStationKr) { + String arriveStation,String arriveStationKr, + long writeVersion) { if (busRoutesResult != null) { boolean isLastStop = false; if (arrivedStationIndex == busRoutesResult.getSites().size() - 1) { @@ -821,7 +825,7 @@ public class OrderModel { sendArrivedStationToClient(arriveStation); - reBuildCacheRouteData(arrivedStationIndex, BusConst.STATION_STATUS_STOPPED,false); + reBuildCacheRouteData(arrivedStationIndex, BusConst.STATION_STATUS_STOPPED,false,writeVersion); } private void sendTaskDetailsToClients() { @@ -891,13 +895,15 @@ public class OrderModel { isArrivedStation = false; CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-离站成功开往下一站===="); + + long writeVersion = DateTimeUtil.getCurrentTimeStamp(); leaveStationSuccess(backgroundCurrentStationIndex, currentStationName, - finalNextStationName,finalNextStationNameKr); + finalNextStationName,finalNextStationNameKr,writeVersion); OrderServiceManager.leaveStation(mContext, stationList.get(backgroundCurrentStationIndex).getSeq(), stationList.get(backgroundCurrentStationIndex).getSiteId(), - currentTaskId, + currentTaskId,writeVersion, new OchCommonServiceCallback() { @Override public void onSuccess(BaseData o) { diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt index a239420e1a..f081f08a34 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt @@ -106,12 +106,13 @@ object OrderServiceManager { seq: Int, siteId: Int, taskId: Int, + writeVersion: Long, callback: OchCommonServiceCallback? ) { mService.leaveStation( MoGoAiCloudClientConfig.getInstance().serviceAppId, MoGoAiCloudClientConfig.getInstance().token, - BusUpdateSiteStatusRequest(taskId, siteId, seq) + BusUpdateSiteStatusRequest(taskId, siteId, seq,writeVersion) ) .transformTry() .subscribe(OchCommonSubscribeImpl(context, callback, "leaveStation")) @@ -126,13 +127,13 @@ object OrderServiceManager { */ @JvmStatic fun arriveSiteStation( - context: Context, seq: Int, siteId: Int, taskId: Int, + context: Context, seq: Int, siteId: Int, taskId: Int, writeVersion: Long, callback: OchCommonServiceCallback? ) { mService.arriveSiteStation( MoGoAiCloudClientConfig.getInstance().serviceAppId, MoGoAiCloudClientConfig.getInstance().token, - BusUpdateSiteStatusRequest(taskId, siteId, seq) + BusUpdateSiteStatusRequest(taskId, siteId, seq, writeVersion) ) .transformTry() .subscribe(OchCommonSubscribeImpl(context, callback, "arriveSiteStation")) diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java index 0a10e5b41f..ea411d37b0 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java @@ -167,14 +167,14 @@ public class BusPresenter extends Presenter @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); + } + + @Override + public void onAutopilotStatusResponse(int state) { switch (state) { case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE: if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { @@ -210,26 +210,21 @@ public class BusPresenter extends Presenter && ( (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) && OrderModel.getInstance().isGoingToNextStation() - ) ) { CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); return; } - if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; } - runOnUIThread(() -> { - mView.onAutopilotStatusChanged(currentAutopilotStatus); - }); + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); break; case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING: if (FunctionBuildConfig.isDemoMode && ( (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) && OrderModel.getInstance().isGoingToNextStation() - ) ) { CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); @@ -238,9 +233,7 @@ public class BusPresenter extends Presenter if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) { currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING; } - runOnUIThread(() -> { - mView.onAutopilotStatusChanged(currentAutopilotStatus); - }); + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); break; default: runOnUIThread(() -> mView.onAutopilotEnableChange(false)); @@ -279,8 +272,6 @@ public class BusPresenter extends Presenter /** * 测试使用 - * - * @param status */ public void debugAutoPilotStatus(int status) { AutopilotStatusInfo info = new AutopilotStatusInfo(); @@ -345,4 +336,9 @@ public class BusPresenter extends Presenter public void onStartAdasFailure() { runOnUIThread(() -> mView.stopAnimAndUpdateBtnStatus()); } + + @Override + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + } + } diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java index b37e399e18..947adbfc0c 100644 --- a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java @@ -50,13 +50,13 @@ public class BusAnalyticsManager { CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_CODE, failCode); mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG, failMsg); } mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT - , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + , CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerAutopilotPlanningCallback.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerAutopilotPlanningCallback.java index 7b607580bd..badb7dee50 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerAutopilotPlanningCallback.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerAutopilotPlanningCallback.java @@ -2,6 +2,7 @@ package com.mogo.och.taxi.passenger.callback; import com.amap.api.maps.model.LatLng; +import com.mogo.eagle.core.data.map.MogoLocation; import java.util.List; @@ -11,7 +12,7 @@ import mogo.telematics.pad.MessagePad; * @date: 2021/11/1 */ public interface IOCHTaxiPassengerAutopilotPlanningCallback { - void setLineMarker(List models); - void routeResultByServer(List models,int haveArrivedIndex); + void setLineMarker(LatLng startStation,LatLng endStation); + void routeResultByServer(List routeArriviedTemp, List routeArrivingTemp, MogoLocation location); void showRottingMapView(); } \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java index daaf6b231c..f95bba5744 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java @@ -14,7 +14,6 @@ import com.amap.api.maps.model.LatLng; import com.amap.api.navi.model.NaviLatLng; import com.elegant.network.utils.GsonUtil; import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager; -import com.mogo.commons.debug.DebugConfig; import com.mogo.commons.module.intent.IMogoIntentListener; import com.mogo.commons.module.intent.IntentManager; import com.mogo.commons.module.status.IMogoStatusChangedListener; @@ -48,6 +47,9 @@ import com.mogo.och.common.module.biz.network.OchCommonServiceCallback; import com.mogo.och.common.module.callback.OchAdasStartFailureCallback; import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager; import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.manager.distancemamager.IDistanceListener; +import com.mogo.och.common.module.manager.distancemamager.ITrajectoryListener; +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager; import com.mogo.och.common.module.map.AmapNaviToDestinationModel; import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; import com.mogo.och.common.module.utils.PinYinUtil; @@ -109,7 +111,6 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback } private Context mContext; - private volatile int mPrevAPStatus = -1; //前一次自动驾驶状态值 private volatile TaxiPassengerOrderQueryRespBean.Result mCurrentOCHOrder; //当前订单 private volatile List mInServiceList = Collections.emptyList(); //进行中订单 private volatile List mWaitServiceList = Collections.emptyList(); //待服务订单 @@ -241,7 +242,7 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback IntentManager.getInstance().registerIntentListener( ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener ); MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); // 定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,mMapLocationListener); + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,10,mMapLocationListener); //2021.11.1 自动驾驶路线规划接口 CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG,moGoAutopilotPlanningListener); @@ -255,6 +256,10 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener); CallerMsgBoxEventListenerManager.INSTANCE.addListener(TAG,iMsgBoxEventListener); + + TrajectoryAndDistanceManager.INSTANCE.addDistanceListener(TAG,distanceListener); + + TrajectoryAndDistanceManager.INSTANCE.addTrajectoryListener(TAG,trajectoryListener); } private void releaseListeners() { @@ -275,6 +280,8 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null); CallerMsgBoxEventListenerManager.INSTANCE.removeListener(iMsgBoxEventListener); + + TrajectoryAndDistanceManager.INSTANCE.removeListener(TAG); } /** @@ -447,7 +454,27 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback } } + //监听网络变化,避免启动机器时无网导致无法更新订单信息 + private final IDistanceListener distanceListener = distance -> { + + }; + + private final ITrajectoryListener trajectoryListener = (routeArrivied, routeArriving, location) -> { + List routeArriviedTemp = new ArrayList<>(); + List routeArrivingTemp = new ArrayList<>(); + LatLng temp; + for (MogoLocation mogoLocation : routeArrivied) { + temp = new LatLng(mogoLocation.getLatitude(),mogoLocation.getLongitude()); + routeArriviedTemp.add(temp); + } + for (MogoLocation mogoLocation : routeArriving) { + temp = new LatLng(mogoLocation.getLatitude(),mogoLocation.getLongitude()); + routeArrivingTemp.add(temp); + } + mAutopilotPlanningCallback.routeResultByServer(routeArriviedTemp,routeArrivingTemp,location); + setRouteLineMarker(); + }; private final IMogoIntentListener mNetWorkIntentListener = new IMogoIntentListener() { @Override public void onIntentReceived( String intentStr, Intent intent ) { @@ -500,8 +527,11 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ @Override - public void onAutopilotRouteLineId(long lineId) { + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + } + @Override + public void onAutopilotRouteLineId(long lineId) { } @Override @@ -510,31 +540,26 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback @Override public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { + } + @Override + public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { } private boolean arriveAtEnd = false; //乘客app专用字段 @Override - public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { - int state = autopilotStatusInfo.getState(); + public void onAutopilotStatusResponse(int state) { // CallerLogger.INSTANCE.d( M_TAXI_P + TAG, "state = %s", state ); if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning(); if (mCurrentOCHOrder != null - && getCurOrderStatus() == TaxiPassengerOrderStatusEnum.UserArriveAtStart - && state != mPrevAPStatus) { - + && getCurOrderStatus() == TaxiPassengerOrderStatusEnum.UserArriveAtStart) { TaxiPassengerAnalyticsManager.getInstance().triggerStartAutopilotEvent(false, true, mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo); - - // 当高频返回autopilot 2时,不重复调用订单状态变更 - mPrevAPStatus = state; // 每个状态单独赋值,解决无订单时已经是2的状态导致的新订单来时无法进入此逻辑更新状态 startServicePilotDone(); } } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { - mPrevAPStatus = state; - if (FunctionBuildConfig.isDemoMode && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) { // 当美化模式(演示模式)开启时:且是乘客app、且未到终点时,维持自动驾驶icon开启状态 @@ -544,11 +569,8 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback arriveAtEnd = false; } } - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotEnable(); } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { - mPrevAPStatus = state; - if (FunctionBuildConfig.isDemoMode && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) { // 当美化模式(演示模式)开启时:且是乘客app、且未到终点时,维持自动驾驶icon开启状态 @@ -558,14 +580,12 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback arriveAtEnd = false; } } - if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotDisable(); } } @Override public void onAutopilotSNRequest() { - } @Override @@ -579,14 +599,10 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback || (getCurOrderStatus() == TaxiPassengerOrderStatusEnum.ArriveAtEnd)) { return; } - if (DebugConfig.isDebug()) { - // TipToast.shortTip("到达目的地"); - } } @Override public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { - } }; @@ -596,7 +612,6 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback public void onAutopilotRotting(@Nullable MessagePad.GlobalPathResp routeList) { if (null != routeList && routeList.getWayPointsList().size() > 0){ calculateRouteLineSum(CoordinateCalculateRouteUtil.coordinateConverterWgsToGcjListCommon(mContext,routeList.getWayPointsList())); - setRouteLineMarker(routeList.getWayPointsList()); startToRouteAndWipe(routeList.getWayPointsList()); } } @@ -676,38 +691,26 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback * @param isStart */ public void startOrStopRouteAndWipe(boolean isStart){ - if (isStart){ - TaxiPassengerModelLoopManager.getInstance().startRouteAndWipe(); - }else { - mPreRouteIndex = 0; - TaxiPassengerModelLoopManager.getInstance().stopRouteAndWipe(); - } - } - public void loopRouteAndWipe() { - if (mLocationsModels != null && mLocationsModels.size() > 0 && mLocation != null){ - int haveArrivedIndex = CoordinateCalculateRouteUtil - .getArrivedPointIndexNew(mPreRouteIndex, - mLocationsModels, - mLocation); - mPreRouteIndex = haveArrivedIndex; - if (mAutopilotPlanningCallback != null){ - List latLngsModels = CoordinateCalculateRouteUtil - .coordinateConverterLocationToLatLng(mContext, - mLocationsModels); - mAutopilotPlanningCallback.routeResultByServer(latLngsModels,haveArrivedIndex); - } - } } /** * 设置小地图路径的起终点marker */ - public void setRouteLineMarker(List models){ - List latLngModels = CoordinateCalculateRouteUtil - .coordinateConverterWgsToGcjListCommon(mContext,models); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.setLineMarker(latLngModels); + public void setRouteLineMarker(){ + if (mCurrentOCHOrder.startSiteGcjPoint == null || mCurrentOCHOrder.startSiteGcjPoint.isEmpty() || mCurrentOCHOrder.startSiteGcjPoint.size() < 2|| + mCurrentOCHOrder.endSiteGcjPoint == null || mCurrentOCHOrder.endSiteGcjPoint.isEmpty() || mCurrentOCHOrder.endSiteGcjPoint.size() < 2) { + setMarker(null,null); + return; + } + LatLng startStation = new LatLng(mCurrentOCHOrder.startSiteGcjPoint.get(1),mCurrentOCHOrder.startSiteGcjPoint.get(0)); + LatLng endStation = new LatLng(mCurrentOCHOrder.endSiteGcjPoint.get(1),mCurrentOCHOrder.endSiteGcjPoint.get(0)); + setMarker(startStation,endStation); + } + + private void setMarker(LatLng startStation,LatLng endStation){ + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback.setLineMarker(startStation,endStation); } } @@ -784,9 +787,9 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback if (data != null && data.data != null && data.data != null && data.data.size() > 0){ if (mAutopilotPlanningCallback != null){ calculateRouteLineSum(data.data); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.setLineMarker(data.data); - } +// if (mAutopilotPlanningCallback != null){ +// mAutopilotPlanningCallback.setLineMarker(data.data); +// } mLocationsModels.clear(); List locationsModels = CoordinateCalculateRouteUtil. coordinateConverterLatlngToLocation(data.data); @@ -1056,4 +1059,20 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback } } + public void setStation(){ + if(mCurrentOCHOrder!=null){ + MogoLocation startStation = new MogoLocation(); + startStation.setLongitude(mCurrentOCHOrder.startSiteGcjPoint.get(0)); + startStation.setLatitude(mCurrentOCHOrder.startSiteGcjPoint.get(1)); + MogoLocation endStation = new MogoLocation(); + endStation.setLongitude(mCurrentOCHOrder.endSiteGcjPoint.get(0)); + endStation.setLatitude(mCurrentOCHOrder.endSiteGcjPoint.get(1)); + TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation,endStation,mCurrentOCHOrder.lineId); + } + } + + public void cleanStation(){ + TrajectoryAndDistanceManager.INSTANCE.setStationPoint(null,null,-1L); + } + } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModelLoopManager.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModelLoopManager.java index f182ba65c3..bb3ebec0dc 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModelLoopManager.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModelLoopManager.java @@ -59,45 +59,6 @@ public class TaxiPassengerModelLoopManager { } } - public void startRouteAndWipe() { - CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "startRouteAndWipe()"); - if (mRouteWipeDisposable != null) return; - - mRouteWipeDisposable = new CompositeDisposable(); - Disposable disposable = startLoopRouteAndWipe() - .doOnSubscribe(new Consumer() { - @Override - public void accept(Disposable disposable) throws Exception { - - } - }).doOnError(new Consumer() { - @Override - public void accept(Throwable throwable) throws Exception { - } - }) - .delay(TaxiPassengerConst.LOOP_PERIOD_1S, TimeUnit.MILLISECONDS, true) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 - .subscribeOn(Schedulers.io()) - .repeat() // repeat保证请求成功后能够重新订阅。 - .retry() // retry保证请求失败后能重新订阅 - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { - @Override - public void accept(Integer integer) throws Exception { - } - }); - mRouteWipeDisposable.add(disposable); - } - - public Observable startLoopRouteAndWipe(){ - return Observable.create(new ObservableOnSubscribe() { - @Override - public void subscribe(ObservableEmitter emitter) throws Exception { - TaxiPassengerModel.getInstance().loopRouteAndWipe(); - emitter.onComplete(); - } - }); - } - public void stopRouteAndWipe() { if (mRouteWipeDisposable != null) { CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "stopRouteAndWipe()"); diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java index d61feb6cc9..3a0e4215c1 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java @@ -173,6 +173,7 @@ public class BaseTaxiPassengerPresenter extends Presenter{ @@ -201,6 +203,7 @@ public class BaseTaxiPassengerPresenter extends Presenter models) { - if (models == null) return; - runOnUIThread(() -> mView.setLineMarker(models)); + public void setLineMarker(LatLng startStation,LatLng endStation) { + if (startStation == null || endStation == null) return; + runOnUIThread(() -> mView.setLineMarker(startStation,endStation)); } @Override - public void routeResultByServer(List models, int haveArrivedIndex) { - if (models == null) return; - CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "routeResultByServer:" + models.size() - + " haveArrivedIndex = " + haveArrivedIndex); - runOnUIThread(() ->mView.routeResultByServer(models,haveArrivedIndex)); + public void routeResultByServer(List routeArriviedTemp, List routeArrivingTemp, MogoLocation location) { + runOnUIThread(() ->mView.routeResultByServer(routeArriviedTemp,routeArrivingTemp,location)); } @Override diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.java deleted file mode 100644 index 831abdbe23..0000000000 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.mogo.och.taxi.passenger.ui; - -/** - * @author xiaoyuzhou - * @date 2021/6/24 11:33 上午 - */ -public interface ITaxiPassengerMapDirectionView { - - /** - * 绘制路径线 - */ - void drawablePolyline(); - - /** - * 清除路径线 - */ - void clearPolyline(); - - /** - * 设置路径中起终点marker - */ - void setLineMarker(); -} diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.kt new file mode 100644 index 0000000000..4db01025e5 --- /dev/null +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/ITaxiPassengerMapDirectionView.kt @@ -0,0 +1,24 @@ +package com.mogo.och.taxi.passenger.ui + +import com.amap.api.maps.model.LatLng + +/** + * @author xiaoyuzhou + * @date 2021/6/24 11:33 上午 + */ +interface ITaxiPassengerMapDirectionView { + /** + * 绘制路径线 + */ + fun drawablePolyline() + + /** + * 清除路径线 + */ + fun clearPolyline() + + /** + * 设置路径中起终点marker + */ + fun setLineMarker(startStation: LatLng, endStation: LatLng) +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/OverviewFragment.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/OverviewFragment.kt index 7229e39206..bacbed20e7 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/OverviewFragment.kt +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/OverviewFragment.kt @@ -1,6 +1,5 @@ package com.mogo.och.taxi.passenger.ui -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -13,7 +12,6 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.taxi.passenger.constant.TaxiPassengerOrderStatusEnum import com.mogo.och.taxi.passenger.model.TaxiPassengerModel -import com.mogo.och.taxi.passenger.ui.leftmenu.OverlayLeftViewUtils import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerBaseFragment.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerBaseFragment.java index 3254104ca0..42c739cee9 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerBaseFragment.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerBaseFragment.java @@ -21,7 +21,9 @@ import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager; import com.mogo.eagle.core.function.hmi.ui.msgbox.PassengerMsgBoxBubbleView; import com.mogo.eagle.core.function.hmi.ui.msgbox.PassengerMsgBoxButtonView; import com.mogo.eagle.core.function.hmi.ui.msgbox.PassengerMsgBoxListView; +import com.mogo.eagle.core.function.hmi.ui.widget.RomaPassengerView; import com.mogo.eagle.core.function.view.MapBizView; +import com.mogo.eagle.core.utilcode.util.DeviceUtils; import com.mogo.eagle.core.utilcode.util.OverlayViewUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.map.listener.IMogoMapListener; @@ -58,6 +60,7 @@ public class TaxiPassengerBaseFragment extends MvpFragment mArrivedEndView; private WeakReference mArrivedCheckView; @@ -94,10 +97,17 @@ public class TaxiPassengerBaseFragment extends MvpFragment onAutopilotStatusChanged(CallerAutoPilotStatusListenerManager.INSTANCE.getState()), 1000L); } @NonNull diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.java deleted file mode 100644 index 7b18908634..0000000000 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.mogo.och.taxi.passenger.ui; - -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI_P; - -import android.content.Context; -import android.os.Bundle; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.widget.RelativeLayout; - -import androidx.annotation.Nullable; - -import com.amap.api.maps.AMap; -import com.amap.api.maps.CameraUpdate; -import com.amap.api.maps.CameraUpdateFactory; -import com.amap.api.maps.CoordinateConverter; -import com.amap.api.maps.TextureMapView; -import com.amap.api.maps.UiSettings; -import com.amap.api.maps.model.BitmapDescriptor; -import com.amap.api.maps.model.BitmapDescriptorFactory; -import com.amap.api.maps.model.CameraPosition; -import com.amap.api.maps.model.CustomMapStyleOptions; -import com.amap.api.maps.model.LatLng; -import com.amap.api.maps.model.LatLngBounds; -import com.amap.api.maps.model.Marker; -import com.amap.api.maps.model.MarkerOptions; -import com.amap.api.maps.model.Polyline; -import com.amap.api.maps.model.PolylineOptions; -import com.mogo.eagle.core.data.map.MogoLatLng; -import com.mogo.eagle.core.data.map.MogoLocation; -import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; -import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; -import com.mogo.och.taxi.passenger.R; -import com.mogo.och.taxi.passenger.callback.ITaxiPassengerMapViewCallback; -import com.mogo.och.taxi.passenger.utils.TaxiPassengerMapAssetStyleUtil; - -import java.util.ArrayList; -import java.util.List; - -/** - * 乘客屏小地图 - */ -public class TaxiPassengerMapDirectionView - extends RelativeLayout - implements IMoGoChassisLocationGCJ02Listener, ITaxiPassengerMapDirectionView, AMap.OnCameraChangeListener { - - //小地图名称 - public static final String TAG = "TPMapDirectionView"; - - private TextureMapView mAMapNaviView; - private AMap mAMap; - private Marker mCarMarker; - private Marker mStartMarker; - private Marker mEndMarker; - - private int zoomLevel = 13; - private List mCoordinatesLatLng = new ArrayList<>(); - private Polyline mPolyline; - private CameraUpdate mCameraUpdate; - private Context mContext; - private int mHaveArrivedIndex; - - List textureList = new ArrayList<>(); - List texIndexList = new ArrayList<>(); - - private BitmapDescriptor mArrivedRes; - private BitmapDescriptor mUnArrivedRes; - - private ITaxiPassengerMapViewCallback mITaxiPassengerMapViewCallback; - - public TaxiPassengerMapDirectionView(Context context) { - this(context, null); - } - - public TaxiPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public TaxiPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - try { - initView(context); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void setTaxiPassengerMapViewCallback(ITaxiPassengerMapViewCallback ITaxiPassengerMapViewCallback){ - this.mITaxiPassengerMapViewCallback = ITaxiPassengerMapViewCallback; - } - - private void initView(Context context) { - CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "initView"); - - mContext = context; - - View smpView = LayoutInflater.from(context).inflate(R.layout.taxi_p_map_view, this); - - mAMapNaviView = (TextureMapView) smpView.findViewById(R.id.taxi_p_order_amap_view); - - initAMapView(); - - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, this); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); - } - - private void initAMapView() { - mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel); - mAMap = mAMapNaviView.getMap(); - // 设置导航地图模式,aMap是地图控制器对象。 - mAMap.setMapType(AMap.MAP_TYPE_NIGHT); - - // 关闭显示实时路况图层,aMap是地图控制器对象。 - mAMap.setTrafficEnabled(false); - - // 设置 锚点 图标 - mCarMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_car)) - .anchor(0.5f, 0.5f)); - mStartMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_view_dir_start))); - mEndMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_view_dir_end))); - - mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow_arrived); - mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow_un_arrive); - - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(TaxiPassengerMapAssetStyleUtil.getAssetsStyle(getContext(),"map_style.data")) - .setStyleExtraData(TaxiPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(),"map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - - //设置希望展示的地图缩放级别 - mAMap.moveCamera(mCameraUpdate); - - // 设置地图的样式 - UiSettings uiSettings = mAMap.getUiSettings(); - uiSettings.setZoomControlsEnabled(false);// 地图缩放级别的交换按钮 - uiSettings.setAllGesturesEnabled(false);// 所有手势 - uiSettings.setMyLocationButtonEnabled(false); // 显示默认的定位按钮 - uiSettings.setLogoBottomMargin(-150); //设置Logo下边界距离屏幕底部的边距,设置为负值即可 - - mAMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() { - @Override - public void onMapLoaded() { - CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "smp---onMapLoaded"); - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(TaxiPassengerMapAssetStyleUtil.getAssetsStyle(getContext(),"map_style.data")) - .setStyleExtraData(TaxiPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(),"map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - mAMapNaviView.getMap().setPointToCenter(mAMapNaviView.getWidth() / 2, mAMapNaviView.getHeight() / 2); - } - }); - - //设置地图状态的监听接口 - mAMap.setOnCameraChangeListener(this); - } - - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return true; - } - - @Override - public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { - if (gnssInfo == null){ - return; - } - LatLng currentLatLng = new LatLng(gnssInfo.getLatitude(), gnssInfo.getLongitude()); - - if (mCoordinatesLatLng.size() > 1) { - //圈定地图显示范围 - LatLng endLatLng = mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1); - //存放经纬度 - LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); - boundsBuilder.include(currentLatLng); - boundsBuilder.include(endLatLng); - //第二个参数为四周留空宽度 - mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100,100,100,100)); -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "onCarLocationChanged2--moveCamera :" + location.getLatitude()+", "+location.getLongitude()); - - } else { - //设置希望展示的地图缩放级别 - CameraPosition cameraPosition = new CameraPosition.Builder() - .target(mCarMarker.getPosition()).tilt(0).bearing((float) gnssInfo.getHeading()).zoom(zoomLevel).build(); - mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); - } - //更新车辆位置 - if (mCarMarker != null) { -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "location.getBearing() = " + location.getBearing()); - mCarMarker.setRotateAngle((float) (360 - gnssInfo.getHeading())); - mCarMarker.setPosition(currentLatLng); -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "onCarLocationChanged2--loacation :" + location.getLatitude()+", "+location.getLongitude()); - mCarMarker.setToTop(); - } - } - - @Override - public void setLineMarker() { - if (mStartMarker != null) { - mStartMarker.setVisible(false); - } - if (mEndMarker != null) { - mEndMarker.setVisible(false); - } - if (mCoordinatesLatLng.size() >= 2) { - // 设置开始结束Marker位置 - LatLng startLatLng = mCoordinatesLatLng.get(0); - LatLng endLatLng = mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1); - if (mStartMarker != null) { - mStartMarker.setPosition(startLatLng); - mStartMarker.setVisible(true); - } - - if (mEndMarker != null) { - mEndMarker.setPosition(endLatLng); - mEndMarker.setVisible(true); - } - } - } - - @Override - public void drawablePolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - if (mAMap != null) { - - addRouteColorList(); - - if (mCoordinatesLatLng.size() >= 2) { - //设置线段纹理 - PolylineOptions polylineOptions = new PolylineOptions(); - polylineOptions.addAll(mCoordinatesLatLng); - polylineOptions.setUseTexture(true); - polylineOptions.width(15); - polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound); - polylineOptions.setCustomTextureList(textureList); - polylineOptions.setCustomTextureIndex(texIndexList); -// polylineOptions.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow_un_arrive)); - - // 绘制线 - mPolyline = mAMap.addPolyline(polylineOptions); - - } - } - } - - /** - * 添加画线颜色值 - */ - private void addRouteColorList() { - textureList.clear(); - texIndexList.clear(); - for (int i = 0; i < mCoordinatesLatLng.size(); i++){ - if (i <= mHaveArrivedIndex){ - textureList.add(mArrivedRes); - }else { - textureList.add(mUnArrivedRes); - } - texIndexList.add(i); - } - } - - - public LatLng CoordinateConverterFrom84(Context mContext, MogoLatLng mogoLatLng) { - CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); - mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); - mCoordinateConverter.coord(new LatLng(mogoLatLng.lat, mogoLatLng.lon)); - LatLng latLng = mCoordinateConverter.convert(); - return latLng; - } - - public List CoordinateConverterFrom84ForList(Context mContext, List mogoLatLngList) { - List list = new ArrayList<>(); - for (MogoLatLng m : mogoLatLngList) { - LatLng mogoLatLng = CoordinateConverterFrom84(mContext, m); - list.add(mogoLatLng); - } - return list; - } - - @Override - public void clearPolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - if (mStartMarker != null) { - mStartMarker.setVisible(false); - } - if (mEndMarker != null) { - mEndMarker.setVisible(false); - } - } - - public void resetPolyine() { - mCoordinatesLatLng.clear(); - if (mPolyline != null) { - mPolyline.remove(); - } - if (mStartMarker != null) { - mStartMarker.setVisible(false); - } - if (mEndMarker != null) { - mEndMarker.setVisible(false); - } - } - - public void onCreateView(Bundle savedInstanceState) { - if (mAMapNaviView != null) { - mAMapNaviView.onCreate(savedInstanceState); - } - } - - public void onResume() { - if (mAMapNaviView != null) { - mAMapNaviView.onResume(); - } - } - - public void onPause() { - if (mAMapNaviView != null) { - mAMapNaviView.onPause(); - } - } - - public void onDestroy() { - if (mAMapNaviView != null) { - mAMapNaviView.onDestroy(); - } - } - - public void convert(List coordinates) { - mCoordinatesLatLng.clear(); - List latLngs = CoordinateConverterFrom84ForList(mContext, coordinates); - mCoordinatesLatLng.addAll(latLngs); - } - - public void setCoordinatesLatLng(List latLngs){ - mCoordinatesLatLng.clear(); - mCoordinatesLatLng.addAll(latLngs); - } - - public void setCoordinatesLatLng(List latLngs, int haveArrivedIndex){ - mCoordinatesLatLng.clear(); - mCoordinatesLatLng.addAll(latLngs); - mHaveArrivedIndex = haveArrivedIndex; - } - - @Override - public void onCameraChange(CameraPosition cameraPosition) { - mITaxiPassengerMapViewCallback.onCameraChange(cameraPosition.bearing); - } - - @Override - public void onCameraChangeFinish(CameraPosition cameraPosition) { - - } -} diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.kt new file mode 100644 index 0000000000..0536e8e49d --- /dev/null +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerMapDirectionView.kt @@ -0,0 +1,271 @@ +package com.mogo.och.taxi.passenger.ui + +import android.content.Context +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.MotionEvent +import android.widget.RelativeLayout +import com.amap.api.maps.AMap +import com.amap.api.maps.CameraUpdate +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.TextureMapView +import com.amap.api.maps.model.BitmapDescriptor +import com.amap.api.maps.model.BitmapDescriptorFactory +import com.amap.api.maps.model.CameraPosition +import com.amap.api.maps.model.CustomMapStyleOptions +import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker +import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.model.Polyline +import com.amap.api.maps.model.PolylineOptions +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager.addListener +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.taxi.passenger.R +import com.mogo.och.taxi.passenger.callback.ITaxiPassengerMapViewCallback +import com.mogo.och.taxi.passenger.utils.TaxiPassengerMapAssetStyleUtil + +/** + * 乘客屏小地图 + */ +class TaxiPassengerMapDirectionView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener, + ITaxiPassengerMapDirectionView, AMap.OnCameraChangeListener { + + companion object { + //小地图名称 + const val TAG = "TaxiPassengerMapDirectionView" + private const val zoomLevel = 13.0f + } + + private lateinit var mAMapNaviView: TextureMapView + private lateinit var mAMap: AMap + private lateinit var mCarMarker: Marker + private lateinit var mStartMarker: Marker + private lateinit var mEndMarker: Marker + private lateinit var mArrivedRes: BitmapDescriptor + private lateinit var mUnArrivedRes: BitmapDescriptor + + private val mCoordinatesLatLng: MutableList = ArrayList() + private var mPolyline: Polyline? = null + private var mCameraUpdate: CameraUpdate? = null + private var mContext: Context? = null + var textureList: MutableList = ArrayList() + var texIndexList: MutableList = ArrayList() + private var mITaxiPassengerMapViewCallback: ITaxiPassengerMapViewCallback? = null + + private val routeArrivied: MutableList = ArrayList() + private val routeArriving: MutableList = ArrayList() + private var location: MogoLocation? = null + + init { + initView(context) + } + + fun setTaxiPassengerMapViewCallback(ITaxiPassengerMapViewCallback: ITaxiPassengerMapViewCallback?) { + mITaxiPassengerMapViewCallback = ITaxiPassengerMapViewCallback + } + + private fun initView(context: Context) { + d(SceneConstant.M_TAXI_P + TAG, "initView") + mContext = context + LayoutInflater.from(context).inflate(R.layout.taxi_p_map_view, this) + mAMapNaviView = findViewById(R.id.taxi_p_order_amap_view) + initAMapView() + + // 注册定位监听 + addListener(TAG, 10, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + } + + private fun initAMapView() { + mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel) + mAMap = mAMapNaviView.map + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap.mapType = AMap.MAP_TYPE_NIGHT + + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap.isTrafficEnabled = false + + // 设置 锚点 图标 + mCarMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_car)).anchor(0.5f, 0.5f)) + mStartMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_view_dir_start))) + mEndMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_view_dir_end))) + mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow_arrived) + mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow_un_arrive) + + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(TaxiPassengerMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData(TaxiPassengerMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data")) + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions) + + //设置希望展示的地图缩放级别 + mAMap.moveCamera(mCameraUpdate) + + // 设置地图的样式 + mAMap.uiSettings.apply { + isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + setAllGesturesEnabled(false) // 所有手势 + isMyLocationButtonEnabled = false // 显示默认的定位按钮 + setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + } + + mAMap.setOnMapLoadedListener { + d(SceneConstant.M_TAXI_P + TAG, "smp---onMapLoaded") + // 加载自定义样式 + val options = CustomMapStyleOptions() + .setEnable(true) + .setStyleData( + TaxiPassengerMapAssetStyleUtil.getAssetsStyle(context, "map_style.data") + ) + .setStyleExtraData( + TaxiPassengerMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data") + ) + // 设置自定义样式 + mAMap.setCustomMapStyle(options) + mAMapNaviView.map.setPointToCenter(mAMapNaviView.width / 2, mAMapNaviView.height / 2) + } + + //设置地图状态的监听接口 + mAMap.setOnCameraChangeListener(this) + } + + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + return true + } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (mogoLocation == null) { + return + } + val currentLatLng = LatLng(mogoLocation.latitude, mogoLocation.longitude) + if (mPolyline!=null&&!mPolyline!!.points.isNullOrEmpty()) { + //圈定地图显示范围 + val endLatLng = mPolyline!!.points.last() + //存放经纬度 + val boundsBuilder = LatLngBounds.Builder().apply { + include(currentLatLng) + include(endLatLng) + } + //第二个参数为四周留空宽度 + mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100, 100, 100, 100)) + } else { + //设置希望展示的地图缩放级别 + val cameraPosition = CameraPosition.Builder() + .target(mCarMarker.position) + .tilt(0f) + .bearing(mogoLocation.heading.toFloat()) + .zoom(zoomLevel).build() + mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) + } + //更新车辆位置 + mCarMarker.rotateAngle = (360 - mogoLocation.heading).toFloat() + mCarMarker.position = currentLatLng + mCarMarker.setToTop() + } + + override fun setLineMarker(startStation:LatLng,endStation:LatLng) { + mStartMarker.isVisible = false + mEndMarker.isVisible = false + mStartMarker.position = startStation + mStartMarker.isVisible = true + mEndMarker.position = endStation + mEndMarker.isVisible = true + } + + override fun drawablePolyline() { + if (routeArrivied.isEmpty() && routeArriving.isEmpty()) { + d(SceneConstant.M_TAXI + TAG, "没有点") + return + } + texIndexList.clear() + val allPoints = ArrayList(routeArrivied) + for (i in routeArrivied.indices) { + if (routeArrivied.size > 1 && i < routeArrivied.size - 1) { + texIndexList.add(0) + } + } + texIndexList.add(0) + allPoints.add(LatLng(location!!.latitude, location!!.longitude)) + allPoints.addAll(routeArriving) + for (ignored in routeArrivied) { + texIndexList.add(1) + } + if (mPolyline != null) { + mPolyline!!.points = allPoints + mPolyline!!.options.customTextureIndex = texIndexList + return + } + if(textureList.isEmpty()) { + textureList.add(mArrivedRes) + textureList.add(mUnArrivedRes) + } + //设置线段纹理 + val polylineOptions = PolylineOptions().apply { + addAll(allPoints) + isUseTexture = true + width(15f) + lineCapType(PolylineOptions.LineCapType.LineCapRound) + customTextureList = textureList + customTextureIndex = texIndexList + } + + // 绘制线 + mPolyline = mAMap.addPolyline(polylineOptions) + } + + override fun clearPolyline() { + if (mPolyline != null) { + mPolyline!!.remove() + mPolyline = null + } + mStartMarker.isVisible = false + mEndMarker.isVisible = false + } + + fun onCreateView(savedInstanceState: Bundle?) { + mAMapNaviView.onCreate(savedInstanceState) + } + + fun onResume() { + mAMapNaviView.onResume() + } + + fun onPause() { + mAMapNaviView.onPause() + } + + fun onDestroy() { + mAMapNaviView.onDestroy() + } + + fun setCoordinatesLatLng(routeArrivied: List?, routeArriving: List?, location: MogoLocation?) { + this.routeArrivied.clear() + this.routeArrivied.addAll(routeArrivied!!) + this.routeArriving.clear() + this.routeArriving.addAll(routeArriving!!) + this.location = location + } + + override fun onCameraChange(cameraPosition: CameraPosition) { + mITaxiPassengerMapViewCallback!!.onCameraChange(cameraPosition.bearing) + } + + override fun onCameraChangeFinish(cameraPosition: CameraPosition) {} +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.java deleted file mode 100644 index c40834776b..0000000000 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.java +++ /dev/null @@ -1,435 +0,0 @@ -package com.mogo.och.taxi.passenger.ui; - -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI_P; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.os.Build; -import android.os.Bundle; -import android.os.Looper; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.RotateAnimation; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import androidx.appcompat.widget.AppCompatSeekBar; -import androidx.fragment.app.FragmentTransaction; - -import com.amap.api.maps.model.LatLng; -import com.mogo.commons.mvp.MvpFragment; -import com.mogo.eagle.core.data.map.MogoLocation; -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; -import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; -import com.mogo.eagle.core.utilcode.util.UiThreadHandler; -import com.mogo.och.common.module.map.AmapNaviToDestinationModel; -import com.mogo.och.common.module.map.CommonAmapNaviVIew; -import com.mogo.och.common.module.utils.DateTimeUtil; -import com.mogo.och.common.module.utils.NumberFormatUtil; -import com.mogo.och.common.module.wigets.OCHGradientTextView; -import com.mogo.och.common.module.wigets.OCHRadiusImageView; -import com.mogo.och.taxi.passenger.R; -import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean; -import com.mogo.och.taxi.passenger.callback.ITaxiPassengerMapViewCallback; -import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst; -import com.mogo.och.taxi.passenger.constant.TaxiPassengerOrderStatusEnum; -import com.mogo.och.taxi.passenger.model.TaxiPassengerModel; -import com.mogo.och.taxi.passenger.presenter.TaxiPassengerServingOrderPresenter; -import com.mogo.och.taxi.passenger.utils.TPRouteDataTestUtils; - -import java.util.Calendar; -import java.util.List; - -/** - * @author: wangmingjun - * @date: 2022/3/8 - */ -public class TaxiPassengerServingOrderFragment extends - MvpFragment - implements TaxiPassengerTaxiView, ITaxiPassengerMapViewCallback { - - private final String TAG = TaxiPassengerServingOrderFragment.class.getSimpleName(); - - private OCHGradientTextView mTPSpeedTv; - private TextView mTPSpeedTvShadowBg; - - private TextView mTPOrderStatus; - private TextView mTPOrderStartStation; - private TextView mTPOrderEndStation; - private TextView mTPOrderRemainDis; - private TextView mTPOrderRemainDisUnit; - private TextView mTPOrderRemainTime; - private TextView mTPOrderRemainArriveTime; - private ImageView mMapArrowIcon; - - private TaxiPassengerMapDirectionView mMapRottingView; - private CommonAmapNaviVIew mAmapNaviVIew; - - private float lastBearing = 0; - private RotateAnimation rotateAnimation; - - private AppCompatSeekBar mProgressSeekBar; - private TextView mProgessDes; - - private OCHRadiusImageView mSpeedLayoutBg; - - private int mLimitingVelocity = 0;// 返回的道路限速值 - - public static TaxiPassengerServingOrderFragment newInstance() { - - Bundle args = new Bundle(); - - TaxiPassengerServingOrderFragment fragment = new TaxiPassengerServingOrderFragment(); - fragment.setArguments(args); - return fragment; - } - - @Override - protected int getLayoutId() { - return R.layout.taxi_p_activity_serving_order_view; - } - - @Override - public String getTagName() { - return "TaxiPassengerServingOrderFragment"; - } - - @Override - protected void initViews() { - - mTPSpeedTv = findViewById(R.id.taxi_p_speed_tv); - mTPSpeedTvShadowBg = findViewById(R.id.taxi_p_speed_tv_bg); - mTPSpeedTv.setVertrial(true); - mTPSpeedTv.setmColorList(new int[]{getResources().getColor(R.color.taxi_p_speed_normal_color1),getResources().getColor(R.color.taxi_p_speed_normal_color2)}); - mTPSpeedTv.setText(String.valueOf(0)); - mTPSpeedTvShadowBg.setText(String.valueOf(0)); - - mTPOrderStatus = findViewById(R.id.taxi_p_order_status_tv); - mTPOrderStartStation = findViewById(R.id.taxi_p_order_status_start_station_tv); - mTPOrderEndStation = findViewById(R.id.taxi_p_order_status_end_station_tv); - mTPOrderRemainDis = findViewById(R.id.taxi_p_order_remain_distance); - mTPOrderRemainDisUnit = findViewById(R.id.taxi_p_order_remain_distance_unit); - mTPOrderRemainTime = findViewById(R.id.taxi_p_order_remain_time); - mTPOrderRemainArriveTime = findViewById(R.id.taxi_p_order_remain_arrive_time); - - mMapArrowIcon = findViewById(R.id.taxi_p_arrow_nor); - mProgressSeekBar = findViewById(R.id.taxi_p_seekbar); - mProgessDes = findViewById(R.id.taxi_p_progress_des); - - mSpeedLayoutBg = findViewById(R.id.taxi_p_speed_bg); - - mTPOrderStatus.setOnLongClickListener(new View.OnLongClickListener() { //测试用 - @Override - public boolean onLongClick(View v) { - TPRouteDataTestUtils.converToRouteData(); - return true; - } - }); - - } - - @Override - protected void initViews(Bundle savedInstanceState) { - super.initViews(savedInstanceState); - initRouteNaviView(savedInstanceState); - initAmapNaviView(savedInstanceState); - } - - private void initAmapNaviView(Bundle savedInstanceState) { - mAmapNaviVIew = mRootView.findViewById(R.id.taxi_p_order_amap_navi_view); - mAmapNaviVIew.onCreate(savedInstanceState); - TaxiPassengerModel.getInstance().startNaviByAmap(); - } - - private void initRouteNaviView(Bundle savedInstanceState) { - mMapRottingView = mRootView.findViewById(R.id.taxi_p_order_rotting_map_view); - mMapRottingView.onCreateView(savedInstanceState); - mMapRottingView.setTaxiPassengerMapViewCallback(this); - } - - @NonNull - @Override - protected TaxiPassengerServingOrderPresenter createPresenter() { - return new TaxiPassengerServingOrderPresenter(this); - } - - /** - * 设置进度条最大值为 起点终点首次规划出的值 - */ - private void setSeekBarMax() { - //计算订单起点和终点距离 - int maxInt = SharedPrefsMgr.getInstance(getContext()).getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,0); - CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "maxInt = " + maxInt); - mProgressSeekBar.setMax(maxInt); - } - - /** - * 行驶进度值更新 - */ - @RequiresApi(api = Build.VERSION_CODES.N) - private void updateDriveProcessLoading(int progressLoading) { - int progressInt = SharedPrefsMgr.getInstance(getContext()) - .getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,0) - progressLoading; - CallerLogger.INSTANCE.d(M_TAXI_P + TAG,"progressInt = "+progressInt); - mProgressSeekBar.setProgress( - progressInt - , true); - mProgressSeekBar.jumpDrawablesToCurrentState(); - } - - private void updateDriveRoadName(String currentRoadName){ - if (mProgessDes != null){ - mProgessDes.setText(currentRoadName); - } - } - - @Override - public void onResume() { - super.onResume(); - if (mMapRottingView != null) { - mMapRottingView.onResume(); - } - if (mAmapNaviVIew != null){ - mAmapNaviVIew.onResume(); - } - TaxiPassengerModel.getInstance().initGeocodeSearch(); - } - - @Override - public void onHiddenChanged(boolean hidden) { - super.onHiddenChanged(hidden); - - if (hidden){//fragment 隐藏, 导航取消c - clearPolyline(); - TaxiPassengerModel.getInstance().destoryGeocodeSearch(); - }else { //fragment 显示, 导航开始 - CallerLogger.INSTANCE.e(M_TAXI_P +"TaxiPassengerNaviTo","initGeocodeSearch"); - TaxiPassengerModel.getInstance().initGeocodeSearch(); - } - } - - @Override - public void onPause() { - super.onPause(); - if (mMapRottingView != null) { - mMapRottingView.onPause(); - } - if (mAmapNaviVIew != null){ - mAmapNaviVIew.onPause(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (mMapRottingView != null) { - mMapRottingView.onDestroy(); - } - if (mAmapNaviVIew != null){ - mAmapNaviVIew.onDestroy(); - } - AmapNaviToDestinationModel.getInstance(getContext()).destroyAmaNavi(); - TaxiPassengerModel.getInstance().destoryGeocodeSearch(); - } - - public void showRottingMapView(){ - if (mAmapNaviVIew != null && mAmapNaviVIew.getVisibility() == View.VISIBLE){ - mAmapNaviVIew.setVisibility(View.GONE); - } - if (mMapRottingView != null && mMapRottingView.getVisibility() == View.GONE){ - mMapRottingView.setVisibility(View.VISIBLE); - } - } - - public void setLineMarker(List latLngList){ - if (latLngList.size() > 0) { - if (mMapRottingView != null) { - mMapRottingView.setCoordinatesLatLng(latLngList); - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapRottingView.setLineMarker(); - } - }); - } - } else { - clearPolyline(); - } - } - - public void routeResultByServer(List latLngList,int haveArrivedIndex) { - if (latLngList.size() > 0) { - drawablePolylineByServerRoute(latLngList,haveArrivedIndex); - } else { - clearPolyline(); - } - } - - public void drawablePolylineByServerRoute(List mCoordinatesLatLng,int haveArrivedIndex){ - if (mMapRottingView != null){ - mMapRottingView.setCoordinatesLatLng(mCoordinatesLatLng,haveArrivedIndex); - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapRottingView.drawablePolyline(); - } - }); - } - } - private void clearPolyline() { - if (mMapRottingView != null) { - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapRottingView.clearPolyline(); - } - }); - } - } - - public void updateOrderStatusView(TaxiPassengerOrderQueryRespBean.Result order) { - mTPOrderStartStation.setText(order.startSiteAddr); - mTPOrderEndStation.setText(order.endSiteAddr); - - if (TaxiPassengerOrderStatusEnum.ArriveAtStart.getCode() == order.orderStatus) { - mTPOrderStatus.setText(getString(R.string.taxi_p_arrive_to_start)); - mTPOrderRemainDis.setText("--"); - mTPOrderRemainTime.setText("--"); - mTPOrderRemainArriveTime.setText("--"); - setSeekBarMax(); - return; - } - - if (TaxiPassengerOrderStatusEnum.OnTheWayToEnd.getCode() == order.orderStatus) { - mTPOrderStatus.setText(R.string.taxi_p_start_to_end); - setSeekBarMax(); - return; - } - } - - /** - * 剩余里程,剩余时间,当前定位点所在道路 - * @param meters 单位 米 - * @param remainTime 单位 秒 - */ - @RequiresApi(api = Build.VERSION_CODES.N) - public void onCurrentOrderDistToEndChanged(long meters, long remainTime) { - String disUnit = "公里"; - String remainDis = "0"; - - if (meters > 0){ - if (meters / 1000 < 1){ - disUnit = "米"; - remainDis = String.valueOf(Math.round(meters)); - }else { - disUnit = "公里"; - remainDis = NumberFormatUtil.formatLong((double) meters / 1000); - } - } - - int time = (int)Math.ceil((double)remainTime/ 60f); - - Calendar beforeTime = Calendar.getInstance(); - beforeTime.add(Calendar.MINUTE,time); - String arriveTime = DateTimeUtil.formatCalendarToString(beforeTime,DateTimeUtil.HH_mm); - updateOrderDisAndTimeView(remainDis, disUnit,time, arriveTime); - updateDriveProcessLoading(new Long(meters).intValue()); - } - - public void onCurrentRoadName(String roadName){ - updateDriveRoadName(roadName); - } - - private void updateOrderDisAndTimeView(String remainDis, String remainDisUnit, int remainTime, String arriveTime) { - mTPOrderRemainDis.setText(remainDis); - mTPOrderRemainDisUnit.setText(remainDisUnit); - mTPOrderRemainTime.setText(String.valueOf(remainTime)); - mTPOrderRemainArriveTime.setText(arriveTime); - - } - - public void onCarLocationChanged(MogoLocation location) { - updateSpeedView((float) location.getGnssSpeed()); - } - - public void onLimitingVelocityChange(int limitingVelocity) { - mLimitingVelocity = limitingVelocity; - } - - /** - * 更新速度 - * - * @param newSpeed - */ - private void updateSpeedView(float newSpeed) { - int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值 - CallerLogger.INSTANCE.d(M_TAXI_P + TAG,"mLimitingVelocity = "+mLimitingVelocity); -// if (mLimitingVelocity > 0 && speed >= mLimitingVelocity) { -// mTPSpeedTv.setmColorList(new int[]{getResources().getColor(R.color.taxi_p_speed_warn_color1),getResources().getColor(R.color.taxi_p_speed_warn_color2)}); -// mTPSpeedTv.setText(String.valueOf(speed)); -// mTPSpeedTvShadowBg.setText(String.valueOf(speed)); -// -// mSpeedLayoutBg.setImageResource(R.drawable.taxi_p_speed_light_red_bg); -// } else { - mTPSpeedTv.setmColorList(new int[]{getResources().getColor(R.color.taxi_p_speed_normal_color1),getResources().getColor(R.color.taxi_p_speed_normal_color2)}); - mTPSpeedTv.setText(String.valueOf(speed)); - mTPSpeedTvShadowBg.setText(String.valueOf(speed)); - - mSpeedLayoutBg.setImageResource(R.drawable.taxi_p_speed_light_green_bg); -// } - } - - private void runOnUIThread(Runnable executor) { - if (executor == null) { - return; - } - if (Looper.myLooper() != Looper.getMainLooper()) { - UiThreadHandler.post(executor); - } else { - executor.run(); - } - } - - @Override - public void onCameraChange(float bearing) { - startIvCompass(bearing); - } - - /** - * 设置指南针旋转 - * - * @param bearing - */ - private void startIvCompass(float bearing) { - bearing = 360 - bearing; - CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "startIvCompass: " + bearing); - rotateAnimation = new RotateAnimation(lastBearing, bearing, Animation.RELATIVE_TO_SELF - , 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); - rotateAnimation.setFillAfter(true); - - mMapArrowIcon.startAnimation(rotateAnimation); - lastBearing = bearing; - } - - @Nullable - @Override - public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { - if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) { - if (enter) {//普通的进入的动作 - return AnimatorInflater.loadAnimator(getContext(),R.animator.alpha_hide_show_f); - } else {//比如一个已经Fragmen被另一个replace,是一个进入动作,被replace的那个就是false - return AnimatorInflater.loadAnimator(getContext(),R.animator.alpha_hide_hide_f); - } - } else if (FragmentTransaction.TRANSIT_FRAGMENT_CLOSE == transit) { - if (enter) {//之前被replace的重新进入到界面或者Fragment回到栈顶 - return AnimatorInflater.loadAnimator(getContext(),R.animator.alpha_hide_show_f); - } else {//Fragment退出,出栈 - return AnimatorInflater.loadAnimator(getContext(),R.animator.alpha_hide_hide_f); - } - } - return super.onCreateAnimator(transit,enter,nextAnim); - } -} diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.kt new file mode 100644 index 0000000000..926ee23f72 --- /dev/null +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerServingOrderFragment.kt @@ -0,0 +1,370 @@ +package com.mogo.och.taxi.passenger.ui + +import android.animation.Animator +import android.animation.AnimatorInflater +import android.os.Build +import android.os.Bundle +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.appcompat.widget.AppCompatSeekBar +import androidx.fragment.app.FragmentTransaction +import com.amap.api.maps.model.LatLng +import com.mogo.commons.mvp.MvpFragment +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.common.module.map.AmapNaviToDestinationModel +import com.mogo.och.common.module.map.CommonAmapNaviVIew +import com.mogo.och.common.module.utils.DateTimeUtil +import com.mogo.och.common.module.utils.NumberFormatUtil +import com.mogo.och.common.module.wigets.OCHGradientTextView +import com.mogo.och.common.module.wigets.OCHRadiusImageView +import com.mogo.och.taxi.passenger.R +import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean +import com.mogo.och.taxi.passenger.callback.ITaxiPassengerMapViewCallback +import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst +import com.mogo.och.taxi.passenger.constant.TaxiPassengerOrderStatusEnum +import com.mogo.och.taxi.passenger.model.TaxiPassengerModel +import com.mogo.och.taxi.passenger.presenter.TaxiPassengerServingOrderPresenter +import com.mogo.och.taxi.passenger.utils.TPRouteDataTestUtils +import java.util.Calendar + +/** + * @author: wangmingjun + * @date: 2022/3/8 + */ +class TaxiPassengerServingOrderFragment : + MvpFragment(), + TaxiPassengerTaxiView, ITaxiPassengerMapViewCallback { + private val TAG = TaxiPassengerServingOrderFragment::class.java.simpleName + private var mTPSpeedTv: OCHGradientTextView? = null + private var mTPSpeedTvShadowBg: TextView? = null + private var mTPOrderStatus: TextView? = null + private var mTPOrderStartStation: TextView? = null + private var mTPOrderEndStation: TextView? = null + private var mTPOrderRemainDis: TextView? = null + private var mTPOrderRemainDisUnit: TextView? = null + private var mTPOrderRemainTime: TextView? = null + private var mTPOrderRemainArriveTime: TextView? = null + private var mMapArrowIcon: ImageView? = null + private var mMapRottingView: TaxiPassengerMapDirectionView? = null + private var mAmapNaviVIew: CommonAmapNaviVIew? = null + private var lastBearing = 0f + private var rotateAnimation: RotateAnimation? = null + private var mProgressSeekBar: AppCompatSeekBar? = null + private var mProgessDes: TextView? = null + private var mSpeedLayoutBg: OCHRadiusImageView? = null + @Volatile + private var mLimitingVelocity = 0 // 返回的道路限速值 + override fun getLayoutId(): Int { + return R.layout.taxi_p_activity_serving_order_view + } + + override fun getTagName(): String { + return "TaxiPassengerServingOrderFragment" + } + + override fun initViews() { + mTPSpeedTv = findViewById(R.id.taxi_p_speed_tv) + mTPSpeedTvShadowBg = findViewById(R.id.taxi_p_speed_tv_bg) + mTPSpeedTv!!.setVertrial(true) + mTPSpeedTv!!.setmColorList( + intArrayOf( + resources.getColor(R.color.taxi_p_speed_normal_color1), resources.getColor( + R.color.taxi_p_speed_normal_color2 + ) + ) + ) + mTPSpeedTv!!.text = 0.toString() + mTPSpeedTvShadowBg!!.text = 0.toString() + mTPOrderStatus = findViewById(R.id.taxi_p_order_status_tv) + mTPOrderStartStation = findViewById(R.id.taxi_p_order_status_start_station_tv) + mTPOrderEndStation = findViewById(R.id.taxi_p_order_status_end_station_tv) + mTPOrderRemainDis = findViewById(R.id.taxi_p_order_remain_distance) + mTPOrderRemainDisUnit = findViewById(R.id.taxi_p_order_remain_distance_unit) + mTPOrderRemainTime = findViewById(R.id.taxi_p_order_remain_time) + mTPOrderRemainArriveTime = findViewById(R.id.taxi_p_order_remain_arrive_time) + mMapArrowIcon = findViewById(R.id.taxi_p_arrow_nor) + mProgressSeekBar = findViewById(R.id.taxi_p_seekbar) + mProgessDes = findViewById(R.id.taxi_p_progress_des) + mSpeedLayoutBg = findViewById(R.id.taxi_p_speed_bg) + mTPOrderStatus!!.setOnLongClickListener { + TPRouteDataTestUtils.converToRouteData() + true + } + } + + override fun initViews(savedInstanceState: Bundle?) { + super.initViews(savedInstanceState) + initRouteNaviView(savedInstanceState) + initAmapNaviView(savedInstanceState) + } + + private fun initAmapNaviView(savedInstanceState: Bundle?) { + mAmapNaviVIew = findViewById(R.id.taxi_p_order_amap_navi_view) + mAmapNaviVIew?.onCreate(savedInstanceState) + TaxiPassengerModel.getInstance().startNaviByAmap() + } + + private fun initRouteNaviView(savedInstanceState: Bundle?) { + mMapRottingView = findViewById(R.id.taxi_p_order_rotting_map_view) + mMapRottingView?.onCreateView(savedInstanceState) + mMapRottingView?.setTaxiPassengerMapViewCallback(this) + } + + override fun createPresenter(): TaxiPassengerServingOrderPresenter { + return TaxiPassengerServingOrderPresenter(this) + } + + /** + * 设置进度条最大值为 起点终点首次规划出的值 + */ + private fun setSeekBarMax() { + //计算订单起点和终点距离 + val maxInt = SharedPrefsMgr.getInstance(requireContext()) + .getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS, 0) + d(SceneConstant.M_TAXI_P + TAG, "maxInt = $maxInt") + mProgressSeekBar!!.max = maxInt + } + + /** + * 行驶进度值更新 + */ + @RequiresApi(api = Build.VERSION_CODES.N) + private fun updateDriveProcessLoading(progressLoading: Int) { + val progressInt = SharedPrefsMgr.getInstance(requireContext()) + .getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS, 0) - progressLoading + d(SceneConstant.M_TAXI_P + TAG, "progressInt = $progressInt") + mProgressSeekBar?.setProgress(progressInt, true) + mProgressSeekBar?.jumpDrawablesToCurrentState() + } + + private fun updateDriveRoadName(currentRoadName: String) { + mProgessDes?.text = currentRoadName + } + + override fun onResume() { + super.onResume() + mMapRottingView?.onResume() + mAmapNaviVIew?.onResume() + TaxiPassengerModel.getInstance().initGeocodeSearch() + } + + override fun onHiddenChanged(hidden: Boolean) { + super.onHiddenChanged(hidden) + if (hidden) { //fragment 隐藏, 导航取消c + clearPolyline() + TaxiPassengerModel.getInstance().destoryGeocodeSearch() + } else { //fragment 显示, 导航开始 + e(SceneConstant.M_TAXI_P + "TaxiPassengerNaviTo", "initGeocodeSearch") + TaxiPassengerModel.getInstance().initGeocodeSearch() + } + } + + override fun onPause() { + super.onPause() + mMapRottingView?.onPause() + mAmapNaviVIew?.onPause() + } + + override fun onDestroy() { + super.onDestroy() + mMapRottingView?.onDestroy() + mAmapNaviVIew?.onDestroy() + AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() + TaxiPassengerModel.getInstance().destoryGeocodeSearch() + } + + fun showRottingMapView() { + if (mAmapNaviVIew != null && mAmapNaviVIew!!.visibility == View.VISIBLE) { + mAmapNaviVIew!!.visibility = View.GONE + } + if (mMapRottingView != null && mMapRottingView!!.visibility == View.GONE) { + mMapRottingView!!.visibility = View.VISIBLE + } + } + + fun setLineMarker(startStation: LatLng?, endStation: LatLng?) { + if (startStation != null && endStation != null) { + UiThreadHandler.post { mMapRottingView?.setLineMarker(startStation, endStation) } + } else { + clearPolyline() + } + } + + fun routeResultByServer( + routeArriviedTemp: List?, + routeArrivingTemp: List?, + location: MogoLocation + ) { + if (routeArriviedTemp.isNullOrEmpty()||routeArrivingTemp.isNullOrEmpty()) { + clearPolyline() + } else { + drawablePolylineByServerRoute(routeArriviedTemp, routeArrivingTemp,location) + } + } + + private fun drawablePolylineByServerRoute(routeArrivied: List?, + routeArriving: List?, + location: MogoLocation?) { + mMapRottingView?.setCoordinatesLatLng(routeArrivied, routeArriving,location) + UiThreadHandler.post { mMapRottingView?.drawablePolyline() } + } + + private fun clearPolyline() { + UiThreadHandler.post { mMapRottingView?.clearPolyline() } + } + + fun updateOrderStatusView(order: TaxiPassengerOrderQueryRespBean.Result) { + mTPOrderStartStation!!.text = order.startSiteAddr + mTPOrderEndStation!!.text = order.endSiteAddr + if (TaxiPassengerOrderStatusEnum.ArriveAtStart.code == order.orderStatus) { + mTPOrderStatus!!.text = getString(R.string.taxi_p_arrive_to_start) + mTPOrderRemainDis!!.text = "--" + mTPOrderRemainTime!!.text = "--" + mTPOrderRemainArriveTime!!.text = "--" + setSeekBarMax() + return + } + if (TaxiPassengerOrderStatusEnum.OnTheWayToEnd.code == order.orderStatus) { + mTPOrderStatus!!.setText(R.string.taxi_p_start_to_end) + setSeekBarMax() + return + } + } + + /** + * 剩余里程,剩余时间,当前定位点所在道路 + * @param meters 单位 米 + * @param remainTime 单位 秒 + */ + @RequiresApi(api = Build.VERSION_CODES.N) + fun onCurrentOrderDistToEndChanged(meters: Long, remainTime: Long) { + var disUnit = "公里" + var remainDis = "0" + if (meters > 0) { + if (meters / 1000 < 1) { + disUnit = "米" + remainDis = Math.round(meters.toFloat()).toString() + } else { + disUnit = "公里" + remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000) + } + } + val time = Math.ceil(remainTime.toDouble() / 60f).toInt() + val beforeTime = Calendar.getInstance() + beforeTime.add(Calendar.MINUTE, time) + val arriveTime = DateTimeUtil.formatCalendarToString(beforeTime, DateTimeUtil.HH_mm) + updateOrderDisAndTimeView(remainDis, disUnit, time, arriveTime) + updateDriveProcessLoading(meters.toInt()) + } + + fun onCurrentRoadName(roadName: String) { + updateDriveRoadName(roadName) + } + + private fun updateOrderDisAndTimeView( + remainDis: String, + remainDisUnit: String, + remainTime: Int, + arriveTime: String + ) { + mTPOrderRemainDis!!.text = remainDis + mTPOrderRemainDisUnit!!.text = remainDisUnit + mTPOrderRemainTime!!.text = remainTime.toString() + mTPOrderRemainArriveTime!!.text = arriveTime + } + + fun onCarLocationChanged(location: MogoLocation) { + updateSpeedView(location.gnssSpeed) + } + + fun onLimitingVelocityChange(limitingVelocity: Int) { + mLimitingVelocity = limitingVelocity + } + + /** + * 更新速度 + * + * @param newSpeed + */ + private fun updateSpeedView(newSpeed: Float) { + val speed = (Math.abs(newSpeed) * 3.6f).toInt() // 倒车时工控机反馈定位信息中speed为负值 + d(SceneConstant.M_TAXI_P + TAG, "mLimitingVelocity = $mLimitingVelocity") + mTPSpeedTv?.setmColorList( + intArrayOf( + resources.getColor(R.color.taxi_p_speed_normal_color1), resources.getColor( + R.color.taxi_p_speed_normal_color2 + ) + ) + ) + mTPSpeedTv?.text = speed.toString() + mTPSpeedTvShadowBg?.text = speed.toString() + mSpeedLayoutBg?.setImageResource(R.drawable.taxi_p_speed_light_green_bg) + } + + override fun onCameraChange(bearing: Float) { + startIvCompass(360-bearing) + } + + /** + * 设置指南针旋转 + * + * @param bearing + */ + private fun startIvCompass(bearing: Float) { + d(SceneConstant.M_TAXI_P + TAG, "startIvCompass: $bearing") + rotateAnimation = RotateAnimation( + lastBearing, bearing, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f + ) + rotateAnimation!!.fillAfter = true + mMapArrowIcon!!.startAnimation(rotateAnimation) + lastBearing = bearing + } + + override fun onCreateAnimator(transit: Int, enter: Boolean, nextAnim: Int): Animator? { + if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) { + return if (enter) { //普通的进入的动作 + AnimatorInflater.loadAnimator( + context, + R.animator.alpha_hide_show_f + ) + } else { //比如一个已经Fragmen被另一个replace,是一个进入动作,被replace的那个就是false + AnimatorInflater.loadAnimator( + context, + R.animator.alpha_hide_hide_f + ) + } + } else if (FragmentTransaction.TRANSIT_FRAGMENT_CLOSE == transit) { + return if (enter) { //之前被replace的重新进入到界面或者Fragment回到栈顶 + AnimatorInflater.loadAnimator( + context, + R.animator.alpha_hide_show_f + ) + } else { //Fragment退出,出栈 + AnimatorInflater.loadAnimator( + context, + R.animator.alpha_hide_hide_f + ) + } + } + return super.onCreateAnimator(transit, enter, nextAnim) + } + + companion object { + @JvmStatic + fun newInstance(): TaxiPassengerServingOrderFragment { + val args = Bundle() + val fragment = TaxiPassengerServingOrderFragment() + fragment.arguments = args + return fragment + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/comment/TaxiPassengerArrivedView.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/comment/TaxiPassengerArrivedView.kt index 548280ca96..545947b0ef 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/comment/TaxiPassengerArrivedView.kt +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/comment/TaxiPassengerArrivedView.kt @@ -259,7 +259,7 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener { .setDuration(120) alpha.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener{ var isStart = false - override fun onAnimationUpdate(animation: ValueAnimator?) { + override fun onAnimationUpdate(animation: ValueAnimator) { val animatedValue = animation?.getAnimatedValue("alpha") animatedValue as Float if(animatedValue>0.45&&!isStart){ @@ -293,7 +293,7 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener { if(currentAnimarion==maxIndex) { // 最后一个动画结束后提交积分 set.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator?) { + override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) // 启动变高动画 startChangeHeightAnimarion() diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/leftmenu/OverlayLeftViewUtils.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/leftmenu/OverlayLeftViewUtils.kt index f16747eef7..d833aab94a 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/leftmenu/OverlayLeftViewUtils.kt +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/leftmenu/OverlayLeftViewUtils.kt @@ -226,8 +226,8 @@ object OverlayLeftViewUtils { windowManager?.updateViewLayout(overlayView, params) } valueAnimator.addListener(object : Animator.AnimatorListener { - override fun onAnimationStart(animation: Animator?) {} - override fun onAnimationEnd(animation: Animator?) { + override fun onAnimationStart(animation: Animator) {} + override fun onAnimationEnd(animation: Animator) { acivOpenClose?.apply { pivotX = (width /2).toFloat() pivotY = (height /2).toFloat() @@ -239,8 +239,8 @@ object OverlayLeftViewUtils { WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL windowManager?.updateViewLayout(overlayView, params) } - override fun onAnimationCancel(animation: Animator?) {} - override fun onAnimationRepeat(animation: Animator?) {} + override fun onAnimationCancel(animation: Animator) {} + override fun onAnimationRepeat(animation: Animator) {} }) valueAnimator.start() } @@ -324,8 +324,8 @@ object OverlayLeftViewUtils { } } valueAnimator.addListener(object : Animator.AnimatorListener { - override fun onAnimationStart(animation: Animator?) {} - override fun onAnimationEnd(animation: Animator?) { + override fun onAnimationStart(animation: Animator) {} + override fun onAnimationEnd(animation: Animator) { acivOpenClose?.apply { pivotX = (width /2).toFloat() pivotY = (height /2).toFloat() @@ -340,8 +340,8 @@ object OverlayLeftViewUtils { } } - override fun onAnimationCancel(animation: Animator?) {} - override fun onAnimationRepeat(animation: Animator?) {} + override fun onAnimationCancel(animation: Animator) {} + override fun onAnimationRepeat(animation: Animator) {} }) valueAnimator.start() } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/video/layoutmanage/CarouselLayoutManager.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/video/layoutmanage/CarouselLayoutManager.java index e77f40efe4..326341e950 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/video/layoutmanage/CarouselLayoutManager.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/video/layoutmanage/CarouselLayoutManager.java @@ -934,7 +934,7 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements } private CarouselSavedState(@NonNull final Parcel in) { - mSuperState = in.readParcelable(Parcelable.class.getClassLoader()); + mSuperState = in.readParcelable(RecyclerView.LayoutManager.class.getClassLoader()); mCenterItemPosition = in.readInt(); } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TPRouteDataTestUtils.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TPRouteDataTestUtils.java index 7bd9a381ea..d837a76b89 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TPRouteDataTestUtils.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TPRouteDataTestUtils.java @@ -37,7 +37,6 @@ public class TPRouteDataTestUtils { builder.setLongitude(s.getDouble("lon")); list.add(builder.build()); } - TaxiPassengerModel.getInstance().setRouteLineMarker(list); TaxiPassengerModel.getInstance().startToRouteAndWipe(list); } catch (JSONException e) { e.printStackTrace(); diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TaxiPassengerAnalyticsManager.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TaxiPassengerAnalyticsManager.java index 21ff9ef517..a3b8d863a1 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TaxiPassengerAnalyticsManager.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/utils/TaxiPassengerAnalyticsManager.java @@ -52,7 +52,7 @@ public class TaxiPassengerAnalyticsManager { CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_FAILURE_CODE, failCode); mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_FAILURE_MSG, @@ -60,7 +60,7 @@ public class TaxiPassengerAnalyticsManager { } mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_RESULT - , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + , CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml index 85eba2cdd4..a5533567ba 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml @@ -50,6 +50,7 @@ app:layout_constraintStart_toStartOf="parent" /> models); - void routeResult(List models, int haveArrivedIndex); + void setLineMarker(LatLng startStation,LatLng endStation); + void routeResult(List routeArrivied,List routeArriving, MogoLocation location); } \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java index d07526da74..edae674246 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java @@ -1,5 +1,10 @@ package com.mogo.och.taxi.model; +import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_CODE_OCH_TAXI_START_AUTOPILOT; +import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_SOURCE_ADAS; +import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_TYPE_SOCKET_AUTOPILOT; +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI; + import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; @@ -32,6 +37,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListener import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.eagle.core.utilcode.util.CoordinateUtils; +import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils; import com.mogo.eagle.core.utilcode.util.NetworkUtils; import com.mogo.eagle.core.utilcode.util.ToastUtils; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; @@ -44,6 +50,9 @@ import com.mogo.och.common.module.biz.provider.LoginService; import com.mogo.och.common.module.callback.OchAdasStartFailureCallback; import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager; import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.manager.distancemamager.IDistanceListener; +import com.mogo.och.common.module.manager.distancemamager.ITrajectoryListener; +import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager; import com.mogo.och.common.module.map.AmapNaviToDestinationModel; import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; import com.mogo.och.common.module.utils.PinYinUtil; @@ -75,7 +84,6 @@ import com.mogo.och.taxi.utils.OrderUtil; import com.mogo.och.taxi.utils.TaxiAnalyticsManager; import com.mogo.och.taxi.utils.TaxiTrajectoryManager; import com.zhjt.service.chain.ChainLog; -import com.zhjt.service.chain.TracingConstants; import org.jetbrains.annotations.NotNull; @@ -83,7 +91,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import io.reactivex.exceptions.UndeliverableException; import io.reactivex.functions.Consumer; @@ -92,11 +99,6 @@ import mogo.telematics.pad.MessagePad; import mogo_msg.MogoReportMsg; import system_master.SystemStatusInfo; -import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_ALIAS_CODE_OCH_TAXI_START_AUTOPILOT; -import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_LINK_ADAS; -import static com.mogo.eagle.core.data.deva.chain.ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT; -import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI; - /** * Created by pangfan on 2021/8/19 *

@@ -115,7 +117,6 @@ public class TaxiModel { } private Context mContext; - private volatile int mPrevAPStatus = -1; //前一次自动驾驶状态值 private volatile String mPrevOrderNo = ""; //前一次的新到单id(当次和前一次orderId相同时,本次不再弹出) private volatile OrderQueryRespBean.Result mNewBookingOrder; //新到待抢预约单 private volatile OrderQueryRespBean.Result mCurrentOCHOrder; //当前订单 @@ -134,7 +135,7 @@ public class TaxiModel { private int mPreRouteIndex = 0; private double mLongitude, mLatitude; - private MogoLocation mLocation = null; + private MogoLocation mLocation = null; private LoginService loginService; @@ -224,7 +225,7 @@ public class TaxiModel { MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); //定位监听, 传false是高德坐标系 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,mMapLocationLIstener); + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,10, mMapLocationListener); //2021.11.1 自动驾驶路线规划接口 CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener); @@ -238,6 +239,9 @@ public class TaxiModel { AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext); + TrajectoryAndDistanceManager.INSTANCE.addDistanceListener(TAG,distanceListener); + TrajectoryAndDistanceManager.INSTANCE.addTrajectoryListener(TAG,trajectoryListener); + } private final IMogoOnMessageListener mMogoOnMessageListener = @@ -249,13 +253,13 @@ public class TaxiModel { @Override public void onMsgReceived(OCHOperationalMessage obj) { - if (obj == null){ + if (obj == null) { CallerLogger.INSTANCE.d(M_TAXI + TAG, "onMsgReceived = null"); return; } - CallerLogger.INSTANCE.d(M_TAXI + TAG, "onMsgReceived = "+obj.getMessage()); + CallerLogger.INSTANCE.d(M_TAXI + TAG, "onMsgReceived = " + obj.getMessage()); OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox(obj.getPushTimeStamp(), - obj.getMessage(),OCHSocketMessageManager.OPERATION_SYSTEM); + obj.getMessage(), OCHSocketMessageManager.OPERATION_SYSTEM); } }; @@ -289,11 +293,11 @@ public class TaxiModel { //更新接单状态 public void updateCarStatus() { - if(!LoginStatusManager.isLogin()){ + if (!LoginStatusManager.isLogin()) { loginService.queryLoginStatusByNet(); return; } - TaxiServiceManager.changeOrderServing(mContext,TaxtServingStatusManager.isOpeningOrderStatus(), + TaxiServiceManager.changeOrderServing(mContext, TaxtServingStatusManager.isOpeningOrderStatus(), new OchCommonServiceCallback() { @Override public void onSuccess(BaseData data) { @@ -348,8 +352,8 @@ public class TaxiModel { //1.1.2. 当本地有currentOrder: //orderId不一致时:通过currentOrder.orderId查询订单状态,并通知ui更新 //orderId一致且orderStatus不一致时:则更新currentOrder,并通知ui更新 - CallerLogger.INSTANCE.d(M_TAXI + TAG,"AutopilotControl-mCurrentOCHOrder = "+mCurrentOCHOrder.orderStatus - + ", orderStatus = " +data.data.servicing.get(0).orderStatus); + CallerLogger.INSTANCE.d(M_TAXI + TAG, "AutopilotControl-mCurrentOCHOrder = " + mCurrentOCHOrder.orderStatus + + ", orderStatus = " + data.data.servicing.get(0).orderStatus); if (!mCurrentOCHOrder.orderNo.equals(data.data.servicing.get(0).orderNo)) { queryCurOrderStatus(); } else if (mCurrentOCHOrder.orderStatus != data.data.servicing.get(0).orderStatus) { @@ -461,7 +465,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtilsOch.showWithCodeMessage(code,msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); } @@ -490,7 +494,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtilsOch.showWithCodeMessage(code,msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); } @@ -544,7 +548,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtilsOch.showWithCodeMessage(code,msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); } @@ -638,7 +642,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtilsOch.showWithCodeMessage(code,msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); } @@ -732,7 +736,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtilsOch.showWithCodeMessage(code,msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); } @@ -748,7 +752,7 @@ public class TaxiModel { TaxiServiceManager.confirmAutopilotConditionByDriver(mContext, mCurrentOCHOrder.orderNo, result, - new OchCommonServiceCallback(){ + new OchCommonServiceCallback() { @Override public void onSuccess(TaxiDataBaseRespBean data) { @@ -762,19 +766,19 @@ public class TaxiModel { }); } - public void updateAutopilotStatus(boolean isSafe){ - if (mOrderStatusCallback != null){ + public void updateAutopilotStatus(boolean isSafe) { + if (mOrderStatusCallback != null) { mOrderStatusCallback.onDriverHasCheckedPilotCondition(isSafe); } } - public void queryAutopilotStatus(boolean isStart){ - if (isStart){ + public void queryAutopilotStatus(boolean isStart) { + if (isStart) { queryAutopilotStatus(); } } - public void queryAutopilotStatus(){ + public void queryAutopilotStatus() { if (mCurrentOCHOrder == null) return; TaxiServiceManager.queryAutopilotStatus(mContext, mCurrentOCHOrder.orderNo, new OchCommonServiceCallback() { @@ -820,7 +824,7 @@ public class TaxiModel { SharedPrefsMgr.getInstance(mContext).putString(TaxiConst.SP_KEY_OCH_TAXI_ORDER, GsonUtil.jsonFromObject(data)); - if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.OnTheWayToEnd.getCode()){ + if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.OnTheWayToEnd.getCode()) { if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; @@ -831,7 +835,7 @@ public class TaxiModel { updateAutopilotControlParameters(); } - if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.ArriveAtEnd.getCode()){ + if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.ArriveAtEnd.getCode()) { if (FunctionBuildConfig.isDemoMode) { CallerLogger.INSTANCE.d(M_TAXI + TAG, "setIPCDemoMode:false"); CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(false); @@ -847,7 +851,7 @@ public class TaxiModel { private void updateAutopilotControlParameters() { AutopilotControlParameters parameters = initAutopilotControlParameters(); - if (null == parameters){ + if (null == parameters) { CallerLogger.INSTANCE.e(M_TAXI + TAG, "AutopilotControlParameters is empty."); return; } @@ -855,7 +859,7 @@ public class TaxiModel { CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(parameters); } - private void clearAutopilotControlParameters(){ + private void clearAutopilotControlParameters() { CallerLogger.INSTANCE.d(M_TAXI + TAG, "AutopilotControlParameters is clear."); CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(null); } @@ -891,12 +895,10 @@ public class TaxiModel { * 以当前订单为基础,开启自动驾驶 **/ @ChainLog( - linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_AUTOPILOT, - linkCode = CHAIN_LINK_ADAS, - endpoint = TracingConstants.Endpoint.PAD, - nodeAliasCode = CHAIN_ALIAS_CODE_OCH_TAXI_START_AUTOPILOT, - paramIndexes = {-1}, // - clientPkFileName = "sn" + linkChainLog = CHAIN_TYPE_SOCKET_AUTOPILOT, + linkCode = CHAIN_SOURCE_ADAS, + nodeAliasCode = CHAIN_CODE_OCH_TAXI_START_AUTOPILOT, + paramIndexes = {-1} ) public void startAutoPilot() { @@ -908,19 +910,19 @@ public class TaxiModel { //根据开关和后台是否发布轨迹启动自驾 if (FunctionBuildConfig.isPassStartAutopilotCommand && TextUtils.isEmpty(mCurrentOCHOrder.csvFileUrl) - && TextUtils.isEmpty(mCurrentOCHOrder.csvFileUrlDPQP)){ + && TextUtils.isEmpty(mCurrentOCHOrder.csvFileUrlDPQP)) { ToastUtils.showLong("无发布轨迹, 请发布后重试"); CallerLogger.INSTANCE.e(M_TAXI + TAG, "isPassStartAutopilotCommand = " + FunctionBuildConfig.isPassStartAutopilotCommand - + "busRoutesResult.csvFileUrl = "+ mCurrentOCHOrder.csvFileUrl - + "busRoutesResult.csvFileUrlDPQP = "+mCurrentOCHOrder.csvFileUrlDPQP); + + "busRoutesResult.csvFileUrl = " + mCurrentOCHOrder.csvFileUrl + + "busRoutesResult.csvFileUrlDPQP = " + mCurrentOCHOrder.csvFileUrlDPQP); return; } CallerLogger.INSTANCE.e(M_TAXI + TAG, "isPassStartAutopilotCommand = " + FunctionBuildConfig.isPassStartAutopilotCommand); - if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().getAutopilotAbilityStatus()){ + if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().getAutopilotAbilityStatus()) { ToastUtils.showLong(OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason() + ", 请稍候重试"); TaxiAnalyticsManager.getInstance().triggerUnableStartAPReasonEvent( @@ -929,17 +931,11 @@ public class TaxiModel { return; } - if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE - == CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) { - // TODO: 2021/11/28 工控机存在刚开始状态为0,但是可以开启变为2,工控机解决前不显示此toast -// ToastUtils.showShort("自动驾驶状态为不可用!"); - } - //点击开始自动驾驶按钮订单状态去流转, 不再与自动驾驶是否启动成功挂钩 - if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.UserArriveAtStart.getCode()){ + if (mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.UserArriveAtStart.getCode()) { startServicePilotDone(); isRestartAutopilot = false; - }else { + } else { isRestartAutopilot = true; } @@ -953,9 +949,9 @@ public class TaxiModel { CallerAutoPilotControlManager.INSTANCE.startAutoPilot(parameters); CallerLogger.INSTANCE.d(M_TAXI + TAG, "start autopilot with parameter: %s", GsonUtil.jsonFromObject(parameters) - + " ,startSiteName=" + mCurrentOCHOrder.startSiteAddr + + " ,startSiteName=" + mCurrentOCHOrder.startSiteAddr + " ,endSiteName=" + mCurrentOCHOrder.endSiteAddr - + "isRestartAutopilot = "+isRestartAutopilot); + + "isRestartAutopilot = " + isRestartAutopilot); TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestartAutopilot, false, mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.lineId, mCurrentOCHOrder.orderNo); @@ -1026,7 +1022,6 @@ public class TaxiModel { if (distance <= TaxiConst.ARRIVE_AT_START_STATION_DISTANCE) { arrivedStartPoint(); - return; } } @@ -1037,7 +1032,7 @@ public class TaxiModel { CallerLogger.INSTANCE.d(M_TAXI + TAG, "onIntentReceived = %s", intentStr); if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intentStr)) { if (NetworkUtils.isConnected(mContext)) { - startOrStopOrderLoop(LoginStatusManager.isLogin()&&TaxtServingStatusManager.isOpeningOrderStatus()); + startOrStopOrderLoop(LoginStatusManager.isLogin() && TaxtServingStatusManager.isOpeningOrderStatus()); loginService.queryLoginStatusByNet(); } } @@ -1048,8 +1043,8 @@ public class TaxiModel { @Override public void onStartAutopilotFailure(@NotNull String startFailedCode, @NonNull String startFailedMessage) { TaxiAnalyticsManager.getInstance().triggerStartAutopilotFailureEventByAdas(startFailedCode, startFailedMessage); - if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode){ - CallerLogger.INSTANCE.e(M_TAXI + TAG, "mAdasStartFailureListener = "+startFailedMessage); + if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode) { + CallerLogger.INSTANCE.e(M_TAXI + TAG, "mAdasStartFailureListener = " + startFailedMessage); mADASStatusCallback.onStartAdasFailure(); } } @@ -1068,7 +1063,7 @@ public class TaxiModel { }; // 自车定位 - private final IMoGoChassisLocationGCJ02Listener mMapLocationLIstener = new IMoGoChassisLocationGCJ02Listener() { + private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() { @Override public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { //位置变化时,通过围栏判断是否到达x点 @@ -1078,7 +1073,7 @@ public class TaxiModel { judgeStartStation(gnssInfo); } if (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd && - mPrevAPStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ + CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { judgeEndStation(gnssInfo); } } @@ -1092,27 +1087,47 @@ public class TaxiModel { } }; - private void judgeEndStation(MogoLocation location) { + private void judgeEndStation(MogoLocation currentLocation) { if (mCurrentOCHOrder == null || mCurrentOCHOrder.endSiteGcjPoint == null || mCurrentOCHOrder.endSiteGcjPoint.size() < 2) { return; } - double startLon = mCurrentOCHOrder.endSiteGcjPoint.get(0); - double startLat = mCurrentOCHOrder.endSiteGcjPoint.get(1); + double endLon = mCurrentOCHOrder.endSiteGcjPoint.get(0); + double endLat = mCurrentOCHOrder.endSiteGcjPoint.get(1); double distance = CoordinateUtils.calculateLineDistance( - startLon, startLat, - location.getLongitude(), location.getLatitude()); + endLon, endLat, + currentLocation.getLongitude(), currentLocation.getLatitude()); CallerLogger.INSTANCE.i(M_TAXI + TAG, "judgeEndStation() distance = " + distance); - if (distance <= TaxiConst.ARRIVE_AT_START_STATION_DISTANCE) { + if (distance <= TaxiConst.ARRIVE_AT_START_STATION_DISTANCE) { //1、当前位置和站点围栏15m内 + if (!checkCurrentOCHOrder() || (getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) { CallerLogger.INSTANCE.i(M_TAXI + TAG, "order exception or order ArriveAtEnd"); return; } - arriveTerminal(); - return; + + //2、开始计算当前位置和站点的向量角度 < 90度 未经过 >90度 经过 + double stationAngle = DrivingDirectionUtils.getDegreeOfCar2Poi( + currentLocation.getLongitude(), + currentLocation.getLatitude(), + endLon, + endLat, + (int) currentLocation.getHeading()); + + CallerLogger.INSTANCE.i(M_TAXI + TAG, "judgeEndStation() stationAngle = " + stationAngle); + + //3、刚过站且过站距离在15m内, 提交到站 + if (stationAngle > 90 && distance <= TaxiConst.ARRIVE_AT_START_STATION_DISTANCE){ + if (!checkCurrentOCHOrder() + || (getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) { + CallerLogger.INSTANCE.i(M_TAXI + TAG, "order exception or order ArriveAtEnd"); + return; + } + CallerLogger.INSTANCE.i(M_TAXI + TAG, "judgeEndStation() = 刚过站且在15m内"); + arriveTerminal(); + } } } @@ -1161,8 +1176,11 @@ public class TaxiModel { private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener() { @Override - public void onAutopilotRouteLineId(long lineId) { + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + } + @Override + public void onAutopilotRouteLineId(long lineId) { } @Override @@ -1176,26 +1194,24 @@ public class TaxiModel { @Override public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { - int state = autopilotStatusInfo.getState(); + } + + @Override + public void onAutopilotStatusResponse(int state) { if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { - if (state != mPrevAPStatus && mADASStatusCallback != null){ + if (mADASStatusCallback != null) { mADASStatusCallback.onAutopilotRunning(); } if (mCurrentOCHOrder != null - && TaxiOrderStatusEnum.OnTheWayToEnd.getCode() == mCurrentOCHOrder.orderStatus){ - if (state != mPrevAPStatus) { - // 当高频返回autopilot 2时,不重复调用订单状态变更 - mPrevAPStatus = state; // 每个状态单独赋值,解决无订单时已经是2的状态导致的新订单来时无法进入此逻辑更新状态 - - TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestartAutopilot, true, - mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.lineId, mCurrentOCHOrder.orderNo); - if (FunctionBuildConfig.isDemoMode) { - // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true - FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; - CallerAutoPilotControlManager.INSTANCE.setIgnoreConditionDraw(true); - CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(true); - CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(到达出发点且已开启自动驾驶)"); - } + && TaxiOrderStatusEnum.OnTheWayToEnd.getCode() == mCurrentOCHOrder.orderStatus) { + TaxiAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestartAutopilot, true, + mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.lineId, mCurrentOCHOrder.orderNo); + if (FunctionBuildConfig.isDemoMode) { + // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotControlManager.INSTANCE.setIgnoreConditionDraw(true); + CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(true); + CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(到达出发点且已开启自动驾驶)"); } } } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { @@ -1206,10 +1222,9 @@ public class TaxiModel { // 当美化模式(演示模式)开启时:且有订单、且为去往目的地状态,维持自动驾驶icon开启状态 return; } - if (mADASStatusCallback != null){ + if (mADASStatusCallback != null) { mADASStatusCallback.onAutopilotEnable(); } - mPrevAPStatus = state; } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { if (FunctionBuildConfig.isDemoMode && checkCurrentOCHOrder() @@ -1218,34 +1233,30 @@ public class TaxiModel { // 当美化模式(演示模式)开启时:且有订单、且为去往目的地状态,维持自动驾驶icon开启状态 return; } - if (mADASStatusCallback != null){ + if (mADASStatusCallback != null) { mADASStatusCallback.onAutopilotDisable(); } - mPrevAPStatus = state; - - }else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){ - if (FunctionBuildConfig.isDemoMode){ + } else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) { + if (FunctionBuildConfig.isDemoMode) { if (checkCurrentOCHOrder() && (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd - || getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)){//订单中 + || getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) {//订单中 // 当美化模式(演示模式)开启时:且有订单、且为去往目的地状态,维持自动驾驶icon开启状态 - }else { //美化模式下没订单,显示人工驾驶 - if (mADASStatusCallback != null){ + } else { //美化模式下没订单,显示人工驾驶 + if (mADASStatusCallback != null) { mADASStatusCallback.onAutopilotDisable(); } } return; } - if (mADASStatusCallback != null){ + if (mADASStatusCallback != null) { mADASStatusCallback.onManMachineCoDriving(); } - mPrevAPStatus = state; } } @Override public void onAutopilotSNRequest() { - } @Override @@ -1277,7 +1288,7 @@ public class TaxiModel { @Override public void onAutopilotRotting(MessagePad.GlobalPathResp routeList) { - if (null != routeList && routeList.getWayPointsList() != null){ + if (null != routeList && routeList.getWayPointsList() != null) { CallerLogger.INSTANCE.d(M_TAXI + TAG, "getWayPointsList = " + routeList.getWayPointsList().size()); } @@ -1291,13 +1302,26 @@ public class TaxiModel { /** * 设置路径规划起终点 - * @param latLngModels + * */ - public void setRouteLineMarker(List latLngModels) { -// List latLngModels = CoordinateCalculateRouteUtil -// .coordinateConverterWgsToGcjListCommon(mContext,models); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.setLineMarker(latLngModels); + public void setRouteLineMarker() { + OrderQueryRespBean.Result currentOCHOrder = getCurrentOCHOrder(); + if(currentOCHOrder!=null) { + if (currentOCHOrder.startSiteGcjPoint == null || currentOCHOrder.startSiteGcjPoint.isEmpty() || currentOCHOrder.startSiteGcjPoint.size() < 2|| + currentOCHOrder.endSiteGcjPoint == null || currentOCHOrder.endSiteGcjPoint.isEmpty() || currentOCHOrder.endSiteGcjPoint.size() < 2) { + cleanLineMarker(); + return; + } + LatLng startStation = new LatLng(currentOCHOrder.startSiteGcjPoint.get(1),currentOCHOrder.startSiteGcjPoint.get(0)); + LatLng endStation = new LatLng(currentOCHOrder.endSiteGcjPoint.get(1),currentOCHOrder.endSiteGcjPoint.get(0)); + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback.setLineMarker(startStation,endStation); + } + } + } + public void cleanLineMarker(){ + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback.setLineMarker(null,null); } } @@ -1351,7 +1375,7 @@ public class TaxiModel { CallerLogger.INSTANCE.d(M_TAXI + TAG, "--------计算出sumLength开始---------- "); //转换成高德坐标系 - if (mRoutePoints.size() > 0){ + if (mRoutePoints.size() > 0) { mRoutePoints.clear(); } mRoutePoints.addAll(CoordinateCalculateRouteUtil @@ -1367,14 +1391,14 @@ public class TaxiModel { } CallerLogger.INSTANCE.d(M_TAXI + TAG, "--------mRoutePoints.size---------- " + mRoutePoints.size()); - if (mRoutePoints.size() > 0){ + if (mRoutePoints.size() > 0) { reportTotalDisAndTime(); } //开启实时计算剩余距离,剩余时间,预计时间 startOrStopCalculateRouteInfo(true); AmapNaviToDestinationModel.getInstance(mContext).destroyAmaNavi(); - if (mOrderStatusCallback != null){ - mOrderStatusCallback.onNaviToEnd(false,false); + if (mOrderStatusCallback != null) { + mOrderStatusCallback.onNaviToEnd(false, false); } } @@ -1389,62 +1413,95 @@ public class TaxiModel { * 实时计算当前剩余里程和时间 */ public void dynamicCalculateRouteInfo() { - if (mLocation == null){ - return; +// if (mLocation == null) { +// return; +// } +// if (mRoutePoints.size() > 0 && mLocation != null) { +// Map> lastPointsMap = CoordinateCalculateRouteUtil +// .getRemainPointListByCompareNew(mPreRouteIndex, mRoutePoints, mLocation); +// +// for (int index : lastPointsMap.keySet()) { +// mPreRouteIndex = index; +// break; +// } +// for (List lastPoints : lastPointsMap.values()) { +// float lastSumLength = 0; +// if (lastPoints.size() == 1) { //只是最后一个点,计算当前位置和最后一个点的距离 +// lastSumLength = CoordinateUtils.calculateLineDistance( +// lastPoints.get(0).getLongitude(), lastPoints.get(0).getLatitude(), +// mLocation.getLongitude(), mLocation.getLatitude()); +// } else { +// lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(lastPoints); +// } +// updateDistance(lastSumLength); +// break; +// } +// routeAndWipe(); +// } + } + + private void updateDistance(float lastSumLength){ + double lastTime = lastSumLength / TaxiConst.TAXI_AVERAGE_SPEED * 3.6; //秒 + CallerLogger.INSTANCE.d(M_TAXI + "dynamicCalculateRouteInfo" + , "---lastSumLength: " + lastSumLength + "----lastTime : " + lastTime + + " thread = " + Thread.currentThread().getName()); + + if (mCurrentOCHOrder != null) { + mCurrentOCHOrder.decreaseTravelDistance(lastSumLength); } - if (mRoutePoints.size() > 0 && mLocation != null){ - Map> lastPointsMap = CoordinateCalculateRouteUtil - .getRemainPointListByCompareNew(mPreRouteIndex,mRoutePoints, mLocation); - - for (int index: lastPointsMap.keySet()) { - mPreRouteIndex = index; - break; - } - for (List lastPoints: lastPointsMap.values()){ - float lastSumLength = 0; - if (lastPoints.size() == 1) { //只是最后一个点,计算当前位置和最后一个点的距离 - lastSumLength = CoordinateUtils.calculateLineDistance( - lastPoints.get(0).getLongitude(), lastPoints.get(0).getLatitude(), - mLocation.getLongitude(), mLocation.getLatitude()); - } else { - lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(lastPoints); - } - - double lastTime = lastSumLength / TaxiConst.TAXI_AVERAGE_SPEED * 3.6; //秒 - CallerLogger.INSTANCE.d(M_TAXI + "dynamicCalculateRouteInfo" - , "---lastSumLength: " + lastSumLength + "----lastTime : " + lastTime - + " thread = "+ Thread.currentThread().getName()); - - if (mCurrentOCHOrder != null){ - mCurrentOCHOrder.decreaseTravelDistance(lastSumLength); - } - if (mOrderStatusCallback != null) { - mOrderStatusCallback.onCurrentOrderDistToEndChanged((long) lastSumLength, (long) lastTime); - } - - reportOrderRemain((long) lastSumLength, (long) lastTime); - break; - } - routeAndWipe(); + if (mOrderStatusCallback != null) { + mOrderStatusCallback.onCurrentOrderDistToEndChanged((long) lastSumLength, (long) lastTime); } + + reportOrderRemain((long) lastSumLength, (long) lastTime); } private void routeAndWipe() { - if (mRoutePoints != null && mRoutePoints.size() > 0 && mLocation != null){ + if (mRoutePoints != null && mRoutePoints.size() > 0 && mLocation != null) { int haveArrivedIndex = CoordinateCalculateRouteUtil .getArrivedPointIndexNew(mPreRouteIndex, mRoutePoints, mLocation.getLongitude(), mLocation.getLatitude()); List routePoints = CoordinateCalculateRouteUtil - .coordinateConverterLocationToLatLng(mContext,mRoutePoints); - if (mAutopilotPlanningCallback != null){ - mAutopilotPlanningCallback.routeResult(routePoints,haveArrivedIndex); + .coordinateConverterLocationToLatLng(mContext, mRoutePoints); + List routeArrivied = new ArrayList<>(); + List routeArriving = new ArrayList<>(); + for (int i = 0; i < routePoints.size(); i++){ + if (i <= haveArrivedIndex){ + routeArrivied.add(routePoints.get(i)); + }else { + routeArriving.add(routePoints.get(i)); + } } - setRouteLineMarker(routePoints); + if (mAutopilotPlanningCallback != null) { + mAutopilotPlanningCallback.routeResult(routeArrivied,routeArriving, mLocation); + } + setRouteLineMarker(); } } + private final IDistanceListener distanceListener = this::updateDistance; + + private final ITrajectoryListener trajectoryListener = (routeArrivied, routeArriving, location) -> { + if (mAutopilotPlanningCallback != null) { + List routeArriviedTemp = new ArrayList<>(); + List routeArrivingTemp = new ArrayList<>(); + LatLng temp; + for (MogoLocation mogoLocation : routeArrivied) { + temp = new LatLng(mogoLocation.getLatitude(),mogoLocation.getLongitude()); + routeArriviedTemp.add(temp); + } + for (MogoLocation mogoLocation : routeArriving) { + temp = new LatLng(mogoLocation.getLatitude(),mogoLocation.getLongitude()); + routeArrivingTemp.add(temp); + } + mAutopilotPlanningCallback.routeResult(routeArriviedTemp, routeArrivingTemp,location); + setRouteLineMarker(); + } + }; + + /** * 查询当前订单的全局路径 (当自动驾驶开启后,订单前往乘客上车点,杀掉应用再次进来时候) */ @@ -1540,7 +1597,7 @@ public class TaxiModel { }); } - public void startServicePilotDone(){ + public void startServicePilotDone() { if (mCurrentOCHOrder == null) return; TaxiOrPassengerReadyReqBean.Result result = new TaxiOrPassengerReadyReqBean.Result(); @@ -1561,7 +1618,7 @@ public class TaxiModel { }); } - public void arrivedStartPoint(){ + public void arrivedStartPoint() { if (mCurrentOCHOrder == null) return; TaxiOrPassengerReadyReqBean.Result result = new TaxiOrPassengerReadyReqBean.Result(); result.lat = mLatitude; @@ -1582,7 +1639,7 @@ public class TaxiModel { }); } - public void arriveTerminal(){ + public void arriveTerminal() { if (mCurrentOCHOrder == null) return; TaxiOrPassengerReadyReqBean.Result result = new TaxiOrPassengerReadyReqBean.Result(); result.lat = mLatitude; @@ -1603,7 +1660,7 @@ public class TaxiModel { }); } - public void orderCompleted(){ + public void orderCompleted() { if (mCurrentOCHOrder == null) return; TaxiOrPassengerReadyReqBean.Result result = new TaxiOrPassengerReadyReqBean.Result(); result.lat = mLatitude; @@ -1625,30 +1682,47 @@ public class TaxiModel { // 登出 public void logout() { - loginService.loginOut(mLatitude,mLongitude); + loginService.loginOut(mLatitude, mLongitude); } //导航去订单终点目的地 - public void startNaviToEndStation(boolean isShow){ - if (mRoutePoints.size() > 0 ){ //使用自驾轨迹 - if (mOrderStatusCallback != null){ - mOrderStatusCallback.onNaviToEnd(false,isShow); + public void startNaviToEndStation(boolean isShow) { + if (mRoutePoints.size() > 0) { //使用自驾轨迹 + if (mOrderStatusCallback != null) { + mOrderStatusCallback.onNaviToEnd(false, isShow); } - }else {//若直接要显示导航地图则直接导航, 若不是则2s后若无轨迹数据使用高德导航 - if (isShow && mRoutePoints.size() == 0 && mOrderStatusCallback != null){ + } else {//若直接要显示导航地图则直接导航, 若不是则2s后若无轨迹数据使用高德导航 + if (isShow && mRoutePoints.size() == 0 && mOrderStatusCallback != null) { - mOrderStatusCallback.onNaviToEnd(true,true); - }else { + mOrderStatusCallback.onNaviToEnd(true, true); + } else { UiThreadHandler.postDelayed(new Runnable() { @Override public void run() { - if (mRoutePoints.size() == 0 && mOrderStatusCallback != null){ - mOrderStatusCallback.onNaviToEnd(true,false); + if (mRoutePoints.size() == 0 && mOrderStatusCallback != null) { + mOrderStatusCallback.onNaviToEnd(true, false); } } - },2000l); + }, 2000l); } } } + + public void setStation(){ + OrderQueryRespBean.Result currentOCHOrder = getCurrentOCHOrder(); + if(currentOCHOrder!=null){ + MogoLocation startStation = new MogoLocation(); + startStation.setLongitude(currentOCHOrder.startSiteGcjPoint.get(0)); + startStation.setLatitude(currentOCHOrder.startSiteGcjPoint.get(1)); + MogoLocation endStation = new MogoLocation(); + endStation.setLongitude(currentOCHOrder.endSiteGcjPoint.get(0)); + endStation.setLatitude(currentOCHOrder.endSiteGcjPoint.get(1)); + TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation,endStation,currentOCHOrder.lineId); + } + } + + public void cleanStation(){ + TrajectoryAndDistanceManager.INSTANCE.setStationPoint(null,null,-1L); + } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/NaviPresenter.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/NaviPresenter.java index 1c98be1ad8..112ed99f50 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/NaviPresenter.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/NaviPresenter.java @@ -10,6 +10,7 @@ import androidx.lifecycle.LifecycleOwner; import com.amap.api.maps.model.LatLng; import com.mogo.commons.AbsMogoApplication; import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.map.MogoLocation; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.taxi.callback.IOCHTaxiAutopilotPlanningCallback; @@ -65,12 +66,12 @@ public class NaviPresenter extends Presenter implements } @Override - public void setLineMarker(List models) { - runOnUIThread(() -> mView.setLineMarker(models)); + public void setLineMarker(LatLng startStation, LatLng endStation) { + runOnUIThread(() -> mView.setLineMarker(startStation,endStation)); } @Override - public void routeResult(List models, int haveArrivedIndex) { - mView.routeResult(models,haveArrivedIndex); + public void routeResult(List routeArrivied, List routeArriving, MogoLocation location) { + mView.routeResult(routeArrivied,routeArriving,location); } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java index 72c76408eb..d53d3e16f3 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java @@ -240,10 +240,12 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS CallerLogger.INSTANCE.d(M_TAXI + TAG,"order = "+order.toString()); if (TaxiOrderStatusEnum.UserArriveAtStart.getCode() == order.orderStatus){ TaxiModel.getInstance().queryAutopilotStatus(true); + TaxiModel.getInstance().setStation(); } if (TaxiOrderStatusEnum.OnTheWayToEnd.getCode() == order.orderStatus){ TaxiModel.getInstance().startDynamicCalculateRouteInfo(); + TaxiModel.getInstance().setStation(); runOnUIThread(() -> { mView.updateCtvAutopilotStatusTag(true); CallerOrderListenerManager.INSTANCE.invokeOrderStatus(true); @@ -255,7 +257,8 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiOrderStatusEnum.Cancel.getCode() == order.orderStatus || TaxiOrderStatusEnum.JourneyCompleted.getCode() == order.orderStatus){ TaxiModel.getInstance().startOrStopCalculateRouteInfo(false); - TaxiModel.getInstance().setRouteLineMarker(null); + TaxiModel.getInstance().cleanLineMarker(); + TaxiModel.getInstance().cleanStation(); runOnUIThread(() -> { if(TaxiOrderStatusEnum.ArriveAtEnd.getCode() == order.orderStatus){ CallerOrderListenerManager.INSTANCE.invokeOrderStatus(false); @@ -329,7 +332,6 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS if (null != location){ runOnUIThread(() -> { mView.updateSpeedView((float) location.getGnssSpeed()); - mView.updateLocation(location.getLatitude(),location.getLongitude()); }); } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java index 2bd1fc7c0d..8b928582cb 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java @@ -228,7 +228,7 @@ public abstract class BaseTaxiTabFragment @@ -363,9 +363,6 @@ public abstract class BaseTaxiTabFragment grabOrderFragmentWR; + private WeakReference serverOrdersFragmentWR; private WeakReference personalDialogFragment = null; - protected double mCurLatitude = 0.0; - protected double mCurLongitude = 0.0; private LoginService loginService; @Override @@ -120,32 +118,34 @@ public class TaxiFragment extends BaseTaxiTabFragment(TaxiServerOrdersFragment.newInstance()); + grabOrderFragmentWR = new WeakReference<>(TaxiGrabOrderFragment.newInstance()); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); //默认显示OCHTaxiServerOrdersFragment - transaction.add(R.id.fragment_container, serverOrdersFragment).show(serverOrdersFragment); - transaction.add(R.id.fragment_container, grabOrderFragment).hide(grabOrderFragment); + transaction.add(R.id.fragment_container, serverOrdersFragmentWR.get()).show(serverOrdersFragmentWR.get()); + transaction.add(R.id.fragment_container, grabOrderFragmentWR.get()).hide(grabOrderFragmentWR.get()); transaction.commitAllowingStateLoss(); } private void showGrabFragmentAndUpdate() { FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - if (grabOrderFragment == null) { - grabOrderFragment = TaxiGrabOrderFragment.newInstance(); - transaction.add(R.id.fragment_container, grabOrderFragment).show(grabOrderFragment).commitAllowingStateLoss(); + if (grabOrderFragmentWR == null || grabOrderFragmentWR.get() == null) { + grabOrderFragmentWR = new WeakReference<>(TaxiGrabOrderFragment.newInstance()); + transaction.add(R.id.fragment_container, grabOrderFragmentWR.get()) + .show(grabOrderFragmentWR.get()).commitAllowingStateLoss(); } else { - transaction.show(grabOrderFragment).hide(serverOrdersFragment).commitAllowingStateLoss(); + transaction.show(grabOrderFragmentWR.get()).hide(serverOrdersFragmentWR.get()).commitAllowingStateLoss(); } } public void showServerFragmentAndUpdate() { FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - if (serverOrdersFragment == null) { - serverOrdersFragment = TaxiServerOrdersFragment.newInstance(); - transaction.add(R.id.fragment_container, serverOrdersFragment).show(serverOrdersFragment); + if (serverOrdersFragmentWR == null || serverOrdersFragmentWR.get() == null) { + serverOrdersFragmentWR = new WeakReference<>(TaxiServerOrdersFragment.newInstance()); + transaction.add(R.id.fragment_container, serverOrdersFragmentWR.get()) + .show(serverOrdersFragmentWR.get()); } else { - transaction.show(serverOrdersFragment).hide(grabOrderFragment).commitAllowingStateLoss(); + transaction.show(serverOrdersFragmentWR.get()).hide(grabOrderFragmentWR.get()).commitAllowingStateLoss(); } } @@ -210,8 +210,8 @@ public class TaxiFragment extends BaseTaxiTabFragment waitServiceList) { if (null == waitServiceList) return; - if (null == serverOrdersFragment) return; - serverOrdersFragment.onOrdersWaitServiceChanged(waitServiceList); + if (null == serverOrdersFragmentWR || serverOrdersFragmentWR.get() == null) return; + serverOrdersFragmentWR.get().onOrdersWaitServiceChanged(waitServiceList); } public void queryCurOrderRouteInfo() { @@ -333,18 +333,13 @@ public class TaxiFragment extends BaseTaxiTabFragment mCoordinatesLatLng = new ArrayList<>(); - private Polyline mPolyline; - private CameraUpdate mCameraUpdate; - private Context mContext; - private int mHaveArrivedIndex; - - List textureList = new ArrayList<>(); - List texIndexList = new ArrayList<>(); - - private BitmapDescriptor mArrivedRes; - private BitmapDescriptor mUnArrivedRes; - - public TaxiMapDirectionView(Context context) { - this(context, null); - } - - public TaxiMapDirectionView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public TaxiMapDirectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - try { - initView(context); - } catch (Exception e) { - e.printStackTrace(); - } - } - - - private void initView(Context context) { - CallerLogger.INSTANCE.d(M_TAXI + TAG, "initView"); - - mContext = context; - - View smpView = LayoutInflater.from(context).inflate(R.layout.taxi_map_view, this); - - mAMapNaviView = (TextureMapView) smpView.findViewById(R.id.taxi_amap_view); - - initAMapView(); - - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, this); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // 注册定位监听 - CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); - } - - private void initAMapView() { - mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel); - mAMap = mAMapNaviView.getMap(); - // 设置导航地图模式,aMap是地图控制器对象。 - mAMap.setMapType(AMap.MAP_TYPE_NIGHT); - - // 关闭显示实时路况图层,aMap是地图控制器对象。 - mAMap.setTrafficEnabled(false); - - // 设置 锚点 图标 - mCarMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_car)) - .anchor(0.5f, 0.5f)); - mStartMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_view_dir_start))); - mEndMarker = mAMap.addMarker(new MarkerOptions() - .icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_view_dir_end))); - mStartMarker.setVisible(false); - mEndMarker.setVisible(false); - - mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_arrived); - mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_un_arrive); - - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(TaxiMapAssetStyleUtil.getAssetsStyle(getContext(),"map_style.data")) - .setStyleExtraData(TaxiMapAssetStyleUtil.getAssetsExtraStyle(getContext(),"map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - - //设置希望展示的地图缩放级别 - mAMap.moveCamera(mCameraUpdate); - - // 设置地图的样式 - UiSettings uiSettings = mAMap.getUiSettings(); - uiSettings.setZoomControlsEnabled(false);// 地图缩放级别的交换按钮 - uiSettings.setAllGesturesEnabled(false);// 所有手势 - uiSettings.setMyLocationButtonEnabled(false); // 显示默认的定位按钮 - uiSettings.setLogoBottomMargin(-150); //设置Logo下边界距离屏幕底部的边距,设置为负值即可 - - mAMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() { - @Override - public void onMapLoaded() { - CallerLogger.INSTANCE.d(M_TAXI + TAG, "smp---onMapLoaded"); - // 加载自定义样式 - CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() - .setEnable(true) - .setStyleData(TaxiMapAssetStyleUtil.getAssetsStyle(getContext(),"map_style.data")) - .setStyleExtraData(TaxiMapAssetStyleUtil.getAssetsExtraStyle(getContext(),"map_style_extra.data")); - // 设置自定义样式 - mAMap.setCustomMapStyle(customMapStyleOptions); - mAMapNaviView.getMap().setPointToCenter(mAMapNaviView.getWidth() / 2, mAMapNaviView.getHeight() / 2); - } - }); - - //设置地图状态的监听接口 - mAMap.setOnCameraChangeListener(this); - } - - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return true; - } - - @Override - public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { - if (gnssInfo == null){ - return; - } - try { - LatLng currentLatLng = new LatLng(gnssInfo.getLatitude(), gnssInfo.getLongitude()); - if (mCoordinatesLatLng.size() > 1) { - //圈定地图显示范围 - LatLng endLatLng = mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1); - //存放经纬度 - LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); - boundsBuilder.include(currentLatLng); - boundsBuilder.include(endLatLng); - //第二个参数为四周留空宽度 - mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100,100,100,100)); -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "onCarLocationChanged2--moveCamera :" + location.getLatitude()+", "+location.getLongitude()); - - } else { - //设置希望展示的地图缩放级别 - CameraPosition cameraPosition = new CameraPosition.Builder() - .target(mCarMarker.getPosition()).tilt(0).bearing((float) gnssInfo.getHeading()).zoom(zoomLevel).build(); - mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); - } - //更新车辆位置 - if (mCarMarker != null) { -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "location.getBearing() = " + location.getBearing()); - mCarMarker.setRotateAngle((float) (360 - gnssInfo.getHeading())); - mCarMarker.setPosition(currentLatLng); -// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "onCarLocationChanged2--loacation :" + location.getLatitude()+", "+location.getLongitude()); - mCarMarker.setToTop(); - } - }catch (Exception e){ - - } - } - - @Override - public void setLineMarker() { -// if (mStartMarker != null) { -// mStartMarker.setVisible(false); -// } -// if (mEndMarker != null) { -// mEndMarker.setVisible(false); -// } - if (mStartMarker != null && mEndMarker != null - && mStartMarker.isVisible() && mEndMarker.isVisible()) { - return; - } - - if (mCoordinatesLatLng.size() > 2) { - // 设置开始结束Marker位置 - LatLng startLatLng = mCoordinatesLatLng.get(0); - LatLng endLatLng = mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1); - if (mStartMarker != null) { - mStartMarker.setPosition(startLatLng); - mStartMarker.setVisible(true); - } - if (mEndMarker != null) { - mEndMarker.setPosition(endLatLng); - mEndMarker.setVisible(true); - } - } - } - - @Override - public void drawablePolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - if (mAMap != null) { - - addRouteColorList(); - - if (mCoordinatesLatLng.size() > 2) { - //设置线段纹理 - PolylineOptions polylineOptions = new PolylineOptions(); - polylineOptions.addAll(mCoordinatesLatLng); - polylineOptions.setUseTexture(true); - polylineOptions.width(15); - polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound); - polylineOptions.setCustomTextureList(textureList); - polylineOptions.setCustomTextureIndex(texIndexList); - - // 绘制线 - mPolyline = mAMap.addPolyline(polylineOptions); - - } - } - } - - /** - * 添加画线颜色值 - */ - private void addRouteColorList() { - textureList.clear(); - texIndexList.clear(); - for (int i = 0; i < mCoordinatesLatLng.size(); i++){ - if (i <= mHaveArrivedIndex){ - textureList.add(mArrivedRes); - }else { - textureList.add(mUnArrivedRes); - } - texIndexList.add(i); - } - } - - - public LatLng CoordinateConverterFrom84(Context mContext, MogoLatLng mogoLatLng) { - CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); - mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); - mCoordinateConverter.coord(new LatLng(mogoLatLng.lat, mogoLatLng.lon)); - LatLng latLng = mCoordinateConverter.convert(); - return latLng; - } - - public List CoordinateConverterFrom84ForList(Context mContext, List mogoLatLngList) { - List list = new ArrayList<>(); - for (MogoLatLng m : mogoLatLngList) { - LatLng mogoLatLng = CoordinateConverterFrom84(mContext, m); - list.add(mogoLatLng); - } - return list; - } - - @Override - public void clearPolyline() { - if (mPolyline != null) { - mPolyline.remove(); - } - if (mStartMarker != null) { - mStartMarker.setVisible(false); - } - if (mEndMarker != null) { - mEndMarker.setVisible(false); - } - } - - public void resetPolyLine() { - mCoordinatesLatLng.clear(); - if (mPolyline != null) { - mPolyline.remove(); - } - if (mStartMarker != null) { - mStartMarker.setVisible(false); - } - if (mEndMarker != null) { - mEndMarker.setVisible(false); - } - } - - public void onCreateView(Bundle savedInstanceState) { - if (mAMapNaviView != null) { - mAMapNaviView.onCreate(savedInstanceState); - } - } - - public void onResume() { - if (mAMapNaviView != null) { - mAMapNaviView.onResume(); - } - } - - public void onPause() { - if (mAMapNaviView != null) { - mAMapNaviView.onPause(); - } - } - - public void onDestroy() { - if (mAMapNaviView != null) { - mAMapNaviView.onDestroy(); - } - } - - public void convert(List coordinates) { - mCoordinatesLatLng.clear(); - List latLngs = CoordinateConverterFrom84ForList(mContext, coordinates); - mCoordinatesLatLng.addAll(latLngs); - } - - public void setCoordinatesLatLng(List latLngs){ - mCoordinatesLatLng.clear(); - mCoordinatesLatLng.addAll(latLngs); - } - - public void setCoordinatesLatLng(List latLngs, int haveArrivedIndex){ - mCoordinatesLatLng.clear(); - mCoordinatesLatLng.addAll(latLngs); - mHaveArrivedIndex = haveArrivedIndex; - } - - @Override - public void onCameraChange(CameraPosition cameraPosition) { - - } - - @Override - public void onCameraChangeFinish(CameraPosition cameraPosition) { - - } -} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiMapDirectionView.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiMapDirectionView.kt new file mode 100644 index 0000000000..5718ed6a16 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiMapDirectionView.kt @@ -0,0 +1,289 @@ +package com.mogo.och.taxi.ui + +import android.content.Context +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.MotionEvent +import android.widget.RelativeLayout +import com.amap.api.maps.AMap +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.TextureMapView +import com.amap.api.maps.model.BitmapDescriptor +import com.amap.api.maps.model.BitmapDescriptorFactory +import com.amap.api.maps.model.CameraPosition +import com.amap.api.maps.model.CustomMapStyleOptions +import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker +import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.model.Polyline +import com.amap.api.maps.model.PolylineOptions +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.taxi.R +import com.mogo.och.taxi.utils.TaxiMapAssetStyleUtil + +/** + * taxi司机端前往目的地小地图导航 + */ +class TaxiMapDirectionView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener, + ITaxiMapDirectionView, AMap.OnCameraChangeListener { + private lateinit var mAMapNaviView: TextureMapView + private lateinit var mAMap: AMap + private var mCarMarker: Marker? = null + private lateinit var mStartMarker: Marker + private lateinit var mEndMarker: Marker + private val zoomLevel = 13 + private val routeArrivied: MutableList = ArrayList() + private val routeArriving: MutableList = ArrayList() + private var location: MogoLocation? = null + private var startStation: LatLng? = null + private var endStation: LatLng? = null + private var mPolyline: Polyline? = null + var textureList: MutableList = ArrayList() + var texIndexList: MutableList = ArrayList() + private var mArrivedRes: BitmapDescriptor? = null + private var mUnArrivedRes: BitmapDescriptor? = null + + init { + try { + initView(context) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun initView(context: Context) { + d(SceneConstant.M_TAXI + TAG, "initView") + val smpView = LayoutInflater.from(context).inflate(R.layout.taxi_map_view, this) + mAMapNaviView = smpView.findViewById(R.id.taxi_amap_view) + initAMapView() + + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 10, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + } + + private fun initAMapView() { + val mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel.toFloat()) + mAMap = mAMapNaviView.map + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap.mapType = AMap.MAP_TYPE_NIGHT + + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap.isTrafficEnabled = false + + // 设置 锚点 图标 + mCarMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_car)).anchor(0.5f, 0.5f)) + mStartMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_view_dir_start))) + mEndMarker = mAMap.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_view_dir_end))) + mStartMarker.isVisible = false + mEndMarker.isVisible = false + mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_arrived) + mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_un_arrive) + + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(TaxiMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData( + TaxiMapAssetStyleUtil.getAssetsExtraStyle( + context, + "map_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions) + + //设置希望展示的地图缩放级别 + mAMap.moveCamera(mCameraUpdate) + + // 设置地图的样式 + mAMap.uiSettings.apply { + isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + setAllGesturesEnabled(false) // 所有手势 + isMyLocationButtonEnabled = false // 显示默认的定位按钮 + setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + } + mAMap.setOnMapLoadedListener(AMap.OnMapLoadedListener { + d(SceneConstant.M_TAXI + TAG, "smp---onMapLoaded") + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(TaxiMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData( + TaxiMapAssetStyleUtil.getAssetsExtraStyle( + context, + "map_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions) + mAMapNaviView.map.setPointToCenter( + mAMapNaviView.width / 2, + mAMapNaviView.height / 2 + ) + }) + + //设置地图状态的监听接口 + mAMap.setOnCameraChangeListener(this) + } + + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + return true + } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (mogoLocation == null) { + return + } + try { + val currentLatLng = LatLng(mogoLocation.latitude, mogoLocation.longitude) + if (mPolyline != null && mPolyline!!.points.size > 1) { + val points = mPolyline!!.points + //圈定地图显示范围 + val endLatLng = points[points.size - 1] + //存放经纬度 + val boundsBuilder = LatLngBounds.Builder() + boundsBuilder.include(currentLatLng) + boundsBuilder.include(endLatLng) + //第二个参数为四周留空宽度 + mAMap.moveCamera( + CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100, 100, 100, 100) + ) + } else { + //设置希望展示的地图缩放级别 + val cameraPosition = CameraPosition.Builder() + .target(mCarMarker!!.position).tilt(0f).bearing(mogoLocation.heading.toFloat()) + .zoom(zoomLevel.toFloat()).build() + mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) + } + //更新车辆位置 + if (mCarMarker != null) { + mCarMarker!!.rotateAngle = (360 - mogoLocation.heading).toFloat() + mCarMarker!!.position = currentLatLng + mCarMarker!!.setToTop() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + override fun setLineMarker() { + if (mStartMarker.isVisible && mEndMarker.isVisible + ) { + return + } + if (startStation != null && endStation != null) { + // 设置开始结束Marker位置 + mStartMarker.position = startStation + mStartMarker.isVisible = true + mEndMarker.position = endStation + mEndMarker.isVisible = true + } + } + + override fun drawablePolyline() { + if (routeArrivied.isEmpty() && routeArriving.isEmpty()) { + d(SceneConstant.M_TAXI + TAG, "没有点") + return + } + texIndexList.clear() + val allPoints = ArrayList(routeArrivied) + for (i in routeArrivied.indices) { + if (routeArrivied.size > 1 && i < routeArrivied.size - 1) { + texIndexList.add(0) + } + } + texIndexList.add(0) + allPoints.add(LatLng(location!!.latitude, location!!.longitude)) + allPoints.addAll(routeArriving) + for (ignored in routeArrivied) { + texIndexList.add(1) + } + if (mPolyline != null) { + mPolyline!!.points = allPoints + mPolyline!!.options.customTextureIndex = texIndexList + return + } + if(textureList.isEmpty()) { + textureList.add(mArrivedRes) + textureList.add(mUnArrivedRes) + } + //设置线段纹理 + val polylineOptions = PolylineOptions().apply { + addAll(allPoints) + isUseTexture = true + width(15f) + lineCapType(PolylineOptions.LineCapType.LineCapRound) + customTextureList = textureList + customTextureIndex = texIndexList + } + + // 绘制线 + mPolyline = mAMap.addPolyline(polylineOptions) + } + + override fun clearPolyline() { + if (mPolyline != null) { + mPolyline!!.remove() + mPolyline = null + } + mStartMarker.isVisible = false + mEndMarker.isVisible = false + } + + fun onCreateView(savedInstanceState: Bundle?) { + mAMapNaviView.onCreate(savedInstanceState) + } + + fun onResume() { + mAMapNaviView.onResume() + } + + fun onPause() { + mAMapNaviView.onPause() + } + + fun onDestroy() { + mAMapNaviView.onDestroy() + } + + fun setStartMarkAndEndMark(startStation: LatLng?, endStation: LatLng?) { + this.startStation = startStation + this.endStation = endStation + } + + fun setCoordinatesLatLng( + routeArrivied: List?, + routeArriving: List?, + location: MogoLocation? + ) { + this.routeArrivied.clear() + this.routeArrivied.addAll(routeArrivied!!) + this.routeArriving.clear() + this.routeArriving.addAll(routeArriving!!) + this.location = location + } + + override fun onCameraChange(cameraPosition: CameraPosition) {} + override fun onCameraChangeFinish(cameraPosition: CameraPosition) {} + + companion object { + //小地图名称 + const val TAG = "TaxiMapDirectionView" + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiRottingNaviFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiRottingNaviFragment.java index d237e395cd..003c211eaa 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiRottingNaviFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiRottingNaviFragment.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import com.amap.api.maps.model.LatLng; import com.mogo.commons.mvp.MvpFragment; +import com.mogo.eagle.core.data.map.MogoLocation; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.och.taxi.R; import com.mogo.och.taxi.presenter.NaviPresenter; @@ -79,49 +80,34 @@ public class TaxiRottingNaviFragment extends MvpFragment latLngList, int haveArrivedIndex){ - if (latLngList.size() > 0) { - drawablePolylineByRoute(latLngList,haveArrivedIndex); + public void routeResult(List routeArrivied, List routeArriving, MogoLocation location){ + if ((routeArrivied.size()+routeArriving.size()) > 0) { + drawablePolylineByRoute(routeArrivied,routeArriving,location); } else { clearPolyline(); } } - public void setLineMarker(List latLngList){ - if (null != latLngList && latLngList.size() > 0) { + public void setLineMarker(LatLng startStation, LatLng endStation){ + if (startStation!=null&&endStation!=null) { if (mMapDirectionView != null) { - mMapDirectionView.setCoordinatesLatLng(latLngList); - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapDirectionView.setLineMarker(); - } - }); + mMapDirectionView.setStartMarkAndEndMark(startStation,endStation); + UiThreadHandler.post(() -> mMapDirectionView.setLineMarker()); } } else { clearPolyline(); } } - public void drawablePolylineByRoute(List mCoordinatesLatLng,int haveArrivedIndex){ + public void drawablePolylineByRoute(List routeArrivied, List routeArriving, MogoLocation location){ if (mMapDirectionView != null){ - mMapDirectionView.setCoordinatesLatLng(mCoordinatesLatLng,haveArrivedIndex); - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapDirectionView.drawablePolyline(); - } - }); + mMapDirectionView.setCoordinatesLatLng(routeArrivied,routeArriving,location); + UiThreadHandler.post(() -> mMapDirectionView.drawablePolyline()); } } private void clearPolyline() { if (mMapDirectionView != null) { - UiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMapDirectionView.clearPolyline(); - } - }); + UiThreadHandler.post(() -> mMapDirectionView.clearPolyline()); } } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java index c0e75d16ad..c43e4617c6 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/TaxiAnalyticsManager.java @@ -56,14 +56,14 @@ public class TaxiAnalyticsManager { if (mStartAutopilotParams.isEmpty()) return; CallerLogger.INSTANCE.e(M_TAXI + "triggerStartAutopilotFailureEvent", failMsg); - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + if (CallerAutoPilotStatusListenerManager.INSTANCE.getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ mStartAutopilotParams.put(TaxiConst.EVENT_PARAM_START_FAILURE_CODE, failCode); mStartAutopilotParams.put(TaxiConst.EVENT_PARAM_START_FAILURE_MSG, failMsg); } mStartAutopilotParams.put(TaxiConst.EVENT_PARAM_START_RESULT, - CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + CallerAutoPilotStatusListenerManager.INSTANCE.getState() == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); diff --git a/OCH/mogo-och-sweeper/.gitignore b/OCH/sweeper/sweeper-cloud/.gitignore similarity index 100% rename from OCH/mogo-och-sweeper/.gitignore rename to OCH/sweeper/sweeper-cloud/.gitignore diff --git a/OCH/sweeper/sweeper-cloud/AutopilotModeConfig.json b/OCH/sweeper/sweeper-cloud/AutopilotModeConfig.json new file mode 100644 index 0000000000..9b3ec5a186 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/AutopilotModeConfig.json @@ -0,0 +1,38 @@ +{ + "mode": 1, + "source": 1, + "routeInfo": { + "startLocation": { + "longitude": 112.56970262448544, + "latitude": 26.817567832504274 + }, + "startName": "衡阳测试起点", + "endLocation": { + "longitude": 112.57723562874442, + "latitude": 26.819769725304003 + }, + "endName": "衡阳测试终点", + "wayPoints": [ + { + "longitude": 112.56970262448544, + "latitude": 26.817567832504274 + }, + { + "longitude": 112.57723562874442, + "latitude": 26.819769725304003 + } + ], + "vehicleType": 10, + "routeID": 60006, + "routeName": "衡阳测试路段", + "line": { + "lineId": 60006, + "trajUrl": "https://dzt-test.zhidaozhixing.com/yycp-sweeper/largeSweeper/trajInfo/download?key=largeSweeperTraj/0519qsc_1684823042062.csv", + "trajMd5": "6ad8c0456ced62ba1258753588d5d517", + "stopUrl": "https://dzt-test.zhidaozhixing.com/yycp-sweeper/largeSweeper/trajInfo/download?key=largeSweeperTraj/da_dian_hengyang_1684823379063.txt", + "stopMd5": "b1ecdc2c3a9467d58eb013bda53acf97", + "timestamp": 1684823379533, + "vehicleModel": "" + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/build.gradle b/OCH/sweeper/sweeper-cloud/build.gradle similarity index 100% rename from OCH/mogo-och-sweeper/build.gradle rename to OCH/sweeper/sweeper-cloud/build.gradle diff --git a/OCH/mogo-och-sweeper/gradle.properties b/OCH/sweeper/sweeper-cloud/gradle.properties similarity index 100% rename from OCH/mogo-och-sweeper/gradle.properties rename to OCH/sweeper/sweeper-cloud/gradle.properties diff --git a/OCH/mogo-och-sweeper/proguard-rules.pro b/OCH/sweeper/sweeper-cloud/proguard-rules.pro similarity index 100% rename from OCH/mogo-och-sweeper/proguard-rules.pro rename to OCH/sweeper/sweeper-cloud/proguard-rules.pro diff --git a/OCH/sweeper/sweeper-cloud/schemas/com.mogo.och.sweeper.database.MyDataBase/1.json b/OCH/sweeper/sweeper-cloud/schemas/com.mogo.och.sweeper.database.MyDataBase/1.json new file mode 100644 index 0000000000..a9451322a4 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/schemas/com.mogo.och.sweeper.database.MyDataBase/1.json @@ -0,0 +1,86 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "0897ef4b7b6a43fccf8bcf4b2144dafa", + "entities": [ + { + "tableName": "welt_data_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `subTaskId` INTEGER NOT NULL, `locLon` REAL NOT NULL, `locLat` REAL NOT NULL, `weltDistance` REAL NOT NULL, `cleanMode` INTEGER NOT NULL, `cleanDirection` INTEGER NOT NULL, `cleanIntensity` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subTaskId", + "columnName": "subTaskId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "locLon", + "columnName": "locLon", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "locLat", + "columnName": "locLat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "weltDistance", + "columnName": "weltDistance", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "cleanMode", + "columnName": "cleanMode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "cleanDirection", + "columnName": "cleanDirection", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "cleanIntensity", + "columnName": "cleanIntensity", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_welt_data_table_id", + "unique": true, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_welt_data_table_id` ON `${TABLE_NAME}` (`id`)" + } + ], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0897ef4b7b6a43fccf8bcf4b2144dafa')" + ] + } +} \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt b/OCH/sweeper/sweeper-cloud/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt similarity index 100% rename from OCH/mogo-och-sweeper/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt rename to OCH/sweeper/sweeper-cloud/src/androidTest/java/com/mogo/och/sweeper/ExampleInstrumentedTest.kt diff --git a/OCH/sweeper/sweeper-cloud/src/main/AndroidManifest.xml b/OCH/sweeper/sweeper-cloud/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..62a365f431 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/AndroidManifest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/assets/map_style.data b/OCH/sweeper/sweeper-cloud/src/main/assets/map_style.data similarity index 100% rename from OCH/mogo-och-sweeper/src/main/assets/map_style.data rename to OCH/sweeper/sweeper-cloud/src/main/assets/map_style.data diff --git a/OCH/mogo-och-sweeper/src/main/assets/map_style_extra.data b/OCH/sweeper/sweeper-cloud/src/main/assets/map_style_extra.data similarity index 100% rename from OCH/mogo-och-sweeper/src/main/assets/map_style_extra.data rename to OCH/sweeper/sweeper-cloud/src/main/assets/map_style_extra.data diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/IMogoOCH.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/IMogoOCH.java new file mode 100644 index 0000000000..028cb07e56 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/IMogoOCH.java @@ -0,0 +1,24 @@ +package com.mogo.och.sweepercloud; + +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/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/SweeperProvider.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/SweeperProvider.java new file mode 100644 index 0000000000..476d872e83 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/SweeperProvider.java @@ -0,0 +1,87 @@ +package com.mogo.och.sweepercloud; + + +import android.content.Context; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.sweepercloud.constant.SweeperConst; +import com.mogo.och.sweepercloud.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; + + @Override + public void init(Context context) { + } + private void showFragment() { + FragmentManager supportFragmentManager = activity.getSupportFragmentManager(); + if (sweeperFragment == null) { + CallerLogger.INSTANCE.d(TAG, "准备add fragment======"); + Fragment fragmentByTag = supportFragmentManager.findFragmentByTag(sweeperFragment.TAG); + if (fragmentByTag instanceof SweeperFragment) { + sweeperFragment = (SweeperFragment) fragmentByTag; + } else { + sweeperFragment = new SweeperFragment(); + } + if(!sweeperFragment.isAdded()) { + supportFragmentManager.beginTransaction().add(containerId, sweeperFragment, sweeperFragment.TAG).commitAllowingStateLoss(); + } + return; + } + CallerLogger.INSTANCE.d(TAG, "准备show fragment"); + supportFragmentManager.beginTransaction().show(sweeperFragment).commitAllowingStateLoss(); + } + private void hideFragment() { + if (sweeperFragment != null) { + CallerLogger.INSTANCE.d(TAG, "准备hide fragment"); + activity.getSupportFragmentManager().beginTransaction().hide(sweeperFragment).commitAllowingStateLoss(); + } + + } + + @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; + showFragment(); + return null; + } + + @Override + public void onDestroy() { + //若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠 + if (activity == null) return; + activity.finish(); + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/bean/SweeperRoutePlanningUpdateReqBean.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/bean/SweeperRoutePlanningUpdateReqBean.java new file mode 100644 index 0000000000..e2b10f7824 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/bean/SweeperRoutePlanningUpdateReqBean.java @@ -0,0 +1,32 @@ +package com.mogo.och.sweepercloud.bean; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by pangfan on 2021/8/19 + * + * 订单状态更新请求数据结构 + */ +public class SweeperRoutePlanningUpdateReqBean implements Serializable { + public String sn; + public int lineId; + public int startSiteId; + public int endSiteId; + public ArrayList points; + + public static class Result implements Serializable{ + public Double latitude; + public Double longitude; + } + + public SweeperRoutePlanningUpdateReqBean(String sn, int lineId, int startSiteId + , int endSiteId, ArrayList points) { + this.sn = sn; + this.lineId = lineId; + this.startSiteId = startSiteId; + this.endSiteId = endSiteId; + this.points = points; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ICleaningModeStateCallback.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ICleaningModeStateCallback.java new file mode 100644 index 0000000000..300a7300ad --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ICleaningModeStateCallback.java @@ -0,0 +1,12 @@ +package com.mogo.och.sweepercloud.callback; + +import com.mogo.och.sweepercloud.constant.OperateStateEnum; + +import chassis.ChassisStatesOuterClass; + +/** + * 上装状态回调 + */ +public interface ICleaningModeStateCallback { + void cleaningModeState(OperateStateEnum cleaningModeState, ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState,boolean isSelectPureSweepMode); +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperADASStatusCallback.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperADASStatusCallback.java new file mode 100644 index 0000000000..f8ce45d1a5 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperADASStatusCallback.java @@ -0,0 +1,11 @@ +package com.mogo.och.sweepercloud.callback; + +/** + * Created on 2021/9/8 + * + * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等) + */ +public interface ISweeperADASStatusCallback { + //自驾返回失败 + void onStartAdasFailure(); +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperCloudTaskCallback.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperCloudTaskCallback.kt new file mode 100644 index 0000000000..92fc78aafb --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperCloudTaskCallback.kt @@ -0,0 +1,69 @@ +package com.mogo.och.sweepercloud.callback + +import chassis.ChassisStatesOuterClass +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.database.bean.WeltDataBean +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable.IsBootableResp +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon.Code +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.stop.SweeperTaskStop.StopTaskType + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +interface ISweeperCloudTaskCallback { + /** + * 接取云端任务/正在执行中任务信息回调 + */ + fun onSweeperCloudTask(messageType: SweeperCloudTask.MessageType,taskInfo: SweeperTask.TaskInfo?) + + /** + * 云端下发子任务请求pad确认 + */ + fun onSweeperCloudTaskConfirm(taskId:String,subTaskId:String,isPop:Boolean) + + /** + * 云端下发子任务状态同步 + */ + fun onSweeperCloudTaskStatus(taskId:String,subTaskId:String,subTaskStatus: SweeperCommon.TaskStatus) + + /** + * 云端下发结束大任务指令 + */ + fun onSweeperCloudTaskStop(taskId:String,stopTaskType: StopTaskType,isPop:Boolean) + + /** + * 挂起/恢复 + */ + fun onSweeperCloudTaskSuspendResume(messageType: SweeperCloudTask.MessageType,taskId:String,subTaskId:String,code:Code) + + /** + * pad请求云端进入自驾 + */ + fun onSweeperCloudBootable(taskId:String,subTaskId:String,isBootableResp: IsBootableResp) + + /** + * 云端同步大任务状态 + */ + fun onSweeperCloudBigTaskStatus(taskId:String,subTaskStatus: SweeperBigTaskStatus.BigTaskStatus) + /** + * 设置轨迹坐标点集合 + */ + fun setRouteList(routeList: java.util.ArrayList) + /** + * 贴边数据回传 + */ + fun setWeltDataToMap(weltDataBeans: ArrayList, isWeltData: Boolean, distance: String) + + /** + * 底盘清扫模式数据回传 + */ + fun onSweeperFutianCleanSystemState(cleanSystemState: ChassisStatesOuterClass.SweeperFuTianTaskSystemStates) + + +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperControllerStatusCallback.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperControllerStatusCallback.java new file mode 100644 index 0000000000..2ad48d1d5b --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperControllerStatusCallback.java @@ -0,0 +1,17 @@ +package com.mogo.och.sweepercloud.callback; + +import com.mogo.eagle.core.data.map.MogoLocation; + +/** + * 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(MogoLocation location); + //自动驾驶状态 + void onAutopilotState(int state); +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskDataToFragmentCallback.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskDataToFragmentCallback.kt new file mode 100644 index 0000000000..4e5badf48d --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskDataToFragmentCallback.kt @@ -0,0 +1,15 @@ +package com.mogo.och.sweepercloud.callback + +import com.amap.api.maps.model.LatLng +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.database.bean.WeltDataBean +import java.util.ArrayList + +interface ISweeperTaskDataToFragmentCallback { + fun setRouteList(routeList: ArrayList) + fun setWeltData(weltDatas: ArrayList?, distance: String) + fun clearAllMarkerAndPolyline() + fun setProgress(progress:String) + fun setTaskListCoordinatesLatLng(coordinatesLatLng: ArrayList) + fun setCurrentTaskCoordinatesLatLng(coordinatesLatLng: LatLng) +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskRouteCallback.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskRouteCallback.kt new file mode 100644 index 0000000000..81f37c8a64 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/ISweeperTaskRouteCallback.kt @@ -0,0 +1,8 @@ +package com.mogo.och.sweepercloud.callback + +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import java.util.ArrayList + +interface ISweeperTaskRouteCallback { + fun setRouteList(routeList:ArrayList) +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/IWeltMapSwitchToSmallCallback.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/IWeltMapSwitchToSmallCallback.kt new file mode 100644 index 0000000000..20748b003b --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/IWeltMapSwitchToSmallCallback.kt @@ -0,0 +1,5 @@ +package com.mogo.och.sweepercloud.callback + +interface IWeltMapSwitchToSmallCallback { + fun onWeltMapSwitchToSmall() +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/SweeperCloudDialogClickListener.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/SweeperCloudDialogClickListener.kt new file mode 100644 index 0000000000..abf3be40ca --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/callback/SweeperCloudDialogClickListener.kt @@ -0,0 +1,8 @@ +package com.mogo.och.sweepercloud.callback + +interface SweeperCloudDialogClickListener { + fun onConfirm() + fun onRefuseOrEnd() + fun onCountDownStop() + fun onNext() +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/OperateStateEnum.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/OperateStateEnum.kt new file mode 100644 index 0000000000..d757fee453 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/OperateStateEnum.kt @@ -0,0 +1,12 @@ +package com.mogo.och.sweepercloud.constant + +/** + * 上装面板操作状态 + */ +enum class OperateStateEnum(val code: Int) { + SYNCING_STATUS( 1),//清扫车底盘状态同步中 + STARTING_STATUS( 2),//上装中 + FAIL_STATUS( 3),//上装失败 + SUCCESS_STATUS(4),//上装成功 + NO_STATUS(-1);//暂无模式 +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/SweeperConst.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/SweeperConst.kt new file mode 100644 index 0000000000..aa96c7f40d --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/constant/SweeperConst.kt @@ -0,0 +1,70 @@ +package com.mogo.och.sweepercloud.constant + +import com.mogo.commons.debug.DebugConfig + +/** + * Created on 2021/12/6 + */ +class SweeperConst { + companion object { + + // OCH arouter 路由path + const val PATH = "/driver/api" + + // 测试用的广播 + const val BROADCAST_TEST_SWEEPER_CONTROL_TYPE_EXTRA_KEY = "sceneType" + + // 上报心跳轮询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_START_FAILURE_CODE = "start_autopilot_failure_code" // 启动自驾失败code + 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:开启自动驾驶前已识别的异常,会导致无法开启自驾 + const val EVENT_KEY_AP_UNABLE_START_REASON = "event_key_och_bus_ap_unable_start_reason" + const val EVENT_PARAM_UNABLE_START_REASON = "unable_start_reason"; + + /** + * 订单起终点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 + + //非贴边 + const val NONWELT = -10000.0 + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/MyDataBase.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/MyDataBase.java new file mode 100644 index 0000000000..7d2cdb3e22 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/MyDataBase.java @@ -0,0 +1,31 @@ +package com.mogo.och.sweepercloud.database; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.database.dao.WeltDataDao; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.database.dao.WeltDataDao; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; + +//注解Database告诉系统这是Room数据库对象 +//entities指定该数据库有哪些表,多张表就逗号分隔 +//version指定数据库版本号,升级时需要用到 +//数据库继承自RoomDatabase +@Database(entities = {WeltDataBean.class}, version = 1) +public abstract class MyDataBase extends RoomDatabase { + private static final String DATABASE_NAME = "weltData_db"; + + //结合单例模式完成数据库实例创建 + public static MyDataBase getInstance() { + return SingleTon.instance; + } + + private static class SingleTon { + private static final MyDataBase instance = + Room.databaseBuilder(AbsMogoApplication.getApp().getApplicationContext(), MyDataBase.class, DATABASE_NAME).build(); + } + public abstract WeltDataDao getWeltDataDao(); +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/bean/WeltDataBean.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/bean/WeltDataBean.java new file mode 100644 index 0000000000..f6a3be84ee --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/bean/WeltDataBean.java @@ -0,0 +1,127 @@ +package com.mogo.och.sweepercloud.database.bean; + +import java.io.Serializable; + +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +@Entity(tableName = WeltDataBean.WeltDataTable, indices = {@Index(value = "id", unique = true)}) +public class WeltDataBean implements Serializable { + + public static final String WeltDataTable = "welt_data_table"; + //ColumnInfo用于指定该字段存储在表中的名字,并指定类型 + + @PrimaryKey(autoGenerate = true) + + @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER) + + private int id; + + @ColumnInfo(name = "subTaskId", typeAffinity = ColumnInfo.TEXT)//子任务id + + private String subTaskId; + + @ColumnInfo(name = "locLon", typeAffinity = ColumnInfo.REAL) + + private double locLon;//自车RTK定位经度 + + @ColumnInfo(name = "locLat", typeAffinity = ColumnInfo.REAL) + + private double locLat;//自车RTK定位纬度 + + @ColumnInfo(name = "weltDistance", typeAffinity = ColumnInfo.REAL) + + private double weltDistance;//贴边距离 + + @ColumnInfo(name = "cleanMode", typeAffinity = ColumnInfo.INTEGER) + + private int cleanMode;//清扫作业模式 1–纯扫 2--洗扫, 3--纯洗, 4--纯吸 + + @ColumnInfo(name = "cleanDirection", typeAffinity = ColumnInfo.INTEGER) + + private int cleanDirection;//清扫方向 1--两侧, 2--左侧, 3--右侧 + + @ColumnInfo(name = "cleanIntensity", typeAffinity = ColumnInfo.INTEGER) + + private int cleanIntensity;//清扫强度 1--两侧, 2--左侧, 3--右侧 + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getSubTaskId() { + return subTaskId; + } + + public void setSubTaskId(String subTaskId) { + this.subTaskId = subTaskId; + } + + public double getLocLon() { + return locLon; + } + + public void setLocLon(double locLon) { + this.locLon = locLon; + } + + public double getLocLat() { + return locLat; + } + + public void setLocLat(double locLat) { + this.locLat = locLat; + } + + public double getWeltDistance() { + return weltDistance; + } + + public void setWeltDistance(double weltDistance) { + this.weltDistance = weltDistance; + } + + public int getCleanMode() { + return cleanMode; + } + + public void setCleanMode(int cleanMode) { + this.cleanMode = cleanMode; + } + + public int getCleanDirection() { + return cleanDirection; + } + + public void setCleanDirection(int cleanDirection) { + this.cleanDirection = cleanDirection; + } + + public int getCleanIntensity() { + return cleanIntensity; + } + + public void setCleanIntensity(int cleanIntensity) { + this.cleanIntensity = cleanIntensity; + } + + @Override + public String toString() { + return "WeltDataBean{" + + "id=" + id + + ", subTaskId='" + subTaskId + '\'' + + ", locLon=" + locLon + + ", locLat=" + locLat + + ", weltDistance=" + weltDistance + + ", cleanMode=" + cleanMode + + ", cleanDirection=" + cleanDirection + + ", cleanIntensity=" + cleanIntensity + + '}'; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/dao/WeltDataDao.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/dao/WeltDataDao.java new file mode 100644 index 0000000000..4217b93d85 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/database/dao/WeltDataDao.java @@ -0,0 +1,28 @@ +package com.mogo.och.sweepercloud.database.dao; + +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; + +import java.util.List; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import static com.mogo.och.sweepercloud.database.bean.WeltDataBean.WeltDataTable; + +@Dao +public interface WeltDataDao { + //插入数据 + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(WeltDataBean fileInfo); + + //删除所有数据 + @Query("DELETE FROM " + WeltDataBean.WeltDataTable) + int deleteAllWeltData(); + + //查询所有数据 + @Query("SELECT * FROM " + WeltDataBean.WeltDataTable) + List loadAllWeltDataInfo(); +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperTabFragment.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperTabFragment.java new file mode 100644 index 0000000000..e3842fcf82 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperTabFragment.java @@ -0,0 +1,609 @@ +package com.mogo.och.sweepercloud.fragment; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_SWEEPER; + +import android.os.Bundle; +import android.os.Parcelable; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.Group; +import androidx.fragment.app.FragmentTransaction; + +import com.amap.api.maps.model.LatLng; +import com.elegant.network.utils.GsonUtil; +import com.google.protobuf.TextFormat; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.mvp.IView; +import com.mogo.commons.mvp.MvpFragment; +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; +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.call.map.CallerMapUIServiceManager; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxBubbleView; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxButtonView; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxListView; +import com.mogo.eagle.core.function.view.MapBizView; +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.ThreadUtils; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.map.listener.IMogoMapListener; +import com.mogo.map.listener.MogoMapListenerHandler; +import com.mogo.map.uicontroller.IMogoMapUIController; +import com.mogo.map.uicontroller.VisualAngleMode; +import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; +import com.mogo.och.common.module.utils.PinYinUtil; +import com.mogo.och.sweepercloud.R; +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweepercloud.callback.ISweeperTaskDataToFragmentCallback; +import com.mogo.och.sweepercloud.callback.IWeltMapSwitchToSmallCallback; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.util.AutopilotModeConfigManager; +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils; +import com.mogo.och.sweepercloud.view.SweeperTrafficDataView; +import com.mogo.och.sweepercloud.view.WeltSmallMapView; +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; + +import mogo.telematics.pad.MessagePad; + +/** + * 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况 + *

+ * 部分业务放在了此处处理 + * + * @author tongchenfei + */ +public abstract class BaseSweeperTabFragment> extends MvpFragment implements IMogoMapListener, + IWeltMapSwitchToSmallCallback, View.OnTouchListener { + + private static final String TAG = "BaseSweeperTabFragment"; + //地图放大缩小 + private ImageView mSwitchMapModeImage; + //设置信息面板 + protected ImageView mSettingBtn; + //安全员问题上报面板 + protected ImageView mCardBtn; + //道路状况上报面板 + protected ImageView mAICollectBtn; + //任务列表面板 + private FrameLayout flTaskListPanelContainer; + private MapBizView mapBizView; + private Group groupTestPanel; + //清扫车车辆基本信息 速度 档位 转向灯 红绿灯等 + private SweeperTrafficDataView mTrafficDataView; + //作业任务贴边数据展示图 + private WeltSmallMapView mMapWeltView; + //任务作业全览图 + private WeltMapOverViewFragment mWeltMapOverViewFragment; + private FrameLayout mFlWeltMapOverView; + private DriverMsgBoxButtonView mViewDriverMsgBoxButton; + private DriverMsgBoxListView mViewDriverMsgBoxList; + private DriverMsgBoxBubbleView mViewDriverMsgBoxBubble; + private ArrayList mWeltDataBeanList;//存储贴边数据 + private ArrayList mSubTaskCoordinates;//存储当前大任务的所有子任务起点和终点 + // 当前子任务的终点坐标 + protected LatLng mCurrentTaskEndStation; + private ArrayList mRouteList;//存储任务的坐标轨迹 + private String mProgress; + private ISweeperTaskDataToFragmentCallback mTaskDataToFragmentCallback; + + @Override + protected int getLayoutId() { + return R.layout.sweeper_base_fragment; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + + @Override + protected void initViews() { + mapBizView = findViewById(R.id.mapBizView); + groupTestPanel = findViewById(R.id.groupTestPanel); + flTaskListPanelContainer = findViewById(R.id.module_mogo_och_task_list_container); + mTrafficDataView = findViewById(R.id.sweeper_arc); + LayoutInflater.from(getContext()).inflate(getTaskListPanelViewId(), flTaskListPanelContainer); + mSwitchMapModeImage = findViewById(R.id.sweeper_switch_model_icon); + mSettingBtn = findViewById(R.id.sweeper_setting_model_icon); + mCardBtn = findViewById(R.id.sweeper_card_model_icon); + mAICollectBtn = findViewById(R.id.sweeper_collect_model_icon); + mMapWeltView = findViewById(R.id.sweeper_task_welt_small_map); + mFlWeltMapOverView = findViewById(R.id.sweeper_welt_map_overview); + initListener(); + //设置消息盒子 + setMessageBox(); + //设置左下角四个按钮监听事件 + setBottomBtnListener(); + // 模拟 下发启动自驾命令 + findViewById(R.id.btnStartAutopilot).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().getAutopilotAbilityStatus()) { + ToastUtils.showLong(OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason() + ", 请稍候重试"); + return; + } + new AutopilotModeConfigManager(new AutopilotModeConfigManager.OnReadAutopilotModeConfigListener() { + @Override + public void onReadFailed(String err) { + ThreadUtils.runOnUiThread(() -> { + ToastUtils.showLong("读取失败=" + err); + }); + } + + @Override + public void onParseFailed(String err) { + ToastUtils.showLong("解析失败=" + err); + } + + @Override + public void onParse(MessagePad.SetAutopilotModeReq bean) { + ToastUtils.showLong("下发命令\n" + TextFormat.printer().escapingNonAscii(false).printToString(bean)); + AutopilotControlParameters parameters = new AutopilotControlParameters(); + MessagePad.RouteInfo routeInfo = bean.getRouteInfo(); + if (routeInfo.getRouteID() > 0) { + parameters.routeID = routeInfo.getRouteID(); + } + parameters.routeName = routeInfo.getRouteName(); + parameters.startName = routeInfo.getStartName();//拼音 + parameters.endName = routeInfo.getEndName();//拼音 + parameters.startLatLon = new AutopilotControlParameters + .AutoPilotLonLat(routeInfo.getStartLocation().getLatitude(), routeInfo.getStartLocation().getLongitude()); + parameters.endLatLon = new AutopilotControlParameters + .AutoPilotLonLat(routeInfo.getEndLocation().getLatitude(), routeInfo.getEndLocation().getLongitude()); + parameters.vehicleType = 10; + MessagePad.Line line = routeInfo.getLine(); + parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine( + line.getLineId(), + line.getTrajUrl(), line.getTrajMd5(), + line.getStopUrl(), line.getStopMd5(), + line.getTimestamp(), line.getVehicleModel(), + line.getTrajUrlDpqp(), line.getTrajMd5Dpqp(), + line.getStopUrlDpqp(), line.getStopMd5Dpqp(), + line.getTimestampDpqp()); + CallerAutoPilotControlManager.INSTANCE.startAutoPilot(parameters); + } + }).read(); + } + }); + // 模拟 查询当前任务 + findViewById(R.id.btnQueryCurrentTask).setOnClickListener(view -> + SweeperCloudTaskUtils.mockQueryCurrentTaskInfo() + ); + // 模拟 云端发送任务 + findViewById(R.id.btnSendTask).setOnClickListener(view -> { + SweeperCloudTaskUtils.mockSendCloudTaskInfo(SweeperCloudTask.MessageType.CloudPushTask); + UiThreadHandler.postDelayed(() -> { + debugEndSubTask(); + }, 5000); + + } + + ); + // 模拟 云端发送子任务确认 + findViewById(R.id.btnSendSubTaskConfirm).setOnClickListener(view -> + SweeperCloudTaskUtils.mockSendCloudSubTaskConfirm() + ); + + // 模拟 云端请求结束大任务 + findViewById(R.id.btnSendEndTask).setOnClickListener(view -> + SweeperCloudTaskUtils.mockSendCloudBigTaskEnd() + ); + // 模拟 云端发送子任务状态 + findViewById(R.id.btnSendSubtaskStatus).setOnClickListener(view -> + SweeperCloudTaskUtils.mockSendCloudUpdateSubTaskStatus() + ); + // 模拟 云端发送大任务状态 + findViewById(R.id.btnSendTaskStatus).setOnClickListener(view -> + SweeperCloudTaskUtils.mockSendCloudBigTaskStatus() + ); + mTrafficDataView.getSpeedImage().setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + debugTestBar(); + return false; + } + }); + } + + private void updateSwitchMapIcon() { + IMogoMapUIController controller = CallerMapUIServiceManager.INSTANCE.getMapUIController(); + if (controller != null) { + if (controller.getCurrentMapVisualAngle().isLongSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_big_selector); + } else if (controller.getCurrentMapVisualAngle().isMediumSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_small_selector); + } else { + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_small_selector); + } + } + } + + /** + * 设置任务进度 + * + * @param progress + */ + protected void setTaskProgress(String progress) { + ThreadUtils.runOnUiThread(() -> { + mMapWeltView.setTaskProgress(progress); + mProgress = progress; + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.setProgress(progress); + } + }); + } + + @Override + protected void initViews(Bundle savedInstanceState) { + super.initViews(savedInstanceState); + mapBizView.onCreate(savedInstanceState); + mMapWeltView.onCreateView(savedInstanceState); + } + + public void setAutoState(int state) { + mTrafficDataView.setAutoState(state); + } + + /** + * 消息盒子 + */ + private void setMessageBox() { + mViewDriverMsgBoxButton = findViewById(R.id.viewDriverMsgBoxButton); + mViewDriverMsgBoxList = findViewById(R.id.viewDriverMsgBoxList); + mViewDriverMsgBoxBubble = findViewById(R.id.viewDriverMsgBoxBubble); + //消息盒子 + mViewDriverMsgBoxButton.setClickListener(show -> { + if (show) { + mViewDriverMsgBoxList.setVisibility(View.VISIBLE); + mViewDriverMsgBoxList.notifyData(); + mViewDriverMsgBoxBubble.setVisibility(View.GONE); + mViewDriverMsgBoxBubble.isShowData(false); + } else { + mViewDriverMsgBoxList.setVisibility(View.GONE); + mViewDriverMsgBoxBubble.setVisibility(View.VISIBLE); + mViewDriverMsgBoxBubble.isShowData(true); + } + }); + } + + @Override + public void onPause() { + super.onPause(); + mMapWeltView.onPause(); + } + + @Override + public void onResume() { + super.onResume(); + mapBizView.onResume(); + mMapWeltView.onResume(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + mapBizView.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapBizView.onLowMemory(); + } + + @Override + public void onDestroyView() { + mapBizView.onDestroy(); + super.onDestroyView(); + CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + view.setOnTouchListener(this); + + } + + private void initListener() { + MogoMapListenerHandler.Companion.getMogoMapListenerHandler().registerHostMapListener(TAG, this); + mMapWeltView.getSwitchToBig().setOnClickListener((v) -> { + showOrHideOverMapViewFragment(true); + }); + } + + /** + * 清扫车任务列表面板view,在{@link #initViews()}时候添加到container中 + * + * @return 站点面板view + */ + public abstract int getTaskListPanelViewId(); + + + /** + * 迈速表实时更新 + * + * @param newSpeed + */ + public void updateSpeedView(float newSpeed) { + int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值 + if (mTrafficDataView != null) { + mTrafficDataView.updateSpeedWithValue(speed); + } + } + + /** + * 车辆基本信息View + * + * @return + */ + public SweeperTrafficDataView getTrafficDataView() { + return mTrafficDataView; + } + + @Override + public void onDestroy() { + super.onDestroy(); + mMapWeltView.onDestroy(); + MogoMapListenerHandler.Companion.getMogoMapListenerHandler().unregisterHostMapListener(TAG); + } + + @Override + public void onMapVisualAngleChanged(VisualAngleMode visualAngleMode) { + if (visualAngleMode.isMediumSight()) { + mSwitchMapModeImage.setVisibility(View.VISIBLE); + } else if (visualAngleMode.isLongSight()) { + mSwitchMapModeImage.setVisibility(View.VISIBLE); + } else if (visualAngleMode.isCloseSight()) { + mSwitchMapModeImage.setVisibility(View.GONE); + } + } + + /** + * sweeper调试面板打开关闭 + */ + public void debugTestBar() { + if (groupTestPanel.getVisibility() == View.VISIBLE) { + groupTestPanel.setVisibility(View.GONE); + } else { + groupTestPanel.setVisibility(View.VISIBLE); + } + } + + /** + * 底部四个按钮监听 + * 1.地图放大缩小 + * 2.设置面板 + * 3.安全员问题上报面板 + * 4.道路状况上报面板 + */ + private void setBottomBtnListener() { + updateSwitchMapIcon(); + mSwitchMapModeImage.setOnClickListener(new OnPreventFastClickListener() { + @Override + public void onClickImpl(View v) { + IMogoMapUIController controller = CallerMapUIServiceManager.INSTANCE.getMapUIController(); + if (controller != null) { + //切换地图的远近视图 + if (controller.getCurrentMapVisualAngle().isLongSight()) { + // 2.11.0去掉 +// MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).visibleAllMarkers(); + controller.changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_small_selector); + } else if (controller.getCurrentMapVisualAngle().isMediumSight()) { + // 2.11.0去掉 +// MogoMarkerManager.getInstance(AbsMogoApplication.getApp()) +// .inVisibleWithoutMarkers(DataTypes.TYPE_MARKER_ADAS, BusConst.TYPE_MARKER_BUS_ORDER); + controller.changeMapVisualAngle(VisualAngleMode.MODE_LONG_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_big_selector); + } else { + // 2.11.0去掉 +// MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).visibleAllMarkers(); + controller.changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.sweeper_switch_map_big_selector); + } + } + } + }); + mSettingBtn.setOnClickListener(v -> { + // TODO: 2021/12/9 + CallerHmiManager.INSTANCE.showToolsView(); + }); + if (mCardBtn != null) { + CallerDevaToolsManager.INSTANCE.initBadCase(mCardBtn); + } + if (mAICollectBtn != null) { + CallerDevaToolsManager.INSTANCE.initAiCollect(mAICollectBtn); + } + } + + /** + * 设置作业任务全览图隐藏或者显示 + * + * @param isShow + */ + public void showOrHideOverMapViewFragment(boolean isShow) { + FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); + if (isShow) { + mFlWeltMapOverView.setVisibility(View.VISIBLE); + if (mWeltMapOverViewFragment == null) { + mWeltMapOverViewFragment = mWeltMapOverViewFragment.newInstance( + (IWeltMapSwitchToSmallCallback) this, + mCurrentTaskEndStation, + mWeltDataBeanList, + mSubTaskCoordinates, + mRouteList, + mProgress, + (SweeperFragment) this); + } + if (mWeltMapOverViewFragment.isHidden()) { + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .show(mWeltMapOverViewFragment).commitAllowingStateLoss(); + return; + } + if (mWeltMapOverViewFragment.isAdded()) { + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .show(mWeltMapOverViewFragment).commitAllowingStateLoss(); + return; + } + transaction + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .add(R.id.sweeper_welt_map_overview, mWeltMapOverViewFragment) + .show(mWeltMapOverViewFragment).commitAllowingStateLoss(); + } else { + mFlWeltMapOverView.setVisibility(View.GONE); + if (mWeltMapOverViewFragment != null) { + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE) + .hide(mWeltMapOverViewFragment).commitAllowingStateLoss(); + } + } + } + + @Override + public void onWeltMapSwitchToSmall() { + showOrHideOverMapViewFragment(false); + } + + /** + * 设置贴边数据到地图 + * + * @param weltDataBeans + */ + public void setWeltDataToMap(ArrayList weltDataBeans, Boolean isWeltData, String distance) { + mWeltDataBeanList = weltDataBeans; + ThreadUtils.getSinglePool().execute(new Runnable() { + @Override + public void run() { + if (mMapWeltView != null) { + mMapWeltView.setWeltData(weltDataBeans, isWeltData, distance); + } + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.setWeltData(weltDataBeans, distance); + } + } + }); + } + + public void setTaskListCoordinatesLatLng(ArrayList subTaskCoordinates) { + this.mSubTaskCoordinates = subTaskCoordinates; + if (mMapWeltView != null) { + mMapWeltView.setTaskListCoordinatesLatLng(subTaskCoordinates); + } + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.setTaskListCoordinatesLatLng(subTaskCoordinates); + } + } + + /** + * 设置当前任务终点 + * + * @param subTaskCoordinate + */ + public void setCurrentTaskEndMarker(LatLng subTaskCoordinate) { + if (mMapWeltView != null) { + mMapWeltView.setCurrentTaskCoordinatesLatLng(subTaskCoordinate); + } + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.setCurrentTaskCoordinatesLatLng(subTaskCoordinate); + } + } + + /** + * 清除marker标记和任务路线数据 + */ + public void clearAllMarkerAndPolyline() { + if (mMapWeltView != null) { + mMapWeltView.clearAllMarkerAndPolyline(); + } + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.clearAllMarkerAndPolyline(); + } + } + + /** + * 设置任务轨迹点数据 + */ + public void setTaskRouteList(ArrayList routeList) { + mRouteList = routeList; + ThreadUtils.getSinglePool().execute(() -> { + mMapWeltView.setRouteList(routeList); + if (mTaskDataToFragmentCallback != null) { + mTaskDataToFragmentCallback.setRouteList(routeList); + } + }); + } + + public static String format(double value) { + BigDecimal bd = new BigDecimal(value); + bd = bd.setScale(2, RoundingMode.HALF_UP); + return bd.toString(); + } + + public void setTaskDataToFragmentCallback(ISweeperTaskDataToFragmentCallback mTaskDataToFragmentCallback) { + this.mTaskDataToFragmentCallback = mTaskDataToFragmentCallback; + } + + /** + * 结束子任务 + */ + public void debugEndSubTask() { + ArrayList resultArrayList = tempData(); + setTaskRouteList(resultArrayList); + UiThreadHandler.postDelayed(() -> { + ArrayList routeList = tempData1(); + ArrayList weltDataBeans = new ArrayList<>(); + ArrayList subTaskCoordinates = new ArrayList<>(); + for (int i = 0; i < routeList.size(); i++) { + WeltDataBean weltDataBean = new WeltDataBean(); + weltDataBean.setLocLon(routeList.get(i).longitude); + weltDataBean.setLocLat(routeList.get(i).latitude); + weltDataBean.setWeltDistance(Math.random() * 50); + weltDataBeans.add(weltDataBean); + subTaskCoordinates.add(new LatLng(routeList.get(i).latitude, routeList.get(i).longitude)); + } + setTaskListCoordinatesLatLng(subTaskCoordinates); + setWeltDataToMap(weltDataBeans, true, format(Math.random() * 50)); + }, 2000); + } + + private ArrayList tempData() { + ArrayList results = new ArrayList<>(); + results.add(getRoute(112.56970669282785, 26.8175674285121)); + results.add(getRoute(112.57154905962457, 26.81762377130161)); + results.add(getRoute(112.57723562917293, 26.819769721883098)); + return results; + } + + private ArrayList tempData1() { + ArrayList results = new ArrayList<>(); + results.add(getRoute(112.56970669282785, 26.8175674285121)); + results.add(getRoute(112.57154905962457, 26.81762377130161)); + results.add(getRoute(112.57723562917293, 26.819769721883098)); + return results; + } + + private SweeperRoutePlanningUpdateReqBean.Result getRoute(double longitude, double latitude) { + LatLng latLng = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj(AbsMogoApplication.getApp(), longitude, latitude); + SweeperRoutePlanningUpdateReqBean.Result result = new SweeperRoutePlanningUpdateReqBean.Result(); + result.latitude = latLng.latitude; + result.longitude = latLng.longitude; + return result; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperUIFragment.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperUIFragment.java new file mode 100644 index 0000000000..e220d1a777 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/BaseSweeperUIFragment.java @@ -0,0 +1,50 @@ +package com.mogo.och.sweepercloud.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +/** + * @author: wangmingjun + * @date: 2021/9/9 + */ +public abstract class BaseSweeperUIFragment extends Fragment { + private View mRootView; + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + if (mRootView == null) { + mRootView = inflater.inflate(getLayoutId(), container, false); + } else { + ViewGroup viewGroup = (ViewGroup) mRootView.getParent(); + if (viewGroup != null) { + viewGroup.removeView(mRootView); + } + } + initViews(mRootView); + initViews(savedInstanceState); + return mRootView; + } + /** + * 布局资源 + * + * @return + */ + protected abstract int getLayoutId(); + + protected abstract void initViews(View view); + + protected void initViews(Bundle savedInstanceState) { + } + + @Override + public void onDestroy() { + super.onDestroy(); + mRootView = null; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperAmapNaviFragment.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperAmapNaviFragment.java new file mode 100644 index 0000000000..e05d396e95 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperAmapNaviFragment.java @@ -0,0 +1,230 @@ +package com.mogo.och.sweepercloud.fragment; + +import android.os.Bundle; +import android.view.View; + +import com.amap.api.navi.AMapNaviViewListener; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.common.module.map.AmapNaviToDestinationModel; +import com.mogo.och.common.module.map.CommonAmapNaviVIew; +import com.mogo.och.common.module.map.ICommonNaviChangedCallback; +import com.mogo.och.sweepercloud.R; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI; + +/** + * @author: wangmingjun + * @date: 2021/11/30 + */ +public class SweeperAmapNaviFragment extends BaseSweeperUIFragment implements AMapNaviViewListener { + + private CommonAmapNaviVIew mAMapNaviView; + private ICommonNaviChangedCallback mNaviToStartInfoCallback; + public static SweeperAmapNaviFragment newInstance() { + + Bundle args = new Bundle(); + + SweeperAmapNaviFragment fragment = new SweeperAmapNaviFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + protected int getLayoutId() { + return R.layout.sweeper_amap_navi_view; + } + + @Override + protected void initViews(View view) { + mAMapNaviView = view.findViewById(R.id.navi_view); + } + + @Override + protected void initViews(Bundle savedInstanceState) { + super.initViews(savedInstanceState); + if (mAMapNaviView != null) + mAMapNaviView.onCreate(savedInstanceState); + } + + @Override + public void onResume() { + super.onResume(); + if (mAMapNaviView != null) + mAMapNaviView.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + if (mAMapNaviView != null) + mAMapNaviView.onPause(); + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (hidden) { //不在最前端界面显示 + if (mAMapNaviView != null){ + mAMapNaviView.onPause(); + } + } else { //重新显示到最前端 + if (mAMapNaviView != null){ + mAMapNaviView.onResume(); + } + } + } + @Override + public void onDestroy() { + super.onDestroy(); + + AmapNaviToDestinationModel.getInstance(getContext()).setVoiceIsMute(false); + if (mAMapNaviView != null){ + mAMapNaviView.onDestroy(); + } + + if (mNaviToStartInfoCallback != null){ + mNaviToStartInfoCallback = null; + } + } + + @Override + public void onNaviSetting() { + //底部导航设置点击回调 + } + + @Override + public void onNaviCancel() { + } + + @Override + public void onNaviMapMode(int naviMode) { + //导航态车头模式,0:车头朝上状态;1:正北朝上模式。 + } + + @Override + public void onNaviTurnClick() { + //转弯view的点击回调 + } + + @Override + public void onNextRoadClick() { + //下一个道路View点击回调 + } + + + @Override + public void onScanViewButtonClick() { + //全览按钮点击回调 + } + + + @Override + public void onLockMap(boolean isLock) { + //锁地图状态发生变化时回调 + } + + @Override + public void onNaviViewLoaded() { + CallerLogger.INSTANCE.d(M_TAXI + "wlx", "导航页面加载成功"); + CallerLogger.INSTANCE.d(M_TAXI + "wlx", "请不要使用AMapNaviView.getMap().setOnMapLoadedListener();会overwrite导航SDK内部画线逻辑"); + } + + @Override + public void onMapTypeChanged(int i) { + + } + + @Override + public void onNaviViewShowMode(int i) { + + } + + @Override + public boolean onNaviBackClick() { + return false; + } + + /** + * 车道信息说明: + *

+ * 0xFF, 无对应车道 + * 0, 直行 + * 1, 左转 + * 2, 直行+左转 + * 3, 右转 + * 4, 直行+右转 + * 5, 左掉头 + * 6, 左转+右转 + * 7, 直行+左转+右转 + * 8, 右掉头 + * 9, 直行+左掉头 + * 10, 直行+右掉头 + * 11, 左转+左掉头 + * 12, 右转+右掉头 + * 13, 直行+扩展 + * 14, 左转+左掉头+扩展 + * 15, 保留 + * 16, 直行+左转+左掉头 + * 17, 右转+左掉头 + * 18, 左转+右转+左掉头 + * 19, 直行+右转+左掉头 + * 20, 左转+右掉头 + * 21, 公交车道 + * 22, 空车道 + * 23 可变车道 + */ + + String[] array = { + "直行车道" + , "左转车道" + , "左转或直行车道" + , "右转车道" + , "右转或直行车道" + , "左掉头车道" + , "左转或者右转车道" + , " 左转或右转或直行车道" + , "右转掉头车道" + , "直行或左转掉头车道" + , "直行或右转掉头车道" + , "左转或左掉头车道" + , "右转或右掉头车道" + , "直行并且车道扩展" + , "左转+左掉头+扩展" + , "不可以选择该车道" + , "直行+左转+左掉头车道" + , "右转+左掉头" + , "左转+右转+左掉头" + , "直行+右转+左掉头" + , "左转+右掉头" + , "公交车道" + , "空车道" + , "可变车道" + }; + + String[] actions = { + "直行" + , "左转" + , "左转或直行" + , "右转" + , "右转或这行" + , "左掉头" + , "左转或者右转" + , " 左转或右转或直行" + , "右转掉头" + , "直行或左转掉头" + , "直行或右转掉头" + , "左转或左掉头" + , "右转或右掉头" + , "直行并且车道扩展" + , "左转+左掉头+扩展" + , "不可以选择" + , "直行+左转+左掉头" + , "右转+左掉头" + , "左转+右转+左掉头" + , "直行+右转+左掉头" + , "左转+右掉头" + , "公交车道" + , "空车道" + , "可变车道" + }; +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperFragment.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperFragment.kt new file mode 100644 index 0000000000..a59f2c0fd7 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/SweeperFragment.kt @@ -0,0 +1,587 @@ +package com.mogo.och.sweepercloud.fragment + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.lifecycleScope +import chassis.ChassisStatesOuterClass +import com.amap.api.maps.model.LatLng +import com.elegant.utils.UiThreadHandler +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener.Companion.STATUS_AUTOPILOT_ENABLE +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.common.module.voice.VoiceNotice.showNotice +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.callback.SweeperCloudDialogClickListener +import com.mogo.och.sweepercloud.database.MyDataBase +import com.mogo.och.sweepercloud.presenter.SweeperPresenter +import com.mogo.och.sweepercloud.ui.dialog.SweeperCloudDialog +import com.mogo.och.sweepercloud.ui.dialog.SweeperCloudLoadingDialog +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.createConfirmStartSubTaskDialog +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.createReceivedTaskInfoDialog +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.createSweeperTaskEndDialog +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.createSweeperTaskNormalEndDialog +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.printMessage +import com.mogo.och.sweepercloud.view.SweeperCurrentTaskInfoView +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.SubTaskInfo +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.TaskModel +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.confirm.SweeperTaskConfirm +import com.zhjt.mogo.adas.data.sweeper.task.stop.SweeperTaskStop +import kotlinx.android.synthetic.main.fragment_och_sweeper.* +import kotlinx.android.synthetic.main.sweeper_no_data_common_view.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +/** + * 清扫车主界面 + */ +class SweeperFragment : BaseSweeperTabFragment() { + + companion object { + const val TAG = "SweeperFragment" + } + + private var mSubMutableList: MutableList? = null + private var mCleanSystemState: ChassisStatesOuterClass.SweeperFuTianTaskSystemStates? = null + private var mLocation: MogoLocation? = null + private var mTaskInfo: SweeperTask.TaskInfo? = null + private var mSubTaskType: TaskModel = TaskModel.DEFAULT_MODEL //1:自动驾驶子任务 2:人工驾驶子任务 -1:未知任务类型 + private var mCurrentSubTaskInfo: SubTaskInfo? = null//当前正在执行的子任务 + private val mLoadingDialog: SweeperCloudLoadingDialog by lazy { SweeperCloudLoadingDialog(requireContext()) } + private var mDialog: SweeperCloudDialog? = null + + override fun getTagName(): String { + return "SweepersFragment" + } + + override fun initViews() { + super.initViews() + initListener() + sweeper_cl_work_mode.setTrafficDataView(trafficDataView) + } + + override fun createPresenter(): SweeperPresenter { + return SweeperPresenter(this) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + mPresenter?.getCurrentTask() + } + + override fun getTaskListPanelViewId(): Int { + return R.layout.fragment_och_sweeper + } + + /** + * 设置当前任务信息列表是否显示 + */ + private fun setShowCurrentTaskPanelView(isShow: Boolean) { + if (isShow) { + sweeper_current_task_view.visibility = View.VISIBLE + noTaskDataView.visibility = View.GONE + } else { + sweeper_current_task_view.visibility = View.GONE + noTaskDataView.visibility = View.VISIBLE + } + } + + /** + * VR模式切换 + * + * @param isVRMode + */ + fun onVRModeChanged(isVRMode: Boolean) { + if (mRootView != null) { + mRootView.visibility = if (isVRMode) View.VISIBLE else View.GONE + } + } + + fun hideOchSweeper() {} + + /** + * 设置各种监听事件 + */ + private fun initListener() { + getCurrentView().getAutoBtn().setOnClickListener { + //前置条件 (1)必须处于人工驾驶状态 (2)必须有正在执行的子任务,且子任务类型为自动驾驶子任务 才能请求云端进入自驾 + mCurrentSubTaskInfo?.let { + if (mPresenter?.autopilotState == STATUS_AUTOPILOT_ENABLE && it.taskModel == TaskModel.AUTO) { + mLoadingDialog.showLoading() + mPresenter?.sendSweeperAutopilotBootable(mTaskInfo?.taskId, it.subTaskId, it.lineId.toLong()) + } + } + } + } + + fun onSweeperFutianCleanSystemState(cleanSystemState: ChassisStatesOuterClass.SweeperFuTianTaskSystemStates) { + mCleanSystemState = cleanSystemState + sweeper_cl_work_mode.setSweeperFutianCleanSystemState(mSubTaskType, cleanSystemState) + } + + /** + * 当前位置经纬度 + */ + fun setCurrentLocation(location: MogoLocation) { + this.mLocation = location + } + + /** + * 大任务中所有子任务起终点集合 + */ + private fun addTaskData() { + lifecycleScope.launch(Dispatchers.IO) { + mSubMutableList?.let { subList -> + if (subList.size <= 0) { + return@launch + } + val dataList = ArrayList() + for (index in subList.indices) { + val startLocation = subList[index].startLocation + val startLatLng = LatLng(startLocation.latitude, startLocation.longitude) + dataList.add(index, startLatLng) + val endLocation = subList[index].endLocation + val endLatLng = LatLng(endLocation.latitude, endLocation.longitude) + dataList.add(index + 1, endLatLng) + } + setTaskListCoordinatesLatLng(dataList) + } + } + } + + /** + * 设置当前子任务终点 + */ + private fun setEndStationMarker(position: Int) { + lifecycleScope.launch(Dispatchers.IO) { + mSubMutableList?.let { subList -> + val endPoint = subList[position - 1].endLocation + val endLatLng = LatLng(endPoint.latitude, endPoint.longitude) + super.mCurrentTaskEndStation = endLatLng + setCurrentTaskEndMarker(endLatLng) + } + } + } + + /** + * 设置云端任务信息 + */ + fun onSweeperCloudTask(messageType: SweeperCloudTask.MessageType, taskInfo: SweeperTask.TaskInfo?) { + this.mTaskInfo = taskInfo + this.mSubMutableList = taskInfo?.subListList + CallerLogger.d(SceneConstant.M_SWEEPER + TAG, taskInfo?.let { printMessage(it) }) + if (taskInfo == null || this.mSubMutableList == null) { + resetTaskInfoPanel() + return + } + //主动拉取云端正在执行的任务,有则直接在任务列表展示 + if (messageType == SweeperCloudTask.MessageType.PadSendGetTaskReq) { + getCurrentView().setData(taskInfo, getCurrentPosition()) + setShowCurrentTaskPanelView(true) + addTaskData() + mPresenter?.isHasTaskInfo(true) + } else {//云端下发的任务信息需要弹窗接取 + if (taskInfo.isPop) {//是否需要弹窗确认 + receivedTaskInfoDialog() + } else { + mPresenter?.sendSweeperStartTaskResp(taskInfo.taskId, SweeperTask.StartTaskCode.RECEIVED) + setShowCurrentTaskPanelView(true) + getCurrentView().setData(taskInfo) + addTaskData() + mPresenter?.isHasTaskInfo(true) + //延时2秒再上报确认接取任务,防止时间太短跟收到任务指令冲突 + UiThreadHandler.postDelayed({ mPresenter?.sendSweeperStartTaskResp(taskInfo.taskId, SweeperTask.StartTaskCode.MANUAL_CONFIRM) }, 2000) + } + //设置任务进度 + this.mSubMutableList?.let { + setTaskProgress("0/${it.size}") + } + } + } + + /** + * 根据云端同步的子任务状态,更新列表中任务状态 + */ + fun onSweeperUpdateSubTaskStatus(taskId: String, subTaskId: String, subTaskStatus: SweeperCommon.TaskStatus) { + mLoadingDialog.hideLoading() + updateSubTaskInfo(taskId, subTaskId, subTaskStatus) + } + + /** + * 子任务确认时,更新子任务信息 + */ + private fun updateSubTaskInfo(taskId: String, subTaskId: String, subTaskStatus: SweeperCommon.TaskStatus) { + mTaskInfo?.let { + //如果云端要更新的任务和本地缓存任务不是同一个,在无法更新子任务状态 + if (taskId != it.taskId) { + return + } + mSubMutableList?.let { subTaskList -> + for (index in 0 until subTaskList.size) { + if (subTaskList[index].subTaskId == subTaskId) { + val subBuilder = subTaskList[index].toBuilder() + subBuilder.taskStatus = subTaskStatus + if (subTaskStatus == SweeperCommon.TaskStatus.RUNNING) { + mCurrentSubTaskInfo = subBuilder.build() + //更新当前正在执行的任务状态 + updateCurrentSubTaskInfo(index + 1) + } else { + mCurrentSubTaskInfo = null + } + //判断是否结束子任务 + if (subTaskStatus == SweeperCommon.TaskStatus.FINISHED) { + //已完成的计入任务进度,未完成的不计入 + ToastUtils.showLong("任务完成") + showNotice("任务完成") + } + val builder = it.toBuilder() + builder.setSubList(index, subBuilder.build()) + mTaskInfo = builder.build() + mSubMutableList = mTaskInfo?.subListList + getCurrentView().setData(mTaskInfo, index) + } + } + } + } + } + + /** + * 云端请求结束大任务 + */ + fun onSweeperCloudTaskStop(taskId: String, stopTaskType: SweeperTaskStop.StopTaskType, isPop: Boolean) { + mTaskInfo?.let { + //如果云端要更新的任务和本地缓存任务不是同一个,在无法结束任务 + if (taskId != it.taskId) { + return + } + if (isPop) { + sweeperCloudTaskStopDialog(taskId, stopTaskType, it) + } else { + mPresenter?.sendSweeperStopTaskResp(taskId, SweeperTaskStop.StopTaskCode.MANUAL_CONFIRM) + } + } + + } + + /** + * 结束任务弹窗处理 + */ + private fun sweeperCloudTaskStopDialog(taskId: String, stopTaskType: SweeperTaskStop.StopTaskType, taskInfo: SweeperTask.TaskInfo) { + mLoadingDialog.hideLoading() + val timeout: String = getTimeSpent(taskInfo.taskEndTime) + //数据重复导致连续弹窗 + if (mDialog != null && mDialog!!.isShowing) { + return + } + if (stopTaskType == SweeperTaskStop.StopTaskType.NORMAL) { + mPresenter?.isHasTaskInfo(false) + mDialog = sweeperCloudTaskNormalEndDialog() + showNotice("任务已结束") + } else { + mDialog = createSweeperTaskEndDialog(context, object : SweeperCloudDialogClickListener { + override fun onConfirm() { + mPresenter?.sendSweeperStopTaskResp(taskId, SweeperTaskStop.StopTaskCode.MANUAL_CONFIRM) + mLoadingDialog.showLoading() + //ToastUtils.showLong("确认") + } + + override fun onRefuseOrEnd() { + mPresenter?.sendSweeperStopTaskResp(taskId, SweeperTaskStop.StopTaskCode.MANUAL_REFUSE) + mLoadingDialog.showLoading() + //ToastUtils.showLong("拒绝") + } + + override fun onCountDownStop() { + mPresenter?.sendSweeperStopTaskResp(taskId, SweeperTaskStop.StopTaskCode.OVER_TIME) + mLoadingDialog.showLoading() + //ToastUtils.showLong("倒计时") + } + + override fun onNext() { + } + + }, stopTaskType, timeout) + } + mDialog?.show() + } + + /** + * 大任务结束弹窗 + */ + private fun sweeperCloudTaskNormalEndDialog(): SweeperCloudDialog? { + return createSweeperTaskNormalEndDialog(context, object : SweeperCloudDialogClickListener { + override fun onConfirm() { + ToastUtils.showLong("任务已结束") + resetTaskInfoPanel() + } + + override fun onRefuseOrEnd() { + + } + + override fun onCountDownStop() { + ToastUtils.showLong("任务已结束") + resetTaskInfoPanel() + } + + override fun onNext() { + + } + + }) + } + + /** + * 云端同步大任务状态 + */ + fun onSweeperCloudBigTaskStatus(taskId: String, subTaskStatus: SweeperBigTaskStatus.BigTaskStatus) { + //隐藏loading + mLoadingDialog.hideLoading() + mTaskInfo?.let { + //如果云端要更新的任务和本地缓存任务不是同一个,在无法进行任务列表状态更新 + if (it.taskId != taskId) { + return + } + //大任务处于取消状态 异常状态pad端都显示无任务列表 + if (subTaskStatus == SweeperBigTaskStatus.BigTaskStatus.CANCLE || subTaskStatus == SweeperBigTaskStatus.BigTaskStatus.ABNORMAL || subTaskStatus == SweeperBigTaskStatus.BigTaskStatus.FINISHED) { + mPresenter?.isHasTaskInfo(false) + //数据重复导致连续弹窗 + if (mDialog != null && mDialog!!.isShowing) { + return + } + mDialog = sweeperCloudTaskNormalEndDialog() + mDialog?.show() + showNotice("任务已结束") + } + } + } + + /** + * pad请求云端进入自动驾驶回调 + */ + fun onSweeperCloudAutopilotBootable(taskId: String, subTaskId: String, isBootableResp: SweeperBootable.IsBootableResp) { + mLoadingDialog.hideLoading() + //如果云端要更新的任务和本地缓存任务不是同一个,在无法进行任务列表状态更新 + mTaskInfo?.let { + if (it.taskId != taskId) { + return + } + if (isBootableResp.code == SweeperCommon.Code.SUCCEED) { + ToastUtils.showLong("上报云控成功") + } else { + ToastUtils.showLong("上报云控失败") + } + } + } + + /** + * 重置任务面板为无数据状态 + */ + private fun resetTaskInfoPanel() { + //清除任务缓存数据 + mPresenter?.clearRouteList() + lifecycleScope.launch(Dispatchers.IO) { + //清除任务地图绘制标记和作业路线 + clearAllMarkerAndPolyline() + //清除贴边数据缓存 + MyDataBase.getInstance().weltDataDao.deleteAllWeltData() + } + setShowCurrentTaskPanelView(false) + mTaskInfo = null + mCurrentSubTaskInfo = null + mSubMutableList = null + mSubTaskType = TaskModel.DEFAULT_MODEL + setTaskProgress("0") + } + + /** + * + * 获取当前正在执行的子任务在列表中的位置 + */ + private fun getCurrentPosition(): Int { + mSubMutableList = mTaskInfo?.subListList + mSubMutableList?.apply { + for (index in 0 until size) { + if (get(index).taskStatus == SweeperCommon.TaskStatus.RUNNING) { + mCurrentSubTaskInfo = get(index) + updateCurrentSubTaskInfo(index + 1) + return index + } + } + } + return -1 + } + + /** + * 根据子任务id获取子任务信息 + */ + private fun bySubTaskIdFindSubTaskInfo(subTaskId: String): SubTaskInfo? { + mSubMutableList = mTaskInfo?.subListList + mSubMutableList?.apply { + for (index in 0 until size) { + if (get(index).subTaskId == subTaskId) { + return get(index) + } + } + } + return null + } + + /** + * 更新当前子任务信息 + */ + private fun updateCurrentSubTaskInfo(position: Int) { + mCurrentSubTaskInfo?.let { + mSubTaskType = it.taskModel + mPresenter?.setSubtask(it.subTaskId, it.taskModel, it.lineId) + setEndStationMarker(position) + //设置任务进度 + this.mSubMutableList?.apply { + setTaskProgress("${position}/${size}") + } + } + } + + /** + * 设置路线轨迹 + */ + override fun setTaskRouteList(routeList: ArrayList) { + super.setTaskRouteList(routeList) + } + + private fun getCurrentView(): SweeperCurrentTaskInfoView = sweeper_current_task_view + + + fun handleSubTaskInfoDialog(taskId: String, subTaskId: String, isPop: Boolean) { + if (mTaskInfo == null) return + if (mTaskInfo?.taskId != taskId) return + val subInfo = bySubTaskIdFindSubTaskInfo(subTaskId) + subInfo?.let { + if (isPop) { + showSubTaskInfoDialog(taskId, subTaskId, it) + } else { + mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_CONFIRM) + //mPresenter?.setPreLineId(-1) + updateSubTaskInfo(taskId, subTaskId, SweeperCommon.TaskStatus.RUNNING) + } + } + } + + /** + * 云控下发子任务确认弹窗 + */ + private fun showSubTaskInfoDialog(taskId: String, subTaskId: String, subTaskInfo: SubTaskInfo) { + mLoadingDialog.hideLoading() + if (mTaskInfo == null) return + if (mTaskInfo?.taskId != taskId) return + //数据重复导致连续弹窗 + if (mDialog != null && mDialog!!.isShowing) { + return + } + mDialog = createConfirmStartSubTaskDialog(context, object : SweeperCloudDialogClickListener { + override fun onConfirm() { + //ToastUtils.showLong("确认") + mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_CONFIRM) + //mPresenter?.setPreLineId(-1) + updateSubTaskInfo(taskId, subTaskId, SweeperCommon.TaskStatus.RUNNING) + mLoadingDialog.showLoading() + } + + override fun onRefuseOrEnd() { + //ToastUtils.showLong("结束") + mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_REFUSE_ALL) + mLoadingDialog.showLoading() + } + + override fun onCountDownStop() { + //ToastUtils.showLong("倒计时结束") + mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.OVER_TIME) + mLoadingDialog.showLoading() + } + + override fun onNext() { + //ToastUtils.showLong("下一个") + mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_REFUSE_SINGLE) + mLoadingDialog.showLoading() + } + + }, subTaskInfo) + mDialog?.show() + showNotice("请确认是否执行任务") + } + + /** + * 接取云端任务弹窗 + */ + private fun receivedTaskInfoDialog() { + mTaskInfo?.let { + mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.RECEIVED) + //数据重复导致连续弹窗 + if (mDialog != null && mDialog!!.isShowing) { + return + } + mDialog = createReceivedTaskInfoDialog(context, object : SweeperCloudDialogClickListener { + override fun onConfirm() { + //ToastUtils.showLong("确认") + mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.MANUAL_CONFIRM) + setShowCurrentTaskPanelView(true) + getCurrentView().setData(it) + mLoadingDialog.showLoading() + addTaskData() + mPresenter?.isHasTaskInfo(true) + } + + override fun onRefuseOrEnd() { + //ToastUtils.showLong("拒绝") + mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.MANUAL_REFUSE) + mLoadingDialog.showLoading() + resetTaskInfoPanel() + } + + override fun onCountDownStop() { + //ToastUtils.showLong("倒计时结束") + resetTaskInfoPanel() + mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.OVER_TIME) + mLoadingDialog.showLoading() + } + + override fun onNext() { + + } + + }, it) + mDialog?.show() + showNotice("请确认是否接取任务") + } + + } + + /** + * 计算任务超时时间 + */ + private fun getTimeSpent(taskEndTime: Long): String { + + val timeLag: Long = System.currentTimeMillis() - taskEndTime + //天 + val day: Long = timeLag / (24 * 60 * 60 * 1000) + //小时 + val hour = (timeLag / (60 * 60 * 1000) - day * 24) + //分钟 + val minute = ((timeLag / (60 * 1000)) - day * 24 * 60 - hour * 60) + + if (day >= 1) { + return "${day}天${hour}时${minute}分钟" + } + if (hour >= 1) { + return "${hour}时${minute}分钟" + } + return "${minute}分钟" + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/WeltMapOverViewFragment.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/WeltMapOverViewFragment.kt new file mode 100644 index 0000000000..de471c94b8 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/fragment/WeltMapOverViewFragment.kt @@ -0,0 +1,129 @@ +package com.mogo.och.sweepercloud.fragment + +import android.os.Bundle +import com.amap.api.maps.model.LatLng +import com.mogo.commons.mvp.BaseFragment +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.callback.ISweeperTaskDataToFragmentCallback +import com.mogo.och.sweepercloud.callback.IWeltMapSwitchToSmallCallback +import com.mogo.och.sweepercloud.database.bean.WeltDataBean +import kotlinx.android.synthetic.main.fragment_welt_map_overview.* +import kotlinx.android.synthetic.main.sweeper_welt_map_overview.* + +/** + * 作业任务全览图 + */ +class WeltMapOverViewFragment : BaseFragment(), ISweeperTaskDataToFragmentCallback { + private var mIWeltMapSwitchToSmallCallBack: IWeltMapSwitchToSmallCallback? = null + private var mFragment: SweeperFragment? = null + override fun getLayoutId(): Int = R.layout.fragment_welt_map_overview + override fun getTagName(): String { + return "WeltMapOverViewFragment" + } + + override fun initViews() { + + } + fun setWeltMapSwitchToSmallCallBack(iWeltMapSwitchToSmallCallback: IWeltMapSwitchToSmallCallback){ + this.mIWeltMapSwitchToSmallCallBack=iWeltMapSwitchToSmallCallback + } + fun setSweeperFragment(fragment: SweeperFragment){ + this.mFragment=fragment + mFragment?.setTaskDataToFragmentCallback(this) + } + override fun initViews(savedInstanceState: Bundle?) { + super.initViews(savedInstanceState) + weltMapOverView?.onCreateView(savedInstanceState) + sweeperSwitchToSmall.setOnClickListener { + mIWeltMapSwitchToSmallCallBack?.onWeltMapSwitchToSmall() + } + val bundle = arguments + if (bundle != null) { + val latLngs = bundle.getSerializable("subTaskCoordinates") as? ArrayList + val latLng = bundle.getParcelable("subTaskEndCoordinates") + val weltDataList = bundle.getSerializable("weltDataList") as? ArrayList + val routeList = bundle.getSerializable("routeList") as? ArrayList + val progress = bundle.getString("progress") + routeList?.let { + weltMapOverView?.setRouteList(it) + } + latLng?.let { + setCurrentTaskCoordinatesLatLng(it) + } + latLngs?.let { + setTaskListCoordinatesLatLng(it) + } + weltDataList?.let { + setWeltData(it,"0.0cm") + } + progress?.let { + weltMapOverView?.setProgress(progress) + } + } + + } + + companion object { + @JvmStatic + fun newInstance( + mIWeltMapSwitchToSmallCallBack: IWeltMapSwitchToSmallCallback, + mCurrentTaskEndStation:LatLng?, + weltDataList: ArrayList?, + latLngs: ArrayList?, + routeList: ArrayList?, + progress:String?, + sweeperFragment: SweeperFragment + ): WeltMapOverViewFragment { + val args = Bundle() + args.putSerializable("weltDataList", weltDataList) + args.putSerializable("subTaskCoordinates", latLngs) + args.putParcelable("subTaskEndCoordinates", mCurrentTaskEndStation) + args.putSerializable("routeList", routeList) + args.putString("progress", progress) + val fragment = WeltMapOverViewFragment() + fragment.setWeltMapSwitchToSmallCallBack(mIWeltMapSwitchToSmallCallBack) + fragment.setSweeperFragment(sweeperFragment) + fragment.arguments = args + return fragment + } + } + + override fun onPause() { + super.onPause() + weltMapOverView?.onPause() + } + + override fun onResume() { + super.onResume() + weltMapOverView?.onResume() + } + + override fun onDestroy() { + super.onDestroy() + weltMapOverView?.onDestroy() + } + override fun setTaskListCoordinatesLatLng(coordinatesLatLng: java.util.ArrayList) { + weltMapOverView?.setTaskListCoordinatesLatLng(coordinatesLatLng) + } + + override fun setCurrentTaskCoordinatesLatLng(coordinatesLatLng: LatLng) { + weltMapOverView?.setCurrentTaskCoordinatesLatLng(coordinatesLatLng) + } + + override fun clearAllMarkerAndPolyline() { + weltMapOverView?.clearAllMarkerAndPolyline() + } + + override fun setProgress(progress: String) { + weltMapOverView?.setProgress(progress) + } + + override fun setRouteList(routeList: java.util.ArrayList) { + weltMapOverView?.setRouteList(routeList) + } + + override fun setWeltData(weltDatas: java.util.ArrayList?, distance: String) { + weltMapOverView?.setWeltData(weltDatas,true,distance) + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/model/SweeperTaskModel.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/model/SweeperTaskModel.java new file mode 100644 index 0000000000..fd3b224b17 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/model/SweeperTaskModel.java @@ -0,0 +1,672 @@ +package com.mogo.och.sweepercloud.model; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_SWEEPER; +import static com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils.printMessage; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.amap.api.maps.model.LatLng; +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; +import com.mogo.commons.AbsMogoApplication; +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.data.autopilot.AutopilotStatusInfo; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoSweeperFutianCleanSystemListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoSweeperFutianCloudTaskListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerSweeperFutianCleanSystemListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerSweeperFutianCloudTaskListenerManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; +import com.mogo.och.common.module.utils.NumberFormatUtil; +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweepercloud.callback.ISweeperCloudTaskCallback; +import com.mogo.och.sweepercloud.callback.ISweeperControllerStatusCallback; +import com.mogo.och.sweepercloud.constant.SweeperConst; +import com.mogo.och.sweepercloud.database.MyDataBase; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.util.SweeperCloudTaskUtils; +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask; +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable; +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask; +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTaskSuspendResume; +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus; +import com.zhjt.mogo.adas.data.sweeper.task.confirm.SweeperTaskConfirm; +import com.zhjt.mogo.adas.data.sweeper.task.status.SweeperTaskStatus; +import com.zhjt.mogo.adas.data.sweeper.task.stop.SweeperTaskStop; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import chassis.ChassisStatesOuterClass; +import io.reactivex.exceptions.UndeliverableException; +import io.reactivex.functions.Consumer; +import io.reactivex.plugins.RxJavaPlugins; +import mogo.telematics.pad.MessagePad; +import mogo_msg.MogoReportMsg; +import planning.RoboSweeperTaskIndexOuterClass; +import system_master.SystemStatusInfo; + +/** + * @author congtaowang + * @since 2021/3/23 + *

+ * 清扫车任务管理 + */ +public class SweeperTaskModel implements IMoGoSweeperFutianCloudTaskListener, IMoGoAutopilotStatusListener, IMoGoSweeperFutianCleanSystemListener { + private final String TAG = SweeperTaskModel.class.getSimpleName(); + private static volatile SweeperTaskModel sInstance; + public double mLongitude = 0; + public double mLatitude = 0; + private Context mContext; + private ISweeperControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 + private ISweeperCloudTaskCallback mSweeperTaskCallback; + ArrayList points = new ArrayList<>();//全路径信息 + private SweeperTask.TaskModel mSubTaskType = SweeperTask.TaskModel.DEFAULT_MODEL; //1自动驾驶 2.人工驾驶 0:无效值 + private int mCurrentLineId = 0; //当前路线id + private int mPreLineId = -1;//上一次存储的路线id + //自动驾驶状态 + private int mAutopilotState = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; + //当前子任务id + private String mSubTaskId = ""; + // 清扫模式回调时间间隔 + private static final long VEHICLE_STATE_INTERVAL_MILLIS = 500L; + // 清扫模式当前时间戳 + private long mVehicleStateCurrentTimeMillis; + // 贴边数据回调时间间隔 + private static final long WELT_DATA_INTERVAL_MILLIS = 1000L; + // 贴边数据当前时间戳 + private long mWeltDataCurrentTimeMillis; + + // 轨迹数据回调时间间隔 + private static final long ROUTE_DATA_INTERVAL_MILLIS = 1000L; + // 轨迹数据当前时间戳 + private long mRouteDataCurrentTimeMillis; + + private String longitude;//经度 + + private String latitude;//纬度 + + private boolean isHasTaskInfo = false;//判断是否有任务数据 + + //用于对应messageType和reqNo绑定在一起,保证请求的reqNo和响应的reqNo一致 + private HashMap msgTypeAndReqNo = new HashMap<>(); + + public static SweeperTaskModel getInstance() { + if (sInstance == null) { + synchronized (SweeperTaskModel.class) { + if (sInstance == null) { + sInstance = new SweeperTaskModel(); + } + } + } + return sInstance; + } + + private SweeperTaskModel() { + + } + + public void init() { + mContext = AbsMogoApplication.getApp(); + // 定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, mMapLocationListener); + + MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + + //自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener); + + //添加清扫车云控任务回调监听 + CallerSweeperFutianCloudTaskListenerManager.INSTANCE.addListener(TAG, this); + + //自动驾驶状态监听 + CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, this); + + //清扫车模式和贴边数据回调监听 + CallerSweeperFutianCleanSystemListenerManager.INSTANCE.addListener(TAG, this); + + //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_SWEEPER + TAG, "UndeliverableException"); + } + if ((e instanceof IOException)) {// + // fine, irrelevant network problem or API that throws on cancellation + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "IOException"); + return; + } + if (e instanceof InterruptedException) { + // fine, some blocking code was interrupted by a dispose call + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "InterruptedException"); + return; + } + if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) { + // that's likely a bug in the application + CallerLogger.INSTANCE.d(M_SWEEPER + 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_SWEEPER + TAG, "IllegalStateException"); + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + return; + } + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "Undeliverable exception"); + } + }); + } + + + public void setControllerStatusCallback(ISweeperControllerStatusCallback callback) { + this.mControllerStatusCallback = callback; + } + + public void setSweeperTaskCallback(ISweeperCloudTaskCallback callback) { + this.mSweeperTaskCallback = callback; + } + + private final IMoGoPlanningRottingListener moGoAutopilotPlanningListener = new IMoGoPlanningRottingListener() { + + @Override + public void onAutopilotRotting(MessagePad.GlobalPathResp routeList) { + if (null != routeList && routeList.getWayPointsList() != null && routeList.getWayPointsList().size() > 0) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotRotting: " + printMessage(routeList)); + + // MAP返回路线信息,在1秒内返回了2次,这里加上数据过滤 + long current = System.currentTimeMillis(); + if (current - mRouteDataCurrentTimeMillis <= ROUTE_DATA_INTERVAL_MILLIS) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotRotting: interval <=" + ROUTE_DATA_INTERVAL_MILLIS + " data is abandon"); + return; + } + mRouteDataCurrentTimeMillis = current; + + if (mCurrentLineId != mPreLineId) {//判断是否同一条路线 + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotRotting: mCurrentLineId" + mCurrentLineId + "mPreLineId:" + mPreLineId); + mPreLineId = mCurrentLineId; + points.addAll(coordinateConverterWgsToGcjList(mContext, routeList.getWayPointsList())); + if (mSweeperTaskCallback != null) { + mSweeperTaskCallback.setRouteList(points); + } + } + } + } + + }; + + public void setSubtask(String subTaskId, SweeperTask.TaskModel subTaskType, int currentLineId) { + this.mSubTaskId = subTaskId; + this.mSubTaskType = subTaskType; + this.mCurrentLineId = currentLineId; + } + + /** + * 清除路线缓存数据 + */ + public void clearRouteList() { + points.clear(); + mSubTaskType = SweeperTask.TaskModel.UNRECOGNIZED; + mCurrentLineId = 0; + mPreLineId = -1; + } + + /** + * 重新设置上一次的lineId,防止同一个轨迹,同一个lineid时不绘制轨迹 + */ + public void setPreLineId(int preLineId) { + this.mPreLineId = preLineId; + } + + /** + * 判断是否有任务数据 + */ + public void isHasTaskInfo(boolean isHasTaskInfo) { + this.isHasTaskInfo = isHasTaskInfo; + } + + /** + * 获取自动开始状态 + */ + public int getAutopilotState() { + return this.mAutopilotState; + } + + 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 release() { + MogoStatusManager.getInstance().unregisterStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + // 注销定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); + //自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); + OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null); + } + + 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 IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() { + @Override + public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { + if (null == gnssInfo) return; + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onCarLocationChanged(gnssInfo); + } + if (mSubTaskType == SweeperTask.TaskModel.MANUAL) {//收集人工驾驶子任务坐标点 + addCoordinates(gnssInfo); + return; + } + } + }; + + /** + * 根据当前定位收集人工驾驶子任务轨迹点 + * + * @param mogoLatLng + */ + private void addCoordinates(MogoLocation mogoLatLng) { + String tempLongitude = NumberFormatUtil.cutOutNumber(mogoLatLng.getLongitude(), 5); + String tempLatitude = NumberFormatUtil.cutOutNumber(mogoLatLng.getLatitude(), 5); + //用于过滤车是否停在原地,经纬度相同的情况 + if (!tempLongitude.equals(mLongitude) && !tempLatitude.equals(mLatitude)) { + mLongitude = mogoLatLng.getLongitude(); + mLatitude = mogoLatLng.getLatitude(); + SweeperRoutePlanningUpdateReqBean.Result result = new SweeperRoutePlanningUpdateReqBean.Result(); + result.latitude = mogoLatLng.getLatitude(); + result.longitude = mogoLatLng.getLongitude(); + points.add(result); + if (mSweeperTaskCallback != null) { + mSweeperTaskCallback.setRouteList(points); + } + } + } + + @Override + public void onSweeperFutianCloudTask(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperTask.TaskInfo taskInfo) { + + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " onSweeperFutianCloudTask:" + (taskInfo == null ? "null" : printMessage(taskInfo)) + " mSweeperTaskCallback:" + mSweeperTaskCallback); + if (mSweeperTaskCallback != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudTask(messageType, taskInfo); + } + } + + @Override + public void onSweeperFutianCloudTaskConfirm(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperTaskConfirm.TaskConfirm taskConfirm) { + + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudTaskConfirm:" + printMessage(taskConfirm)); + if (mSweeperTaskCallback != null && taskConfirm != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudTaskConfirm(taskConfirm.getTaskId(), taskConfirm.getSubTaskId(), taskConfirm.getIsPop()); + } + } + + @Override + public void onSweeperFutianCloudTaskStatus(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperTaskStatus.TaskStatusPush taskStatusPush) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudTaskStatus:" + printMessage(taskStatusPush)); + if (mSweeperTaskCallback != null && taskStatusPush != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudTaskStatus(taskStatusPush.getTaskId(), taskStatusPush.getSubTaskId(), taskStatusPush.getTaskStatus()); + } + } + + @Override + public void onSweeperFutianCloudTaskStop(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperTaskStop.StopTaskReq stopTaskReq) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudTaskStop:" + printMessage(stopTaskReq)); + if (mSweeperTaskCallback != null && stopTaskReq != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudTaskStop(stopTaskReq.getTaskId(), stopTaskReq.getType(), stopTaskReq.getIsPop()); + } + } + + @Override + public void onSweeperFutianCloudTaskSuspendResume(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperTaskSuspendResume.SuspendResumeTaskResp suspendResumeTaskResp) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudTaskSuspendResume:" + printMessage(suspendResumeTaskResp)); + if (mSweeperTaskCallback != null && suspendResumeTaskResp != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudTaskSuspendResume(messageType, suspendResumeTaskResp.getTaskId(), + suspendResumeTaskResp.getSubTaskId(), suspendResumeTaskResp.getCode()); + } + } + + @Override + public void onSweeperFutianCloudBootable(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperBootable.IsBootableResp isBootableResp) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudBootable:" + printMessage(isBootableResp)); + if (mSweeperTaskCallback != null && isBootableResp != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudBootable(isBootableResp.getTaskId(), isBootableResp.getSubTaskId(), isBootableResp); + } + } + + @Override + public void onSweeperFutianCloudBigTaskStatus(@NonNull SweeperCloudTask.MessageType messageType, String reqNo, long sysTime, + SweeperBigTaskStatus.BigTaskStatusPush bigTaskStatusPush) { + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "messageType: " + messageType.getNumber() + " sysTime:" + sysTime + " reqNo:" + reqNo + " " + + "onSweeperFutianCloudBigTaskStatus:" + printMessage(bigTaskStatusPush)); + if (mSweeperTaskCallback != null && bigTaskStatusPush != null) { + msgTypeAndReqNo.put(messageType.getNumber(), reqNo); + mSweeperTaskCallback.onSweeperCloudBigTaskStatus(bigTaskStatusPush.getTaskId(), bigTaskStatusPush.getTaskStatus()); + } + } + + @Override + public void onSweeperFutianCleanSystemState(@NonNull ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState) { + if (cleanSystemState == null) { + return; + } + long current = System.currentTimeMillis(); + if (current - mVehicleStateCurrentTimeMillis <= VEHICLE_STATE_INTERVAL_MILLIS) { + return; + } + mVehicleStateCurrentTimeMillis = current; + // CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onSweeperFutianCleanSystemState:" + printMessage(cleanSystemState)); + if (mSweeperTaskCallback != null) { + mSweeperTaskCallback.onSweeperFutianCleanSystemState(cleanSystemState); + } + } + + @Override + public void onSweeperFutianTaskIndexData(@NonNull RoboSweeperTaskIndexOuterClass.RoboSweeperTaskIndex roboSweeperTaskIndex) { + if (roboSweeperTaskIndex == null) { + return; + } + + long current = System.currentTimeMillis(); + if (current - mWeltDataCurrentTimeMillis <= WELT_DATA_INTERVAL_MILLIS) { + return; + } + mWeltDataCurrentTimeMillis = current; + + //没有任务数据时,不处理贴边 + if (!isHasTaskInfo) { + return; + } + + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "mSubTaskType:" + mSubTaskType + "+ onSweeperFutianTaskIndexData:" + printMessage(roboSweeperTaskIndex)); + handleWeltData(roboSweeperTaskIndex); + } + + /** + * 贴边数据处理 + */ + private void handleWeltData(RoboSweeperTaskIndexOuterClass.RoboSweeperTaskIndex roboSweeperTaskIndex) { + String tempLongitude = NumberFormatUtil.cutOutNumber(roboSweeperTaskIndex.getLocLon(), 6); + String tempLatitude = NumberFormatUtil.cutOutNumber(roboSweeperTaskIndex.getLocLat(), 6); + //用于过滤车是否停在原地,经纬度相同的情况 + if (!tempLongitude.equals(longitude) && !tempLatitude.equals(latitude)) { + latitude = NumberFormatUtil.cutOutNumber(roboSweeperTaskIndex.getLocLat(), 6); + longitude = NumberFormatUtil.cutOutNumber(roboSweeperTaskIndex.getLocLon(), 6); + //保存贴边数据到数据库中 + WeltDataBean weltDataBean = new WeltDataBean(); + //把wgs坐标系坐标转换成gcj坐标 + LatLng latLng = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj(AbsMogoApplication.getApp(), roboSweeperTaskIndex.getLocLon(), + roboSweeperTaskIndex.getLocLat()); + weltDataBean.setLocLon(latLng.longitude); + weltDataBean.setLocLat(latLng.latitude); + int edgeCleanState = roboSweeperTaskIndex.getEdgeCleanState(); + if (edgeCleanState == 0 || + (mSubTaskType == SweeperTask.TaskModel.MANUAL)) { + //人工子任务 当前因为云控需求时MAP不能获取任务状态,在人工子任务时还是返回的上一个任务的贴边数据 + // 所以 20230529 暂时过滤掉,待后面MAP修改后这里可删除,这里人工子任务默认都是非贴边 + weltDataBean.setWeltDistance(SweeperConst.NONWELT); + } else { + weltDataBean.setWeltDistance(roboSweeperTaskIndex.getDistToRefEdgePoint()); + } + weltDataBean.setCleanMode(roboSweeperTaskIndex.getCleanMode()); + weltDataBean.setCleanDirection(roboSweeperTaskIndex.getCleanDirection()); + weltDataBean.setCleanIntensity(roboSweeperTaskIndex.getCleanIntensity()); + weltDataBean.setSubTaskId(mSubTaskId); + MyDataBase.getInstance().getWeltDataDao().insert(weltDataBean); + String distance; + if (roboSweeperTaskIndex.getDistToRefEdgePoint() >= 1.0) {//大于等于1m + distance = format(roboSweeperTaskIndex.getDistToRefEdgePoint()) + "m"; + } else {//小于1m + distance = Math.round(roboSweeperTaskIndex.getDistToRefEdgePoint() * 100) + "cm";//m->cm 四舍五入到整数 + } + if (mSweeperTaskCallback != null) { + mSweeperTaskCallback.setWeltDataToMap((ArrayList) MyDataBase.getInstance().getWeltDataDao().loadAllWeltDataInfo(), + true, distance); + } + } + } + + public static String format(double value) { + BigDecimal bd = new BigDecimal(value); + bd = bd.setScale(2, RoundingMode.HALF_UP); + return bd.toString(); + } + + /** + * 获取当前正在执行的任务 + */ + public void getCurrentTask() { + SweeperTask.GetTaskReq.Builder builder = SweeperTask.GetTaskReq.newBuilder(); + builder.setSn(getDriverSn()); + String reqNo = SweeperCloudTaskUtils.getRequestId(); + SweeperTask.GetTaskReq getTaskReq = builder.build(); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "getCurrentTask:" + printMessage(getTaskReq) + " reqNo:" + reqNo + " messageType:" + SweeperCloudTask.MessageType.PadSendGetTaskReq.getNumber()); + getAutoPilotControlManager().sendSweeperGetTaskReq(reqNo, getTaskReq); + } + + /** + * 接取任务响应 + */ + public void sendSweeperStartTaskResp(String taskId, SweeperTask.StartTaskCode code) { + SweeperTask.StartTaskResp.Builder builder = SweeperTask.StartTaskResp.newBuilder(); + builder.setSn(getDriverSn()); + builder.setTaskId(taskId); + builder.setCode(code); + SweeperTask.StartTaskResp startTaskResp = builder.build(); + String reqNo = msgTypeAndReqNo.get(SweeperCloudTask.MessageType.CloudPushTask.getNumber()); + getAutoPilotControlManager().sendSweeperStartTaskResp(reqNo, startTaskResp); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "sendSweeperStartTaskResp:" + printMessage(startTaskResp) + " reqNo:" + reqNo + " messageType:" + SweeperCloudTask.MessageType.CloudPushTask.getNumber()); + } + + /** + * 子任务开始确认 + */ + public void sendSweeperTaskConfirmResp(String taskId, String subTaskId, SweeperTaskConfirm.TaskConfirmCode code) { + SweeperTaskConfirm.TaskConfirmResp.Builder builder = SweeperTaskConfirm.TaskConfirmResp.newBuilder(); + builder.setSn(getDriverSn()); + builder.setTaskId(taskId); + builder.setSubTaskId(subTaskId); + builder.setCode(code); + SweeperTaskConfirm.TaskConfirmResp taskConfirmResp = builder.build(); + String reqNo = msgTypeAndReqNo.get(SweeperCloudTask.MessageType.CloudPushTaskConfirm.getNumber()); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "sendSweeperTaskConfirmResp" + printMessage(taskConfirmResp) + " reqNo:" + reqNo + " messageType:" + SweeperCloudTask.MessageType.CloudPushTaskConfirm.getNumber()); + getAutoPilotControlManager().sendSweeperTaskConfirmResp(reqNo, taskConfirmResp); + } + + /** + * 大任务结束确认 + * + * @param taskId + * @param code + */ + public void sendSweeperStopTaskResp(String taskId, SweeperTaskStop.StopTaskCode code) { + SweeperTaskStop.StopTaskResp.Builder builder = SweeperTaskStop.StopTaskResp.newBuilder(); + builder.setSn(getDriverSn()); + builder.setTaskId(taskId); + builder.setCode(code); + SweeperTaskStop.StopTaskResp stopTaskResp = builder.build(); + String reqNo = msgTypeAndReqNo.get(SweeperCloudTask.MessageType.CloudPushTaskStop.getNumber()); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "sendSweeperStopTaskResp" + printMessage(stopTaskResp) + " reqNo:" + reqNo + " messageType:" + SweeperCloudTask.MessageType.CloudPushTaskStop.getNumber()); + getAutoPilotControlManager().sendSweeperStopTaskResp(reqNo, stopTaskResp); + } + + /** + * pad上报是否可以进自驾 + * + * @param taskId + * @param subTaskId + * @param lineId + */ + public void sendSweeperAutopilotBootable(String taskId, String subTaskId, long lineId) { + SweeperBootable.IsBootable.Builder builder = SweeperBootable.IsBootable.newBuilder(); + builder.setSn(getDriverSn()); + builder.setTaskId(taskId); + builder.setSubTaskId(subTaskId); + builder.setLineId(lineId); + SweeperBootable.IsBootable isBootable = builder.build(); + String reqNo = SweeperCloudTaskUtils.getRequestId(); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, + "sendSweeperAutopilotBootable" + printMessage(isBootable) + " reqNo:" + reqNo + " messageType:" + SweeperCloudTask.MessageType.PadSendBootable.getNumber()); + getAutoPilotControlManager().sendSweeperAutopilotBootable(reqNo, isBootable); + // TODO: 2023/5/16 + //SweeperCloudTaskUtils.mockSendCloudBootable(); + } + + public CallerAutoPilotControlManager getAutoPilotControlManager() { + return CallerAutoPilotControlManager.INSTANCE; + } + + public String getDriverSn() { + return MoGoAiCloudClientConfig.getInstance().getSn(); + } + + @Override + public void onAutopilotStatusResponse(@NonNull AutopilotStatusInfo autoPilotStatusInfo) { + //CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotStatusResponse state:" + autoPilotStatusInfo.getState()); + this.mAutopilotState = autoPilotStatusInfo.getState(); + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onAutopilotState(autoPilotStatusInfo.getState()); + } + switch (autoPilotStatusInfo.getState()) { + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE://不可自动驾驶 + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE://人工驾驶 + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING://自动驾驶中 + break; + case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING://平行驾驶 + break; + default: + break; + } + } + + @Override + public void onAutopilotArriveAtStation(@Nullable MessagePad.ArrivalNotification arrivalNotification) { + + } + + @Override + public void onAutopilotSNRequest() { + + } + + @Override + public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { + + } + + @Override + public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) { + if (status == 0x00) {//判断工控机重连后,获取当前正在执行的子任务,延时10秒,防止工控机连接上时SN为空 + UiThreadHandler.postDelayed(() -> { + getCurrentTask(); + }, 10000); + } + //CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotIpcConnectStatusChanged status:" + status + " reason:" + reason); + } + + @Override + public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { + // CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onAutopilotStatusRespByQuery status:" + status.getSysState().getNumber()); + } + + @Override + public void onAutopilotRouteLineId(long lineId) { + + } + + /** + * 云控数据异常或者工控机传递数据异常 + * + * @param bytes + */ + @Override + public void onSweeperFutianCloudTaskUnknown(@NonNull byte[] bytes) { + String string = new String(bytes, StandardCharsets.UTF_8); + CallerLogger.INSTANCE.d(M_SWEEPER + TAG, "onSweeperFutianCloudTaskUnknown:" + string); + } + + @Override + public void onAutopilotStatusResponse(int state) { + IMoGoAutopilotStatusListener.super.onAutopilotStatusResponse(state); + // TODO: 2023/6/19 bingbing + } + + @Override + public void onAutopilotDockerInfo(@NonNull String dockerVersion) { + IMoGoAutopilotStatusListener.super.onAutopilotDockerInfo(dockerVersion); + // TODO: 2023/6/19 bingbing + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/presenter/SweeperPresenter.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/presenter/SweeperPresenter.java new file mode 100644 index 0000000000..c454c5e66f --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/presenter/SweeperPresenter.java @@ -0,0 +1,228 @@ +package com.mogo.och.sweepercloud.presenter; + + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.eagle.core.function.call.autopilot.CallerSweeperFutianCleanSystemListenerManager; +import com.mogo.eagle.core.utilcode.util.ThreadUtils; +import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean; +import com.mogo.och.sweepercloud.callback.ISweeperControllerStatusCallback; +import com.mogo.och.sweepercloud.callback.ISweeperCloudTaskCallback; +import com.mogo.och.sweepercloud.callback.ISweeperTaskRouteCallback; +import com.mogo.och.sweepercloud.database.bean.WeltDataBean; +import com.mogo.och.sweepercloud.fragment.SweeperFragment; +import com.mogo.och.sweepercloud.model.SweeperTaskModel; +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask; +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable; +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon; +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask; +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus; +import com.zhjt.mogo.adas.data.sweeper.task.confirm.SweeperTaskConfirm; +import com.zhjt.mogo.adas.data.sweeper.task.stop.SweeperTaskStop; + + +import java.util.ArrayList; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import chassis.ChassisStatesOuterClass; + +/** + * 网约车小巴 + * + * @author tongchenfei + */ +public class SweeperPresenter extends Presenter + implements ISweeperControllerStatusCallback, + ISweeperCloudTaskCallback, ISweeperTaskRouteCallback { + + private static final String TAG = "SweeperPresenter"; + + public SweeperPresenter(SweeperFragment view) { + super(view); + SweeperTaskModel.getInstance().init(); + OCHAdasAbilityManager.getInstance().init(AbsMogoApplication.getApp()); + } + + @Override + public void onCreate(@NonNull LifecycleOwner owner) { + super.onCreate(owner); + initModelListener(); + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + super.onDestroy(owner); + SweeperTaskModel.getInstance().release(); + releaseListener(); + } + + public void initModelListener() { + SweeperTaskModel.getInstance().setControllerStatusCallback(this); + SweeperTaskModel.getInstance().setSweeperTaskCallback(this); + } + + public void releaseListener() { + SweeperTaskModel.getInstance().setControllerStatusCallback(null); + SweeperTaskModel.getInstance().setSweeperTaskCallback(null); + CallerSweeperFutianCleanSystemListenerManager.INSTANCE.removeListener(TAG); + } + + @Override + public void onVRModeChanged(boolean isVRMode) { + ThreadUtils.runOnUiThread(() -> mView.onVRModeChanged(isVRMode)); + } + + @Override + public void onCarLocationChanged(MogoLocation location) { + if (null != location) { + ThreadUtils.runOnUiThread(() -> mView.updateSpeedView((float) location.getGnssSpeed())); + ThreadUtils.runOnUiThread(() -> mView.setCurrentLocation(location)); + } + } + + @Override + public void onAutopilotState(int state) { + ThreadUtils.runOnUiThread(() -> mView.setAutoState(state)); + } + + /** + * 获取自动驾驶状态 + * + * @return + */ + public int getAutopilotState() { + return SweeperTaskModel.getInstance().getAutopilotState(); + } + + /** + * 清除路线缓存数据 + */ + public void clearRouteList() { + SweeperTaskModel.getInstance().clearRouteList(); + } + + /** + * 设置当前子任务信息 + */ + public void setSubtask(String subTaskId, SweeperTask.TaskModel subTaskType, int currentLineId) { + SweeperTaskModel.getInstance().setSubtask(subTaskId, subTaskType, currentLineId); + } + + /** + * 判断是否有任务数据 + */ + public void isHasTaskInfo(boolean isHasTaskInfo) { + SweeperTaskModel.getInstance().isHasTaskInfo(isHasTaskInfo); + } + + /** + * 设置上一个任务的lineId + * @param preLineId + */ + public void setPreLineId(int preLineId) { + SweeperTaskModel.getInstance().setPreLineId(preLineId); + } + + /** + * 获取当前正在执行的任务 + */ + public void getCurrentTask() { + SweeperTaskModel.getInstance().getCurrentTask(); + } + + /** + * 接取任务弹窗响应 + * + * @param taskId + * @param code + */ + public void sendSweeperStartTaskResp(String taskId, SweeperTask.StartTaskCode code) { + SweeperTaskModel.getInstance().sendSweeperStartTaskResp(taskId, code); + } + + /** + * 子任务弹窗确认 + * + * @param taskId + * @param subTaskId + * @param code + */ + public void sendSweeperTaskConfirmResp(String taskId, String subTaskId, SweeperTaskConfirm.TaskConfirmCode code) { + SweeperTaskModel.getInstance().sendSweeperTaskConfirmResp(taskId, subTaskId, code); + } + + /** + * 大任务结束弹窗确认 + * + * @param taskId + * @param code + */ + public void sendSweeperStopTaskResp(String taskId, SweeperTaskStop.StopTaskCode code) { + SweeperTaskModel.getInstance().sendSweeperStopTaskResp(taskId, code); + } + + /** + * pad上报是否可以进自驾 + * + * @param taskId + * @param subTaskId + * @param lineId + */ + public void sendSweeperAutopilotBootable(String taskId, String subTaskId, long lineId) { + SweeperTaskModel.getInstance().sendSweeperAutopilotBootable(taskId, subTaskId, lineId); + } + + @Override + public void setRouteList(@NonNull ArrayList routeList) { + mView.setTaskRouteList(routeList); + } + + @Override + public void onSweeperCloudTask(@NonNull SweeperCloudTask.MessageType messageType, SweeperTask.TaskInfo taskInfo) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperCloudTask(messageType, taskInfo)); + } + + @Override + public void onSweeperCloudTaskConfirm(@NonNull String taskId, @NonNull String subTaskId, boolean isPop) { + ThreadUtils.runOnUiThread(() -> mView.handleSubTaskInfoDialog(taskId, subTaskId, isPop)); + } + + @Override + public void onSweeperCloudTaskStatus(@NonNull String taskId, @NonNull String subTaskId, SweeperCommon.TaskStatus subTaskStatus) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperUpdateSubTaskStatus(taskId, subTaskId, subTaskStatus)); + } + + @Override + public void onSweeperCloudTaskStop(@NonNull String taskId, SweeperTaskStop.StopTaskType stopTaskType, boolean isPop) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperCloudTaskStop(taskId, stopTaskType, isPop)); + } + + @Override + public void onSweeperCloudTaskSuspendResume(@NonNull SweeperCloudTask.MessageType messageType, @NonNull String taskId, + @NonNull String subTaskId, SweeperCommon.Code code) { + + } + + @Override + public void onSweeperCloudBootable(@NonNull String taskId, @NonNull String subTaskId, SweeperBootable.IsBootableResp isBootableResp) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperCloudAutopilotBootable(taskId, subTaskId, isBootableResp)); + } + + @Override + public void onSweeperCloudBigTaskStatus(@NonNull String taskId, SweeperBigTaskStatus.BigTaskStatus subTaskStatus) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperCloudBigTaskStatus(taskId, subTaskStatus)); + } + + @Override + public void setWeltDataToMap(@NonNull ArrayList weltDataBeans, boolean isWeltData, @NonNull String distance) { + ThreadUtils.runOnUiThread(() -> mView.setWeltDataToMap(weltDataBeans, isWeltData, distance)); + } + + @Override + public void onSweeperFutianCleanSystemState(@NonNull ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState) { + ThreadUtils.runOnUiThread(() -> mView.onSweeperFutianCleanSystemState(cleanSystemState)); + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/receiver/TestSweeperBroadcastReceiver.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/receiver/TestSweeperBroadcastReceiver.java new file mode 100644 index 0000000000..29a82c69ab --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/receiver/TestSweeperBroadcastReceiver.java @@ -0,0 +1,42 @@ +package com.mogo.och.sweepercloud.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.sweepercloud.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/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/SweeperOperatePanelView.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/SweeperOperatePanelView.java new file mode 100644 index 0000000000..741b9a9e6e --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/SweeperOperatePanelView.java @@ -0,0 +1,1097 @@ +package com.mogo.och.sweepercloud.ui; + +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_BOTH_SIDE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_LEFT_SIDE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_RIGHT_SIDE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_INTENSITY_STRAND; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_INTENSITY_STRONG; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_DRAW; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_SWEEP; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_MODE_PURE_WASH; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_MODE_WASH_SWEEP; + +import android.animation.ObjectAnimator; +import android.content.Context; +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.view.animation.LinearInterpolator; +import android.widget.CheckedTextView; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; +import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.sweepercloud.R; +import com.mogo.och.sweepercloud.callback.ICleaningModeStateCallback; +import com.mogo.och.sweepercloud.constant.OperateStateEnum; +import com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil; +import com.mogo.och.sweepercloud.view.NoTouchConstraintLayout; +import com.mogo.och.sweepercloud.callback.ICleaningModeStateCallback; +import com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil; +import com.mogo.och.sweepercloud.view.NoTouchConstraintLayout; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import chassis.ChassisStatesOuterClass; +import chassis.SpecialVehicleTaskCmdOuterClass; + +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_DIRECTION_CLOSE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_MODE_CLOSE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_WORK_CLOSE; +import static com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil.CLEAN_WORK_OPEN; + +/** + * 清扫车操作面板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; + private boolean isFirst = false; + + CheckedTextView mBtnCleanWorkOpenClose;//开关 + CheckedTextView mBtnCleanModePureSweep;//纯扫 + CheckedTextView mBtnCleanModePureWash;//纯洗 + CheckedTextView mBtnCleanModeSweepWash;//洗扫 + CheckedTextView mBtnCleanModePureAbsorption;//纯吸 + CheckedTextView mBtnCleanDirectionLeftSide;//左侧 + CheckedTextView mBtnCleanDirectionRightSide;//右侧 + CheckedTextView mBtnCleanDirectionBothSide;//两侧 + CheckedTextView mBtnCleanIntensityStandard;//普通 + CheckedTextView mBtnCleanIntensityStrong;//强力 + FrameLayout mLoadingContainer;//loading container + TextView mLoadingHint;//loading 文本提示 + ImageView mLoadingView;//loading 转圈动画 + NoTouchConstraintLayout mWorkmodePanelRootView; + + // 作业模式相关操作按钮的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, SweeperFutianCmdUtil.CLEAN_MODE_PURE_SWEEP); + put(R.id.btn_clean_mode_pure_wash, SweeperFutianCmdUtil.CLEAN_MODE_PURE_WASH); + put(R.id.btn_clean_mode_sweep_wash, SweeperFutianCmdUtil.CLEAN_MODE_WASH_SWEEP); + put(R.id.btn_clean_mode_pure_absorption, SweeperFutianCmdUtil.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, SweeperFutianCmdUtil.CLEAN_DIRECTION_LEFT_SIDE); + put(R.id.btn_clean_direction_right_side, SweeperFutianCmdUtil.CLEAN_DIRECTION_RIGHT_SIDE); + put(R.id.btn_clean_direction_both_side, SweeperFutianCmdUtil.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, SweeperFutianCmdUtil.CLEAN_INTENSITY_STRAND); + put(R.id.btn_clean_intensity_strong, SweeperFutianCmdUtil.CLEAN_INTENSITY_STRONG); + } + }; + private boolean isSelectPureSweepMode = false;//用于标注是否选中纯扫 + + private ICleaningModeStateCallback cleaningModeStateCallback; + + private OperateStateEnum operateStateEnum = OperateStateEnum.SYNCING_STATUS; + + private ObjectAnimator objectAnimator; + + private static ChassisStatesOuterClass.SweeperFuTianTaskSystemStates mCurrentCleanSystemState;//当前作业模式 + + 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); + mWorkmodePanelRootView = (NoTouchConstraintLayout) findViewById(R.id.work_mode_panel_root_view); + 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); + mLoadingHint = findViewById(R.id.loading_hint); + mLoadingView = findViewById(R.id.loading_view); + 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(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState) { + boolean success = false; + if (cleanSystemState == null) { + return success; + } + if (isCloseAction) { + success = !cleanSystemState.getSecuMotWorkSts(); + } else { + success = cleanSystemState.getSecuMotWorkSts(); + } + return success; + } + + @Override + public void onCmdSuccess() { + if (isCloseAction) { + mBtnCleanWorkOpenClose.setText("打开"); + mBtnCleanWorkOpenClose.setChecked(false); + toggleCleanModeBtnsStatus(false); + toggleCleanDirectionBtnsStatus(false); + toggleCleanIntensityBtnsStatus(false); + } else { + mBtnCleanWorkOpenClose.setText("关闭"); + mBtnCleanWorkOpenClose.setChecked(true); + toggleCleanModeBtnsStatus(true); + } + hideLoadingMask(); + showCmdExecuteSuccessToast(); + } + + @Override + public void onCmdFailed() { + } + + @Override + public void onCmdTimeout() { + //按钮样式恢复原样 + if (isCloseAction) { + mBtnCleanWorkOpenClose.setText("关闭"); + mBtnCleanWorkOpenClose.setChecked(true); + } else { + mBtnCleanWorkOpenClose.setText("打开"); + mBtnCleanWorkOpenClose.setChecked(false); + } + hideLoadingMask(); + showCmdExecuteTimeoutToast(); + } + }; + if (isCloseAction) { + //关闭操作,点击时需要弹框提示确认后,关闭 + 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(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates 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 = SweeperFutianCmdUtil.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; + isSelectPureSweepMode = false; + } else if (isPureSweepClick) { + //success = clean_mode_pure_sweep; + //纯扫 这个模式实际在福田清扫车上没有这个按钮,只是发送指令给特种车端,默认此命令肯定是正确的 + success = true; + isSelectPureSweepMode = true; + } else if (isPureWashClick) { + success = clean_mode_pure_wash; + isSelectPureSweepMode = false; + } else if (isWashSweepClick) { + success = clean_mode_wash_sweep; + isSelectPureSweepMode = false; + } else if (isPureAbsorptionClick) { + success = clean_mode_pure_draw; + isSelectPureSweepMode = false; + } + return success; + } + + @Override + public void onCmdSuccess() { + ((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() { + ((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(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates 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() { + ((CheckedTextView) currentClickView).setChecked(!isClickCurrentChoosedDirectionBtn); + toggleCleanDirectionBtnsByChoosedViewId(currentClickView.getId(), isClickCurrentChoosedDirectionBtn); + if (isClickCurrentChoosedDirectionBtn) { + toggleCleanIntensityBtnsStatus(false); + } else { + toggleCleanIntensityBtnsStatus(true); + // 一并设置作业强度为标准 + setCleanIntensityStandard(); + } + hideLoadingMask(); + showCmdExecuteSuccessToast(); + } + + @Override + public void onCmdFailed() { + } + + @Override + public void onCmdTimeout() { + ((CheckedTextView) currentClickView).setChecked(isClickCurrentChoosedDirectionBtn); + hideLoadingMask(); + showCmdExecuteTimeoutToast(); + } + }; + if (isClickCurrentChoosedDirectionBtn) { + //当前已选择模式的按钮,取消当前模式,重置作业强度为标准,并置灰作业强度按钮 + sendSweeperCmd( + SweeperFutianCmdUtil.buildCleanDirectionCloseCmd(), + cmdRequestCallback, + CMD_EXECUTE_TIMEOUT_SECONDS); + } else { + //开启新的作业模式,直接发送命令(作业强度默认为标准) + int cmdValue = cleanDirectionBtnAndCmdValueMap.get(currentClickView.getId()); + sendSweeperCmd( + SweeperFutianCmdUtil.buildCleanDirectionCmd(cmdValue), + cmdRequestCallback, + CMD_EXECUTE_TIMEOUT_SECONDS); + } + } + + private void onCleanIntensityBtnClick(final View currentClickView) { + CheckedTextView currentChoosedModeBtnView = null; + for (Integer viewId : cleanIntensityBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + if (view.isChecked()) { + currentChoosedModeBtnView = view; + break; + } + } + boolean isClickCurrentChoosedModeBtn = currentChoosedModeBtnView != null + && currentChoosedModeBtnView.getId() == currentClickView.getId(); + //作业强度如果已经选中,则重复点击时不需要再重复发送指令 + if (isClickCurrentChoosedModeBtn) { + return; + } + 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(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates 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() { + ((CheckedTextView) currentClickView).setChecked(true); + if (isStandardBtnClick) { + setCleanIntensityStandard(); + } else { + setCleanIntensityStrong(); + } + hideLoadingMask(); + showCmdExecuteSuccessToast(); + } + + @Override + public void onCmdFailed() { + } + + @Override + public void onCmdTimeout() { + ((CheckedTextView) currentClickView).setChecked(false); + hideLoadingMask(); + showCmdExecuteTimeoutToast(); + } + }; + int cmdValue = cleanIntensityBtnAndCmdValueMap.get(currentClickView.getId()); + sendSweeperCmd( + SweeperFutianCmdUtil.buildCleanIntensityCmd(cmdValue), + cmdRequestCallback, + CMD_EXECUTE_TIMEOUT_SECONDS); + } + + /** + * 作业模式按钮状态切换-置灰/开启 按钮 + * + * @param enable + */ + private void toggleCleanModeBtnsStatus(boolean enable) { + for (Integer viewId : cleanModeBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + view.setEnabled(enable); + view.setChecked(false); + } + } + + /** + * 作业模式按钮状态切换-将当前点击按钮之外的其他按钮 置灰或开启 + * + * @param choosedBtnId + * @param enable + */ + private void toggleCleanModeBtnsByChoosedViewId(int choosedBtnId, boolean enable) { + for (Integer viewId : cleanModeBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + if (view.getId() != choosedBtnId) { + view.setEnabled(enable); + view.setChecked(false); + } + } + } + + /** + * 清扫方向按钮状态切换-置灰/开启 按钮 + * + * @param enable + */ + private void toggleCleanDirectionBtnsStatus(boolean enable) { + for (Integer viewId : cleanDirectionBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + view.setEnabled(enable); + view.setChecked(false); + } + } + + /** + * 清扫方向按钮状态切换-将当前点击按钮之外的其他按钮 置灰或开启 + * + * @param choosedBtnId + * @param enable + */ + private void toggleCleanDirectionBtnsByChoosedViewId(int choosedBtnId, boolean enable) { + for (Integer viewId : cleanDirectionBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + if (view.getId() != choosedBtnId) { + view.setEnabled(enable); + view.setChecked(false); + } + } + } + + /** + * 作业强度按钮状态切换-置灰/开启 按钮 + * + * @param enable + */ + private void toggleCleanIntensityBtnsStatus(boolean enable) { + for (Integer viewId : cleanIntensityBtnViewIds) { + CheckedTextView view = (CheckedTextView) findViewById(viewId); + view.setEnabled(enable); + view.setChecked(false); + } + } + + /** + * 设置作业强度-标准 + */ + private void setCleanIntensityStandard() { + mBtnCleanIntensityStandard.setChecked(true); + mBtnCleanIntensityStandard.setEnabled(true); + mBtnCleanIntensityStrong.setChecked(false); + mBtnCleanIntensityStrong.setEnabled(true); + } + + /** + * 设置作业强度-加强 + */ + private void setCleanIntensityStrong() { + mBtnCleanIntensityStandard.setChecked(false); + mBtnCleanIntensityStandard.setEnabled(true); + mBtnCleanIntensityStrong.setChecked(true); + mBtnCleanIntensityStrong.setEnabled(true); + } + + /** + * 发送命令后等待时,展示loading + * + * @param timeout + */ + private void showLoadingMask(int timeout) { + mLoadingContainer.setVisibility(View.VISIBLE); + mWorkmodePanelRootView.setInterceptTouchEvent(true); + if (timeout < 0) {//状态同步中 + mLoadingHint.setText("状态同步中,请稍后"); + mLoadingView.setVisibility(View.GONE); + } else { + mLoadingHint.setText(timeout + "s"); + mLoadingView.setVisibility(View.VISIBLE); + startRotation(); + } + if (cleaningModeStateCallback != null && timeout > 0) { + operateStateEnum = OperateStateEnum.STARTING_STATUS; + cleaningModeStateCallback.cleaningModeState(operateStateEnum, mCurrentCleanSystemState, isSelectPureSweepMode); + } + } + + /** + * 隐藏loading + */ + private void hideLoadingMask() { + mSweeperOperateCmdHandler.removeMessages(MSG_CMD_EXECUTE_COUNT_DOWN); + mLoadingContainer.setVisibility(View.GONE); + mWorkmodePanelRootView.setInterceptTouchEvent(false); + } + + /** + * 更新loading中倒计时 + * + * @param timeout + */ + private void updateLoadingCountDown(int timeout) { + mLoadingHint.setText(timeout + "s"); + } + + /** + * 命令执行成功toast + */ + private void showCmdExecuteSuccessToast() { + if (cleaningModeStateCallback != null) { + operateStateEnum = OperateStateEnum.SUCCESS_STATUS; + cleaningModeStateCallback.cleaningModeState(operateStateEnum, mCurrentCleanSystemState, isSelectPureSweepMode); + } + //停止旋转动画 + stopRotation(); + ToastUtils.showLong("设备已响应,操作成功"); + } + + /** + * 命令执行超时toast + */ + private void showCmdExecuteTimeoutToast() { + if (cleaningModeStateCallback != null) { + operateStateEnum = OperateStateEnum.FAIL_STATUS; + cleaningModeStateCallback.cleaningModeState(operateStateEnum, mCurrentCleanSystemState, isSelectPureSweepMode); + } + //停止旋转动画 + stopRotation(); + ToastUtils.showLong("超时未响应,操作失败"); + } + + private void setClickListener(View view, OnClickListener listener) { + view.setOnClickListener(new OnPreventFastClickListener() { + @Override + public void onClickImpl(View v) { + listener.onClick(v); + } + }); + } + + public void setSweeperFutianCleanSystemState(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState, + ICleaningModeStateCallback cleaningModeStateCallback) { + this.cleaningModeStateCallback = cleaningModeStateCallback; + // 有命令正在执行 + if (mCurrentCmdRequestCallback != null) { + Log.d(TAG, "getSecuWorkLeftSts = " + cleanSystemState.getSecuWorkLeftSts()); + if (mCurrentCmdRequestCallback.onCheckIfCmdSuccess(cleanSystemState)) { + mCurrentCmdRequestCallback.onCmdSuccess(); + mCurrentCmdRequestCallback = null; + } + } + //正在上装中或者上装失败,则不更新面板内容 + if (operateStateEnum == OperateStateEnum.STARTING_STATUS) { + return; + } + if (!isFirst) { + isFirst = true; + onSyncVehicleStateCallBack(cleanSystemState); + } + } + + /** + * 设置是否展示状态同步中 + * + * @param operateState + */ + public void showSyncing(OperateStateEnum operateState) { + if (operateState == OperateStateEnum.SYNCING_STATUS) { + syncVehicleStateAndRecoverOperatePanelStates(); + isFirst = false; + } else { + hideLoadingMask(); + } + } + + /** + * 等待同步底盘数据,并根据底盘数据恢复操作面板中按钮的状态 + */ + private synchronized void syncVehicleStateAndRecoverOperatePanelStates() { + // show sync loading + showLoadingMask(-1); + } + + private synchronized void onSyncVehicleStateCallBack(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState) { + if (cleanSystemState == null) return; + // 清扫作业开启状态(以电机状态为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 = SweeperFutianCmdUtil.checkIfCleanModePureSweep(cleanSystemState); + + // 作业强度状态 + boolean clean_intensity_standard = cleanSystemState.getSecuWorkStandSts(); + boolean clean_intensity_strong = cleanSystemState.getSecuWorkStrongSts(); + if (clean_open_requirement) { + // 打开状态 + mBtnCleanWorkOpenClose.setText("关闭"); + mBtnCleanWorkOpenClose.setChecked(true); + } else { + // 关闭状态 + mBtnCleanWorkOpenClose.setText("打开"); + 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(); + } + + /** + * 发送清扫车相关作业命令 + * + * @param fuTianCleanCmd + * @param cmdRequestCallback + * @param timeout + */ + private void sendSweeperCmd( + SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd fuTianCleanCmd, + CmdRequestCallback cmdRequestCallback, + int timeout) { + // 设置当前请求的回调 + mCurrentCmdRequestCallback = cmdRequestCallback; + // onSendCmd + mCurrentCmdRequestCallback.onSendCmd(); + // 发送命令 + CallerAutoPilotControlManager.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 + //mockCleanModeSuccess(fuTianCleanCmd); + } + + 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 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) { + if (mCurrentCmdRequestCallback.onCheckIfCmdSuccess(mCurrentCleanSystemState)) { + mCurrentCmdRequestCallback.onCmdSuccess(); + mCurrentCmdRequestCallback = null; + } + } + removeMessages(MSG_CMD_EXECUTE_COUNT_DOWN); + } + } + } + + interface CmdRequestCallback { + void onSendCmd(); + + void onCountDownTick(int senonds); + + boolean onCheckIfCmdSuccess(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState); + + void onCmdSuccess(); + + void onCmdFailed(); + + void onCmdTimeout(); + } + + /** + * 开始旋转 + */ + private void startRotation() { + if (objectAnimator == null) { + objectAnimator = ObjectAnimator.ofFloat(mLoadingView, "rotation", 0, 360f); + objectAnimator.setDuration(1500); + objectAnimator.setRepeatCount(-1); + objectAnimator.setInterpolator(new LinearInterpolator()); + objectAnimator.start(); + } + } + + /** + * 停止旋转 + */ + private void stopRotation() { + if (objectAnimator != null && objectAnimator.isRunning()) { + objectAnimator.end(); + objectAnimator = null; + } + } + + /** + * 模拟指令操作成功 + */ + private void mockCleanModeSuccess(SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd fuTianTaskCmd) { + ChassisStatesOuterClass.SweeperFuTianTaskSystemStates.Builder builder = ChassisStatesOuterClass.SweeperFuTianTaskSystemStates.newBuilder(); + chassis.SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd fuTianCleanCmd = fuTianTaskCmd.getRoboSweeperFutianCleanCmd(); + if (fuTianCleanCmd.getCleanOpenRequirement() == SweeperFutianCmdUtil.CLEAN_WORK_OPEN) {//打开 + builder.setSecuMotWorkSts(true); + builder.setSecuModWashSweepSts(false); + builder.setSecuModWashSts(false); + builder.setSecuWorkTonSts(false); + builder.setSecuWorkOnBothsidesSts(false); + builder.setSecuWorkLeftSts(false); + builder.setSecuWorkRightSts(false); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanOpenRequirement() == SweeperFutianCmdUtil.CLEAN_WORK_CLOSE) {//关闭 + builder.setSecuModWashSweepSts(false); + builder.setSecuModWashSts(false); + builder.setSecuWorkTonSts(false); + builder.setSecuWorkOnBothsidesSts(false); + builder.setSecuWorkLeftSts(false); + builder.setSecuWorkRightSts(false); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + builder.setSecuMotWorkSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } + if (fuTianCleanCmd.getCleanModeRequirement() == SweeperFutianCmdUtil.CLEAN_MODE_PURE_SWEEP) {//纯扫 + builder.setSecuModWashSweepSts(false); + builder.setSecuModWashSts(false); + builder.setSecuWorkTonSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanModeRequirement() == SweeperFutianCmdUtil.CLEAN_MODE_WASH_SWEEP) {//洗扫 + builder.setSecuModWashSweepSts(!mCurrentCleanSystemState.getSecuModWashSweepSts()); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanModeRequirement() == SweeperFutianCmdUtil.CLEAN_MODE_PURE_WASH) {//纯洗 + builder.setSecuModWashSts(!mCurrentCleanSystemState.getSecuModWashSts()); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanModeRequirement() == SweeperFutianCmdUtil.CLEAN_MODE_PURE_DRAW) {//纯吸 + builder.setSecuWorkTonSts(!mCurrentCleanSystemState.getSecuWorkTonSts()); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkOnBothsidesSts(false); + builder.setSecuWorkLeftSts(false); + builder.setSecuWorkRightSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanModeRequirement() == SweeperFutianCmdUtil.CLEAN_MODE_CLOSE) { + builder.setSecuModWashSweepSts(false); + builder.setSecuModWashSts(false); + builder.setSecuWorkTonSts(false); + builder.setSecuWorkOnBothsidesSts(false); + builder.setSecuWorkLeftSts(false); + builder.setSecuWorkRightSts(false); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } + if (fuTianCleanCmd.getCleanDirectionRequirement() == SweeperFutianCmdUtil.CLEAN_DIRECTION_BOTH_SIDE) {//两侧 + builder.setSecuWorkOnBothsidesSts(!mCurrentCleanSystemState.getSecuWorkOnBothsidesSts()); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanDirectionRequirement() == SweeperFutianCmdUtil.CLEAN_DIRECTION_LEFT_SIDE) {//左侧 + builder.setSecuWorkLeftSts(!mCurrentCleanSystemState.getSecuWorkLeftSts()); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanDirectionRequirement() == SweeperFutianCmdUtil.CLEAN_DIRECTION_RIGHT_SIDE) {//右侧 + builder.setSecuWorkRightSts(!mCurrentCleanSystemState.getSecuWorkRightSts()); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanDirectionRequirement() == SweeperFutianCmdUtil.CLEAN_DIRECTION_CLOSE) { + builder.setSecuWorkLeftSts(false); + builder.setSecuWorkRightSts(false); + builder.setSecuWorkOnBothsidesSts(false); + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } + if (fuTianCleanCmd.getCleanIntensityRequirement() == SweeperFutianCmdUtil.CLEAN_INTENSITY_STRAND) { + builder.setSecuWorkStrongSts(true); + builder.setSecuWorkStandSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + return; + } else if (fuTianCleanCmd.getCleanIntensityRequirement() == SweeperFutianCmdUtil.CLEAN_INTENSITY_STRONG) { + builder.setSecuWorkStandSts(true); + builder.setSecuWorkStrongSts(false); + mCurrentCleanSystemState = builder.build(); + mockSendCmdSuccess(); + } + + } + +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudDialog.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudDialog.kt new file mode 100644 index 0000000000..23deab9621 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudDialog.kt @@ -0,0 +1,133 @@ +package com.mogo.och.sweepercloud.ui.dialog + +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.content.Context +import android.view.View +import android.view.animation.LinearInterpolator +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.LifecycleObserver +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.eagle.core.utilcode.util.ClickUtils +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.callback.SweeperCloudDialogClickListener +import com.mogo.och.sweepercloud.view.CountDownView + +/** + * 清扫车云控任务dialog基类 + */ + class SweeperCloudDialog : BaseFloatDialog, LifecycleObserver { + private var commonTitle: TextView? = null //标题 + private var commonLeft: TextView? = null//底部左边按钮 + private var commonMiddle: TextView? = null //底部中间按钮 + private var commonRight: TextView? = null //底部右边按钮 + private var commonCountDown: CountDownView? = null //倒计时 + private var commonContent: TextView? = null //内容 + private var commonTip: TextView? = null //文本提示 + private var countDownImage: ImageView? = null //内容 + private var objectAnimator: ObjectAnimator? = null + + constructor(builder: Builder, context: Context) : super(context) { + commonTitle?.text = builder.titleStr + commonContent?.text = builder.contentStr + if (builder.tipStr == "") { + commonTip?.visibility = View.GONE + } else { + commonTip?.text = builder.tipStr + } + if (builder.leftStr == "") { + commonLeft?.visibility = View.GONE + } else { + commonLeft?.text = builder.leftStr + } + if (builder.middleStr == "") { + commonMiddle?.visibility = View.GONE + } else { + commonMiddle?.text = builder.middleStr + } + if (builder.rightStr == "") { + commonRight?.visibility = View.GONE + } else { + commonRight?.text = builder.rightStr + } + if (builder.countDownTime == 0) { + commonCountDown?.visibility = View.GONE + } else { + commonCountDown?.startCountDown(builder.countDownTime) + } + commonLeft?.setOnClickListener { + //防止重复点击 + if(ClickUtils.isFastClick()){ + builder.listener?.onConfirm() + objectAnimator?.cancel() + commonCountDown?.stopCountDown() + dismiss() + } + } + commonMiddle?.setOnClickListener { + //防止重复点击 + if(ClickUtils.isFastClick()){ + builder.listener?.onNext() + objectAnimator?.cancel() + commonCountDown?.stopCountDown() + dismiss() + } + } + commonRight?.setOnClickListener { + //防止重复点击 + if(ClickUtils.isFastClick()){ + builder.listener?.onRefuseOrEnd() + objectAnimator?.cancel() + commonCountDown?.stopCountDown() + dismiss() + } + } + commonCountDown?.setCountDownListener(object : CountDownView.CountDownListener { + override fun stop() { + builder.listener?.onCountDownStop() + objectAnimator?.cancel() + commonCountDown?.stopCountDown() + dismiss() + } + + }) + countDownImage?.let { startAnima(it) } + } + + init { + setContentView(R.layout.dialog_sweeper_cloud_view) + setCanceledOnTouchOutside(false) + commonTitle = findViewById(R.id.sweeper_cloud_title) + commonContent = findViewById(R.id.sweeper_cloud_content) + commonTip = findViewById(R.id.sweeper_cloud_tip) + commonLeft = findViewById(R.id.sweeper_cloud_left) + commonMiddle = findViewById(R.id.sweeper_cloud_middle) + commonRight = findViewById(R.id.sweeper_cloud_right) + countDownImage = findViewById(R.id.sweeper_cloud_imageview) + commonCountDown = findViewById(R.id.sweeper_cloud_countdown) + } + class Builder { + var titleStr: String = "" + var contentStr: String = "" + var tipStr: String = "" + var leftStr: String = "" + var middleStr: String = "" + var rightStr: String = "" + var countDownTime: Int = 0 + var listener: SweeperCloudDialogClickListener? = null + fun build(context: Context): SweeperCloudDialog { + return SweeperCloudDialog(this, context) + } + } + /** + * 启动动画 + */ + private fun startAnima(imageView: ImageView) { + objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 359f) + objectAnimator?.repeatCount = ValueAnimator.INFINITE + objectAnimator?.duration = 1500 + objectAnimator?.interpolator = LinearInterpolator() + objectAnimator?.start() + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudLoadingDialog.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudLoadingDialog.kt new file mode 100644 index 0000000000..3321382705 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperCloudLoadingDialog.kt @@ -0,0 +1,75 @@ +package com.mogo.och.sweepercloud.ui.dialog + +import android.animation.ObjectAnimator +import android.content.Context +import android.view.animation.LinearInterpolator +import androidx.lifecycle.LifecycleObserver +import com.elegant.utils.UiThreadHandler +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.sweepercloud.R +import kotlinx.android.synthetic.main.dialog_sweeper_cloud_loading.* + +/** + * loading + */ +class SweeperCloudLoadingDialog : BaseFloatDialog, LifecycleObserver { + private var objectAnimator: ObjectAnimator? = null + private val mLoadingView by lazy { dialog_loading_view } + private val mLoadingText by lazy { dialog_loading_text } + private var mRunnable:Runnable= Runnable { + ToastUtils.showLong("超时未响应,操作失败") + hideLoading() + } + + constructor(context: Context) : super(context) + + init { + setContentView(R.layout.dialog_sweeper_cloud_loading) + setCanceledOnTouchOutside(false) + } + + /** + * 开始旋转 + */ + private fun startRotation() { + objectAnimator = ObjectAnimator.ofFloat(mLoadingView, "rotation", -720f, 0f) + objectAnimator?.let { + it.duration = 3000 + it.repeatCount = -1 + it.interpolator = LinearInterpolator() + it.start() + } + } + + /** + * 停止旋转 + */ + private fun stopRotation() { + objectAnimator?.let { + if (it.isRunning) { + it.end() + objectAnimator = null + } + } + } + + /** + * 显示dialog + */ + fun showLoading() { + mLoadingText.text = "加载中..." + startRotation() + show() + UiThreadHandler.getsUiHandler().postDelayed(mRunnable, 15000L) + } + + /** + * 隐藏dialog + */ + fun hideLoading() { + UiThreadHandler.getsUiHandler().removeCallbacks(mRunnable) + stopRotation() + dismiss() + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperManualDrivingDialog.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperManualDrivingDialog.kt new file mode 100644 index 0000000000..52e21df88c --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperManualDrivingDialog.kt @@ -0,0 +1,70 @@ +package com.mogo.och.sweepercloud.ui.dialog + +import android.content.Context +import android.widget.TextView +import androidx.lifecycle.LifecycleObserver +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.och.sweepercloud.R + +/** + * 不带带有title, tip,confirm,cancel的dialog + */ +class SweeperManualDrivingDialog: BaseFloatDialog, LifecycleObserver { + + private var commonConfirm : TextView? = null + private var commonTips : TextView? = null + + private var clickListener: ClickListener? = null + + constructor(builder: Builder,context: Context) : super(context) { + commonTips?.text = builder.tipsStr + commonConfirm?.text = builder.confirmStr + } + + init{ + setContentView(R.layout.dialog_sweeper_manual_driving) + + setCanceledOnTouchOutside(false) + + commonConfirm = findViewById(R.id.sweeper_common_confirm) + commonTips = findViewById(R.id.sweeper_common_tips) + + commonConfirm?.setOnClickListener{ + clickListener?.confirm() + dismiss() + } + } + + fun setClickListener(clickListener: ClickListener) { + this.clickListener = clickListener + } + + fun showUpgradeDialog(){ + if(isShowing){ + return + } + show() + } + + interface ClickListener{ + fun confirm() + } + + class Builder{ + var tipsStr:String = "" + var confirmStr:String = "" + fun tips(tips: String) : Builder{ + this.tipsStr = tips + return this + } + + fun confirmStr(commit: String) : Builder{ + this.confirmStr = commit + return this + } + fun build(context: Context): SweeperManualDrivingDialog? { + return SweeperManualDrivingDialog(this,context) + } + } + +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperNoTitleCommonDialog.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperNoTitleCommonDialog.kt new file mode 100644 index 0000000000..a2b41f4592 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/dialog/SweeperNoTitleCommonDialog.kt @@ -0,0 +1,85 @@ +package com.mogo.och.sweepercloud.ui.dialog + +import android.content.Context +import android.widget.TextView +import androidx.lifecycle.LifecycleObserver +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.och.sweepercloud.R + +/** + * 不带带有title, tip,confirm,cancel的dialog + */ +class SweeperNoTitleCommonDialog: BaseFloatDialog, LifecycleObserver { + + private var commonConfirm : TextView? = null + private var commonCancel : TextView? = null + private var commonTips : TextView? = null + + private var clickListener: ClickListener? = null + + constructor(builder: Builder,context: Context) : super(context) { + commonTips?.text = builder.tipsStr + commonCancel?.text = builder.cancelStr + commonConfirm?.text = builder.confirmStr + } + + init{ + setContentView(R.layout.dialog_sweeper_no_title) + + setCanceledOnTouchOutside(true) + + commonConfirm = findViewById(R.id.sweeper_common_confirm) + commonCancel = findViewById(R.id.sweeper_common_cancel) + commonTips = findViewById(R.id.sweeper_common_tips) + + commonConfirm?.setOnClickListener{ + clickListener?.confirm() + dismiss() + } + commonCancel?.setOnClickListener { + clickListener?.cancel() + dismiss() + } + } + + fun setClickListener(clickListener: ClickListener) { + this.clickListener = clickListener + } + + fun showUpgradeDialog(){ + if(isShowing){ + return + } + show() + } + + interface ClickListener{ + fun confirm() + fun cancel() + } + + class Builder{ + var tipsStr:String = "" + var confirmStr:String = "" + var cancelStr:String = "" + fun tips(tips: String) : Builder{ + this.tipsStr = tips + return this + } + + fun confirmStr(commit: String) : Builder{ + this.confirmStr = commit + return this + } + + fun cancelStr(cancel: String) : Builder{ + this.cancelStr = cancel + return this + } + + fun build(context: Context): SweeperNoTitleCommonDialog? { + return SweeperNoTitleCommonDialog(this,context) + } + } + +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/popwindow/SweeperOperatePanelPopWindow.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/popwindow/SweeperOperatePanelPopWindow.kt new file mode 100644 index 0000000000..4db379e1ac --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/ui/popwindow/SweeperOperatePanelPopWindow.kt @@ -0,0 +1,59 @@ +package com.mogo.och.sweepercloud.ui.popwindow + +import android.content.Context +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.PopupWindow +import chassis.ChassisStatesOuterClass +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.callback.ICleaningModeStateCallback +import com.mogo.och.sweepercloud.constant.OperateStateEnum +import com.mogo.och.sweepercloud.ui.SweeperOperatePanelView + +/** + * 清扫车面板浮窗 + */ +class SweeperOperatePanelPopWindow : PopupWindow{ + + private var mOperatePanelView: SweeperOperatePanelView? = null + + constructor(context: Context) : super(context) { + init(context) + } + private fun init(context: Context) { + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + mOperatePanelView = LayoutInflater.from(context).inflate(R.layout.sweeper_popwindow_operate_panel, null) as SweeperOperatePanelView? + width = ViewGroup.LayoutParams.WRAP_CONTENT + height = ViewGroup.LayoutParams.WRAP_CONTENT + contentView = mOperatePanelView + } + + /** + * 设置清扫模式数据 + */ + fun setCleanSystemState( + cleanSystemState: ChassisStatesOuterClass.SweeperFuTianTaskSystemStates?, + cleaningModeStateCallback: ICleaningModeStateCallback + ) { + mOperatePanelView?.setSweeperFutianCleanSystemState(cleanSystemState, cleaningModeStateCallback) + } + + /**. + * + * 设置是否让popWindow消失 + */ + fun setIsOutsideTouchable(isOutsideTouchable:Boolean){ + this.isFocusable = isOutsideTouchable + this.isOutsideTouchable = isOutsideTouchable + this.isTouchable=isOutsideTouchable + } + + /** + * 设置是否展示状态同步中 + */ + fun showSyncing(operateState: OperateStateEnum){ + mOperatePanelView?.showSyncing(operateState) + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/AutopilotModeConfigManager.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/AutopilotModeConfigManager.java new file mode 100644 index 0000000000..f828af22a5 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/AutopilotModeConfigManager.java @@ -0,0 +1,127 @@ +package com.mogo.och.sweepercloud.util; + +import android.os.Environment; +import android.text.TextUtils; +import android.util.Pair; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.util.JsonFormat; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.atomic.AtomicBoolean; + +import mogo.telematics.pad.MessagePad; + +/** + * 读取启动自动驾驶配置 + */ +public class AutopilotModeConfigManager { + private final static String TAG = AutopilotModeConfigManager.class.getSimpleName(); + private final AtomicBoolean isReadConfig = new AtomicBoolean(false); + private OnReadAutopilotModeConfigListener listener; + + + public interface OnReadAutopilotModeConfigListener { + void onReadFailed(String err);//文件不存在或读取失败 + + void onParseFailed(String err);//配置文件解析失败 + + void onParse(MessagePad.SetAutopilotModeReq bean);//解析完成 + } + + public AutopilotModeConfigManager(OnReadAutopilotModeConfigListener listener) { + this.listener = listener; + } + + + public void registerListener(OnReadAutopilotModeConfigListener listener) { + this.listener = listener; + } + + public void unregisterListener() { + listener = null; + } + + /** + * 读取配置文件 + * + * @return 是否调用成功 + */ + public boolean read() { + if (!isReadConfig.get()) { + isReadConfig.set(true); + Runnable runnable = new Runnable() { + @Override + public void run() { + Pair config = readFilesToString(new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AutopilotModeConfig.json")); + if (TextUtils.isEmpty(config.first)) { + if (listener != null) { + listener.onReadFailed(config.second); + } + } else { + MessagePad.SetAutopilotModeReq.Builder builder = MessagePad.SetAutopilotModeReq.newBuilder(); + String err = null; + try { + JsonFormat.parser().ignoringUnknownFields().merge(config.first, builder); + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + err = e.getMessage(); + } + if (TextUtils.isEmpty(err)) { + MessagePad.SetAutopilotModeReq bean = builder.build(); + if (listener != null) { + listener.onParse(bean); + } + } else { + if (listener != null) { + listener.onParseFailed(err); + } + } + } + isReadConfig.set(false); + } + }; + new Thread(runnable).start(); + return true; + } + return false; + } + + /** + * @param file + * @return first:读取到的内容 second:失败信息 + */ + private Pair readFilesToString(File file) { + InputStream inputStream = null; + String err = null; + try { + inputStream = new FileInputStream(file); + byte[] buffer = new byte[1024]; + int length = -1; + StringBuilder stringBuilder = new StringBuilder(); + while ((length = inputStream.read(buffer)) != -1) { + stringBuilder.append(new String(buffer, 0, length)); + } + return new Pair(stringBuilder.toString(), err); + } catch (FileNotFoundException e) { + e.printStackTrace(); + err = e.toString(); + } catch (IOException e) { + e.printStackTrace(); + err = e.toString(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return new Pair(null, err); + } +} diff --git a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperAnalyticsManager.java similarity index 98% rename from OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java rename to OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperAnalyticsManager.java index bf01bbf0b5..91b5820710 100644 --- a/OCH/mogo-och-sweeper/src/main/java/com/mogo/och/sweeper/util/SweeperAnalyticsManager.java +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperAnalyticsManager.java @@ -1,4 +1,4 @@ -package com.mogo.och.sweeper.util; +package com.mogo.och.sweepercloud.util; import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_SWEEPER; @@ -14,7 +14,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListener 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.sweeper.constant.SweeperConst; +import com.mogo.och.sweepercloud.constant.SweeperConst; import java.util.HashMap; diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperCloudTaskUtils.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperCloudTaskUtils.kt new file mode 100644 index 0000000000..25fb456c39 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperCloudTaskUtils.kt @@ -0,0 +1,348 @@ +package com.mogo.och.sweepercloud.util + +import android.content.Context +import com.elegant.utils.UiThreadHandler +import com.google.protobuf.MessageOrBuilder +import com.google.protobuf.TextFormat +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.common.module.utils.DateTimeUtil +import com.mogo.och.common.module.voice.VoiceNotice +import com.mogo.och.sweepercloud.callback.SweeperCloudDialogClickListener +import com.mogo.och.sweepercloud.model.SweeperTaskModel +import com.mogo.och.sweepercloud.ui.dialog.SweeperCloudDialog +import com.zhjt.mogo.adas.data.sweeper.SweeperCloudTask.MessageType +import com.zhjt.mogo.adas.data.sweeper.bootable.SweeperBootable +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.* +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.big.SweeperBigTaskStatus.BigTaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.confirm.SweeperTaskConfirm.TaskConfirm +import com.zhjt.mogo.adas.data.sweeper.task.status.SweeperTaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.stop.SweeperTaskStop +import java.util.* + +object SweeperCloudTaskUtils { + const val TAG = "SweeperCloudTaskUtils" + + /** + * 模拟发送查询当前任务的请求 + */ + @JvmStatic + fun mockQueryCurrentTaskInfo() { +// UiThreadHandler.getsUiHandler().postDelayed({ +// mockSendCloudTaskInfo(MessageType.PadSendGetTaskReq) +// },1000) + SweeperTaskModel.getInstance().getCurrentTask() + } + + /** + * 模拟云控发送任务给pad + */ + @JvmStatic + fun mockSendCloudTaskInfo(messageType: MessageType) { + val builder = TaskInfo.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.taskName = "烟台清扫车作业任务" + builder.currentTime = System.currentTimeMillis() + builder.taskStartTime = 1683507615000 + builder.taskEndTime = 1683540015000 + //第一个子任务 + val subBuilder0 = SubTaskInfo.newBuilder() + subBuilder0.subTaskId = "1" + subBuilder0.subTaskName = "海水浴场-佛兴禅寺(前岛贴右)" + subBuilder0.taskModel = TaskModel.AUTO + subBuilder0.taskStatus = SweeperCommon.TaskStatus.TO_START + val startLocation0 = Location.newBuilder() + startLocation0.siteName = "自动驾驶子任务起点0" + startLocation0.wgsLongitude =112.56970262448544 + startLocation0.wgsLatitude = 26.817567832504274 + startLocation0.longitude = 112.57493487730413 + startLocation0.latitude = 26.81397095451884 + subBuilder0.startLocation = startLocation0.build() + val endLocation0 = Location.newBuilder() + endLocation0.siteName = "自动驾驶子任务终点0" + endLocation0.wgsLongitude = 112.57723562874442 + endLocation0.wgsLatitude = 26.819769725304003 + endLocation0.longitude = 112.5824598556873 + endLocation0.latitude = 26.81616501438377 + subBuilder0.endLocation = endLocation0.build() + subBuilder0.lineId = 123 + subBuilder0.lineName = "测试路线0" + builder.addSubList(subBuilder0.build()) + //第二个子任务 +// val subBuilder1 = SubTaskInfo.newBuilder() +// subBuilder1.subTaskId = "2" +// subBuilder1.subTaskName = "佛兴禅寺-海水浴场(前岛贴左)" +// subBuilder1.taskModel = TaskModel.AUTO +// subBuilder1.taskStatus = SweeperCommon.TaskStatus.TO_START +// val startLocation1 = Location.newBuilder() +// startLocation1.siteName = "自动驾驶子任务起点1" +// startLocation1.wgsLongitude = 112.57723562874442 +// startLocation1.wgsLatitude = 26.819769725304003 +// startLocation1.longitude = 112.5824598556873 +// startLocation1.latitude = 26.81616501438377 +// subBuilder1.startLocation = startLocation1.build() +// val endLocation1 = Location.newBuilder() +// endLocation1.siteName = "自动驾驶子任务终点1" +// endLocation1.wgsLongitude = 112.56970262448544 +// endLocation1.wgsLatitude = 26.817567832504274 +// endLocation1.longitude = 112.57493487730413 +// endLocation1.latitude = 26.81397095451884 +// subBuilder1.endLocation = endLocation1.build() +// subBuilder1.lineId = 124 +// subBuilder1.lineName = "测试路线1" +// builder.addSubList(subBuilder1.build()) +// //第三个子任务 +// val subBuilder2 = SubTaskInfo.newBuilder() +// subBuilder2.subTaskId = "3" +// subBuilder2.subTaskName = "海水浴场-佛兴禅寺(前岛贴左)" +// subBuilder2.taskModel = TaskModel.MANUAL +// subBuilder2.taskStatus = SweeperCommon.TaskStatus.TO_START +// val startLocation2 = Location.newBuilder() +// startLocation2.siteName = "人工驾驶子任务起点2" +// startLocation2.wgsLongitude = 121.31344761929978 +// startLocation2.wgsLatitude = 37.53205755535642 +// startLocation2.longitude = 121.3185679517558 +// startLocation2.latitude = 37.5329694887952 +// subBuilder2.startLocation = startLocation2.build() +// val endLocation2 = Location.newBuilder() +// endLocation2.siteName = "人工驾驶子任务终点2" +// endLocation2.wgsLongitude = 121.4551205070834 +// endLocation2.wgsLatitude = 37.47936696980237 +// endLocation2.longitude = 121.46030960742117 +// endLocation2.latitude = 37.48032689641474 +// subBuilder2.endLocation = endLocation2.build() +// subBuilder2.lineId = 125 +// subBuilder2.lineName = "测试路线2" +// builder.addSubList(subBuilder2.build()) +// //第四个子任务 +// val subBuilder3 = SubTaskInfo.newBuilder() +// subBuilder3.subTaskId = "4" +// subBuilder3.subTaskName = "海水浴场-佛兴禅寺(前岛贴左第四个任务)" +// subBuilder3.taskModel = TaskModel.MANUAL +// subBuilder3.taskStatus = SweeperCommon.TaskStatus.TO_START +// val startLocation3 = Location.newBuilder() +// startLocation3.siteName = "人工驾驶子任务起点3" +// startLocation3.wgsLongitude = 121.31344761929978 +// startLocation3.wgsLatitude = 37.53205755535642 +// startLocation3.longitude = 121.3185679517558 +// startLocation3.latitude = 37.5329694887952 +// subBuilder3.startLocation = startLocation3.build() +// val endLocation3 = Location.newBuilder() +// endLocation3.siteName = "人工驾驶子任务终点3" +// endLocation3.wgsLongitude = 121.4551205070834 +// endLocation3.wgsLatitude = 37.47936696980237 +// endLocation3.longitude = 121.46030960742117 +// endLocation3.latitude = 37.48032689641474 +// subBuilder3.endLocation = endLocation3.build() +// subBuilder3.lineId = 126 +// subBuilder3.lineName = "测试路线3" +// builder.addSubList(subBuilder3.build()) + SweeperTaskModel.getInstance().onSweeperFutianCloudTask( + messageType, + "${System.currentTimeMillis()}", + System.currentTimeMillis(), + builder.build() + ) + CallerLogger.d(SceneConstant.M_SWEEPER + TAG, "messageType:" + messageType.number + "taskInfo:" + printMessage(builder.build())) + } + + /** + * 模拟云控发送子任务开始确认信息 + */ + @JvmStatic + fun mockSendCloudSubTaskConfirm() { + val builder = TaskConfirm.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.subTaskId = "1" + SweeperTaskModel.getInstance().onSweeperFutianCloudTaskConfirm( + MessageType.CloudPushTaskConfirm, "${System.currentTimeMillis()}", + System.currentTimeMillis(), builder.build() + ) + } + + /** + * 模拟下发更新子任务状态指令 + */ + @JvmStatic + fun mockSendCloudUpdateSubTaskStatus() { + val builder = SweeperTaskStatus.TaskStatusPush.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.subTaskId = "1" + builder.taskStatus = SweeperCommon.TaskStatus.RUNNING + SweeperTaskModel.getInstance().onSweeperFutianCloudTaskStatus( + MessageType.CloudPushTaskStatus, "${System.currentTimeMillis()}", + System.currentTimeMillis(), builder.build() + ) + } + + /** + * 模拟云端发送大任务结束 + */ + @JvmStatic + fun mockSendCloudBigTaskEnd() { + val builder = SweeperTaskStop.StopTaskReq.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.type = SweeperTaskStop.StopTaskType.ADVANCE + SweeperTaskModel.getInstance().onSweeperFutianCloudTaskStop( + MessageType.CloudPushTaskStop, "${System.currentTimeMillis()}", + System.currentTimeMillis(), builder.build() + ) + } + + /** + * 模拟云端发送大任务状态给pad + */ + @JvmStatic + fun mockSendCloudBigTaskStatus() { + val builder = SweeperBigTaskStatus.BigTaskStatusPush.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.taskStatus = BigTaskStatus.FINISHED + builder.systemTime = System.currentTimeMillis() + SweeperTaskModel.getInstance().onSweeperFutianCloudBigTaskStatus( + MessageType.CloudPushBigTaskStatus, "${System.currentTimeMillis()}", + System.currentTimeMillis(), builder.build() + ) + } + + /** + * 模拟云端发送是否可以启动自驾 + */ + @JvmStatic + fun mockSendCloudBootable() { + val builder = SweeperBootable.IsBootableResp.newBuilder() + builder.sn = getDriverSn() + builder.taskId = "10" + builder.subTaskId = "1" + builder.code = SweeperCommon.Code.SUCCEED + UiThreadHandler.getsUiHandler().postDelayed({ + SweeperTaskModel.getInstance().onSweeperFutianCloudBootable( + MessageType.PadSendBootable, "${System.currentTimeMillis()}", + System.currentTimeMillis(), builder.build() + ) + }, 10000) + } + + private fun getDriverSn(): String? { + return MoGoAiCloudClientConfig.getInstance().sn + } + + /** + * 创建接收任务弹窗 + */ + @JvmStatic + fun createReceivedTaskInfoDialog(context: Context?, listener: SweeperCloudDialogClickListener?, taskInfo: TaskInfo): SweeperCloudDialog? { + var builder: SweeperCloudDialog.Builder = SweeperCloudDialog.Builder() + val startCalendar = DateTimeUtil.formatLongToCalendar(taskInfo.taskStartTime) + val endCalendar = DateTimeUtil.formatLongToCalendar(taskInfo.taskEndTime) + builder.titleStr = "任务接取" + builder.contentStr = "请确认是否接取${taskInfo.taskName}" + builder.tipStr = "(任务时间${DateTimeUtil.formatCalendarToString(startCalendar, DateTimeUtil.HH_mm)}-${ + DateTimeUtil.formatCalendarToString( + endCalendar, + DateTimeUtil.HH_mm + ) + })" + builder.leftStr = "确认" + builder.middleStr = "" + builder.rightStr = "拒绝" + builder.countDownTime = 15 + builder.listener = listener + return context?.let { it1 -> builder.build(it1) } + } + + /** + * 创建确认开始子任务弹窗 + */ + @JvmStatic + fun createConfirmStartSubTaskDialog( + context: Context?, + listener: SweeperCloudDialogClickListener?, + subTaskInfo: SubTaskInfo + ): SweeperCloudDialog? { + var builder: SweeperCloudDialog.Builder = SweeperCloudDialog.Builder() + builder.titleStr = "任务确认" + builder.contentStr = "请确认是否执行${subTaskInfo.subTaskName}" + builder.tipStr = + if (subTaskInfo.taskModel == TaskModel.MANUAL) "[需手动驾驶至终点${subTaskInfo.endLocation.siteName}]" else "[自动驾驶至终点${subTaskInfo.endLocation.siteName}]" + builder.leftStr = "确认" + builder.middleStr = "下一个" + builder.rightStr = "结束" + builder.countDownTime = 15 + builder.listener = listener + return context?.let { it1 -> builder.build(it1) } + } + + /** + * 创建结束任务弹窗 + */ + @JvmStatic + fun createSweeperTaskEndDialog( + context: Context?, + listener: SweeperCloudDialogClickListener?, + stopTaskType: SweeperTaskStop.StopTaskType, + timeoutStr: String + ): SweeperCloudDialog? { + var builder: SweeperCloudDialog.Builder = SweeperCloudDialog.Builder() + builder.titleStr = "任务结束" + when (stopTaskType) { + //任务提前结束 + SweeperTaskStop.StopTaskType.ADVANCE -> { + builder.contentStr = "云端请求终止任务,请确认" + builder.tipStr = "【确认后请接管停车】" + builder.leftStr = "确认" + builder.middleStr = "" + builder.rightStr = "拒绝" + VoiceNotice.showNotice("云端请求终止任务,请确认") + } + //任务超时结束 + SweeperTaskStop.StopTaskType.TIMEOUT -> { + builder.contentStr = "任务已超时${timeoutStr},请确认是否结束" + builder.tipStr = "【结束后请接管停车】" + builder.leftStr = "确认" + builder.middleStr = "" + builder.rightStr = "拒绝" + VoiceNotice.showNotice("任务已超时${timeoutStr},请确认是否结束") + } + } + builder.countDownTime = 15 + builder.listener = listener + return context?.let { it1 -> builder.build(it1) } + } + + /** + * 任务正常结束弹窗 + */ + @JvmStatic + fun createSweeperTaskNormalEndDialog( + context: Context?, + listener: SweeperCloudDialogClickListener? + ): SweeperCloudDialog? { + var builder: SweeperCloudDialog.Builder = SweeperCloudDialog.Builder() + builder.titleStr = "任务结束" + builder.contentStr = "任务已完成,干的漂亮!" + builder.tipStr = "" + builder.leftStr = "确认" + builder.middleStr = "" + builder.rightStr = "" + builder.countDownTime = 10 + builder.listener = listener + return context?.let { it1 -> builder.build(it1) } + } + + @JvmStatic + fun printMessage(message: MessageOrBuilder): String { + return "\n"+TextFormat.printer().escapingNonAscii(false).printToString(message) + } + @JvmStatic + fun getRequestId():String{ + return UUID.randomUUID().toString() + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperFutianCmdUtil.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperFutianCmdUtil.java new file mode 100644 index 0000000000..35e2a0963b --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperFutianCmdUtil.java @@ -0,0 +1,202 @@ +package com.mogo.och.sweepercloud.util; + +import chassis.ChassisStatesOuterClass; +import chassis.SpecialVehicleTaskCmdOuterClass; + +/** + * 清扫车-福田,构建业务命令数据的工具类 + */ +public class SweeperFutianCmdUtil { + public static final int CLEAN_WORK_OPEN = 1; //清扫作业-开启 + public 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;//作业模式-纯吸 + public 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;//清扫方向-右侧 + public 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(); + } + + /** + * 判断是否有作业模式 + * @param cleanSystemState + * @return true:没有作业模式 false:有作业模式 + */ + public static boolean checkIfCleanMode(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState){ + return (!cleanSystemState.getSecuModWashSweepSts()&&!cleanSystemState.getSecuModWashSts()&&!cleanSystemState.getSecuWorkTonSts())&& + (!cleanSystemState.getSecuWorkLeftSts()&&!cleanSystemState.getSecuWorkRightSts()&&!cleanSystemState.getSecuWorkOnBothsidesSts()); + } + + /** + * 判断是否有清扫方向 + * @param cleanSystemState + * @return true:没有清扫方向 false:有清扫方向 + */ + public static boolean checkIfCleanDirection(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState){ + return !cleanSystemState.getSecuWorkLeftSts()&&!cleanSystemState.getSecuWorkRightSts()&&!cleanSystemState.getSecuWorkOnBothsidesSts(); + } + /** + * 判断是否有作业强度 + * @param cleanSystemState + * @return true:没有作业强度 false:有作业强度 + */ + public static boolean checkIfCleanIntensity(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates cleanSystemState){ + return !cleanSystemState.getSecuWorkStandSts()&&!cleanSystemState.getSecuWorkStrongSts(); + } + /** + * 判断是否纯扫模式 + * + * @param cleanSystemState + * @return + */ + public static boolean checkIfCleanModePureSweep(ChassisStatesOuterClass.SweeperFuTianTaskSystemStates 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; + } + /** + * 构建底盘Mock数据 + * + * @return + */ + public static ChassisStatesOuterClass.SweeperFuTianTaskSystemStates buildSweeperFuTionCleanSystemStateMockData() { + ChassisStatesOuterClass.SweeperFuTianTaskSystemStates.Builder builder = ChassisStatesOuterClass.SweeperFuTianTaskSystemStates.newBuilder(); + builder.setSecuMotWorkSts(true); + builder.setSecuModWashSts(true); + builder.setSecuWorkOnBothsidesSts(true); + builder.setSecuWorkStrongSts(true); + return builder.build(); + } + +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperMapAssetStyleUtil.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperMapAssetStyleUtil.java new file mode 100644 index 0000000000..57d39a354b --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/util/SweeperMapAssetStyleUtil.java @@ -0,0 +1,61 @@ +package com.mogo.och.sweepercloud.util; + + +import android.content.Context; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author donghongyu + * @date 12/18/20 5:37 PM + */ +public class SweeperMapAssetStyleUtil { + + public static byte[] getAssetsStyle(Context context,String fileName) { + byte[] buffer1 = null; + InputStream is1 = null; + try { + is1 = context.getResources().getAssets().open(fileName); //eg. over_view_style.data + int lenght1 = is1.available(); + buffer1 = new byte[lenght1]; + is1.read(buffer1); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (is1 != null) { + is1.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return buffer1; + } + + + public static byte[] getAssetsExtraStyle(Context context, String fileName) { + byte[] buffer1 = null; + InputStream is1 = null; + try { + is1 = context.getResources().getAssets().open(fileName); //eg. over_view_style_extra.data + int lenght1 = is1.available(); + buffer1 = new byte[lenght1]; + is1.read(buffer1); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (is1 != null) { + is1.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return buffer1; + } + + +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/CountDownView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/CountDownView.kt new file mode 100644 index 0000000000..5790ef8072 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/CountDownView.kt @@ -0,0 +1,65 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.os.Handler +import android.os.Message +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView +/** + * 倒计时View + */ +class CountDownView : AppCompatTextView, Handler.Callback { + private val mHandler = Handler(this) + private var mCountDownTime = DEFAULT_COUNT_DOWN_TIME + private var listener: CountDownListener? = null + + constructor(context: Context?) : super(context!!) {} + constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {} + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr) {} + + override fun handleMessage(message: Message): Boolean { + if (message.what == MSG_COUNT_DOWN) { + mCountDownTime-- + if (mCountDownTime > 0) { + text = "$mCountDownTime" + mHandler.sendEmptyMessageDelayed(MSG_COUNT_DOWN, DEFAULT_COUNT_DOWN_DELAY) + } else { + stopCountDown() + listener?.stop() + } + } + return false + } + + fun setCountDownListener(listener: CountDownListener?) { + this.listener = listener + } + + /** + * 启动倒计时 + */ + fun startCountDown(countDownTime:Int) { + mHandler.removeMessages(MSG_COUNT_DOWN) + text = "$countDownTime" + mCountDownTime=countDownTime + mHandler.sendEmptyMessageDelayed(MSG_COUNT_DOWN, DEFAULT_COUNT_DOWN_DELAY) + } + + /** + * 停止倒计时 + */ + fun stopCountDown() { + mHandler.removeMessages(MSG_COUNT_DOWN) + text = null + } + + interface CountDownListener { + fun stop() + } + + companion object { + private const val DEFAULT_COUNT_DOWN_TIME = 15 + private const val MSG_COUNT_DOWN = 1001 + private const val DEFAULT_COUNT_DOWN_DELAY = 1000L + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/FontAdaptionTextView.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/FontAdaptionTextView.java new file mode 100644 index 0000000000..816baff142 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/FontAdaptionTextView.java @@ -0,0 +1,47 @@ +package com.mogo.och.sweepercloud.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.TextView; + +public class FontAdaptionTextView extends TextView { + public FontAdaptionTextView(Context context) { + super(context); + } + + public FontAdaptionTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FontAdaptionTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (getMeasuredWidth() != 0) { + + //判断View字体行数 + if (getLayout().getLineCount() > 1) { + //获取view内部间隔 + int l = getPaddingLeft(); + int r = getPaddingRight(); + float pp = 0; + //计算字符串长度 + for (int i = 0; i < getLayout().getLineCount(); i++) { + pp = pp + l + r + getLayout().getLineWidth(i); + } + + //计算view的宽度与字符串长度的比例 + float f = getMeasuredWidth() / pp; + //获取缩放后的字体高度 + float s = getTextSize() * f; + //设置控件字体大小 + setTextSize(TypedValue.COMPLEX_UNIT_PX, s); + } + } + } + +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/LegendItemView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/LegendItemView.kt new file mode 100644 index 0000000000..b5598dce04 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/LegendItemView.kt @@ -0,0 +1,32 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.mogo.och.sweepercloud.R +import kotlinx.android.synthetic.main.sweeper_item_legend.view.* + +/** + * 任务路线全览图图例 + */ +class LegendItemView:LinearLayout { + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_item_legend, this) + } + + /** + * 设置数据 + */ + fun setData(resId:Int,text:String){ + sweeperLegendIcon.setImageResource(resId) + sweeperLegendText.text = text + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchConstraintLayout.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchConstraintLayout.java new file mode 100644 index 0000000000..0e5714b7cf --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchConstraintLayout.java @@ -0,0 +1,45 @@ +package com.mogo.och.sweepercloud.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.constraintlayout.widget.ConstraintLayout; + +/** + * 强制拦截所有touch时间的约束布局 + * + * @author tongchenfei + */ +public class NoTouchConstraintLayout extends ConstraintLayout { + private boolean interceptTouchEvent = false; + + 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 (interceptTouchEvent) { + return true; + } + return false; + } + + /** + * 设置事件拦截 + * + * @param interceptTouchEvent + */ + public void setInterceptTouchEvent(boolean interceptTouchEvent) { + this.interceptTouchEvent = interceptTouchEvent; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchFrameLayout.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchFrameLayout.java new file mode 100644 index 0000000000..10ff08d760 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/NoTouchFrameLayout.java @@ -0,0 +1,30 @@ +package com.mogo.och.sweepercloud.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +/** + * 强制拦截所有touch时间的约束布局 + * + * @author tongchenfei + */ +public class NoTouchFrameLayout extends FrameLayout { + public NoTouchFrameLayout(Context context) { + super(context); + } + + public NoTouchFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoTouchFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } +} diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SubTaskView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SubTaskView.kt new file mode 100644 index 0000000000..32559b6bdc --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SubTaskView.kt @@ -0,0 +1,48 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import com.mogo.och.sweepercloud.R +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.SubTaskInfo +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.TaskModel +import kotlinx.android.synthetic.main.sweeper_subtask_view.view.* + +/** + * 子任务View + */ +class SubTaskView : ConstraintLayout { + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_subtask_view, this) + } + + /** + * 设置子任务信息 + */ + fun setData(taskInfo: SubTaskInfo,isLastTask: Boolean = false) { + tvSubTaskName.text = taskInfo.subTaskName + tvSubTaskName.setTextColor(if (taskInfo.taskStatus==SweeperCommon.TaskStatus.RUNNING) Color.parseColor("#3BD2FF") else Color.parseColor("#FFFFFF")) + if (taskInfo.taskModel == TaskModel.MANUAL) {//人工驾驶子任务 + ivManualDriving.visibility = View.VISIBLE + } else { + ivManualDriving.visibility = View.GONE + } + if (taskInfo.taskStatus==SweeperCommon.TaskStatus.RUNNING) { + ivSubTask.setImageResource(R.drawable.sweeper_icon_select_subtask) + } else { + ivSubTask.setImageResource(R.drawable.sweeper_icon_not_select_subtask) + } + ivRightDownArrow.visibility = if (isLastTask) View.GONE else View.VISIBLE + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperCurrentTaskInfoView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperCurrentTaskInfoView.kt new file mode 100644 index 0000000000..3bdbcea852 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperCurrentTaskInfoView.kt @@ -0,0 +1,128 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import com.mogo.och.common.module.utils.DateTimeUtil +import com.mogo.och.sweepercloud.R +import com.zhjt.mogo.adas.data.sweeper.common.SweeperCommon.TaskStatus +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.SubTaskInfo +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.TaskInfo +import kotlinx.android.synthetic.main.sweeper_current_task_info.view.* + +/** + * 清扫车当前任务信息展示 + */ +class SweeperCurrentTaskInfoView : ConstraintLayout { + private val TAG: String = "SweeperCurrentTaskInfoView" + + //当前任务操作菜单 + private var listTask: List? = null + + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_current_task_info, this) + setSubTaskState(false) + } + + fun getAutoBtn(): TextView { + return tvStartAuto + } + + /** + * 设置当前任务数据 + */ + fun setData( + subTaskBean: TaskInfo?, + currentPosition: Int = -1 + ) { + subTaskBean?.apply { + this@SweeperCurrentTaskInfoView.listTask = subListList + tvTaskName.text = taskName + val calendarStart = DateTimeUtil.formatLongToCalendar(taskStartTime) + val calendarEnd = DateTimeUtil.formatLongToCalendar(taskEndTime) + tvTaskTime.text = "${DateTimeUtil.formatCalendarToString(calendarStart, DateTimeUtil.HH_mm)}-${ + DateTimeUtil.formatCalendarToString( + calendarEnd, + DateTimeUtil.HH_mm + ) + }" + } + listTask?.let { + //特殊处理当前暂无执行中任务的情况 + if (currentPosition == -1) { + setSubTaskState(false) + setCurrentData(currentPosition + 1) + } else { + setSubTaskState(it[currentPosition].taskStatus == TaskStatus.RUNNING) + setCurrentData(currentPosition) + } + } + } + + /** + * 设置子任务的状态 + */ + private fun setSubTaskState(isWorking: Boolean) { + if (isWorking) { + tvTaskState.text = "正在作业" + tvTaskState.setBackgroundResource(R.drawable.bg_shape_task_state_working) + } else { + tvTaskState.text = "暂未准备" + tvTaskState.setBackgroundResource(R.drawable.bg_shape_task_state_not_ready) + } + } + + /** + * 填充数据 + */ + private fun setCurrentData(currentPosition: Int) { + listTask?.let { + if (it.size == 1) { + preSubTask.setData(it[currentPosition], isLastTask = true) + currentSubTask.visibility = View.INVISIBLE + lastSubTask.visibility = View.INVISIBLE + } else if (it.size == 2) { + if (currentPosition == 0) { + preSubTask.setData(it[currentPosition]) + currentSubTask.setData(it[1], isLastTask = true) + } else { + preSubTask.setData(it[currentPosition - 1]) + currentSubTask.setData(it[currentPosition], isLastTask = true) + } + preSubTask.visibility = View.VISIBLE + currentSubTask.visibility = View.VISIBLE + lastSubTask.visibility = View.GONE + } else { + preSubTask.visibility = View.VISIBLE + currentSubTask.visibility = View.VISIBLE + lastSubTask.visibility = View.VISIBLE + //当前正在执行的任务是第一个子任务 + if (currentPosition == 0) { + preSubTask.setData(it[currentPosition]) + currentSubTask.setData(it[1]) + lastSubTask.setData(it[2], isLastTask = true) + //当前正在执行的任务是最后一个子任务 + } else if (currentPosition == it.size - 1) { + preSubTask.setData(it[currentPosition - 2]) + currentSubTask.setData(it[currentPosition - 1]) + lastSubTask.setData(it[currentPosition], isLastTask = true) + } else { + preSubTask.setData(it[currentPosition - 1]) + currentSubTask.setData(it[currentPosition]) + lastSubTask.setData(it[currentPosition + 1], isLastTask = true) + } + } + } + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperLimitingVelocityView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperLimitingVelocityView.kt new file mode 100644 index 0000000000..f7c2dff777 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperLimitingVelocityView.kt @@ -0,0 +1,59 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.LinearLayout +import com.mogo.eagle.core.data.enums.DataSourceType +import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener +import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.LimitingVelocityView_TAG +import com.mogo.eagle.core.function.api.datacenter.union.ILimitingVelocityListener +import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager +import com.mogo.eagle.core.function.call.v2x.CallerLimitingVelocityListenerManager +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.sweepercloud.R +import kotlinx.android.synthetic.main.sweeper_limiting_speed.view.* + +class SweeperLimitingVelocityView( + context: Context, + attrs: AttributeSet? = null, +) : LinearLayout(context, attrs), ILimitingVelocityListener, IViewControlListener { + + companion object { + private const val TAG = "SweeperLimitingVelocityView" + } + + init { + LayoutInflater.from(context).inflate(R.layout.sweeper_limiting_speed, this, true) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + CallerLimitingVelocityListenerManager.addListener(TAG, this) + CallerHmiViewControlListenerManager.addListener(LimitingVelocityView_TAG, this) + } + + override fun onLimitingVelocityChange(limitingVelocity: Int, sourceType: DataSourceType) { + ThreadUtils.runOnUiThread { + if (limitingVelocity > 0) { + this.visibility = View.VISIBLE + tvLimitingVelocity.text = "$limitingVelocity" + } else { + this.visibility = View.GONE + } + } + } + + override fun visible(v: Int) { + super.visible(v) + this.visibility = v + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerLimitingVelocityListenerManager.removeListener(TAG) + CallerHmiViewControlListenerManager.removeListener(LimitingVelocityView_TAG) + } + +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficDataView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficDataView.kt new file mode 100644 index 0000000000..6ee2639db7 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficDataView.kt @@ -0,0 +1,196 @@ +package com.mogo.och.sweepercloud.view + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import chassis.Chassis.GearPosition +import chassis.Chassis.LightSwitch +import chassis.ChassisStatesOuterClass.BMSSystemStates +import chassis.ChassisStatesOuterClass.SweeperFuTianTaskSystemStates +import com.elegant.utils.UiThreadHandler +import com.mogo.eagle.core.function.api.autopilot.* +import com.mogo.eagle.core.function.call.autopilot.* +import com.mogo.eagle.core.function.hmi.ui.widget.TapPositionView +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.sweepercloud.R +import planning.RoboSweeperTaskIndexOuterClass +import kotlin.math.roundToInt + +/** + * 车辆基本信息:方向盘下方的档位 转向灯 限速 速度 电量 水量 + */ +class SweeperTrafficDataView : ConstraintLayout, + IMoGoBatteryManagementSystemListener, + IMoGoChassisLamplightListener, + IMoGoChassisGearStateListener, + IMoGoSweeperFutianCleanSystemListener { + private var tapPositionView //方向盘下方的档位 + : TapPositionView? = null + private var speedImage //速度图标 + : ImageView? = null + private var speedTextView //速度值 + : TextView? = null + private var sweeperAutoState //自动驾驶状态 + : TextView? = null + private var tvBattery //电量百分比展示 + : TextView? = null + private var ivBgWaterWarning //水位预警背景图 + : ImageView? = null + private var ivWater //水位图标 + : ImageView? = null + + private val TAG = "SweeperTrafficDataView" + + // 底盘数据回调时间间隔 + private val VEHICLE_STATE_INTERVAL_MILLIS = 500L + + // 当前时间戳 + private var mCurrentTimeWaterMillis: Long = 0 + + private var mCurrentTimeBatteryMillis: Long = 0 + + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_traffic_data, this) + tapPositionView = findViewById(R.id.sweeperTrafficPosition) + speedImage = findViewById(R.id.sweeperSpeedImage) + speedTextView = findViewById(R.id.sweeperSpeedText) + sweeperAutoState = findViewById(R.id.sweeperAutoState) + tvBattery = findViewById(R.id.tvBattery) + ivBgWaterWarning = findViewById(R.id.sweeperIvBgWaterWarning) + ivWater = findViewById(R.id.sweeperIvWater) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + //电量 + CallerBatteryManagementSystemListenerManager.addListener(TAG, this) + //转向灯 + CallerChassisLamplightListenerManager.addListener(TAG, this) + //档位 + CallerChassisGearStateListenerManager.addListener(TAG, this) + //清扫车相关数据接口 + CallerSweeperFutianCleanSystemListenerManager.addListener(TAG, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerBatteryManagementSystemListenerManager.removeListener(TAG) + CallerChassisLamplightListenerManager.removeListener(TAG) + CallerChassisGearStateListenerManager.removeListener(TAG) + CallerSweeperFutianCleanSystemListenerManager.removeListener(TAG) + } + + override fun onSweeperFutianTaskIndexData(roboSweeperTaskIndex: RoboSweeperTaskIndexOuterClass.RoboSweeperTaskIndex) {} + override fun onSweeperFutianCleanSystemState(cleanSystemState: SweeperFuTianTaskSystemStates) { + val current = System.currentTimeMillis() + if (current - mCurrentTimeWaterMillis <= VEHICLE_STATE_INTERVAL_MILLIS) { + return + } + mCurrentTimeWaterMillis = current + d(SceneConstant.M_SWEEPER + TAG, "水位:${cleanSystemState.hasSecuCleanWaterTankLow()}") + UiThreadHandler.post { + if (cleanSystemState.hasSecuCleanWaterTankLow()) { //清水箱水位低不能清洗作业报警信号 + ivBgWaterWarning?.visibility = VISIBLE + ivWater?.isSelected = true + } else { + ivBgWaterWarning?.visibility = GONE + ivWater?.isSelected = false + } + } + + } + + @SuppressLint("SetTextI18n") + override fun onBatteryManagementSystemStates(states: BMSSystemStates) { + val current = System.currentTimeMillis() + if (current - mCurrentTimeBatteryMillis <= VEHICLE_STATE_INTERVAL_MILLIS) { + return + } + mCurrentTimeBatteryMillis = current + d(SceneConstant.M_SWEEPER + TAG, "电量:${states.bmsSoc}") + UiThreadHandler.post { + tvBattery?.text = "${states.bmsSoc.roundToInt()}%" + } + } + + /** + * 车辆转向灯 + * @param directionLight + */ + override fun onAutopilotLightSwitchData(lightSwitch: LightSwitch?) { + //转向灯状态 0是正常 1是左转 2是右转 + } + + /** + * 设置自动驾驶状态 + */ + fun setAutoState(state: Int) { + when (state) { + //不可自动驾驶 + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE -> { + sweeperAutoState?.text="自动驾驶" + sweeperAutoState?.setBackgroundResource(R.drawable.icon_not_auto) + } + //人工驾驶 + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE -> { + sweeperAutoState?.text="人工驾驶" + sweeperAutoState?.setBackgroundResource(R.drawable.icon_auto) + } + //自动驾驶中 + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING -> { + sweeperAutoState?.text="自动驾驶" + sweeperAutoState?.setBackgroundResource(R.drawable.icon_auto) + } + //平行驾驶 + IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING -> { + sweeperAutoState?.text="平行驾驶" + sweeperAutoState?.setBackgroundResource(R.drawable.icon_auto) + } + } + } + + /** + * 刹车灯 + * @param brakeLight + */ + override fun onAutopilotBrakeLightData(brakeLight: Boolean) { + d(TAG, "刹车灯:$brakeLight") + } + + /** + * 方向盘下方的档位 + * @param gear + */ + override fun onAutopilotGearData(gear: GearPosition) { + d(TAG, "司机屏档位$gear") + ThreadUtils.runOnUiThread { + tapPositionView?.updateWithGear(gear) + } + } + + fun getSpeedImage(): ImageView? { + return speedImage + } + + /** + * 速度设置 + */ + fun updateSpeedWithValue(newSpeed: Int) { + speedTextView?.text = newSpeed.toString() + speedImage?.setBackgroundResource(if (newSpeed > 60) R.drawable.sweeper_traffic_data_speed_warning else R.drawable.sweeper_bg_traffic_data_speed) + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficLightView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficLightView.kt new file mode 100644 index 0000000000..96a5af1933 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperTrafficLightView.kt @@ -0,0 +1,148 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.mogo.eagle.core.data.enums.DataSourceType +import com.mogo.eagle.core.data.enums.TrafficLightEnum +import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener +import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.sweepercloud.R +import kotlinx.android.synthetic.main.sweeper_traffic_light_view.view.* + +/** + * 清扫车:红绿灯view- + * + * Created on 2022/3/29 + */ +class SweeperTrafficLightView @JvmOverloads constructor( + context: Context?, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener { + + companion object { + private const val TAG = "SweeperTrafficLightView" + } + + private var mCurrentLightId = TrafficLightEnum.BLACK + + init { + init(context) + } + + private fun init(context: Context?) { + LayoutInflater.from(context).inflate(R.layout.sweeper_traffic_light_view, this, true) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + CallerTrafficLightListenerManager.addListener(TAG, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerTrafficLightListenerManager.removeListener(TAG) + } + + /** + * 展示红绿灯预警 + * + * @param checkLightId 0-都是默认,1-红,2-黄,3-绿 + * @param lightSource 1:云端下发;2:自车感知 + */ + override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) { + mCurrentLightId = checkLightId + updateTrafficLightIcon(checkLightId) + CallerLogger.d(SceneConstant.M_SWEEPER + TAG,"灯态类型:"+checkLightId.name +" 灯态来源:"+DataSourceType.getName(lightSource)) + } + + /** + * 关闭红绿灯预警展示,并重制灯态 + */ + override fun disableTrafficLight() { + UiThreadHandler.post { + mCurrentLightId = TrafficLightEnum.BLACK + sweeper_traffic_light_iv.setImageResource(R.drawable.sweeper_light_gay_nor) + sweeper_traffic_light_time_tv.text = "" + this@SweeperTrafficLightView.visibility = VISIBLE + CallerLogger.d(SceneConstant.M_SWEEPER + TAG,"灯态类型:disableTrafficLight") + } + } + + /** + * @param redNum 红灯倒计时 + * @param yellowNum 黄灯倒计时 + * @param greenNum 绿灯倒计时 + */ + override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) { + when (mCurrentLightId) { + TrafficLightEnum.RED -> changeCountdownRed(redNum) + TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum) + TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum) + else -> UiThreadHandler.post { sweeper_traffic_light_time_tv.text = "" } + } + } + + override fun changeCountdownRed(redNum: Int) { + UiThreadHandler.post { + if (redNum > 0) { + sweeper_traffic_light_time_tv.text = redNum.toString() + } else { + sweeper_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownGreen(greenNum: Int) { + UiThreadHandler.post { + if (greenNum > 0) { + sweeper_traffic_light_time_tv.text = greenNum.toString() + } else { + sweeper_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownYellow(yellowNum: Int) { + UiThreadHandler.post { + if (yellowNum > 0) { + sweeper_traffic_light_time_tv.text = yellowNum.toString() + } else { + sweeper_traffic_light_time_tv.text = "" + } + } + } + + /** + * 更新红绿灯icon + * + * @param lightId 0-都是默认,1-红,2-黄,3-绿 + */ + private fun updateTrafficLightIcon(lightId: TrafficLightEnum) { + UiThreadHandler.post { + when (lightId) { + TrafficLightEnum.RED -> { + sweeper_traffic_light_iv.setImageResource(R.drawable.sweeper_light_red_nor) + this@SweeperTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.YELLOW -> { + sweeper_traffic_light_iv.setImageResource(R.drawable.sweeper_lightyellow_nor) + this@SweeperTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.GREEN -> { + sweeper_traffic_light_iv.setImageResource(R.drawable.sweeper_light_green_nor) + this@SweeperTrafficLightView.visibility = VISIBLE + } + else -> { + sweeper_traffic_light_iv.setImageResource(R.drawable.sweeper_light_gay_nor) + this@SweeperTrafficLightView.visibility = VISIBLE + } + } + } + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperWorkModeView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperWorkModeView.kt new file mode 100644 index 0000000000..08dd7f348c --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/SweeperWorkModeView.kt @@ -0,0 +1,180 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import chassis.ChassisStatesOuterClass.SweeperFuTianTaskSystemStates +import com.elegant.utils.UiThreadHandler +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.callback.ICleaningModeStateCallback +import com.mogo.och.sweepercloud.constant.OperateStateEnum +import com.mogo.och.sweepercloud.ui.popwindow.SweeperOperatePanelPopWindow +import com.mogo.och.sweepercloud.util.SweeperFutianCmdUtil +import com.zhjt.mogo.adas.data.sweeper.task.SweeperTask.TaskModel +import kotlinx.android.synthetic.main.sweeper_work_mode.view.* + +/** + * 清扫车模式信息展示 + */ +class SweeperWorkModeView : ConstraintLayout,ICleaningModeStateCallback { + + private var isSelectPureSweepMode: Boolean = false + private val TAG = "SweeperWorkModeView" + //清扫模式选择面板 + private var mOperatePanelPopWindow: SweeperOperatePanelPopWindow? = null + + private var operateState: OperateStateEnum=OperateStateEnum.SYNCING_STATUS + + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_work_mode, this) + mOperatePanelPopWindow = SweeperOperatePanelPopWindow(context) + setShowOrHideCleanSystemState(OperateStateEnum.SYNCING_STATUS,null) + } + + /** + * 设置view + */ + fun setTrafficDataView(trafficDataView: SweeperTrafficDataView){ + //清扫模式选择面板打开关闭处理 + ivOpenOperatePanel.setOnClickListener { + if (mOperatePanelPopWindow?.isShowing != true) { + mOperatePanelPopWindow?.showAsDropDown( + trafficDataView, + resources.getDimension(R.dimen.dp_600).toInt(), + 0 + ) + UiThreadHandler.postDelayed({ + d(SceneConstant.M_SWEEPER + TAG, "operateState:"+operateState.code) + mOperatePanelPopWindow?.showSyncing(operateState) + + },300) + } else { + mOperatePanelPopWindow?.dismiss() + } + } + } + /** + * 设置清扫模式面板 + */ + fun setSweeperFutianCleanSystemState(taskType: TaskModel, cleanSystemState: SweeperFuTianTaskSystemStates?) { + // TODO:传递清扫车底盘数据给上装面板 + //mOperatePanelPopWindow?.setCleanSystemState(cleanSystemState, this@SweeperWorkModeView) + if (this.operateState.code==OperateStateEnum.STARTING_STATUS.code){ + return + } + //如果状态是同步中,在底盘首次回调时把状态强制修改成成功 + if (this.operateState.code==OperateStateEnum.SYNCING_STATUS.code){ + this.operateState=OperateStateEnum.SUCCESS_STATUS + d(SceneConstant.M_SWEEPER + TAG, "SystemState operateState:"+operateState.code) + } + //清扫车暂未选择清扫模式或者任务类型是人工驾驶子任务,则暂无清扫模式 + if (SweeperFutianCmdUtil.checkIfCleanMode(cleanSystemState) || taskType==TaskModel.MANUAL||taskType==TaskModel.DEFAULT_MODEL) { + setShowOrHideCleanSystemState(OperateStateEnum.NO_STATUS, cleanSystemState) + } else { + setShowOrHideCleanSystemState(OperateStateEnum.SUCCESS_STATUS, cleanSystemState) + } + } + + /** + * 设置清扫模式状态显示和隐藏 + */ + private fun setShowOrHideCleanSystemState(operateState: OperateStateEnum, cleanSystemState: SweeperFuTianTaskSystemStates?) { + when (operateState.code) { + OperateStateEnum.SYNCING_STATUS.code -> { + groupWorkModelPanel?.visibility = View.GONE + tvNoDataDesc?.visibility = View.VISIBLE + tvNoDataDesc?.text = "状态同步中,请稍后" + mOperatePanelPopWindow?.setIsOutsideTouchable(true) + } + OperateStateEnum.FAIL_STATUS.code -> { + groupWorkModelPanel?.visibility = View.GONE + tvNoDataDesc?.visibility = View.VISIBLE + tvNoDataDesc?.text = "上装启动失败" + mOperatePanelPopWindow?.setIsOutsideTouchable(true) + } + OperateStateEnum.STARTING_STATUS.code -> { + groupWorkModelPanel?.visibility = View.GONE + tvNoDataDesc?.visibility = View.VISIBLE + tvNoDataDesc?.text = "上装启动中..." + mOperatePanelPopWindow?.setIsOutsideTouchable(false) + } + OperateStateEnum.NO_STATUS.code -> { + groupWorkModelPanel?.visibility = View.GONE + tvNoDataDesc?.visibility = View.VISIBLE + tvNoDataDesc?.text = "暂无" + mOperatePanelPopWindow?.setIsOutsideTouchable(true) + } + else -> { + groupWorkModelPanel?.visibility = View.VISIBLE + tvNoDataDesc?.visibility = View.GONE + setCleanModeData(cleanSystemState) + mOperatePanelPopWindow?.setIsOutsideTouchable(true) + } + + } + } + + override fun cleaningModeState(operateState: OperateStateEnum, cleanSystemState: SweeperFuTianTaskSystemStates?, isSelectPureSweepMode: Boolean) { + this.isSelectPureSweepMode = isSelectPureSweepMode + this.operateState=operateState + setShowOrHideCleanSystemState(operateState, cleanSystemState) + } + + /** + * 设置清扫模式数据 + */ + private fun setCleanModeData(cleanSystemState: SweeperFuTianTaskSystemStates?) { + if (isSelectPureSweepMode) { + tvCleaningMode?.text = "纯扫模式" + groupWorkModelPanel?.visibility = View.VISIBLE + tvNoDataDesc?.visibility = View.GONE + } else { + if (SweeperFutianCmdUtil.checkIfCleanMode(cleanSystemState)) { + groupWorkModelPanel?.visibility = View.GONE + tvNoDataDesc?.visibility = View.VISIBLE + tvNoDataDesc?.text = "暂无" + return + } else { + groupWorkModelPanel?.visibility = View.VISIBLE + tvNoDataDesc?.visibility = View.GONE + // 作业模式 + if (cleanSystemState?.secuModWashSweepSts == true) tvCleaningMode?.text = "洗扫模式" + if (cleanSystemState?.secuModWashSts == true) tvCleaningMode?.text = "纯洗模式" + if (cleanSystemState?.secuWorkTonSts == true) tvCleaningMode?.text = "纯吸模式" + if (SweeperFutianCmdUtil.checkIfCleanModePureSweep(cleanSystemState)) tvCleaningMode?.text = "纯扫模式" + } + } + //清扫方向 + if (SweeperFutianCmdUtil.checkIfCleanDirection(cleanSystemState)) { + tvCleaningDirection.visibility = View.GONE + } else { + tvCleaningDirection.visibility = View.VISIBLE + // 左侧 + if (cleanSystemState?.secuWorkLeftSts == true) tvCleaningDirection?.text = "左侧" + // 右侧 + if (cleanSystemState?.secuWorkRightSts == true) tvCleaningDirection?.text = "右侧" + // 两侧 + if (cleanSystemState?.secuWorkOnBothsidesSts == true) tvCleaningDirection?.text = "两侧" + } + if (SweeperFutianCmdUtil.checkIfCleanIntensity(cleanSystemState)) { + tvCleaningIntensity.visibility = View.GONE + } else { + tvCleaningIntensity.visibility = View.VISIBLE + // 作业强度 + if (cleanSystemState?.secuWorkStandSts == true) tvCleaningIntensity?.text = "标准" + if (cleanSystemState?.secuWorkStrongSts == true) tvCleaningIntensity?.text = "强力" + } + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/TurnSignalView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/TurnSignalView.kt new file mode 100644 index 0000000000..59bbe0788d --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/TurnSignalView.kt @@ -0,0 +1,90 @@ +package com.mogo.och.sweepercloud.view + +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import android.widget.LinearLayout +import chassis.Chassis +import com.mogo.och.sweepercloud.R +import kotlinx.android.synthetic.main.sweeper_turn_signal.view.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +class TurnSignalView : LinearLayout { + constructor(context: Context?) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + private var init: Boolean = false + + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + } + + constructor( + context: Context?, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) { + } + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_turn_signal, this) + init = true + } + + /** + * 转向灯动画 + */ + fun setTurnLight(directionLight: Chassis.LightSwitch?) { + GlobalScope.launch(Dispatchers.Main) { + if (!init) { + return@launch + } + //根据左右进行显示和隐藏,实际要判断每个来的时间和频度 + when (directionLight) { + Chassis.LightSwitch.LIGHT_LEFT -> { //左转向 + leftSelectImage.visibility = View.VISIBLE + rightSelectImage.visibility = View.GONE + rightSelectImage.clearAnimation() + setAnimation(leftSelectImage) + } + Chassis.LightSwitch.LIGHT_RIGHT -> { //右转向 + leftSelectImage.visibility = View.GONE + rightSelectImage.visibility = View.VISIBLE + leftSelectImage.clearAnimation() + setAnimation(rightSelectImage) + } + else -> { //消失 + leftSelectImage.clearAnimation() + rightSelectImage.clearAnimation() + leftSelectImage.visibility = View.GONE + rightSelectImage.visibility = View.GONE + } + } + } + } + + //实现图片闪烁效果 + private fun setAnimation(imageView: ImageView) { + val animationSet = AnimatorSet() + val valueAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1.0f) + val valueAnimatorDisappare = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0f) + valueAnimator.duration = 1000 + valueAnimatorDisappare.duration = 800 + valueAnimator.repeatCount = -1 + valueAnimatorDisappare.repeatCount = -1 + animationSet.playTogether(valueAnimatorDisappare, valueAnimator) + animationSet.start() + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/VerticalDashLineView.java b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/VerticalDashLineView.java new file mode 100644 index 0000000000..bc6aae4605 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/VerticalDashLineView.java @@ -0,0 +1,64 @@ +package com.mogo.och.sweepercloud.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/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltMapOverView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltMapOverView.kt new file mode 100644 index 0000000000..5f157e0d67 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltMapOverView.kt @@ -0,0 +1,342 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.graphics.Color +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.ContextCompat +import com.amap.api.maps.AMap +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.constant.SweeperConst +import com.mogo.och.sweepercloud.database.bean.WeltDataBean +import com.mogo.och.sweepercloud.util.SweeperMapAssetStyleUtil +import kotlinx.android.synthetic.main.sweeper_welt_map_overview.view.* + + +/** + * 作业任务全览图 + */ +class WeltMapOverView : ConstraintLayout, IMoGoChassisLocationGCJ02Listener { + private var mTaskCoordinatesLatLng: MutableList = mutableListOf() //当前大任务的所有起终点集合 + private var mCarMarker: Marker? = null + private var mAMap: AMap? = null + private var mWeltPolylines: Polyline? = null + private var mRoutePolylines: Polyline?=null +// private val mLineMarkers: MutableList = mutableListOf() + private var mEndStationMarker: Marker? = null + private var mFirst: Boolean = false + + //清扫车任务地图 + private val TAG = "WeltMapOverView" + + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_welt_map_overview, this) + initAMapView() + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, this) + CallerChassisLocationGCJ02ListenerManager.setListenerHz(TAG,5) + } + + private fun initAMapView() { + mAMap = sweeperTextureMapView.map + // 地图文字标注 + mAMap?.showMapText(true) + //显示3D建筑物 + mAMap?.showBuildings(true) + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap?.mapType = AMap.MAP_TYPE_NIGHT + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap?.isTrafficEnabled = false + // 设置 锚点 图标 + mCarMarker = mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_car_big)) + .anchor(0.5f, 0.5f) + ) + // 设置地图的样式 + val uiSettings = mAMap?.uiSettings + uiSettings?.isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + uiSettings?.setAllGesturesEnabled(false) // 所有手势 + uiSettings?.isMyLocationButtonEnabled = false // 显示默认的定位按钮 + uiSettings?.setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(SweeperMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData(SweeperMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data")) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions) + //mAMap?.moveCamera(CameraUpdateFactory.zoomTo(15f)) + mAMap?.setOnMapLoadedListener(AMap.OnMapLoadedListener { + //mAMap?.moveCamera(CameraUpdateFactory.zoomTo(15f)) + CallerLogger.d(SceneConstant.M_SWEEPER + TAG, "WeltView---onMapLoaded") + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(SweeperMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData(SweeperMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data")) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions) + // 实时路况图层关闭,必须添加在loaded结束之后,其他位置不生效 + mAMap?.isTrafficEnabled = false + mAMap?.showBuildings(true) + }) + } + + /** + * 添加画线颜色值 + */ + private fun getRouteColorList(weltData: MutableList):MutableList { + val colorList= mutableListOf() + var nextWeltDataBean:WeltDataBean?=null + for (i in weltData.indices) { + val weltDataBean = weltData[i] + if(i+110){ + colorList.add(Color.TRANSPARENT) + continue + } + } + if (weltDataBean.weltDistance == SweeperConst.NONWELT) {//非贴边 + colorList.add(ContextCompat.getColor(context,R.color.sweeper_236299)) + } else if (weltDataBean.weltDistance < 0) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_c22101)) + } else if (weltDataBean.weltDistance >= 0 && weltDataBean.weltDistance < 0.1) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_4dffa4)) + } else if (weltDataBean.weltDistance >= 0.1 && weltDataBean.weltDistance < 0.2) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_ffdd4d)) + } else if (weltDataBean.weltDistance >= 0.2) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_ff912b)) + } + } + return colorList + } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + ThreadUtils.getSinglePool().run { + mogoLocation?.let { gnssInfo -> + val currentLatLng = LatLng(gnssInfo.latitude, gnssInfo.longitude) + //更新车辆位置 + mCarMarker?.rotateAngle = (360 - gnssInfo.heading).toFloat() + mCarMarker?.position = currentLatLng + mCarMarker?.setToTop() + //圈定地图显示范围 + val boundsBuilder = LatLngBounds.Builder() + if (mTaskCoordinatesLatLng.size > 0) { + //存放经纬度 + for (i in mTaskCoordinatesLatLng.indices) { + val latLng = mTaskCoordinatesLatLng[i] + boundsBuilder.include(latLng) + } + } + mRoutePolylines?.points?.forEach {latLng-> + boundsBuilder.include(latLng) + } + boundsBuilder.include(currentLatLng) + mAMap?.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100, 100, 100, 100)) + + } + } + } + + /** + * 根据贴边数据绘制任务路线 + */ + fun drawablePolyline(weltDatas: MutableList?) { + weltDatas?.let { + val colorList=getRouteColorList(it) + val coordinatesLatLngs= mutableListOf() + for (i in it.indices) { + coordinatesLatLngs.add(LatLng(it[i].locLat,it[i].locLon)) + } + if (coordinatesLatLngs.size > 2) { + //设置线段纹理 + mWeltPolylines?.remove() + val polylineOptions = PolylineOptions() + polylineOptions.addAll(coordinatesLatLngs) + polylineOptions.width(14f) //线段宽度 + polylineOptions.isUseTexture = false + polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapSquare) + polylineOptions.colorValues(colorList) + polylineOptions.visible(true) + // 绘制线 + mWeltPolylines = mAMap?.addPolyline(polylineOptions) + } + } + } + + /** + * 绘制起点和终点的marker + */ + private fun drawStartAndEndMarker(startPoint: LatLng, endPoint: LatLng) { +// val startMarker = mAMap?.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_big_start_maker_icon))) +// startMarker?.position = startPoint +// mLineMarkers.add(startMarker) +// val endMarker = mAMap?.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_big_end_maker_icon))) +// endMarker?.position = endPoint +// mLineMarkers.add(endMarker) + } + + private fun drawEndMarker(endPoint: LatLng){ + mEndStationMarker?.remove() + mEndStationMarker = mAMap?.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_big_end_maker_icon))) + mEndStationMarker?.position = endPoint + } + + /** + * 清除所有标记和路线 + */ + fun clearAllMarkerAndPolyline() { +// for (i in mLineMarkers.indices) { +// mLineMarkers[i]?.isVisible = false +// mLineMarkers[i]?.remove() +// } + mEndStationMarker?.remove() + mWeltPolylines?.remove() + mRoutePolylines?.remove() +// mLineMarkers.clear() + //mFirst = false + //showOrHiddenLegendData(false) + } + + /** + * 设置贴边数据 + */ + fun setWeltData(weltDatas: MutableList?, isWeltData: Boolean, distance: String?) { + drawablePolyline(weltDatas) + ThreadUtils.runOnUiThread { + distance?.let { + setDistance(it) + } + } + //if (!mFirst && isWeltData) { + // mFirst = true + // showOrHiddenLegendData(true) + //} + } + + /** + * 任务轨迹数据 + */ + fun setRouteList(routeList: ArrayList) { + val routeCoordinatesLatLngs= mutableListOf() + for (i in routeList.indices) { + routeCoordinatesLatLngs.add(LatLng(routeList[i].latitude,routeList[i].longitude)) + } + ThreadUtils.runOnUiThread { + drawRouteListPolyline(routeCoordinatesLatLngs) + } + } + + private fun drawRouteListPolyline(routeList: MutableList) { + mRoutePolylines?.remove() + val polylineOptions = PolylineOptions() + polylineOptions.width(14f) //线段宽度 + polylineOptions.isUseTexture = false + polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapSquare) + polylineOptions.color(ContextCompat.getColor(context,R.color.sweeper_3ba1cc)) + polylineOptions.addAll(routeList) + polylineOptions.visible(true) + mRoutePolylines=mAMap?.addPolyline(polylineOptions) + } + + /** + * 设置当前大任务的所有子任务起终点集合 + */ + fun setTaskListCoordinatesLatLng(coordinatesLatLng: MutableList) { + ThreadUtils.runOnUiThread { + this.mTaskCoordinatesLatLng = coordinatesLatLng + if (mTaskCoordinatesLatLng.size > 0) { + drawStartAndEndMarker(mTaskCoordinatesLatLng[0], mTaskCoordinatesLatLng[mTaskCoordinatesLatLng.size - 1]) + } + } + } + /** + * 设置当前任务终点 + */ + fun setCurrentTaskCoordinatesLatLng(coordinatesLatLng: LatLng) { + ThreadUtils.runOnUiThread { + drawEndMarker(coordinatesLatLng) + } + } + + /** + * 设置图例数据 + */ + private fun showOrHiddenLegendData(isShow: Boolean) { + groupLegend.visibility = if (isShow) View.VISIBLE else View.GONE + sweeperLegend1.setData(R.drawable.sweeper_legend1, "a<0") + sweeperLegend2.setData(R.drawable.sweeper_legend2, "0≤a<10") + sweeperLegend3.setData(R.drawable.sweeper_legend3, "10≤a<20") + sweeperLegend4.setData(R.drawable.sweeper_legend4, "a≥20") + sweeperLegend5.setData(R.drawable.sweeper_legend5, "非贴边") + sweeperLegend6.setData(R.drawable.sweeper_legend6, "未经过") + } + + private fun setDistance(distance: String) { + taskWeltDistanceTv.text="贴边:${distance}" + } + + fun setProgress(progress: String?) { + progress?.let { + if ("0" == progress) { + taskProgressTv.visibility = View.GONE + taskWeltDistanceTv.visibility = View.GONE + showOrHiddenLegendData(false) + } else { + taskProgressTv.visibility = View.VISIBLE + taskWeltDistanceTv.visibility = View.VISIBLE + taskProgressTv.text = it + showOrHiddenLegendData(true) + } + } + } + fun onCreateView(savedInstanceState: Bundle?) { + sweeperTextureMapView.onCreate(savedInstanceState) + } + + fun onResume() { + sweeperTextureMapView.onResume() + } + + fun onPause() { + sweeperTextureMapView.onPause() + } + + fun onDestroy() { + sweeperTextureMapView.onDestroy() + } + + fun getSweeperSwitchToSmall(): ImageView { + return sweeperSwitchToSmall + } +} \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltSmallMapView.kt b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltSmallMapView.kt new file mode 100644 index 0000000000..4db516bb7a --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/java/com/mogo/och/sweepercloud/view/WeltSmallMapView.kt @@ -0,0 +1,304 @@ +package com.mogo.och.sweepercloud.view + +import android.content.Context +import android.graphics.Color +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.ContextCompat +import com.amap.api.maps.AMap +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.sweepercloud.R +import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean +import com.mogo.och.sweepercloud.constant.SweeperConst +import com.mogo.och.sweepercloud.database.bean.WeltDataBean +import com.mogo.och.sweepercloud.util.SweeperMapAssetStyleUtil +import kotlinx.android.synthetic.main.sweeper_welt_small_map_view.view.* + + +/** + * 作业任务小地图 + */ +class WeltSmallMapView : ConstraintLayout, IMoGoChassisLocationGCJ02Listener { + private var mTaskCoordinatesLatLng: MutableList = mutableListOf() //当前大任务的所有起终点集合 + private var mCarMarker: Marker? = null + private var mAMap: AMap? = null + private var mWeltPolylines: Polyline? = null + private var mRoutePolylines: Polyline?=null +// private val mLineMarkers: MutableList = mutableListOf() + private var endStationMarker:Marker? = null + + //清扫车任务地图 + private val TAG = "WeltMapView" + + constructor(context: Context) : super(context) {} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {} + + private fun initView(context: Context) { + LayoutInflater.from(context).inflate(R.layout.sweeper_welt_small_map_view, this) + initAMapView() + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, this) + CallerChassisLocationGCJ02ListenerManager.setListenerHz(TAG,5) + } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + d(SceneConstant.M_SWEEPER + TAG, "mogoLocation:$mogoLocation") + ThreadUtils.getSinglePool().run { + mogoLocation?.let { + val currentLatLng = LatLng(it.latitude, it.longitude) + drawCarMarker(mogoLocation) + //圈定地图显示范围 + val boundsBuilder = LatLngBounds.Builder() + if (mTaskCoordinatesLatLng.size > 0) { + //存放经纬度 + for (i in mTaskCoordinatesLatLng.indices) { + boundsBuilder.include(mTaskCoordinatesLatLng[i]) + } + } + mRoutePolylines?.points?.forEach {latLng-> + boundsBuilder.include(latLng) + } + boundsBuilder.include(currentLatLng) + mAMap!!.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(), 100, 100, 100, 100)) + } + } + } + + /** + * 绘制自车 + * + * @param location + */ + private fun drawCarMarker(location: MogoLocation?) { + if (location == null) return + val currentLatLng = LatLng(location.latitude, location.longitude) + //更新车辆位置 + if (mCarMarker != null) { + mCarMarker!!.rotateAngle = (360 - location.heading).toFloat() + mCarMarker!!.position = currentLatLng + mCarMarker!!.setToTop() + } + } + + private fun initAMapView() { + mAMap = sweeperSmallTextureMapView?.map + // 地图文字标注 + mAMap?.showMapText(true) + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap?.mapType = AMap.MAP_TYPE_NIGHT + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap?.isTrafficEnabled = false + // 设置 锚点 图标 + mCarMarker = mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_car_small)) + .anchor(0.5f, 0.5f) + ) + // 设置地图的样式 + val uiSettings = mAMap?.uiSettings + uiSettings?.isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + uiSettings?.setAllGesturesEnabled(false) // 所有手势 + uiSettings?.isMyLocationButtonEnabled = false // 显示默认的定位按钮 + uiSettings?.setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(SweeperMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData(SweeperMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data")) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions) + mAMap?.setOnMapLoadedListener(AMap.OnMapLoadedListener { + d(SceneConstant.M_SWEEPER + TAG, "WeltView---onMapLoaded") + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(SweeperMapAssetStyleUtil.getAssetsStyle(context, "map_style.data")) + .setStyleExtraData(SweeperMapAssetStyleUtil.getAssetsExtraStyle(context, "map_style_extra.data")) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions) + mAMap?.setPointToCenter(sweeperSmallTextureMapView.width / 2, sweeperSmallTextureMapView.height / 2) + }) + } + + /** + * 根据贴边数据绘制任务路线 + */ + private fun drawablePolyline(weltDatas: MutableList?) { + weltDatas?.let { + val colorList = getRouteColorList(it) + val coordinatesLatLngs = mutableListOf() + for (i in it.indices) { + coordinatesLatLngs.add(LatLng(it[i].locLat,it[i].locLon)) + } + if (coordinatesLatLngs.size > 2) { + //设置线段纹理 + mWeltPolylines?.remove() + val polylineOptions = PolylineOptions() + polylineOptions.addAll(coordinatesLatLngs) + polylineOptions.width(14f) //线段宽度 + polylineOptions.isUseTexture = false + polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapSquare) + polylineOptions.colorValues(colorList) + polylineOptions.visible(true) + // 绘制线 + mWeltPolylines = mAMap?.addPolyline(polylineOptions) + } + } + } + + /** + * 添加画线颜色值 + */ + private fun getRouteColorList(weltData: MutableList): MutableList { + val colorList = mutableListOf() + var nextWeltDataBean:WeltDataBean?=null + for (i in weltData.indices) { + val weltDataBean = weltData[i] + if(i+110){ + colorList.add(Color.TRANSPARENT) + continue + } + } + + if (weltDataBean.weltDistance == SweeperConst.NONWELT) {//非贴边 + colorList.add(ContextCompat.getColor(context,R.color.sweeper_236299)) + } else if (weltDataBean.weltDistance < 0) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_c22101)) + } else if (weltDataBean.weltDistance >= 0 && weltDataBean.weltDistance < 0.1) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_4dffa4)) + } else if (weltDataBean.weltDistance >= 0.1 && weltDataBean.weltDistance < 0.2) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_ffdd4d)) + } else if (weltDataBean.weltDistance >= 0.2) { + colorList.add(ContextCompat.getColor(context,R.color.sweeper_ff912b)) + } + } + return colorList + } + + /** + * 设置当前大任务的所有子任务起终点集合 + */ + fun setTaskListCoordinatesLatLng(coordinatesLatLng: MutableList) { + ThreadUtils.runOnUiThread { + this.mTaskCoordinatesLatLng = coordinatesLatLng + } + } + + /** + * 设置当前任务的终点 + */ + fun setCurrentTaskCoordinatesLatLng(coordinatesLatLng: LatLng) { + ThreadUtils.runOnUiThread { + endStationMarker?.remove() + endStationMarker = mAMap?.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.sweeper_small_end_marker_icon))) + endStationMarker?.position = coordinatesLatLng + } + } + + /** + * 清除所有标记和路线 + */ + fun clearAllMarkerAndPolyline() { + endStationMarker?.remove() + mWeltPolylines?.remove() + mRoutePolylines?.remove() + } + + fun getSwitchToBig(): ImageView = sweeperSwitchToBig + /** + * 设置贴边数据 + */ + fun setWeltData(weltDatas: MutableList, isWeltData: Boolean, distance: String) { + drawablePolyline(weltDatas) + ThreadUtils.runOnUiThread { + setWeltDistance(distance) + } + } + + /** + * 设置贴边距离 + */ + private fun setWeltDistance(distance: String) { + taskWeltDistanceTv.text = "贴边:${distance}" + } + + /** + * 设置任务轨迹数据 + */ + fun setRouteList(routeList: ArrayList) { + val routeCoordinatesLatLngs = mutableListOf() + for (i in routeList.indices) { + routeCoordinatesLatLngs.add(LatLng(routeList[i].latitude, routeList[i].longitude)) + } + ThreadUtils.runOnUiThread { + drawRouteListPolyline(routeCoordinatesLatLngs) + } + } + + private fun drawRouteListPolyline(routeList: MutableList) { + mRoutePolylines?.remove() + val polylineOptions = PolylineOptions() + polylineOptions.addAll(routeList) + polylineOptions.width(14f) //线段宽度 + polylineOptions.isUseTexture = false + polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapSquare) + polylineOptions.color(ContextCompat.getColor(context,R.color.sweeper_3ba1cc)) + polylineOptions.visible(true) + mRoutePolylines=mAMap?.addPolyline(polylineOptions) + } + + /** + * 设置任务进度 + */ + fun setTaskProgress(progress: String?) { + if (progress == "0") { + taskWeltDistanceTv.visibility = View.GONE + taskProgressTv.visibility = View.GONE + } else { + taskWeltDistanceTv.visibility = View.VISIBLE + taskProgressTv.visibility = View.VISIBLE + taskProgressTv.text = progress + } + + } + + fun onCreateView(savedInstanceState: Bundle?) { + sweeperSmallTextureMapView?.onCreate(savedInstanceState) + } + + fun onResume() { + sweeperSmallTextureMapView?.onResume() + } + + fun onPause() { + sweeperSmallTextureMapView?.onPause() + } + + fun onDestroy() { + sweeperSmallTextureMapView?.onDestroy() + } +} \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/bg_shape_work_mode.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/bg_shape_work_mode.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/bg_shape_work_mode.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/bg_shape_work_mode.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/bg_sweeper_operate_panel.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/bg_sweeper_operate_panel.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/bg_sweeper_operate_panel.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/bg_sweeper_operate_panel.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_ai_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_ai_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_ai_normal.png diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_auto.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_auto.png new file mode 100755 index 0000000000..b76ce3dd2b Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_auto.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_battery.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_battery.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_battery.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_battery.png diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_manual_driving.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_manual_driving.png new file mode 100755 index 0000000000..8e1fa65d96 Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_manual_driving.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_message_box.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_message_box.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_message_box.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_message_box.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_message_box_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_message_box_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_message_box_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_message_box_pressed.png diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_not_auto.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_not_auto.png new file mode 100755 index 0000000000..3cb8679a55 Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_not_auto.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_right_down_arrow.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_right_down_arrow.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_right_down_arrow.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_right_down_arrow.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_level_warning.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_level_warning.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_level_warning.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_level_warning.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_select.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_select.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/icon_water_select.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/icon_water_select.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/no_task_data.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/no_task_data.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/no_task_data.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/no_task_data.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_base_slide_block.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data_speed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data_speed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data_speed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_bg_traffic_data_speed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_big_end_maker_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_big_end_maker_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_big_end_maker_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_big_end_maker_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_big_start_maker_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_big_start_maker_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_big_start_maker_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_big_start_maker_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_car_big.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_car_big.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_car_big.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_car_big.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_car_small.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_car_small.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_car_small.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_car_small.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_card_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_card_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_card_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_card_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_card_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_card_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_card_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_card_pressed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_clean_mode_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_clean_mode_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_clean_mode_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_clean_mode_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_close_navi_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_close_navi_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_close_navi_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_close_navi_icon.png diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_loading.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_loading.png new file mode 100644 index 0000000000..0c2d84f448 Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_loading.png differ diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotate.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotate.png new file mode 100755 index 0000000000..3e49a07b00 Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotate.png differ diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation.png new file mode 100644 index 0000000000..9f33e0d8dd Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation.png differ diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation_background.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation_background.png new file mode 100755 index 0000000000..8d3650e9ba Binary files /dev/null and b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_cloud_rotation_background.png differ diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_collect_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_collect_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_collect_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_collect_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_collect_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_collect_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_collect_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_collect_pressed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_full_screen_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_full_screen_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_full_screen_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_full_screen_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_ai_select.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_ai_select.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_ai_select.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_ai_select.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_select.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_select.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_select.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_bad_case_select.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_close.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_close.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_close.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_close.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_open.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_open.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_open.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_msg_box_open.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_not_select_subtask.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_not_select_subtask.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_not_select_subtask.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_not_select_subtask.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_select_subtask.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_select_subtask.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_icon_select_subtask.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_icon_select_subtask.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_gay_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_gay_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_gay_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_gay_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_green_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_light_red_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_lightyellow_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_line.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_line.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_line.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_loading_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_loading_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_loading_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_loading_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_navi_refresh.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_navi_refresh.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_navi_refresh.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_navi_refresh.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_och_dot_line.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_btn_bg.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_setting_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_setting_pressed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_small_end_marker_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_small_end_marker_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_small_end_marker_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_small_end_marker_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_small_start_marker_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_small_start_marker_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_small_start_marker_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_small_start_marker_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_big_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_big_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_big_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_big_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_big_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_big_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_big_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_big_pressed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_long.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_medium.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_small_normal.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_small_normal.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_small_normal.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_small_normal.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_small_pressed.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_small_pressed.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_switch_map_small_pressed.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_switch_map_small_pressed.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_list_left_select_icon.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_list_left_select_icon.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_list_left_select_icon.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_list_left_select_icon.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_not_working.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_not_working.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_not_working.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_not_working.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_working.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_working.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_task_working.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_task_working.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_traffic_data_speed_warning.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_traffic_data_speed_warning.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_traffic_data_speed_warning.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_traffic_data_speed_warning.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/sweeper_unselect_btn.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_left_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_left_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_left_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_left_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_left_select.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_left_select.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_left_select.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_left_select.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_right_nor.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_right_nor.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_right_nor.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_right_nor.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_right_select.png b/OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_right_select.png similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable-xhdpi/turn_signal_right_select.png rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable-xhdpi/turn_signal_right_select.png diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_bubble.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_bubble.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_bubble.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_bubble.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_clean_mode.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_clean_mode.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_clean_mode.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_clean_mode.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_dialog_cloud_view.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_dialog_cloud_view.xml new file mode 100644 index 0000000000..a0f105b0ac --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_dialog_cloud_view.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_dialog_no_title.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_dialog_no_title.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_dialog_no_title.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_dialog_no_title.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_left_bottom_round.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_left_bottom_round.xml new file mode 100644 index 0000000000..5d247295b3 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_left_bottom_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_left_right_bottom_round.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_left_right_bottom_round.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_left_right_bottom_round.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_left_right_bottom_round.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_right_bottom_round.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_right_bottom_round.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_right_bottom_round.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_right_bottom_round.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_panel.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_panel.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_panel.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_panel.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_state_not_ready.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_state_not_ready.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_state_not_ready.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_state_not_ready.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_state_working.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_state_working.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_task_state_working.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_task_state_working.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_welt_panel.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_welt_panel.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_shape_welt_panel.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_shape_welt_panel.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_close.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_default.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_disabled.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_open.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_sweeper_operate_panel_btn_pressed.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/bg_task_menu.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_task_menu.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/bg_task_menu.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/bg_task_menu.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/icon_more.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/icon_more.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/icon_more.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/icon_more.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_ai_collect_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_ai_collect_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_ai_collect_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_ai_collect_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_bad_case_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_bad_case_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_bad_case_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_bad_case_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_bg_waring_limiting_velocity.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_bg_waring_limiting_velocity.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_bg_waring_limiting_velocity.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_bg_waring_limiting_velocity.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_cloud_rotation_layer.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_cloud_rotation_layer.xml new file mode 100644 index 0000000000..b4793b37ad --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_cloud_rotation_layer.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_collect_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_collect_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_collect_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_collect_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend1.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend1.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend1.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend1.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend2.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend2.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend2.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend2.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend3.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend3.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend3.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend3.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend4.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend4.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend4.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend4.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend5.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend5.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend5.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend5.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend6.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend6.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_legend6.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_legend6.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_list_left_top_line.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_list_left_top_line.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_list_left_top_line.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_list_left_top_line.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_message_box.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_message_box.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_message_box.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_message_box.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operate_panel_btn1_bg_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operate_panel_btn2_bg_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_bg.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_bg.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_bg_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_bg_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_bg_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_select_bg.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_select_bg.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_operation_status_select_bg.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_operation_status_select_bg.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_oprate_panel_cancel_btn.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_oprate_panel_cancel_btn.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_oprate_panel_cancel_btn.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_oprate_panel_cancel_btn.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_oprate_panel_reset_btn.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_oprate_panel_reset_btn.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_oprate_panel_reset_btn.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_oprate_panel_reset_btn.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_anchor_bkg.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_panel_anchor_bkg.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_anchor_bkg.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_panel_anchor_bkg.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_bkg.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_panel_bkg.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_panel_bkg.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_panel_bkg.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_refresh.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_refresh.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_refresh.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_refresh.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_selector_msg_box.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_selector_msg_box.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_selector_msg_box.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_selector_msg_box.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_setting_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_setting_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_setting_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_setting_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_green_dash_line.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_station_green_dash_line.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_green_dash_line.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_station_green_dash_line.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_v_green_dash.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_station_v_green_dash.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_station_v_green_dash.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_station_v_green_dash.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_card_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_card_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_card_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_card_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_bg.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_bg.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_bg.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_bg.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_big_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_big_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_big_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_big_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_small_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_small_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_switch_map_small_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_switch_map_small_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_dividing_line1_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_task_dividing_line1_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_dividing_line1_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_task_dividing_line1_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_dividing_line2_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_task_dividing_line2_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_dividing_line2_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_task_dividing_line2_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_list_selected.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_upload_autopoiltstate.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_task_list_selected.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_upload_autopoiltstate.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_water_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_water_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/sweeper_water_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/sweeper_water_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/turn_signal_left_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/turn_signal_left_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/turn_signal_left_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/turn_signal_left_selector.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/drawable/turn_signal_right_selector.xml b/OCH/sweeper/sweeper-cloud/src/main/res/drawable/turn_signal_right_selector.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/drawable/turn_signal_right_selector.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/drawable/turn_signal_right_selector.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_loading.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_loading.xml new file mode 100644 index 0000000000..c2154df812 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_loading.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_view.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_view.xml new file mode 100644 index 0000000000..a0b0c6a17b --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_cloud_view.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/dialog_sweeper_manual_driving.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_manual_driving.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/layout/dialog_sweeper_manual_driving.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_manual_driving.xml diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/dialog_sweeper_no_title.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_no_title.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/layout/dialog_sweeper_no_title.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/layout/dialog_sweeper_no_title.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_och_sweeper.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_och_sweeper.xml new file mode 100644 index 0000000000..0c276dceb1 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_och_sweeper.xml @@ -0,0 +1,36 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_welt_map_overview.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_welt_map_overview.xml new file mode 100644 index 0000000000..b59e5e23eb --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/layout/fragment_welt_map_overview.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-sweeper/src/main/res/layout/sweeper_amap_navi_view.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/sweeper_amap_navi_view.xml similarity index 100% rename from OCH/mogo-och-sweeper/src/main/res/layout/sweeper_amap_navi_view.xml rename to OCH/sweeper/sweeper-cloud/src/main/res/layout/sweeper_amap_navi_view.xml diff --git a/OCH/sweeper/sweeper-cloud/src/main/res/layout/sweeper_base_fragment.xml b/OCH/sweeper/sweeper-cloud/src/main/res/layout/sweeper_base_fragment.xml new file mode 100644 index 0000000000..f600703e61 --- /dev/null +++ b/OCH/sweeper/sweeper-cloud/src/main/res/layout/sweeper_base_fragment.xml @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +