Merge branch 'master' into dev_robouiadapter_1062_221117_1.6.2

# Conflicts:
#	OCH/mogo-och-bus-passenger/src/main/res/layout/bus_p_route_fragment.xml
#	OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/video/VideoActivity.kt
#	OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_passenger_check_panel.xml
#	OCH/mogo-och-taxi/src/main/res/layout/taxi_being_order.xml
#	OCH/mogo-och-taxi/src/main/res/layout/taxi_navi_view.xml
#	app/src/main/java/com/mogo/launcher/MogoApplication.java
#	core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt
#	core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_auto_pilot_check.xml
#	core/function-impl/mogo-core-function-hmi/src/main/res/values-xhdpi-2560x1440/color.xml
#	gradle.properties
This commit is contained in:
yangyakun
2022-11-18 10:36:15 +08:00
527 changed files with 18862 additions and 3434 deletions

View File

@@ -3,4 +3,5 @@
2. mogo-och-bus-passengerBus乘客端BusPassenger
3. mogo-och-taxiTaxi司机端Taxi
4. mogo-och-taxi-passengerTaxi乘客端TaxiPassenger
5. mogo-och-noop空实现用于独立鹰眼打包
5. mogo-och-noop空实现用于独立鹰眼打包
6. mogo-och-sweeper: 清扫车Sweeper

View File

@@ -1,6 +1,7 @@
package com.mogo.och.bus.passenger.adapter;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -14,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.mogo.och.bus.passenger.R;
import com.mogo.och.bus.passenger.bean.BusPassengerStation;
import com.mogo.och.common.module.utils.BlinkAnimationUtil;
import com.mogo.och.common.module.wigets.MarqueeTextView;
import java.util.List;
@@ -58,9 +60,11 @@ public class BusPassengerLineStationsAdapter extends RecyclerView.Adapter<Recycl
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_current_station_txt_color));
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_green);
BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
}else {
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_station_txt_color));
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_gray);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
}
}else{
if (position == mStations.size() - 1){
@@ -77,22 +81,26 @@ public class BusPassengerLineStationsAdapter extends RecyclerView.Adapter<Recycl
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_station_txt_color));
viewHolder.curArrowBg.setImageResource(R.drawable.bus_p_line_grey);
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_gray);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
} else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//刚到站未离开的
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_current_station_txt_color));
viewHolder.curArrowBg.setImageResource(R.drawable.bus_p_line_grey);
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_green);
BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
}else if (station.getDrivingStatus() == STATION_STATUS_ARRIVING && preStation.isLeaving()){//即将到站
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_current_station_txt_color));
viewHolder.curArrowBg.setImageResource(R.drawable.bus_p_line_green);
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_green);
BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
}else if (station.getDrivingStatus() == STATION_STATUS_ARRIVING &&
(preStation.getDrivingStatus() == STATION_STATUS_ARRIVING
|| preStation.getDrivingStatus() == STATION_STATUS_STOPPED)){ //未到站的并且前面也是未到站或者刚到站的
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.bus_p_station_txt_color));
viewHolder.curArrowBg.setImageResource(R.drawable.bus_p_line_blue);
viewHolder.stationCircle.setImageResource(R.drawable.bus_p_point_blue);
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
}
}
}
@@ -103,7 +111,7 @@ public class BusPassengerLineStationsAdapter extends RecyclerView.Adapter<Recycl
}
}
class StationViewHolder extends RecyclerView.ViewHolder{
public TextView stationName;
public MarqueeTextView stationName;
public ImageView stationCircle;
public ImageView curArrowBg;
public ImageView stationStationTag;

View File

@@ -39,8 +39,8 @@ 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.BusPassengerServiceCallback;
import com.mogo.och.bus.passenger.network.BusPassengerServiceManager;
import com.mogo.och.common.module.biz.network.OchCommonServiceCallback;
import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil;
import com.mogo.service.intent.IMogoIntentListener;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
@@ -129,8 +129,8 @@ public class BusPassengerModel {
}
private void queryDriverOperationStatus() {
BusPassengerServiceManager.getInstance().queryDriverOperationStatus(mContext
, new BusPassengerServiceCallback<BusPassengerOperationStatusResponse>() {
BusPassengerServiceManager.queryDriverOperationStatus(mContext
, new OchCommonServiceCallback<BusPassengerOperationStatusResponse>() {
@Override
public void onSuccess(BusPassengerOperationStatusResponse data) {
if (data == null || data.data == null) return;
@@ -149,8 +149,8 @@ public class BusPassengerModel {
}
public void queryDriverSiteByCoordinate(){
BusPassengerServiceManager.getInstance().queryDriverSiteByCoordinate(mContext
, new BusPassengerServiceCallback<BusPassengerRoutesResponse>() {
BusPassengerServiceManager.queryDriverSiteByCoordinate(mContext
, new OchCommonServiceCallback<BusPassengerRoutesResponse>() {
@Override
public void onSuccess(BusPassengerRoutesResponse data) {
if ( data == null
@@ -172,8 +172,10 @@ public class BusPassengerModel {
@Override
public void onFail(int code, String msg) {
//code = 1003; message = bus车辆已收车或未出车;
//code = 1003; message = bus车辆已收车或未出车;bus driver shadow,not exists
if (code == 1003){
routesResult = null;
startOrStopCalculateRouteInfo(false);
queryDriverOperationDelay();
}
}

View File

@@ -1,15 +0,0 @@
package com.mogo.och.bus.passenger.network;
/**
* Created on 2022/3/31
*/
public interface BusPassengerServiceCallback<T> {
void onSuccess(T data);
void onFail(int code, String msg);
default void onError() {
}
}

View File

@@ -1,118 +0,0 @@
package com.mogo.och.bus.passenger.network;
import android.content.Context;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.eagle.core.data.BaseData;
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager;
import com.mogo.eagle.core.network.MoGoRetrofitFactory;
import com.mogo.eagle.core.network.RequestOptions;
import com.mogo.eagle.core.network.SubscribeImpl;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.och.bus.passenger.bean.BusPassengerOperationStatusResponse;
import com.mogo.och.bus.passenger.bean.BusPassengerQueryLineRequest;
import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResponse;
import com.mogo.och.bus.passenger.constant.BusPassengerConst;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
/**
* Created on 2022/3/31
*/
public class BusPassengerServiceManager {
private static final String TAG = BusPassengerServiceManager.class.getSimpleName();
private static final class SingletonHolder {
private static final BusPassengerServiceManager INSTANCE = new BusPassengerServiceManager();
}
public static BusPassengerServiceManager getInstance() {
return SingletonHolder.INSTANCE;
}
private BusPassengerServiceApi mBusPassengerServiceApi;
private BusPassengerServiceManager() {
if (mBusPassengerServiceApi == null){
mBusPassengerServiceApi = MoGoRetrofitFactory.getInstance(
BusPassengerConst.getBaseUrl()).create(BusPassengerServiceApi.class);
}
}
/**
* 获取Bus司机端的sn
* @return
*/
private String getDriverAppSn(){
return CallerTelematicManager.INSTANCE.getServerToken();
// return "X2020211111NG0XNFK";
}
/**
* 查询绑定行驶的小巴车路线
* @param context
* @param callback
*/
public void queryDriverSiteByCoordinate(Context context
,BusPassengerServiceCallback<BusPassengerRoutesResponse> callback){
mBusPassengerServiceApi.queryDriverSiteByCoordinate(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusPassengerQueryLineRequest(getDriverAppSn()))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"queryDriverSiteByCoordinate"));
}
/**
* 查询司机端出车收车状态,以及车牌号
* @param context
* @param callback
*/
public void queryDriverOperationStatus(Context context, BusPassengerServiceCallback<BusPassengerOperationStatusResponse> callback){
mBusPassengerServiceApi.queryDriverOperationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,getDriverAppSn())
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"queryDriverOperationStatus"));
}
private <T extends BaseData> SubscribeImpl getSubscribeImpl(
Context context, BusPassengerServiceCallback<T> callback, String apiName) {
return new SubscribeImpl<T>(RequestOptions.create(context)) {
@Override
public void onSuccess(T o) {
super.onSuccess(o);
CallerLogger.INSTANCE.e(M_BUS_P + TAG,apiName +
": onSuccess() " + o.msg);
if (callback != null) {
callback.onSuccess(o);
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
CallerLogger.INSTANCE.e(M_BUS_P + TAG,apiName +
": onError() " + e.getMessage());
if (callback != null) {
callback.onError();
}
}
@Override
public void onError(String message, int code) {
super.onError(message, code);
CallerLogger.INSTANCE.e(M_BUS_P + TAG,String.format(apiName +
": onError() code = %d; message = %s;", code, message));
if (callback != null) {
callback.onFail(code, message);
}
}
};
}
}

View File

@@ -0,0 +1,62 @@
package com.mogo.och.bus.passenger.network
import android.content.Context
import com.mogo.och.bus.passenger.constant.BusPassengerConst.Companion.getBaseUrl
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager.getServerToken
import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResponse
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.och.bus.passenger.bean.BusPassengerQueryLineRequest
import com.mogo.och.bus.passenger.bean.BusPassengerOperationStatusResponse
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.och.common.module.biz.network.OchCommonServiceCallback
import com.mogo.och.common.module.biz.network.OchCommonSubscribeImpl
import com.mogo.och.common.module.biz.network.interceptor.transformTry
/**
* Created on 2022/3/31
*/
object BusPassengerServiceManager {
private var mBusPassengerServiceApi = MoGoRetrofitFactory.getInstance(getBaseUrl())
.create(BusPassengerServiceApi::class.java)
/**
* 获取Bus司机端的sn
* @return
*/
private val driverAppSn: String
get() = getServerToken()
/**
* 查询绑定行驶的小巴车路线
* @param context
* @param callback
*/
@JvmStatic
fun queryDriverSiteByCoordinate(
context: Context, callback: OchCommonServiceCallback<BusPassengerRoutesResponse>?
) {
mBusPassengerServiceApi.queryDriverSiteByCoordinate(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusPassengerQueryLineRequest(driverAppSn))
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverSiteByCoordinate"))
}
/**
* 查询司机端出车收车状态,以及车牌号
* @param context
* @param callback
*/
@JvmStatic
fun queryDriverOperationStatus(
context: Context,
callback: OchCommonServiceCallback<BusPassengerOperationStatusResponse>?) {
mBusPassengerServiceApi.queryDriverOperationStatus(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
driverAppSn)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverOperationStatus"))
}
}

View File

@@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.amap.api.maps.model.LatLng;
import com.elegant.utils.UiThreadHandler;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr;
@@ -26,6 +27,7 @@ import com.mogo.och.bus.passenger.presenter.BaseBusPassengerPresenter;
import com.mogo.och.bus.passenger.ui.layoutmanager.CenterLayoutManager;
import com.mogo.och.bus.passenger.utils.BPRouteDataTestUtils;
import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil;
import com.mogo.och.common.module.wigets.MarqueeTextView;
import java.util.ArrayList;
import java.util.List;
@@ -49,7 +51,7 @@ public class BusPassengerRouteFragment extends
private TextView mSpeedTv;
private ConstraintLayout mNoLineInfoView;
private TextView mCarPlateNum;
private TextView mLineName;
private MarqueeTextView mLineName;
private TextView mOperationTime;
private ConstraintLayout mRouteInfoView;
private RecyclerView mStationsListRv;
@@ -97,19 +99,21 @@ public class BusPassengerRouteFragment extends
mMapArrowIcon = findViewById(R.id.bus_p_arrow_nor);
//测试
mSpeedTv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
BPRouteDataTestUtils.converToRouteData();
UiThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
updateWayPointList(mStationsList,1);
}
},1000);
return false;
}
});
if (DebugConfig.isDebug()){
mSpeedTv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
BPRouteDataTestUtils.converToRouteData();
UiThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
updateWayPointList(mStationsList,1);
}
},1000);
return false;
}
});
}
}
@Override

View File

@@ -105,21 +105,25 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
<com.mogo.och.common.module.wigets.MarqueeTextView
android:id="@+id/bus_p_line_name_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_20"
android:layout_marginRight="@dimen/dp_20"
android:maxLines="1"
android:ellipsize="end"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:text="----"
app:customGap="0.5"
app:useCustomGap="true"
android:textColor="@color/bus_p_line_name_color"
android:textSize="@dimen/bus_p_driver_number_plate_size"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="@+id/bus_p_driver_num_plate_tv"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/bus_p_driver_num_plate_tv"
app:layout_constraintBottom_toBottomOf="@+id/bus_p_driver_num_plate_tv"
app:layout_goneMarginLeft="0dp" />
<TextView

View File

@@ -3,7 +3,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
<com.mogo.och.common.module.wigets.MarqueeTextView
android:id="@+id/bus_p_station"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -17,6 +18,8 @@
android:layout_marginRight="@dimen/dp_60"
android:textColor="@color/bus_p_station_txt_color"
android:layout_marginLeft="@dimen/dp_90"
app:customGap="0.5"
app:useCustomGap="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bus_p_tag"
app:layout_constraintTop_toBottomOf="@+id/bus_p_cur_arrow_bg"/>

View File

@@ -0,0 +1,11 @@
package com.mogo.och.bus.callback;
/**
* Created on 2021/9/8
*
* Model->Presenter回调ADAS相关自动驾驶状态回调到达终点等等
*/
public interface IBusADASStatusCallback {
//自驾返回失败
void onStartAdasFailure();
}

View File

@@ -63,8 +63,12 @@ class BusConst {
const val EVENT_PARAM_END_NAME = "end_name"
const val EVENT_PARAM_LINE_ID = "line_id"
const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false
const val EVENT_PARAM_START_FAILURE_MSG = "start_autopilot_failure_msg" // 启动自驾失败原因
const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号
const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境true/false
// 埋点key开启自动驾驶前已识别的异常会导致无法开启自驾
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类型

View File

@@ -318,12 +318,6 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
});
}
public void showNotice(String notice) {
getActivity().runOnUiThread(() -> {
AIAssist.getInstance(getContext()).speakTTSVoice(notice);
});
}
public void playDI(){
SoundPoolHelper.getSoundPoolHelper().playSoundWithRedId(getContext(), R.raw.bus_di);
}
@@ -392,14 +386,18 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
return;
}
if (isAnimateRunning){
stopAutopilotAnimation();
updateAutopilotStatus(autopilotStatus);
stopAnimAndUpdateBtnStatus();
}else {
setAutopilotBtnStatus(autopilotStatus);
}
}
public void stopAnimAndUpdateBtnStatus(){
stopAutopilotAnimation();
updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState());
}
/**
* 隐藏【自动驾驶】按钮
*/

View File

@@ -19,6 +19,7 @@ import com.mogo.eagle.core.data.temp.EventLogout;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
import com.mogo.eagle.core.function.call.map.CallerHDMapManager;
import com.mogo.eagle.core.function.call.map.CallerSmpManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.map.MogoMarkerManager;
@@ -35,6 +36,7 @@ import com.mogo.och.common.module.biz.constant.OchCommonConst;
import com.mogo.och.common.module.biz.provider.LoginService;
import com.mogo.och.common.module.utils.BlinkAnimationUtil;
import com.mogo.och.common.module.utils.OCHThreadPoolManager;
import com.mogo.och.common.module.wigets.MarqueeTextView;
import com.mogo.och.common.module.wigets.OCHCommitDialog;
import org.greenrobot.eventbus.Subscribe;
@@ -53,7 +55,7 @@ public class BusFragment extends BaseBusTabFragment<BusFragment, BusPresenter>
public static final String TAG = "BusFragment";
private TextView mSwitchLine; //切换路线
private TextView mLineName;
private MarqueeTextView mLineName;
private TextView mTaskTime;
private Group groupStationsPanel;
private ConstraintLayout noDataView;
@@ -428,6 +430,9 @@ public class BusFragment extends BaseBusTabFragment<BusFragment, BusPresenter>
setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
}
//清除鹰眼右下角小地图轨迹
CallerSmpManager.clearPolyline();
}
/**

View File

@@ -11,8 +11,9 @@ import com.mogo.och.bus.bean.BusQueryLinesResponse;
import com.mogo.och.bus.bean.BusRoutesResponse;
import com.mogo.och.bus.callback.IBusLinesCallback;
import com.mogo.och.bus.net.BusServiceManager;
import com.mogo.och.bus.net.IBusServiceCallback;
import com.mogo.och.bus.ui.BusSwitchLineActivity;
import com.mogo.och.bus.util.BusSendTripInfoManager;
import com.mogo.och.common.module.biz.network.OchCommonServiceCallback;
/**
* @author: wangmingjun
@@ -42,7 +43,7 @@ public class BusLineModel {
mBusLinesCallback = callback;
}
public void queryBusLines(){
BusServiceManager.getInstance().queryBusLines(mContext, new IBusServiceCallback<BusQueryLinesResponse>() {
BusServiceManager.queryBusLines(mContext, new OchCommonServiceCallback<BusQueryLinesResponse>() {
@Override
public void onSuccess(BusQueryLinesResponse data) {
if (null == data && mBusLinesCallback != null) {
@@ -56,7 +57,7 @@ public class BusLineModel {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else {
@@ -72,7 +73,7 @@ public class BusLineModel {
* @param position 位置
*/
public void queryBusLineTasksById(int lineId, int position,boolean autoRefresh){
BusServiceManager.getInstance().queryBusTaskByLineId(mContext, String.valueOf(lineId),new IBusServiceCallback<BusQueryLineTaskResponse>() {
BusServiceManager.queryBusTaskByLineId(mContext, String.valueOf(lineId),new OchCommonServiceCallback<BusQueryLineTaskResponse>() {
@Override
public void onSuccess(BusQueryLineTaskResponse data) {
if (null == data && mBusLinesCallback != null) {
@@ -86,7 +87,7 @@ public class BusLineModel {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else {
@@ -97,7 +98,7 @@ public class BusLineModel {
}
public void commitSwitchLineId(int taskId,int lineId){
BusServiceManager.getInstance().switchLine(mContext,taskId, new IBusServiceCallback<BusRoutesResponse>() {
BusServiceManager.switchLine(mContext,taskId, new OchCommonServiceCallback<BusRoutesResponse>() {
@Override
public void onSuccess(BusRoutesResponse o) {
SharedPrefs.getInstance(mContext).putInt(BusSwitchLineActivity.LASTCOMMITLINEID,lineId);
@@ -107,7 +108,7 @@ public class BusLineModel {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else {

View File

@@ -40,18 +40,21 @@ import com.mogo.och.bus.bean.BusRoutesResponse;
import com.mogo.och.bus.bean.BusRoutesResult;
import com.mogo.och.bus.bean.BusStationBean;
import com.mogo.och.bus.bean.WriteOffPassenger;
import com.mogo.och.bus.callback.IBusADASStatusCallback;
import com.mogo.och.bus.callback.IBusControllerStatusCallback;
import com.mogo.och.bus.callback.IPassengerCallback;
import com.mogo.och.bus.callback.IRefreshBusStationsCallback;
import com.mogo.och.bus.callback.ISlidePannelHideCallback;
import com.mogo.och.bus.constant.BusConst;
import com.mogo.och.bus.net.BusServiceManager;
import com.mogo.och.bus.net.IBusServiceCallback;
import com.mogo.och.bus.presenter.BusModelLoopManager;
import com.mogo.och.bus.util.BusAnalyticsManager;
import com.mogo.och.bus.util.BusSendTripInfoManager;
import com.mogo.och.bus.util.BusTrajectoryManager;
import com.mogo.och.common.module.biz.constant.OchCommonConst;
import com.mogo.och.common.module.biz.network.OchCommonServiceCallback;
import com.mogo.och.common.module.biz.provider.LoginService;
import com.mogo.och.common.module.callback.OchAdasStartFailureCallback;
import com.mogo.och.common.module.manager.OCHAdasAbilityManager;
import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil;
import com.mogo.och.common.module.utils.DateTimeUtil;
@@ -59,6 +62,7 @@ import com.mogo.och.common.module.utils.NumberFormatUtil;
import com.mogo.och.common.module.utils.PinYinUtil;
import com.mogo.och.common.module.utils.SoundPoolHelper;
import com.mogo.och.common.module.utils.ToastUtilsOch;
import com.mogo.och.common.module.voice.VoiceNotice;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
import com.mogo.service.statusmanager.StatusDescriptor;
@@ -66,7 +70,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.UndeliverableException;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;
@@ -103,6 +106,7 @@ public class BusOrderModel {
private ISlidePannelHideCallback slidePanelHideCallback;
private IBusControllerStatusCallback mControllerStatusCallback; //Model->PresenterVR mode等
private IPassengerCallback mPassengerCallback; //乘客核销回调
private IBusADASStatusCallback mADASStatusCallback;
List<BusRoutePlanningUpdateReqBean.Result> points = new ArrayList<>();//全路径信息
@@ -158,6 +162,9 @@ public class BusOrderModel {
//自动驾驶路线规划接口
CallerAutopilotPlanningListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener);
//开启自驾后 异常信息返回
OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener);
}
//2022.1.28
@@ -198,6 +205,10 @@ public class BusOrderModel {
});
}
public void setAdasStatusCallback(IBusADASStatusCallback callback){
this.mADASStatusCallback = callback;
}
public void setRefreshBusStationsCallback(IRefreshBusStationsCallback callback){
this.refreshBusStationsCallback = callback;
}
@@ -255,15 +266,15 @@ public class BusOrderModel {
BusStationBean currentStation = stationList.get( backgroundCurrentStationIndex);
BusStationBean nextStation = stationList.get( backgroundCurrentStationIndex +1);
BusServiceManager.getInstance().updateOrderRoute(mContext, currentLineId, currentStation.getSiteId()
, nextStation.getSiteId(), points, new IBusServiceCallback<BaseData>() {
BusServiceManager.updateOrderRoute(mContext, currentLineId, currentStation.getSiteId()
, nextStation.getSiteId(), points, new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData o) {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
if (isGoingToNextStation){//重试
updateOrderRoute();
}
@@ -295,6 +306,8 @@ public class BusOrderModel {
//自动驾驶路线规划接口
CallerAutopilotPlanningListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener);
loginService = null;
OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null);
}
private Object readResolve() {
@@ -314,6 +327,17 @@ public class BusOrderModel {
}
};
private final OchAdasStartFailureCallback mAdasStartFailureListener = new OchAdasStartFailureCallback() {
@Override
public void onStartAutopilotFailure(@NonNull String startFailedMessage) {
BusAnalyticsManager.getInstance().triggerStartAutopilotFailureEventByAdas(startFailedMessage);
if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode){
CallerLogger.INSTANCE.e( M_BUS + TAG, "mAdasStartFailureListener = "+startFailedMessage );
mADASStatusCallback.onStartAdasFailure();
}
}
};
// 自车定位
private final IMogoCarLocationChangedListener2 mCarLocationChangedListener2 = new IMogoCarLocationChangedListener2() {
@@ -361,7 +385,7 @@ public class BusOrderModel {
*/
public void queryBusRoutes() {
CallerLogger.INSTANCE.d(M_BUS + TAG, "查询小巴路线");
BusServiceManager.getInstance().queryBusRoutes(mContext, new IBusServiceCallback<BusRoutesResponse>() {
BusServiceManager.queryBusRoutes(mContext, new OchCommonServiceCallback<BusRoutesResponse>() {
@Override
public void onSuccess(BusRoutesResponse data) {
if ( data == null
@@ -382,7 +406,7 @@ public class BusOrderModel {
updateBusStatus( data.getResult());
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
// 重复请求小巴路线,直至成功
//改为任务,为空不再去一直取
// queryBusStationDelay();
@@ -448,14 +472,13 @@ public class BusOrderModel {
*/
public void abortTask() {
CallerLogger.INSTANCE.d( M_BUS + TAG, "结束当前路线abortTask");
BusServiceManager.getInstance().abortTask(mContext, currentTaskId
, new IBusServiceCallback<BaseData>() {
BusServiceManager.abortTask(mContext, currentTaskId
, new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData o) {
CallerLogger.INSTANCE.d(M_BUS + TAG, "abortTask success: " + o);
clearNativeTag();
if (o.code == 0){ // 重置成功
clearNativeTag();
endOrAbortTaskSuccess();
clearBusStationDatas();
queryBusRoutes();
startOrStopQueryPassengerWriteOff(false);
@@ -463,16 +486,28 @@ public class BusOrderModel {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
ToastUtils.showShort(failMsg);
}
});
}
private void clearNativeTag() {
/**
* 中断或者正常结束任务后的处理
*/
private void endOrAbortTaskSuccess() {
isGoingToNextStation = false;
backgroundCurrentStationIndex = 0;
if (busRoutesResult != null){
BusSendTripInfoManager.INSTANCE.sendBusTripInfo(BusSendTripInfoManager.END_TRIP
, busRoutesResult.getName()
,""
,""
,false);
}
}
/**
@@ -480,7 +515,27 @@ public class BusOrderModel {
* 服务端返回的OchBusRoutesResult逻辑 离开站为当前站, 到达下一站后才会将下一站置为当前站,
* 车机端展示是离开当前站,下一站设置为当前站, 所以服务端数据回来要做处理,不能直接渲染
*/
private void leaveStationSuccess(int leaveIndex) {
private void leaveStationSuccess(int leaveIndex,String leaveStation,String nextStation) {
onStartAutopilot(leaveIndex);
leaveTTSTips(nextStation);
if (busRoutesResult != null){
boolean isLastStop = false;
if (leaveIndex + 1 == stationList.size() -1){
isLastStop = true;
}
//给bus外屏发送
BusSendTripInfoManager.INSTANCE.sendBusTripInfo(BusSendTripInfoManager.LEAVE_STATION
, busRoutesResult.getName()
,leaveStation
,nextStation
,isLastStop);
}
}
private void onStartAutopilot(int leaveIndex) {
//开启自动驾驶 2.10.0: 如果自动驾驶状态下开启, 非自动驾驶状态下不开启,需手动点击自动驾驶按钮开启
isGoingToNextStation = true;
if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()
@@ -500,6 +555,7 @@ public class BusOrderModel {
if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().getAutopilotAbilityStatus()){
ToastUtils.showLong(OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason() +
", 请稍候重试");
triggerUnableStartAPReasonEvent();
return;
}
@@ -532,11 +588,11 @@ public class BusOrderModel {
CallerLogger.INSTANCE.e( M_BUS + TAG, "数组越界" );
return;
}
BusServiceManager.getInstance().queryStationWriteOffPassengers(mContext,
BusServiceManager.queryStationWriteOffPassengers(mContext,
currentTaskId,
stationList.get(backgroundCurrentStationIndex).getSiteId(),
prePassengerWriteOffTime,
new IBusServiceCallback<BusQueryWriteOffPassengersResponse>(){
new OchCommonServiceCallback<BusQueryWriteOffPassengersResponse>(){
@Override
public void onSuccess(BusQueryWriteOffPassengersResponse o) {
@@ -548,7 +604,7 @@ public class BusOrderModel {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
}
});
@@ -586,28 +642,27 @@ public class BusOrderModel {
}
int arrivedStationIndex = backgroundCurrentStationIndex + 1;
String arriveStation = stationList.get(arrivedStationIndex).getName();
String departureStopName = stationList.get(backgroundCurrentStationIndex).getName();
CallerLogger.INSTANCE.d(M_BUS + TAG,"arriveSiteStation-currentStationIndex = "+ arrivedStationIndex);
BusServiceManager.getInstance().arriveSiteStation(mContext ,
BusServiceManager.arriveSiteStation(mContext ,
stationList.get(arrivedStationIndex).getSeq(),
stationList.get(arrivedStationIndex).getSiteId(),
currentTaskId ,
new IBusServiceCallback<BaseData>() {
new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData o) {
CallerLogger.INSTANCE.d(M_BUS + TAG,"行程日志-arriveSiteStation success");
queryBusRoutes();
ttsTips(String.format(mContext
.getString(R.string.bus_arrived_station_tip),
arriveStation));
arriveStationSuccess(arrivedStationIndex,departureStopName,arriveStation);
//5s轮询核销乘客
startOrStopQueryPassengerWriteOff(true);
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
isArrivedStation = false;
isGoingToNextStation = true;
if (ToastUtilsOch.isCustomFastClick(5000)){
@@ -621,6 +676,25 @@ public class BusOrderModel {
});
}
private void arriveStationSuccess(int arrivedStationIndex,String departureStopName,String arriveStation) {
if (busRoutesResult != null){
boolean isLastStop = false;
if (arrivedStationIndex == busRoutesResult.getSites().size() - 1 ){
isLastStop = true;
}
//给bus外屏发送
BusSendTripInfoManager.INSTANCE.sendBusTripInfo(BusSendTripInfoManager.ARRIVE_STATION
, busRoutesResult.getName()
,departureStopName
,arriveStation
,isLastStop);
}
VoiceNotice.showNotice(String.format(mContext
.getString(R.string.bus_arrived_station_tip),
arriveStation));
}
/**
* 离站上报
*/
@@ -630,12 +704,13 @@ public class BusOrderModel {
if (backgroundCurrentStationIndex < stationList.size() - 1){
nextStationName = stationList.get(backgroundCurrentStationIndex + 1).getName();
}
final String currentStationName = stationList.get(backgroundCurrentStationIndex).getName();
String finalNextStationName = nextStationName;
BusServiceManager.getInstance().leaveStation(mContext,
BusServiceManager.leaveStation(mContext,
stationList.get(backgroundCurrentStationIndex).getSeq(),
stationList.get(backgroundCurrentStationIndex).getSiteId(),
currentTaskId,
new IBusServiceCallback<BaseData>() {
new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData o) {
isArrivedStation = false;
@@ -643,11 +718,10 @@ public class BusOrderModel {
//需要更改当前站和下一站的状态 然后渲染
startOrStopQueryPassengerWriteOff(false);
queryBusRoutes();
leaveStationSuccess(backgroundCurrentStationIndex);
leaveTTSTips(finalNextStationName);
leaveStationSuccess(backgroundCurrentStationIndex,currentStationName,finalNextStationName);
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else{
@@ -659,20 +733,9 @@ public class BusOrderModel {
//车站10s后播报
private void leaveTTSTips(String nextStation) {
UiThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
ttsTips(String.format(mContext
.getString(R.string.bus_leave_station_tip),
nextStation));
}
},DELAY_10S);
}
private void ttsTips(String notice) {
UiThreadHandler.post(() ->{
AIAssist.getInstance(mContext).speakTTSVoice(notice);
});
VoiceNotice.showNotice(String.format(mContext
.getString(R.string.bus_leave_station_tip),
nextStation),DELAY_10S);
}
/**
@@ -734,6 +797,10 @@ public class BusOrderModel {
if (backgroundCurrentStationIndex == 0 &&
stationList.get(0).getDrivingStatus() == STATION_STATUS_STOPPED
&& !stationList.get(0).isLeaving()){ //默认是第一站到站查询
if (busRoutesResult != null){ // 第一站到站也是行程开始的时候
BusSendTripInfoManager.INSTANCE.sendBusTripInfo(BusSendTripInfoManager.START_TRIP
,busRoutesResult.getName(),"","",false);
}
startOrStopQueryPassengerWriteOff(true);
}
@@ -829,22 +896,22 @@ public class BusOrderModel {
*/
private void endTask() {
CallerLogger.INSTANCE.d( M_BUS + TAG, "任务正常走完endTask()");
BusServiceManager.getInstance().endTask(mContext, currentTaskId
, new IBusServiceCallback<BaseData>() {
BusServiceManager.endTask(mContext, currentTaskId
, new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData o) {
CallerLogger.INSTANCE.d(M_BUS + TAG, "endTask success: " + o);
if (o.code == 0){
clearNativeTag();
endOrAbortTaskSuccess();
clearBusStationDatas();
queryBusRoutes();// 重新获取任务
startOrStopQueryPassengerWriteOff(false);
ttsTips(mContext.getString(R.string.bus_end_task_tip));
VoiceNotice.showNotice(mContext.getString(R.string.bus_end_task_tip));
}
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
ToastUtils.showShort(failMsg);
}
});
@@ -895,15 +962,15 @@ public class BusOrderModel {
// 车机端上传心跳数据(只在出车状态时上传)
public void runCarHeartbeat() {
BusServiceManager.getInstance().runCarHeartbeat(mContext, mLongitude, mLatitude,
new IBusServiceCallback<BaseData>() {
BusServiceManager.runCarHeartbeat(mContext, mLongitude, mLatitude,
new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData data) {
}
@Override
public void onFail(String failMsg) {
public void onFail(int code, String failMsg) {
}
});
@@ -933,6 +1000,17 @@ public class BusOrderModel {
currentStation.getName(), nextStation.getName(), currentLineId);
}
public void triggerUnableStartAPReasonEvent() {
if (stationList == null || backgroundCurrentStationIndex >= stationList.size()-1) {
return;
}
BusStationBean currentStation = stationList.get( backgroundCurrentStationIndex);
BusStationBean nextStation = stationList.get( backgroundCurrentStationIndex +1);
BusAnalyticsManager.getInstance().triggerUnableStartAPReasonEvent(
currentStation.getName(), nextStation.getName(), currentLineId,
OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason());
}
public BusRoutesResult getBusRoutesResult() {
return busRoutesResult;
}

View File

@@ -0,0 +1,268 @@
package com.mogo.och.bus.net
import android.content.Context
import com.mogo.och.bus.constant.BusConst.Companion.getBaseUrl
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.och.bus.bean.*
import com.mogo.och.common.module.biz.network.OchCommonServiceCallback
import com.mogo.och.common.module.biz.network.OchCommonSubscribeImpl
import com.mogo.och.common.module.biz.network.interceptor.transformTry
/**
* @author: wangmingjun
* @date: 2021/10/20
*/
object BusServiceManager {
private val mService: IBusApiService = MoGoRetrofitFactory.getInstance(getBaseUrl()).create(
IBusApiService::class.java
)
/**
* 查询小巴车当前任务
* @param context
* @param callback
*/
@JvmStatic
fun queryBusRoutes(context: Context, callback: OchCommonServiceCallback<BusRoutesResponse>?) {
//获取当前高德坐标
mService.queryBusRoutes(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusQueryLineStationsRequest()
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryBusRoutes"))
}
/**
* 重置线路站点
* @param context
* @param taskId
* @param callback
*/
@JvmStatic
fun switchLine(
context: Context,
taskId: Int,
callback: OchCommonServiceCallback<BusRoutesResponse>?
) {
mService.switchLine(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusResetDrivingLineRequest(taskId)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "switchLine"))
}
/**
* 中断当前任务
* @param context
* @param taskId
* @param callback
*/
@JvmStatic
fun abortTask(context: Context, taskId: Int, callback: OchCommonServiceCallback<BaseData>?) {
mService.abortTask(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusCloseTaskRequest(taskId)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "abortTask"))
}
/**
* 正常结束任务
* @param context
* @param taskId
* @param callback
*/
@JvmStatic
fun endTask(context: Context, taskId: Int, callback: OchCommonServiceCallback<BaseData>?) {
mService.endTask(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusCloseTaskRequest(taskId)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "endTask"))
}
/**
* 离站上报
* @param context
* @param seq
* @param siteId
* @param callback
*/
@JvmStatic
fun leaveStation(
context: Context,
seq: Int,
siteId: Int,
taskId: Int,
callback: OchCommonServiceCallback<BaseData>?
) {
mService.leaveStation(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusUpdateSiteStatusRequest(taskId, siteId, seq)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "leaveStation"))
}
/**
* 到站更新站点状态
* @param context
* @param seq
* @param siteId
* @param callback
*/
@JvmStatic
fun arriveSiteStation(
context: Context, seq: Int, siteId: Int, taskId: Int,
callback: OchCommonServiceCallback<BaseData>?
) {
mService.arriveSiteStation(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusUpdateSiteStatusRequest(taskId, siteId, seq)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "arriveSiteStation"))
}
/**
* 查询下车乘客
* @param context
* @param seq
* @param siteId
* @param callback
*/
@JvmStatic
fun queryStationLeaveAwayPassengers(
context: Context,
seq: Int,
siteId: Int,
callback: OchCommonServiceCallback<QueryLeaveAwayPassengersResponse>?
) {
mService.queryStationLeaveAwayPassengers(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
QueryLeaveAwayPassengersRequest(seq, siteId)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryStationLeaveAwayPassengers"))
}
/**
* 查询当前到站点核销乘客
* @param context
* @param siteId
* @param callback
*/
@JvmStatic
fun queryStationWriteOffPassengers(
context: Context,
taskId: Int,
siteId: Int,
prePassengerTime: Long,
callback: OchCommonServiceCallback<BusQueryWriteOffPassengersResponse>?
) {
mService.queryWriteOffPassengers(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusWriteOffPassengersQueryRequest(taskId, siteId, prePassengerTime)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryStationWriteOffPassengers"))
}
/**
* 查询小巴车订单
* @param context
* @param callback
*/
@JvmStatic
fun queryBusOrders(context: Context, callback: OchCommonServiceCallback<BusOrdersResponse>?) {
mService.queryBusOrders(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
MoGoAiCloudClientConfig.getInstance().sn
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryBusOrders"))
}
@JvmStatic
fun queryBusLines(context: Context, callback: OchCommonServiceCallback<BusQueryLinesResponse>?) {
mService.queryBusLines(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
MoGoAiCloudClientConfig.getInstance().sn
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryBusLines"))
}
@JvmStatic
fun queryBusTaskByLineId(
context: Context,
lineId: String?,
callback: OchCommonServiceCallback<BusQueryLineTaskResponse>?
) {
mService.queryBusTaskByLineId(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
lineId
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryBusLines"))
}
@JvmStatic
fun updateOrderRoute(
context: Context,
lineId: Int,
startSiteId: Int,
endSiteId: Int,
points: List<BusRoutePlanningUpdateReqBean.Result?>?,
callback: OchCommonServiceCallback<BaseData>?
) {
mService.updateOrderRoute(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
BusRoutePlanningUpdateReqBean(
MoGoAiCloudClientConfig.getInstance().sn, lineId, startSiteId, endSiteId, points
)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "updateOrderRoute"))
}
/**
* 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度
* @param context
* @param lon
* @param lat
* @param callback
*/
@JvmStatic
fun runCarHeartbeat(
context: Context, lon: Double, lat: Double,
callback: OchCommonServiceCallback<BaseData>?
) {
mService.runCarHeartbeat(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
CarHeartbeatReqBean(
MoGoAiCloudClientConfig.getInstance().sn, lon, lat
)
)
.transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "runCarHeartbeat"))
}
}

View File

@@ -11,6 +11,7 @@ import androidx.lifecycle.LifecycleOwner;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.mvp.Presenter;
import com.mogo.commons.voice.AIAssist;
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;
@@ -20,6 +21,7 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.bus.R;
import com.mogo.och.bus.bean.BusStationBean;
import com.mogo.och.bus.bean.WriteOffPassenger;
import com.mogo.och.bus.callback.IBusADASStatusCallback;
import com.mogo.och.bus.callback.IBusControllerStatusCallback;
import com.mogo.och.bus.callback.IPassengerCallback;
import com.mogo.och.bus.callback.IRefreshBusStationsCallback;
@@ -31,6 +33,7 @@ import com.mogo.och.common.module.biz.bean.DriverStatusQueryRespBean;
import com.mogo.och.common.module.biz.callback.ILoginCallback;
import com.mogo.och.common.module.manager.OCHAdasAbilityManager;
import com.mogo.och.common.module.utils.SoundPoolHelper;
import com.mogo.och.common.module.voice.VoiceNotice;
import com.zhidao.socket.utils.LoginStatusUtil;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +52,7 @@ import system_master.SystemStatusInfo;
*/
public class BusPresenter extends Presenter<BusFragment>
implements IRefreshBusStationsCallback, ISlidePannelHideCallback
, IMoGoAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IPassengerCallback {
, IMoGoAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IPassengerCallback, IBusADASStatusCallback {
private static final String TAG = "BusPresenter";
@@ -84,6 +87,7 @@ public class BusPresenter extends Presenter<BusFragment>
BusOrderModel.getInstance().setSlidePanelHideCallback(this);
BusOrderModel.getInstance().setControllerStatusCallback(this);
BusOrderModel.getInstance().setPassengerCallback(this);
BusOrderModel.getInstance().setAdasStatusCallback(this);
}
public void releaseListener() {
@@ -91,6 +95,7 @@ public class BusPresenter extends Presenter<BusFragment>
BusOrderModel.getInstance().setSlidePanelHideCallback(null);
BusOrderModel.getInstance().setControllerStatusCallback(null);
BusOrderModel.getInstance().setPassengerCallback(null);
BusOrderModel.getInstance().setAdasStatusCallback(null);
OCHAdasAbilityManager.getInstance().release();
}
@@ -302,10 +307,16 @@ public class BusPresenter extends Presenter<BusFragment>
@Override
public void playPassenger(WriteOffPassenger passenger) {
int passengerNum = passenger.passengerSize;
if (passengerNum > 1){ //多人播报 "x人"
mView.showNotice(passengerNum + "");
}else { //是 1 播放 "滴"
mView.playDI();
if (passengerNum > 1){ //多人播报 "x人" ---》x人核验通过
VoiceNotice.showNotice(passengerNum+"人核验通过", AIAssist.LEVEL3);
}else { //是 1 播放 "滴" 2022.11.09 改为: "核验通过"
// mView.playDI();
VoiceNotice.showNotice("核验通过", AIAssist.LEVEL3);
}
}
@Override
public void onStartAdasFailure() {
runOnUIThread(() -> mView.stopAnimAndUpdateBtnStatus());
}
}

View File

@@ -1,5 +1,6 @@
package com.mogo.och.bus.util;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.text.TextUtils;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
@@ -8,12 +9,12 @@ import com.mogo.eagle.core.data.app.AppConfigInfo;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.analytics.AnalyticsManager;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.DateTimeUtils;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.bus.constant.BusConst;
import java.util.HashMap;
import java.util.Map;
/**
* OCH Bus埋点工具
@@ -30,18 +31,35 @@ public class BusAnalyticsManager {
return BusAnalyticsManager.SingletonHolder.INSTANCE;
}
private String mStartAutopilotKey;
private HashMap<String, Object> mStartAutopilotParams = new HashMap<>();
private Runnable startAutopilotRunnable = () -> {
// 15s内未开启上报失败埋点
triggerStartAutopilotFailureEvent("15s后app等待超时");
};
public void triggerStartAutopilotFailureEventByAdas(String failMsg){
removeWaitingCallback();
triggerStartAutopilotFailureEvent(failMsg);
}
private void triggerStartAutopilotFailureEvent(String failMsg){
CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg );
mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT
, CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() ==
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG,
failMsg);
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
};
}
private void removeWaitingCallback() {
if (startAutopilotRunnable != null &&
UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) {
UiThreadHandler.removeCallbacks(startAutopilotRunnable);
}
}
/**
* 触发'开启自动驾驶'埋点流程
@@ -69,14 +87,38 @@ public class BusAnalyticsManager {
if (send) {
// 开启成功,上报埋点
if (startAutopilotRunnable != null &&
UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) {
UiThreadHandler.removeCallbacks(startAutopilotRunnable);
}
removeWaitingCallback();
mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT, true);
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
} else {
UiThreadHandler.postDelayed(startAutopilotRunnable, BusConst.LOOP_PERIOD_15S);
}
}
/**
* 触发"无法开启自驾已知异常"埋点
* @param startName
* @param endName
* @param lineId
*/
public void triggerUnableStartAPReasonEvent(String startName, String endName, int lineId,
String reason) {
String sn = MoGoAiCloudClientConfig.getInstance().getSn();
String plateNum = AppConfigInfo.INSTANCE.getPlateNumber();
String dateTime = DateTimeUtils.getTimeText(
System.currentTimeMillis(), DateTimeUtils.yyyy_MM_dd_HH_mm_ss);
HashMap<String, Object> params = new HashMap<>();
params.put(BusConst.EVENT_PARAM_SN, sn);
params.put(BusConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum);
params.put(BusConst.EVENT_PARAM_ENV_ONLINE,
DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false);
params.put(BusConst.EVENT_PARAM_TIME, dateTime);
params.put(BusConst.EVENT_PARAM_START_NAME, startName);
params.put(BusConst.EVENT_PARAM_END_NAME, endName);
params.put(BusConst.EVENT_PARAM_LINE_ID, lineId);
params.put(BusConst.EVENT_PARAM_UNABLE_START_REASON, reason);
AnalyticsManager.INSTANCE.track(BusConst.EVENT_KEY_AP_UNABLE_START_REASON, params);
}
}

View File

@@ -0,0 +1,36 @@
package com.mogo.och.bus.util
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
/**
* @author: wangmingjun
* @date: 2022/10/24
*/
object BusSendTripInfoManager{
const val START_TRIP = 1
const val END_TRIP = 2
const val LEAVE_STATION = 3
const val ARRIVE_STATION = 4
/**
* 行程信息
* @param type 事件类型, 1:行程开始, 2:行程结束, 3:出站, 4:进站, 5:城市占道施工预警
* @param lineName 路线名, for type 1, 2
* @param departureStopName 出站站点名, for type 3, 4
* @param arrivalStopName 下一站到达站点名, for type 3, 4
* @param isLastStop 是否终点站(下一站或者要到达站)
* @return
*/
fun sendBusTripInfo(type: Int, lineName: String,
departureStopName: String,
arrivalStopName: String,
isLastStop: Boolean) {
d(SceneConstant.M_BUS + "BusSendTripInfoManager", "type: "+ type
+", lineName: "+ lineName +", departureStopName: "+ departureStopName
+ ", arrivalStopName: "+arrivalStopName+", isLastStop: "+isLastStop)
CallerAutoPilotManager.sendTripInfo(type,lineName,departureStopName, arrivalStopName, isLastStop)
}
}

View File

@@ -10,15 +10,16 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
<com.mogo.och.common.module.wigets.MarqueeTextView
android:id="@+id/module_och_bus_line_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_68"
android:layout_marginRight="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_64"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:text="--"
android:textColor="#FFF"
android:textSize="38dp"

View File

@@ -39,8 +39,12 @@
<string name="bus_dialog_cancel">取消</string>
<string name="bus_no_task_tip">暂无任务</string>
<!-- region tts -->
<string name="bus_arrived_station_tip">已到达%1$s带好随身物品下车请注意。</string>
<string name="bus_leave_station_tip">车辆起步,请扶稳坐好,前方到站是%1$s请下车的乘客做好准备。</string>
<string name="bus_end_task_tip">感谢您体验\'蘑菇车联\'无人驾驶小巴车,请您携带好随身物品,我们下次再见。</string>
<string name="bus_arrived_station_tip">已到达%1$s带好随身物品下车请注意安全。</string>
<string name="bus_end_task_tip">感谢您体验\'蘑菇车联\'自动驾驶小巴车,我们下次再见。</string>
<!-- endregion -->
</resources>

View File

@@ -10,58 +10,9 @@ class SimpleInterceptor: Interceptor {
val encodedPath = original.url().encodedPath()
Log.e("SimpleInterceptor",original.method()+ encodedPath+original.url().encodedQuery())
when (encodedPath) {
"/autopilot-car-hailing/operation/v1/driver/bus/loginStatus" -> {
val builder = Response.Builder()
val create:ResponseBody
if(first) {
create = ResponseBody.create(
MediaType.parse("application/json"),
"{\"code\":0,\"msg\":\"\",\"data\":{\"servingStatus\":0,\"driverStatus\":1,\"orderNo\":\"12111\",\"purpose\":1,\"sn\":\"fjsdlfjslf\",\"plateNumber\":\"车牌号\",\"phone\":\"18811539480\",\"lineId\":\"线路id\",\"taskId\":\"任务id\"}}"
)
first = false
}else{
create = ResponseBody.create(
MediaType.parse("application/json"),
"{\"code\":0,\"msg\":\"\",\"data\":{\"servingStatus\":0,\"driverStatus\":0,\"orderNo\":\"12111\",\"purpose\":1,\"sn\":\"fjsdlfjslf\",\"plateNumber\":\"车牌号\",\"phone\":\"18811539480\",\"lineId\":\"线路id\",\"taskId\":\"任务id\"}}"
)
first = true
}
builder.code(200)
builder.request(original)
builder.protocol(Protocol.HTTP_1_1)
builder.message("")
return builder.body(create).build()
}
"/autopilot-car-hailing/line/v2/driver/bus/task/query" -> {
val builder = Response.Builder()
val create = ResponseBody.create(MediaType.parse("application/json"), "{\"code\":0,\"msg\":\"\",\"data\":[{\"id\":1,\"taskStartTime\":1663722000000},{\"id\":2,\"taskStartTime\":1663725600000},{\"id\":3,\"taskStartTime\":1663729200000},{\"id\":4,\"taskStartTime\":1663732800000},{\"id\":5,\"taskStartTime\":1663736400000},{\"id\":6,\"taskStartTime\":1663740000000},{\"id\":7,\"taskStartTime\":1663743600000},{\"id\":8,\"taskStartTime\":1663747200000},{\"id\":9,\"taskStartTime\":1663750800000},{\"id\":10,\"taskStartTime\":1663754400000}]}")
builder.code(200)
builder.request(original)
builder.protocol(Protocol.HTTP_1_1)
builder.message("")
return builder.body(create).build()
}
"/autopilot-car-hailing/cab/flow/v1/bus/driver/bus/startTask" -> {
val builder = Response.Builder()
val create = ResponseBody.create(MediaType.parse("application/json"), "{\"code\":0,\"msg\":\"\",\"data\":null}")
builder.code(200)
builder.request(original)
builder.protocol(Protocol.HTTP_1_1)
builder.message("")
return builder.body(create).build()
}
"/autopilot-car-hailing/cab/flow/v1/bus/driver/bus/endOperation" -> {
val builder = Response.Builder()
val create = ResponseBody.create(MediaType.parse("application/json"), "{\"code\":0,\"msg\":\"\",\"data\":null}")
builder.code(200)
builder.request(original)
builder.protocol(Protocol.HTTP_1_1)
builder.message("")
return builder.body(create).build()
}
"/autopilot-car-hailing/cab/flow/v1/bus/driver/bus/startOperation" -> {
val builder = Response.Builder()
val create = ResponseBody.create(MediaType.parse("application/json"), "{\"code\":0,\"msg\":\"\",\"data\":null}")
val create = ResponseBody.create(MediaType.parse("application/json"), "{\"code\":100006,\"msg\":\"\",\"data\":null}")
builder.code(200)
builder.request(original)
builder.protocol(Protocol.HTTP_1_1)

View File

@@ -71,66 +71,70 @@ object OchCommonLoginModel{
* 获取手机验证码
*/
fun getPhoneCode(phone: String?) {
OchCommonServiceManager.getInstance().getPhoneCode(mContext, phone,
object : OchCommonServiceCallback<BaseData?> {
override fun onSuccess(data: BaseData?) {
if (null != data && 0 == data.code) {
// 获取验证码成功
ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_get_code_success))
iTaxiLoginCallback?.getPhoneCodeSuccess()
} else {
if (data != null) {
ToastUtils.showShort(data.code)
mContext?.let {
OchCommonServiceManager.getPhoneCode(it, phone,
object : OchCommonServiceCallback<BaseData> {
override fun onSuccess(data: BaseData?) {
if (null != data && 0 == data.code) {
// 获取验证码成功
ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_get_code_success))
iTaxiLoginCallback?.getPhoneCodeSuccess()
} else {
if (data != null) {
ToastUtils.showShort(data.code)
}
}
}
}
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))
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))
}
}
}
override fun onFail(code: Int, msg: String) {
ToastUtilsOch.showWithCodeMessage(code,msg)
}
})
override fun onFail(code: Int, msg: String) {
ToastUtilsOch.showWithCodeMessage(code,msg)
}
})
}
}
fun gotoLogin(phone: String, code: String) {
val location4Login = TaxiLoginReqBean.Location4Login(mLatitude, mLongitude)
OchCommonServiceManager.getInstance().gotoLoginBycode(mContext, phone, code, location4Login,
object : OchCommonServiceCallback<TaxiLoginRespBean?> {
override fun onSuccess(data: TaxiLoginRespBean?) {
if (null != data && 0 == data.code) {
// 获取验证码成功
ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_login_success))
LoginStatusManager.setLoginStatus(TaxiLoginStatusEnum.Login)
mContext?.let {
SharedPrefs.getInstance(it).putString("och_account",phone)
}
iTaxiLoginCallback?.loginSuccess()
} else {
if (data != null) {
ToastUtils.showShort(data.code)
mContext?.let {
val location4Login = TaxiLoginReqBean.Location4Login(mLatitude, mLongitude)
OchCommonServiceManager.gotoLoginBycode(it, phone, code, location4Login,
object : OchCommonServiceCallback<TaxiLoginRespBean> {
override fun onSuccess(data: TaxiLoginRespBean?) {
if (null != data && 0 == data.code) {
// 获取验证码成功
ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_login_success))
LoginStatusManager.setLoginStatus(TaxiLoginStatusEnum.Login)
mContext?.let {
SharedPrefs.getInstance(it).putString("och_account",phone)
}
iTaxiLoginCallback?.loginSuccess()
} else {
if (data != null) {
ToastUtils.showShort(data.code)
}
}
}
}
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))
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))
}
}
}
override fun onFail(code: Int, msg: String) {
ToastUtilsOch.showWithCodeMessage(code,msg)
}
})
override fun onFail(code: Int, msg: String) {
ToastUtilsOch.showWithCodeMessage(code,msg)
}
})
}
}
}

View File

@@ -53,7 +53,7 @@ public abstract class OchCommonLoginStatusModel {
* 8、登录页面关闭后查下状态
*/
public void queryCarStatus() {
OchCommonServiceManager.getInstance().queryDriverServiceStatus(mContext,
OchCommonServiceManager.queryDriverServiceStatus(mContext,
new OchCommonServiceCallback<DriverStatusQueryRespBean>() {
@Override
public void onSuccess(DriverStatusQueryRespBean data) {
@@ -93,7 +93,7 @@ public abstract class OchCommonLoginStatusModel {
// 登出
public void logout(double mLatitude,double mLongitude) {
TaxiLogoutReqBean.Location4Login location4Login = new TaxiLogoutReqBean.Location4Login(mLatitude, mLongitude);
OchCommonServiceManager.getInstance().logout(mContext,location4Login,
OchCommonServiceManager.logout(mContext,location4Login,
new OchCommonServiceCallback<BaseData>() {
@Override
public void onSuccess(BaseData data) {

View File

@@ -1,187 +0,0 @@
package com.mogo.och.common.module.biz.network;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI;
import android.content.Context;
import com.mogo.cloud.passport.MoGoAiCloudClient;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.eagle.core.data.BaseData;
import com.mogo.eagle.core.network.MoGoRetrofitFactory;
import com.mogo.eagle.core.network.RequestOptions;
import com.mogo.eagle.core.network.SubscribeImpl;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.och.common.module.biz.bean.DriverStatusQueryRespBean;
import com.mogo.och.common.module.biz.bean.TaxiLoginReqBean;
import com.mogo.och.common.module.biz.bean.TaxiLoginRespBean;
import com.mogo.och.common.module.biz.bean.TaxiLoginSmsReqBean;
import com.mogo.och.common.module.biz.bean.TaxiLogoutReqBean;
import com.mogo.och.common.module.biz.constant.OchCommonConst;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by pangfan on 2021/8/19
*/
public class OchCommonServiceManager {
private static final String TAG = OchCommonServiceManager.class.getSimpleName();
private static final class SingletonHolder {
private static final OchCommonServiceManager INSTANCE = new OchCommonServiceManager();
}
public static OchCommonServiceManager getInstance() {
return SingletonHolder.INSTANCE;
}
private OchCommonServiceApiNew mOCHTaxiServiceApi;
private OchCommonServiceManager() {
if (mOCHTaxiServiceApi == null){
mOCHTaxiServiceApi = MoGoRetrofitFactory.getInstance(OchCommonConst.getBaseUrl()).create(OchCommonServiceApiNew.class);
}
}
/**
* 获取手机验证码
* @param context
* @param callback
*/
public void getPhoneCode(Context context, String phone,
OchCommonServiceCallback<BaseData> callback) {
mOCHTaxiServiceApi.getPhoneCode(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
, MoGoAiCloudClientConfig.getInstance().getToken()
, new TaxiLoginSmsReqBean(phone))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context, callback, "getPhoneCode"));
}
/**
* 通过验证码登录
* @param context
* @param callback
*/
public void gotoLoginBycode(Context context, String phone, String code,
TaxiLoginReqBean.Location4Login location4Login,
OchCommonServiceCallback<TaxiLoginRespBean> callback) {
String sn = MoGoAiCloudClientConfig.getInstance().getSn();
Observable<TaxiLoginRespBean> taxiLoginRespBeanObservable = null;
switch (DebugConfig.getProductFlavor()) {
case "fPadLenovoOchTaxi": {//出租车司机
taxiLoginRespBeanObservable = mOCHTaxiServiceApi.gotoLoginBycode4Taxi(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
, MoGoAiCloudClientConfig.getInstance().getToken()
, new TaxiLoginReqBean(phone, code, sn, location4Login));
break;
}
case "fPadLenovoOchBus": {//小巴车司机
taxiLoginRespBeanObservable = mOCHTaxiServiceApi.gotoLoginBycode4Bus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
, MoGoAiCloudClientConfig.getInstance().getToken()
, new TaxiLoginReqBean(phone, code, sn, location4Login));
break;
}
}
if (taxiLoginRespBeanObservable != null) {
taxiLoginRespBeanObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context, callback, "gotoLoginBycode"));
}
}
/**
* 登出
*/
public void logout(Context context, TaxiLogoutReqBean.Location4Login location4Login, OchCommonServiceCallback<BaseData> callback) {
Observable<BaseData> logout = null;
switch (DebugConfig.getProductFlavor()) {
case "fPadLenovoOchTaxi": {//出租车司机
logout = mOCHTaxiServiceApi.logout4Taxi(
MoGoAiCloudClientConfig.getInstance().getServiceAppId(),
MoGoAiCloudClientConfig.getInstance().getToken(),
new TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().getSn(), location4Login));
break;
}
case "fPadLenovoOchBus": {//小巴车司机
logout = mOCHTaxiServiceApi.logout4Bus(
MoGoAiCloudClientConfig.getInstance().getServiceAppId(),
MoGoAiCloudClientConfig.getInstance().getToken(),
new TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().getSn(), location4Login));
break;
}
}
if (logout != null) {
logout.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context, callback, "logout"));
}
}
/**
* 接单状态和登录状态查询
*
* @param context
* @param callback
*/
public void queryDriverServiceStatus(Context context,
OchCommonServiceCallback<DriverStatusQueryRespBean> callback) {
if (MoGoAiCloudClientConfig.getInstance().getToken().isEmpty()) {
callback.onFail(OchCommonConst.WAIT_TAKEN, "等待令牌中请稍等");
MoGoAiCloudClient.getInstance().refreshToken();
return;
}
String flavor = "";
switch (DebugConfig.getProductFlavor()) {
case "fPadLenovoOchTaxi": {//出租车司机
flavor = "taxi";
break;
}
case "fPadLenovoOchBus": {//小巴车司机
flavor = "bus";
break;
}
case "fPadLenovoOchBusPassenger": {//小巴车乘客
flavor = "bus/passenger";
break;
}
}
mOCHTaxiServiceApi.queryDriverServiceStatusAndLoginStatus(flavor, MoGoAiCloudClientConfig.getInstance().getServiceAppId()
, MoGoAiCloudClientConfig.getInstance().getToken()
, MoGoAiCloudClientConfig.getInstance().getSn())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context, callback, "queryDriverServiceStatus"));
}
private <T extends BaseData> SubscribeImpl getSubscribeImpl(
Context context, OchCommonServiceCallback<T> callback, String apiName) {
return new SubscribeImpl<T>(RequestOptions.create(context)) {
@Override
public void onSuccess(T o) {
super.onSuccess(o);
CallerLogger.INSTANCE.d(M_TAXI + TAG, apiName + ": onSuccess() " + o.msg);
if (callback != null) {
callback.onSuccess(o);
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
CallerLogger.INSTANCE.e(M_TAXI + TAG, apiName + ": onError() " + e.getMessage());
if (callback != null) {
callback.onError();
}
}
@Override
public void onError(String message, int code) {
super.onError(message, code);
CallerLogger.INSTANCE.e(M_TAXI + TAG, String.format(apiName + ": onError() code = %d; message = %s;", code, message));
if (callback != null) {
callback.onFail(code, message);
}
}
};
}
}

View File

@@ -0,0 +1,154 @@
package com.mogo.och.common.module.biz.network
import android.content.Context
import com.mogo.och.common.module.biz.constant.OchCommonConst.Companion.getBaseUrl
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.och.common.module.biz.bean.TaxiLoginSmsReqBean
import com.mogo.och.common.module.biz.bean.TaxiLoginReqBean
import com.mogo.och.common.module.biz.bean.TaxiLoginRespBean
import com.mogo.och.common.module.biz.bean.TaxiLogoutReqBean
import com.mogo.och.common.module.biz.bean.DriverStatusQueryRespBean
import com.mogo.och.common.module.biz.constant.OchCommonConst
import com.mogo.cloud.passport.MoGoAiCloudClient
import com.mogo.commons.debug.DebugConfig
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.och.common.module.biz.network.interceptor.transformTry
import io.reactivex.Observable
/**
* Created by pangfan on 2021/8/19
*/
object OchCommonServiceManager {
private const val TAG = "OchCommonServiceManager"
private val mOCHTaxiServiceApi: OchCommonServiceApiNew =
MoGoRetrofitFactory.getInstance(getBaseUrl()).create(
OchCommonServiceApiNew::class.java
)
/**
* 获取手机验证码
* @param context
* @param callback
*/
@JvmStatic
fun getPhoneCode(
context: Context, phone: String?,
callback: OchCommonServiceCallback<BaseData>?
) {
mOCHTaxiServiceApi.getPhoneCode(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
TaxiLoginSmsReqBean(phone)
).transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "getPhoneCode"))
}
/**
* 通过验证码登录
* @param context
* @param callback
*/
@JvmStatic
fun gotoLoginBycode(
context: Context, phone: String?, code: String?,
location4Login: TaxiLoginReqBean.Location4Login?,
callback: OchCommonServiceCallback<TaxiLoginRespBean>?
) {
val sn = MoGoAiCloudClientConfig.getInstance().sn
var taxiLoginRespBeanObservable: Observable<TaxiLoginRespBean>? = null
when (DebugConfig.getProductFlavor()) {
"fPadLenovoOchTaxi" -> {
//出租车司机
taxiLoginRespBeanObservable = mOCHTaxiServiceApi.gotoLoginBycode4Taxi(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
TaxiLoginReqBean(phone, code, sn, location4Login)
).transformTry()
}
"fPadLenovoOchBus" -> {
//小巴车司机
taxiLoginRespBeanObservable = mOCHTaxiServiceApi.gotoLoginBycode4Bus(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
TaxiLoginReqBean(phone, code, sn, location4Login)
).transformTry()
}
}
taxiLoginRespBeanObservable?.subscribe(OchCommonSubscribeImpl(context, callback, "gotoLoginBycode"))
}
/**
* 登出
*/
@JvmStatic
fun logout(
context: Context,
location4Login: TaxiLogoutReqBean.Location4Login?,
callback: OchCommonServiceCallback<BaseData>?
) {
var logout: Observable<BaseData>? = null
when (DebugConfig.getProductFlavor()) {
"fPadLenovoOchTaxi" -> {
//出租车司机
logout = mOCHTaxiServiceApi.logout4Taxi(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().sn, location4Login)
).transformTry()
}
"fPadLenovoOchBus" -> {
//小巴车司机
logout = mOCHTaxiServiceApi.logout4Bus(
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().sn, location4Login)
).transformTry()
}
}
logout?.subscribe(OchCommonSubscribeImpl(context, callback, "logout"))
}
/**
* 接单状态和登录状态查询
*
* @param context
* @param callback
*/
@JvmStatic
fun queryDriverServiceStatus(
context: Context,
callback: OchCommonServiceCallback<DriverStatusQueryRespBean>?
) {
if (MoGoAiCloudClientConfig.getInstance().token.isEmpty()) {
callback?.onFail(OchCommonConst.WAIT_TAKEN, "等待令牌中请稍等")
MoGoAiCloudClient.getInstance().refreshToken()
return
}
var flavor = ""
when (DebugConfig.getProductFlavor()) {
"fPadLenovoOchTaxi" -> {
//出租车司机
flavor = "taxi"
}
"fPadLenovoOchBus" -> {
//小巴车司机
flavor = "bus"
}
"fPadLenovoOchBusPassenger" -> {
//小巴车乘客
flavor = "bus/passenger"
}
}
mOCHTaxiServiceApi.queryDriverServiceStatusAndLoginStatus(
flavor,
MoGoAiCloudClientConfig.getInstance().serviceAppId,
MoGoAiCloudClientConfig.getInstance().token,
MoGoAiCloudClientConfig.getInstance().sn
).transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverServiceStatus"))
}
}

View File

@@ -0,0 +1,36 @@
package com.mogo.och.common.module.biz.network
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.network.RequestOptions
import com.mogo.eagle.core.network.SubscribeImpl
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.utils.CallerLoggerUtils.flavorTag
class OchCommonSubscribeImpl<T : BaseData>(
val context: Any,
val callback: OchCommonServiceCallback<T>?,
val apiName: String
) : SubscribeImpl<T>(RequestOptions.create(context)) {
companion object {
const val TAG = "OchCommonSubscribeImpl"
}
override fun onSuccess(o: T) {
super.onSuccess(o)
CallerLogger.d("$flavorTag$TAG", "$apiName: onSuccess() ${o.msg}")
callback?.onSuccess(o)
}
override fun onError(e: Throwable) {
super.onError(e)
CallerLogger.e("$flavorTag$TAG", "$apiName: onError() ${e.message}")
callback?.onError()
}
override fun onError(message: String, code: Int) {
super.onError(message, code)
CallerLogger.e("$flavorTag$TAG", "$apiName: onError() code = $code; message = $message")
callback?.onFail(code, message)
}
}

View File

@@ -0,0 +1,20 @@
package com.mogo.och.common.module.biz.network.interceptor
import com.mogo.cloud.passport.MoGoAiCloudClient
import com.mogo.eagle.core.data.BaseData
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
class FRetryWithTime<T : BaseData> : Function<T, ObservableSource<T>> {
override fun apply(baseData: T): ObservableSource<T> {
baseData.let {
if (it.code == 100046 || it.code == 100045 || it.code == 100005 || it.code == 100006 || it.code == 520003) {
MoGoAiCloudClient.getInstance().refreshToken()
return Observable.error(OchCommonRetryException())
}
}
return Observable.just(baseData)
}
}

View File

@@ -0,0 +1,13 @@
package com.mogo.och.common.module.biz.network.interceptor
import io.reactivex.Observable
import com.mogo.eagle.core.data.BaseData
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
fun <T : BaseData> Observable<T>.transformTry():Observable<T> {
return flatMap(FRetryWithTime<T>())
.retryWhen(RetryWithTime())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}

View File

@@ -0,0 +1,5 @@
package com.mogo.och.common.module.biz.network.interceptor;
public class OchCommonRetryException extends RuntimeException{
}

View File

@@ -0,0 +1,30 @@
package com.mogo.och.common.module.biz.network.interceptor
import com.mogo.eagle.core.utilcode.constant.TimeConstants
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.och.common.module.utils.CallerLoggerUtils.flavorTag
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
import java.util.concurrent.TimeUnit
class RetryWithTime : Function<Observable<Throwable?>, ObservableSource<Any?>> {
companion object {
private const val TAG = "RetryWithTime"
}
var current = -1
private var timeDelys = intArrayOf(3, 1, 2)
override fun apply(throwableObservable: Observable<Throwable?>): ObservableSource<Any?>? {
return throwableObservable.flatMap {
++current
CallerLogger.e("${flavorTag}${TAG}", " 时间:${TimeUtils.getStringByNow(0, TimeConstants.SEC)}")
if (it is OchCommonRetryException && current < timeDelys.size) {
Observable.timer(timeDelys[current].toLong(), TimeUnit.SECONDS)
} else {
Observable.error(it)
}
}
}
}

View File

@@ -1,5 +1,6 @@
package com.mogo.och.common.module.biz.ui
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Rect
import android.os.Bundle
@@ -20,10 +21,10 @@ import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.debug.DebugConfig
import com.mogo.commons.mvp.MvpDialogFragment
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.utilcode.kotlin.onClick
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.BarUtils
import com.mogo.eagle.core.utilcode.util.KeyboardUtils
import com.mogo.och.common.module.R
import com.mogo.och.common.module.biz.constant.OchCommonConst
@@ -35,7 +36,8 @@ import com.mogo.och.common.module.biz.provider.LoginService
* @author: yangyakun
* @date: 2022/8/15
*/
class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchCommonLoginPresenter?>(),
class TaxiLoginDialogFragment :
MvpDialogFragment<TaxiLoginDialogFragment?, OchCommonLoginPresenter?>(),
DialogInterface.OnKeyListener {
lateinit var clMain: ConstraintLayout
@@ -54,14 +56,6 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
setStyle(STYLE_NO_TITLE, R.style.DialogFullScreen) //dialog全屏
}
override fun onResume() {
super.onResume()
dialog?.let {
it.window?.let {window->
BarUtils.setNavBarVisibility(window,false)
}
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -88,11 +82,8 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
initBg()
initListener()
dialog?.window?.let {
context?.let { contextIn->
BarUtils.setStatusBarColor(
it,
ContextCompat.getColor(contextIn, R.color.taxi_4D000000)
)
context?.let { _ ->
CallerHmiManager.setStatusBarDarkOrLight(false)
}
}
}
@@ -108,23 +99,22 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
}
}
@SuppressLint("ClickableViewAccessibility")
private fun initListener() {
mRootView.isFocusable = true
mRootView.isFocusableInTouchMode = true
mRootView.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
closeSoftInput()
}
mRootView.setOnTouchListener { _, event ->
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
closeSoftInput()
}
return false
}
})
false
}
acbtnLogin.onClick {
val phone = aceLoginPhoneValue.text.toString()
val code = acetPhoneCodeValue.text.toString()
mPresenter?.gotoLogin(phone,code)
mPresenter?.gotoLogin(phone, code)
}
actvWelcomeLoginTitle.setOnClickListener {
continuousClick()
@@ -148,7 +138,7 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
actvLoginGetCode.onClick {
mPresenter?.getPhoneCode(aceLoginPhoneValue.text.toString())
}
actvLoginShowSn.setOnLongClickListener{
actvLoginShowSn.setOnLongClickListener {
val loginService = ARouter.getInstance().build(OchCommonConst.LOGINSERVICE)
.navigation() as LoginService
loginService.showUiModel(false)
@@ -156,8 +146,8 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
true
}
aceLoginPhoneValue.addTextChangedListener {
it?.let { itEditable->
if(itEditable.isNotEmpty()){
it?.let { itEditable ->
if (itEditable.isNotEmpty()) {
inputPhoneNormal()
}
}
@@ -175,28 +165,29 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
}
}
fun setCountDownText(text:String,enable: Boolean){
if(enable){
fun setCountDownText(text: String, enable: Boolean) {
if (enable) {
actvLoginGetCode.setText(R.string.module_och_taxi_login_get_code)
actvLoginGetCode.isEnabled = true
}else{
} else {
actvLoginGetCode.text = text
actvLoginGetCode.isEnabled = false
}
}
fun inputPhoneError(){
fun inputPhoneError() {
aceLoginPhoneValue.text?.clear()
aceLoginPhoneValue.setHint(R.string.module_och_taxi_login_phone_error)
context?.let {
aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it,R.color.taxi_EF262C))
aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it, R.color.taxi_EF262C))
aceLoginPhoneValue.setBackgroundResource(R.drawable.taxi_login_phone_error)
}
}
private fun inputPhoneNormal(){
private fun inputPhoneNormal() {
//aceLoginPhoneValue.setHint(R.string.module_och_taxi_login_phone_hint_text)
context?.let {
aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it,R.color.taxi_878890))
aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it, R.color.taxi_878890))
aceLoginPhoneValue.setBackgroundResource(R.drawable.taxi_login_phone_normal)
}
}
@@ -205,17 +196,30 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
return OchCommonLoginPresenter(this)
}
val COUNTS = 4 // 点击次数
val DURATION: Long = 1000 // 规定有效时间
var mHits = LongArray(COUNTS)
companion object {
private const val COUNTS = 4 // 点击次数
private const val DURATION: Long = 1000 // 规定有效时间
val TAG = TaxiLoginDialogFragment::class.java.simpleName
@JvmStatic
fun newInstance(): TaxiLoginDialogFragment {
val args = Bundle()
val fragment = TaxiLoginDialogFragment()
fragment.arguments = args
return fragment
}
}
private var mHits = LongArray(COUNTS)
private fun continuousClick() {
//每次点击时,数组向前移动一位
System.arraycopy(mHits, 1, mHits, 0, mHits.size - 1)
//为数组最后一位赋值
mHits[mHits.size-1] = SystemClock.uptimeMillis()
mHits[mHits.size - 1] = SystemClock.uptimeMillis()
if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION)) {
mHits = LongArray(COUNTS) //重新初始化数组
mPresenter?.gotoLogin("13288888888","8888")
mPresenter?.gotoLogin("13288888888", "8888")
}
}
@@ -234,6 +238,7 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
mOnClickListener?.onDismiss(dialog)
CallerHmiManager.setStatusBarDarkOrLight(false)
}
/**
@@ -269,16 +274,4 @@ class TaxiLoginDialogFragment : MvpDialogFragment<TaxiLoginDialogFragment?, OchC
}
}
companion object {
val TAG = TaxiLoginDialogFragment::class.java.simpleName
@JvmStatic
fun newInstance(): TaxiLoginDialogFragment {
val args = Bundle()
val fragment = TaxiLoginDialogFragment()
fragment.arguments = args
return fragment
}
}
}

View File

@@ -0,0 +1,9 @@
package com.mogo.och.common.module.callback
/**
* @author: wangmingjun
* @date: 2022/11/9
*/
interface OchAdasStartFailureCallback {
fun onStartAutopilotFailure(startFailedMessage : String)
}

View File

@@ -6,9 +6,13 @@ import androidx.annotation.Nullable;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotActionsListener;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatisticsListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotActionsListenerManager;
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotStatisticsListenerManager;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import com.mogo.och.common.module.callback.OchAdasStartFailureCallback;
import com.zhidao.support.adas.high.bean.AutopilotAbility;
import com.zhidao.support.adas.high.bean.AutopilotStatistics;
import chassis.Chassis;
import system_master.SystemStatusInfo;
@@ -18,12 +22,15 @@ import system_master.SystemStatusInfo;
* 工控机状态信息回调(判断是否能否启动自动驾驶的回调)
* 目前定的是3秒回调一次
*/
public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener {
public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener, IMoGoAutopilotStatisticsListener {
private static final String TAG = OCHAdasAbilityManager.class.getSimpleName();
private boolean isAutopilotAbility = true;
private String autopilotAbilityReason = "";
private String startFailedMessage = "";
private OchAdasStartFailureCallback failureCallback = null;
private static final class SingletonHolder {
private static final OCHAdasAbilityManager INSTANCE = new OCHAdasAbilityManager();
@@ -37,6 +44,10 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener {
initListeners();
}
public void setAdasStartFailureCallback(OchAdasStartFailureCallback callback){
failureCallback = callback;
}
public boolean getAutopilotAbilityStatus(){
return isAutopilotAbility;
}
@@ -45,13 +56,19 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener {
return autopilotAbilityReason;
}
public String getStartFailedMessage() {
return startFailedMessage;
}
private void initListeners() {
//2022.10.9 工控机状态信息回调(判断是否能否启动自动驾驶的回调), 目前定的是3秒回调一次
CallerAutopilotActionsListenerManager.INSTANCE.addListener(TAG, this);
CallerAutopilotStatisticsListenerManager.INSTANCE.addListener(TAG,this);
}
private void releaseListeners() {
CallerAutopilotActionsListenerManager.INSTANCE.removeListener(this);
CallerAutopilotStatisticsListenerManager.INSTANCE.removeListener(this);
}
@Override
@@ -88,6 +105,18 @@ public class OCHAdasAbilityManager implements IMoGoAutopilotActionsListener {
Logger.d(TAG, "是否可以启动自动驾驶=" + isAutopilotAbility + " 原因=" + autopilotAbilityReason);
}
@Override
public void onAutopilotStatistics(@Nullable AutopilotStatistics statistics) {
if (statistics == null) return;
Logger.d(TAG, "AutopilotStatistics= " + statistics.status);
if (failureCallback != null && 1 == statistics.status){
startFailedMessage = statistics.failedMessage.getMsg();
failureCallback.onStartAutopilotFailure(startFailedMessage);
Logger.d(TAG, "statistics-startFailedMessage= " + startFailedMessage);
}
}
public void release() {
releaseListeners();
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.taxi.model;
package com.mogo.och.common.module.map;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI;
@@ -25,8 +25,7 @@ import com.amap.api.navi.model.NaviLatLng;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.NetworkUtils;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.och.taxi.callback.ITaxiNaviChangedCallback;
import com.mogo.och.taxi.utils.PermissionUtil;
import com.mogo.och.common.module.utils.PermissionUtil;
import java.util.ArrayList;
import java.util.List;
@@ -36,24 +35,27 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author: wangmingjun
* @date: 2021/12/6
*/
public class NaviToDestinationModel implements AMapNaviListener {
public class AmapNaviToDestinationModel implements AMapNaviListener {
public static final String TAG = "NaviToDestinationModel";
private static Context mContext;
private AMapNavi mAMapNavi = null;
protected final List<NaviLatLng> sList = new ArrayList<NaviLatLng>();
protected final List<NaviLatLng> eList = new ArrayList<NaviLatLng>();
protected List<NaviLatLng> mWayPointList = new ArrayList<NaviLatLng>();
private ITaxiNaviChangedCallback mNaviChangedCallback;
private ICommonNaviChangedCallback mNaviChangedCallback;
private AtomicInteger errorCount = new AtomicInteger(0);
private boolean isPlay;
public static NaviToDestinationModel getInstance(Context context) {
public static AmapNaviToDestinationModel getInstance(Context context) {
mContext = context;
return SingletonHolder.INSTANCE;
}
private static final class SingletonHolder {
private static final NaviToDestinationModel INSTANCE = new NaviToDestinationModel();
private static final AmapNaviToDestinationModel INSTANCE = new AmapNaviToDestinationModel();
}
private NaviToDestinationModel(){
private AmapNaviToDestinationModel(){
}
public void initAMapNavi(NaviLatLng startLatLng,NaviLatLng endLatLng) {
try {
@@ -90,7 +92,7 @@ public class NaviToDestinationModel implements AMapNaviListener {
}
}
public void setOCHTaciNaviChangedCallback(ITaxiNaviChangedCallback callback){
public void setOCHTaciNaviChangedCallback(ICommonNaviChangedCallback callback){
this.mNaviChangedCallback = callback;
}
@Override
@@ -132,6 +134,7 @@ public class NaviToDestinationModel implements AMapNaviListener {
public void onNaviInfoUpdate(NaviInfo naviinfo) {
//导航过程中的信息更新请看NaviInfo的具体说明
if (null != mNaviChangedCallback){
CallerLogger.INSTANCE.i(M_TAXI + TAG, "距离=" + naviinfo.getPathRetainDistance() + ", 剩余时间 " + naviinfo.getPathRetainTime());
mNaviChangedCallback.onCurrentNaviDistAndTimeChanged(naviinfo.getPathRetainDistance(),naviinfo.getPathRetainTime());//
}
}
@@ -165,13 +168,9 @@ public class NaviToDestinationModel implements AMapNaviListener {
}
return;
}
// if (result.getErrorCode() == 3){
// ToastUtils.showShort("车辆当前坐标错误");
// }else if (result.getErrorCode() == 6){
// ToastUtils.showShort("终点坐标错误");
// }
CallerLogger.INSTANCE.i(M_TAXI + "dm", "路线计算失败:错误码=" + result.getErrorCode() + ",Error Message= " + result.getErrorDetail());
CallerLogger.INSTANCE.i(M_TAXI + "dm", "错误码详细链接见http://lbs.amap.com/api/android-navi-sdk/guide/tools/errorcode/");
CallerLogger.INSTANCE.i(M_TAXI + TAG, "路线计算失败:错误码=" + result.getErrorCode() + ",Error Message= " + result.getErrorDetail());
CallerLogger.INSTANCE.i(M_TAXI + TAG, "错误码详细链接见http://lbs.amap.com/api/android-navi-sdk/guide/tools/errorcode/");
}
@Override
public void onStartNavi(int type) {
@@ -341,88 +340,4 @@ public class NaviToDestinationModel implements AMapNaviListener {
public void onPlayRing(int i) {
}
/**
* 车道信息说明
* <p>
* 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 = {
"直行"
, "左转"
, "左转或直行"
, "右转"
, "右转或这行"
, "左掉头"
, "左转或者右转"
, " 左转或右转或直行"
, "右转掉头"
, "直行或左转掉头"
, "直行或右转掉头"
, "左转或左掉头"
, "右转或右掉头"
, "直行并且车道扩展"
, "左转+左掉头+扩展"
, "不可以选择"
, "直行+左转+左掉头"
, "右转+左掉头"
, "左转+右转+左掉头"
, "直行+右转+左掉头"
, "左转+右掉头"
, "公交车道"
, "空车道"
, "可变车道"
};
}

View File

@@ -0,0 +1,249 @@
package com.mogo.och.common.module.map
import android.content.Context
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.RelativeLayout
import com.amap.api.maps.AMap
import com.amap.api.maps.model.CustomMapStyleOptions
import com.amap.api.navi.AMapNaviView
import com.amap.api.navi.AMapNaviViewListener
import com.amap.api.navi.AMapNaviViewOptions
import com.amap.api.navi.model.RouteOverlayOptions
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.och.common.module.R
import kotlinx.android.synthetic.main.taxi_common_amap_navi_view.view.*
import kotlin.concurrent.thread
/**
* @author: wangmingjun
* @date: 2022/10/23
*/
class CommonAmapNaviVIew @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0)
: RelativeLayout(context,attrs,defStyleAttr), AMapNaviViewListener {
private val TAG : String = "TaxiAmapNaviVIew"
var aMap : AMap? = null
init {
LayoutInflater.from(context).inflate(R.layout.taxi_common_amap_navi_view,this,true)
initMapView()
}
private fun initMapView(){
amapNaviView.setAMapNaviViewListener(this)
//车头向上模式
amapNaviView.naviMode = AMapNaviView.CAR_UP_MODE
aMap = amapNaviView.map
//关闭地图文字显示
aMap!!.showMapText(false)
// 设置导航地图模式aMap是地图控制器对象。
aMap!!.mapType = AMap.MAP_TYPE_NIGHT
// 关闭显示实时路况图层aMap是地图控制器对象。
aMap!!.isTrafficEnabled = false
setMapViewOptions()
thread(start = true){
try {
Thread.sleep(1000L)
} catch (e : InterruptedException) {
e.printStackTrace()
}
if (null == context){
return@thread
}
aMap!!.setCustomMapStyle(
CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(context, "over_view_style.data"))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(context, "over_view_style_extra.data"))
)
}
}
private fun setMapViewOptions() {
val options = AMapNaviViewOptions()
options.tilt = 0 //设置 2D 模式
options.isLayoutVisible = false //设置导航界面UI是否显示。
options.isTrafficBarEnabled = false //设置路况光柱条是否显示(只适用于驾车导航,需要联网)。
options.isAutoLockCar = true //设置6秒后是否自动锁车
options.isAutoDisplayOverview = true //设置是否自动全览模式,即在算路成功后自动进入全览模式
options.isTrafficLine = false
options.setModeCrossDisplayShow(true) //设置是否显示路口放大图(路口模型图)
options.isAutoChangeZoom = true //自动缩放级别
options.carBitmap =
BitmapFactory.decodeResource(context.resources, R.drawable.taxi_navi_arrow_icon)
options.fourCornersBitmap =
BitmapFactory.decodeResource(this.resources, R.drawable.taxi_navi_direction_icon)
options.isAutoChangeZoom = true //设置是否开启动态比例尺 (锁车态下自动进行地图缩放变化)
// options.setZoom(18);//14-18
// options.setTrafficInfoUpdateEnabled(false);
// options.setTrafficLayerEnabled(false);//设置[实时交通图层开关按钮]是否显示(只适用于驾车导航,需要联网)。
// options.setCameraInfoUpdateEnabled(false);
// options.setCompassEnabled(false);//设置指南针图标否在导航界面显示,默认显示。
// options.setLaneInfoShow(false);// 设置是否显示道路信息view
// options.setNaviArrowVisible(false);//设置路线转向箭头隐藏和显示
// options.setRealCrossDisplayShow(false);//设置是否显示路口放大图(实景图)
// options.setRouteListButtonShow(true);//设置导航界面是否显示路线全览按钮。
// options.setSettingMenuEnabled(false);//设置菜单按钮是否在导航界面显示。
// options.setZoom(18);//14-18
// options.setTrafficInfoUpdateEnabled(false);
// options.setTrafficLayerEnabled(false);//设置[实时交通图层开关按钮]是否显示(只适用于驾车导航,需要联网)。
// options.setCameraInfoUpdateEnabled(false);
// options.setCompassEnabled(false);//设置指南针图标否在导航界面显示,默认显示。
// options.setLaneInfoShow(false);// 设置是否显示道路信息view
// options.setNaviArrowVisible(false);//设置路线转向箭头隐藏和显示
// options.setRealCrossDisplayShow(false);//设置是否显示路口放大图(实景图)
// options.setRouteListButtonShow(true);//设置导航界面是否显示路线全览按钮。
// options.setSettingMenuEnabled(false);//设置菜单按钮是否在导航界面显示。
val routeOverlayOptions = RouteOverlayOptions()
// routeOverlayOptions.setArrowOnTrafficRoute(BitmapFactory.decodeResource(getResources(),R.drawable.custtexture_aolr));
// routeOverlayOptions.setArrowOnTrafficRoute(BitmapFactory.decodeResource(getResources(),R.drawable.custtexture_aolr));
routeOverlayOptions.normalRoute =
BitmapFactory.decodeResource(resources, R.drawable.taxi_navi_line_icon)
options.routeOverlayOptions = routeOverlayOptions
amapNaviView.viewOptions = options
}
override fun onNaviSetting() {
//底部导航设置点击回调
}
override fun onNaviCancel() {
TODO("Not yet implemented")
}
override fun onNaviBackClick(): Boolean {
return false
}
override fun onNaviMapMode(p0: Int) {
//导航态车头模式0:车头朝上状态1:正北朝上模式。
}
override fun onNaviTurnClick() {
//转弯view的点击回调
}
override fun onNextRoadClick() {
//下一个道路View点击回调
}
override fun onScanViewButtonClick() {
//全览按钮点击回调
}
override fun onLockMap(p0: Boolean) {
//锁地图状态发生变化时回调
}
override fun onNaviViewLoaded() {
d(SceneConstant.M_TAXI + TAG, "导航页面加载成功")
d(
SceneConstant.M_TAXI + TAG,
"请不要使用AMapNaviView.getMap().setOnMapLoadedListener();会overwrite导航SDK内部画线逻辑"
)
}
override fun onMapTypeChanged(p0: Int) {
TODO("Not yet implemented")
}
override fun onNaviViewShowMode(p0: Int) {
TODO("Not yet implemented")
}
fun onCreate(savedInstanceState : Bundle?){
amapNaviView.onCreate(savedInstanceState)
}
fun onResume(){
amapNaviView.onResume()
}
fun onPause(){
amapNaviView.onPause()
}
fun onDestroy(){
amapNaviView.onDestroy()
}
var array = arrayOf(
"直行车道",
"左转车道",
"左转或直行车道",
"右转车道",
"右转或直行车道",
"左掉头车道",
"左转或者右转车道",
" 左转或右转或直行车道",
"右转掉头车道",
"直行或左转掉头车道",
"直行或右转掉头车道",
"左转或左掉头车道",
"右转或右掉头车道",
"直行并且车道扩展",
"左转+左掉头+扩展",
"不可以选择该车道",
"直行+左转+左掉头车道",
"右转+左掉头",
"左转+右转+左掉头",
"直行+右转+左掉头",
"左转+右掉头",
"公交车道",
"空车道",
"可变车道"
)
var actions = arrayOf(
"直行",
"左转",
"左转或直行",
"右转",
"右转或这行",
"左掉头",
"左转或者右转",
" 左转或右转或直行",
"右转掉头",
"直行或左转掉头",
"直行或右转掉头",
"左转或左掉头",
"右转或右掉头",
"直行并且车道扩展",
"左转+左掉头+扩展",
"不可以选择",
"直行+左转+左掉头",
"右转+左掉头",
"左转+右转+左掉头",
"直行+右转+左掉头",
"左转+右掉头",
"公交车道",
"空车道",
"可变车道"
)
}

View File

@@ -1,11 +1,11 @@
package com.mogo.och.taxi.callback;
package com.mogo.och.common.module.map;
/**
* @author: wangmingjun
* @date: 2021/12/3
*/
public interface ITaxiNaviChangedCallback {
public interface ICommonNaviChangedCallback {
// 当前位置距离上车点的距离预估时间
void onCurrentNaviDistAndTimeChanged(int meters, long timeInSecond);
void reInitNaviAmap(boolean isPlay,boolean isRestart);
}
}

View File

@@ -0,0 +1,31 @@
package com.mogo.och.common.module.utils
import com.mogo.commons.debug.DebugConfig
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI_P
object CallerLoggerUtils {
var flavorTag = when (DebugConfig.getProductFlavor()) {
"fPadLenovoOchTaxi" -> {
//出租车司机
M_TAXI
}
"fPadLenovoOchBus" -> {
//小巴车司机
M_BUS
}
"fPadLenovoOchTaxiPassenger" -> {
//出租车乘客
M_TAXI_P
}
"fPadLenovoOchBusPassenger" -> {
//小巴车乘客
M_BUS_P
}
else -> {
""
}
}
}

View File

@@ -1,6 +1,7 @@
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;
@@ -8,7 +9,9 @@ import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mogo.telematics.pad.MessagePad;
@@ -161,7 +164,7 @@ public class CoordinateCalculateRouteUtil {
// Logger.d(M_TAXI + "calculateRouteSumLength", "点:"+currentIndex+"-------是最近的点------ ");
if (currentIndex == mRoutePoints.size()-1){
latePoints.add(mRoutePoints.get(currentIndex));
}else {
}else if(currentIndex < mRoutePoints.size()-1){
latePoints.addAll(mRoutePoints.subList(currentIndex,mRoutePoints.size()-1));
}
return latePoints;
@@ -202,4 +205,108 @@ public class CoordinateCalculateRouteUtil {
}
return currentIndex;
}
public static float calculateRouteSumLengthByLocation(List<Location> 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<Location> coordinateConverterWgsToGcjLocations(Context mContext, List<MessagePad.Location> models) {
//转成MogoLatLng集合
List<Location> list = new ArrayList<>();
for (MessagePad.Location m : models) {
LatLng mogoLatLng = coordinateConverterWgsToGcj(mContext, m);
Location location = new Location("gcj_provider");
location.setBearing((float) m.getHeading());
location.setLatitude(mogoLatLng.latitude);
location.setLongitude(mogoLatLng.longitude);
list.add(location);
}
return list;
}
public static Map<Integer,List<LatLng>> getRemainPointListByCompareNew(int preIndex,
List<Location> mRoutePoints,
Location realLocation) {
Map<Integer,List<LatLng>> routePonits = new HashMap<>();
List<LatLng> latePoints = new ArrayList<>(); // 剩余轨迹集合
int currentIndex = 0; //记录疑似点
if (mRoutePoints.size() > preIndex){
//基础点
Location baseLatLng = mRoutePoints.get(preIndex);
float baseDiffDis = CoordinateUtils.calculateLineDistance(realLocation.getLongitude(),
realLocation.getLatitude()
,baseLatLng.getLongitude(),baseLatLng.getLongitude());// lon,lat, prelon, prelat
for (int i= preIndex; i < mRoutePoints.size(); i++){
Location latLng = mRoutePoints.get(i);
//todo 先看index对应点的方向和realLocation方向是否一致 方向角度不能过90度
if (Math.abs(realLocation.getBearing() - latLng.getBearing()) <= 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){
Location location = mRoutePoints.get(currentIndex);
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
latePoints.add(latLng);
}else {
List<Location> locations = mRoutePoints.subList(currentIndex,mRoutePoints.size()-1);
for (Location location: locations) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
latePoints.add(latLng);
}
}
routePonits.put(currentIndex,latePoints);
return routePonits;
}
return routePonits;
}
public static int getArrivedPointIndexNew(List<Location> mRoutePoints,
Location realLocation) {
int currentIndex = 0; //记录疑似点 //基础点
Location 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++) {
Location latLng = mRoutePoints.get(i);
//todo 先看index对应点的方向和realLocation方向是否一致 方向角度不能过90度
if (Math.abs(realLocation.getBearing() - latLng.getBearing()) <= 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 + "-------是最近的点------ ");
return currentIndex;
}
}

View File

@@ -0,0 +1,37 @@
package com.mogo.och.common.module.utils;
import android.text.TextUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
public class FieldUtils {
public static Field getDeclaredField(final Class<?> cls, final String fieldName, final
boolean forceAccess) {
if (cls == null || TextUtils.isEmpty(fieldName)) {
return null;
}
try {
// only consider the specified class by using getDeclaredField()
final Field field = cls.getDeclaredField(fieldName);
if (!isAccessible(field)) {
if (forceAccess) {
field.setAccessible(true);
} else {
return null;
}
}
return field;
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean isAccessible(final Member m) {
return m != null && Modifier.isPublic(m.getModifiers()) && !m.isSynthetic();
}
}

View File

@@ -0,0 +1,35 @@
package com.mogo.och.common.module.utils;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import androidx.core.content.ContextCompat;
/**
* @author: wangmingjun
* @date: 2021/12/7
*/
public class PermissionUtil {
public static boolean checkPermission(Context context,String... permissons) {
for (String permisson : permissons) {
if ((ContextCompat.checkSelfPermission(context,
permisson) != PackageManager.PERMISSION_GRANTED)) {
return false;
}
}
return true;
}
public static boolean isLocServiceEnable(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (gps || network) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,49 @@
package com.mogo.och.common.module.voice
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
object VoiceNotice {
@JvmStatic
fun showNotice(notice: String?) {
showNotice(notice, AIAssist.LEVEL0)
}
@JvmStatic
fun showNotice(notice: String?, level: Int) {
showNotice(notice,level,0)
}
@JvmStatic
fun showNotice(notice: String?, delayed: Long) {
showNotice(notice, AIAssist.LEVEL0, delayed)
}
@JvmStatic
fun showNotice(notice: String?, level: Int, delayed: Long = 0) {
notice?.let {
if (delayed == 0L) {
UiThreadHandler.post {
AIAssist.getInstance(AbsMogoApplication.getApp())
.speakTTSVoiceWithLevel(it, level)
}
} else {
UiThreadHandler.postDelayed({
AIAssist.getInstance(AbsMogoApplication.getApp())
.speakTTSVoiceWithLevel(it, level)
}, delayed)
}
}
}
/**
* 中断当前在播语音
*/
@JvmStatic
fun stopCurrentTts(){
UiThreadHandler.post {
AIAssist.getInstance(AbsMogoApplication.getApp()).stopTts()
}
}
}

View File

@@ -0,0 +1,129 @@
package com.mogo.och.common.module.wigets;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.ViewDebug;
import android.widget.TextView;
import com.mogo.och.common.module.R;
import com.mogo.och.common.module.utils.FieldUtils;
import java.lang.reflect.Field;
public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView{
/**
* 上一次设置的时间,用于过滤多余操作
*/
private long mLastSetTime;
/**
* 自定义 gap
*/
private float mCustomGap = 0.3f;
/**
* 是否使用自定义 gap
*/
private boolean mUseCustomGap;
public MarqueeTextView(Context context) {
this(context, null);
}
public MarqueeTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MarqueeTextView);
mCustomGap = typedArray.getFloat(R.styleable.MarqueeTextView_customGap, mCustomGap);
mUseCustomGap = typedArray.getBoolean(R.styleable.MarqueeTextView_useCustomGap, false);
typedArray.recycle();
}
@Override
@ViewDebug.ExportedProperty(category = "focus")
public boolean isFocused() {
return true;
}
@Override
@ViewDebug.ExportedProperty
public boolean isSelected() {
return true;
}
@Override
public void invalidate() {
reflectToChangeGap();
super.invalidate();
}
private void reflectToChangeGap() {
if (!mUseCustomGap) {
return;
}
if (System.currentTimeMillis() - mLastSetTime < 1000) {
// 1s 内不重新设置,过滤多余操作
return;
}
try {
Class marqueClass = null;
Class[] innerClazz = TextView.class.getDeclaredClasses();
for (Class clazz : innerClazz) {
if ("Marquee".equals(clazz.getSimpleName())) {
marqueClass = clazz;
}
}
if (marqueClass == null) {
return;
}
Field field1 = FieldUtils.getDeclaredField(marqueClass, "mGhostStart", true);
if (field1 == null) {
return;
}
final int textWidth = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
final float lineWidth = getLayout().getLineWidth(0);
final float gap = mCustomGap*textWidth;
float ghostStart = lineWidth - textWidth + gap;
float maxScroll = ghostStart + textWidth;
float ghostOffset = lineWidth + gap;
float maxFadeScroll = ghostStart + lineWidth + lineWidth;
final Field field = FieldUtils.getDeclaredField(TextView.class, "mMarquee", true);
if (field != null) {
Object mMarque = field.get(this);
if (mMarque != null) {
mLastSetTime = System.currentTimeMillis();
float mGhostStart = (float) field1.get(mMarque);
if (mGhostStart != ghostStart) {
// 需要设置的 mGhostStart 与当前 ghostStart 不相等时才去设置
Field field2 = FieldUtils.getDeclaredField(marqueClass, "mMaxScroll", true);
Field field3 = FieldUtils.getDeclaredField(marqueClass, "mGhostOffset", true);
Field field4 = FieldUtils.getDeclaredField(marqueClass, "mMaxFadeScroll", true);
if (field2 == null || field3 == null || field4 == null) {
return;
}
field1.set(mMarque, ghostStart);
field2.set(mMarque, maxScroll);
field3.set(mMarque, ghostOffset);
field4.set(mMarque, maxFadeScroll);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<com.amap.api.navi.AMapNaviView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/amapNaviView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -52,4 +52,9 @@
<attr name="och_realtime_end_color" format="color" />
<attr name="och_realtime_radius" format="dimension" />
</declare-styleable>
<declare-styleable name="MarqueeTextView">
<attr name="customGap" format="float" />
<attr name="useCustomGap" format="boolean"/>
</declare-styleable>
</resources>

1
OCH/mogo-och-sweeper/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,75 @@
apply plugin: 'com.android.library'
apply plugin: 'com.alibaba.arouter'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
// buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.arouter
annotationProcessor rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.amapnavi3dmap
implementation rootProject.ext.dependencies.rxjava
implementation rootProject.ext.dependencies.rxandroid
implementation project(":OCH:mogo-och-common-module")
implementation rootProject.ext.dependencies.androidxrecyclerview
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
implementation rootProject.ext.dependencies.mogoutils
implementation rootProject.ext.dependencies.mogocommons
implementation rootProject.ext.dependencies.modulecommon
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_function_call
implementation rootProject.ext.dependencies.mogo_core_function_hmi
}else {
implementation project(":core:mogo-core-utils")
implementation project(":foudations:mogo-commons")
implementation project(':modules:mogo-module-common')
implementation project(':core:mogo-core-data')
implementation project(':core:mogo-core-function-call')
implementation project(':core:function-impl:mogo-core-function-hmi')
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.och
POM_ARTIFACT_ID=och-sweeper
VERSION_CODE=1

21
OCH/mogo-och-sweeper/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,24 @@
package com.mogo.och.sweeper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.mogo.och.sweeper", appContext.packageName)
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.och.sweeper">
<application>
<!--这里是为了测试增加的广播-->
<receiver android:name=".receiver.TestSweeperBroadcastReceiver">
<intent-filter>
<action android:name="com.bus.test_control" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity android:name=".ui.SweeperSwitchLineActivity"
android:theme="@style/SwitchLineDialogStyle"
android:launchMode="singleTask"
android:screenOrientation="landscape" />/>
</application>
</manifest>

View File

@@ -0,0 +1,24 @@
package com.mogo.och.sweeper;
import androidx.annotation.IdRes;
import androidx.fragment.app.FragmentActivity;
import com.mogo.eagle.core.function.api.base.IMoGoFunctionProvider;
public
/**
* @author congtaowang
* @since 2021/1/15
*
* 网约车抽象接口
*/
interface IMogoOCH extends IMoGoFunctionProvider {
/**
* 初始化网约车容器
*
* @param activity
* @param containerId 容器ID
*/
void createCoverage(FragmentActivity activity, @IdRes int containerId);
}

View File

@@ -0,0 +1,114 @@
package com.mogo.och.sweeper;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.map.MogoMapUIController;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.och.sweeper.constant.SweeperConst;
import com.mogo.och.sweeper.fragment.SweeperFragment;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
import com.mogo.service.statusmanager.StatusDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* 清扫车业务实现入口
*
* @author tongchenfei
*/
@Route(path = SweeperConst.PATH)
public class SweeperProvider implements IMogoOCH {
private static final String TAG = "SweeperProvider";
private SweeperFragment sweeperFragment;
private int containerId;
private FragmentActivity activity;
/**
* 进入鹰眼模式,设置手势缩放地图失效
*/
private void stepIntoVrMode(){
CallerLogger.INSTANCE.d( M_BUS + TAG, "进入vr模式" );
MogoMapUIController.getInstance()
.stepInVrMode(false);
}
@Override
public void init(Context context) {
MogoApisHandler.getInstance().getApis().getStatusManagerApi().registerStatusChangedListener("OchSweeper"
, StatusDescriptor.VR_MODE, statusChangedListener);
}
private void showFragment() {
if (sweeperFragment == null) {
CallerLogger.INSTANCE.d(TAG, "准备add fragment======");
sweeperFragment = new SweeperFragment();
activity.getSupportFragmentManager().beginTransaction().add(containerId, sweeperFragment).commitAllowingStateLoss();
return;
}
CallerLogger.INSTANCE.d(TAG, "准备show fragment");
activity.getSupportFragmentManager().beginTransaction().show(sweeperFragment).commitAllowingStateLoss();
}
private void hideFragment() {
if (sweeperFragment != null) {
CallerLogger.INSTANCE.d(TAG, "准备hide fragment");
activity.getSupportFragmentManager().beginTransaction().hide(sweeperFragment).commitAllowingStateLoss();
}
}
private final IMogoStatusChangedListener statusChangedListener = (descriptor, isTrue) -> {
if (descriptor == StatusDescriptor.VR_MODE) {
// 进入vr模式默认显示网约车小巴fragment
if (isTrue) {
showFragment();
} else {
hideFragment();
}
} else if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
// topView进行展示时推出网约车界面但是不隐藏整个fragment
if (sweeperFragment != null && isTrue) {
sweeperFragment.hideOchSweeper();
}
}
};
@Override
public void createCoverage(FragmentActivity activity, int containerId) {
}
@NotNull
@Override
public String getFunctionName() {
return null;
}
@Nullable
@Override
public Fragment createCoverage(@Nullable FragmentActivity fragmentActivity, @Nullable Integer integer) {
this.containerId = integer;
this.activity = fragmentActivity;
// UiThreadHandler.postDelayed(this::stepIntoVrMode, 5_000L );
return null;
}
@Override
public void onDestroy() {
//若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠
if (activity == null) return;
activity.finish();
}
}

View File

@@ -0,0 +1,26 @@
package com.mogo.och.sweeper.bean;
import com.mogo.och.sweeper.constant.SweeperConst;
import java.util.UUID;
/**
* Created on 2021/9/16
*
* 上传车机心跳信息请求数据
*/
public class CarHeartbeatReqBean {
public String sn;
public double lon; //经度
public double lat; //纬度
public String msgId; //心跳信息唯一标识
public int interval; //上报间隔单位秒非必传默认60秒
public CarHeartbeatReqBean(String sn, double lon, double lat) {
this.sn = sn;
this.lon = lon;
this.lat = lat;
this.msgId = UUID.randomUUID().toString();
this.interval = (int) (SweeperConst.LOOP_PERIOD_60S / 1000);
}
}

View File

@@ -0,0 +1,36 @@
package com.mogo.och.sweeper.bean;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
/**
* 查询下车乘客请求参数
*
* @author tongchenfei
*/
public class QueryLeaveAwayPassengersRequest {
private String sn;
private int seq; //站点在线路中的序号
private int siteId; //站点id
public QueryLeaveAwayPassengersRequest(int seq, int siteId) {
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
this.seq = seq;
this.siteId = siteId;
}
public void setSeq(int seq) {
this.seq = seq;
}
public void setSiteId(int siteId) {
this.siteId = siteId;
}
public int getSeq() {
return seq;
}
public int getSiteId() {
return siteId;
}
}

View File

@@ -0,0 +1,60 @@
package com.mogo.och.sweeper.bean;
import com.mogo.eagle.core.data.BaseData;
import java.util.List;
public
/**
* @author congtaowang
* @since 2021/3/26
*
* 到站查询下车乘客
*/
class QueryLeaveAwayPassengersResponse extends BaseData {
public Result data;
public static class Result {
public List< LeaveAwayPassenger > orders;
}
public static class LeaveAwayPassenger {
/**
* orderNo: 订单no
* orderStatus: 订单状态
* orderType订单类型0及时1预约
* bookingTime预计用车时间
* businessType订单运营类型 9:taxi10:bus
* startSiteId 起点站点id
* userPhone: 乘客联系方式
* startSitePoint开始站点坐标
* startSiteAddr开始地址
* endSiteId结束站点id
* endSitePoint结束站点坐标
* carNumber车牌号
* createTime: 创建时间
* startTime开始时间
* startSiteGcjPoint高精坐标
* endSiteGcjPoint
*/
//todo 目前是需要乘客电话来通知乘客下车 目前后台没有乘客信息userPhone
public String orderNo;
public int orderStatus;
public int orderType;
public long bookingTime;
public int businessType;
public int startSiteId;
public String passengerPhone;
public List<Double> startSitePoint;
public String startSiteAddr;
public int endSiteId;
public List<Double> endSitePoint;
public String carNumber;
public long createTime;
public long startTime;
public List< Double > startSiteGcjPoint;
public List< Double > endSiteGcjPoint;
}
}

View File

@@ -0,0 +1,42 @@
package com.mogo.och.sweeper.bean;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
public
/**
* @author congtaowang
* @since 2021/3/22
*
* 小巴车运营状态请求参数
*/
class SweeperOperationStatusRequest {
private String sn;
private double lat;
private double lon;
public SweeperOperationStatusRequest(double lon, double lat) {
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
this.lat = lat;
this.lon = lon;
}
public void setLat(double lat) {
this.lat = lat;
}
public void setLon(double lon) {
this.lon = lon;
}
public String getSn() {
return sn;
}
public double getLat() {
return lat;
}
public double getLon() {
return lon;
}
}

View File

@@ -0,0 +1,20 @@
package com.mogo.och.sweeper.bean;
import com.mogo.eagle.core.data.BaseData;
/**
* @author congtaowang
* @since 2021/3/22
*
* 小巴车运营状态返回参数
*/
public class SweeperOperationStatusResponse extends BaseData {
public Result data;
public static class Result {
public int serviceStatus;//0:已收车1:已出车
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.och.sweeper.bean;
/**
* @author congtaowang
* @since 2021/3/23
* <p>
* 小巴订单
*/
public class SweeperOrderBean {
/**
* orderNo number
* passengerPhone string 下单用户电话
* startStationId integer 开始站点
* startStationName string
* endStationId integer 结束站点
* endStationName string
*/
private String orderNo;
private String passengerPhone;
private int startStationId;//乘客上车点
private String startStationName;
private String endStationName;
private int endStationId;//乘客下车点
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public void setPassengerPhone(String passengerPhone) {
this.passengerPhone = passengerPhone;
}
public void setStartStationId(int startStationId) {
this.startStationId = startStationId;
}
public void setStartStationName(String startStationName) {
this.startStationName = startStationName;
}
public void setEndStationName(String endStationName) {
this.endStationName = endStationName;
}
public void setEndStationId(int endStationId) {
this.endStationId = endStationId;
}
public String getOrderNo() {
return orderNo;
}
public String getPassengerPhone() {
return passengerPhone;
}
public int getStartStationId() {
return startStationId;
}
public String getStartStationName() {
return startStationName;
}
public String getEndStationName() {
return endStationName;
}
public int getEndStationId() {
return endStationId;
}
@Override
public String toString() {
return "BusOrderBean{" +
"orderNo=" + orderNo +
", passengerPhone='" + passengerPhone + '\'' +
", startStationId=" + startStationId +
", startStationName='" + startStationName + '\'' +
", endStationName='" + endStationName + '\'' +
", endStationId=" + endStationId +
'}';
}
}

View File

@@ -0,0 +1,23 @@
package com.mogo.och.sweeper.bean;
import com.mogo.eagle.core.data.BaseData;
import java.util.List;
/**
* @author: wangmingjun
* @date: 2021/10/19
*/
public class SweeperOrdersResponse extends BaseData {
public Result data;
public static class Result{
public List<SweeperOrderBean> orders;
}
@Override
public String toString() {
return "BusOrdersResponse{" +
"data=" + data +
'}';
}
}

View File

@@ -0,0 +1,61 @@
package com.mogo.och.sweeper.bean;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
/**
* @author congtaowang
* @since 2021/3/22
*
* 根据车机行驶线路站点信息
*/
public class SweeperQueryLineStationsRequest {
private String sn;
private double lat;
private double lon;
private boolean markDrivingStatus; // 默认falsetrue:是否需要返回站点的行驶状态对应返回的drivingStatus
// 0 - 关闭、1 - 启动
// public String status;
public SweeperQueryLineStationsRequest(double lon, double lat, boolean markDrivingStatus) {
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
this.lat = lat;
this.lon = lon;
this.markDrivingStatus = markDrivingStatus;
}
public boolean isMarkDrivingStatus() {
return markDrivingStatus;
}
public void setMarkDrivingStatus(boolean markDrivingStatus) {
this.markDrivingStatus = markDrivingStatus;
}
public void setLat(double lat) {
this.lat = lat;
}
public void setLon(double lon) {
this.lon = lon;
}
public String getSn() {
return sn;
}
public double getLat() {
return lat;
}
public double getLon() {
return lon;
}
// public BusOperationStatusRequest shutdown() {
// status = "0";
// return this;
// }
//
// public BusOperationStatusRequest launch() {
// status = "1";
// return this;
// }
}

View File

@@ -0,0 +1,23 @@
package com.mogo.och.sweeper.bean;
import com.mogo.eagle.core.data.BaseData;
import java.util.List;
/**
* @author: wangmingjun
* @date: 2022/2/9
*/
public class SweeperQueryLinesResponse extends BaseData {
public List<Result> data;
public static class Result {
public int lineId;//线路id
public String name;//线路名字
public int choose; // 1:绑定 2:未被绑定
public String startSiteName;//始发站名称
public String endSiteName;//终点名称
}
}

View File

@@ -0,0 +1,17 @@
package com.mogo.och.sweeper.bean;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
/**
* @author: wangmingjun
* @date: 2021/10/18
*/
public class SweeperResetDrivingLineRequest {
public String sn;
public int lineId; //切换到的线路id
public SweeperResetDrivingLineRequest(int lineId) {
sn = MoGoAiCloudClientConfig.getInstance().getSn();
this.lineId = lineId;
}
}

View File

@@ -0,0 +1,30 @@
package com.mogo.och.sweeper.bean;
import java.util.List;
/**
* Created by pangfan on 2021/8/19
*
* 订单状态更新请求数据结构
*/
public class SweeperRoutePlanningUpdateReqBean {
public String sn;
public int lineId;
public int startSiteId;
public int endSiteId;
public List<Result> points;
public static class Result {
public Double latitude;
public Double longitude;
}
public SweeperRoutePlanningUpdateReqBean(String sn, int lineId, int startSiteId
, int endSiteId, List<Result> points) {
this.sn = sn;
this.lineId = lineId;
this.startSiteId = startSiteId;
this.endSiteId = endSiteId;
this.points = points;
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.och.sweeper.bean;
import com.mogo.eagle.core.data.BaseData;
/**
* 网约车小巴路线接口请求响应结果
*
* @author tongchenfei
*/
public class SweeperRoutesResponse extends BaseData {
private SweeperRoutesResult data;
public SweeperRoutesResult getResult() {
return data;
}
public void setResult(SweeperRoutesResult data) {
this.data = data;
}
@Override
public String toString() {
return "BusRoutesResponse{" +
"data=" + data +
'}';
}
}

View File

@@ -0,0 +1,69 @@
package com.mogo.och.sweeper.bean;
import java.util.List;
/**
* 网约车小巴路线接口返回接口数据封装
*
* @author tongchenfei
*/
public class SweeperRoutesResult {
private List<SweeperStationBean> sites;
private int lineId;
private String name;
private int lineType; //线路类型0:环形
private String description;
private int status;
//线路轨迹相关字段
public String csvFileUrl = ""; //轨迹文件下载的cos url默认“”
public String csvFileMd5 = ""; //轨迹文件md5默认“”
public String txtFileUrl = ""; //打点文件下载的cos url默认“”
public String txtFileMd5 = ""; //轨迹文件md5默认“”
public long contrailSaveTime; //上传轨迹完成时间戳ms用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖
public String carModel = ""; //[optional] 车型号如红旗H9默认“”暂不加入校验逻辑、用于人工排查问题
public String csvFileUrlDPQP = ""; //轨迹文件下载的cos url默认“”
public String csvFileMd5DPQP = ""; //轨迹文件md5默认“”
public String txtFileUrlDPQP = ""; //打点文件下载的cos url默认“”
public String txtFileMd5DPQP = ""; //轨迹文件md5默认“”
public long contrailSaveTimeDPQP; //上传轨迹完成时间戳ms用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖
public int getLineId() {
return lineId;
}
public String getName() {
return name;
}
public List<SweeperStationBean> getSites() {
return sites;
}
public void setSite(List<SweeperStationBean> site) {
this.sites = sites;
}
@Override
public String toString() {
return "BusRoutesResult{" +
"sites=" + sites +
", lineId=" + lineId +
", name='" + name + '\'' +
", lineType=" + lineType +
", description='" + description + '\'' +
", status=" + status +
", csvFileUrl='" + csvFileUrl + '\'' +
", csvFileMd5='" + csvFileMd5 + '\'' +
", txtFileUrl='" + txtFileUrl + '\'' +
", txtFileMd5='" + txtFileMd5 + '\'' +
", contrailSaveTime=" + contrailSaveTime +
", carModel='" + carModel + '\'' +
", csvFileUrlDPQP='" + csvFileUrlDPQP + '\'' +
", csvFileMd5DPQP='" + csvFileMd5DPQP + '\'' +
", txtFileUrlDPQP='" + txtFileUrlDPQP + '\'' +
", txtFileMd5DPQP='" + txtFileMd5DPQP + '\'' +
", contrailSaveTimeDPQP=" + contrailSaveTimeDPQP +
'}';
}
}

View File

@@ -0,0 +1,162 @@
package com.mogo.och.sweeper.bean;
/**
* 单个网约车小巴车站信息
*
* @author tongchenfei
*/
public class SweeperStationBean {
// private int lineId;
// private int siteId;
// private String siteName;
// private String cityCode;
// private String areaCode;
// private String areaName;
// private double lat;
// private double lon;
// private String siteDesc;
// private int siteState;
// private int isCurrentSite;// @see OchBusConst 是否是当前站 1是 2下一站 0普通站
// private int siteColor;
// private String peoples;
// private int ifStop; // 是否需要停靠、1需要、0不需要
private String name;
private String description;
private String cityCode;
private double lon; //高精坐标
private double lat; //高精坐标
private int businessType; //站点类型9:taxi10:bus
private double gcjLon; //高德
private double gcjLat; //高德
private int status;
private int siteId;
private int seq;
private int drivingStatus;//行驶信息0初始值1已经过2当前站3未到站
private int ifStop = 1; // 是否需要停靠、1需要、0不需要 // TODO: 2021/10/19 原来站点里有设计是否需要停靠字段,现设计暂无,默认都需要停靠
private boolean leaving;
public double getGcjLon() {
return gcjLon;
}
public double getGcjLat() {
return gcjLat;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public void setLon(double lon) {
this.lon = lon;
}
public void setLat(double lat) {
this.lat = lat;
}
public void setBusinessType(int businessType) {
this.businessType = businessType;
}
public void setStatus(int status) {
this.status = status;
}
public void setSiteId(int siteId) {
this.siteId = siteId;
}
public void setSeq(int seq) {
this.seq = seq;
}
public void setDrivingStatus(int drivingStatus) {
this.drivingStatus = drivingStatus;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getCityCode() {
return cityCode;
}
public int getBusinessType() {
return businessType;
}
public int getStatus() {
return status;
}
public int getSiteId() {
return siteId;
}
public int getSeq() {
return seq;
}
public int getDrivingStatus() {
return drivingStatus;
}
public double getLon() {
return lon;
}
public double getLat() {
return lat;
}
public void setIfStop(int ifStop) {
this.ifStop = ifStop;
}
public int getIfStop() {
return ifStop;
}
public void setLeaving(boolean leaving) {
this.leaving = leaving;
}
public boolean isLeaving() {
return leaving;
}
@Override
public String toString() {
return "BusStationBean{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", cityCode='" + cityCode + '\'' +
", lon=" + lon +
", lat=" + lat +
", businessType=" + businessType +
", status=" + status +
", siteId=" + siteId +
", seq=" + seq +
", drivingStatus=" + drivingStatus +
", ifStop=" + ifStop +
", leaving=" + leaving +
'}';
}
}

View File

@@ -0,0 +1,26 @@
package com.mogo.och.sweeper.bean;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
/**
* @author congtaowang
* @since 2021/3/22
*
* 小巴车运营状态请求参数
*/
public class SweeperUpdateSiteStatusRequest {
public String sn;
public int seq;//站点序号
public int siteId;//站点id
public double lon;
public double lat;
public SweeperUpdateSiteStatusRequest(int seq, int siteId, double lon, double lat) {
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
this.seq = seq;
this.siteId = siteId;
this.lon = lon;
this.lat = lat;
}
}

View File

@@ -0,0 +1,9 @@
package com.mogo.och.sweeper.callback;
/**
* @author: wangmingjun
* @date: 2021/10/22
*/
public interface ICarOperationStatusCallback {
void changeOperationStatus(boolean changeStatus);
}

View File

@@ -0,0 +1,13 @@
package com.mogo.och.sweeper.callback;
import com.mogo.och.sweeper.bean.SweeperStationBean;
import java.util.List;
/**
* @author: wangmingjun
* @date: 2021/10/22
*/
public interface IRefreshSweeperStationsCallback {
void refreshBusStations(String lineName, List<SweeperStationBean> stationList, int currentStation, int nextStation, boolean isArrived);
}

View File

@@ -0,0 +1,9 @@
package com.mogo.och.sweeper.callback;
/**
* @author: wangmingjun
* @date: 2021/10/22
*/
public interface ISlidePannelHideCallback {
void hideSlidePanel();
}

View File

@@ -0,0 +1,17 @@
package com.mogo.och.sweeper.callback;
import android.location.Location;
/**
* Created on 2021/9/10
*
* Model->Presenter回调状态控制器监听accOn、adas ui show、voice ui show、push ui show、v2x ui show等等
*/
public interface ISweeperControllerStatusCallback {
// 是否vr map模式
void onVRModeChanged(boolean isVRMode);
// 自车定位
void onCarLocationChanged(Location location);
//开始开启自动驾驶
void startOpenAutopilot();
}

View File

@@ -0,0 +1,12 @@
package com.mogo.och.sweeper.callback;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
/**
* @author: wangmingjun
* @date: 2022/2/9
*/
public interface ISweeperLinesCallback {
void onBusLinesChange(SweeperQueryLinesResponse lines);
void onChangeLineIdSuccess();
}

View File

@@ -0,0 +1,79 @@
package com.mogo.och.sweeper.constant
import com.mogo.commons.debug.DebugConfig
/**
* Created on 2021/12/6
*/
class SweeperConst {
companion object {
private const val BASE_URL_OCH_DEV = "http://tech-dev.zhidaohulian.com"
private const val BASE_URL_OCH_QA = "https://tech-qa.zhidaohulian.com"
private const val BASE_URL_OCH_RELEASE = "https://tech.zhidaohulian.com"
@JvmStatic
fun getBaseUrl(): String {
return when (DebugConfig.getNetMode()) {
DebugConfig.NET_MODE_DEV, DebugConfig.NET_MODE_DEMO -> BASE_URL_OCH_DEV
DebugConfig.NET_MODE_QA -> BASE_URL_OCH_QA
DebugConfig.NET_MODE_RELEASE -> BASE_URL_OCH_RELEASE
else -> BASE_URL_OCH_RELEASE
}
}
// OCH arouter 路由path
const val PATH = "/och/api"
// 测试用的广播
const val BROADCAST_TEST_SWEEPER_CONTROL_TYPE_EXTRA_KEY = "sceneType"
// 无状态
const val STATION_STATUS_IDLE = 0
// 已过站(历史站)
const val STATION_STATUS_LEAVING = 1
// 到站(当前站)
const val STATION_STATUS_STOPPED = 2
// 未到站(未到站)
const val STATION_STATUS_ARRIVING = 3
// 上报心跳轮询ms
const val LOOP_PERIOD_60S = 60 * 1000L
// 开始服务启动自动驾驶等待时间(埋点上传)
const val LOOP_PERIOD_15S = 15 * 1000L
const val LOOP_PERIOD_1S = 1 * 1000L
const val LOOP_DELAY = 100L
// 下发给MEC轨迹信息间隔时间 10秒
const val LOOP_PERIOD_10S = 10 * 1000L
// 尝试下发给MEC轨迹最多10次
const val LOOP_SEND_TRAJ_TIMES = 10
//起点UUID
const val SWEEPER_START_MAP_MAKER = "sweeper_start_map_maker";
//终点UUID
const val SWEEPER_END_MAP_MAKER = "sweeper_end_map_maker";
// 埋点key接管后点击'自动驾驶'按钮启动
const val EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_sweeper_restart_autopilot"
// 埋点key开始服务开启自动驾驶成功/失败)
const val EVENT_KEY_START_SERVICE = "event_key_och_sweeper_start_service"
const val EVENT_PARAM_SN = "sn"
const val EVENT_PARAM_TIME = "time"
const val EVENT_PARAM_START_NAME = "start_name"
const val EVENT_PARAM_END_NAME = "end_name"
const val EVENT_PARAM_LINE_ID = "line_id"
const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false
const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号
const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境true/false
/**
* 订单起终点Marker类型
*/
const val TYPE_MARKER_SWEEPER_ORDER = "TYPE_MARKER_SWEEPER_ORDER"
const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L
//围栏到站 暂定10米
const val ARRIVE_AT_END_STATION_DISTANCE = 10
}
}

View File

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

View File

@@ -0,0 +1,406 @@
package com.mogo.och.sweeper.fragment;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.content.Intent;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.commons.voice.AIAssist;
import com.mogo.eagle.core.data.map.CenterLine;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
import com.mogo.eagle.core.function.call.map.CallerHDMapManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.map.MogoMarkerManager;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.MogoMarkerOptions;
import com.mogo.och.sweeper.R;
import com.mogo.och.sweeper.bean.SweeperStationBean;
import com.mogo.och.sweeper.constant.SweeperConst;
import com.mogo.och.sweeper.presenter.SweeperPresenter;
import com.mogo.och.sweeper.ui.SweeperSwitchLineActivity;
import com.mogo.och.sweeper.view.SlidePanelView;
import com.mogo.och.common.module.utils.OCHThreadPoolManager;
import java.util.List;
/**
* 网约车小巴界面
*
* @author tongchenfei
*/
public class SweeperFragment extends BaseSweeperTabFragment<SweeperFragment, SweeperPresenter>
implements SlidePanelView.OnSlidePanelMoveToEndListener, View.OnClickListener {
private static final String TAG = "SweeperFragment";
private TextView mCurrentStationName;
private TextView mNextStationName;
private TextView mCurrentTag;
private TextView mNextTag;
private TextView mSwitchLine; //切换路线
private TextView mLineName;
private int mCurrentStation = 0;
private View mSweepers;
private SweeperStationBean startStation = null;
private SweeperStationBean endStation = null;
@Override
public String getTagName() {
return "SweepersFragment";
}
@Override
protected void initViews() {
super.initViews();
mSweepers = findViewById(R.id.module_och_sweeper_tag);
mCurrentStationName = findViewById(R.id.module_och_sweeper_current_station);
mCurrentTag = findViewById(R.id.module_och_sweeper_current_station_anchor);
mNextStationName = findViewById(R.id.module_och_sweeper_order_end_station);
mNextTag = findViewById(R.id.module_och_sweeper_next_station_anchor);
mSwitchLine = findViewById(R.id.switch_line_btn);
mLineName = findViewById(R.id.module_och_sweeper_line_name);
if (DebugConfig.isDebug()) {
mSweepers.setOnClickListener(view -> {
ToastUtils.showShort("重置了车站状态");
mPresenter.querySweepersRoutes();
});
//debug下调用测试面板
mCurrentStationName.setOnLongClickListener(v -> {
debugTestBar();
showHideTestBar();
return true;
});
}
CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState());
// 初始化的时候设置 UI 按钮状态
switch (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) {
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
hideAutopilotBiz();
break;
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
showAutopilotBiz();
onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE);
break;
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
showAutopilotBiz();
onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
break;
default:
break;
}
mSwitchLine.setOnClickListener(this);
}
@Override
protected void debugArrivedStation() {
mPresenter.onAutopilotArriveAtStation(null);
}
@NonNull
@Override
protected SweeperPresenter createPresenter() {
return new SweeperPresenter(this);
}
@Override
public void onResume() {
super.onResume();
}
/**
* 根据站点列表信息刷新车站面板,滑块面板
*
* @param stationList 车站列表信息
* @param currentStation 当前站点
* @param nextStation 下个站点
* @param isArrived 是否都站
*/
public void refreshSweeperStations(String lineName, List<SweeperStationBean> stationList
, int currentStation, int nextStation, boolean isArrived) {
mCurrentStation = currentStation;
if (getActivity() == null) {
return;
}
getActivity().runOnUiThread(() -> {
if (stationList == null) {
// 获取小巴数据失败
return;
}
// 渲染小巴路线数据
renderCurrentStationStatus(lineName,stationList, currentStation, nextStation, isArrived);
});
}
/**
* 重新刷新站点信息 isArrived 是否到站
*/
private void renderCurrentStationStatus(String lineName, List<SweeperStationBean> stationList, int currentStation
, int nextStation, boolean isArrived) {
CallerLogger.INSTANCE.d(M_BUS + "MapMaker ", "currentStation=" + currentStation + ",nextStation=" + nextStation + "isArrived=" + isArrived);
String currentStationName = null;
String nextStationName = null;
boolean isArriveEndStation = false;
boolean isArriveAtStation = false;
boolean isArriveAtStartStation = false;
mLineName.setText(lineName);
// 获取当前站点的名称
currentStationName = stationList.get(currentStation).getName();
startStation = stationList.get(0);
endStation = stationList.get(stationList.size() - 1);
// 是否到达起点
if (currentStation == 0) {
isArriveAtStartStation = true;
mCurrentTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_start));
setOrRemoveMapMaker(true, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat()
, startStation.getLon(),R.raw.star_marker);
setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
} else if (currentStation > 0 && currentStation < stationList.size() - 1) {// 是否到达站点
isArriveAtStation = true;
mCurrentTag.setText(getResources().getString(R.string.sweeper_arrive_to_current_tag));
mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_next_tag));
setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat()
, startStation.getLon(),R.raw.star_marker);
setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
} else if (currentStation == stationList.size() - 1) {// 是否到达终点
isArriveEndStation = true;
nextStationName = "--";
mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_end));
setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat()
, startStation.getLon(),R.raw.star_marker);
if (isArrived) {
setOrRemoveMapMaker(false, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
} else {
setOrRemoveMapMaker(true, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
}
}
// 获取下一站点名称
if (nextStation > currentStation && nextStation <= stationList.size() - 1) {
nextStationName = stationList.get(nextStation).getName();
}
// 是否到达终点
if ( nextStation == stationList.size() - 1 || nextStation == -1) {
mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_end_end));
}else {
mNextTag.setText(getResources().getString(R.string.sweeper_arrive_to_next_tag));
}
if (currentStation == 0 && isArrived){
showOrHideSwitchLineBtn(true);
}else {
showOrHideSwitchLineBtn(false);
}
// 重置滑动按钮文字
if (isArriveEndStation) {
showSlidePanle("单程结束");
} else if (isArriveAtStartStation) {
showSlidePanle("滑动出发");
} else if (isArriveAtStation) {
showSlidePanle("滑动出发");
}
mCurrentStationName.setText(currentStationName);
mNextStationName.setText(nextStationName);
updateSweeperTestBarInfo();
}
private void showOrHideSwitchLineBtn(boolean isShow) {
if (isShow){
mSwitchLine.setVisibility(View.VISIBLE);
}else {
mSwitchLine.setVisibility(View.GONE);
}
}
public void hideOchSweeper() {
// tvNotice.setVisibility(View.GONE);
}
@Override
public int getStationPanelViewId() {
return R.layout.fragment_och_sweeper;
}
@Override
public int getSweepOperatePanelViewId() {
return R.layout.sweeper_operate_panel_view;
}
@Override
public void restartAutopilot() {
if (!isAnimateRunning) {
mPresenter.restartAutopilot();
}
}
@Override
public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() {
return this;
}
@Override
public void moveToEnd() {
// 开启自动驾驶到下一站
if (isAnimateRunning){
stopAutopilotAnimation();
}
mPresenter.autoDriveToNextStation(false);
}
/**
* 设置自动驾驶可用状态
*/
public void onAutopilotEnableChange(boolean isEnable) {
if (isEnable) {
showAutopilotBiz();
} else {
hideAutopilotBiz();
}
}
@Override
protected void onChangeOperationStatus() {
super.onChangeOperationStatus();
mPresenter.onChangeOperationStatus();
}
/**
* 修改经营状态
*
* @param launch true-收车false-出车
*/
public void changeOperationStatus(boolean launch) {
isOperationStatus = launch;
if (launch) {
// 出车的时候重制站点状态
mPresenter.querySweepersRoutes();
tvOperationStatus.setText("收车");
showPanel();
} else {
AIAssist.getInstance(getContext()).speakTTSVoice("已收车");
tvOperationStatus.setText("出车");
hideSlidePanel();
hidPanel();
//移除起点终点
if (null != startStation) {
setOrRemoveMapMaker(false, SweeperConst.SWEEPER_START_MAP_MAKER, startStation.getLat()
, startStation.getLon(),R.raw.star_marker);
}
if (null != endStation) {
setOrRemoveMapMaker(false, SweeperConst.SWEEPER_END_MAP_MAKER, endStation.getLat()
, endStation.getLon(),R.raw.end_marker);
}
}
}
/**
* VR模式切换
*
* @param isVRMode
*/
public void onVRModeChanged(boolean isVRMode) {
if (mRootView != null) {
mRootView.setVisibility(isVRMode ? View.VISIBLE : View.GONE);
}
}
/**
* 绘制地图起点终点
*
* @param isAdd
* @param uuid
*/
private void setOrRemoveMapMaker(boolean isAdd, String uuid, double lat, double longi,int resourceId) {
if (isAdd) {
Runnable setMapMarkerRunnable = new Runnable() {
@Override
public void run() {
CallerLogger.INSTANCE.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(),
uuid + "=latitude=" + lat + ",longitude=" + longi);
MogoMarkerOptions options = new MogoMarkerOptions()
.owner(SweeperConst.TYPE_MARKER_SWEEPER_ORDER)
.anchor(0.5f, 0.5f)
.set3DMode(true)
.gps(true)
.controlAngle(true)
.icon3DRes(resourceId)
.latitude(lat)
.longitude(longi);
IMogoMarker marker = MogoMarkerManager.getInstance(AbsMogoApplication.getApp()) .addMarker(uuid, options);
CenterLine centerLine = CallerHDMapManager.INSTANCE.getCenterLineInfo(
longi,lat,-1);
if (null != centerLine){ // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致
marker.setRotateAngle(centerLine.getAngle().floatValue());
}
}
};
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable);
}else {
Runnable removeMapMarkerRunnable = new Runnable() {
@Override
public void run() {
CallerLogger.INSTANCE.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(),
uuid+"=latitude="+lat+",longitude="+longi);
MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).removeMarkers(uuid);
}
};
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable);
}
}
@Override
public void debugAutoPilotStatus(int status) {
mPresenter.debugAutoPilotStatus(status);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中点击则toast提示自动驾驶中不可切换路线
//本次行程未结束不支持切换路线。点击则toast提示当前行程未完成不可切换路线
if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()
== IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
ToastUtils.showLong(getResources().getString(R.string.sweeper_switch_line_btn_warning1));
return;
}
if (mCurrentStation > 0) {
ToastUtils.showLong(getResources().getString(R.string.sweeper_switch_line_btn_warning2));
return;
}
Intent intent = new Intent(getContext(), SweeperSwitchLineActivity.class);
startActivity(intent);
}
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.och.sweeper.model;
import android.content.Context;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.eagle.core.utilcode.util.NetworkUtils;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
import com.mogo.och.sweeper.bean.SweeperRoutesResponse;
import com.mogo.och.sweeper.callback.ISweeperLinesCallback;
import com.mogo.och.sweeper.net.SweeperServiceManager;
import com.mogo.och.sweeper.net.ISweeperServiceCallback;
/**
* @author: wangmingjun
* @date: 2022/2/9
*/
public class SweeperLineModel {
private static volatile SweeperLineModel sInstance;
private Context mContext;
private ISweeperLinesCallback mBusLinesCallback;
public static SweeperLineModel getInstance() {
if ( sInstance == null ) {
synchronized ( SweeperLineModel.class ) {
if ( sInstance == null ) {
sInstance = new SweeperLineModel();
}
}
}
return sInstance;
}
private SweeperLineModel() {
}
public void init() {
mContext = AbsMogoApplication.getApp();
}
public void setBusLinesCallback(ISweeperLinesCallback callback){
mBusLinesCallback = callback;
}
public void queryBusLines(){
SweeperServiceManager.getInstance().queryBusLines(mContext, new ISweeperServiceCallback<SweeperQueryLinesResponse>() {
@Override
public void onSuccess(SweeperQueryLinesResponse data) {
if (null == data && mBusLinesCallback != null) {
mBusLinesCallback.onBusLinesChange(null);
return;
}
if (mBusLinesCallback != null){
mBusLinesCallback.onBusLinesChange(data);
}
}
@Override
public void onFail(String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else {
ToastUtils.showShort("查询所有绑定路线失败:"+failMsg);
}
}
});
}
public void commitSwitchLineId(int lineId){
SweeperServiceManager.getInstance().resetStationStatus(mContext,lineId, new ISweeperServiceCallback<SweeperRoutesResponse>() {
@Override
public void onSuccess(SweeperRoutesResponse o) {
if (mBusLinesCallback != null){
mBusLinesCallback.onChangeLineIdSuccess();
}
}
@Override
public void onFail(String failMsg) {
if (!NetworkUtils.isConnected(mContext)) {
ToastUtils.showShort("网络异常,请稍后重试");
}else {
ToastUtils.showShort("切换路线失败:"+failMsg);
}
}
});
}
}

View File

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

View File

@@ -0,0 +1,117 @@
package com.mogo.och.sweeper.net;
import com.mogo.eagle.core.data.BaseData;
import com.mogo.och.sweeper.bean.SweeperOperationStatusRequest;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
import com.mogo.och.sweeper.bean.SweeperRoutePlanningUpdateReqBean;
import com.mogo.och.sweeper.bean.SweeperRoutesResponse;
import com.mogo.och.sweeper.bean.CarHeartbeatReqBean;
import com.mogo.och.sweeper.bean.SweeperQueryLineStationsRequest;
import com.mogo.och.sweeper.bean.SweeperOperationStatusResponse;
import com.mogo.och.sweeper.bean.SweeperResetDrivingLineRequest;
import com.mogo.och.sweeper.bean.SweeperUpdateSiteStatusRequest;
import io.reactivex.Observable;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Query;
/**
* 小巴车相关接口
*
* @author tongchenfei
* <p>
* wiki: http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48970072
*/
public interface ISweeperApiService {
/**
* 根据车机坐标获取所在区域全部站点信息
*
* @param request 请求参数
* @return 接口返回数据
*/
@Headers( {"Content-Type:application/json;charset=UTF-8"} )
@POST( "/autopilot-car-hailing/line/v2/driver/bus/lineDataWithDriver/query" )
Observable<SweeperRoutesResponse> querySiteByCoordinate(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperQueryLineStationsRequest request);
/**
* 重置巴士路线: 点击小巴车tab 或者出车后会使用
*
* @param request 请求参数{"destLine":1,"sn":"F803EB2046PZD00229"} 这个接口是重置bus线路的 不是重置线路中站点的
* @return 返回值是重置后的车站列表
*/
@Headers( {"Content-Type:application/json;charset=UTF-8"} )
@POST( "/autopilot-car-hailing/car/v2/driver/bus/drivingLine/reset" )
Observable<SweeperRoutesResponse> resetStationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperResetDrivingLineRequest request);
/**
* 离站,通知服务器
* @param request
* @return
*/
@Headers({"Content-Type:application/json;charset=UTF-8"})
@POST("/autopilot-car-hailing/car/v2/driver/bus/driving/away")
Observable<SweeperRoutesResponse> leaveStation(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperUpdateSiteStatusRequest request);
/**
* 到站 更新到站信息
* @param request
* @return
*/
@Headers({"Content-type:application/json;charset=UTF-8"})
@POST("/autopilot-car-hailing/order/v2/driver/bus/driving/attachSite")
Observable< BaseData > arriveSiteStation(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperUpdateSiteStatusRequest request);
/**
* 出车
* @param request
* @return
*/
@Headers( {"Content-type:application/json;charset=UTF-8"} )
@POST("/autopilot-car-hailing/car/v2/driver/bus/startTakeOrder")
Observable<BaseData> startTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperOperationStatusRequest request);
/**
* 收车
* @param request
* @return
*/
@Headers({"Content-type:application/json;charset=UTF-8"})
@POST("/autopilot-car-hailing/car/v2/driver/bus/stopTakeOrder")
Observable<BaseData> stopTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweeperOperationStatusRequest request);
/**
* 查询小巴出车/收车状态
* @param sn
* @return
*/
@Headers({"Content-type:application/json;charset=UTF-8"})
@GET("/autopilot-car-hailing/car/v2/driver/bus/takeOrderStatus/query")
Observable<SweeperOperationStatusResponse> queryOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
/**
* 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度
* @param data
* @return
*/
@Headers( {"Content-type:application/json;charset=UTF-8"} )
@POST( "/autopilot-car-hailing/location/v2/driver/bus/heartbeat" )
Observable<BaseData> runCarHeartbeat(@Header ("appId") String appId,@Header("ticket") String ticket,@Body CarHeartbeatReqBean data);
/**
* 查询车辆配置的所有路线
* @param appId
* @param ticket
* @param sn
* @return
*/
@GET("/autopilot-car-hailing/line/v2/driver/bus/bindLine/query")
Observable<SweeperQueryLinesResponse> queryBusLines(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
@Headers( {"Content-type:application/json;charset=UTF-8"} )
@POST( "/autopilot-car-hailing/location/v2/driver/bus/saveLineCoordinate" )
Observable<BaseData> updateOrderRoute(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweeperRoutePlanningUpdateReqBean data);
}

View File

@@ -1,10 +1,10 @@
package com.mogo.och.bus.net;
package com.mogo.och.sweeper.net;
/**
* @author: wangmingjun
* @date: 2021/10/20
*/
public interface IBusServiceCallback< T >{
public interface ISweeperServiceCallback< T >{
void onSuccess(T o);
void onFail(String failMsg);

View File

@@ -1,5 +1,4 @@
package com.mogo.och.bus.net;
package com.mogo.och.sweeper.net;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.content.Context;
@@ -10,22 +9,17 @@ import com.mogo.eagle.core.network.MoGoRetrofitFactory;
import com.mogo.eagle.core.network.RequestOptions;
import com.mogo.eagle.core.network.SubscribeImpl;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.och.bus.bean.BusCloseTaskRequest;
import com.mogo.och.bus.bean.BusQueryLineTaskResponse;
import com.mogo.och.bus.bean.BusQueryLinesResponse;
import com.mogo.och.bus.bean.BusQueryWriteOffPassengersResponse;
import com.mogo.och.bus.bean.BusRoutePlanningUpdateReqBean;
import com.mogo.och.bus.bean.BusRoutesResponse;
import com.mogo.och.bus.bean.BusWriteOffPassengersQueryRequest;
import com.mogo.och.bus.bean.CarHeartbeatReqBean;
import com.mogo.och.bus.bean.BusOrdersResponse;
import com.mogo.och.bus.bean.BusQueryLineStationsRequest;
import com.mogo.och.bus.bean.BusResetDrivingLineRequest;
import com.mogo.och.bus.bean.BusUpdateSiteStatusRequest;
import com.mogo.och.bus.bean.QueryLeaveAwayPassengersRequest;
import com.mogo.och.bus.bean.QueryLeaveAwayPassengersResponse;
import com.mogo.och.bus.constant.BusConst;
import com.mogo.och.bus.model.BusOrderModel;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
import com.mogo.och.sweeper.bean.SweeperRoutePlanningUpdateReqBean;
import com.mogo.och.sweeper.bean.SweeperRoutesResponse;
import com.mogo.och.sweeper.bean.CarHeartbeatReqBean;
import com.mogo.och.sweeper.bean.SweeperOperationStatusRequest;
import com.mogo.och.sweeper.bean.SweeperOperationStatusResponse;
import com.mogo.och.sweeper.bean.SweeperQueryLineStationsRequest;
import com.mogo.och.sweeper.bean.SweeperResetDrivingLineRequest;
import com.mogo.och.sweeper.bean.SweeperUpdateSiteStatusRequest;
import com.mogo.och.sweeper.constant.SweeperConst;
import com.mogo.och.sweeper.model.SweeperOrderModel;
import java.util.List;
@@ -36,78 +30,51 @@ import io.reactivex.schedulers.Schedulers;
* @author: wangmingjun
* @date: 2021/10/20
*/
public class BusServiceManager {
public class SweeperServiceManager {
private static final String TAG = BusServiceManager.class.getSimpleName();
private static final String TAG = SweeperServiceManager.class.getSimpleName();
private final IBusApiService mService;
private final ISweeperApiService mService;
private static final class SingletonHolder {
private static final BusServiceManager INSTANCE = new BusServiceManager();
private static final SweeperServiceManager INSTANCE = new SweeperServiceManager();
}
public static BusServiceManager getInstance(){
public static SweeperServiceManager getInstance(){
return SingletonHolder.INSTANCE;
}
private BusServiceManager(){
mService = MoGoRetrofitFactory.getInstance(BusConst.getBaseUrl()).create(IBusApiService.class);
private SweeperServiceManager(){
mService = MoGoRetrofitFactory.getInstance(SweeperConst.getBaseUrl()).create(ISweeperApiService.class);
}
/**
* 查询小巴车当前任务
* 查询小巴车线路
* @param context
* @param callback
*/
public void queryBusRoutes(Context context, IBusServiceCallback<BusRoutesResponse> callback) {
public void queryBusRoutes(Context context, ISweeperServiceCallback<SweeperRoutesResponse> callback) {
//获取当前高德坐标
mService.queryBusRoutes(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
mService.querySiteByCoordinate(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
, new BusQueryLineStationsRequest())
, new SweeperQueryLineStationsRequest(SweeperOrderModel.getInstance().mLongitude
, SweeperOrderModel.getInstance().mLatitude,true))
.subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() )
.subscribe( getSubscribeImpl(context,callback,"queryBusRoutes"));
.subscribe( getSubscribeImpl(context,callback,"querySiteByCoordinate"));
}
/**
* 重置线路站点
* @param context
* @param taskId
* @param lineId
* @param callback
*/
public void switchLine(Context context, int taskId, IBusServiceCallback<BusRoutesResponse> callback){
mService.switchLine(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken(),new BusResetDrivingLineRequest(taskId))
public void resetStationStatus(Context context, int lineId, ISweeperServiceCallback<SweeperRoutesResponse> callback){
mService.resetStationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken(),new SweeperResetDrivingLineRequest(lineId))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"switchLine"));
}
/**
* 中断当前任务
* @param context
* @param taskId
* @param callback
*/
public void abortTask(Context context, int taskId, IBusServiceCallback<BaseData> callback){
mService.abortTask(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusCloseTaskRequest(taskId))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"abortTask"));
}
/**
* 正常结束任务
* @param context
* @param taskId
* @param callback
*/
public void endTask(Context context, int taskId, IBusServiceCallback<BaseData> callback){
mService.endTask(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusCloseTaskRequest(taskId))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"endTask"));
.subscribe(getSubscribeImpl(context,callback,"debugResetStationStatus"));
}
/**
@@ -117,10 +84,11 @@ public class BusServiceManager {
* @param siteId
* @param callback
*/
public void leaveStation(Context context, int seq, int siteId,int taskId, IBusServiceCallback<BaseData> callback){
public void leaveStation(Context context, int seq, int siteId, ISweeperServiceCallback<SweeperRoutesResponse> callback){
mService.leaveStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusUpdateSiteStatusRequest(taskId,siteId,seq))
,new SweeperUpdateSiteStatusRequest(seq,siteId, SweeperOrderModel.getInstance().mLongitude
, SweeperOrderModel.getInstance().mLatitude))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"leaveStation"));
@@ -133,87 +101,74 @@ public class BusServiceManager {
* @param siteId
* @param callback
*/
public void arriveSiteStation(Context context, int seq, int siteId,int taskId,
IBusServiceCallback<BaseData> callback){
public void arriveSiteStation(Context context, int seq, int siteId, ISweeperServiceCallback<BaseData> callback){
mService.arriveSiteStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusUpdateSiteStatusRequest(taskId,siteId,seq))
,new SweeperUpdateSiteStatusRequest(seq,siteId
, SweeperOrderModel.getInstance().mLongitude, SweeperOrderModel.getInstance().mLatitude))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"arriveSiteStation"));
.subscribe(getSubscribeImpl(context,callback,"leaveStation"));
}
/**
* 查询下车乘客
* 收车
* @param context
* @param seq
* @param siteId
* @param callback
*/
public void queryStationLeaveAwayPassengers(Context context, int seq, int siteId
, IBusServiceCallback<QueryLeaveAwayPassengersResponse> callback){
mService.queryStationLeaveAwayPassengers( MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken(),new QueryLeaveAwayPassengersRequest(seq,siteId))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"queryStationLeaveAwayPassengers"));
}
/**
* 查询当前到站点核销乘客
* @param context
* @param siteId
* @param callback
*/
public void queryStationWriteOffPassengers(Context context,int taskId,int siteId,long prePassengerTime
, IBusServiceCallback<BusQueryWriteOffPassengersResponse> callback){
mService.queryWriteOffPassengers( MoGoAiCloudClientConfig.getInstance().getServiceAppId()
public void stopTakeOrder(Context context, ISweeperServiceCallback<BaseData> callback){
mService.stopTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusWriteOffPassengersQueryRequest(taskId,siteId,prePassengerTime))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"queryStationWriteOffPassengers"));
,new SweeperOperationStatusRequest(SweeperOrderModel.getInstance().mLongitude
, SweeperOrderModel.getInstance().mLatitude))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"stopTakeOrder"));
}
/**
* 查询小巴车订单
* 出车
* @param context
* @param callback
*/
public void queryBusOrders(Context context, IBusServiceCallback<BusOrdersResponse> callback){
mService.queryBusOrders(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
public void startTakeOrder(Context context, ISweeperServiceCallback<BaseData> callback){
mService.startTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new SweeperOperationStatusRequest(SweeperOrderModel.getInstance().mLongitude
, SweeperOrderModel.getInstance().mLatitude))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"startTakeOrder"));
}
/**
* 查询出车/收车状态
* @param context
* @param callback
*/
public void queryOperationStatus(Context context, ISweeperServiceCallback<SweeperOperationStatusResponse> callback){
mService.queryOperationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"queryBusOrders"));
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe(getSubscribeImpl(context,callback,"queryOperationStatus"));
}
public void queryBusLines(Context context, IBusServiceCallback<BusQueryLinesResponse> callback){
public void queryBusLines(Context context, ISweeperServiceCallback<SweeperQueryLinesResponse> callback){
mService.queryBusLines(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,MoGoAiCloudClientConfig.getInstance().getSn())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"queryBusLines"));
}
public void queryBusTaskByLineId(Context context,String lineId,IBusServiceCallback<BusQueryLineTaskResponse> callback){
mService.queryBusTaskByLineId(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,lineId)
,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeImpl(context,callback,"queryBusLines"));
}
public void updateOrderRoute(Context context,int lineId, int startSiteId, int endSiteId
, List< BusRoutePlanningUpdateReqBean.Result > points
, IBusServiceCallback<BaseData> callback){
, List< SweeperRoutePlanningUpdateReqBean.Result > points
, ISweeperServiceCallback<BaseData> callback){
mService.updateOrderRoute(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken()
,new BusRoutePlanningUpdateReqBean(MoGoAiCloudClientConfig.getInstance().getSn()
,new SweeperRoutePlanningUpdateReqBean(MoGoAiCloudClientConfig.getInstance().getSn()
,lineId,startSiteId,endSiteId, points))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -228,7 +183,7 @@ public class BusServiceManager {
* @param callback
*/
public void runCarHeartbeat(Context context, double lon, double lat,
IBusServiceCallback<BaseData> callback) {
ISweeperServiceCallback<BaseData> callback) {
mService.runCarHeartbeat(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
,MoGoAiCloudClientConfig.getInstance().getToken(),new CarHeartbeatReqBean(
MoGoAiCloudClientConfig.getInstance().getSn(), lon, lat))
@@ -237,7 +192,7 @@ public class BusServiceManager {
.subscribe(getSubscribeImpl(context, callback, "runCarHeartbeat"));
}
private <T extends BaseData> SubscribeImpl getSubscribeImpl(Context context, IBusServiceCallback<T> callback, String apiName){
private <T extends BaseData> SubscribeImpl getSubscribeImpl(Context context, ISweeperServiceCallback<T> callback, String apiName){
return new SubscribeImpl<T>(RequestOptions.create(context)){
@Override
public void onSuccess(T o) {

View File

@@ -0,0 +1,79 @@
package com.mogo.och.sweeper.presenter;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import com.mogo.commons.mvp.Presenter;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
import com.mogo.och.sweeper.callback.ISweeperLinesCallback;
import com.mogo.och.sweeper.model.SweeperLineModel;
import com.mogo.och.sweeper.model.SweeperOrderModel;
import com.mogo.och.sweeper.ui.SweeperSwitchLineView;
/**
* @author: wangmingjun
* @date: 2022/2/9
*/
public class SweeperLinePresenter extends Presenter<SweeperSwitchLineView> implements ISweeperLinesCallback {
public SweeperLinePresenter(SweeperSwitchLineView view) {
super(view);
SweeperLineModel.getInstance().init();
SweeperOrderModel.getInstance().init();
}
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
super.onCreate(owner);
initListener();
}
private void initListener() {
SweeperLineModel.getInstance().setBusLinesCallback(this);
}
private void runOnUIThread( Runnable executor ) {
if ( executor == null ) {
return;
}
if ( Looper.myLooper() != Looper.getMainLooper() ) {
UiThreadHandler.post( executor );
} else {
executor.run();
}
}
@Override
public void onBusLinesChange(SweeperQueryLinesResponse lines) {
runOnUIThread(() -> mView.onBusLinesChange(lines));
}
@Override
public void onChangeLineIdSuccess() {
runOnUIThread(() -> mView.onChangeLineIdSuccess());
}
public void queryBusLines(){
SweeperLineModel.getInstance().queryBusLines();
}
public void commitSwitchLineId(int lineId){
SweeperLineModel.getInstance().commitSwitchLineId(lineId);
}
public void removeListener(){
SweeperLineModel.getInstance().setBusLinesCallback(null);
}
public void queryBusRoutes(){
SweeperOrderModel.getInstance().querySweeperRoutes();
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
super.onDestroy(owner);
}
}

View File

@@ -0,0 +1,55 @@
package com.mogo.och.sweeper.presenter;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.och.sweeper.constant.SweeperConst;
import com.mogo.och.sweeper.model.SweeperOrderModel;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* Created on 2021/11/22
*
* 管理轮询逻辑(订单轮询、新单轮询、新单抢单结果轮询等等)
*/
public class SweeperModelLoopManager {
private static final String TAG = SweeperModelLoopManager.class.getSimpleName();
private static final class SingletonHolder {
private static final SweeperModelLoopManager INSTANCE = new SweeperModelLoopManager();
}
public static SweeperModelLoopManager getInstance() {
return SingletonHolder.INSTANCE;
}
private Disposable mHeartbeatDisposable; //心跳轮询
public void startHeartbeatLoop() {
if (mHeartbeatDisposable != null && !mHeartbeatDisposable.isDisposed()) {
return;
}
CallerLogger.INSTANCE.i(M_BUS + TAG, "startHeartbeatLoop()");
mHeartbeatDisposable = Observable.interval(SweeperConst.LOOP_DELAY,
SweeperConst.LOOP_PERIOD_60S, TimeUnit.MILLISECONDS)
.map((aLong -> aLong + 1))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> SweeperOrderModel.getInstance().runCarHeartbeat());
}
public void stopHeartbeatLoop() {
if (mHeartbeatDisposable != null) {
CallerLogger.INSTANCE.i(M_BUS + TAG, "stopHeartbeatLoop()");
mHeartbeatDisposable.dispose();
mHeartbeatDisposable = null;
}
}
}

View File

@@ -0,0 +1,288 @@
package com.mogo.och.sweeper.presenter;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.location.Location;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import com.mogo.commons.mvp.Presenter;
import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo;
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.sweeper.bean.SweeperStationBean;
import com.mogo.och.sweeper.callback.ICarOperationStatusCallback;
import com.mogo.och.sweeper.callback.ISweeperControllerStatusCallback;
import com.mogo.och.sweeper.callback.IRefreshSweeperStationsCallback;
import com.mogo.och.sweeper.callback.ISlidePannelHideCallback;
import com.mogo.och.sweeper.fragment.SweeperFragment;
import com.mogo.och.sweeper.model.SweeperOrderModel;
import com.mogo.och.sweeper.util.SweeperTrajectoryManager;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import mogo.telematics.pad.MessagePad;
import mogo_msg.MogoReportMsg;
import system_master.SystemStatusInfo;
/**
* 网约车小巴
*
* @author tongchenfei
*/
public class SweeperPresenter extends Presenter<SweeperFragment>
implements ICarOperationStatusCallback, IRefreshSweeperStationsCallback, ISlidePannelHideCallback
, IMoGoAutopilotStatusListener, ISweeperControllerStatusCallback {
private static final String TAG = "BusPresenter";
private int currentAutopilotStatus = -1;
private List<SweeperStationBean> mStationList = new ArrayList<>();
private int mCurrentStation = 0;
private boolean isRestartAutopilot = false;
public SweeperPresenter(SweeperFragment view) {
super(view);
//2021.11.1 鹰眼架构整合由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口
CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, this);
SweeperOrderModel.getInstance().init();
}
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
super.onCreate(owner);
SweeperOrderModel.getInstance().queryOperationStatus();
SweeperOrderModel.getInstance().querySweeperRoutes();
initModelListener();
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
super.onDestroy(owner);
SweeperOrderModel.getInstance().release();
releaseListener();
}
public void initModelListener() {
SweeperOrderModel.getInstance().setCarOperationStatusCallback(this);
SweeperOrderModel.getInstance().setRefreshBusStationsCallback(this);
SweeperOrderModel.getInstance().setSlidePannelHideCallback(this);
SweeperOrderModel.getInstance().setControllerStatusCallback(this);
}
public void releaseListener() {
SweeperOrderModel.getInstance().setCarOperationStatusCallback(null);
SweeperOrderModel.getInstance().setRefreshBusStationsCallback(null);
SweeperOrderModel.getInstance().setSlidePannelHideCallback(null);
SweeperOrderModel.getInstance().setControllerStatusCallback(null);
}
public void querySweepersRoutes() {
SweeperOrderModel.getInstance().querySweeperRoutes();
}
public void debugResetStationStatus() {
SweeperOrderModel.getInstance().debugResetStationStatus();
}
public void autoDriveToNextStation(boolean isRestart) {
currentAutopilotStatus = -1;
SweeperOrderModel.getInstance().autoDriveToNextStation(isRestart);
isRestartAutopilot = false;
}
public void restartAutopilot() {
// if (SweeperOrderModel.getInstance().isGoingToNextStation()){
currentAutopilotStatus = -1;
SweeperOrderModel.getInstance().restartAutopilot();
isRestartAutopilot = true;
// }
}
public void onChangeOperationStatus() {
SweeperOrderModel.getInstance().onChangeOperationStatus();
}
@Override
public void changeOperationStatus(boolean changeStatus) {
if (mView != null) {
runOnUIThread(() -> mView.changeOperationStatus(changeStatus));
}
}
@Override
public void refreshBusStations(String lineName,List<SweeperStationBean> stationList
, int currentStation, int nextStation, boolean isArrived) {
mStationList.clear();
mStationList.addAll(stationList);
mCurrentStation = currentStation;
// functionDemoModeChange();
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation);
if (mView != null) {
runOnUIThread(() -> mView.refreshSweeperStations(lineName,
stationList, currentStation, nextStation, isArrived));
}
}
private void functionDemoModeChange() {
// CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel ="," functionDemoModeChange ="+mCurrentStation);
if (FunctionBuildConfig.isDemoMode
&& ((mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|| ((mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
&& SweeperOrderModel.getInstance().isGoingToNextStation()))) {
runOnUIThread(() -> mView.onAutopilotStatusChanged(
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING));
}
}
@Override
public void hideSlidePanel() {
if (mView != null) {
runOnUIThread(() -> mView.hideSlidePanel());
}
}
@Override
public void onAutopilotArriveAtStation(MessagePad.ArrivalNotification arrivalNotification) {
SweeperOrderModel.getInstance().onArriveAt(arrivalNotification);
}
@Override
public void onAutopilotSNRequest() {
}
@Override
public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) {
if (autopilotStatusInfo == null) return;
int state = autopilotStatusInfo.getState();
// CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChange: " + state + "currentAutopilotStatus = " + currentAutopilotStatus);
switch (state) {
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) {
if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->1语音提示
// AIAssist.getInstance( getContext() ).speakTTSVoice( "已进入人工驾驶模式" );
}
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE;
// 设置UI【自动驾驶】按钮是否展示
runOnUIThread(() -> mView.onAutopilotEnableChange(true));
if (SweeperOrderModel.getInstance().isGoingToNextStation()) {
runOnUIThread(() -> mView.hideSlidePanel());
}
if (FunctionBuildConfig.isDemoMode
&& (
(mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|| (
(mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
&& SweeperOrderModel.getInstance().isGoingToNextStation()
)
)
) {
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能");
return;
}
// 改变UI自动驾驶状态
runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus));
}
break;
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING;
// 改变UI自动驾驶状态
runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus));
SweeperOrderModel.getInstance().triggerStartServiceEvent(
isRestartAutopilot, true);
}
break;
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) {
if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->0语音提示
// AIAssist.getInstance( getContext() ).speakTTSVoice( "自动驾驶已停止,请人工接管" );
}
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE;
if (FunctionBuildConfig.isDemoMode
&& (
(mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|| (
(mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
&& SweeperOrderModel.getInstance().isGoingToNextStation()
)
)
) {
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能");
return;
}
runOnUIThread(() -> {
mView.onAutopilotStatusChanged(currentAutopilotStatus);
});
}
break;
default:
runOnUIThread(() -> mView.onAutopilotEnableChange(false));
break;
}
}
@Override
public void onVRModeChanged(boolean isVRMode) {
runOnUIThread(() -> mView.onVRModeChanged(isVRMode));
}
@Override
public void onCarLocationChanged(Location location) {
if (null != location) {
runOnUIThread(() -> mView.updateSpeedView(location.getSpeed()));
}
}
@Override
public void startOpenAutopilot() {
//非美化模式下启动动画
runOnUIThread(() -> mView.startAutopilotAnimation());
}
private void runOnUIThread(Runnable executor) {
if (executor == null) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
UiThreadHandler.post(executor);
} else {
executor.run();
}
}
/**
* 测试使用
*
* @param status
*/
public void debugAutoPilotStatus(int status) {
AutopilotStatusInfo info = new AutopilotStatusInfo();
info.setState(status);
onAutopilotStatusResponse(info);
}
@Override
public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo) {
SweeperTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo);
}
@Override
public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) {
}
@Override
public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) {
}
}

View File

@@ -0,0 +1,42 @@
package com.mogo.och.sweeper.receiver;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.och.sweeper.constant.SweeperConst;
/**
* 测试小巴车的场景
*
* @author donghongyu
* @date 4/26/21 12:08 PM
*/
public class TestSweeperBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "TestBusBroadcastReceiver";
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
try {
this.mContext = context;
int sceneType = intent.getIntExtra(SweeperConst.BROADCAST_TEST_SWEEPER_CONTROL_TYPE_EXTRA_KEY, 0);
CallerLogger.INSTANCE.d(M_BUS + TAG, "sceneType:" + sceneType);
// 分发场景
dispatchSceneTest(sceneType);
} catch (Exception e) {
e.printStackTrace();
}
}
private void dispatchSceneTest(int sceneType) {
}
}

View File

@@ -0,0 +1,300 @@
package com.mogo.och.sweeper.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.mogo.commons.mvp.MvpActivity;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.och.sweeper.R;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
import com.mogo.och.sweeper.presenter.SweeperLinePresenter;
import java.util.ArrayList;
import java.util.List;
/**
* @author: wangmingjun
* @date: 2022/2/8
*/
public class SweeperSwitchLineActivity extends MvpActivity<SweeperSwitchLineView, SweeperLinePresenter>
implements View.OnClickListener, SweeperSwitchLineView {
private ImageView mClose;
private ConstraintLayout mNoDatasView;
private RecyclerView mLinesListView;
private TextView mLineCommitBtn;
private SwitchLineAdapter mAdapter;
private List<SweeperQueryLinesResponse.Result> mData = new ArrayList<>();
private int mSelectLineId = -1;
@Override
protected int getLayoutId() {
return R.layout.activity_sweeper_switch_line;
}
@NonNull
@Override
protected SweeperLinePresenter createPresenter() {
return new SweeperLinePresenter(this);
}
@Override
protected void initViews() {
initWH();
initView();
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDatas();
}
/**
* 初始化view
*/
private void initView() {
mClose = findViewById(R.id.switch_line_close);
mClose.setOnClickListener(this);
mNoDatasView = findViewById(R.id.no_order_data_view);
mLineCommitBtn = findViewById(R.id.switch_line_btn_commit);
mLineCommitBtn.setOnClickListener(this);
mLinesListView = findViewById(R.id.switch_line_rv);
mLinesListView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new SwitchLineAdapter(getApplicationContext(),mData);
mLinesListView.setAdapter(mAdapter);
//设置item 点击事件
mAdapter.setOnLineItemClickListener(new LineItemClickListener() {
@Override
public void onItemClick(int position) {
if (mData.size() > position && !TextUtils.isEmpty(mData.get(position).startSiteName )
&& !TextUtils.isEmpty(mData.get(position).endSiteName)){
mSelectLineId = mData.get(position).lineId;
}else {
mSelectLineId = -1;
}
}
});
}
/**
* 设置布局宽高
*/
private void initWH() {
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
windowManager.getDefaultDisplay().getSize(point);//用于获取屏幕高度
params.width = (int)(point.x * 0.375);
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
window.setAttributes(params);
window.setGravity(Gravity.LEFT|Gravity.BOTTOM);
}
/**
* 初始化数据
*/
private void initDatas() {
mPresenter.queryBusLines();
}
/**
* 查询返回绑定路线集合
* @param data
*/
@Override
public void onBusLinesChange(SweeperQueryLinesResponse data){
if (null == data){
showNoData(true);
return;
}
if (data.data != null && data.data.size() > 0){
showNoData(false);
mData.clear();
mData.addAll(data.data);
mAdapter.notifyDataSetChanged();
changeCommitBtnBg();
}else {
showNoData(true);
}
}
/**
* 根据路线选中情况设置提交按钮样式
*/
private void changeCommitBtnBg() {
for (int i=0; i<mData.size();i++){
if (mData.get(i).choose == 1){
mLineCommitBtn.setBackgroundResource(R.drawable.sweeper_switch_line_btn_commit);
mLineCommitBtn.setTextColor(getResources().getColor(R.color.sweeper_white));
return;
}
}
}
@Override
public void onChangeLineIdSuccess(){
ToastUtils.showLong(getResources().getString(R.string.sweeper_change_line_commit_tip_s));
mPresenter.queryBusRoutes();
if (mAdapter != null){
mAdapter.setOnLineItemClickListener(null);
}
mPresenter.removeListener();
finish();
}
/**
* 有无数据UI显示
* @param b
*/
private void showNoData(boolean b) {
if (b){
mLinesListView.setVisibility(View.GONE);
mLineCommitBtn.setVisibility(View.GONE);
mNoDatasView.setVisibility(View.VISIBLE);
}else {
mLinesListView.setVisibility(View.VISIBLE);
mLineCommitBtn.setVisibility(View.VISIBLE);
mNoDatasView.setVisibility(View.GONE);
}
}
@Override
public void onClick(View v) {
//关闭dialog
if (v.getId() == R.id.switch_line_close){
finish();
return;
}
//切换路线提交
if (v.getId() == R.id.switch_line_btn_commit){
if (mSelectLineId > -1){
mPresenter.commitSwitchLineId(mSelectLineId);
}else {
finish();
}
return;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
/**
* 路线列表adapter
*/
static class SwitchLineAdapter extends RecyclerView.Adapter<SwitchLineViewHolder>{
private Context mContext;
private List<SweeperQueryLinesResponse.Result> mData;
// RecyclerView设置点击事件
private LineItemClickListener mItemClickListener ;
private int clickPos = -1;
public SwitchLineAdapter(Context context, List<SweeperQueryLinesResponse.Result> data){
mContext = context;
mData = data;
}
@NonNull
@Override
public SwitchLineViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.sweeper_switch_line_list_item
,parent,false);
SwitchLineViewHolder viewHolder = new SwitchLineViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull SwitchLineViewHolder holder, @SuppressLint("RecyclerView") int position) {
SweeperQueryLinesResponse.Result line = mData.get(position);
holder.lineName.setText(mContext.getString(R.string.sweeper_switch_line_name)+" "+line.name);
holder.lineStartName.setText(mContext.getString(R.string.sweeper_line_start)+" "+line.startSiteName);
holder.lineEndName.setText(mContext.getString(R.string.sweeper_line_end)+" "+line.endSiteName);
//设置item点击事件
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null){
mItemClickListener.onItemClick(position);
clickPos = position;
notifyDataSetChanged();
}
}
});
//选中绑定
if (clickPos > -1){
if (clickPos == position){
holder.selectIv.setImageResource(R.drawable.sweeper_selected_btn);
}else {
holder.selectIv.setImageResource(R.drawable.sweeper_unselect_btn);
}
}else {
if (line.choose == 1){//1:绑定 2:未绑定 默认绑定
if (mItemClickListener != null) {
mItemClickListener.onItemClick(position);
}
holder.selectIv.setImageResource(R.drawable.sweeper_selected_btn);
}else {
holder.selectIv.setImageResource(R.drawable.sweeper_unselect_btn);
}
}
}
@Override
public int getItemCount() {
return mData.size();
}
public void setOnLineItemClickListener(LineItemClickListener itemClickListener){
this.mItemClickListener = itemClickListener ;
}
}
static class SwitchLineViewHolder extends RecyclerView.ViewHolder{
private ImageView selectIv;
private TextView lineName; //线路名称
private TextView lineStartName; //起点
private TextView lineEndName; //终点
public SwitchLineViewHolder(@NonNull View itemView) {
super(itemView);
selectIv = itemView.findViewById(R.id.switch_line_item_select_iv);
lineName = itemView.findViewById(R.id.switch_line_name);
lineStartName = itemView.findViewById(R.id.switch_line_start_station);
lineEndName = itemView.findViewById(R.id.switch_line_end_station);
}
}
public interface LineItemClickListener {
void onItemClick(int position) ;
}
}

View File

@@ -0,0 +1,15 @@
package com.mogo.och.sweeper.ui;
import com.mogo.commons.mvp.IView;
import com.mogo.och.sweeper.bean.SweeperQueryLinesResponse;
/**
* @author: wangmingjun
* @date: 2022/2/10
*/
public interface SweeperSwitchLineView extends IView {
void onBusLinesChange(SweeperQueryLinesResponse data);
void onChangeLineIdSuccess();
}

View File

@@ -0,0 +1,167 @@
package com.mogo.och.sweeper.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.sweeper.R;
import com.mogo.och.common.module.wigets.OCHGradientTextView;
import org.jetbrains.annotations.Nullable;
/**
* Bus司机端红绿灯view
*
* Created on 2022/3/29
*/
public class SweeperTrafficLightView extends IViewTrafficLight {
private ImageView mLightIconIV;
private OCHGradientTextView mLightTimeTV;
private int mCurrentLightId;
public SweeperTrafficLightView(@Nullable Context context) {
this(context, null, 0);
}
public SweeperTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SweeperTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.sweeper_traffic_light_view, this, true);
mLightIconIV = findViewById(R.id.sweeper_traffic_light_iv);
mLightTimeTV = findViewById(R.id.sweeper_traffic_light_time_tv);
}
/**
* 展示红绿灯预警
*
* @param checkLightId 0-都是默认1-红2-黄3-绿
* @param lightSource 1:云端下发2:自车感知
*/
@Override
public void showWarningTrafficLight(int checkLightId,int lightSource) {
super.showWarningTrafficLight(checkLightId,lightSource);
mCurrentLightId = checkLightId;
updateTrafficLightIcon(checkLightId);
}
/**
* 关闭红绿灯预警展示,并重制灯态
*/
@Override
public void disableWarningTrafficLight() {
super.disableWarningTrafficLight();
UiThreadHandler.post(() -> {
mCurrentLightId = 0;
SweeperTrafficLightView.this.setVisibility(GONE);
});
}
/**
* @param redNum 红灯倒计时
* @param yellowNum 黄灯倒计时
* @param greenNum 绿灯倒计时
*/
@Override
public void changeCountdownTrafficLightNum(int redNum, int yellowNum, int greenNum) {
super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum);
switch (mCurrentLightId) {
case 1:
changeCountdownRed(redNum);
break;
case 2:
changeCountdownYellow(yellowNum);
break;
case 3:
changeCountdownGreen(greenNum);
break;
default:
UiThreadHandler.post(() -> {
mLightTimeTV.setText("");
});
break;
}
}
@Override
public void changeCountdownRed(int redNum) {
super.changeCountdownRed(redNum);
UiThreadHandler.post(() -> {
if (redNum > 0) {
mLightTimeTV.setVertrial(true);
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_red_color_up),
getResources().getColor(R.color.sweeper_traffic_light_red_color_down)});
mLightTimeTV.setText(String.valueOf(redNum));
} else {
mLightTimeTV.setText("");
}
});
}
@Override
public void changeCountdownGreen(int greenNum) {
super.changeCountdownGreen(greenNum);
UiThreadHandler.post(() -> {
if (greenNum > 0) {
mLightTimeTV.setVertrial(true);
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_green_color_up),
getResources().getColor(R.color.sweeper_traffic_light_green_color_down)});
mLightTimeTV.setText(String.valueOf(greenNum));
} else {
mLightTimeTV.setText("");
}
});
}
@Override
public void changeCountdownYellow(int yellowNum) {
super.changeCountdownYellow(yellowNum);
UiThreadHandler.post(() -> {
if (yellowNum > 0) {
mLightTimeTV.setVertrial(true);
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweeper_traffic_light_yellow_color_up),
getResources().getColor(R.color.sweeper_traffic_light_yellow_color_down)});
mLightTimeTV.setText(String.valueOf(yellowNum));
} else {
mLightTimeTV.setText("");
}
});
}
/**
* 更新红绿灯icon
*
* @param lightId 0-都是默认1-红2-黄3-绿
*/
private void updateTrafficLightIcon(int lightId) {
UiThreadHandler.post(() -> {
switch (lightId) {
case 1:
mLightIconIV.setBackgroundResource(R.drawable.sweeper_light_red_nor);
SweeperTrafficLightView.this.setVisibility(VISIBLE);
break;
case 2:
mLightIconIV.setBackgroundResource(R.drawable.sweeper_lightyellow_nor);
SweeperTrafficLightView.this.setVisibility(VISIBLE);
break;
case 3:
mLightIconIV.setBackgroundResource(R.drawable.sweeper_light_green_nor);
SweeperTrafficLightView.this.setVisibility(VISIBLE);
break;
default:
SweeperTrafficLightView.this.setVisibility(GONE);
break;
}
});
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,81 @@
package com.mogo.och.sweeper.util;
import android.text.TextUtils;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.eagle.core.data.app.AppConfigInfo;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
import com.mogo.eagle.core.function.call.analytics.AnalyticsManager;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
import com.mogo.eagle.core.utilcode.util.DateTimeUtils;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.och.sweeper.constant.SweeperConst;
import java.util.HashMap;
/**
* OCH sweeper埋点工具
*
* Created on 2022/3/24
*/
public class SweeperAnalyticsManager {
private static final class SingletonHolder {
private static final SweeperAnalyticsManager INSTANCE = new SweeperAnalyticsManager();
}
public static SweeperAnalyticsManager getInstance() {
return SweeperAnalyticsManager.SingletonHolder.INSTANCE;
}
private String mStartAutopilotKey;
private HashMap<String, Object> mStartAutopilotParams = new HashMap<>();
private Runnable startAutopilotRunnable = () -> {
// 15s内未开启上报失败埋点
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_RESULT
, CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() ==
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
};
/**
* 触发'开启自动驾驶'埋点流程
* 开启自动驾驶15s内成功则发送成功埋点否则发送失败埋点
* @param restart false点击'滑动出发'启动)/true接管后点击'自动驾驶'按钮启动)
* @param send 是否直接发送埋点15s内开启成功则直接发送成功埋点
*/
public void triggerStartAutopilotEvent(
boolean restart, boolean send, String startName, String endName, int lineId) {
mStartAutopilotKey = restart ?
SweeperConst.EVENT_KEY_RESTART_AUTOPILOT : SweeperConst.EVENT_KEY_START_SERVICE;
String sn = MoGoAiCloudClientConfig.getInstance().getSn();
String plateNum = AppConfigInfo.INSTANCE.getPlateNumber();
String dateTime = DateTimeUtils.getTimeText(
System.currentTimeMillis(), DateTimeUtils.yyyy_MM_dd_HH_mm_ss);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_SN, sn);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_ENV_ONLINE,
DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_TIME, dateTime);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_NAME, startName);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_END_NAME, endName);
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_LINE_ID, lineId);
if (send) {
// 开启成功,上报埋点
if (startAutopilotRunnable != null &&
UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) {
UiThreadHandler.removeCallbacks(startAutopilotRunnable);
}
mStartAutopilotParams.put(SweeperConst.EVENT_PARAM_START_RESULT, true);
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
} else {
UiThreadHandler.postDelayed(startAutopilotRunnable, SweeperConst.LOOP_PERIOD_15S);
}
}
}

View File

@@ -0,0 +1,148 @@
package com.mogo.och.sweeper.util;
import chassis.SpecialVehicleTaskCmdOuterClass;
import chassis.VehicleStateOuterClass;
/**
* 清扫车-福田,构建业务命令数据的工具类
*/
public class SweeperFutianCmdUtil {
private static final int CLEAN_WORK_OPEN = 1; //清扫作业-开启
private static final int CLEAN_WORK_CLOSE = 2;//清扫作业-关闭
public static final int CLEAN_MODE_PURE_SWEEP = 1;//作业模式-纯扫
public static final int CLEAN_MODE_WASH_SWEEP = 2;//作业模式-洗扫
public static final int CLEAN_MODE_PURE_WASH = 3;//作业模式-纯洗
public static final int CLEAN_MODE_PURE_DRAW = 4;//作业模式-纯吸
private static final int CLEAN_MODE_CLOSE = 5;//作业模式-关闭
public static final int CLEAN_DIRECTION_BOTH_SIDE = 1;//清扫方向-两侧
public static final int CLEAN_DIRECTION_LEFT_SIDE = 2;//清扫方向-左侧
public static final int CLEAN_DIRECTION_RIGHT_SIDE = 3;//清扫方向-右侧
private static final int CLEAN_DIRECTION_CLOSE = 4;//清扫方向-关闭
public static final int CLEAN_INTENSITY_STRAND = 1;//作业强度-标准
public static final int CLEAN_INTENSITY_STRONG = 2;//作业强度-加强
/**
* 清扫作业:打开
*
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkStartCmd() {
return buildCleanWorkCmd(CLEAN_WORK_OPEN);
}
/**
* 清扫作业:关闭
*
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkStopCmd() {
return buildCleanWorkCmd(CLEAN_WORK_CLOSE);
}
private static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanWorkCmd(int startOrStop) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanOpenRequirement(startOrStop);
return buildTaskCmd(builder.build());
}
/**
* 作业模式:传入具体的模式对应的值
*
* @param value
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModeCmd(int value) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanModeRequirement(value);
return buildTaskCmd(builder.build());
}
/**
* 作业模式:纯吸
*
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModePureDrawCmd() {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanModeRequirement(CLEAN_MODE_PURE_DRAW);
//不用设置作业方向,自动设置作业强度为:标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
/**
* 作业模式:关闭作业模式
*
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanModeCloseCmd() {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanModeRequirement(CLEAN_MODE_CLOSE);
//关闭清扫方向,待下次在选择
builder.setCleanDirectionRequirement(CLEAN_DIRECTION_CLOSE);
//自动设置作业强度为:标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
/**
* 作业方向:根据具体的方向传入具体的值
*
* @param value
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanDirectionCmd(int value) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanDirectionRequirement(value);
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
// 同时作业强度默认:标准
return buildTaskCmd(builder.build());
}
/**
* 作业方向:关闭作业方向
*
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanDirectionCloseCmd() {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanDirectionRequirement(CLEAN_DIRECTION_CLOSE);
//重置作业强度为标准
builder.setCleanIntensityRequirement(CLEAN_INTENSITY_STRAND);
return buildTaskCmd(builder.build());
}
/**
* 作业强度:传入具体的值
*
* @param value
* @return
*/
public static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildCleanIntensityCmd(int value) {
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
builder.setCleanIntensityRequirement(value);
return buildTaskCmd(builder.build());
}
private static SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd buildTaskCmd(
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd fuTianCleanCmd) {
return SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd.newBuilder()
.setRoboSweeperFutianCleanCmd(fuTianCleanCmd).build();
}
/**
* 构建底盘Mock数据
*
* @return
*/
public static VehicleStateOuterClass.SweeperFuTianCleanSystemState buildSweeperFuTionCleanSystemStateMockData() {
VehicleStateOuterClass.SweeperFuTianCleanSystemState.Builder builder = VehicleStateOuterClass.SweeperFuTianCleanSystemState.newBuilder();
builder.setSecuMotWorkSts(true);
builder.setSecuModWashSts(true);
builder.setSecuWorkOnBothsidesSts(true);
builder.setSecuWorkStrongSts(true);
return builder.build();
}
}

View File

@@ -0,0 +1,204 @@
package com.mogo.och.sweeper.util;
import androidx.annotation.Nullable;
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.GsonUtils;
import com.mogo.och.sweeper.bean.SweeperRoutesResult;
import com.mogo.och.sweeper.constant.SweeperConst;
import com.mogo.och.sweeper.model.SweeperOrderModel;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import mogo_msg.MogoReportMsg;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
/**
* Bus轨迹管理给MEC下发用于轨迹下载的信息
* Created on 2022/6/23
*/
public class SweeperTrajectoryManager {
private static final String TAG = SweeperTrajectoryManager.class.getSimpleName();
private static final class SingletonHolder {
private static final SweeperTrajectoryManager INSTANCE = new SweeperTrajectoryManager();
}
public static SweeperTrajectoryManager getInstance() {
return SweeperTrajectoryManager.SingletonHolder.INSTANCE;
}
private AutopilotControlParameters.AutoPilotLine mAutoPilotLine = null;
private Disposable mSendReqDisposable = null;
public SweeperTrajectoryManager() {
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(-1,
"", "", "", "", 0, "",
"", "", "", "", 0);
}
/**
* 同步Bus路线信息
*/
public void syncTrajectoryInfo() {
SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult();
if (SweeperOrderModel.getInstance().isWorking() && routesResult != null
&& SweeperOrderModel.getInstance().getCurrentStationIndex() == 0
&& !SweeperOrderModel.getInstance().isGoingToNextStation()) {
CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() start.");
startTrajReqLoop();
} else {
// 无路线信息or当前未在始发站
CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() stop.");
stopTrajReqLoop();
}
}
/**
* 接口MEC反馈的常规信息MAP v2.5.0新增轨迹相关信息)
* @param guardianInfo
*/
public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) {
if (guardianInfo == null || !guardianInfo.hasCode()) return;
if ("ISYS_INIT_TRAJECTORY_START".equals(guardianInfo.getCode())) {
// 1. 轨迹管理_轨迹开始下载本地已有对应轨迹也触发
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹开始下载");
// ToastUtils.showShort("轨迹开始下载");
stopTrajReqLoop();
} else if ("ISYS_INIT_TRAJECTORY_SUCCESS".equals(guardianInfo.getCode())) {
// 2. 轨迹管理_轨迹下载成功本地已有对应轨迹也触发
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载成功");
// ToastUtils.showShort("轨迹下载成功");
stopTrajReqLoop();
} else if ("ISYS_INIT_TRAJECTORY_FAILURE".equals(guardianInfo.getCode())) {
// 3. 轨迹管理_轨迹下载失败本地无对应轨迹
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " +
"轨迹下载失败,本地无对应轨迹");
// ToastUtils.showShort("轨迹下载失败,本地无对应轨迹");
} else if ("ISYS_INIT_TRAJECTORY_WARNING".equals(guardianInfo.getCode())) {
// 4. 轨迹管理_轨迹下载失败本地有对应轨迹认为成功
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " +
"轨迹下载失败,本地有对应轨迹,认为成功");
// ToastUtils.showShort("轨迹下载失败,本地有对应轨迹,认为成功");
} else if ("ISYS_INIT_TRAJECTORY_TIMEOUT".equals(guardianInfo.getCode())) {
// 5. 轨迹管理_轨迹下载超时
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载超时");
// ToastUtils.showShort("轨迹下载超时");
}
}
private void setupAutoPilotLine() {
SweeperRoutesResult routesResult = SweeperOrderModel.getInstance().getBusRoutesResult();
if (routesResult == null) {
CallerLogger.INSTANCE.e(M_BUS + TAG,
"setupAutoPilotLine(): routesResult is null.");
return;
} else {
if (mAutoPilotLine == null) {
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(routesResult.getLineId(),
routesResult.csvFileUrl, routesResult.csvFileMd5,
routesResult.txtFileUrl, routesResult.txtFileMd5,
routesResult.contrailSaveTime, routesResult.carModel,
routesResult.csvFileUrlDPQP, routesResult.csvFileMd5DPQP,
routesResult.txtFileUrlDPQP, routesResult.txtFileMd5DPQP,
routesResult.contrailSaveTimeDPQP);
} else {
mAutoPilotLine.setLineId(routesResult.getLineId());
mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl);
mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5);
mAutoPilotLine.setStopUrl(routesResult.txtFileUrl);
mAutoPilotLine.setStopMd5(routesResult.txtFileMd5);
mAutoPilotLine.setTimestamp(routesResult.contrailSaveTime);
mAutoPilotLine.setVehicleModel(routesResult.carModel);
mAutoPilotLine.setTrajUrl_dpqp(routesResult.csvFileUrlDPQP);
mAutoPilotLine.setTrajMd5_dpqp(routesResult.csvFileMd5DPQP);
mAutoPilotLine.setStopUrl_dpqp(routesResult.txtFileUrlDPQP);
mAutoPilotLine.setStopMd5_dpqp(routesResult.txtFileMd5DPQP);
mAutoPilotLine.setTimestamp_dpqp(routesResult.contrailSaveTimeDPQP);
}
}
}
private void clearAutoPilotLine() {
if (mAutoPilotLine == null) return;
mAutoPilotLine.setLineId(-1);
mAutoPilotLine.setTrajUrl("");
mAutoPilotLine.setTrajMd5("");
mAutoPilotLine.setStopUrl("");
mAutoPilotLine.setStopMd5("");
mAutoPilotLine.setTimestamp(0);
mAutoPilotLine.setVehicleModel("");
mAutoPilotLine.setTrajUrl_dpqp("");
mAutoPilotLine.setTrajMd5_dpqp("");
mAutoPilotLine.setStopUrl_dpqp("");
mAutoPilotLine.setStopMd5_dpqp("");
mAutoPilotLine.setTimestamp_dpqp(0);
}
private void startTrajReqLoop() {
if (mSendReqDisposable != null && !mSendReqDisposable.isDisposed()) {
return;
}
CallerLogger.INSTANCE.d(M_BUS + TAG, "startTrajReqLoop()");
setupAutoPilotLine();
mSendReqDisposable = Observable.interval(SweeperConst.LOOP_DELAY,
SweeperConst.LOOP_PERIOD_10S, TimeUnit.MILLISECONDS)
.map((aLong -> aLong + 1))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> {
if (aLong > SweeperConst.LOOP_SEND_TRAJ_TIMES) {
stopTrajReqLoop();
return;
}
CallerLogger.INSTANCE.d(M_BUS + TAG, "loop sendTrajectoryReq: " + aLong);
sendTrajectoryReq();
});
}
public void stopTrajReqLoop() {
if (mSendReqDisposable != null) {
CallerLogger.INSTANCE.d(M_BUS + TAG, "stopTrajReqLoop()");
mSendReqDisposable.dispose();
mSendReqDisposable = null;
clearAutoPilotLine();
}
}
private void sendTrajectoryReq() {
if (mAutoPilotLine == null) {
CallerLogger.INSTANCE.e(M_BUS + TAG, "sendTrajectoryReq(): mAutoPilotLine is null!!!");
return;
}
// TODO: 2022/6/24
// test1
// mAutoPilotLine.setLineId(148);
// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/e27c20c2da32481021d934c3ef084536/traj_148.csv");
// mAutoPilotLine.setTrajMd5("e27c20c2da32481021d934c3ef084536");
// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/6224c9dd2c0e2bd990c6482c0464de45/stop_148.txt");
// mAutoPilotLine.setStopMd5("6224c9dd2c0e2bd990c6482c0464de45");
// mAutoPilotLine.setTimestamp(1654596000000L); //20220607 18:00
// mAutoPilotLine.setVehicleModel("红旗H9");
// test2
// mAutoPilotLine.setLineId(148);
// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/8654497cf918be461a59c7ad8e22920d/traj_148.csv");
// mAutoPilotLine.setTrajMd5("8654497cf918be461a59c7ad8e22920d");
// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/1bb098b244922649bf3e7bada0d3950f/stop_148.txt");
// mAutoPilotLine.setStopMd5("1bb098b244922649bf3e7bada0d3950f");
// mAutoPilotLine.setTimestamp(1654761600000L); //20220609 16:00
// mAutoPilotLine.setVehicleModel("红旗H9");
CallerAutoPilotManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine);
CallerLogger.INSTANCE.d(M_BUS + TAG, "sendTrajectoryReq(): "
+ GsonUtils.toJson(mAutoPilotLine));
}
}

View File

@@ -0,0 +1,190 @@
package com.mogo.och.sweeper.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import androidx.annotation.Nullable;
import com.mogo.och.sweeper.R;
/**
* created by wujifei on 2021/3/24 16:20
* describe:
*/
public class BusArcView extends View {
//中心的文字描述
private String mDes = "KM/H";
//根据数据显示的圆弧Paint
private Paint mArcPaint;
//圆弧颜色
private int mArcColor;
//圆弧的画笔的宽度
private float mStrokeWith = getResources().getDimension(R.dimen.sweeper_ext_arcView_stroke_with);
//文字描述的paint
private Paint mTextPaint;
//当前进度夹角大小
private float mIncludedAngle = 0;
//当前数据
private int currentValue;
//最大数据
private int maxValue = 240;
//圆弧背景的开始和结束间的夹角大小
private float mAngle = 270;
//上次绘制圆弧夹角
private float lastAngle = 0;
public BusArcView(Context context) {
this(context, null);
}
public BusArcView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BusArcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//初始化paint
initPaint();
//绘制弧度
drawArc(canvas);
//绘制文本
drawText(canvas);
}
private void drawText(Canvas canvas) {
Rect mRect = new Rect();
String mValue = String.valueOf(currentValue);
mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
//绘制中心的数值
mTextPaint.getTextBounds(mValue, 0, mValue.length(), mRect);
canvas.drawText(mValue, getWidth() / 2, getHeight() / 2 + mRect.height() / 2 - 10, mTextPaint);
mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
//绘制中心文字描述
mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweeper_ext_arcView_des_text_size));
mTextPaint.getTextBounds(mDes, 0, mDes.length(), mRect);
canvas.drawText(mDes, getWidth() / 2, getHeight() * 17 / 20 + mRect.height() / 2, mTextPaint);
}
private void drawArc(Canvas canvas) {
//绘制圆弧背景
RectF mRectF = new RectF(mStrokeWith, mStrokeWith, getWidth() - mStrokeWith, getHeight() - mStrokeWith);
canvas.drawArc(mRectF, 135, mAngle, false, mArcPaint);
//绘制当前数值对应的圆弧
mArcPaint.setColor(mArcColor);
//根据当前数据绘制对应的圆弧
canvas.drawArc(mRectF, 135, mIncludedAngle, false, mArcPaint);
}
private void initPaint() {
//圆弧的paint
mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//抗锯齿
mArcPaint.setAntiAlias(true);
mArcPaint.setColor(Color.parseColor("#151D4C"));
//设置透明度数值为0-255
mArcPaint.setAlpha(100);
//设置画笔的画出的形状
mArcPaint.setStrokeJoin(Paint.Join.ROUND);
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
//设置画笔类型
mArcPaint.setStyle(Paint.Style.STROKE);
//画笔宽度
mArcPaint.setStrokeWidth(mStrokeWith);
//中心文字的paint
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.parseColor("#FFFFFF"));
//设置文本的对齐方式
mTextPaint.setTextAlign(Paint.Align.CENTER);
//mTextPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.dp_12));
mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweeper_ext_arcView_center_text_size));
}
/**
* 为绘制弧度及数据设置动画
*
* @param startAngle 开始的弧度
* @param currentAngle 需要绘制的弧度
* @param time 动画执行的时长
*/
private void setAnimation(float startAngle, float currentAngle, int time) {
//绘制当前数据对应的圆弧的动画效果
ValueAnimator progressAnimator = ValueAnimator.ofFloat(startAngle, currentAngle);
progressAnimator.setDuration(time);
progressAnimator.setTarget(mIncludedAngle);
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mIncludedAngle = (float) animation.getAnimatedValue();
//重新绘制,不然不会出现效果
postInvalidate();
}
});
//开始执行动画
progressAnimator.start();
}
/**
* 设置弧形颜色
*
* @param value 颜色值
*/
public void setArcColor(int value) {
mArcColor = value;
}
/**
* 设置数据
*
* @param value 当前绘制的值
*/
public void setValues(int value) {
//完全覆盖
if (value > maxValue) {
value = maxValue;
}
if (value < 0) {
value = 0;
}
currentValue = value;
//计算弧度比重
float scale = (float) currentValue / maxValue;
//计算弧度
float currentAngle = scale * mAngle;
//开始执行动画
setAnimation(lastAngle, currentAngle, 1000);
lastAngle = currentAngle;
//重新绘制
postInvalidate();
}
private float dp2px(float dp) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
return dp * metrics.density;
}
}

View File

@@ -0,0 +1,37 @@
package com.mogo.och.sweeper.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.mogo.commons.debug.DebugConfig;
/**
* 强制拦截所有touch时间的约束布局
*
* @author tongchenfei
*/
public class NoTouchConstraintLayout extends ConstraintLayout {
public NoTouchConstraintLayout(Context context) {
super(context);
}
public NoTouchConstraintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoTouchConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(DebugConfig.isDebug()){
return super.onInterceptTouchEvent(ev);
}else {
return true;
}
}
}

View File

@@ -0,0 +1,270 @@
package com.mogo.och.sweeper.view;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import androidx.annotation.Nullable;
import com.mogo.och.sweeper.R;
/**
* 滑块滑动面板
*
* @author tongchenfei
*/
public class SlidePanelView extends View {
private static final String TAG = "SlidePanelView";
public SlidePanelView(Context context) {
this(context, null);
}
public SlidePanelView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidePanelView);
textSize = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_textSize, textSize);
BLOCK_START_X = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_X, BLOCK_START_X);
BLOCK_START_Y = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_Y, BLOCK_START_Y);
NORMAL_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_LEFT, NORMAL_TEXT_MARGIN_LEFT);
NORMAL_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_RIGHT, NORMAL_TEXT_MARGIN_RIGHT);
SHORT_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_LEFT, SHORT_TEXT_MARGIN_LEFT);
SHORT_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_RIGHT, SHORT_TEXT_MARGIN_RIGHT);
init();
}
private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private static int textSize = 40;
private static int BLOCK_START_X = 15;
private static int BLOCK_START_Y = 15;
private static int NORMAL_TEXT_MARGIN_LEFT = 40;
private static int NORMAL_TEXT_MARGIN_RIGHT = 60;
private static int SHORT_TEXT_MARGIN_LEFT = 60;
private static int SHORT_TEXT_MARGIN_RIGHT = 70;
private int textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
private int textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
private OnSlidePanelMoveToEndListener moveToEndListener;
private int blockWidth = 0;
private int blockOffset = 0;
private float lastX;
private boolean isToEnd = false;
private static final String STRING_SLIDE_TO_RIGHT = "向右滑动";
private RectF bgRectF;
private Bitmap bmBlock;
private final Matrix gradientMatrix = new Matrix();
private float matrixTranslate;
private final Rect textRect = new Rect();
private LinearGradient textGradient;
private ObjectAnimator matrixAnim;
private String blockText = STRING_SLIDE_TO_RIGHT;
private Paint.FontMetrics blockTextMetrics = new Paint.FontMetrics();
private static final int GRADIENT_OFFSET = 200;
public void setOnSlidePanelMoveToEndListener(OnSlidePanelMoveToEndListener moveToEndListener) {
this.moveToEndListener = moveToEndListener;
}
private void setBlockOffset(int blockOffset) {
this.blockOffset = blockOffset;
invalidate();
}
private void setMatrixTranslate(float matrixTranslate) {
this.matrixTranslate = matrixTranslate;
invalidate();
}
public void setText(String text) {
this.blockText = text;
requestLayout();
invalidate();
}
private void init() {
bgRectF = new RectF(0, 0, 0, 0);
bgPaint.setColor(Color.parseColor("#CC0F1325"));
bgPaint.setStyle(Paint.Style.FILL);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(textSize);
textPaint.setTextAlign(Paint.Align.LEFT);
textGradient = new LinearGradient(-GRADIENT_OFFSET, 0, 0, 0, new int[]{0x33ffffff, 0xffffffff, 0x33ffffff}, null, Shader.TileMode.CLAMP);
textGradient.setLocalMatrix(gradientMatrix);
textPaint.setShader(textGradient);
textPaint.getFontMetrics(blockTextMetrics);
bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.sweeper_base_slide_block);
blockWidth = bmBlock.getWidth();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize;
int heightSize;
if (blockText.length() < 5) {
textMarginLeft = SHORT_TEXT_MARGIN_LEFT;
textMarginRight = SHORT_TEXT_MARGIN_RIGHT;
} else {
textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
}
if (widthMode == MeasureSpec.AT_MOST) {
// 宽度根据图片大小,字符串长度,各种间隔确定
// 高度根据图片大小和上下间隔确定
textPaint.getTextBounds(blockText, 0, blockText.length(), textRect);
widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + textMarginLeft + textMarginRight + textRect.width();
heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight();
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private float textOffset = 0;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (bgRectF != null){
bgRectF.left = 0;
bgRectF.top = 0;
bgRectF.right = w;
bgRectF.bottom = h;
}
if (matrixAnim != null) {
matrixAnim.cancel();
}
textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2;
matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + GRADIENT_OFFSET).setDuration(2000);
matrixAnim.setRepeatCount(ValueAnimator.INFINITE);
matrixAnim.start();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (matrixAnim != null) {
matrixAnim.start();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (matrixAnim != null) {
matrixAnim.cancel();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) {
isToEnd = false;
lastX = x;
}
break;
case MotionEvent.ACTION_MOVE:
if (lastX != 0) {
blockOffset = (int) (x - lastX);
if (blockOffset < 0) {
blockOffset = 0;
}
if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) {
// 超出右边界
blockOffset = getWidth() - BLOCK_START_X - blockWidth;
if (!isToEnd) {
isToEnd = true;
if (moveToEndListener != null) {
moveToEndListener.moveToEnd();
}
startBlockBackAnim();
}
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// 执行滑块回归动画
if (!isToEnd) {
startBlockBackAnim();
}
break;
default:
break;
}
return true;
}
private void startBlockBackAnim() {
ObjectAnimator blockBackanimator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0);
blockBackanimator.setInterpolator(new DecelerateInterpolator());
blockBackanimator.setDuration(1000 * blockOffset / getWidth());
blockBackanimator.start();
lastX = 0;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画背景
canvas.drawRoundRect(bgRectF, (float) getHeight() / 2, (float) getHeight() / 2, bgPaint);
// 画文字
gradientMatrix.setTranslate(matrixTranslate, 0);
textGradient.setLocalMatrix(gradientMatrix);
canvas.save();
canvas.drawText(blockText, blockWidth + BLOCK_START_X + textMarginLeft, textOffset, textPaint);
canvas.restore();
// 画滑块
canvas.drawBitmap(bmBlock, BLOCK_START_X + blockOffset, BLOCK_START_Y, blockPaint);
}
public interface OnSlidePanelMoveToEndListener {
/**
* 滑块滑到了末尾
*/
void moveToEnd();
}
}

View File

@@ -0,0 +1,64 @@
package com.mogo.och.sweeper.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
/**
* 垂直虚线
*
* @author tongchenfei
*/
public class VerticalDashLineView extends View {
public VerticalDashLineView(Context context) {
this(context,null);
}
public VerticalDashLineView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public VerticalDashLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private final Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path dashPath = new Path();
private void init(){
linePaint.setColor(Color.GREEN);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeWidth(2);
linePaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));
}
public void setGradient(int startColor, int endColor) {
LinearGradient linearGradient = new LinearGradient(0, 0, getWidth(), getHeight(), startColor, endColor, Shader.TileMode.CLAMP);
linePaint.setShader(linearGradient);
invalidate();
}
public void setColor(int color) {
linePaint.setShader(null);
linePaint.setColor(color);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
dashPath.reset();
dashPath.moveTo((float) getWidth()/2, 0);
dashPath.lineTo((float) getWidth()/2,getHeight());
canvas.drawPath(dashPath,linePaint);
}
}

Some files were not shown because too many files have changed in this diff Show More